Reduce meta-data object sizes, introduce meta-data helper classes.
Change-Id: Id14ad218f1c74c659701352fdf1a45bf6444daa3
diff --git a/src/check_jni.cc b/src/check_jni.cc
index 659dcb8..037edfc 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -21,6 +21,7 @@
#include "class_linker.h"
#include "logging.h"
+#include "object_utils.h"
#include "scoped_jni_thread_state.h"
#include "thread.h"
#include "runtime.h"
@@ -112,7 +113,7 @@
// such as NewByteArray.
// If -verbose:third-party-jni is on, we want to log any JNI function calls
// made by a third-party native method.
- std::string classNameStr(method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8());
+ std::string classNameStr(MethodHelper(method).GetDeclaringClassDescriptor());
if (!vm->trace.empty() && classNameStr.find(vm->trace) != std::string::npos) {
return true;
}
@@ -180,7 +181,7 @@
if (f == NULL) {
return;
}
- Class* field_type = f->GetType();
+ Class* field_type = FieldHelper(f).GetType();
if (!field_type->IsPrimitive()) {
if (java_object != NULL) {
Object* obj = Decode<Object*>(ts, java_object);
@@ -237,10 +238,9 @@
if (f == NULL) {
return;
}
- // check invariant that all jfieldIDs have resolved types
- DCHECK(f->GetType() != NULL);
Class* c = o->GetClass();
- if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f->GetTypeDescriptor()) == NULL) {
+ FieldHelper fh(f);
+ if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f)
<< " not valid for an object of class " << PrettyTypeOf(o);
JniAbort();
@@ -263,11 +263,11 @@
*/
void CheckSig(jmethodID mid, const char* expectedType, bool isStatic) {
ScopedJniThreadState ts(env_);
- const Method* m = CheckMethodID(mid);
+ Method* m = CheckMethodID(mid);
if (m == NULL) {
return;
}
- if (*expectedType != m->GetShorty()->CharAt(0)) {
+ if (*expectedType != MethodHelper(m).GetShorty()[0]) {
LOG(ERROR) << "JNI ERROR: the return type of " << function_name_ << " does not match "
<< PrettyMethod(m);
JniAbort();
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9e4a76d..6555070 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -19,6 +19,7 @@
#include "monitor.h"
#include "oat_file.h"
#include "object.h"
+#include "object_utils.h"
#include "runtime.h"
#include "runtime_support.h"
#include "ScopedLocalRef.h"
@@ -59,13 +60,14 @@
void ThrowNoSuchMethodError(const char* kind,
Class* c, const StringPiece& name, const StringPiece& signature) {
- DexCache* dex_cache = c->GetDexCache();
+ ClassHelper kh(c);
std::ostringstream msg;
msg << "no " << kind << " method " << name << "." << signature
- << " in class " << c->GetDescriptor()->ToModifiedUtf8()
+ << " in class " << kh.GetDescriptor()
<< " or its superclasses";
- if (dex_cache) {
- msg << " (defined in " << dex_cache->GetLocation()->ToModifiedUtf8() << ")";
+ std::string location(kh.GetLocation());
+ if (!location.empty()) {
+ msg << " (defined in " << location << ")";
}
Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
}
@@ -81,11 +83,11 @@
if (c->GetVerifyErrorClass() != NULL) {
// TODO: change the verifier to store an _instance_, with a useful detail message?
- std::string error_descriptor(c->GetVerifyErrorClass()->GetDescriptor()->ToModifiedUtf8());
- Thread::Current()->ThrowNewException(error_descriptor.c_str(),
- PrettyDescriptor(c->GetDescriptor()).c_str());
+ ClassHelper ve_ch(c->GetVerifyErrorClass());
+ std::string error_descriptor(ve_ch.GetDescriptor());
+ Thread::Current()->ThrowNewException(error_descriptor.c_str(), PrettyDescriptor(c).c_str());
} else {
- ThrowNoClassDefFoundError("%s", PrettyDescriptor(c->GetDescriptor()).c_str());
+ ThrowNoClassDefFoundError("%s", PrettyDescriptor(c).c_str());
}
}
@@ -204,7 +206,6 @@
dex_lock_("ClassLinker dex lock"),
classes_lock_("ClassLinker classes lock"),
class_roots_(NULL),
- array_interfaces_(NULL),
array_iftable_(NULL),
init_done_(false),
intern_table_(intern_table) {
@@ -269,14 +270,6 @@
java_lang_String->SetObjectSize(sizeof(String));
java_lang_String->SetStatus(Class::kStatusResolved);
- // Backfill Class descriptors missing until this point
- java_lang_Class->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Class;"));
- java_lang_Object->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Object;"));
- class_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Class;"));
- object_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Object;"));
- java_lang_String->SetDescriptor(intern_table_->InternStrong("Ljava/lang/String;"));
- char_array_class->SetDescriptor(intern_table_->InternStrong("[C"));
-
// Create storage for root classes, save away our work so far (requires
// descriptors)
class_roots_ = ObjectArray<Class>::Alloc(object_array_class.get(), kClassRootsMax);
@@ -299,12 +292,10 @@
SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
// Create array interface entries to populate once we can load system classes
- array_interfaces_ = AllocClassArray(2);
array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
// Create int array type for AllocDexCache (done in AppendToBootClassPath)
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.get());
SetClassRoot(kIntArrayClass, int_array_class.get());
@@ -324,7 +315,6 @@
// Constructor, Field, and Method are necessary so that FindClass can link members
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.get() != NULL);
java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
@@ -332,14 +322,12 @@
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.get());
java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
Field::SetClass(java_lang_reflect_Field.get());
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.get() != NULL);
java_lang_reflect_Method->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
@@ -398,21 +386,19 @@
CHECK(java_lang_Cloneable != NULL);
Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
CHECK(java_io_Serializable != NULL);
- CHECK(array_interfaces_ != NULL);
- array_interfaces_->Set(0, java_lang_Cloneable);
- array_interfaces_->Set(1, java_io_Serializable);
// We assume that Cloneable/Serializable don't have superinterfaces --
// normally we'd have to crawl up and explicitly list all of the
// supers as well.
- array_iftable_->Set(0, AllocInterfaceEntry(array_interfaces_->Get(0)));
- array_iftable_->Set(1, AllocInterfaceEntry(array_interfaces_->Get(1)));
+ array_iftable_->Set(0, AllocInterfaceEntry(java_lang_Cloneable));
+ array_iftable_->Set(1, AllocInterfaceEntry(java_io_Serializable));
// Sanity check Class[] and Object[]'s interfaces
- CHECK_EQ(java_lang_Cloneable, class_array_class->GetInterface(0));
- CHECK_EQ(java_io_Serializable, class_array_class->GetInterface(1));
- CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
- CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
-
+ ClassHelper kh(class_array_class.get(), this);
+ CHECK_EQ(java_lang_Cloneable, kh.GetInterface(0));
+ CHECK_EQ(java_io_Serializable, kh.GetInterface(1));
+ kh.ChangeClass(object_array_class.get());
+ CHECK_EQ(java_lang_Cloneable, kh.GetInterface(0));
+ CHECK_EQ(java_io_Serializable, kh.GetInterface(1));
// 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;");
@@ -497,25 +483,37 @@
Heap::SetWellKnownClasses(java_lang_ref_FinalizerReference, java_lang_ref_ReferenceQueue);
+ const DexFile& java_lang_dex = FindDexFile(java_lang_ref_Reference->GetDexCache());
+
Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
- CHECK(pendingNext->GetName()->Equals("pendingNext"));
- CHECK_EQ(ResolveType(pendingNext->GetTypeIdx(), pendingNext), java_lang_ref_Reference);
+ FieldHelper fh(pendingNext, this);
+ CHECK_STREQ(fh.GetName(), "pendingNext");
+ CHECK_EQ(java_lang_dex.GetFieldId(pendingNext->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_Reference->GetDexTypeIndex());
Field* queue = java_lang_ref_Reference->GetInstanceField(1);
- CHECK(queue->GetName()->Equals("queue"));
- CHECK_EQ(ResolveType(queue->GetTypeIdx(), queue), java_lang_ref_ReferenceQueue);
+ fh.ChangeField(queue);
+ CHECK_STREQ(fh.GetName(), "queue");
+ CHECK_EQ(java_lang_dex.GetFieldId(queue->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_ReferenceQueue->GetDexTypeIndex());
Field* queueNext = java_lang_ref_Reference->GetInstanceField(2);
- CHECK(queueNext->GetName()->Equals("queueNext"));
- CHECK_EQ(ResolveType(queueNext->GetTypeIdx(), queueNext), java_lang_ref_Reference);
+ fh.ChangeField(queueNext);
+ CHECK_STREQ(fh.GetName(), "queueNext");
+ CHECK_EQ(java_lang_dex.GetFieldId(queueNext->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_Reference->GetDexTypeIndex());
Field* referent = java_lang_ref_Reference->GetInstanceField(3);
- CHECK(referent->GetName()->Equals("referent"));
- CHECK_EQ(ResolveType(referent->GetTypeIdx(), referent), GetClassRoot(kJavaLangObject));
+ fh.ChangeField(referent);
+ CHECK_STREQ(fh.GetName(), "referent");
+ CHECK_EQ(java_lang_dex.GetFieldId(referent->GetDexFieldIndex()).type_idx_,
+ GetClassRoot(kJavaLangObject)->GetDexTypeIndex());
Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
- CHECK(zombie->GetName()->Equals("zombie"));
- CHECK_EQ(ResolveType(zombie->GetTypeIdx(), zombie), GetClassRoot(kJavaLangObject));
+ fh.ChangeField(zombie);
+ CHECK_STREQ(fh.GetName(), "zombie");
+ CHECK_EQ(java_lang_dex.GetFieldId(zombie->GetDexFieldIndex()).type_idx_,
+ GetClassRoot(kJavaLangObject)->GetDexTypeIndex());
Heap::SetReferenceOffsets(referent->GetOffset(),
queue->GetOffset(),
@@ -534,7 +532,6 @@
}
CHECK(array_iftable_ != NULL);
- CHECK(array_interfaces_ != NULL);
// disable the slow paths in FindClass and CreatePrimitiveClass now
// that Object, Class, and Object[] are setup
@@ -611,7 +608,9 @@
LOG(INFO) << "ClassLinker::OpenOat entering";
}
const ImageHeader& image_header = space->GetImageHeader();
- String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
+ // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
+ // check the down cast
+ String* oat_location = down_cast<String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
std::string oat_filename;
oat_filename += runtime->GetHostPrefix();
oat_filename += oat_location->ToModifiedUtf8();
@@ -734,6 +733,14 @@
Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
+ if (i == 0) {
+ // Special case of setting up the String class early so that we can test arbitrary objects
+ // as being Strings or not
+ Class* java_lang_String = spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)
+ ->AsObjectArray<Class>()->Get(kJavaLangString);
+ String::SetClass(java_lang_String);
+ }
+
CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));
for (int i = 0; i < dex_caches->GetLength(); i++) {
@@ -767,13 +774,10 @@
Object* class_roots_object = spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots);
class_roots_ = class_roots_object->AsObjectArray<Class>();
- // reinit array_interfaces_ and array_iftable_ from any array class instance, they should all be ==
- array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
- DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
+ // reinit array_iftable_ from any array class instance, they should be ==
array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable();
DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
-
- String::SetClass(GetClassRoot(kJavaLangString));
+ // String class root was set above
Field::SetClass(GetClassRoot(kJavaLangReflectField));
Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
@@ -806,7 +810,7 @@
if (obj->IsClass()) {
// restore class to ClassLinker::classes_ table
Class* klass = obj->AsClass();
- std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
+ std::string descriptor(ClassHelper(klass, class_linker).GetDescriptor());
bool success = class_linker->InsertClass(descriptor, klass, true);
DCHECK(success);
return;
@@ -832,7 +836,6 @@
// Note. we deliberately ignore the class roots in the image (held in image_classes_)
}
- visitor(array_interfaces_, arg);
visitor(array_iftable_, arg);
}
@@ -960,7 +963,7 @@
// Check for circular dependencies between classes.
if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
self->ThrowNewException("Ljava/lang/ClassCircularityError;",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
return NULL;
}
// Wait for the pending initialization to complete.
@@ -985,15 +988,16 @@
Thread* self = Thread::Current();
DCHECK(self != NULL);
CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
+ if (descriptor.size() == 1) {
+ // only the descriptors of primitive types should be 1 character long, also avoid class lookup
+ // for primitive classes that aren't backed by dex files.
+ return FindPrimitiveClass(descriptor[0]);
+ }
// Find the class in the loaded classes table.
Class* klass = LookupClass(descriptor, class_loader);
if (klass != NULL) {
return EnsureResolved(klass);
}
- if (descriptor.size() == 1) {
- // only the descriptors of primitive types should be 1 character long
- return FindPrimitiveClass(descriptor[0]);
- }
// Class is not yet loaded.
if (descriptor[0] == '[') {
return CreateArrayClass(descriptor, class_loader);
@@ -1179,14 +1183,6 @@
CHECK(descriptor != NULL);
klass->SetClass(GetClassRoot(kJavaLangClass));
- if (klass->GetDescriptor() != NULL) {
- DCHECK(klass->GetDescriptor()->Equals(descriptor));
- } else {
- klass->SetDescriptor(intern_table_->InternStrong(descriptor));
- if (klass->GetDescriptor() == NULL) {
- return;
- }
- }
uint32_t access_flags = dex_class_def.access_flags_;
// Make sure that none of our runtime-only flags are set.
CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
@@ -1195,21 +1191,7 @@
DCHECK(klass->GetPrimitiveType() == Primitive::kPrimNot);
klass->SetStatus(Class::kStatusIdx);
- klass->SetTypeIdx(dex_class_def.class_idx_);
- klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
- klass->SetAnnotationsOffset(dex_class_def.annotations_off_);
-
- const char* source_file = dex_file.GetSourceFile(dex_class_def);
- if (source_file != NULL) {
- String* source_file_string = intern_table_->InternStrong(source_file);
- if (source_file_string == NULL) {
- return;
- }
- klass->SetSourceFile(source_file_string);
- }
-
- // Load class interfaces.
- LoadInterfaces(dex_file, dex_class_def, klass);
+ klass->SetDexTypeIndex(dex_class_def.class_idx_);
// Load fields fields.
const byte* class_data = dex_file.GetClassData(dex_class_def);
@@ -1279,88 +1261,59 @@
DCHECK(!it.HasNext());
}
-void ClassLinker::LoadInterfaces(const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- SirtRef<Class>& klass) {
- const DexFile::TypeList* list = dex_file.GetInterfacesList(dex_class_def);
- if (list != NULL) {
- klass->SetInterfaces(AllocClassArray(list->Size()));
- IntArray* interfaces_idx = IntArray::Alloc(list->Size());
- klass->SetInterfacesTypeIdx(interfaces_idx);
- for (size_t i = 0; i < list->Size(); ++i) {
- const DexFile::TypeItem& type_item = list->GetTypeItem(i);
- interfaces_idx->Set(i, type_item.type_idx_);
- }
- }
-}
-
void ClassLinker::LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
SirtRef<Class>& klass, SirtRef<Field>& dst) {
- const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
+ uint32_t field_idx = it.GetMemberIndex();
+ dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.get());
- dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
- dst->SetTypeIdx(field_id.type_idx_);
dst->SetAccessFlags(it.GetMemberAccessFlags());
-
- // In order to access primitive types using GetTypeDuringLinking we need to
- // ensure they are resolved into the dex cache
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- 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.get());
- DCHECK(resolved->IsPrimitive());
- }
}
void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
SirtRef<Class>& klass, SirtRef<Method>& dst) {
- const DexFile::MethodId& method_id = dex_file.GetMethodId(it.GetMemberIndex());
+ uint32_t method_idx = it.GetMemberIndex();
+ dst->SetDexMethodIndex(method_idx);
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
dst->SetDeclaringClass(klass.get());
- String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
- if (method_name == NULL) {
- return;
- }
- dst->SetName(method_name);
- if (method_name->Equals("<init>")) {
+
+ StringPiece method_name(dex_file.GetMethodName(method_id));
+ if (method_name == "<init>") {
dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
}
- int32_t utf16_length;
- std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, &utf16_length));
- String* signature_string = intern_table_->InternStrong(utf16_length, signature.c_str());
- if (signature_string == NULL) {
- return;
- }
- dst->SetSignature(signature_string);
-
- if (method_name->Equals("finalize") && signature == "()V") {
- /*
- * The Enum class declares a "final" finalize() method to prevent subclasses from introducing
- * a finalizer. We don't want to set the finalizable flag for Enum or its subclasses, so we
- * exclude it here.
- *
- * We also want to avoid setting the flag on Object, where we know that finalize() is empty.
- */
- if (klass->GetClassLoader() != NULL ||
- (!klass->GetDescriptor()->Equals("Ljava/lang/Object;") &&
- !klass->GetDescriptor()->Equals("Ljava/lang/Enum;"))) {
- klass->SetFinalizable();
+ if (method_name == "finalize") {
+ // Create the prototype for a signature of "()V"
+ const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
+ if (void_string_id != NULL) {
+ const DexFile::TypeId* void_type_id =
+ dex_file.FindTypeId(dex_file.GetIndexForStringId(*void_string_id));
+ if (void_type_id != NULL) {
+ std::vector<uint16_t> no_args;
+ const DexFile::ProtoId* finalizer_proto =
+ dex_file.FindProtoId(dex_file.GetIndexForTypeId(*void_type_id), no_args);
+ if (finalizer_proto != NULL) {
+ // We have the prototype in the dex file
+ if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
+ klass->SetFinalizable();
+ } else {
+ StringPiece klass_descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
+ // The Enum class declares a "final" finalize() method to prevent subclasses from
+ // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
+ // subclasses, so we exclude it here.
+ // We also want to avoid setting the flag on Object, where we know that finalize() is
+ // empty.
+ if (klass_descriptor != "Ljava/lang/Object;" &&
+ klass_descriptor != "Ljava/lang/Enum;") {
+ klass->SetFinalizable();
+ }
+ }
+ }
+ }
}
}
-
- dst->SetProtoIdx(method_id.proto_idx_);
dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
- const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
- String* shorty_string = intern_table_->InternStrong(shorty);
- dst->SetShorty(shorty_string);
- if (shorty_string == NULL) {
- return;
- }
dst->SetAccessFlags(it.GetMemberAccessFlags());
- uint32_t return_type_idx = dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_;
- DCHECK_LT(return_type_idx, dex_file.NumTypeIds());
- dst->SetReturnTypeIdx(return_type_idx);
dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
@@ -1370,20 +1323,6 @@
dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
// TODO: check for finalize method
-
- const DexFile::CodeItem* code_item = it.GetMethodCodeItem();
- if (code_item != NULL) {
- dst->SetNumRegisters(code_item->registers_size_);
- dst->SetNumIns(code_item->ins_size_);
- dst->SetNumOuts(code_item->outs_size_);
- } else {
- uint16_t num_args = Method::NumArgRegisters(shorty);
- if ((it.GetMemberAccessFlags() & kAccStatic) == 0) {
- ++num_args;
- }
- dst->SetNumRegisters(num_args);
- // TODO: native methods
- }
}
void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
@@ -1474,8 +1413,6 @@
// TODO: deduce one argument from the other
CHECK(primitive_class != NULL);
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
- primitive_class->SetDescriptor(intern_table_->InternStrong(descriptor));
- CHECK(primitive_class->GetDescriptor() != NULL);
primitive_class->SetPrimitiveType(type);
primitive_class->SetStatus(Class::kStatusInitialized);
bool success = InsertClass(descriptor, primitive_class, false);
@@ -1561,14 +1498,6 @@
new_class->SetComponentType(component_type);
}
DCHECK(new_class->GetComponentType() != NULL);
- if (new_class->GetDescriptor() != NULL) {
- DCHECK(new_class->GetDescriptor()->Equals(descriptor));
- } else {
- new_class->SetDescriptor(intern_table_->InternStrong(descriptor.c_str()));
- if (new_class->GetDescriptor() == NULL) {
- return NULL;
- }
- }
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
new_class->SetVTable(java_lang_Object->GetVTable());
@@ -1591,9 +1520,7 @@
// Use the single, global copies of "interfaces" and "iftable"
// (remember not to free them for arrays).
- CHECK(array_interfaces_ != NULL);
CHECK(array_iftable_ != NULL);
- new_class->SetInterfaces(array_interfaces_);
new_class->SetIfTable(array_iftable_);
// Inherit access flags from the component type. Arrays can't be
@@ -1677,16 +1604,19 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh;
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
classes_.erase(it);
return true;
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
image_classes_.erase(it);
return true;
}
@@ -1699,15 +1629,18 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh(NULL, this);
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
return klass;
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
return klass;
}
}
@@ -1720,16 +1653,19 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh(NULL, this);
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
- Class* c = it->second;
- if (c->GetDescriptor()->Equals(descriptor)) {
- classes.push_back(c);
+ Class* klass = it->second;
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor()) {
+ classes.push_back(klass);
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
- Class* c = it->second;
- if (c->GetDescriptor()->Equals(descriptor)) {
- classes.push_back(c);
+ Class* klass = it->second;
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor()) {
+ classes.push_back(klass);
}
}
}
@@ -1749,48 +1685,56 @@
Thread* self = Thread::Current();
CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
self->ThrowNewExceptionF("Ljava/lang/VerifyError;", "Verification of %s failed",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
CHECK_EQ(klass->GetStatus(), Class::kStatusVerifying);
klass->SetStatus(Class::kStatusError);
}
}
Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
- ClassLoader* loader, ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws) {
+ ClassLoader* loader, ObjectArray<Method>* methods,
+ ObjectArray<ObjectArray<Class> >* throws) {
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));
- klass->SetAccessFlags(kAccPublic | kAccFinal);
+ klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal);
klass->SetClassLoader(loader);
- klass->SetStatus(Class::kStatusInitialized); // no loading or initializing necessary
+ klass->SetName(name);
Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
+ klass->SetDexCache(proxy_class->GetDexCache());
+ klass->SetDexTypeIndex(-1);
klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy
- klass->SetInterfaces(interfaces); // The interfaces are the array of interfaces specified
+ klass->SetStatus(Class::kStatusInitialized); // no loading or initializing necessary
// Proxies have 1 direct method, the constructor
klass->SetDirectMethods(AllocObjectArray<Method>(1));
- klass->SetDirectMethod(0, CreateProxyConstructor(klass));
+ klass->SetDirectMethod(0, CreateProxyConstructor(klass, proxy_class));
// Create virtual method using specified prototypes
size_t num_virtual_methods = methods->GetLength();
klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
for (size_t i = 0; i < num_virtual_methods; ++i) {
SirtRef<Method> prototype(methods->Get(i));
- klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype, throws->Get(i)));
+ klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype));
}
// Link the virtual methods, creating vtable and iftables
- if (!LinkMethods(klass)) {
+ if (!LinkMethods(klass, interfaces)) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
return klass.get();
}
-Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass) {
+std::string ClassLinker::GetDescriptorForProxy(const Class* proxy_class) {
+ DCHECK(proxy_class->IsProxyClass());
+ String* name = proxy_class->GetName();
+ DCHECK(name != NULL);
+ return DotToDescriptor(name->ToModifiedUtf8().c_str());
+}
+
+
+Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) {
// Create constructor for Proxy that must initialize h
- Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
ObjectArray<Method>* proxy_direct_methods = proxy_class->GetDirectMethods();
CHECK_EQ(proxy_direct_methods->GetLength(), 15);
Method* proxy_constructor = proxy_direct_methods->Get(2);
@@ -1802,15 +1746,18 @@
constructor->SetDeclaringClass(klass.get());
// Sanity checks
CHECK(constructor->IsConstructor());
- CHECK(constructor->GetName()->Equals("<init>"));
- CHECK(constructor->GetSignature()->Equals("(Ljava/lang/reflect/InvocationHandler;)V"));
+ MethodHelper mh(constructor);
+ CHECK_STREQ(mh.GetName(), "<init>");
+ CHECK(mh.GetSignature() == "(Ljava/lang/reflect/InvocationHandler;)V");
DCHECK(constructor->IsPublic());
return constructor;
}
-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
+Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype) {
+ // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
+ // prototype method
+ prototype->GetDexCacheResolvedMethods()->Set(prototype->GetDexMethodIndex(), prototype.get());
+ // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
// as necessary
Method* method = down_cast<Method*>(prototype->Clone());
@@ -1818,7 +1765,6 @@
// the intersection of throw exceptions as defined in Proxy
method->SetDeclaringClass(klass.get());
method->SetAccessFlags((method->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
- method->SetExceptionTypes(throws);
// At runtime the method looks like a reference and argument saving method, clone the code
// related parameters from this method.
@@ -1829,12 +1775,21 @@
method->SetCode(reinterpret_cast<void*>(art_proxy_invoke_handler));
// Basic sanity
- DCHECK(method->GetName()->Equals(prototype->GetName()));
- DCHECK(method->GetSignature()->Equals(prototype->GetSignature()));
- DCHECK(method->GetShorty()->Equals(prototype->GetShorty()));
+ CHECK(!prototype->IsFinal());
+ CHECK(method->IsFinal());
+ CHECK(!method->IsAbstract());
+ MethodHelper mh(method);
+ const char* method_name = mh.GetName();
+ const char* method_shorty = mh.GetShorty();
+ Class* method_return = mh.GetReturnType();
+
+ mh.ChangeMethod(prototype.get());
+
+ CHECK_STREQ(mh.GetName(), method_name);
+ CHECK_STREQ(mh.GetShorty(), method_shorty);
// More complex sanity - via dex cache
- CHECK_EQ(method->GetReturnType(), prototype->GetReturnType());
+ CHECK_EQ(mh.GetReturnType(), method_return);
return method;
}
@@ -1928,8 +1883,8 @@
thread_stats->class_init_time_ns += (t1 - t0);
klass->SetStatus(Class::kStatusInitialized);
if (verbose_) {
- LOG(INFO) << "Initialized class " << klass->GetDescriptor()->ToModifiedUtf8()
- << " from " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
+ ClassHelper kh(klass);
+ LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
}
}
lock.NotifyAll();
@@ -1959,7 +1914,7 @@
// The caller wants an exception, but it was thrown in a
// different thread. Synthesize one here.
ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
return false;
}
if (klass->IsInitialized()) {
@@ -1984,7 +1939,9 @@
!HasSameMethodDescriptorClasses(method, super, klass)) {
klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
- ThrowLinkageError("Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(super->GetDescriptor()).c_str());
+ ThrowLinkageError("Class %s method %s resolves differently in superclass %s",
+ PrettyDescriptor(klass).c_str(), PrettyMethod(method).c_str(),
+ PrettyDescriptor(super).c_str());
return false;
}
}
@@ -1999,7 +1956,10 @@
method->GetDeclaringClass())) {
klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
- ThrowLinkageError("Class %s method %s resolves differently in interface %s", PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(interface->GetDescriptor()).c_str());
+ ThrowLinkageError("Class %s method %s resolves differently in interface %s",
+ PrettyDescriptor(method->GetDeclaringClass()).c_str(),
+ PrettyMethod(method).c_str(),
+ PrettyDescriptor(interface).c_str());
return false;
}
}
@@ -2015,7 +1975,8 @@
return true;
}
const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
- const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
+ const DexFile::ProtoId& proto_id =
+ dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
const char* descriptor = it.GetDescriptor();
if (descriptor == NULL) {
@@ -2121,10 +2082,10 @@
if (dex_cache == NULL) {
return;
}
- const DexFile& dex_file = FindDexFile(dex_cache);
- const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
- const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
+ ClassHelper kh(klass);
+ const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
CHECK(dex_class_def != NULL);
+ const DexFile& dex_file = kh.GetDexFile();
EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
if (it.HasNext()) {
@@ -2142,7 +2103,7 @@
if (!LinkSuperClass(klass)) {
return false;
}
- if (!LinkMethods(klass)) {
+ if (!LinkMethods(klass, NULL)) {
return false;
}
if (!LinkInstanceFields(klass)) {
@@ -2160,30 +2121,38 @@
bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) {
CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
- if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex16) {
- Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass.get());
+ StringPiece descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
+ const DexFile::ClassDef* class_def = dex_file.FindClassDef(descriptor);
+ if (class_def == NULL) {
+ return false;
+ }
+ uint16_t super_class_idx = class_def->superclass_idx_;
+ if (super_class_idx != DexFile::kDexNoIndex16) {
+ Class* super_class = ResolveType(dex_file, super_class_idx, klass.get());
if (super_class == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return false;
}
klass->SetSuperClass(super_class);
}
- for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
- uint32_t idx = klass->GetInterfacesTypeIdx()->Get(i);
- Class* interface = ResolveType(dex_file, idx, klass.get());
- klass->SetInterface(i, interface);
- if (interface == NULL) {
- DCHECK(Thread::Current()->IsExceptionPending());
- return false;
- }
- // Verify
- if (!klass->CanAccess(interface)) {
- // TODO: the RI seemed to ignore this in my testing.
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
- "Interface %s implemented by class %s is inaccessible",
- PrettyDescriptor(interface->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
- return false;
+ const DexFile::TypeList* interfaces = dex_file.GetInterfacesList(*class_def);
+ if (interfaces != NULL) {
+ for (size_t i = 0; i < interfaces->Size(); i++) {
+ uint16_t idx = interfaces->GetTypeItem(i).type_idx_;
+ Class* interface = ResolveType(dex_file, idx, klass.get());
+ if (interface == NULL) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return false;
+ }
+ // Verify
+ if (!klass->CanAccess(interface)) {
+ // TODO: the RI seemed to ignore this in my testing.
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+ "Interface %s implemented by class %s is inaccessible",
+ PrettyDescriptor(interface).c_str(),
+ PrettyDescriptor(klass.get()).c_str());
+ return false;
+ }
}
}
// Mark the class as loaded.
@@ -2194,7 +2163,7 @@
bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) {
CHECK(!klass->IsPrimitive());
Class* super = klass->GetSuperClass();
- if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
+ if (klass.get() == GetClassRoot(kJavaLangObject)) {
if (super != NULL) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassFormatError;",
"java.lang.Object must not have a superclass");
@@ -2203,24 +2172,23 @@
return true;
}
if (super == NULL) {
- ThrowLinkageError("No superclass defined for class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ ThrowLinkageError("No superclass defined for class %s", PrettyDescriptor(klass.get()).c_str());
return false;
}
// Verify
if (super->IsFinal() || super->IsInterface()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
"Superclass %s of %s is %s",
- PrettyDescriptor(super->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
+ PrettyDescriptor(super).c_str(),
+ PrettyDescriptor(klass.get()).c_str(),
super->IsFinal() ? "declared final" : "an interface");
return false;
}
if (!klass->CanAccess(super)) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Superclass %s is inaccessible by %s",
- PrettyDescriptor(super->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(super).c_str(),
+ PrettyDescriptor(klass.get()).c_str());
return false;
}
@@ -2237,7 +2205,7 @@
// Disallow custom direct subclasses of java.lang.ref.Reference.
if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) {
ThrowLinkageError("Class %s attempts to subclass java.lang.ref.Reference, which is not allowed",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str());
return false;
}
@@ -2252,7 +2220,7 @@
}
// Populate the class vtable and itable. Compute return type indices.
-bool ClassLinker::LinkMethods(SirtRef<Class>& klass) {
+bool ClassLinker::LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) {
if (klass->IsInterface()) {
// No vtable.
size_t count = klass->NumVirtualMethods();
@@ -2264,10 +2232,10 @@
klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
}
// Link interface method tables
- return LinkInterfaceMethods(klass);
+ return LinkInterfaceMethods(klass, interfaces);
} else {
// Link virtual and interface method tables
- return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass);
+ return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass, interfaces);
}
return true;
}
@@ -2280,18 +2248,22 @@
// TODO: do not assign to the vtable field until it is fully constructed.
ObjectArray<Method>* vtable = klass->GetSuperClass()->GetVTable()->CopyOf(max_count);
// See if any of our virtual methods override the superclass.
+ MethodHelper local_mh(NULL, this);
+ MethodHelper super_mh(NULL, this);
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
Method* local_method = klass->GetVirtualMethodDuringLinking(i);
+ local_mh.ChangeMethod(local_method);
size_t j = 0;
for (; j < actual_count; ++j) {
Method* super_method = vtable->Get(j);
- if (local_method->HasSameNameAndSignature(super_method)) {
+ super_mh.ChangeMethod(super_method);
+ if (local_mh.HasSameNameAndSignature(&super_mh)) {
// Verify
if (super_method->IsFinal()) {
+ MethodHelper mh(local_method);
ThrowLinkageError("Method %s.%s overrides final method in class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
- local_method->GetName()->ToModifiedUtf8().c_str(),
- PrettyDescriptor(super_method->GetDeclaringClass()->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str(),
+ mh.GetName(), mh.GetDeclaringClassDescriptor());
return false;
}
vtable->Set(j, local_method);
@@ -2317,7 +2289,7 @@
}
klass->SetVTable(vtable);
} else {
- CHECK(klass->GetDescriptor()->Equals("Ljava/lang/Object;"));
+ CHECK(klass.get() == GetClassRoot(kJavaLangObject));
uint32_t num_virtual_methods = klass->NumVirtualMethods();
if (!IsUint(16, num_virtual_methods)) {
ThrowClassFormatError("Too many methods: %d", num_virtual_methods);
@@ -2334,7 +2306,7 @@
return true;
}
-bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass) {
+bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) {
size_t super_ifcount;
if (klass->HasSuperClass()) {
super_ifcount = klass->GetSuperClass()->GetIfTableCount();
@@ -2342,9 +2314,12 @@
super_ifcount = 0;
}
size_t ifcount = super_ifcount;
- ifcount += klass->NumInterfaces();
- for (size_t i = 0; i < klass->NumInterfaces(); i++) {
- ifcount += klass->GetInterface(i)->GetIfTableCount();
+ ClassHelper kh(klass.get(), this);
+ uint32_t num_interfaces = interfaces == NULL ? kh.NumInterfaces() : interfaces->GetLength();
+ ifcount += num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ Class* interface = interfaces == NULL ? kh.GetInterface(i) : interfaces->Get(i);
+ ifcount += interface->GetIfTableCount();
}
if (ifcount == 0) {
// TODO: enable these asserts with klass status validation
@@ -2361,14 +2336,15 @@
}
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
- for (size_t i = 0; i < klass->NumInterfaces(); i++) {
- Class* interface = klass->GetInterface(i);
+ for (size_t i = 0; i < num_interfaces; i++) {
+ Class* interface = interfaces == NULL ? kh.GetInterface(i) : interfaces->Get(i);
DCHECK(interface != NULL);
if (!interface->IsInterface()) {
+ ClassHelper ih(interface);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
"Class %s implements non-interface class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
- PrettyDescriptor(interface->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str(),
+ PrettyDescriptor(ih.GetDescriptor()).c_str());
return false;
}
// Add this interface.
@@ -2386,6 +2362,8 @@
return true;
}
std::vector<Method*> miranda_list;
+ MethodHelper vtable_mh(NULL, this);
+ MethodHelper interface_mh(NULL, this);
for (size_t i = 0; i < ifcount; ++i) {
InterfaceEntry* interface_entry = iftable->Get(i);
Class* interface = interface_entry->GetInterface();
@@ -2394,6 +2372,7 @@
ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
Method* interface_method = interface->GetVirtualMethod(j);
+ interface_mh.ChangeMethod(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -2405,7 +2384,8 @@
// matter which direction we go. We walk it backward anyway.)
for (k = vtable->GetLength() - 1; k >= 0; --k) {
Method* vtable_method = vtable->Get(k);
- if (interface_method->HasSameNameAndSignature(vtable_method)) {
+ vtable_mh.ChangeMethod(vtable_method);
+ if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
if (!vtable_method->IsPublic()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Implementation not public: %s", PrettyMethod(vtable_method).c_str());
@@ -2418,7 +2398,9 @@
if (k < 0) {
SirtRef<Method> miranda_method(NULL);
for (size_t mir = 0; mir < miranda_list.size(); mir++) {
- if (miranda_list[mir]->HasSameNameAndSignature(interface_method)) {
+ Method* mir_method = miranda_list[mir];
+ vtable_mh.ChangeMethod(mir_method);
+ if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
miranda_method.reset(miranda_list[mir]);
break;
}
@@ -2481,10 +2463,13 @@
}
struct LinkFieldsComparator {
+ LinkFieldsComparator(FieldHelper* fh) : fh_(fh) {}
bool operator()(const Field* field1, const Field* field2) {
// First come reference fields, then 64-bit, and finally 32-bit
- Primitive::Type type1 = field1->GetPrimitiveType();
- Primitive::Type type2 = field2->GetPrimitiveType();
+ fh_->ChangeField(field1);
+ Primitive::Type type1 = fh_->GetTypeAsPrimitiveType();
+ fh_->ChangeField(field2);
+ Primitive::Type type2 = fh_->GetTypeAsPrimitiveType();
bool isPrimitive1 = type1 != Primitive::kPrimNot;
bool isPrimitive2 = type2 != Primitive::kPrimNot;
bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
@@ -2496,10 +2481,14 @@
}
// same basic group? then sort by string.
- std::string name1 = field1->GetName()->ToModifiedUtf8();
- std::string name2 = field2->GetName()->ToModifiedUtf8();
+ fh_->ChangeField(field1);
+ StringPiece name1(fh_->GetName());
+ fh_->ChangeField(field2);
+ StringPiece name2(fh_->GetName());
return name1 < name2;
}
+
+ FieldHelper* fh_;
};
bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) {
@@ -2532,16 +2521,18 @@
for (size_t i = 0; i < num_fields; i++) {
grouped_and_sorted_fields.push_back(fields->Get(i));
}
+ FieldHelper fh(NULL, this);
std::sort(grouped_and_sorted_fields.begin(),
grouped_and_sorted_fields.end(),
- LinkFieldsComparator());
+ LinkFieldsComparator(&fh));
// References should be at the front.
size_t current_field = 0;
size_t num_reference_fields = 0;
for (; current_field < num_fields; current_field++) {
Field* field = grouped_and_sorted_fields.front();
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool isPrimitive = type != Primitive::kPrimNot;
if (isPrimitive) {
break; // past last reference, move on to the next phase
@@ -2559,7 +2550,8 @@
if (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) {
for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) {
Field* field = grouped_and_sorted_fields[i];
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
continue;
@@ -2580,7 +2572,8 @@
while (!grouped_and_sorted_fields.empty()) {
Field* field = grouped_and_sorted_fields.front();
grouped_and_sorted_fields.pop_front();
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
fields->Set(current_field, field);
field->SetOffset(field_offset);
@@ -2592,11 +2585,14 @@
}
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
- if (!is_static && klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;")) {
+ std::string descriptor(ClassHelper(klass.get(), this).GetDescriptor());
+ if (!is_static && descriptor == "Ljava/lang/ref/Reference;") {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields);
- CHECK(fields->Get(num_fields - 1)->GetName()->Equals("referent"));
+ fh.ChangeField(fields->Get(num_fields - 1));
+ StringPiece name(fh.GetName());
+ CHECK(name == "referent");
--num_reference_fields;
}
@@ -2612,9 +2608,10 @@
<< " field=" << PrettyField(field)
<< " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
}
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool is_primitive = type != Primitive::kPrimNot;
- if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
+ if (descriptor == "Ljava/lang/ref/Reference;" && StringPiece(fh.GetName()) == "referent") {
is_primitive = true; // We lied above, so we have to expect a lie here.
}
if (is_primitive) {
@@ -2711,7 +2708,7 @@
}
Class* ClassLinker::ResolveType(const DexFile& dex_file,
- uint32_t type_idx,
+ uint16_t type_idx,
DexCache* dex_cache,
const ClassLoader* class_loader) {
Class* resolved = dex_cache->GetResolvedType(type_idx);
@@ -2842,4 +2839,15 @@
return dex_lock_.GetOwner();
}
+void ClassLinker::SetClassRoot(ClassRoot class_root, Class* klass) {
+ DCHECK(!init_done_);
+
+ DCHECK(klass != NULL);
+ DCHECK(klass->GetClassLoader() == NULL);
+
+ DCHECK(class_roots_ != NULL);
+ DCHECK(class_roots_->Get(class_root) == NULL);
+ class_roots_->Set(class_root, klass);
+}
+
} // namespace art
diff --git a/src/class_linker.h b/src/class_linker.h
index e408dbb..089040f 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -18,6 +18,7 @@
#define ART_SRC_CLASS_LINKER_H_
#include <map>
+#include <string>
#include <utility>
#include <vector>
@@ -105,7 +106,7 @@
// result in the DexCache. The referrer is used to identity the
// target DexCache and ClassLoader to use for resolution.
Class* ResolveType(const DexFile& dex_file,
- uint32_t type_idx,
+ uint16_t type_idx,
const Class* referrer) {
return ResolveType(dex_file,
type_idx,
@@ -116,7 +117,7 @@
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- Class* ResolveType(uint32_t type_idx, const Method* referrer) {
+ Class* ResolveType(uint16_t type_idx, const Method* referrer) {
Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
if (UNLIKELY(resolved_type == NULL)) {
Class* declaring_class = referrer->GetDeclaringClass();
@@ -128,7 +129,7 @@
return resolved_type;
}
- Class* ResolveType(uint32_t type_idx, const Field* referrer) {
+ Class* ResolveType(uint16_t type_idx, const Field* referrer) {
Class* declaring_class = referrer->GetDeclaringClass();
DexCache* dex_cache = declaring_class->GetDexCache();
Class* resolved_type = dex_cache->GetResolvedType(type_idx);
@@ -145,7 +146,7 @@
// type, since it may be referenced from but not contained within
// the given DexFile.
Class* ResolveType(const DexFile& dex_file,
- uint32_t type_idx,
+ uint16_t type_idx,
DexCache* dex_cache,
const ClassLoader* class_loader);
@@ -244,7 +245,8 @@
void VerifyClass(Class* klass);
Class* CreateProxyClass(String* name, ObjectArray<Class>* interfaces, ClassLoader* loader,
- ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws);
+ ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws);
+ std::string GetDescriptorForProxy(const Class* proxy_class);
pid_t GetClassesLockOwner(); // For SignalCatcher.
pid_t GetDexLockOwner(); // For SignalCatcher.
@@ -303,10 +305,6 @@
SirtRef<Class>& klass,
const ClassLoader* class_loader);
- void LoadInterfaces(const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- SirtRef<Class>& klass);
-
void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass,
SirtRef<Field>& dst);
@@ -340,11 +338,11 @@
bool LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file);
- bool LinkMethods(SirtRef<Class>& klass);
+ bool LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces);
bool LinkVirtualMethods(SirtRef<Class>& klass);
- bool LinkInterfaceMethods(SirtRef<Class>& klass);
+ bool LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces);
bool LinkStaticFields(SirtRef<Class>& klass);
bool LinkInstanceFields(SirtRef<Class>& klass);
@@ -364,8 +362,8 @@
const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file);
const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location);
- Method* CreateProxyConstructor(SirtRef<Class>& klass);
- Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype, ObjectArray<Class>* throws);
+ Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class);
+ Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype);
const bool verbose_;
@@ -433,18 +431,7 @@
return klass;
}
- void SetClassRoot(ClassRoot class_root, Class* klass) {
- DCHECK(!init_done_);
-
- DCHECK(klass != NULL);
- DCHECK(klass->GetClassLoader() == NULL);
- DCHECK(klass->GetDescriptor() != NULL);
- DCHECK(klass->GetDescriptor()->Equals(GetClassRootDescriptor(class_root)));
-
- DCHECK(class_roots_ != NULL);
- DCHECK(class_roots_->Get(class_root) == NULL);
- class_roots_->Set(class_root, klass);
- }
+ void SetClassRoot(ClassRoot class_root, Class* klass);
ObjectArray<Class>* GetClassRoots() {
DCHECK(class_roots_ != NULL);
@@ -459,7 +446,6 @@
return descriptor;
}
- ObjectArray<Class>* array_interfaces_;
ObjectArray<InterfaceEntry>* array_iftable_;
bool init_done_;
@@ -469,6 +455,7 @@
friend class CommonTest;
friend class ImageWriter; // for GetClassRoots
friend class ObjectTest;
+ FRIEND_TEST(ClassLinkerTest, ClassRootDescriptors);
FRIEND_TEST(DexCacheTest, Open);
FRIEND_TEST(ExceptionTest, FindExceptionHandler);
FRIEND_TEST(ObjectTest, AllocObjectArray);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index b51822f..c335ba9 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -30,11 +30,12 @@
}
void AssertPrimitiveClass(const std::string& descriptor, const Class* primitive) {
+ ClassHelper primitive_ch(primitive);
ASSERT_TRUE(primitive != NULL);
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
- ASSERT_TRUE(primitive->GetDescriptor()->Equals(descriptor));
+ ASSERT_STREQ(descriptor.c_str(), primitive_ch.GetDescriptor().c_str());
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
@@ -56,7 +57,7 @@
EXPECT_EQ(0U, primitive->NumVirtualMethods());
EXPECT_EQ(0U, primitive->NumInstanceFields());
EXPECT_EQ(0U, primitive->NumStaticFields());
- EXPECT_EQ(0U, primitive->NumInterfaces());
+ EXPECT_EQ(0U, primitive_ch.NumInterfaces());
EXPECT_TRUE(primitive->GetVTable() == NULL);
EXPECT_EQ(0, primitive->GetIfTableCount());
EXPECT_TRUE(primitive->GetIfTable() == NULL);
@@ -66,22 +67,25 @@
const std::string& component_type,
const ClassLoader* class_loader) {
Class* array = class_linker_->FindClass(array_descriptor, class_loader);
- EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
+ ClassHelper array_component_ch(array->GetComponentType());
+ EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor().c_str());
EXPECT_EQ(class_loader, array->GetClassLoader());
AssertArrayClass(array_descriptor, array);
}
void AssertArrayClass(const std::string& array_descriptor, Class* array) {
+ ClassHelper kh(array);
ASSERT_TRUE(array != NULL);
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
- ASSERT_TRUE(array->GetDescriptor()->Equals(array_descriptor));
+ ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor().c_str());
EXPECT_TRUE(array->GetSuperClass() != NULL);
EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != NULL);
- ASSERT_TRUE(array->GetComponentType()->GetDescriptor() != NULL);
+ kh.ChangeClass(array->GetComponentType());
+ ASSERT_TRUE(kh.GetDescriptor() != NULL);
EXPECT_EQ(Class::kStatusInitialized, array->GetStatus());
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsLoaded());
@@ -99,20 +103,25 @@
EXPECT_EQ(0U, array->NumVirtualMethods());
EXPECT_EQ(0U, array->NumInstanceFields());
EXPECT_EQ(0U, array->NumStaticFields());
- EXPECT_EQ(2U, array->NumInterfaces());
+ kh.ChangeClass(array);
+ EXPECT_EQ(2U, kh.NumInterfaces());
EXPECT_TRUE(array->GetVTable() != NULL);
EXPECT_EQ(2, array->GetIfTableCount());
ObjectArray<InterfaceEntry>* iftable = array->GetIfTable();
ASSERT_TRUE(iftable != NULL);
- EXPECT_TRUE(iftable->Get(0)->GetInterface()->GetDescriptor()->Equals("Ljava/lang/Cloneable;"));
- EXPECT_TRUE(iftable->Get(1)->GetInterface()->GetDescriptor()->Equals("Ljava/io/Serializable;"));
+ kh.ChangeClass(kh.GetInterface(0));
+ EXPECT_STREQ(kh.GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
+ kh.ChangeClass(array);
+ kh.ChangeClass(kh.GetInterface(1));
+ EXPECT_STREQ(kh.GetDescriptor().c_str(), "Ljava/io/Serializable;");
}
void AssertMethod(Class* klass, Method* method) {
+ MethodHelper mh(method);
EXPECT_TRUE(method != NULL);
EXPECT_TRUE(method->GetClass() != NULL);
- EXPECT_TRUE(method->GetName() != NULL);
- EXPECT_TRUE(method->GetSignature() != NULL);
+ EXPECT_TRUE(mh.GetName() != NULL);
+ EXPECT_TRUE(mh.GetSignature() != NULL);
EXPECT_TRUE(method->GetDexCacheStrings() != NULL);
EXPECT_TRUE(method->GetDexCacheResolvedTypes() != NULL);
@@ -135,17 +144,18 @@
}
void AssertField(Class* klass, Field* field) {
+ FieldHelper fh(field);
EXPECT_TRUE(field != NULL);
EXPECT_TRUE(field->GetClass() != NULL);
EXPECT_EQ(klass, field->GetDeclaringClass());
- EXPECT_TRUE(field->GetName() != NULL);
- EXPECT_TRUE(field->GetType() != NULL);
+ EXPECT_TRUE(fh.GetName() != NULL);
+ EXPECT_TRUE(fh.GetType() != NULL);
}
void AssertClass(const std::string& descriptor, Class* klass) {
- EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
- SirtRef<String> Object_descriptor(String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
- if (klass->GetDescriptor()->Equals(Object_descriptor.get())) {
+ ClassHelper kh(klass);
+ EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor().c_str());
+ if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
} else {
EXPECT_TRUE(klass->HasSuperClass());
@@ -160,11 +170,12 @@
EXPECT_FALSE(klass->IsArrayClass());
EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_TRUE(klass->IsInSamePackage(klass));
- EXPECT_TRUE(Class::IsInSamePackage(klass->GetDescriptor(), klass->GetDescriptor()));
+ EXPECT_TRUE(Class::IsInSamePackage(kh.GetDescriptor(), kh.GetDescriptor()));
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
- EXPECT_TRUE(klass->GetDirectMethod(0)->IsClassInitializer());
+ MethodHelper mh(klass->GetDirectMethod(0));
+ EXPECT_TRUE(mh.IsClassInitializer());
EXPECT_TRUE(klass->GetDirectMethod(0)->IsDirect());
} else {
EXPECT_EQ(0U, klass->NumDirectMethods());
@@ -233,18 +244,21 @@
// Confirm that all instances fields are packed together at the start
EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
+ FieldHelper fh;
for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- ASSERT_TRUE(!field->IsPrimitiveType());
- Class* field_type = field->GetType();
+ fh.ChangeField(field);
+ ASSERT_TRUE(!fh.IsPrimitiveType());
+ Class* field_type = fh.GetType();
ASSERT_TRUE(field_type != NULL);
ASSERT_TRUE(!field_type->IsPrimitive());
}
for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- Class* field_type = field->GetType();
+ fh.ChangeField(field);
+ Class* field_type = fh.GetType();
ASSERT_TRUE(field_type != NULL);
- if (!field->IsPrimitiveType() || !field_type->IsPrimitive()) {
+ if (!fh.IsPrimitiveType() || !field_type->IsPrimitive()) {
// While Reference.referent is not primitive, the ClassLinker
// treats it as such so that the garbage collector won't scan it.
EXPECT_EQ(PrettyField(field), "java.lang.Object java.lang.ref.Reference.referent");
@@ -265,7 +279,7 @@
ASSERT_TRUE(descriptor != NULL);
Class* klass = class_linker_->FindSystemClass(descriptor);
ASSERT_TRUE(klass != NULL);
- EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
+ EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass).GetDescriptor().c_str());
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
AssertPrimitiveClass(descriptor, klass);
@@ -339,9 +353,12 @@
error = true;
}
+ FieldHelper fh;
for (size_t i = 0; i < offsets.size(); i++) {
Field* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
- if (!field->GetName()->Equals(offsets[i].java_name)) {
+ fh.ChangeField(field);
+ StringPiece field_name(fh.GetName());
+ if (field_name != offsets[i].java_name) {
error = true;
}
}
@@ -349,12 +366,14 @@
for (size_t i = 0; i < offsets.size(); i++) {
CheckOffset& offset = offsets[i];
Field* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
- if (!field->GetName()->Equals(offsets[i].java_name)) {
+ fh.ChangeField(field);
+ StringPiece field_name(fh.GetName());
+ if (field_name != offsets[i].java_name) {
LG << "JAVA FIELD ORDER MISMATCH NEXT LINE:";
}
LG << "Java field order:"
<< " i=" << i << " class=" << class_descriptor
- << " Java=" << field->GetName()->ToModifiedUtf8()
+ << " Java=" << field_name
<< " CheckOffsets=" << offset.java_name;
}
}
@@ -401,17 +420,12 @@
struct FieldOffsets : public CheckOffsets<Field> {
FieldOffsets() : CheckOffsets<Field>(false, "Ljava/lang/reflect/Field;") {
// alphabetical references
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, declaring_class_), "declaringClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, generic_type_), "genericType"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, name_), "name"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, type_), "type"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, declaring_class_), "declaringClass"));
// alphabetical 32-bit
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, generic_types_are_initialized_), "genericTypesAreInitialized"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, access_flags_), "shadow$_access_flags_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, offset_), "shadow$_offset_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, type_idx_), "shadow$_type_idx_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, slot_), "slot"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, access_flags_), "accessFlags"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, field_dex_idx_), "fieldDexIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Field, offset_), "offset"));
};
};
@@ -419,43 +433,27 @@
MethodOffsets() : CheckOffsets<Method>(false, "Ljava/lang/reflect/Method;") {
// alphabetical references
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, declaring_class_), "declaringClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_exception_types_), "exceptionTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_formal_type_parameters_), "formalTypeParameters"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_exception_types_), "genericExceptionTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_parameter_types_), "genericParameterTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_return_type_), "genericReturnType"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, name_), "name"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_parameter_types_), "parameterTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_return_type_), "returnType"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_code_and_direct_methods_), "shadow$_dex_cache_code_and_direct_methods_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_initialized_static_storage_), "shadow$_dex_cache_initialized_static_storage_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_fields_), "shadow$_dex_cache_resolved_fields_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_methods_), "shadow$_dex_cache_resolved_methods_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_types_), "shadow$_dex_cache_resolved_types_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_), "shadow$_dex_cache_strings_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, gc_map_), "shadow$_gc_map_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, shorty_), "shadow$_shorty_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, signature_), "shadow$_signature_"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_code_and_direct_methods_), "dexCacheCodeAndDirectMethods"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_initialized_static_storage_), "dexCacheInitializedStaticStorage"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_fields_), "dexCacheResolvedFields"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_methods_), "dexCacheResolvedMethods"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_types_), "dexCacheResolvedTypes"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_), "dexCacheStrings"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, gc_map_), "gcMap"));
// alphabetical 32-bit
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_types_are_initialized_), "genericTypesAreInitialized"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, access_flags_), "shadow$_access_flags_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_), "shadow$_code_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_item_offset_), "shadow$_code_item_offset_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, core_spill_mask_), "shadow$_core_spill_mask_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, fp_spill_mask_), "shadow$_fp_spill_mask_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, frame_size_in_bytes_), "shadow$_frame_size_in_bytes_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_), "shadow$_invoke_stub_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_return_type_idx_), "shadow$_java_return_type_idx_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, mapping_table_), "shadow$_mapping_table_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_index_), "shadow$_method_index_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, native_method_), "shadow$_native_method_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_ins_), "shadow$_num_ins_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_outs_), "shadow$_num_outs_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_registers_), "shadow$_num_registers_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, proto_idx_), "shadow$_proto_idx_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, vmap_table_), "shadow$_vmap_table_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_slot_), "slot"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, access_flags_), "accessFlags"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_), "code"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_item_offset_), "codeItemOffset"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, core_spill_mask_), "coreSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, fp_spill_mask_), "fpSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, frame_size_in_bytes_), "frameSizeInBytes"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_), "invokeStub"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, mapping_table_), "mappingTable"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_dex_index_), "methodDexIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_index_), "methodIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, native_method_), "nativeMethod"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, vmap_table_), "vmapTable"));
};
};
@@ -472,23 +470,19 @@
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, name_), "name"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_loader_), "shadow$_class_loader_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, component_type_), "shadow$_component_type_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, descriptor_), "shadow$_descriptor_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, dex_cache_), "shadow$_dex_cache_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, direct_methods_), "shadow$_direct_methods_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, ifields_), "shadow$_ifields_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, iftable_), "shadow$_iftable_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, interfaces_), "shadow$_interfaces_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, interfaces_type_idx_), "shadow$_interfaces_type_idx_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, sfields_), "shadow$_sfields_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, source_file_), "shadow$_source_file_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, super_class_), "shadow$_super_class_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, verify_error_class_), "shadow$_verify_error_class_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, virtual_methods_), "shadow$_virtual_methods_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, vtable_), "shadow$_vtable_"));
// alphabetical 32-bit
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, dex_type_idx_), "dexTypeIndex"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, access_flags_), "shadow$_access_flags_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, annotations_offset_), "shadow$_annotations_offset_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_size_), "shadow$_class_size_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, clinit_thread_id_), "shadow$_clinit_thread_id_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, num_reference_instance_fields_), "shadow$_num_reference_instance_fields_"));
@@ -498,8 +492,6 @@
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, reference_instance_offsets_), "shadow$_reference_instance_offsets_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, reference_static_offsets_), "shadow$_reference_static_offsets_"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, status_), "shadow$_status_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, super_class_type_idx_), "shadow$_super_class_type_idx_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, type_idx_), "shadow$_type_idx_"));
};
};
@@ -595,16 +587,6 @@
FieldClassOffsets() : CheckOffsets<FieldClass>(true, "Ljava/lang/reflect/Field;") {
// alphabetical references
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, ORDER_BY_NAME_AND_DECLARING_CLASS_), "ORDER_BY_NAME_AND_DECLARING_CLASS"));
-
- // alphabetical 32-bit
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_BOOLEAN_), "TYPE_BOOLEAN"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_BYTE_), "TYPE_BYTE"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_CHAR_), "TYPE_CHAR"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_DOUBLE_), "TYPE_DOUBLE"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_FLOAT_), "TYPE_FLOAT"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_INTEGER_), "TYPE_INTEGER"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_LONG_), "TYPE_LONG"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(FieldClass, TYPE_SHORT_), "TYPE_SHORT"));
};
};
@@ -683,11 +665,12 @@
TEST_F(ClassLinkerTest, FindClass) {
Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
+ ClassHelper kh(JavaLangObject);
ASSERT_TRUE(JavaLangObject != NULL);
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
- ASSERT_TRUE(JavaLangObject->GetDescriptor()->Equals("Ljava/lang/Object;"));
+ ASSERT_STREQ(kh.GetDescriptor().c_str(), "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
@@ -708,20 +691,23 @@
EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
- EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
- EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
+ FieldHelper fh(JavaLangObject->GetInstanceField(0));
+ EXPECT_STREQ(fh.GetName(), "shadow$_klass_");
+ fh.ChangeField(JavaLangObject->GetInstanceField(1));
+ EXPECT_STREQ(fh.GetName(), "shadow$_monitor_");
EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
- EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
+ EXPECT_EQ(0U, kh.NumInterfaces());
SirtRef<ClassLoader> class_loader(LoadDex("MyClass"));
AssertNonExistentClass("LMyClass;");
Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader.get());
+ kh.ChangeClass(MyClass);
ASSERT_TRUE(MyClass != NULL);
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
- ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
+ ASSERT_STREQ(kh.GetDescriptor().c_str(), "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.get(), MyClass->GetClassLoader());
@@ -743,7 +729,7 @@
EXPECT_EQ(0U, MyClass->NumVirtualMethods());
EXPECT_EQ(0U, MyClass->NumInstanceFields());
EXPECT_EQ(0U, MyClass->NumStaticFields());
- EXPECT_EQ(0U, MyClass->NumInterfaces());
+ EXPECT_EQ(0U, kh.NumInterfaces());
EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
@@ -785,21 +771,29 @@
// This lets UnboxPrimitive avoid searching for the field by name at runtime.
Class* c;
c = class_linker_->FindClass("Ljava/lang/Boolean;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ FieldHelper fh(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Byte;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Character;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Double;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Float;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Integer;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Long;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
c = class_linker_->FindClass("Ljava/lang/Short;", NULL);
- EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+ fh.ChangeField(c->GetIFields()->Get(0));
+ EXPECT_STREQ("value", fh.GetName());
}
TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
@@ -826,48 +820,57 @@
EXPECT_EQ(9U, statics->NumStaticFields());
Field* s0 = statics->FindStaticField("s0", "Z");
- EXPECT_TRUE(s0->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Field;"));
- EXPECT_TRUE(s0->GetPrimitiveType() == Primitive::kPrimBoolean);
+ FieldHelper fh(s0);
+ EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor().c_str(), "Ljava/lang/reflect/Field;");
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(NULL));
s0->SetBoolean(NULL, false);
Field* s1 = statics->FindStaticField("s1", "B");
- EXPECT_TRUE(s1->GetPrimitiveType() == Primitive::kPrimByte);
+ fh.ChangeField(s1);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimByte);
EXPECT_EQ(5, s1->GetByte(NULL));
s1->SetByte(NULL, 6);
Field* s2 = statics->FindStaticField("s2", "C");
- EXPECT_TRUE(s2->GetPrimitiveType() == Primitive::kPrimChar);
+ fh.ChangeField(s2);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimChar);
EXPECT_EQ('a', s2->GetChar(NULL));
s2->SetChar(NULL, 'b');
Field* s3 = statics->FindStaticField("s3", "S");
- EXPECT_TRUE(s3->GetPrimitiveType() == Primitive::kPrimShort);
+ fh.ChangeField(s3);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimShort);
EXPECT_EQ(-536, s3->GetShort(NULL));
s3->SetShort(NULL, -535);
Field* s4 = statics->FindStaticField("s4", "I");
- EXPECT_TRUE(s4->GetPrimitiveType() == Primitive::kPrimInt);
+ fh.ChangeField(s4);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimInt);
EXPECT_EQ(2000000000, s4->GetInt(NULL));
s4->SetInt(NULL, 2000000001);
Field* s5 = statics->FindStaticField("s5", "J");
- EXPECT_TRUE(s5->GetPrimitiveType() == Primitive::kPrimLong);
+ fh.ChangeField(s5);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimLong);
EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL));
s5->SetLong(NULL, 0x34567890abcdef12LL);
Field* s6 = statics->FindStaticField("s6", "F");
- EXPECT_TRUE(s6->GetPrimitiveType() == Primitive::kPrimFloat);
+ fh.ChangeField(s6);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimFloat);
EXPECT_EQ(0.5, s6->GetFloat(NULL));
s6->SetFloat(NULL, 0.75);
Field* s7 = statics->FindStaticField("s7", "D");
- EXPECT_TRUE(s7->GetPrimitiveType() == Primitive::kPrimDouble);
+ fh.ChangeField(s7);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimDouble);
EXPECT_EQ(16777217, s7->GetDouble(NULL));
s7->SetDouble(NULL, 16777219);
Field* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
- EXPECT_TRUE(s8->GetPrimitiveType() == Primitive::kPrimNot);
+ fh.ChangeField(s8);
+ EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot);
EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android"));
s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
@@ -986,4 +989,15 @@
EXPECT_TRUE(c->IsFinalizable());
}
+TEST_F(ClassLinkerTest, ClassRootDescriptors) {
+ ClassHelper kh;
+ for (int i = 0; i < ClassLinker::kClassRootsMax; i++) {
+ Class* klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
+ kh.ChangeClass(klass);
+ EXPECT_TRUE(kh.GetDescriptor() != NULL);
+ EXPECT_STREQ(kh.GetDescriptor().c_str(),
+ class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
+ }
+}
+
} // namespace art
diff --git a/src/common_test.h b/src/common_test.h
index d140d40..48a9c39 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -17,6 +17,7 @@
#include "gtest/gtest.h"
#include "heap.h"
#include "oat_file.h"
+#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "stl_util.h"
@@ -118,9 +119,9 @@
void MakeExecutable(Method* method) {
CHECK(method != NULL);
+ MethodHelper mh(method);
const CompiledInvokeStub* compiled_invoke_stub =
- compiler_->FindInvokeStub(method->IsStatic(),
- method->GetShorty()->ToModifiedUtf8().c_str());
+ compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty());
CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method);
const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
MakeExecutable(invoke_stub);
diff --git a/src/compiler.cc b/src/compiler.cc
index fba767d..e437062 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -11,6 +11,7 @@
#include "jni_compiler.h"
#include "jni_internal.h"
#include "oat_file.h"
+#include "object_utils.h"
#include "runtime.h"
#include "stl_util.h"
@@ -145,6 +146,18 @@
return image_classes_->find(descriptor) != image_classes_->end();
}
+bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
+ uint32_t type_idx) const {
+ if (!IsImage()) {
+ return false;
+ }
+ Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
+ if (resolved_class == NULL) {
+ return false;
+ }
+ return IsImageClass(ClassHelper(resolved_class).GetDescriptor());
+}
+
// Return true if the class should be skipped during compilation. We
// never skip classes in the boot class loader. However, if we have a
// non-boot class loader and we can resolve the class in the boot
diff --git a/src/compiler.h b/src/compiler.h
index 5203ffb..4e1be1d 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -70,16 +70,7 @@
const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
// Callbacks from OAT/ART compiler to see what runtime checks must be generated
- bool CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache, uint32_t type_idx) const {
- if (!IsImage()) {
- return false;
- }
- Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
- if (resolved_class == NULL) {
- return false;
- }
- return IsImageClass(resolved_class->GetDescriptor()->ToModifiedUtf8());
- }
+ bool CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache, uint32_t type_idx) const;
bool CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache, uint32_t string_idx) const {
// TODO: Add support for loading strings referenced by image_classes_
// See also Compiler::ResolveDexFile
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 5d2c4e6..60a5f38 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -263,17 +263,19 @@
/* Return sp-relative offset in bytes using Method* */
-extern int oatVRegOffsetFromMethod(Method* method, int reg)
+extern int oatVRegOffset(const art::DexFile::CodeItem* code_item,
+ uint32_t core_spills, uint32_t fp_spills,
+ size_t frame_size, int reg)
{
- int numIns = method->NumIns();
- int numRegs = method->NumRegisters() - numIns;
- int numOuts = method->NumOuts();
- int numSpills = __builtin_popcount(method->GetCoreSpillMask()) +
- __builtin_popcount(method->GetFpSpillMask());
+ int numIns = code_item->ins_size_;
+ int numRegs = code_item->registers_size_ - numIns;
+ int numOuts = code_item->outs_size_;
+ int numSpills = __builtin_popcount(core_spills) +
+ __builtin_popcount(fp_spills);
int numPadding = (STACK_ALIGN_WORDS -
(numSpills + numRegs + numOuts + 2)) & (STACK_ALIGN_WORDS-1);
int regsOffset = (numOuts + numPadding + 1) * 4;
- int insOffset = method->GetFrameSizeInBytes() + 4;
+ int insOffset = frame_size + 4;
return (reg < numRegs) ? regsOffset + (reg << 2) :
insOffset + ((reg - numRegs) << 2);
}
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 15fd1ba..2c3ee0d 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "object_utils.h"
+
#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
(1 << kDebugDisplayMissingTargets))
@@ -192,7 +194,7 @@
// See if we can find a dex reference for the storage class.
// we may not if the dex file never references the super class,
// but usually it will.
- std::string descriptor = field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8();
+ std::string descriptor(art::FieldHelper(field).GetDeclaringClassDescriptor());
const art::DexFile::StringId* string_id =
cUnit->dex_file->FindStringId(descriptor);
if (string_id == NULL) {
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc
index d4c1ed2..f8be881 100644
--- a/src/dalvik_system_VMRuntime.cc
+++ b/src/dalvik_system_VMRuntime.cc
@@ -18,6 +18,7 @@
#include "debugger.h"
#include "jni_internal.h"
#include "object.h"
+#include "object_utils.h"
#include "thread.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -65,7 +66,7 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
std::string descriptor;
descriptor += "[";
- descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+ descriptor += ClassHelper(element_class).GetDescriptor();
Class* array_class = class_linker->FindClass(descriptor, NULL);
Array* result = Array::Alloc(array_class, length);
if (result == NULL) {
diff --git a/src/debugger.cc b/src/debugger.cc
index 3a6c154..b2f9629 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -23,6 +23,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "context.h"
+#include "object_utils.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "stack_indirect_reference_table.h"
@@ -87,15 +88,11 @@
};
struct AllocRecordStackTraceElement {
- const Method* method;
+ Method* method;
uintptr_t raw_pc;
int32_t LineNumber() const {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* c = method->GetDeclaringClass();
- DexCache* dex_cache = c->GetDexCache();
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- return dex_file.GetLineNumFromPC(method, method->ToDexPC(raw_pc));
+ return MethodHelper(method).GetLineNumFromNativePC(raw_pc);
}
};
@@ -452,7 +449,7 @@
std::string Dbg::GetClassDescriptor(JDWP::RefTypeId classId) {
Class* c = gRegistry->Get<Class*>(classId);
- return c->GetDescriptor()->ToModifiedUtf8();
+ return ClassHelper(c).GetDescriptor();
}
JDWP::ObjectId Dbg::GetClassObject(JDWP::RefTypeId id) {
@@ -527,7 +524,7 @@
}
if (pDescriptor != NULL) {
- *pDescriptor = c->GetDescriptor()->ToModifiedUtf8();
+ *pDescriptor = ClassHelper(c).GetDescriptor();
}
}
@@ -560,19 +557,14 @@
std::string Dbg::GetSignature(JDWP::RefTypeId refTypeId) {
Class* c = gRegistry->Get<Class*>(refTypeId);
CHECK(c != NULL);
- return c->GetDescriptor()->ToModifiedUtf8();
+ return ClassHelper(c).GetDescriptor();
}
bool Dbg::GetSourceFile(JDWP::RefTypeId refTypeId, std::string& result) {
Class* c = gRegistry->Get<Class*>(refTypeId);
CHECK(c != NULL);
-
- String* source_file = c->GetSourceFile();
- if (source_file == NULL) {
- return false;
- }
- result = source_file->ToModifiedUtf8();
- return true;
+ result = ClassHelper(c).GetSourceFile();
+ return result == NULL;
}
uint8_t Dbg::GetObjectTag(JDWP::ObjectId objectId) {
@@ -619,7 +611,7 @@
uint8_t Dbg::GetArrayElementTag(JDWP::ObjectId arrayId) {
Object* o = gRegistry->Get<Object*>(arrayId);
Array* a = o->AsArray();
- std::string descriptor(a->GetClass()->GetDescriptor()->ToModifiedUtf8());
+ std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
if (!IsPrimitiveTag(tag)) {
tag = TagFromClass(a->GetClass()->GetComponentType());
@@ -635,8 +627,7 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return false;
}
-
- std::string descriptor(a->GetClass()->GetDescriptor()->ToModifiedUtf8());
+ std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
if (IsPrimitiveTag(tag)) {
@@ -676,8 +667,7 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return false;
}
-
- std::string descriptor(a->GetClass()->GetDescriptor()->ToModifiedUtf8());
+ std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
if (IsPrimitiveTag(tag)) {
@@ -763,7 +753,8 @@
}
std::string Dbg::GetMethodName(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId) {
- return FromMethodId(methodId)->GetName()->ToModifiedUtf8();
+ Method* m = FromMethodId(methodId);
+ return MethodHelper(m).GetName();
}
/*
@@ -808,8 +799,8 @@
if (slot == kEclipseWorkaroundSlot) {
return 0;
} else if (slot == 0) {
- Method* m = f.GetMethod();
- return m->NumRegisters() - m->NumIns();
+ const DexFile::CodeItem* code_item = MethodHelper(f.GetMethod()).GetCodeItem();
+ return code_item->registers_size_ - code_item->ins_size_;
}
return slot;
}
@@ -825,10 +816,10 @@
for (size_t i = 0; i < instance_field_count + static_field_count; ++i) {
Field* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count);
-
+ FieldHelper fh(f);
expandBufAddFieldId(pReply, ToFieldId(f));
- expandBufAddUtf8String(pReply, f->GetName()->ToModifiedUtf8().c_str());
- expandBufAddUtf8String(pReply, f->GetTypeDescriptor());
+ expandBufAddUtf8String(pReply, fh.GetName());
+ expandBufAddUtf8String(pReply, fh.GetTypeDescriptor());
if (with_generic) {
static const char genericSignature[1] = "";
expandBufAddUtf8String(pReply, genericSignature);
@@ -848,10 +839,10 @@
for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) {
Method* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count);
-
+ MethodHelper mh(m);
expandBufAddMethodId(pReply, ToMethodId(m));
- expandBufAddUtf8String(pReply, m->GetName()->ToModifiedUtf8().c_str());
- expandBufAddUtf8String(pReply, m->GetSignature()->ToModifiedUtf8().c_str());
+ expandBufAddUtf8String(pReply, mh.GetName());
+ expandBufAddUtf8String(pReply, mh.GetSignature().c_str());
if (with_generic) {
static const char genericSignature[1] = "";
expandBufAddUtf8String(pReply, genericSignature);
@@ -863,10 +854,11 @@
void Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply) {
Class* c = gRegistry->Get<Class*>(refTypeId);
CHECK(c != NULL);
- size_t interface_count = c->NumInterfaces();
+ ClassHelper kh(c);
+ size_t interface_count = kh.NumInterfaces();
expandBufAdd4BE(pReply, interface_count);
for (size_t i = 0; i < interface_count; ++i) {
- expandBufAddRefTypeId(pReply, gRegistry->Add(c->GetInterface(i)));
+ expandBufAddRefTypeId(pReply, gRegistry->Add(kh.GetInterface(i)));
}
}
@@ -885,17 +877,15 @@
};
Method* m = FromMethodId(methodId);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const DexFile& dex_file = class_linker->FindDexFile(m->GetDeclaringClass()->GetDexCache());
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(m->GetCodeItemOffset());
-
+ MethodHelper mh(m);
uint64_t start, end;
if (m->IsNative()) {
start = -1;
end = -1;
} else {
start = 0;
- end = code_item->insns_size_in_code_units_; // TODO: what are the units supposed to be? *2?
+ // TODO: what are the units supposed to be? *2?
+ end = mh.GetCodeItem()->insns_size_in_code_units_;
}
expandBufAdd8BE(pReply, start);
@@ -909,7 +899,8 @@
context.numItems = 0;
context.pReply = pReply;
- dex_file.DecodeDebugInfo(code_item, m, DebugCallbackContext::Callback, NULL, &context);
+ mh.GetDexFile().DecodeDebugInfo(mh.GetCodeItem(), m->IsStatic(), m->GetDexMethodIndex(),
+ DebugCallbackContext::Callback, NULL, &context);
JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems);
}
@@ -941,13 +932,12 @@
};
Method* m = FromMethodId(methodId);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const DexFile& dex_file = class_linker->FindDexFile(m->GetDeclaringClass()->GetDexCache());
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(m->GetCodeItemOffset());
+ MethodHelper mh(m);
+ const DexFile::CodeItem* code_item = mh.GetCodeItem();
// arg_count considers doubles and longs to take 2 units.
// variable_count considers everything to take 1 unit.
- std::string shorty(m->GetShorty()->ToModifiedUtf8());
+ std::string shorty(mh.GetShorty());
expandBufAdd4BE(pReply, m->NumArgRegisters(shorty));
// We don't know the total number of variables yet, so leave a blank and update it later.
@@ -959,24 +949,25 @@
context.variable_count = 0;
context.with_generic = with_generic;
- dex_file.DecodeDebugInfo(code_item, m, NULL, DebugCallbackContext::Callback, &context);
+ mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL,
+ DebugCallbackContext::Callback, &context);
JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
}
JDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId fieldId) {
- return BasicTagFromDescriptor(FromFieldId(fieldId)->GetTypeDescriptor());
+ return BasicTagFromDescriptor(FieldHelper(FromFieldId(fieldId)).GetTypeDescriptor());
}
JDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId fieldId) {
- return BasicTagFromDescriptor(FromFieldId(fieldId)->GetTypeDescriptor());
+ return BasicTagFromDescriptor(FieldHelper(FromFieldId(fieldId)).GetTypeDescriptor());
}
void Dbg::GetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
Object* o = gRegistry->Get<Object*>(objectId);
Field* f = FromFieldId(fieldId);
- JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());
if (IsPrimitiveTag(tag)) {
expandBufAdd1(pReply, tag);
@@ -1002,7 +993,7 @@
Object* o = gRegistry->Get<Object*>(objectId);
Field* f = FromFieldId(fieldId);
- JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());
if (IsPrimitiveTag(tag)) {
if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
@@ -2120,11 +2111,11 @@
StringTable() {
}
- void Add(const String* s) {
+ void Add(const char* s) {
table_.insert(s);
}
- size_t IndexOf(const String* s) {
+ size_t IndexOf(const char* s) {
return std::distance(table_.begin(), table_.find(s));
}
@@ -2133,15 +2124,18 @@
}
void WriteTo(std::vector<uint8_t>& bytes) {
- typedef std::set<const String*>::const_iterator It; // TODO: C++0x auto
+ typedef std::set<const char*>::const_iterator It; // TODO: C++0x auto
for (It it = table_.begin(); it != table_.end(); ++it) {
- const String* s = *it;
- JDWP::AppendUtf16BE(bytes, s->GetCharArray()->GetData(), s->GetLength());
+ const char* s = *it;
+ size_t s_len = CountModifiedUtf8Chars(s);
+ UniquePtr<uint16_t> s_utf16(new uint16_t[s_len]);
+ ConvertModifiedUtf8ToUtf16(s_utf16.get(), s);
+ JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len);
}
}
private:
- std::set<const String*> table_;
+ std::set<const char*> table_;
DISALLOW_COPY_AND_ASSIGN(StringTable);
};
@@ -2206,14 +2200,16 @@
while (count--) {
AllocRecord* record = &recent_allocation_records_[idx];
- class_names.Add(record->type->GetDescriptor());
+ class_names.Add(ClassHelper(record->type).GetDescriptor().c_str());
+ MethodHelper mh;
for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
- const Method* m = record->stack[i].method;
+ Method* m = record->stack[i].method;
+ mh.ChangeMethod(m);
if (m != NULL) {
- class_names.Add(m->GetDeclaringClass()->GetDescriptor());
- method_names.Add(m->GetName());
- filenames.Add(m->GetDeclaringClass()->GetSourceFile());
+ class_names.Add(mh.GetDeclaringClassDescriptor());
+ method_names.Add(mh.GetName());
+ filenames.Add(mh.GetDeclaringClassSourceFile());
}
}
@@ -2251,6 +2247,7 @@
count = gAllocRecordCount;
idx = headIndex();
+ ClassHelper kh;
while (count--) {
// For each entry:
// (4b) total allocation size
@@ -2261,19 +2258,21 @@
size_t stack_depth = record->GetDepth();
JDWP::Append4BE(bytes, record->byte_count);
JDWP::Append2BE(bytes, record->thin_lock_id);
- JDWP::Append2BE(bytes, class_names.IndexOf(record->type->GetDescriptor()));
+ kh.ChangeClass(record->type);
+ JDWP::Append2BE(bytes, class_names.IndexOf(kh.GetDescriptor().c_str()));
JDWP::Append1BE(bytes, stack_depth);
+ MethodHelper mh;
for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
// For each stack frame:
// (2b) method's class name
// (2b) method name
// (2b) method source file
// (2b) line number, clipped to 32767; -2 if native; -1 if no source
- const Method* m = record->stack[stack_frame].method;
- JDWP::Append2BE(bytes, class_names.IndexOf(m->GetDeclaringClass()->GetDescriptor()));
- JDWP::Append2BE(bytes, method_names.IndexOf(m->GetName()));
- JDWP::Append2BE(bytes, filenames.IndexOf(m->GetDeclaringClass()->GetSourceFile()));
+ mh.ChangeMethod(record->stack[stack_frame].method);
+ JDWP::Append2BE(bytes, class_names.IndexOf(mh.GetDeclaringClassDescriptor()));
+ JDWP::Append2BE(bytes, method_names.IndexOf(mh.GetName()));
+ JDWP::Append2BE(bytes, filenames.IndexOf(mh.GetDeclaringClassSourceFile()));
JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber());
}
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 0e4c224..1261bb9 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -15,6 +15,7 @@
#include "file.h"
#include "image_writer.h"
#include "oat_writer.h"
+#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "stringpiece.h"
@@ -242,7 +243,7 @@
if (klass->IsArrayClass() || klass->IsPrimitive()) {
return true;
}
- image_classes->insert(klass->GetDescriptor()->ToModifiedUtf8());
+ image_classes->insert(ClassHelper(klass).GetDescriptor());
return true;
}
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 5185ba8..01bb6d5 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -571,7 +571,7 @@
}
const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
- const std::vector<uint16_t>& signature_type_ids) const {
+ const std::vector<uint16_t>& signature_type_idxs) const {
uint32_t lo = 0;
uint32_t hi = NumProtoIds() - 1;
while (hi >= lo) {
@@ -581,15 +581,15 @@
if (compare == 0) {
DexFileParameterIterator it(*this, proto);
size_t i = 0;
- while (it.HasNext() && i < signature_type_ids.size() && compare == 0) {
- compare = signature_type_ids[i] - it.GetTypeId();
+ while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
+ compare = signature_type_idxs[i] - it.GetTypeIdx();
it.Next();
i++;
}
if (compare == 0) {
if (it.HasNext()) {
compare = -1;
- } else if (i < signature_type_ids.size()) {
+ } else if (i < signature_type_idxs.size()) {
compare = 1;
}
}
@@ -704,7 +704,8 @@
// A method with no line number info should return -1
LineNumFromPcContext context(rel_pc, -1);
- DecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
+ DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
+ NULL, &context);
return context.line_num_;
}
@@ -733,7 +734,7 @@
return -1;
}
-void DexFile::DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
uint32_t line = DecodeUnsignedLeb128(&stream);
@@ -742,13 +743,11 @@
uint32_t address = 0;
bool need_locals = (local_cb != NULL);
- if (!method->IsStatic()) {
+ if (!is_static) {
if (need_locals) {
- std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8();
- const ClassDef* class_def = FindClassDef(descriptor);
- CHECK(class_def != NULL) << descriptor;
+ const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
local_in_reg[arg_reg].name_ = "this";
- local_in_reg[arg_reg].descriptor_ = GetClassDescriptor(*class_def);
+ local_in_reg[arg_reg].descriptor_ = descriptor;
local_in_reg[arg_reg].signature_ = NULL;
local_in_reg[arg_reg].start_address_ = 0;
local_in_reg[arg_reg].is_live_ = true;
@@ -756,7 +755,7 @@
arg_reg++;
}
- DexFileParameterIterator it(*this, GetProtoId(method->GetProtoIdx()));
+ DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
if (arg_reg >= code_item->registers_size_) {
LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
@@ -897,14 +896,14 @@
}
}
-void DexFile::DecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
+void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
void* cnxt) const {
const byte* stream = GetDebugInfoStream(code_item);
LocalInfo local_in_reg[code_item->registers_size_];
if (stream != NULL) {
- DecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
+ DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
}
for (int reg = 0; reg < code_item->registers_size_; reg++) {
InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
diff --git a/src/dex_file.h b/src/dex_file.h
index a7026d6..7f0f975 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -376,7 +376,9 @@
const char* GetMethodShorty(const MethodId& method_id) const {
return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
}
-
+ const char* GetMethodShorty(const MethodId& method_id, int32_t* length) const {
+ return StringDataAndLengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
+ }
// Returns the number of class definitions in the .dex file.
size_t NumClassDefs() const {
CHECK(header_ != NULL);
@@ -425,11 +427,11 @@
}
//
- const CodeItem* GetCodeItem(const uint32_t code_off_) const {
- if (code_off_ == 0) {
+ const CodeItem* GetCodeItem(const uint32_t code_off) const {
+ if (code_off == 0) {
return NULL; // native or abstract method
} else {
- const byte* addr = base_ + code_off_;
+ const byte* addr = base_ + code_off;
return reinterpret_cast<const CodeItem*>(addr);
}
}
@@ -458,7 +460,7 @@
// Looks up a proto id for a given return type and signature type list
const ProtoId* FindProtoId(uint16_t return_type_id,
- const std::vector<uint16_t>& signature_type_ids_) const;
+ const std::vector<uint16_t>& signature_type_idxs_) const;
// Given a signature place the type ids into the given vector, returns true on success
bool CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
@@ -592,7 +594,7 @@
// This is used by runtime; therefore use art::Method not art::DexFile::Method.
int32_t GetLineNumFromPC(const Method* method, uint32_t rel_pc) const;
- void DecodeDebugInfo(const CodeItem* code_item, const Method* method,
+ void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
void* cnxt) const;
@@ -657,14 +659,12 @@
// Returns true if the header magic is of the expected value.
bool IsMagicValid();
- void DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+ void DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
- // The index of descriptors to class definition indexes.
- // TODO: given type_ids are sorted by string_id index, and string_ids are alphabetically, class
- // lookup can be done with a binary search. Is the index necessary?
+ // The index of descriptors to class definition indexes (as opposed to type id indexes)
typedef std::map<const StringPiece, uint32_t> Index;
Index index_;
@@ -721,11 +721,11 @@
}
bool HasNext() const { return pos_ < size_; }
void Next() { ++pos_; }
- uint16_t GetTypeId() {
+ uint16_t GetTypeIdx() {
return type_list_->GetTypeItem(pos_).type_idx_;
}
const char* GetDescriptor() {
- return dex_file_.StringByTypeIdx(GetTypeId());
+ return dex_file_.StringByTypeIdx(GetTypeIdx());
}
private:
const DexFile& dex_file_;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index d162aec..768880a 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -13,6 +13,7 @@
#include "intern_table.h"
#include "leb128.h"
#include "logging.h"
+#include "object_utils.h"
#include "runtime.h"
#include "stringpiece.h"
@@ -69,7 +70,7 @@
if (IsUnresolvedTypes()) {
result += PrettyDescriptor(GetDescriptor());
} else {
- result += PrettyDescriptor(GetClass()->GetDescriptor());
+ result += PrettyDescriptor(GetClass());
}
}
}
@@ -124,7 +125,8 @@
Class* common_elem = ClassJoin(s_ct, t_ct);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const ClassLoader* class_loader = s->GetClassLoader();
- std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
+ std::string descriptor = "[";
+ descriptor += ClassHelper(common_elem).GetDescriptor();
Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
DCHECK(array_class != NULL);
return array_class;
@@ -354,11 +356,15 @@
return *entry;
} else {
DCHECK (type == RegType::kRegTypeReference);
+ ClassHelper kh;
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
// check resolved and unresolved references, ignore uninitialized references
- if (cur_entry->IsReference() && cur_entry->GetClass()->GetDescriptor()->Equals(descriptor)) {
- return *cur_entry;
+ if (cur_entry->IsReference()) {
+ kh.ChangeClass(cur_entry->GetClass());
+ if (descriptor == kh.GetDescriptor()) {
+ return *cur_entry;
+ }
} else if (cur_entry->IsUnresolvedReference() &&
cur_entry->GetDescriptor()->Equals(descriptor)) {
return *cur_entry;
@@ -887,7 +893,7 @@
return true;
}
Class* super = klass->GetSuperClass();
- if (super == NULL && !klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
+ if (super == NULL && ClassHelper(klass).GetDescriptor() != "Ljava/lang/Object;") {
LOG(ERROR) << "Verifier rejected class " << PrettyClass(klass) << " that has no super class";
return false;
}
@@ -1574,7 +1580,8 @@
cur_arg++;
}
- const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_->GetProtoIdx());
+ const DexFile::ProtoId& proto_id =
+ dex_file_->GetMethodPrototype(dex_file_->GetMethodId(method_->GetDexMethodIndex()));
DexFileParameterIterator iterator(*dex_file_, proto_id);
for (; iterator.HasNext(); iterator.Next()) {
@@ -2145,7 +2152,7 @@
if (!res_class->IsArrayClass() || !component_type->IsPrimitive() ||
component_type->IsPrimitiveVoid()) {
Fail(VERIFY_ERROR_GENERIC) << "invalid fill-array-data on "
- << PrettyDescriptor(res_class->GetDescriptor());
+ << PrettyDescriptor(res_class);
} else {
const RegType& value_type = reg_types_.FromClass(component_type);
DCHECK(!value_type.IsUnknown());
@@ -2366,7 +2373,7 @@
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
- descriptor = called_method->GetReturnTypeDescriptor();
+ descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
const RegType& return_type =
reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
@@ -2444,7 +2451,7 @@
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
- descriptor = called_method->GetReturnTypeDescriptor();
+ descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
const RegType& return_type =
reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
@@ -2465,7 +2472,7 @@
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
- descriptor = called_method->GetReturnTypeDescriptor();
+ descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
const RegType& return_type =
reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
@@ -2520,7 +2527,7 @@
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
- descriptor = abs_method->GetReturnTypeDescriptor();
+ descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor();
}
const RegType& return_type =
reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
@@ -2965,7 +2972,7 @@
// check at runtime if access is allowed and so pass here.
if (!result.IsUnresolvedTypes() && !referrer->CanAccess(result.GetClass())) {
Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '"
- << PrettyDescriptor(referrer->GetDescriptor()) << "' -> '"
+ << PrettyDescriptor(referrer) << "' -> '"
<< result << "'";
return reg_types_.Unknown();
} else {
@@ -3038,7 +3045,7 @@
dex_cache->SetResolvedMethod(method_idx, res_method);
} else {
Fail(VERIFY_ERROR_NO_METHOD) << "couldn't find method "
- << PrettyDescriptor(klass->GetDescriptor()) << "." << name
+ << PrettyDescriptor(klass) << "." << name
<< " " << signature;
return NULL;
}
@@ -3046,7 +3053,7 @@
/* Check if access is allowed. */
if (!referrer->CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
Fail(VERIFY_ERROR_ACCESS_METHOD) << "illegal method access (call " << PrettyMethod(res_method)
- << " from " << PrettyDescriptor(referrer->GetDescriptor()) << ")";
+ << " from " << PrettyDescriptor(referrer) << ")";
return NULL;
}
return res_method;
@@ -3088,11 +3095,11 @@
Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from " << PrettyMethod(method_)
<< " to super " << PrettyMethod(res_method);
} else {
+ MethodHelper mh(res_method);
Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from " << PrettyMethod(method_)
- << " to super " << PrettyDescriptor(super->GetDescriptor())
- << "." << res_method->GetName()->ToModifiedUtf8()
- << " " << res_method->GetSignature()->ToModifiedUtf8();
-
+ << " to super " << PrettyDescriptor(super)
+ << "." << mh.GetName()
+ << mh.GetSignature();
}
return NULL;
}
@@ -3108,7 +3115,7 @@
<< ") exceeds outsSize (" << code_item_->outs_size_ << ")";
return NULL;
}
- std::string sig = res_method->GetSignature()->ToModifiedUtf8();
+ std::string sig(MethodHelper(res_method).GetSignature());
if (sig[0] != '(') {
Fail(VERIFY_ERROR_GENERIC) << "rejecting call to " << res_method
<< " as descriptor doesn't start with '(': " << sig;
@@ -3194,6 +3201,11 @@
}
}
+const RegType& DexVerifier::GetMethodReturnType() {
+ return reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(),
+ MethodHelper(method_).GetReturnTypeDescriptor());
+}
+
void DexVerifier::VerifyAGet(const Instruction::DecodedInstruction& dec_insn,
const RegType& insn_type, bool is_primitive) {
const RegType& index_type = work_line_->GetRegisterType(dec_insn.vC_);
@@ -3218,20 +3230,20 @@
const RegType& component_type = reg_types_.FromClass(component_class);
if (!array_class->IsArrayClass()) {
Fail(VERIFY_ERROR_GENERIC) << "not array type "
- << PrettyDescriptor(array_class->GetDescriptor()) << " with aget";
+ << PrettyDescriptor(array_class) << " with aget";
} else if (component_class->IsPrimitive() && !is_primitive) {
Fail(VERIFY_ERROR_GENERIC) << "primitive array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " source for aget-object";
} else if (!component_class->IsPrimitive() && is_primitive) {
Fail(VERIFY_ERROR_GENERIC) << "reference array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " source for category 1 aget";
} else if (is_primitive && !insn_type.Equals(component_type) &&
!((insn_type.IsInteger() && component_type.IsFloat()) ||
(insn_type.IsLong() && component_type.IsDouble()))) {
Fail(VERIFY_ERROR_GENERIC) << "array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " incompatible with aget of type " << insn_type;
} else {
// Use knowledge of the field type which is stronger than the type inferred from the
@@ -3261,20 +3273,20 @@
const RegType& component_type = reg_types_.FromClass(component_class);
if (!array_class->IsArrayClass()) {
Fail(VERIFY_ERROR_GENERIC) << "not array type "
- << PrettyDescriptor(array_class->GetDescriptor()) << " with aput";
+ << PrettyDescriptor(array_class) << " with aput";
} else if (component_class->IsPrimitive() && !is_primitive) {
Fail(VERIFY_ERROR_GENERIC) << "primitive array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " source for aput-object";
} else if (!component_class->IsPrimitive() && is_primitive) {
Fail(VERIFY_ERROR_GENERIC) << "reference array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " source for category 1 aput";
} else if (is_primitive && !insn_type.Equals(component_type) &&
!((insn_type.IsInteger() && component_type.IsFloat()) ||
(insn_type.IsLong() && component_type.IsDouble()))) {
Fail(VERIFY_ERROR_GENERIC) << "array type "
- << PrettyDescriptor(array_class->GetDescriptor())
+ << PrettyDescriptor(array_class)
<< " incompatible with aput of type " << insn_type;
} else {
// The instruction agrees with the type of array, confirm the value to be stored does too
@@ -3367,7 +3379,7 @@
const char* descriptor;
const ClassLoader* loader;
if (field != NULL) {
- descriptor = field->GetTypeDescriptor();
+ descriptor = FieldHelper(field).GetTypeDescriptor();
loader = field->GetDeclaringClass()->GetClassLoader();
} else {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
@@ -3419,7 +3431,7 @@
const char* descriptor;
const ClassLoader* loader;
if (field != NULL) {
- descriptor = field->GetTypeDescriptor();
+ descriptor = FieldHelper(field).GetTypeDescriptor();
loader = field->GetDeclaringClass()->GetClassLoader();
} else {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 182c81a..201cd2b 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -1145,10 +1145,7 @@
* DalvikJniReturnType, because if it's a reference type we need to do the class lookup.
* Returned references are assumed to be initialized. Returns kRegTypeUnknown for "void".
*/
- const RegType& GetMethodReturnType() {
- return reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(),
- method_->GetReturnTypeDescriptor());
- }
+ const RegType& GetMethodReturnType();
/*
* Verify that the target instruction is not "move-exception". It's important that the only way
diff --git a/src/heap.cc b/src/heap.cc
index ac0c366..6b2ea71 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -10,6 +10,7 @@
#include "image.h"
#include "mark_sweep.h"
#include "object.h"
+#include "object_utils.h"
#include "space.h"
#include "stl_util.h"
#include "thread_list.h"
@@ -169,9 +170,9 @@
Object* Heap::AllocObject(Class* klass, size_t byte_count) {
{
ScopedHeapLock lock;
- DCHECK(klass == NULL || klass->GetDescriptor() == NULL ||
- (klass->IsClassClass() && byte_count >= sizeof(Class)) ||
- (klass->IsVariableSize() || klass->GetObjectSize() == byte_count));
+ DCHECK(klass == NULL || (klass->IsClassClass() && byte_count >= sizeof(Class)) ||
+ (klass->IsVariableSize() || klass->GetObjectSize() == byte_count) ||
+ ClassHelper(klass).GetDescriptor().empty());
DCHECK_GE(byte_count, sizeof(Object));
Object* obj = AllocateLocked(byte_count);
if (obj != NULL) {
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index 3c5227f..d2134e0 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -23,13 +23,16 @@
*/
#include "hprof.h"
-#include "heap.h"
+
+#include "class_linker.h"
#include "debugger.h"
+#include "heap.h"
+#include "logging.h"
#include "object.h"
+#include "object_utils.h"
#include "stringprintf.h"
#include "unordered_map.h"
#include "unordered_set.h"
-#include "logging.h"
#include <cutils/open_memstream.h>
#include <sys/uio.h>
@@ -364,6 +367,8 @@
rec->AddU2(0); // empty const pool
+ FieldHelper fh;
+
// Static fields
if (sFieldCount == 0) {
rec->AddU2((uint16_t)0);
@@ -375,10 +380,11 @@
for (size_t i = 0; i < sFieldCount; ++i) {
Field* f = thisClass->GetStaticField(i);
+ fh.ChangeField(f);
size_t size;
- HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
- rec->AddId(LookupStringId(f->GetName()));
+ HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
+ rec->AddId(LookupStringId(fh.GetName()));
rec->AddU1(t);
if (size == 1) {
rec->AddU1(static_cast<uint8_t>(f->Get32(NULL)));
@@ -399,8 +405,9 @@
rec->AddU2((uint16_t)iFieldCount);
for (int i = 0; i < iFieldCount; ++i) {
Field* f = thisClass->GetInstanceField(i);
- HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), NULL);
- rec->AddId(LookupStringId(f->GetName()));
+ fh.ChangeField(f);
+ HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL);
+ rec->AddId(LookupStringId(fh.GetName()));
rec->AddU1(t);
}
} else if (clazz->IsArrayClass()) {
@@ -463,12 +470,14 @@
// Write the instance data; fields for this class, followed by super class fields,
// and so on. Don't write the klass or monitor fields of Object.class.
const Class* sclass = clazz;
+ FieldHelper fh;
while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
for (int i = 0; i < ifieldCount; i++) {
Field* f = sclass->GetInstanceField(i);
+ fh.ChangeField(f);
size_t size;
- SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
+ SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
if (size == 1) {
rec->AddU1(f->Get32(obj));
} else if (size == 2) {
@@ -680,7 +689,7 @@
}
HprofStringId Hprof::LookupClassNameId(Class* clazz) {
- return LookupStringId(PrettyDescriptor(clazz->GetDescriptor()));
+ return LookupStringId(PrettyDescriptor(clazz));
}
HprofClassObjectId Hprof::LookupClassId(Class* clazz) {
diff --git a/src/image_writer.cc b/src/image_writer.cc
index adc7b78..34ad955 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -18,6 +18,7 @@
#include "intern_table.h"
#include "logging.h"
#include "object.h"
+#include "object_utils.h"
#include "runtime.h"
#include "space.h"
#include "utils.h"
@@ -101,7 +102,7 @@
if (klass->IsPrimitive()) {
return true;
}
- const std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
+ const std::string descriptor(ClassHelper(klass).GetDescriptor());
return image_classes_->find(descriptor) != image_classes_->end();
}
@@ -160,7 +161,7 @@
bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
if (!context->image_writer->IsImageClass(klass)) {
- context->non_image_classes->insert(klass->GetDescriptor()->ToModifiedUtf8());
+ context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
}
return true;
}
@@ -178,7 +179,7 @@
return;
}
Class* klass = obj->AsClass();
- CHECK(image_writer->IsImageClass(klass)) << klass->GetDescriptor()->ToModifiedUtf8();
+ CHECK(image_writer->IsImageClass(klass)) << PrettyDescriptor(klass);
}
void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) {
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index b85969e..92fb6fa 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -18,6 +18,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "object.h"
+#include "object_utils.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
@@ -63,6 +64,19 @@
return AddLocalReference<jclass>(env, c);
}
+jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) {
+ Class* c = Decode<Class*>(env, javaClass);
+ if (c->IsPrimitive() || c->IsArrayClass() || c->IsProxyClass()) {
+ return 0; // primitive, array and proxy classes don't have class definitions
+ }
+ const DexFile::ClassDef* class_def = ClassHelper(c).GetClassDef();
+ if (class_def == NULL) {
+ return 0; // not found
+ } else {
+ return class_def->annotations_off_;
+ }
+}
+
template<typename T>
jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
jclass array_class = env->FindClass(array_class_name);
@@ -81,14 +95,10 @@
if (m->IsStatic()) {
return false;
}
- if (m->GetName()->CharAt(0) != '<') {
- return false;
- }
- m->InitJavaFields();
- return true;
+ return m->IsConstructor();
}
-jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Class* c = Decode<Class*>(env, javaClass);
std::vector<Method*> constructors;
@@ -106,11 +116,10 @@
if (public_only && !f->IsPublic()) {
return false;
}
- f->InitJavaFields();
return true;
}
-jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Class* c = Decode<Class*>(env, javaClass);
std::vector<Field*> fields;
@@ -140,14 +149,13 @@
if (public_only && !m->IsPublic()) {
return false;
}
- if (m->GetName()->CharAt(0) == '<') {
+ if (m->IsConstructor()) {
return false;
}
- m->InitJavaFields();
return true;
}
-jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Class* c = Decode<Class*>(env, javaClass);
std::vector<Method*> methods;
@@ -188,44 +196,52 @@
return Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache).GetDexObject(env);
}
-jint Class_getNonInnerClassModifiers(JNIEnv* env, jclass, jclass javaClass) {
+jint Class_getNonInnerClassModifiers(JNIEnv* env, jclass javaClass) {
Class* c = Decode<Class*>(env, javaClass);
return c->GetAccessFlags() & kAccJavaFlagsMask;
}
-jobject Class_getClassLoader(JNIEnv* env, jclass, jobject javaClass) {
+jobject Class_getClassLoaderNative(JNIEnv* env, jclass javaClass) {
Class* c = Decode<Class*>(env, javaClass);
Object* result = c->GetClassLoader();
return AddLocalReference<jobject>(env, result);
}
-jclass Class_getComponentType(JNIEnv* env, jobject javaThis) {
- return AddLocalReference<jclass>(env, Decode<Class*>(env, javaThis)->GetComponentType());
+jclass Class_getComponentType(JNIEnv* env, jclass javaClass) {
+ return AddLocalReference<jclass>(env, Decode<Class*>(env, javaClass)->GetComponentType());
}
-bool MethodMatches(Method* m, String* name, const std::string& signature) {
- if (!m->GetName()->Equals(name)) {
+bool MethodMatches(MethodHelper* mh, const std::string& name, ObjectArray<Class>* arg_array) {
+ if (name != mh->GetName()) {
return false;
}
- std::string method_signature = m->GetSignature()->ToModifiedUtf8();
- if (!StringPiece(method_signature).starts_with(signature)) {
+ const DexFile::TypeList* m_type_list = mh->GetParameterTypeList();
+ uint32_t m_type_list_size = m_type_list == NULL ? 0 : m_type_list->Size();
+ uint32_t sig_length = arg_array->GetLength();
+
+ if (m_type_list_size != sig_length) {
return false;
}
- if (m->IsMiranda()) {
- return false;
+
+ for (uint32_t i = 0; i < sig_length; i++) {
+ if (mh->GetClassFromTypeIdx(m_type_list->GetTypeItem(i).type_idx_) != arg_array->Get(i)) {
+ return false;
+ }
}
return true;
}
-Method* FindConstructorOrMethodInArray(ObjectArray<Method>* methods, String* name,
- const std::string& signature) {
+Method* FindConstructorOrMethodInArray(ObjectArray<Method>* methods, const std::string& name,
+ ObjectArray<Class>* arg_array) {
if (methods == NULL) {
return NULL;
}
Method* result = NULL;
+ MethodHelper mh;
for (int32_t i = 0; i < methods->GetLength(); ++i) {
Method* method = methods->Get(i);
- if (!MethodMatches(method, name, signature)) {
+ mh.ChangeMethod(method);
+ if (method->IsMiranda() || !MethodMatches(&mh, name, arg_array)) {
continue;
}
@@ -242,49 +258,42 @@
return result;
}
-jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass,
- jclass javaClass, jstring javaName, jobjectArray javaSignature) {
+jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName,
+ jobjectArray javaArgs) {
Class* c = Decode<Class*>(env, javaClass);
- String* name = Decode<String*>(env, javaName);
- ObjectArray<Class>* signature_array = Decode<ObjectArray<Class>*>(env, javaSignature);
+ std::string name = Decode<String*>(env, javaName)->ToModifiedUtf8();
+ ObjectArray<Class>* arg_array = Decode<ObjectArray<Class>*>(env, javaArgs);
- std::string signature;
- signature += "(";
- for (int i = 0; i < signature_array->GetLength(); i++) {
- signature += signature_array->Get(i)->GetDescriptor()->ToModifiedUtf8();
- }
- signature += ")";
-
- Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, signature);
+ Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
if (m == NULL) {
- m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, signature);
+ m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, arg_array);
}
if (m != NULL) {
- m->InitJavaFields();
return AddLocalReference<jobject>(env, m);
} else {
return NULL;
}
}
-jobject Class_getDeclaredField(JNIEnv* env, jclass, jclass jklass, jobject jname) {
+jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass jklass, jobject jname) {
Class* klass = Decode<Class*>(env, jklass);
DCHECK(klass->IsClass());
String* name = Decode<String*>(env, jname);
DCHECK(name->GetClass()->IsStringClass());
+ FieldHelper fh;
for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
Field* f = klass->GetInstanceField(i);
- if (f->GetName()->Equals(name)) {
- f->InitJavaFields();
+ fh.ChangeField(f);
+ if (name->Equals(fh.GetName())) {
return AddLocalReference<jclass>(env, f);
}
}
for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
Field* f = klass->GetStaticField(i);
- if (f->GetName()->Equals(name)) {
- f->InitJavaFields();
+ fh.ChangeField(f);
+ if (name->Equals(fh.GetName())) {
return AddLocalReference<jclass>(env, f);
}
}
@@ -302,7 +311,7 @@
*/
jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
Class* c = Decode<Class*>(env, javaThis);
- std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
+ std::string descriptor(ClassHelper(c).GetDescriptor());
if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
// The descriptor indicates that this is the class for
// a primitive type; special-case the return value.
@@ -370,7 +379,7 @@
}
// Validate method/field access.
-bool CheckMemberAccess(const Class* access_from, const Class* access_to, uint32_t member_flags) {
+bool CheckMemberAccess(const Class* access_from, Class* access_to, uint32_t member_flags) {
// quick accept for public access */
if (member_flags & kAccPublic) {
return true;
@@ -403,7 +412,7 @@
Class* c = Decode<Class*>(env, javaThis);
if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
- "Class %s can not be instantiated", PrettyDescriptor(c->GetDescriptor()).c_str());
+ "Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
return NULL;
}
@@ -414,7 +423,7 @@
Method* init = c->FindDirectMethod("<init>", "()V");
if (init == NULL) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
- "Class %s has no default <init>()V constructor", PrettyDescriptor(c->GetDescriptor()).c_str());
+ "Class %s has no default <init>()V constructor", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
return NULL;
}
@@ -433,18 +442,19 @@
Method* caller_caller = frame.GetMethod();
Class* caller_class = caller_caller->GetDeclaringClass();
+ ClassHelper caller_ch(caller_class);
if (!caller_class->CanAccess(c)) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
"Class %s is not accessible from class %s",
- PrettyDescriptor(c->GetDescriptor()).c_str(),
- PrettyDescriptor(caller_class->GetDescriptor()).c_str());
+ PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str(),
+ PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
return NULL;
}
if (!CheckMemberAccess(caller_class, init->GetDeclaringClass(), init->GetAccessFlags())) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
"%s is not accessible from class %s",
PrettyMethod(init).c_str(),
- PrettyDescriptor(caller_class->GetDescriptor()).c_str());
+ PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
return NULL;
}
@@ -463,15 +473,16 @@
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
- NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
+ NATIVE_METHOD(Class, getAnnotationDirectoryOffset, "()I"),
+ NATIVE_METHOD(Class, getClassLoaderNative, "()Ljava/lang/ClassLoader;"),
NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
- NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
- NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
- NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
- NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
- NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
+ NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
+ NATIVE_METHOD(Class, getDeclaredConstructors, "(Z)[Ljava/lang/reflect/Constructor;"),
+ NATIVE_METHOD(Class, getDeclaredFieldNative, "(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "(Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredMethods, "(Z)[Ljava/lang/reflect/Method;"),
NATIVE_METHOD(Class, getDex, "()Lcom/android/dex/Dex;"),
- NATIVE_METHOD(Class, getNonInnerClassModifiers, "(Ljava/lang/Class;)I"),
+ NATIVE_METHOD(Class, getNonInnerClassModifiers, "()I"),
NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
diff --git a/src/java_lang_reflect_Array.cc b/src/java_lang_reflect_Array.cc
index 08960b1..50bfb83 100644
--- a/src/java_lang_reflect_Array.cc
+++ b/src/java_lang_reflect_Array.cc
@@ -17,6 +17,7 @@
#include "jni_internal.h"
#include "class_linker.h"
#include "object.h"
+#include "object_utils.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -43,7 +44,7 @@
// old code assumed this but if you recurse from "[Foo" to "Foo" to "oo",
// you shouldn't assume there isn't a class "oo".
}
- std::string sub_array_descriptor(array_class->GetDescriptor()->ToModifiedUtf8(), 1);
+ std::string sub_array_descriptor(ClassHelper(array_class).GetDescriptor(), 1);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* sub_array_class = class_linker->FindClass(sub_array_descriptor,
array_class->GetClassLoader());
@@ -77,9 +78,9 @@
Class* element_class = Decode<Class*>(env, javaElementClass);
DCHECK(element_class->IsClass());
DCHECK(javaDimArray != NULL);
- Object* dimensions_obj = Decode<Class*>(env, javaDimArray);
+ Object* dimensions_obj = Decode<Object*>(env, javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
- DCHECK(dimensions_obj->GetClass()->GetDescriptor()->Equals("[I"));
+ DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor().c_str(), "[I");
IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj);
// Verify dimensions.
@@ -101,7 +102,7 @@
// Generate the full name of the array class.
std::string descriptor(num_dimensions, '[');
- descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+ descriptor += ClassHelper(element_class).GetDescriptor();
// Find/generate the array class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -130,7 +131,7 @@
}
std::string descriptor;
descriptor += '[';
- descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+ descriptor += ClassHelper(element_class).GetDescriptor();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* array_class = class_linker->FindClass(descriptor, element_class->GetClassLoader());
diff --git a/src/java_lang_reflect_Constructor.cc b/src/java_lang_reflect_Constructor.cc
index f730543..36481f7 100644
--- a/src/java_lang_reflect_Constructor.cc
+++ b/src/java_lang_reflect_Constructor.cc
@@ -17,6 +17,7 @@
#include "jni_internal.h"
#include "class_linker.h"
#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -32,12 +33,13 @@
* check. We can also safely assume the constructor isn't associated
* with an interface, array, or primitive class.
*/
-jobject Constructor_constructNative(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, jclass javaDeclaringClass, jobjectArray javaParams, jint, jboolean) {
+jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
- Class* c = Decode<Class*>(env, javaDeclaringClass);
+ Method* m = Decode<Object*>(env, javaMethod)->AsMethod();
+ Class* c = m->GetDeclaringClass();
if (c->IsAbstract()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
- "Can't instantiate abstract class %s", PrettyDescriptor(c->GetDescriptor()).c_str());
+ "Can't instantiate abstract class %s", PrettyDescriptor(c).c_str());
return NULL;
}
@@ -52,14 +54,14 @@
}
jobject javaReceiver = AddLocalReference<jobject>(env, receiver);
- InvokeMethod(env, javaMethod, javaReceiver, javaArgs, javaParams);
+ InvokeMethod(env, javaMethod, javaReceiver, javaArgs);
// Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
return javaReceiver;
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Constructor, constructNative, "([Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+ NATIVE_METHOD(Constructor, newInstance, "([Ljava/lang/Object;)Ljava/lang/Object;"),
};
} // namespace
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index 7e66dd9..eb56edb 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -17,6 +17,7 @@
#include "jni_internal.h"
#include "class_linker.h"
#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -25,13 +26,9 @@
namespace {
-jint Field_getFieldModifiers(JNIEnv* env, jobject jfield, jclass javaDeclaringClass, jint slot) {
- return Decode<Object*>(env, jfield)->AsField()->GetAccessFlags() & kAccJavaFlagsMask;
-}
-
bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
- switch (f->GetPrimitiveType()) {
+ switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
case Primitive::kPrimBoolean:
value.z = f->GetBoolean(o);
return true;
@@ -72,24 +69,41 @@
return false;
}
-bool CheckReceiver(JNIEnv* env, jobject javaObj, jclass javaDeclaringClass, Field* f, Object*& o) {
+bool CheckReceiver(JNIEnv* env, jobject javaObj, Field* f, Object*& o) {
if (f->IsStatic()) {
o = NULL;
return true;
}
o = Decode<Object*>(env, javaObj);
- Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
+ Class* declaringClass = f->GetDeclaringClass();
if (!VerifyObjectInClass(env, o, declaringClass)) {
return false;
}
return true;
}
-JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jchar dst_descriptor) {
+jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
Field* f = DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, javaDeclaringClass, f, o)) {
+ if (!CheckReceiver(env, javaObj, f, o)) {
+ return NULL;
+ }
+
+ // Get the field's value, boxing if necessary.
+ JValue value;
+ if (!GetFieldValue(o, f, value, true)) {
+ return NULL;
+ }
+ BoxPrimitive(env, FieldHelper(f).GetTypeAsPrimitiveType(), value);
+
+ return AddLocalReference<jobject>(env, value.l);
+}
+
+JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char dst_descriptor) {
+ Field* f = DecodeField(env->FromReflectedField(javaField));
+ Object* o = NULL;
+ if (!CheckReceiver(env, javaObj, f, o)) {
return JValue();
}
@@ -102,47 +116,47 @@
// Widen it if necessary (and possible).
JValue wide_value;
Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
- if (!ConvertPrimitiveValue(f->GetPrimitiveType(), dst_type->GetPrimitiveType(),
+ if (!ConvertPrimitiveValue(FieldHelper(f).GetTypeAsPrimitiveType(), dst_type->GetPrimitiveType(),
field_value, wide_value)) {
return JValue();
}
return wide_value;
}
-jbyte Field_getBField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).b;
+jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'Z').z;
}
-jchar Field_getCField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).c;
+jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'B').b;
}
-jdouble Field_getDField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).d;
+jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'C').c;
}
-jfloat Field_getFField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).f;
+jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'D').d;
}
-jint Field_getIField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).i;
+jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'F').f;
}
-jlong Field_getJField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).j;
+jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'I').i;
}
-jshort Field_getSField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).s;
+jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'J').j;
}
-jboolean Field_getZField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar dst_descriptor) {
- return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, dst_descriptor).z;
+jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField(env, javaField, javaObj, 'S').s;
}
void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_references) {
- switch (f->GetPrimitiveType()) {
+ switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
case Primitive::kPrimBoolean:
f->SetBoolean(o, new_value.z);
break;
@@ -187,14 +201,36 @@
}
}
-void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jchar src_descriptor, const JValue& new_value) {
+void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
+ Field* f = DecodeField(env->FromReflectedField(javaField));
+
+ // Unbox the value, if necessary.
+ Object* boxed_value = Decode<Object*>(env, javaValue);
+ JValue unboxed_value;
+ if (!UnboxPrimitive(env, boxed_value, FieldHelper(f).GetType(), unboxed_value)) {
+ return;
+ }
+
+ // Check that the receiver is non-null and an instance of the field's declaring class.
+ Object* o = NULL;
+ if (!CheckReceiver(env, javaObj, f, o)) {
+ return;
+ }
+
+ SetFieldValue(o, f, unboxed_value, true);
+}
+
+void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
+ const JValue& new_value) {
ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Field* f = DecodeField(env->FromReflectedField(javaField));
Object* o = NULL;
- if (!CheckReceiver(env, javaObj, javaDeclaringClass, f, o)) {
+ if (!CheckReceiver(env, javaObj, f, o)) {
return;
}
- if (f->GetPrimitiveType() == Primitive::kPrimNot) {
+ FieldHelper fh(f);
+ if (!fh.IsPrimitiveType()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"Not a primitive field: %s", PrettyField(f).c_str());
return;
@@ -203,7 +239,7 @@
// Widen the value if necessary (and possible).
JValue wide_value;
Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
- if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), f->GetPrimitiveType(),
+ if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(),
new_value, wide_value)) {
return;
}
@@ -212,112 +248,73 @@
SetFieldValue(o, f, wide_value, false);
}
-void Field_setBField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jbyte value) {
- JValue v = { 0 };
- v.b = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setCField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jchar value) {
- JValue v = { 0 };
- v.c = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setDField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jdouble value) {
- JValue v = { 0 };
- v.d = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setFField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jfloat value) {
- JValue v = { 0 };
- v.f = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setIField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jint value) {
- JValue v = { 0 };
- v.i = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setJField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jlong value) {
- JValue v = { 0 };
- v.j = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setSField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jshort value) {
- JValue v = { 0 };
- v.s = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
-}
-
-void Field_setZField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar src_descriptor, jboolean value) {
+void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean value) {
JValue v = { 0 };
v.z = value;
- SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, src_descriptor, v);
+ SetPrimitiveField(env, javaField, javaObj, 'Z', v);
}
-void Field_setField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jobject javaValue) {
- ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
- Field* f = DecodeField(env->FromReflectedField(javaField));
-
- // Unbox the value, if necessary.
- Object* boxed_value = Decode<Object*>(env, javaValue);
- JValue unboxed_value;
- if (!UnboxPrimitive(env, boxed_value, f->GetType(), unboxed_value)) {
- return;
- }
-
- // Check that the receiver is non-null and an instance of the field's declaring class.
- Object* o = NULL;
- if (!CheckReceiver(env, javaObj, javaDeclaringClass, f, o)) {
- return;
- }
-
- SetFieldValue(o, f, unboxed_value, true);
+void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte value) {
+ JValue v = { 0 };
+ v.b = value;
+ SetPrimitiveField(env, javaField, javaObj, 'B', v);
}
-jobject Field_getField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean) {
- Field* f = DecodeField(env->FromReflectedField(javaField));
- Object* o = NULL;
- if (!CheckReceiver(env, javaObj, javaDeclaringClass, f, o)) {
- return NULL;
- }
+void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar value) {
+ JValue v = { 0 };
+ v.c = value;
+ SetPrimitiveField(env, javaField, javaObj, 'C', v);
+}
- // Get the field's value, boxing if necessary.
- JValue value;
- if (!GetFieldValue(o, f, value, true)) {
- return NULL;
- }
- BoxPrimitive(env, f->GetPrimitiveType(), value);
+void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble value) {
+ JValue v = { 0 };
+ v.d = value;
+ SetPrimitiveField(env, javaField, javaObj, 'D', v);
+}
- return AddLocalReference<jobject>(env, value.l);
+void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat value) {
+ JValue v = { 0 };
+ v.f = value;
+ SetPrimitiveField(env, javaField, javaObj, 'F', v);
+}
+
+void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint value) {
+ JValue v = { 0 };
+ v.i = value;
+ SetPrimitiveField(env, javaField, javaObj, 'I', v);
+}
+
+void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong value) {
+ JValue v = { 0 };
+ v.j = value;
+ SetPrimitiveField(env, javaField, javaObj, 'J', v);
+}
+
+void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort value) {
+ JValue v = { 0 };
+ v.s = value;
+ SetPrimitiveField(env, javaField, javaObj, 'S', v);
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Field, getFieldModifiers, "(Ljava/lang/Class;I)I"),
-
- NATIVE_METHOD(Field, getBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B"),
- NATIVE_METHOD(Field, getCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C"),
- NATIVE_METHOD(Field, getDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D"),
- NATIVE_METHOD(Field, getFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F"),
- NATIVE_METHOD(Field, getField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
- NATIVE_METHOD(Field, getIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I"),
- NATIVE_METHOD(Field, getJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J"),
- NATIVE_METHOD(Field, getSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S"),
- NATIVE_METHOD(Field, getZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z"),
- NATIVE_METHOD(Field, setBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V"),
- NATIVE_METHOD(Field, setCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V"),
- NATIVE_METHOD(Field, setDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V"),
- NATIVE_METHOD(Field, setFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V"),
- NATIVE_METHOD(Field, setField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V"),
- NATIVE_METHOD(Field, setIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V"),
- NATIVE_METHOD(Field, setJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V"),
- NATIVE_METHOD(Field, setSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V"),
- NATIVE_METHOD(Field, setZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V"),
+ NATIVE_METHOD(Field, get, "(Ljava/lang/Object;)Ljava/lang/Object;"),
+ NATIVE_METHOD(Field, getBoolean, "(Ljava/lang/Object;)Z"),
+ NATIVE_METHOD(Field, getByte, "(Ljava/lang/Object;)B"),
+ NATIVE_METHOD(Field, getChar, "(Ljava/lang/Object;)C"),
+ NATIVE_METHOD(Field, getDouble, "(Ljava/lang/Object;)D"),
+ NATIVE_METHOD(Field, getFloat, "(Ljava/lang/Object;)F"),
+ NATIVE_METHOD(Field, getInt, "(Ljava/lang/Object;)I"),
+ NATIVE_METHOD(Field, getLong, "(Ljava/lang/Object;)J"),
+ NATIVE_METHOD(Field, getShort, "(Ljava/lang/Object;)S"),
+ NATIVE_METHOD(Field, set, "(Ljava/lang/Object;Ljava/lang/Object;)V"),
+ NATIVE_METHOD(Field, setBoolean, "(Ljava/lang/Object;Z)V"),
+ NATIVE_METHOD(Field, setByte, "(Ljava/lang/Object;B)V"),
+ NATIVE_METHOD(Field, setChar, "(Ljava/lang/Object;C)V"),
+ NATIVE_METHOD(Field, setDouble, "(Ljava/lang/Object;D)V"),
+ NATIVE_METHOD(Field, setFloat, "(Ljava/lang/Object;F)V"),
+ NATIVE_METHOD(Field, setInt, "(Ljava/lang/Object;I)V"),
+ NATIVE_METHOD(Field, setLong, "(Ljava/lang/Object;J)V"),
+ NATIVE_METHOD(Field, setShort, "(Ljava/lang/Object;S)V"),
};
} // namespace
diff --git a/src/java_lang_reflect_Method.cc b/src/java_lang_reflect_Method.cc
index e36078f..90d718d 100644
--- a/src/java_lang_reflect_Method.cc
+++ b/src/java_lang_reflect_Method.cc
@@ -17,6 +17,7 @@
#include "jni_internal.h"
#include "class_linker.h"
#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -25,33 +26,19 @@
namespace {
-jint Method_getMethodModifiers(JNIEnv* env, jclass, jclass javaDeclaringClass, jobject jmethod, jint slot) {
- Method* m = Decode<Object*>(env, jmethod)->AsMethod();
- jint access_flags = m->GetAccessFlags();
- // We move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
- // position, because the callers of this function are trying to convey
- // the "traditional" meaning of the flags to their callers.
- access_flags &= ~kAccSynchronized;
- if ((access_flags & kAccDeclaredSynchronized) != 0) {
- access_flags |= kAccSynchronized;
- }
-
- return access_flags & kAccJavaFlagsMask;
+jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs) {
+ return InvokeMethod(env, javaMethod, javaReceiver, javaArgs);
}
-jint Method_getProtoIndex(JNIEnv* env, jclass, jclass javaDeclaringClass, jobject jmethod, jint slot) {
- Method* m = Decode<Object*>(env, jmethod)->AsMethod();
- return m->GetProtoIdx();
-}
-
-jobject Method_invokeNative(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jclass, jobject javaParams, jclass, jint, jboolean) {
- return InvokeMethod(env, javaMethod, javaReceiver, javaArgs, javaParams);
+jobject Method_getReturnTypeNative(JNIEnv* env, jobject javaMethod) {
+ Method* m = Decode<Object*>(env, javaMethod)->AsMethod();
+ MethodHelper mh(m);
+ return AddLocalReference<jobject>(env, mh.GetReturnType());
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Method, getMethodModifiers, "(Ljava/lang/Class;Ljava/lang/reflect/AccessibleObject;I)I"),
- NATIVE_METHOD(Method, getProtoIndex, "(Ljava/lang/Class;Ljava/lang/reflect/AccessibleObject;I)I"),
- NATIVE_METHOD(Method, invokeNative, "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+ NATIVE_METHOD(Method, invoke, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
+ NATIVE_METHOD(Method, getReturnTypeNative, "()Ljava/lang/Class;")
};
} // namespace
diff --git a/src/java_lang_reflect_Proxy.cc b/src/java_lang_reflect_Proxy.cc
index 55ecd08..28fe514 100644
--- a/src/java_lang_reflect_Proxy.cc
+++ b/src/java_lang_reflect_Proxy.cc
@@ -25,6 +25,8 @@
namespace {
static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring javaName, jobjectArray javaInterfaces, jobject javaLoader, jobjectArray javaMethods, jobjectArray javaThrows) {
+ // Allocates Class so transition thread state to runnable
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
String* name = Decode<String*>(env, javaName);
ObjectArray<Class>* interfaces = Decode<ObjectArray<Class>*>(env, javaInterfaces);
ClassLoader* loader = Decode<ClassLoader*>(env, javaLoader);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 82c120c..718659f 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -18,6 +18,7 @@
#include "jni.h"
#include "logging.h"
#include "object.h"
+#include "object_utils.h"
#include "runtime.h"
#include "scoped_jni_thread_state.h"
#include "stl_util.h"
@@ -119,24 +120,6 @@
return num_bytes;
}
-static size_t NumArgArrayBytes(const String* shorty) {
- size_t num_bytes = 0;
- size_t end = shorty->GetLength();
- for (size_t i = 1; i < end; ++i) {
- char ch = shorty->CharAt(i);
- if (ch == 'D' || ch == 'J') {
- num_bytes += 8;
- } else if (ch == 'L') {
- // Argument is a reference or an array. The shorty descriptor
- // does not distinguish between these types.
- num_bytes += sizeof(Object*);
- } else {
- num_bytes += 4;
- }
- }
- return num_bytes;
-}
-
// For external use.
template<typename T>
T Decode(JNIEnv* public_env, jobject obj) {
@@ -177,11 +160,12 @@
static byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
- const String* shorty = method->GetShorty();
+ const char* shorty = MethodHelper(method).GetShorty();
+ size_t shorty_len = strlen(shorty);
size_t num_bytes = NumArgArrayBytes(shorty);
UniquePtr<byte[]> arg_array(new byte[num_bytes]);
- for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
- switch (shorty->CharAt(i)) {
+ for (size_t i = 1, offset = 0; i < shorty_len; ++i) {
+ switch (shorty[i]) {
case 'Z':
case 'B':
case 'C':
@@ -215,11 +199,12 @@
static byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
- size_t num_bytes = NumArgArrayBytes(method->GetShorty());
+ const char* shorty = MethodHelper(method).GetShorty();
+ size_t shorty_len = strlen(shorty);
+ size_t num_bytes = NumArgArrayBytes(shorty);
UniquePtr<byte[]> arg_array(new byte[num_bytes]);
- const String* shorty = method->GetShorty();
- for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
- switch (shorty->CharAt(i)) {
+ for (size_t i = 1, offset = 0; i < shorty_len; ++i) {
+ switch (shorty[i]) {
case 'Z':
case 'B':
case 'C':
@@ -313,9 +298,8 @@
}
static void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
- std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
- "no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig);
+ "no %s method \"%s.%s%s\"", kind, ClassHelper(c).GetDescriptor().c_str(), name, sig);
}
static jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
@@ -341,8 +325,6 @@
return NULL;
}
- method->InitJavaFields();
-
return EncodeMethod(method);
}
@@ -374,26 +356,22 @@
// Failed to find type from the signature of the field.
DCHECK(ts.Self()->IsExceptionPending());
ts.Self()->ClearException();
- std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" could be found in class "
- "\"%s\" or its superclasses", sig, name, class_descriptor.c_str());
+ "\"%s\" or its superclasses", sig, name, ClassHelper(c).GetDescriptor().c_str());
return NULL;
}
- std::string field_type_descriptor = field_type->GetDescriptor()->ToModifiedUtf8();
if (is_static) {
- field = c->FindStaticField(name, field_type_descriptor);
+ field = c->FindStaticField(name, ClassHelper(field_type).GetDescriptor());
} else {
- field = c->FindInstanceField(name, field_type_descriptor);
+ field = c->FindInstanceField(name, ClassHelper(field_type).GetDescriptor());
}
if (field == NULL) {
- std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig,
- name, class_descriptor.c_str());
+ name, ClassHelper(c).GetDescriptor().c_str());
return NULL;
}
- field->InitJavaFields();
return EncodeField(field);
}
@@ -1996,7 +1974,7 @@
Class* element_class = Decode<Class*>(ts, element_jclass);
std::string descriptor;
descriptor += "[";
- descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+ descriptor += ClassHelper(element_class).GetDescriptor();
// Find the class.
ScopedLocalRef<jclass> java_array_class(env, FindClass(env, descriptor.c_str()));
@@ -2209,9 +2187,11 @@
m = c->FindVirtualMethod(name, sig);
}
if (m == NULL) {
+ LOG(INFO) << "Failed to register native method " << name << sig;
ThrowNoSuchMethodError(ts, c, name, sig, "static or non-static");
return JNI_ERR;
} else if (!m->IsNative()) {
+ LOG(INFO) << "Failed to register non-native method " << name << sig << " as native";
ThrowNoSuchMethodError(ts, c, name, sig, "native");
return JNI_ERR;
}
diff --git a/src/monitor.cc b/src/monitor.cc
index 3f041e4..69eb9ba 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -27,6 +27,7 @@
#include "class_linker.h"
#include "mutex.h"
#include "object.h"
+#include "object_utils.h"
#include "stl_util.h"
#include "thread.h"
#include "thread_list.h"
@@ -824,15 +825,9 @@
line_number = 0;
return;
}
-
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* c = method->GetDeclaringClass();
- DexCache* dex_cache = c->GetDexCache();
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const DexFile::ClassDef* class_def = dex_file.FindClassDef(c->GetDescriptor()->ToModifiedUtf8());
-
- source_file = dex_file.GetSourceFile(*class_def);
- line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(pc));
+ MethodHelper mh(method);
+ source_file = mh.GetDeclaringClassSourceFile();
+ line_number = mh.GetLineNumFromNativePC(pc);
}
MonitorList::MonitorList() : lock_("MonitorList lock") {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index ac9449f..5cff2ea 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -12,6 +12,7 @@
#include "file.h"
#include "image.h"
#include "os.h"
+#include "object_utils.h"
#include "runtime.h"
#include "space.h"
#include "stringpiece.h"
@@ -299,7 +300,8 @@
StringAppendF(&summary, "%p: ", obj);
if (obj->IsClass()) {
Class* klass = obj->AsClass();
- StringAppendF(&summary, "CLASS %s", klass->GetDescriptor()->ToModifiedUtf8().c_str());
+ summary += "CLASS ";
+ summary += ClassHelper(klass).GetDescriptor();
std::ostringstream ss;
ss << " (" << klass->GetStatus() << ")";
summary += ss.str();
@@ -317,7 +319,7 @@
StringAppendF(&summary, "OBJECT");
}
StringAppendF(&summary, "\n");
- std::string descriptor = obj->GetClass()->GetDescriptor()->ToModifiedUtf8();
+ std::string descriptor(ClassHelper(obj->GetClass()).GetDescriptor());
StringAppendF(&summary, "\tclass %p: %s\n", obj->GetClass(), descriptor.c_str());
state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
state->stats_.descriptor_to_count[descriptor] += 1;
@@ -359,10 +361,7 @@
state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
}
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- class DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
+ const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
state->stats_.dex_instruction_bytes += dex_instruction_bytes;
}
diff --git a/src/object.cc b/src/object.cc
index b8d82dc..14e8c5c 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -18,6 +18,7 @@
#include "intern_table.h"
#include "logging.h"
#include "monitor.h"
+#include "object_utils.h"
#include "runtime.h"
#include "stack.h"
#include "utils.h"
@@ -93,73 +94,18 @@
java_lang_reflect_Field_ = NULL;
}
-void Field::SetTypeIdx(uint32_t type_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), type_idx, false);
-}
-
-Class* Field::GetTypeDuringLinking() const {
- // We are assured that the necessary primitive types are in the dex cache
- // early during class linking
- return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
-}
-
-bool Field::IsPrimitiveType() const {
- Class* type = GetTypeDuringLinking();
- return (type == NULL || type->IsPrimitive());
-}
-
-Primitive::Type Field::GetPrimitiveType() const {
- Class* type = GetTypeDuringLinking();
- if (type == NULL) {
- return Primitive::kPrimNot;
- }
- return type->GetPrimitiveType();
-}
-
-size_t Field::PrimitiveSize() const {
- return Primitive::FieldSize(GetPrimitiveType());
-}
-
-const char* Field::GetTypeDescriptor() const {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
- const char* descriptor = dex_file.StringByTypeIdx(GetTypeIdx());
- DCHECK(descriptor != NULL);
- return descriptor;
-}
-
-Class* Field::GetType() {
- Class* type = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, type_), false);
- if (type == NULL) {
- type = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, type_), type, false);
- }
- return type;
-}
-
void Field::SetOffset(MemberOffset num_bytes) {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- Primitive::Type type = GetPrimitiveType();
+#if 0 // TODO enable later in boot and under !NDEBUG
+ FieldHelper fh(this);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
}
+#endif
SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
}
-void Field::InitJavaFields() {
- Thread* self = Thread::Current();
- ScopedThreadStateChange tsc(self, Thread::kRunnable);
- MonitorEnter(self);
- if (type_ == NULL) {
- InitJavaFieldsLocked();
- }
- MonitorExit(self);
-}
-
-void Field::InitJavaFieldsLocked() {
- GetType(); // Resolves type as a side-effect. May throw.
-}
-
uint32_t Field::Get32(const Object* object) const {
CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
@@ -209,107 +155,121 @@
}
bool Field::GetBoolean(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimBoolean) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get32(object);
}
void Field::SetBoolean(Object* object, bool z) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimBoolean) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set32(object, z);
}
int8_t Field::GetByte(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimByte) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get32(object);
}
void Field::SetByte(Object* object, int8_t b) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimByte) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set32(object, b);
}
uint16_t Field::GetChar(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimChar) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get32(object);
}
void Field::SetChar(Object* object, uint16_t c) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimChar) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set32(object, c);
}
int16_t Field::GetShort(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimShort) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get32(object);
}
void Field::SetShort(Object* object, int16_t s) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimShort) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set32(object, s);
}
int32_t Field::GetInt(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimInt) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimInt, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get32(object);
}
void Field::SetInt(Object* object, int32_t i) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimInt) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimInt, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set32(object, i);
}
int64_t Field::GetLong(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimLong) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimLong, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return Get64(object);
}
void Field::SetLong(Object* object, int64_t j) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimLong) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimLong, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
Set64(object, j);
}
float Field::GetFloat(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimFloat) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
JValue float_bits;
float_bits.i = Get32(object);
return float_bits.f;
}
void Field::SetFloat(Object* object, float f) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimFloat) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
JValue float_bits;
float_bits.f = f;
Set32(object, float_bits.i);
}
double Field::GetDouble(const Object* object) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimDouble) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
JValue double_bits;
double_bits.j = Get64(object);
return double_bits.d;
}
void Field::SetDouble(Object* object, double d) const {
- DCHECK_EQ(GetPrimitiveType(), Primitive::kPrimDouble) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
JValue double_bits;
double_bits.d = d;
Set64(object, double_bits.j);
}
Object* Field::GetObject(const Object* object) const {
- CHECK_EQ(GetPrimitiveType(), Primitive::kPrimNot) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
return GetObj(object);
}
void Field::SetObject(Object* object, const Object* l) const {
- CHECK_EQ(GetPrimitiveType(), Primitive::kPrimNot) << PrettyField(this);
+ DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
+ << PrettyField(this);
SetObj(object, l);
}
-bool Method::IsClassInitializer() const {
- return IsStatic() && GetName()->Equals("<clinit>");
-}
-
// TODO: get global references for these
Class* Method::java_lang_reflect_Constructor_ = NULL;
Class* Method::java_lang_reflect_Method_ = NULL;
@@ -361,118 +321,11 @@
}
}
-void Method::InitJavaFieldsLocked() {
- // Create the array.
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- size_t arg_count = GetShorty()->GetLength() - 1;
- Class* array_class = class_linker->FindSystemClass("[Ljava/lang/Class;");
- ObjectArray<Class>* parameters = ObjectArray<Class>::Alloc(array_class, arg_count);
- if (parameters == NULL) {
- return;
- }
-
- // Parse the signature, filling the array.
- const ClassLoader* cl = GetDeclaringClass()->GetClassLoader();
- std::string signature(GetSignature()->ToModifiedUtf8());
- const char* p = signature.c_str();
- DCHECK_EQ(*p, '(');
- ++p;
- for (size_t i = 0; i < arg_count; ++i) {
- Class* c = ExtractNextClassFromSignature(class_linker, cl, p);
- if (c == NULL) {
- return;
- }
- parameters->Set(i, c);
- }
-
- DCHECK_EQ(*p, ')');
- ++p;
-
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, java_parameter_types_),
- parameters, false);
- Class* java_return_type = ExtractNextClassFromSignature(class_linker, cl, p);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_),
- java_return_type, false);
-}
-
-void Method::InitJavaFields() {
- Thread* self = Thread::Current();
- ScopedThreadStateChange tsc(self, Thread::kRunnable);
- MonitorEnter(self);
- if (java_parameter_types_ == NULL || java_return_type_ == NULL) {
- InitJavaFieldsLocked();
- }
- MonitorExit(self);
-}
-
ObjectArray<String>* Method::GetDexCacheStrings() const {
return GetFieldObject<ObjectArray<String>*>(
OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
}
-void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
- new_return_type_idx, false);
-}
-
-uint32_t Method::GetDexMethodIndex() const {
- // TODO: add the method index to Method - which will also mean a number of Method fields can
- // become dex file lookups (which will then mean we may want faster access to the dex file)
- // Find the dex file
- const DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
- const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
- // Find the class_def in the dex file
- uint32_t class_def_idx;
- bool found_class_def =
- dex_file.FindClassDefIndex(GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8(),
- class_def_idx);
- CHECK(found_class_def);
- const DexFile::TypeId& type_id =
- dex_file.GetTypeId(dex_file.GetClassDef(class_def_idx).class_idx_);
- const DexFile::StringId* name_str_id = dex_file.FindStringId(GetName()->ToModifiedUtf8());
- CHECK(name_str_id != NULL); // Failed to find method's name?
- uint16_t return_type_idx;
- std::vector<uint16_t> param_type_idxs;
- std::string signature = GetSignature()->ToModifiedUtf8();
- bool found_type_list = dex_file.CreateTypeList(&return_type_idx, ¶m_type_idxs, signature);
- CHECK(found_type_list); // Failed to parse signature
- const DexFile::ProtoId* sig_proto_id = dex_file.FindProtoId(return_type_idx, param_type_idxs);
- CHECK(sig_proto_id != NULL); // Failed to find method's prototype
- const DexFile::MethodId* method_id =
- dex_file.FindMethodId(type_id, *name_str_id, *sig_proto_id);
- CHECK(method_id != NULL); // Failed to find method?
- uint32_t method_idx = dex_file.GetIndexForMethodId(*method_id);
- DCHECK_EQ(PrettyMethod(method_idx, dex_file), PrettyMethod(this));
- return method_idx;
-}
-
-const char* Method::GetReturnTypeDescriptor() const {
- Class* declaring_class = GetDeclaringClass();
- DexCache* dex_cache = declaring_class->GetDexCache();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const char* descriptor = dex_file.StringByTypeIdx(GetReturnTypeIdx());
- DCHECK(descriptor != NULL);
- return descriptor;
-}
-
-Class* Method::GetReturnType() const {
- DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous())
- << PrettyMethod(this);
- Class* java_return_type = java_return_type_;
- if (java_return_type != NULL) {
- return java_return_type;
- }
- // Short-cut
- Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
- if (result == NULL) {
- // Do full linkage and set cache value for next call
- result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
- }
- CHECK(result != NULL) << PrettyMethod(this);
- return result;
-}
-
void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
new_dex_cache_strings, false);
@@ -545,85 +398,8 @@
return num_registers;
}
-size_t Method::NumArgs() const {
- // "1 +" because the first in Args is the receiver.
- // "- 1" because we don't count the return type.
- return (IsStatic() ? 0 : 1) + GetShorty()->GetLength() - 1;
-}
-
-// The number of reference arguments to this method including implicit this
-// pointer
-size_t Method::NumReferenceArgs() const {
- const String* shorty = GetShorty();
- size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
- for (int i = 1; i < shorty->GetLength(); i++) {
- char ch = shorty->CharAt(i);
- if ((ch == 'L') || (ch == '[')) {
- result++;
- }
- }
- return result;
-}
-
-// The number of long or double arguments
-size_t Method::NumLongOrDoubleArgs() const {
- const String* shorty = GetShorty();
- size_t result = 0;
- for (int i = 1; i < shorty->GetLength(); i++) {
- char ch = shorty->CharAt(i);
- if ((ch == 'D') || (ch == 'J')) {
- result++;
- }
- }
- return result;
-}
-
-// Is the given method parameter a reference?
-bool Method::IsParamAReference(unsigned int param) const {
- CHECK_LT(param, NumArgs());
- if (IsStatic()) {
- param++; // 0th argument must skip return value at start of the shorty
- } else if (param == 0) {
- return true; // this argument
- }
- return GetShorty()->CharAt(param) == 'L';
-}
-
-// Is the given method parameter a long or double?
-bool Method::IsParamALongOrDouble(unsigned int param) const {
- CHECK_LT(param, NumArgs());
- if (IsStatic()) {
- param++; // 0th argument must skip return value at start of the shorty
- } else if (param == 0) {
- return false; // this argument
- }
- char ch = GetShorty()->CharAt(param);
- return (ch == 'J' || ch == 'D');
-}
-
-static size_t ShortyCharToSize(char x) {
- switch (x) {
- case 'V': return 0;
- case '[': return kPointerSize;
- case 'L': return kPointerSize;
- case 'D': return 8;
- case 'J': return 8;
- default: return 4;
- }
-}
-
-size_t Method::ParamSize(unsigned int param) const {
- CHECK_LT(param, NumArgs());
- if (IsStatic()) {
- param++; // 0th argument must skip return value at start of the shorty
- } else if (param == 0) {
- return kPointerSize; // this argument
- }
- return ShortyCharToSize(GetShorty()->CharAt(param));
-}
-
-size_t Method::ReturnSize() const {
- return ShortyCharToSize(GetShorty()->CharAt(0));
+bool Method::IsProxyMethod() const {
+ return GetDeclaringClass()->IsProxyClass();
}
Method* Method::FindOverriddenMethod() const {
@@ -635,25 +411,39 @@
uint16_t method_index = GetMethodIndex();
ObjectArray<Method>* super_class_vtable = super_class->GetVTable();
Method* result = NULL;
+ // Did this method override a super class method? If so load the result from the super class'
+ // vtable
if (super_class_vtable != NULL && method_index < super_class_vtable->GetLength()) {
result = super_class_vtable->Get(method_index);
} else {
- ObjectArray<Class>* interfaces = declaring_class->GetInterfaces();
- String* name = GetName();
- String* signature = GetSignature();
- for (int32_t i = 0; i < interfaces->GetLength() && result == NULL; i++) {
- Class* interface = interfaces->Get(i);
- result = interface->FindInterfaceMethod(name, signature);
+ // Method didn't override superclass method so search interfaces
+ MethodHelper mh(this);
+ MethodHelper interface_mh;
+ ObjectArray<InterfaceEntry>* iftable = GetDeclaringClass()->GetIfTable();
+ for (int32_t i = 0; i < iftable->GetLength() && result == NULL; i++) {
+ InterfaceEntry* entry = iftable->Get(i);
+ Class* interface = entry->GetInterface();
+ for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
+ Method* interface_method = interface->GetVirtualMethod(j);
+ interface_mh.ChangeMethod(interface_method);
+ if (mh.HasSameNameAndSignature(&interface_mh)) {
+ result = interface_method;
+ break;
+ }
+ }
}
}
- DCHECK(result == NULL || HasSameNameAndSignature(result));
+#ifndef NDEBUG
+ MethodHelper result_mh(result);
+ DCHECK(result == NULL || MethodHelper(this).HasSameNameAndSignature(&result_mh));
+#endif
return result;
}
uint32_t Method::ToDexPC(const uintptr_t pc) const {
const uint32_t* mapping_table = GetMappingTable();
if (mapping_table == NULL) {
- DCHECK(IsNative() || IsCalleeSaveMethod()) << PrettyMethod(this);
+ DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
return DexFile::kDexNoIndex; // Special no mapping case
}
size_t mapping_table_length = GetMappingTableLength();
@@ -695,10 +485,8 @@
}
uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
- DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
+ MethodHelper mh(this);
+ const DexFile::CodeItem* code_item = mh.GetCodeItem();
// Iterate over the catch handlers associated with dex_pc
for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
uint16_t iter_type_idx = it.GetHandlerTypeIndex();
@@ -707,11 +495,11 @@
return it.GetHandlerAddress();
}
// Does this catch exception type apply?
- Class* iter_exception_type = dex_cache->GetResolvedType(iter_type_idx);
+ Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
if (iter_exception_type == NULL) {
// The verifier should take care of resolving all exception classes early
LOG(WARNING) << "Unresolved exception class when finding catch block: "
- << dex_file.GetTypeDescriptor(dex_file.GetTypeId(iter_type_idx));
+ << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
} else if (iter_exception_type->IsAssignableFrom(exception_type)) {
return it.GetHandlerAddress();
}
@@ -819,8 +607,9 @@
}
Class* super = GetSuperClass();
+ ClassHelper kh(this);
os << "----- " << (IsInterface() ? "interface" : "class") << " "
- << "'" << GetDescriptor()->ToModifiedUtf8() << "' cl=" << GetClassLoader() << " -----\n",
+ << "'" << kh.GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n",
os << " objectSize=" << SizeOf() << " "
<< "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n",
os << StringPrintf(" access=0x%04x.%04x\n",
@@ -831,10 +620,10 @@
if (IsArrayClass()) {
os << " componentType=" << PrettyClass(GetComponentType()) << "\n";
}
- if (NumInterfaces() > 0) {
- os << " interfaces (" << NumInterfaces() << "):\n";
- for (size_t i = 0; i < NumInterfaces(); ++i) {
- Class* interface = GetInterface(i);
+ if (kh.NumInterfaces() > 0) {
+ os << " interfaces (" << kh.NumInterfaces() << "):\n";
+ for (size_t i = 0; i < kh.NumInterfaces(); ++i) {
+ Class* interface = kh.GetInterface(i);
const ClassLoader* cl = interface->GetClassLoader();
os << StringPrintf(" %2d: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl);
}
@@ -963,11 +752,7 @@
return false;
}
-bool Class::IsInSamePackage(const String* descriptor_string_1,
- const String* descriptor_string_2) {
- const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
- const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
-
+bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) {
size_t i = 0;
while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
++i;
@@ -1009,7 +794,11 @@
klass2 = klass2->GetComponentType();
}
// Compare the package part of the descriptor string.
- return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
+ ClassHelper kh(klass1);
+ std::string descriptor1 = kh.GetDescriptor();
+ kh.ChangeClass(klass2);
+ std::string descriptor2 = kh.GetDescriptor();
+ return IsInSamePackage(descriptor1, descriptor2);
}
bool Class::IsClassClass() const {
@@ -1018,8 +807,7 @@
}
bool Class::IsStringClass() const {
- // TODO use "this == String::GetJavaLangString()" instead? or do we need this too early?
- return this == GetDescriptor()->GetClass();
+ return this == String::GetJavaLangString();
}
ClassLoader* Class::GetClassLoader() const {
@@ -1047,8 +835,7 @@
if (can_throw) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
"Class %s does not implement interface %s",
- PrettyDescriptor(GetDescriptor()).c_str(),
- PrettyDescriptor(declaring_class->GetDescriptor()).c_str());
+ PrettyDescriptor(this).c_str(), PrettyDescriptor(declaring_class).c_str());
}
return NULL;
}
@@ -1071,30 +858,13 @@
return NULL;
}
-Method* Class::FindInterfaceMethod(String* name, String* signature) const {
- // Check the current class before checking the interfaces.
- Method* method = FindVirtualMethod(name, signature);
- if (method != NULL) {
- return method;
- }
- int32_t iftable_count = GetIfTableCount();
- ObjectArray<InterfaceEntry>* iftable = GetIfTable();
- for (int32_t i = 0; i < iftable_count; i++) {
- Class* interface = iftable->Get(i)->GetInterface();
- method = interface->FindVirtualMethod(name, signature);
- if (method != NULL) {
- return method;
- }
- }
- return NULL;
-}
-
Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
const StringPiece& signature) {
+ MethodHelper mh;
for (size_t i = 0; i < NumDirectMethods(); ++i) {
Method* method = GetDirectMethod(i);
- if (method->GetName()->Equals(name) &&
- method->GetSignature()->Equals(signature)) {
+ mh.ChangeMethod(method);
+ if (name == mh.GetName() && signature == mh.GetSignature()) {
return method;
}
}
@@ -1114,19 +884,11 @@
Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
const StringPiece& signature) const {
+ MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Method* method = GetVirtualMethod(i);
- if (method->GetName()->Equals(name) && method->GetSignature()->Equals(signature)) {
- return method;
- }
- }
- return NULL;
-}
-
-Method* Class::FindDeclaredVirtualMethod(String* name, String* signature) const {
- for (size_t i = 0; i < NumVirtualMethods(); ++i) {
- Method* method = GetVirtualMethod(i);
- if (method->GetName() == name && method->GetSignature() == signature) {
+ mh.ChangeMethod(method);
+ if (name == mh.GetName() && signature == mh.GetSignature()) {
return method;
}
}
@@ -1143,35 +905,14 @@
return NULL;
}
-Method* Class::FindVirtualMethod(String* name, String* signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
- Method* method = klass->FindDeclaredVirtualMethod(name, signature);
- if (method != NULL) {
- return method;
- }
- }
- return NULL;
-}
-
Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) {
// Is the field in this class?
// Interfaces are not relevant because they can't contain instance fields.
+ FieldHelper fh;
for (size_t i = 0; i < NumInstanceFields(); ++i) {
Field* f = GetInstanceField(i);
- if (f->GetName()->Equals(name) &&
- StringPiece(f->GetTypeDescriptor()) == type) {
- return f;
- }
- }
- return NULL;
-}
-
-Field* Class::FindDeclaredInstanceField(String* name, String* type) {
- // Is the field in this class?
- // Interfaces are not relevant because they can't contain instance fields.
- for (size_t i = 0; i < NumInstanceFields(); ++i) {
- Field* f = GetInstanceField(i);
- if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+ fh.ChangeField(f);
+ if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
return f;
}
}
@@ -1190,34 +931,13 @@
return NULL;
}
-Field* Class::FindInstanceField(String* name, String* type) {
- // Is the field in this class, or any of its superclasses?
- // Interfaces are not relevant because they can't contain instance fields.
- for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
- Field* f = c->FindDeclaredInstanceField(name, type);
- if (f != NULL) {
- return f;
- }
- }
- return NULL;
-}
-
Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) {
DCHECK(type != NULL);
+ FieldHelper fh;
for (size_t i = 0; i < NumStaticFields(); ++i) {
Field* f = GetStaticField(i);
- if (f->GetName()->Equals(name) && StringPiece(f->GetTypeDescriptor()) == type) {
- return f;
- }
- }
- return NULL;
-}
-
-Field* Class::FindDeclaredStaticField(String* name, String* type) {
- DCHECK(type != NULL);
- for (size_t i = 0; i < NumStaticFields(); ++i) {
- Field* f = GetStaticField(i);
- if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+ fh.ChangeField(f);
+ if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
return f;
}
}
@@ -1247,29 +967,6 @@
return NULL;
}
-Field* Class::FindStaticField(String* name, String* type) {
- // Is the field in this class (or its interfaces), or any of its
- // superclasses (or their interfaces)?
- for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
- // Is the field in this class?
- Field* f = c->FindDeclaredStaticField(name, type);
- if (f != NULL) {
- return f;
- }
-
- // Is this field in any of this class' interfaces?
- for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
- InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
- Class* interface = interface_entry->GetInterface();
- f = interface->FindDeclaredStaticField(name, type);
- if (f != NULL) {
- return f;
- }
- }
- }
- return NULL;
-}
-
Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
DCHECK(array_class != NULL);
DCHECK_GE(component_count, 0);
@@ -1284,7 +981,7 @@
if (data_size >> component_shift != size_t(component_count) || size < data_size) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;",
"%s of length %zd exceeds the VM limit",
- PrettyDescriptor(array_class->GetDescriptor()).c_str(), component_count);
+ PrettyDescriptor(array_class).c_str(), component_count);
return NULL;
}
@@ -1553,9 +1250,9 @@
java_lang_StackTraceElement_ = NULL;
}
-StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
- const String* method_name,
- const String* file_name,
+StackTraceElement* StackTraceElement::Alloc(String* declaring_class,
+ String* method_name,
+ String* file_name,
int32_t line_number) {
StackTraceElement* trace =
down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
diff --git a/src/object.h b/src/object.h
index 82cd0a3..1a58364 100644
--- a/src/object.h
+++ b/src/object.h
@@ -97,6 +97,7 @@
static const uint32_t kAccConstructor = 0x00010000; // method (dex only)
static const uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex only)
+static const uint32_t kAccClassIsProxy = 0x00040000; // class (dex only)
static const uint32_t kAccWritable = 0x80000000; // method (dex only)
// Special runtime-only flags.
@@ -380,10 +381,6 @@
void SetDeclaringClass(Class *new_declaring_class);
- String* GetName() const;
-
- void SetName(String* new_name);
-
uint32_t GetAccessFlags() const;
void SetAccessFlags(uint32_t new_access_flags) {
@@ -402,25 +399,13 @@
return (GetAccessFlags() & kAccFinal) != 0;
}
- uint32_t GetTypeIdx() const;
+ uint32_t GetDexFieldIndex() const {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), false);
+ }
- void SetTypeIdx(uint32_t type_idx);
-
- // Gets type using type index and resolved types in the dex cache, may be null
- // if type isn't yet resolved
- Class* GetTypeDuringLinking() const;
-
- bool IsPrimitiveType() const;
-
- Primitive::Type GetPrimitiveType() const;
-
- size_t PrimitiveSize() const;
-
- const char* GetTypeDescriptor() const;
-
- // Performs full resolution, may return null and set exceptions if type cannot
- // be resolved
- Class* GetType();
+ void SetDexFieldIndex(uint32_t new_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), new_idx, false);
+ }
// Offset to field within an Object
MemberOffset GetOffset() const;
@@ -473,35 +458,19 @@
return (GetAccessFlags() & kAccVolatile) != 0;
}
- void InitJavaFields();
-
private:
- void InitJavaFieldsLocked();
-
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
-
- // The class in which this field is declared.
+ // The class we are a part of
Class* declaring_class_;
- Object* generic_type_;
-
- String* name_;
-
- // The possibly null type of the field
- Class* type_;
-
- uint32_t generic_types_are_initialized_;
-
uint32_t access_flags_;
+ // Dex cache index of field id
+ uint32_t field_dex_idx_;
+
// Offset of field within an instance or in the Class' static fields
uint32_t offset_;
- // Dex cache index of resolved type
- uint32_t type_idx_;
-
- int32_t slot_;
-
static Class* java_lang_reflect_Field_;
friend struct FieldOffsets; // for verifying offset information
@@ -526,23 +495,6 @@
return MemberOffset(OFFSETOF_MEMBER(Method, declaring_class_));
}
- // Returns the method name, e.g. "<init>" or "eatLunch"
- String* GetName() const;
-
- void SetName(String* new_name);
-
- String* GetShorty() const;
-
- void SetShorty(String* new_shorty);
-
- String* GetSignature() const;
-
- void SetSignature(String* new_signature);
-
- bool HasSameNameAndSignature(const Method* that) const {
- return GetName() == that->GetName() && GetSignature() == that->GetSignature();
- }
-
uint32_t GetAccessFlags() const;
void SetAccessFlags(uint32_t new_access_flags) {
@@ -569,9 +521,6 @@
return (GetAccessFlags() & kAccConstructor) != 0;
}
- // Is this method <clinit>
- bool IsClassInitializer() const;
-
// Returns true if the method is static, private, or a constructor.
bool IsDirect() const {
return IsStatic() || IsPrivate() || IsConstructor();
@@ -603,7 +552,7 @@
return (GetAccessFlags() & kAccSynthetic) != 0;
}
- uint32_t GetDexMethodIndex() const;
+ bool IsProxyMethod() const;
uint16_t GetMethodIndex() const;
@@ -630,28 +579,10 @@
// Number of 32bit registers that would be required to hold all the arguments
static size_t NumArgRegisters(const StringPiece& shorty);
- uint16_t NumRegisters() const;
+ uint32_t GetDexMethodIndex() const;
- void SetNumRegisters(uint16_t new_num_registers) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), new_num_registers, false);
- }
-
- uint16_t NumIns() const;
-
- void SetNumIns(uint16_t new_num_ins) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), new_num_ins, false);
- }
-
- uint16_t NumOuts() const;
-
- void SetNumOuts(uint16_t new_num_outs) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), new_num_outs, false);
- }
-
- uint32_t GetProtoIdx() const;
-
- void SetProtoIdx(uint32_t new_proto_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Method, proto_idx_), new_proto_idx, false);
+ void SetDexMethodIndex(uint32_t new_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_dex_index_), new_idx, false);
}
ObjectArray<String>* GetDexCacheStrings() const;
@@ -692,63 +623,6 @@
// Find the method that this method overrides
Method* FindOverriddenMethod() const;
- void SetReturnTypeIdx(uint32_t new_return_type_idx);
-
- const char* GetReturnTypeDescriptor() const;
-
- Class* GetReturnType() const;
-
- bool IsReturnAReference() const;
-
- bool IsReturnAFloat() const;
-
- bool IsReturnADouble() const;
-
- bool IsReturnAFloatOrDouble() const {
- return IsReturnAFloat() || IsReturnADouble();
- }
-
- bool IsReturnALong() const;
-
- bool IsReturnALongOrDouble() const {
- return IsReturnALong() || IsReturnADouble();
- }
-
- bool IsReturnVoid() const;
-
- // "Args" may refer to any of the 3 levels of "Args."
- // To avoid confusion, our code will denote which "Args" clearly:
- // 1. UserArgs: Args that a user see.
- // 2. Args: Logical JVM-level Args. E.g., the first in Args will be the
- // receiver.
- // 3. CConvArgs: Calling Convention Args, which is physical-level Args.
- // E.g., the first in Args is Method* for both static and non-static
- // methods. And CConvArgs doesn't deal with the receiver because
- // receiver is hardwired in an implicit register, so CConvArgs doesn't
- // need to deal with it.
- //
- // The number of Args that should be supplied to this method
- size_t NumArgs() const;
-
- // The number of reference arguments to this method including implicit this
- // pointer.
- size_t NumReferenceArgs() const;
-
- // The number of long or double arguments.
- size_t NumLongOrDoubleArgs() const;
-
- // Is the given method parameter a reference?
- bool IsParamAReference(unsigned int param) const;
-
- // Is the given method parameter a long or double?
- bool IsParamALongOrDouble(unsigned int param) const;
-
- // Size in bytes of the given parameter
- size_t ParamSize(unsigned int param) const;
-
- // Size in bytes of the return value
- size_t ReturnSize() const;
-
void Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const;
const void* GetCode() const {
@@ -924,18 +798,6 @@
SetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_), fp_spill_mask, false);
}
- ObjectArray<Class>* GetExceptionTypes() const {
- return GetFieldObject<ObjectArray<Class>*>(
- OFFSET_OF_OBJECT_MEMBER(Method, java_exception_types_), false);
- }
-
- void SetExceptionTypes(ObjectArray<Class>* exception_types);
-
- ObjectArray<Class>* GetJavaParameterTypes() const {
- return GetFieldObject<ObjectArray<Class>*>(
- OFFSET_OF_OBJECT_MEMBER(Method, java_parameter_types_), false);
- }
-
// Is this a hand crafted method used for something like describing callee saves?
bool IsCalleeSaveMethod() const {
Runtime* runtime = Runtime::Current();
@@ -974,26 +836,10 @@
static void ResetClasses();
- void InitJavaFields();
-
private:
- uint32_t GetReturnTypeIdx() const;
- void InitJavaFieldsLocked();
-
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // the class we are a part of
+ // The class we are a part of
Class* declaring_class_;
- ObjectArray<Class>* java_exception_types_; // TODO
- Object* java_formal_type_parameters_;
- Object* java_generic_exception_types_;
- Object* java_generic_parameter_types_;
- Object* java_generic_return_type_;
-
- String* name_;
-
- // Initialized by InitJavaFields.
- ObjectArray<Class>* java_parameter_types_;
- Class* java_return_type_;
// short cuts to declaring_class_->dex_cache_ member for fast compiled code access
CodeAndDirectMethods* dex_cache_code_and_direct_methods_;
@@ -1016,23 +862,6 @@
// Garbage collection map
Object* gc_map_;
- // The short-form method descriptor string.
- String* shorty_;
-
- // The method descriptor. This represents the parameters a method
- // takes and value it returns. This string is a list of the type
- // descriptors for the parameters enclosed in parenthesis followed
- // by the return type descriptor. For example, for the method
- //
- // Object mymethod(int i, double d, Thread t)
- //
- // the method descriptor would be
- //
- // (IDLjava/lang/Thread;)Ljava/lang/Object;
- String* signature_;
-
- uint32_t java_generic_types_are_initialized_;
-
// Access flags; low 16 bits are defined by spec.
uint32_t access_flags_;
@@ -1055,13 +884,12 @@
// Native invocation stub entry point for calling from native to managed code.
const InvokeStub* invoke_stub_;
- // Index of the return type in the declaring classes dex cache or dex file's type ids
- // TODO: value is really just 16bit
- uint32_t java_return_type_idx_;
-
// Mapping from native pc to dex pc
const uint32_t* mapping_table_;
+ // Index into method_ids of the dex file associated with this method
+ uint32_t method_dex_index_;
+
// For concrete virtual methods, this is the offset of the method in Class::vtable_.
//
// For abstract methods in an interface class, this is the offset of the method in
@@ -1071,24 +899,11 @@
// The target native method registered with this method
const void* native_method_;
- // Method bounds; not needed for an abstract method.
- //
- // For a native method, we compute the size of the argument list, and
- // set "insSize" and "registerSize" equal to it.
- uint32_t num_ins_;
- uint32_t num_outs_;
- uint32_t num_registers_; // ins + locals
-
- // Method prototype descriptor string (return and argument types).
- uint32_t proto_idx_;
-
// When a register is promoted into a register, the spill mask holds which registers hold dex
// registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
// is vmap_table_[N]. vmap_table_[0] holds the length of the table.
const uint16_t* vmap_table_;
- uint32_t java_slot_;
-
static Class* java_lang_reflect_Constructor_;
static Class* java_lang_reflect_Method_;
@@ -1351,6 +1166,17 @@
return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
}
+ String* GetName() const;
+ void SetName(String* name);
+
+ bool IsProxyClass() const {
+ // Read access flags without using getter as whether something is a proxy can be check in
+ // any loaded state
+ // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
+ uint32_t access_flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
+ return (access_flags & kAccClassIsProxy) != 0;
+ }
+
Primitive::Type GetPrimitiveType() const {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
return static_cast<Primitive::Type>(
@@ -1444,16 +1270,6 @@
// Creates a raw object instance but does not invoke the default constructor.
Object* AllocObject();
- const String* GetDescriptor() const {
- const String* result = GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(Class, descriptor_), false);
- // DCHECK(result != NULL); // may be NULL prior to class linker initialization
- // DCHECK_NE(0, result->GetLength()); // TODO: keep?
- return result;
- }
-
- void SetDescriptor(String* new_descriptor);
-
bool IsVariableSize() const {
// Classes and arrays vary in size, and so the object_size_ field cannot
// be used to get their instance size
@@ -1489,15 +1305,15 @@
// Returns true if this class is in the same packages as that class.
bool IsInSamePackage(const Class* that) const;
- static bool IsInSamePackage(const String* descriptor1, const String* descriptor2);
+ static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2);
// Returns true if this class can access that class.
- bool CanAccess(const Class* that) const {
+ bool CanAccess(Class* that) const {
return that->IsPublic() || this->IsInSamePackage(that);
}
// Validate method/field access.
- bool CanAccessMember(const Class* access_to, uint32_t member_flags) const {
+ bool CanAccessMember(Class* access_to, uint32_t member_flags) const {
// quick accept for public access
if (member_flags & kAccPublic) {
return true;
@@ -1556,10 +1372,6 @@
return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
}
- static MemberOffset SuperClassOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
- }
-
void SetSuperClass(Class *new_super_class) {
// super class is assigned once, except during class linker initialization
Class* old_super_class = GetFieldObject<Class*>(
@@ -1573,14 +1385,8 @@
return GetSuperClass() != NULL;
}
- uint32_t GetSuperClassTypeIdx() const {
- DCHECK(IsIdxLoaded() || IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, super_class_type_idx_),
- false);
- }
-
- void SetSuperClassTypeIdx(int32_t new_super_class_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, super_class_type_idx_), new_super_class_idx, false);
+ static MemberOffset SuperClassOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
}
ClassLoader* GetClassLoader() const;
@@ -1703,7 +1509,6 @@
Method* FindVirtualMethodForInterface(Method* method, bool can_throw);
Method* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const;
- Method* FindInterfaceMethod(String* name, String* descriptor) const;
Method* FindVirtualMethodForVirtualOrInterface(Method* method) {
if (method->IsDirect()) {
@@ -1716,10 +1521,8 @@
}
Method* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const;
- Method* FindDeclaredVirtualMethod(String* name, String* signature) const;
Method* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const;
- Method* FindVirtualMethod(String* name, String* descriptor) const;
Method* FindDeclaredDirectMethod(const StringPiece& name,
const StringPiece& signature);
@@ -1727,43 +1530,6 @@
Method* FindDirectMethod(const StringPiece& name,
const StringPiece& signature);
- size_t NumInterfaces() const {
- CHECK(IsIdxLoaded() || IsErroneous()); // used during loading
- ObjectArray<Class>* interfaces = GetFieldObject<ObjectArray<Class>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
- return (interfaces != NULL) ? interfaces->GetLength() : 0;
- }
-
- IntArray* GetInterfacesTypeIdx() const {
- CHECK(IsIdxLoaded() || IsErroneous());
- return GetFieldObject<IntArray*>(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_), false);
- }
-
- void SetInterfacesTypeIdx(IntArray* new_interfaces_idx);
-
- ObjectArray<Class>* GetInterfaces() const {
- CHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<Class>*>(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
- }
-
- void SetInterfaces(ObjectArray<Class>* new_interfaces) {
- DCHECK(NULL == GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false));
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), new_interfaces, false);
- }
-
- void SetInterface(uint32_t i, Class* f) { // TODO: uint16_t
- DCHECK_LT(i, NumInterfaces());
- ObjectArray<Class>* interfaces =
- GetFieldObject<ObjectArray<Class>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
- interfaces->Set(i, f);
- }
-
- Class* GetInterface(uint32_t i) const {
- DCHECK_LT(i, NumInterfaces());
- return GetInterfaces()->Get(i);
- }
-
int32_t GetIfTableCount() const {
ObjectArray<InterfaceEntry>* iftable = GetIfTable();
if (iftable == NULL) {
@@ -1890,17 +1656,13 @@
// Finds the given instance field in this class or a superclass.
Field* FindInstanceField(const StringPiece& name, const StringPiece& type);
- Field* FindInstanceField(String* name, String* type);
Field* FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type);
- Field* FindDeclaredInstanceField(String* name, String* type);
// Finds the given static field in this class or a superclass.
Field* FindStaticField(const StringPiece& name, const StringPiece& type);
- Field* FindStaticField(String* name, String* type);
Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type);
- Field* FindDeclaredStaticField(String* name, String* type);
pid_t GetClinitThreadId() const {
DCHECK(IsIdxLoaded() || IsErroneous());
@@ -1920,26 +1682,14 @@
klass->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
}
- uint32_t GetAnnotationsOffset() {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, annotations_offset_), false);
+ uint16_t GetDexTypeIndex() const {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false);
}
- void SetAnnotationsOffset(uint32_t annotations_offset) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, annotations_offset_), annotations_offset, false);
+ void SetDexTypeIndex(uint16_t type_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false);
}
- uint32_t GetTypeIdx() {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, type_idx_), false);
- }
-
- void SetTypeIdx(uint32_t type_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, type_idx_), type_idx, false);
- }
-
- String* GetSourceFile() const;
-
- void SetSourceFile(String* new_source_file);
-
private:
bool Implements(const Class* klass) const;
bool IsArrayAssignableFromArray(const Class* klass) const;
@@ -1955,9 +1705,6 @@
// (for String[][][], this will be String[][]). NULL for non-array classes.
Class* component_type_;
- // descriptor for the class such as "Ljava/lang/Class;" or "[C"
- String* descriptor_;
-
// DexCache of resolved constant pool entries
// (will be NULL for VM-generated, e.g. arrays and primitive classes)
DexCache* dex_cache_;
@@ -1992,20 +1739,9 @@
// of the concrete vtable_ methods for the methods in the interface.
ObjectArray<InterfaceEntry>* iftable_;
- // array of interfaces this class implements directly
- // see also interfaces_type_idx_
- ObjectArray<Class>* interfaces_;
-
- // array of type_idx's for interfaces this class implements directly
- // see also interfaces_
- IntArray* interfaces_type_idx_;
-
// Static fields
ObjectArray<Field>* sfields_;
- // source file name, if known. Otherwise, NULL.
- String* source_file_;
-
// The superclass, or NULL if this is java.lang.Object or a
// primitive type.
// see also super_class_type_idx_;
@@ -2023,12 +1759,13 @@
// virtual_ methods_ for miranda methods.
ObjectArray<Method>* vtable_;
+ // type index from dex file
+ // TODO: really 16bits
+ uint32_t dex_type_idx_;
+
// access flags; low 16 bits are defined by VM spec
uint32_t access_flags_;
- // annotation directory offset from dex file
- uint32_t annotations_offset_;
-
// Total size of the Class instance; used when allocating storage on gc heap.
// See also object_size_.
size_t class_size_;
@@ -2059,15 +1796,6 @@
// state of class initialization
Status status_;
- // Set in LoadClass, used to LinkClass
- // see also super_class_
- // TODO: really 16bits
- uint32_t super_class_type_idx_;
-
- // type index from dex file
- // TODO: really 16bits
- uint32_t type_idx_;
-
// TODO: ?
// initiating class loader list
// NOTE: for classes with low serialNumber, these are unused, and the
@@ -2187,32 +1915,6 @@
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), new_declaring_class, false);
}
-inline uint32_t Method::GetReturnTypeIdx() const {
- DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_), false);
-}
-
-inline bool Method::IsReturnAReference() const {
- char d = GetReturnTypeDescriptor()[0];
- return d == 'L' || d == '[';
-}
-
-inline bool Method::IsReturnAFloat() const {
- return GetReturnTypeDescriptor()[0] == 'F';
-}
-
-inline bool Method::IsReturnADouble() const {
- return GetReturnTypeDescriptor()[0] == 'D';
-}
-
-inline bool Method::IsReturnALong() const {
- return GetReturnTypeDescriptor()[0] == 'J';
-}
-
-inline bool Method::IsReturnVoid() const {
- return GetReturnTypeDescriptor()[0] == 'V';
-}
-
inline size_t Array::SizeOf() const {
// This is safe from overflow because the array was already allocated, so we know it's sane.
return sizeof(Array) + GetLength() * GetClass()->GetComponentSize();
@@ -2309,14 +2011,6 @@
class MANAGED FieldClass : public Class {
private:
Object* ORDER_BY_NAME_AND_DECLARING_CLASS_;
- uint32_t TYPE_BOOLEAN_;
- uint32_t TYPE_BYTE_;
- uint32_t TYPE_CHAR_;
- uint32_t TYPE_DOUBLE_;
- uint32_t TYPE_FLOAT_;
- uint32_t TYPE_INTEGER_;
- uint32_t TYPE_LONG_;
- uint32_t TYPE_SHORT_;
friend struct FieldClassOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(FieldClass);
};
@@ -2377,13 +2071,6 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
};
-inline void Class::SetInterfacesTypeIdx(IntArray* new_interfaces_idx) {
- DCHECK(NULL == GetFieldObject<IntArray*>(
- OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_), false));
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_),
- new_interfaces_idx, false);
-}
-
// C++ mirror of java.lang.String
class MANAGED String : public Object {
public:
@@ -2500,27 +2187,11 @@
}
};
-inline String* Field::GetName() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- String* result = GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Field, name_), false);
- DCHECK(result != NULL);
- return result;
-}
-
-inline void Field::SetName(String* new_name) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, name_), new_name, false);
-}
-
inline uint32_t Field::GetAccessFlags() const {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false);
}
-inline uint32_t Field::GetTypeIdx() const {
- DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), false);
-}
-
inline MemberOffset Field::GetOffset() const {
DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
@@ -2531,43 +2202,6 @@
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
}
-inline String* Method::GetName() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- String* result = GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Method, name_), false);
- DCHECK(result != NULL);
- return result;
-}
-
-inline void Method::SetName(String* new_name) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, name_), new_name, false);
-}
-
-inline String* Method::GetShorty() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false);
-}
-
-inline void Method::SetShorty(String* new_shorty) {
- DCHECK(NULL == GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false));
- DCHECK_LE(1, new_shorty->GetLength());
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), new_shorty, false);
-}
-
-inline String* Method::GetSignature() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- String* result = GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Method, signature_), false);
- DCHECK(result != NULL);
- return result;
-}
-
-inline void Method::SetSignature(String* new_signature) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, signature_), new_signature, false);
-}
-
-inline void Method::SetExceptionTypes(ObjectArray<Class>* exception_types) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, java_exception_types_), exception_types, false);
-}
-
inline uint32_t Class::GetAccessFlags() const {
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
@@ -2579,23 +2213,6 @@
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
-inline void Class::SetDescriptor(String* new_descriptor) {
- DCHECK(GetDescriptor() == NULL);
- DCHECK(new_descriptor != NULL);
- DCHECK_NE(0, new_descriptor->GetLength());
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, descriptor_),
- new_descriptor, false);
-}
-
-inline String* Class::GetSourceFile() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, source_file_), false);
-}
-
-inline void Class::SetSourceFile(String* new_source_file) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, source_file_), new_source_file, false);
-}
-
inline uint32_t Method::GetAccessFlags() const {
DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), false);
@@ -2606,24 +2223,16 @@
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
}
-inline uint16_t Method::NumRegisters() const {
+inline uint32_t Method::GetDexMethodIndex() const {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), false);
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_dex_index_), false);
}
-inline uint16_t Method::NumIns() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), false);
+inline String* Class::GetName() const {
+ return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
}
-
-inline uint16_t Method::NumOuts() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), false);
-}
-
-inline uint32_t Method::GetProtoIdx() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, proto_idx_), false);
+inline void Class::SetName(String* name) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
}
// C++ mirror of java.lang.Throwable
@@ -2675,9 +2284,9 @@
OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
}
- static StackTraceElement* Alloc(const String* declaring_class,
- const String* method_name,
- const String* file_name,
+ static StackTraceElement* Alloc(String* declaring_class,
+ String* method_name,
+ String* file_name,
int32_t line_number);
static void SetClass(Class* java_lang_StackTraceElement);
@@ -2686,9 +2295,9 @@
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- const String* declaring_class_;
- const String* file_name_;
- const String* method_name_;
+ String* declaring_class_;
+ String* file_name_;
+ String* method_name_;
int32_t line_number_;
static Class* GetStackTraceElement() {
@@ -2719,7 +2328,7 @@
size_t GetMethodArrayCount() const {
ObjectArray<Method>* method_array = down_cast<ObjectArray<Method>*>(Get(kMethodArray));
- if (method_array == 0) {
+ if (method_array == NULL) {
return 0;
}
return method_array->GetLength();
diff --git a/src/object_test.cc b/src/object_test.cc
index 08abb6f..b1d5885 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -42,18 +42,12 @@
TEST_F(ObjectTest, IsInSamePackage) {
// Matches
- 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()));
+ EXPECT_TRUE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/lang/Class;"));
+ EXPECT_TRUE(Class::IsInSamePackage("LFoo;", "LBar;"));
// Mismatches
- 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()));
+ EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/io/File;"));
+ EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/lang/reflect/Method;"));
}
TEST_F(ObjectTest, Clone) {
@@ -90,11 +84,10 @@
self->ClearException();
ASSERT_TRUE(oa->GetClass() != NULL);
- ASSERT_EQ(2U, oa->GetClass()->NumInterfaces());
- EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Cloneable;"),
- oa->GetClass()->GetInterface(0));
- EXPECT_EQ(class_linker_->FindSystemClass("Ljava/io/Serializable;"),
- oa->GetClass()->GetInterface(1));
+ ClassHelper oa_ch(oa->GetClass());
+ ASSERT_EQ(2U, oa_ch.NumInterfaces());
+ EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Cloneable;"), oa_ch.GetInterface(0));
+ EXPECT_EQ(class_linker_->FindSystemClass("Ljava/io/Serializable;"), oa_ch.GetInterface(1));
}
TEST_F(ObjectTest, AllocArray) {
@@ -288,34 +281,50 @@
ASSERT_TRUE(klass2 != NULL);
Method* m1_1 = klass1->GetVirtualMethod(0);
- EXPECT_TRUE(m1_1->GetName()->Equals("m1"));
+ MethodHelper mh(m1_1);
+ EXPECT_STREQ(mh.GetName(), "m1");
Method* m2_1 = klass1->GetVirtualMethod(1);
- EXPECT_TRUE(m2_1->GetName()->Equals("m2"));
+ mh.ChangeMethod(m2_1);
+ EXPECT_STREQ(mh.GetName(), "m2");
Method* m3_1 = klass1->GetVirtualMethod(2);
- EXPECT_TRUE(m3_1->GetName()->Equals("m3"));
+ mh.ChangeMethod(m3_1);
+ EXPECT_STREQ(mh.GetName(), "m3");
Method* m4_1 = klass1->GetVirtualMethod(3);
- EXPECT_TRUE(m4_1->GetName()->Equals("m4"));
+ mh.ChangeMethod(m4_1);
+ EXPECT_STREQ(mh.GetName(), "m4");
Method* m1_2 = klass2->GetVirtualMethod(0);
- EXPECT_TRUE(m1_2->GetName()->Equals("m1"));
+ mh.ChangeMethod(m1_2);
+ EXPECT_STREQ(mh.GetName(), "m1");
Method* m2_2 = klass2->GetVirtualMethod(1);
- EXPECT_TRUE(m2_2->GetName()->Equals("m2"));
+ mh.ChangeMethod(m2_2);
+ EXPECT_STREQ(mh.GetName(), "m2");
Method* m3_2 = klass2->GetVirtualMethod(2);
- EXPECT_TRUE(m3_2->GetName()->Equals("m3"));
+ mh.ChangeMethod(m3_2);
+ EXPECT_STREQ(mh.GetName(), "m3");
Method* m4_2 = klass2->GetVirtualMethod(3);
- EXPECT_TRUE(m4_2->GetName()->Equals("m4"));
+ mh.ChangeMethod(m4_2);
+ EXPECT_STREQ(mh.GetName(), "m4");
- EXPECT_TRUE(m1_1->HasSameNameAndSignature(m1_2));
- EXPECT_TRUE(m1_2->HasSameNameAndSignature(m1_1));
+ mh.ChangeMethod(m1_1);
+ MethodHelper mh2(m1_2);
+ EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2));
+ EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh));
- EXPECT_TRUE(m2_1->HasSameNameAndSignature(m2_2));
- EXPECT_TRUE(m2_2->HasSameNameAndSignature(m2_1));
+ mh.ChangeMethod(m2_1);
+ mh2.ChangeMethod(m2_2);
+ EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2));
+ EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh));
- EXPECT_TRUE(m3_1->HasSameNameAndSignature(m3_2));
- EXPECT_TRUE(m3_2->HasSameNameAndSignature(m3_1));
+ mh.ChangeMethod(m3_1);
+ mh2.ChangeMethod(m3_2);
+ EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2));
+ EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh));
- EXPECT_TRUE(m4_1->HasSameNameAndSignature(m4_2));
- EXPECT_TRUE(m4_2->HasSameNameAndSignature(m4_1));
+ mh.ChangeMethod(m4_1);
+ mh2.ChangeMethod(m4_2);
+ EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2));
+ EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh));
}
diff --git a/src/object_utils.h b/src/object_utils.h
new file mode 100644
index 0000000..dc48aa0
--- /dev/null
+++ b/src/object_utils.h
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_OBJECT_UTILS_H_
+#define ART_SRC_OBJECT_UTILS_H_
+
+#include "class_linker.h"
+#include "dex_cache.h"
+#include "dex_file.h"
+#include "object.h"
+#include "runtime.h"
+
+#include <string>
+
+namespace art {
+
+class ClassHelper {
+ public:
+ ClassHelper() : class_def_(NULL), class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL),
+ interface_type_list_(NULL), klass_(NULL) {}
+ ClassHelper(const Class* c) : class_def_(NULL), class_linker_(NULL), dex_cache_(NULL),
+ dex_file_(NULL), interface_type_list_(NULL), klass_(c) {}
+ ClassHelper(const Class* c, ClassLinker* l) : class_def_(NULL), class_linker_(l),
+ dex_cache_(NULL), dex_file_(NULL), interface_type_list_(NULL), klass_(c) {}
+
+ void ChangeClass(const Class* new_c) {
+ DCHECK(new_c != NULL);
+ if (dex_cache_ != NULL) {
+ DexCache* new_c_dex_cache = new_c->GetDexCache();
+ if (new_c_dex_cache != dex_cache_) {
+ dex_cache_ = new_c_dex_cache;
+ dex_file_ = NULL;
+ }
+ }
+ klass_ = new_c;
+ interface_type_list_ = NULL;
+ class_def_ = NULL;
+ }
+
+ std::string GetDescriptor() {
+ if (klass_->IsArrayClass()) {
+ std::string result = "[";
+ const Class* saved_klass = klass_;
+ ChangeClass(klass_->GetComponentType());
+ result += GetDescriptor();
+ ChangeClass(saved_klass);
+ return result;
+ } else if (klass_->IsPrimitive()){
+ std::string result;
+ result += Primitive::DescriptorChar(klass_->GetPrimitiveType());
+ return result;
+ } else if (klass_->IsProxyClass()) {
+ return GetClassLinker()->GetDescriptorForProxy(klass_);
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(klass_->GetDexTypeIndex());
+ return dex_file.GetTypeDescriptor(type_id);
+ }
+ }
+ const DexFile::ClassDef* GetClassDef() {
+ const DexFile::ClassDef* result = class_def_;
+ if (result == NULL) {
+ result = GetDexFile().FindClassDef(GetDescriptor());
+ class_def_ = result;
+ }
+ return result;
+ }
+ uint32_t NumInterfaces() {
+ if (klass_->IsPrimitive()) {
+ return 0;
+ } else if (klass_->IsArrayClass()) {
+ return 2;
+ } else {
+ CHECK(!klass_->IsProxyClass());
+ const DexFile::TypeList* interfaces = GetInterfaceTypeList();
+ if (interfaces == NULL) {
+ return 0;
+ } else {
+ return interfaces->Size();
+ }
+ }
+ }
+ uint16_t GetInterfaceTypeIdx(uint32_t idx) {
+ DCHECK(!klass_->IsPrimitive());
+ DCHECK(!klass_->IsArrayClass());
+ return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
+ }
+ Class* GetInterface(uint32_t idx) {
+ DCHECK(!klass_->IsPrimitive());
+ if (klass_->IsArrayClass()) {
+ if (idx == 0) {
+ return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
+ } else {
+ DCHECK_EQ(1U, idx);
+ return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
+ }
+ } else {
+ uint16_t type_idx = GetInterfaceTypeIdx(idx);
+ Class* interface = GetDexCache()->GetResolvedType(type_idx);
+ if (interface == NULL) {
+ interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
+ CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
+ }
+ return interface;
+ }
+ }
+ const char* GetSourceFile() {
+ std::string descriptor = GetDescriptor();
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
+ if (dex_class_def == NULL) {
+ return NULL;
+ } else {
+ return dex_file.GetSourceFile(*dex_class_def);
+ }
+ }
+ std::string GetLocation() {
+ return GetDexCache()->GetLocation()->ToModifiedUtf8();
+ }
+
+ const DexFile& GetDexFile() {
+ const DexFile* result = dex_file_;
+ if (result == NULL) {
+ const DexCache* dex_cache = GetDexCache();
+ result = &GetClassLinker()->FindDexFile(dex_cache);
+ dex_file_ = result;
+ }
+ return *result;
+ }
+
+ private:
+ const DexFile::TypeList* GetInterfaceTypeList() {
+ const DexFile::TypeList* result = interface_type_list_;
+ if (result == NULL) {
+ const DexFile::ClassDef* class_def = GetClassDef();
+ if (class_def != NULL) {
+ result = GetDexFile().GetInterfacesList(*class_def);
+ interface_type_list_ = result;
+ }
+ }
+ return result;
+ }
+ DexCache* GetDexCache() {
+ DexCache* result = dex_cache_;
+ if (result == NULL) {
+ result = klass_->GetDexCache();
+ dex_cache_ = result;
+ }
+ return result;
+ }
+ ClassLinker* GetClassLinker() {
+ ClassLinker* result = class_linker_;
+ if (result == NULL) {
+ result = Runtime::Current()->GetClassLinker();
+ class_linker_ = result;
+ }
+ return result;
+ }
+
+ const DexFile::ClassDef* class_def_;
+ ClassLinker* class_linker_;
+ DexCache* dex_cache_;
+ const DexFile* dex_file_;
+ const DexFile::TypeList* interface_type_list_;
+ const Class* klass_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClassHelper);
+};
+
+class FieldHelper {
+ public:
+ FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {}
+ FieldHelper(const Field* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
+ FieldHelper(const Field* f, ClassLinker* l) : class_linker_(l), dex_cache_(NULL), dex_file_(NULL),
+ field_(f) {}
+
+ void ChangeField(const Field* new_f) {
+ DCHECK(new_f != NULL);
+ if (dex_cache_ != NULL) {
+ DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache();
+ if (new_f_dex_cache != dex_cache_) {
+ dex_cache_ = new_f_dex_cache;
+ dex_file_ = NULL;
+ }
+ }
+ field_ = new_f;
+ }
+ const char* GetName() {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetFieldName(dex_file.GetFieldId(field_->GetDexFieldIndex()));
+ }
+ String* GetNameAsString() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
+ return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache());
+ }
+ Class* GetType() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
+ Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
+ if (type == NULL) {
+ type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
+ CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ }
+ return type;
+ }
+ const char* GetTypeDescriptor() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
+ return dex_file.GetFieldTypeDescriptor(field_id);
+ }
+ Primitive::Type GetTypeAsPrimitiveType() {
+ return Primitive::GetType(GetTypeDescriptor()[0]);
+ }
+ bool IsPrimitiveType() {
+ Primitive::Type type = GetTypeAsPrimitiveType();
+ return type != Primitive::kPrimNot;
+ }
+ size_t FieldSize() {
+ Primitive::Type type = GetTypeAsPrimitiveType();
+ return Primitive::FieldSize(type);
+ }
+ const char* GetDeclaringClassDescriptor() {
+ uint16_t type_idx = field_->GetDeclaringClass()->GetDexTypeIndex();
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
+ }
+
+ private:
+ DexCache* GetDexCache() {
+ DexCache* result = dex_cache_;
+ if (result == NULL) {
+ result = field_->GetDeclaringClass()->GetDexCache();
+ dex_cache_ = result;
+ }
+ return result;
+ }
+ ClassLinker* GetClassLinker() {
+ ClassLinker* result = class_linker_;
+ if (result == NULL) {
+ result = Runtime::Current()->GetClassLinker();
+ class_linker_ = result;
+ }
+ return result;
+ }
+ const DexFile& GetDexFile() {
+ const DexFile* result = dex_file_;
+ if (result == NULL) {
+ const DexCache* dex_cache = GetDexCache();
+ result = &GetClassLinker()->FindDexFile(dex_cache);
+ dex_file_ = result;
+ }
+ return *result;
+ }
+
+ ClassLinker* class_linker_;
+ DexCache* dex_cache_;
+ const DexFile* dex_file_;
+ const Field* field_;
+
+ DISALLOW_COPY_AND_ASSIGN(FieldHelper);
+};
+
+class MethodHelper {
+ public:
+ MethodHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL),
+ shorty_(NULL), shorty_len_(0) {}
+ MethodHelper(const Method* m) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL),
+ method_(NULL), shorty_(NULL), shorty_len_(0) {
+ SetMethod(m);
+ }
+ MethodHelper(const Method* m, ClassLinker* l) : class_linker_(l), dex_cache_(NULL),
+ dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) {
+ SetMethod(m);
+ }
+
+ void ChangeMethod(Method* new_m) {
+ DCHECK(new_m != NULL);
+ if (dex_cache_ != NULL) {
+ Class* klass = new_m->GetDeclaringClass();
+ if (klass->IsProxyClass()) {
+ dex_cache_ = NULL;
+ dex_file_ = NULL;
+ } else {
+ DexCache* new_m_dex_cache = klass->GetDexCache();
+ if (new_m_dex_cache != dex_cache_) {
+ dex_cache_ = new_m_dex_cache;
+ dex_file_ = NULL;
+ }
+ }
+ }
+ SetMethod(new_m);
+ shorty_ = NULL;
+ }
+ const char* GetName() {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetMethodName(dex_file.GetMethodId(method_->GetDexMethodIndex()));
+ }
+ String* GetNameAsString() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
+ return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
+ }
+ const char* GetShorty() {
+ const char* result = shorty_;
+ if (result == NULL) {
+ const DexFile& dex_file = GetDexFile();
+ result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
+ &shorty_len_);
+ shorty_ = result;
+ }
+ return result;
+ }
+ int32_t GetShortyLength() {
+ if (shorty_ == NULL) {
+ GetShorty();
+ }
+ return shorty_len_;
+ }
+ const std::string GetSignature() {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetMethodSignature(dex_file.GetMethodId(method_->GetDexMethodIndex()));
+ }
+ const DexFile::ProtoId& GetPrototype() {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
+ }
+ const DexFile::TypeList* GetParameterTypeList() {
+ const DexFile::ProtoId& proto = GetPrototype();
+ return GetDexFile().GetProtoParameters(proto);
+ }
+ ObjectArray<Class>* GetParameterTypes() {
+ const DexFile::TypeList* params = GetParameterTypeList();
+ Class* array_class = GetClassLinker()->FindSystemClass("[Ljava/lang/Class;");
+ uint32_t num_params = params == NULL ? 0 : params->Size();
+ ObjectArray<Class>* result = ObjectArray<Class>::Alloc(array_class, num_params);
+ for (uint32_t i = 0; i < num_params; i++) {
+ Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_);
+ result->Set(i, param_type);
+ }
+ return result;
+ }
+ Class* GetReturnType() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
+ const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
+ uint16_t return_type_idx = proto_id.return_type_idx_;
+ return GetClassFromTypeIdx(return_type_idx);
+ }
+ const char* GetReturnTypeDescriptor() {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
+ const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
+ uint16_t return_type_idx = proto_id.return_type_idx_;
+ return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
+ }
+ int32_t GetLineNumFromNativePC(uintptr_t raw_pc) {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetLineNumFromPC(method_, method_->ToDexPC(raw_pc));
+ }
+ const char* GetDeclaringClassDescriptor() {
+ Class* klass = method_->GetDeclaringClass();
+ CHECK(!klass->IsProxyClass());
+ uint16_t type_idx = klass->GetDexTypeIndex();
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
+ }
+ const char* GetDeclaringClassSourceFile() {
+ const char* descriptor = GetDeclaringClassDescriptor();
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
+ if (dex_class_def == NULL) {
+ return NULL;
+ } else {
+ return dex_file.GetSourceFile(*dex_class_def);
+ }
+ }
+ bool IsStatic() {
+ return method_->IsStatic();
+ }
+ bool IsClassInitializer() {
+ return IsStatic() && StringPiece(GetName()) == "<clinit>";
+ }
+ size_t NumArgs() {
+ // "1 +" because the first in Args is the receiver.
+ // "- 1" because we don't count the return type.
+ return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
+ }
+ // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods
+ bool IsParamALongOrDouble(size_t param) {
+ CHECK_LT(param, NumArgs());
+ if (IsStatic()) {
+ param++; // 0th argument must skip return value at start of the shorty
+ } else if (param == 0) {
+ return false; // this argument
+ }
+ char ch = GetShorty()[param];
+ return (ch == 'J' || ch == 'D');
+ }
+ // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods
+ bool IsParamAReference(size_t param) {
+ CHECK_LT(param, NumArgs());
+ if (IsStatic()) {
+ param++; // 0th argument must skip return value at start of the shorty
+ } else if (param == 0) {
+ return true; // this argument
+ }
+ return GetShorty()[param] == 'L'; // An array also has a shorty character of 'L' (not '[')
+ }
+ bool HasSameNameAndSignature(MethodHelper* other) {
+ StringPiece name(GetName());
+ StringPiece other_name(other->GetName());
+ if (name != other_name) {
+ return false;
+ }
+ if (GetDexCache() == other->GetDexCache()) {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
+ const DexFile::MethodId& other_mid =
+ dex_file.GetMethodId(other->method_->GetDexMethodIndex());
+ return mid.proto_idx_ == other_mid.proto_idx_;
+ }
+ return GetSignature() == other->GetSignature();
+ }
+ const DexFile::CodeItem* GetCodeItem() {
+ return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
+ }
+ Class* GetClassFromTypeIdx(uint16_t type_idx) {
+ Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
+ if (type == NULL) {
+ type = GetClassLinker()->ResolveType(type_idx, method_);
+ CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ }
+ return type;
+ }
+ const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
+ }
+ Class* GetDexCacheResolvedType(uint16_t type_idx) {
+ return GetDexCache()->GetResolvedType(type_idx);
+ }
+ const DexFile& GetDexFile() {
+ const DexFile* result = dex_file_;
+ if (result == NULL) {
+ const DexCache* dex_cache = GetDexCache();
+ result = &GetClassLinker()->FindDexFile(dex_cache);
+ dex_file_ = result;
+ }
+ return *result;
+ }
+ private:
+ // Set the method_ field, for proxy methods looking up the interface method via the resolved
+ // methods table.
+ void SetMethod(const Method* method) {
+ if (method != NULL) {
+ Class* klass = method->GetDeclaringClass();
+ if (klass->IsProxyClass()) {
+ method = method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
+ CHECK(method != NULL);
+ }
+ }
+ method_ = method;
+ }
+ DexCache* GetDexCache() {
+ DexCache* result = dex_cache_;
+ if (result == NULL) {
+ Class* klass = method_->GetDeclaringClass();
+ result = klass->GetDexCache();
+ dex_cache_ = result;
+ }
+ return result;
+ }
+ ClassLinker* GetClassLinker() {
+ ClassLinker* result = class_linker_;
+ if (result == NULL) {
+ result = Runtime::Current()->GetClassLinker();
+ class_linker_ = result;
+ }
+ return result;
+ }
+
+ ClassLinker* class_linker_;
+ DexCache* dex_cache_;
+ const DexFile* dex_file_;
+ const Method* method_;
+ const char* shorty_;
+ int32_t shorty_len_;
+
+ DISALLOW_COPY_AND_ASSIGN(MethodHelper);
+};
+
+} // namespace art
+
+#endif // ART_SRC_OBJECT_UTILS_H_
diff --git a/src/primitive.h b/src/primitive.h
index 5d41966..402a2b5 100644
--- a/src/primitive.h
+++ b/src/primitive.h
@@ -101,11 +101,13 @@
case kPrimInt:
return 'I';
case kPrimFloat:
- return 'J';
+ return 'F';
case kPrimLong:
return 'J';
case kPrimDouble:
return 'D';
+ case kPrimVoid:
+ return 'V';
default:
LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
return 0;
diff --git a/src/reflection.cc b/src/reflection.cc
index f02c2d2..a6ae096 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -19,6 +19,7 @@
#include "class_linker.h"
#include "jni_internal.h"
#include "object.h"
+#include "object_utils.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -45,7 +46,7 @@
gShort_valueOf = class_linker->FindSystemClass("Ljava/lang/Short;")->FindDeclaredDirectMethod("valueOf", "(S)Ljava/lang/Short;");
}
-jobject InvokeMethod(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jobject javaParams) {
+jobject InvokeMethod(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs) {
Thread* self = Thread::Current();
ScopedThreadStateChange tsc(self, Thread::kRunnable);
@@ -72,21 +73,23 @@
// Get our arrays of arguments and their types, and check they're the same size.
ObjectArray<Object>* objects = Decode<ObjectArray<Object>*>(env, javaArgs);
- ObjectArray<Class>* classes = Decode<ObjectArray<Class>*>(env, javaParams);
- int32_t arg_count = (objects != NULL) ? objects->GetLength() : 0;
- if (arg_count != classes->GetLength()) {
+ MethodHelper mh(m);
+ const DexFile::TypeList* classes = mh.GetParameterTypeList();
+ uint32_t classes_size = classes == NULL ? 0 : classes->Size();
+ uint32_t arg_count = (objects != NULL) ? objects->GetLength() : 0;
+ if (arg_count != classes_size) {
self->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"wrong number of arguments; expected %d, got %d",
- classes->GetLength(), arg_count);
+ classes_size, arg_count);
return NULL;
}
// Translate javaArgs to a jvalue[].
UniquePtr<jvalue[]> args(new jvalue[arg_count]);
JValue* decoded_args = reinterpret_cast<JValue*>(args.get());
- for (int32_t i = 0; i < arg_count; ++i) {
+ for (uint32_t i = 0; i < arg_count; ++i) {
Object* arg = objects->Get(i);
- Class* dst_class = classes->Get(i);
+ Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_);
if (dst_class->IsPrimitive()) {
if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
return NULL;
@@ -111,7 +114,7 @@
}
// Box if necessary and return.
- BoxPrimitive(env, m->GetReturnType()->GetPrimitiveType(), value);
+ BoxPrimitive(env, mh.GetReturnType()->GetPrimitiveType(), value);
return AddLocalReference<jobject>(env, value.l);
}
@@ -121,7 +124,7 @@
return false;
}
if (!o->InstanceOf(c)) {
- std::string expectedClassName(PrettyDescriptor(c->GetDescriptor()));
+ std::string expectedClassName(PrettyDescriptor(c));
std::string actualClassName(PrettyTypeOf(o));
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"expected receiver of type %s, but got %s",
@@ -283,7 +286,7 @@
if (o != NULL && !o->InstanceOf(dst_class)) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"expected object of type %s, but got %s",
- PrettyDescriptor(dst_class->GetDescriptor()).c_str(),
+ PrettyDescriptor(dst_class).c_str(),
PrettyTypeOf(o).c_str());
return false;
}
@@ -302,37 +305,37 @@
}
JValue boxed_value = { 0 };
- const String* src_descriptor = o->GetClass()->GetDescriptor();
+ std::string src_descriptor = ClassHelper(o->GetClass()).GetDescriptor();
Class* src_class = NULL;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Field* primitive_field = o->GetClass()->GetIFields()->Get(0);
- if (src_descriptor->Equals("Ljava/lang/Boolean;")) {
+ if (src_descriptor == "Ljava/lang/Boolean;") {
src_class = class_linker->FindPrimitiveClass('Z');
boxed_value.i = primitive_field->GetBoolean(o); // and extend read value to 32bits
- } else if (src_descriptor->Equals("Ljava/lang/Byte;")) {
+ } else if (src_descriptor == "Ljava/lang/Byte;") {
src_class = class_linker->FindPrimitiveClass('B');
boxed_value.i = primitive_field->GetByte(o); // and extend read value to 32bits
- } else if (src_descriptor->Equals("Ljava/lang/Character;")) {
+ } else if (src_descriptor == "Ljava/lang/Character;") {
src_class = class_linker->FindPrimitiveClass('C');
boxed_value.i = primitive_field->GetChar(o); // and extend read value to 32bits
- } else if (src_descriptor->Equals("Ljava/lang/Float;")) {
+ } else if (src_descriptor == "Ljava/lang/Float;") {
src_class = class_linker->FindPrimitiveClass('F');
boxed_value.f = primitive_field->GetFloat(o);
- } else if (src_descriptor->Equals("Ljava/lang/Double;")) {
+ } else if (src_descriptor == "Ljava/lang/Double;") {
src_class = class_linker->FindPrimitiveClass('D');
boxed_value.d = primitive_field->GetDouble(o);
- } else if (src_descriptor->Equals("Ljava/lang/Integer;")) {
+ } else if (src_descriptor == "Ljava/lang/Integer;") {
src_class = class_linker->FindPrimitiveClass('I');
boxed_value.i = primitive_field->GetInt(o);
- } else if (src_descriptor->Equals("Ljava/lang/Long;")) {
+ } else if (src_descriptor == "Ljava/lang/Long;") {
src_class = class_linker->FindPrimitiveClass('J');
boxed_value.j = primitive_field->GetLong(o);
- } else if (src_descriptor->Equals("Ljava/lang/Short;")) {
+ } else if (src_descriptor == "Ljava/lang/Short;") {
src_class = class_linker->FindPrimitiveClass('S');
boxed_value.i = primitive_field->GetShort(o); // and extend read value to 32bits
} else {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
- "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor).c_str());
+ "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor.c_str()).c_str());
return false;
}
diff --git a/src/reflection.h b/src/reflection.h
index df19deb..e832c3d 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -32,7 +32,7 @@
bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, const JValue& src, JValue& dst);
-jobject InvokeMethod(JNIEnv* env, jobject method, jobject receiver, jobject args, jobject params);
+jobject InvokeMethod(JNIEnv* env, jobject method, jobject receiver, jobject args);
bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c);
diff --git a/src/runtime.cc b/src/runtime.cc
index 9e6ebb1..6491138 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -800,19 +800,8 @@
Class* method_class = Method::GetMethodClass();
SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
method->SetDeclaringClass(method_class);
- const char* name;
- if (type == kSaveAll) {
- name = "$$$callee_save_method$$$";
- } else if (type == kRefsOnly) {
- name = "$$$refs_only_callee_save_method$$$";
- } else {
- DCHECK(type == kRefsAndArgs);
- name = "$$$refs_and_args_callee_save_method$$$";
- }
- method->SetName(intern_table_->InternStrong(name));
- CHECK(method->GetName() != NULL);
- method->SetSignature(intern_table_->InternStrong("()V"));
- CHECK(method->GetSignature() != NULL);
+ // TODO: use a special method for callee saves
+ method->SetMethodIndex(DexFile::kDexNoIndex16);
method->SetCode(NULL);
if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) |
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index e6011da..1d05527 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -19,6 +19,8 @@
#include "dex_cache.h"
#include "dex_verifier.h"
#include "macros.h"
+#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
@@ -172,7 +174,7 @@
result += "tried to access class ";
result += class_name;
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -194,7 +196,7 @@
result += "tried to access field ";
result += class_name + "." + field_name;
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -217,7 +219,7 @@
result += class_name + "." + method_name + ":" +
dex_file.CreateMethodSignature(id.proto_idx_, NULL);
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -352,9 +354,7 @@
Method* caller = *caller_sp;
// less two as return address may span into next dex instruction
uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
- const DexFile& dex_file = Runtime::Current()->GetClassLinker()
- ->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
- const DexFile::CodeItem* code = dex_file.GetCodeItem(caller->GetCodeItemOffset());
+ const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
Instruction::Code instr_code = instr->Opcode();
@@ -473,14 +473,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) {
return field->Get32(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 32-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -495,14 +497,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) {
return field->Get64(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 64-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -517,14 +521,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(!field->IsPrimitiveType())) {
+ FieldHelper fh(field);
+ if (LIKELY(!fh.IsPrimitiveType())) {
return field->GetObj(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (field->IsPrimitiveType()) {
+ FieldHelper fh(field);
+ if (fh.IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of reference on primitive field '%s'",
PrettyField(field, true).c_str());
@@ -539,7 +545,8 @@
uint32_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) {
field->Set32(NULL, new_value);
return 0; // success
}
@@ -547,7 +554,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 32-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -563,7 +571,8 @@
uint64_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) {
field->Set64(NULL, new_value);
return 0; // success
}
@@ -571,7 +580,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (LIKELY(field != NULL)) {
- if (UNLIKELY(!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (UNLIKELY(!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t))) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 64-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -587,7 +597,7 @@
Object* new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(!field->IsPrimitiveType())) {
+ if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
field->SetObj(NULL, new_value);
return 0; // success
}
@@ -595,7 +605,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (field->IsPrimitiveType()) {
+ if (FieldHelper(field).IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of reference to primitive field '%s'",
PrettyField(field, true).c_str());
@@ -643,8 +653,8 @@
Class* referrer = method->GetDeclaringClass();
if (UNLIKELY(!referrer->CanAccess(klass))) {
self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "illegal class access: '%s' -> '%s'",
- PrettyDescriptor(referrer->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(referrer).c_str(),
+ PrettyDescriptor(klass).c_str());
return NULL; // Failure
}
if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
@@ -672,11 +682,11 @@
if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
"Bad filled array request for type %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
} else {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
"Found type %s; filled-new-array not implemented for anything but \'int\'",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
}
return NULL; // Failure
} else {
@@ -731,8 +741,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
"%s cannot be cast to %s",
- PrettyDescriptor(a->GetDescriptor()).c_str(),
- PrettyDescriptor(b->GetDescriptor()).c_str());
+ PrettyDescriptor(a).c_str(),
+ PrettyDescriptor(b).c_str());
return -1; // Failure
}
}
@@ -751,8 +761,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
"Cannot store an object of type %s in to an array of type %s",
- PrettyDescriptor(element_class->GetDescriptor()).c_str(),
- PrettyDescriptor(array_class->GetDescriptor()).c_str());
+ PrettyDescriptor(element_class).c_str(),
+ PrettyDescriptor(array_class).c_str());
return -1; // Failure
}
}
@@ -769,7 +779,7 @@
//
// Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
// running.
- if (klass == referrer->GetDeclaringClass() && referrer->IsClassInitializer()) {
+ if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) {
return klass;
}
if (!class_linker->EnsureInitialized(klass, true)) {
@@ -792,14 +802,14 @@
if (UNLIKELY(!referrer->GetDeclaringClass()->CanAccess(klass))) {
self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Class %s is inaccessible to method %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
+ PrettyDescriptor(klass).c_str(),
PrettyMethod(referrer, true).c_str());
}
// If we are the <clinit> of this class, just return our storage.
//
// Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
// running.
- if (klass == referrer->GetDeclaringClass() && referrer->IsClassInitializer()) {
+ if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) {
return klass;
}
if (!class_linker->EnsureInitialized(klass, true)) {
@@ -1000,10 +1010,11 @@
// Placing into local references incoming arguments from the caller's register arguments,
// replacing original Object* with jobject
- const size_t num_params = proxy_method->NumArgs();
+ MethodHelper proxy_mh(proxy_method);
+ const size_t num_params = proxy_mh.NumArgs();
size_t args_in_regs = 0;
for (size_t i = 1; i < num_params; i++) { // skip receiver
- args_in_regs = args_in_regs + (proxy_method->IsParamALongOrDouble(i) ? 2 : 1);
+ args_in_regs = args_in_regs + (proxy_mh.IsParamALongOrDouble(i) ? 2 : 1);
if (args_in_regs > 2) {
args_in_regs = 2;
break;
@@ -1012,23 +1023,23 @@
size_t cur_arg = 0; // current stack location to read
size_t param_index = 1; // skip receiver
while (cur_arg < args_in_regs && param_index < num_params) {
- if (proxy_method->IsParamAReference(param_index)) {
+ if (proxy_mh.IsParamAReference(param_index)) {
Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
jobject jobj = AddLocalReference<jobject>(env, obj);
*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
}
- cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1);
+ cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
param_index++;
}
// Placing into local references incoming arguments from the caller's stack arguments
cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3
while (param_index < num_params) {
- if (proxy_method->IsParamAReference(param_index)) {
+ if (proxy_mh.IsParamAReference(param_index)) {
Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
jobject jobj = AddLocalReference<jobject>(env, obj);
*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
}
- cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1);
+ cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
param_index++;
}
// Set up arguments array and place in local IRT during boxing (which may allocate/GC)
@@ -1049,13 +1060,14 @@
// Convert proxy method into expected interface method
Method* interface_method = proxy_method->FindOverriddenMethod();
CHECK(interface_method != NULL);
+ CHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
LOG(INFO) << "Interface method is " << PrettyMethod(interface_method, true);
// Box arguments
cur_arg = 0; // reset stack location to read to start
// reset index, will index into param type array which doesn't include the receiver
param_index = 0;
- ObjectArray<Class>* param_types = interface_method->GetJavaParameterTypes();
+ ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
CHECK(param_types != NULL);
// Check number of parameter types agrees with number from the Method - less 1 for the receiver.
CHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1);
@@ -1119,7 +1131,7 @@
Object* result_ref = self->DecodeJObject(result);
if (result_ref != NULL) {
JValue result_unboxed;
- UnboxPrimitive(env, result_ref, interface_method->GetReturnType(), result_unboxed);
+ UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed);
*reinterpret_cast<JValue*>(stack_args) = result_unboxed;
} else {
*reinterpret_cast<jobject*>(stack_args) = NULL;
@@ -1132,7 +1144,10 @@
if (!exception->IsCheckedException()) {
self->SetException(exception);
} else {
- ObjectArray<Class>* declared_exceptions = proxy_method->GetExceptionTypes();
+ // TODO: get the correct intersection of exceptions as passed to the class linker's create
+ // proxy code.
+ UNIMPLEMENTED(FATAL);
+ ObjectArray<Class>* declared_exceptions = NULL; // proxy_mh.GetExceptionTypes();
Class* exception_class = exception->GetClass();
bool declares_exception = false;
for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
diff --git a/src/stack.cc b/src/stack.cc
index 542ac47..9944ec3 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -18,9 +18,12 @@
#include "compiler.h"
#include "object.h"
+#include "object_utils.h"
#include "thread_list.h"
-int oatVRegOffsetFromMethod(art::Method* method, int reg);
+int oatVRegOffset(const art::DexFile::CodeItem* code_item,
+ uint32_t core_spills, uint32_t fp_spills,
+ size_t frame_size, int reg);
namespace art {
@@ -45,16 +48,31 @@
return *reinterpret_cast<uintptr_t*>(pc_addr);
}
-uint32_t Frame::GetVReg(Method* method, int vreg) const {
- DCHECK(method == GetMethod());
- int offset = oatVRegOffsetFromMethod(method, vreg);
+uint32_t Frame::GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills,
+ uint32_t fp_spills, size_t frame_size, int vreg) const {
+ int offset = oatVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
return *reinterpret_cast<uint32_t*>(vreg_addr);
}
-void Frame::SetVReg(Method* method, int vreg, uint32_t new_value) {
- DCHECK(method == GetMethod());
- int offset = oatVRegOffsetFromMethod(method, vreg);
+uint32_t Frame::GetVReg(Method* m, int vreg) const {
+ DCHECK(m == GetMethod());
+ const art::DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
+ DCHECK(code_item != NULL); // can't be NULL or how would we compile its instructions?
+ uint32_t core_spills = m->GetCoreSpillMask();
+ uint32_t fp_spills = m->GetFpSpillMask();
+ size_t frame_size = m->GetFrameSizeInBytes();
+ return GetVReg(code_item, core_spills, fp_spills, frame_size, vreg);
+}
+
+void Frame::SetVReg(Method* m, int vreg, uint32_t new_value) {
+ DCHECK(m == GetMethod());
+ const art::DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
+ DCHECK(code_item != NULL); // can't be NULL or how would we compile its instructions?
+ uint32_t core_spills = m->GetCoreSpillMask();
+ uint32_t fp_spills = m->GetFpSpillMask();
+ size_t frame_size = m->GetFrameSizeInBytes();
+ int offset = oatVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
*reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
}
diff --git a/src/stack.h b/src/stack.h
index a0f13d3..eee1d56 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -17,6 +17,7 @@
#ifndef ART_SRC_STACK_H_
#define ART_SRC_STACK_H_
+#include "dex_file.h"
#include "jni.h"
#include "macros.h"
@@ -54,7 +55,11 @@
uintptr_t LoadCalleeSave(int num) const;
- uint32_t GetVReg(Method* method, int vreg) const;
+
+ uint32_t GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills, uint32_t fp_spills,
+ size_t frame_size, int vreg) const;
+
+ uintptr_t GetVReg(Method* m, int vreg) const;
void SetVReg(Method* method, int vreg, uint32_t new_value);
Method** GetSP() const {
diff --git a/src/thread.cc b/src/thread.cc
index b6962f9..092c071 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -35,6 +35,7 @@
#include "jni_internal.h"
#include "monitor.h"
#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "runtime.h"
#include "runtime_support.h"
@@ -534,8 +535,9 @@
if (m->IsNative()) {
os << "(Native method)";
} else {
- SirtRef<String> source_file(c->GetSourceFile());
- os << "(" << (source_file.get() != NULL ? source_file->ToModifiedUtf8() : "unavailable")
+ mh.ChangeMethod(m);
+ const char* source_file(mh.GetDeclaringClassSourceFile());
+ os << "(" << (source_file != NULL ? source_file : "unavailable")
<< ":" << line_number << ")";
}
os << "\n";
@@ -545,6 +547,7 @@
Monitor::DescribeWait(os, thread);
}
}
+ MethodHelper mh;
Method* last_method;
int last_line_number;
int repetition_count;
@@ -1172,27 +1175,32 @@
*stack_depth = depth;
}
+ MethodHelper mh;
for (int32_t i = 0; i < depth; ++i) {
// Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
Method* method = down_cast<Method*>(method_trace->Get(i));
+ mh.ChangeMethod(method);
uint32_t native_pc = pc_trace->Get(i);
- Class* klass = method->GetDeclaringClass();
- std::string class_name(PrettyDescriptor(klass->GetDescriptor()));
- int32_t line_number = -1;
- DexCache* dex_cache = klass->GetDexCache();
- if (dex_cache != NULL) {
- const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(native_pc));
- }
+ int32_t line_number = mh.GetLineNumFromNativePC(native_pc);
// Allocate element, potentially triggering GC
// TODO: reuse class_name_object via Class::name_?
+ std::string class_name(PrettyDescriptor(mh.GetDeclaringClassDescriptor()));
SirtRef<String> class_name_object(String::AllocFromModifiedUtf8(class_name.c_str()));
if (class_name_object.get() == NULL) {
return NULL;
}
+ SirtRef<String> method_name_object(String::AllocFromModifiedUtf8(mh.GetName()));
+ if (method_name_object.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<String>
+ source_name_object(String::AllocFromModifiedUtf8(mh.GetDeclaringClassSourceFile()));
+ if (source_name_object.get() == NULL) {
+ return NULL;
+ }
StackTraceElement* obj = StackTraceElement::Alloc(class_name_object.get(),
- method->GetName(),
- klass->GetSourceFile(),
+ method_name_object.get(),
+ source_name_object.get(),
line_number);
if (obj == NULL) {
return NULL;
@@ -1247,7 +1255,7 @@
void Thread::ThrowOutOfMemoryError(Class* c, size_t byte_count) {
std::string msg(StringPrintf("Failed to allocate a %zd-byte %s", byte_count,
- PrettyDescriptor(c->GetDescriptor()).c_str()));
+ PrettyDescriptor(c).c_str()));
ThrowOutOfMemoryError(msg.c_str());
}
@@ -1432,8 +1440,14 @@
const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc));
CHECK(reg_bitmap != NULL);
const VmapTable vmap_table(m->GetVmapTableRaw());
+ const art::DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
+ DCHECK(code_item != NULL); // can't be NULL or how would we compile its instructions?
+ uint32_t core_spills = m->GetCoreSpillMask();
+ uint32_t fp_spills = m->GetFpSpillMask();
+ size_t frame_size = m->GetFrameSizeInBytes();
// For all dex registers in the bitmap
- size_t num_regs = std::min(map.RegWidth() * 8, static_cast<size_t>(m->NumRegisters()));
+ size_t num_regs = std::min(map.RegWidth() * 8,
+ static_cast<size_t>(code_item->registers_size_));
for (size_t reg = 0; reg < num_regs; ++reg) {
// Does this register hold a reference?
if (TestBitmap(reg, reg_bitmap)) {
@@ -1454,7 +1468,8 @@
spill_shifts--; // wind back one as we want the last match
ref = reinterpret_cast<Object*>(context_->GetGPR(spill_shifts));
} else {
- ref = reinterpret_cast<Object*>(frame.GetVReg(m, reg));
+ ref = reinterpret_cast<Object*>(frame.GetVReg(code_item, core_spills, fp_spills,
+ frame_size, reg));
}
if (ref != NULL) {
root_visitor_(ref, arg_);
diff --git a/src/utils.cc b/src/utils.cc
index 63787a8..943899d 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -13,6 +13,7 @@
#include "class_loader.h"
#include "file.h"
#include "object.h"
+#include "object_utils.h"
#include "os.h"
#if defined(HAVE_PRCTL)
@@ -68,6 +69,14 @@
return PrettyDescriptor(java_descriptor->ToModifiedUtf8());
}
+std::string PrettyDescriptor(const Class* klass) {
+ if (klass == NULL) {
+ return "null";
+ }
+ return PrettyDescriptor(ClassHelper(klass).GetDescriptor());
+
+}
+
std::string PrettyDescriptor(const std::string& descriptor) {
// Count the number of '['s to get the dimensionality.
const char* c = descriptor.c_str();
@@ -126,14 +135,15 @@
if (f == NULL) {
return "null";
}
+ FieldHelper fh(f);
std::string result;
if (with_type) {
- result += PrettyDescriptor(f->GetTypeDescriptor());
+ result += PrettyDescriptor(fh.GetTypeDescriptor());
result += ' ';
}
- result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(fh.GetDeclaringClassDescriptor());
result += '.';
- result += f->GetName()->ToModifiedUtf8();
+ result += fh.GetName();
return result;
}
@@ -141,14 +151,14 @@
if (m == NULL) {
return "null";
}
- Class* c = m->GetDeclaringClass();
- std::string result(PrettyDescriptor(c->GetDescriptor()));
+ MethodHelper mh(m);
+ std::string result(PrettyDescriptor(mh.GetDeclaringClassDescriptor()));
result += '.';
- result += m->GetName()->ToModifiedUtf8();
+ result += mh.GetName();
if (with_signature) {
// TODO: iterate over the signature's elements and pass them all to
// PrettyDescriptor? We'd need to pull out the return type specially, too.
- result += m->GetSignature()->ToModifiedUtf8();
+ result += mh.GetSignature();
}
return result;
}
@@ -173,9 +183,11 @@
if (obj->GetClass() == NULL) {
return "(raw)";
}
- std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
+ ClassHelper kh(obj->GetClass());
+ std::string result(PrettyDescriptor(kh.GetDescriptor()));
if (obj->IsClass()) {
- result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor()) + ">";
+ kh.ChangeClass(obj->AsClass());
+ result += "<" + PrettyDescriptor(kh.GetDescriptor()) + ">";
}
return result;
}
@@ -186,7 +198,7 @@
}
std::string result;
result += "java.lang.Class<";
- result += PrettyDescriptor(c->GetDescriptor());
+ result += PrettyDescriptor(c);
result += ">";
return result;
}
@@ -197,7 +209,7 @@
}
std::string result;
result += "java.lang.Class<";
- result += PrettyDescriptor(c->GetDescriptor());
+ result += PrettyDescriptor(c);
result += ",";
result += PrettyTypeOf(c->GetClassLoader());
// TODO: add an identifying hash value for the loader
@@ -254,16 +266,15 @@
}
std::string JniShortName(const Method* m) {
- Class* declaring_class = m->GetDeclaringClass();
-
- std::string class_name(declaring_class->GetDescriptor()->ToModifiedUtf8());
+ MethodHelper mh(m);
+ std::string class_name(mh.GetDeclaringClassDescriptor());
// Remove the leading 'L' and trailing ';'...
CHECK_EQ(class_name[0], 'L') << class_name;
CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
class_name.erase(0, 1);
class_name.erase(class_name.size() - 1, 1);
- std::string method_name(m->GetName()->ToModifiedUtf8());
+ std::string method_name(mh.GetName());
std::string short_name;
short_name += "Java_";
@@ -278,7 +289,7 @@
long_name += JniShortName(m);
long_name += "__";
- std::string signature(m->GetSignature()->ToModifiedUtf8());
+ std::string signature(MethodHelper(m).GetSignature());
signature.erase(0, 1);
signature.erase(signature.begin() + signature.find(')'), signature.end());
diff --git a/src/utils.h b/src/utils.h
index f5e0c49..5b3a036 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -159,6 +159,7 @@
std::string PrettyDescriptor(const String* descriptor);
std::string PrettyDescriptor(const std::string& descriptor);
std::string PrettyDescriptor(Primitive::Type type);
+std::string PrettyDescriptor(const Class* klass);
// Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
// "int a.b.C.f" (depending on the value of 'with_type').
diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc
index 77fe2ee..547f8c9 100644
--- a/test/ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/ReferenceMap/stack_walk_refmap_jni.cc
@@ -6,13 +6,14 @@
#include "class_linker.h"
#include "dex_verifier.h"
#include "object.h"
+#include "object_utils.h"
#include "thread.h"
#include "jni.h"
namespace art {
-#define IS_IN_REF_BITMAP(method, ref_bitmap, reg) \
- ( ((reg) < (method)->NumRegisters()) && \
+#define IS_IN_REF_BITMAP(mh, ref_bitmap, reg) \
+ ( ((reg) < mh.GetCodeItem()->registers_size_) && \
(( *((ref_bitmap) + (reg)/8) >> ((reg) % 8) ) & 0x01) )
#define CHECK_REGS_CONTAIN_REFS(...) \
@@ -20,7 +21,7 @@
int t[] = {__VA_ARGS__}; \
int t_size = sizeof(t) / sizeof(*t); \
for (int i = 0; i < t_size; ++i) \
- CHECK(IS_IN_REF_BITMAP(m, ref_bitmap, t[i])) \
+ CHECK(IS_IN_REF_BITMAP(mh, ref_bitmap, t[i])) \
<< "Error: Reg @ " << i << "-th argument is not in GC map"; \
} while(false)
@@ -52,7 +53,8 @@
art::verifier::DexVerifier::VerifyMethodAndDump(m);
}
const uint8_t* ref_bitmap = NULL;
- std::string m_name = m->GetName()->ToModifiedUtf8();
+ MethodHelper mh(m);
+ std::string m_name(mh.GetName());
// Given the method name and the number of times the method has been called,
// we know the Dex registers with live reference values. Assert that what we
diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc
index ad9c674..06b3d41 100644
--- a/test/StackWalk/stack_walk_jni.cc
+++ b/test/StackWalk/stack_walk_jni.cc
@@ -6,19 +6,20 @@
#include "class_linker.h"
#include "dex_verifier.h"
#include "object.h"
+#include "object_utils.h"
#include "jni.h"
namespace art {
-#define REG(method, reg_bitmap, reg) \
- ( ((reg) < (method)->NumRegisters()) && \
+#define REG(mh, reg_bitmap, reg) \
+ ( ((reg) < mh.GetCodeItem()->registers_size_) && \
(( *((reg_bitmap) + (reg)/8) >> ((reg) % 8) ) & 0x01) )
#define CHECK_REGS(...) do { \
int t[] = {__VA_ARGS__}; \
int t_size = sizeof(t) / sizeof(*t); \
for (int i = 0; i < t_size; ++i) \
- CHECK(REG(m, reg_bitmap, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \
+ CHECK(REG(mh, reg_bitmap, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \
} while(false)
static int gJava_StackWalk_refmap_calls = 0;
@@ -39,12 +40,13 @@
}
verifier::PcToReferenceMap map(m);
const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc));
- String* m_name = m->GetName();
+ MethodHelper mh(m);
+ StringPiece m_name(mh.GetName());
// Given the method name and the number of times the method has been called,
// we know the Dex registers with live reference values. Assert that what we
// find is what is expected.
- if (m_name->Equals("f")) {
+ if (m_name == "f") {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(1U, m->ToDexPC(pc));
CHECK_REGS(1);
@@ -53,7 +55,7 @@
CHECK_EQ(5U, m->ToDexPC(pc));
CHECK_REGS(1);
}
- } else if (m_name->Equals("g")) {
+ } else if (m_name == "g") {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(0xcU, m->ToDexPC(pc));
CHECK_REGS(0, 2); // Note that v1 is not in the minimal root set
@@ -62,7 +64,7 @@
CHECK_EQ(0xcU, m->ToDexPC(pc));
CHECK_REGS(0, 2);
}
- } else if (m_name->Equals("shlemiel")) {
+ } else if (m_name == "shlemiel") {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(0x380U, m->ToDexPC(pc));
CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);