Make ResolveField not rely on Field::GetType resolution
Change-Id: I10f4a874809ac9db2cd54e200cf10eb7c8979fce
diff --git a/src/check_jni.cc b/src/check_jni.cc
index c740291..15cc161 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -237,12 +237,12 @@
if (f == NULL) {
return;
}
- Class* f_type = f->GetType();
// check invariant that all jfieldIDs have resolved types
- DCHECK(f_type != NULL);
+ DCHECK(f->GetType() != NULL);
Class* c = o->GetClass();
- if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f_type) == NULL) {
- LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f) << " not valid for an object of class " << PrettyTypeOf(o);
+ if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f->GetTypeDescriptor()) == NULL) {
+ LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f)
+ << " not valid for an object of class " << PrettyTypeOf(o);
JniAbort();
}
}
diff --git a/src/class_linker.cc b/src/class_linker.cc
index de35d33..afb6721 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -284,14 +284,14 @@
SetClassRoot(kJavaLangString, java_lang_String.get());
// Setup the primitive type classes.
- SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
- SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Class::kPrimByte));
- SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Class::kPrimShort));
- SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Class::kPrimInt));
- SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Class::kPrimLong));
- SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Class::kPrimFloat));
- SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Class::kPrimDouble));
- SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Class::kPrimVoid));
+ SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Primitive::kPrimBoolean));
+ SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Primitive::kPrimByte));
+ SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Primitive::kPrimShort));
+ SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Primitive::kPrimInt));
+ SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Primitive::kPrimLong));
+ SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Primitive::kPrimFloat));
+ SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Primitive::kPrimDouble));
+ SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
// Create array interface entries to populate once we can load system classes
array_interfaces_ = AllocClassArray(2);
@@ -343,7 +343,7 @@
// now we can use FindSystemClass
// run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class.get(), "C", Class::kPrimChar);
+ InitializePrimitiveClass(char_class.get(), "C", Primitive::kPrimChar);
SetClassRoot(kPrimitiveChar, char_class.get()); // needs descriptor
// Object and String need to be rerun through FindSystemClass to finish init
@@ -875,7 +875,7 @@
Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
DCHECK_GE(class_size, sizeof(Class));
SirtRef<Class> klass(Heap::AllocObject(java_lang_Class, class_size)->AsClass());
- klass->SetPrimitiveType(Class::kPrimNot); // default to not being primitive
+ klass->SetPrimitiveType(Primitive::kPrimNot); // default to not being primitive
klass->SetClassSize(class_size);
return klass.get();
}
@@ -1062,7 +1062,7 @@
DexFile::Field dex_field;
dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
- const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
char c = descriptor[0];
if (c == 'L' || c == '[') {
num_ref++;
@@ -1138,7 +1138,7 @@
CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
klass->SetAccessFlags(access_flags);
klass->SetClassLoader(class_loader);
- DCHECK(klass->GetPrimitiveType() == Class::kPrimNot);
+ DCHECK(klass->GetPrimitiveType() == Primitive::kPrimNot);
klass->SetStatus(Class::kStatusIdx);
klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
@@ -1264,7 +1264,7 @@
// In order to access primitive types using GetTypeDuringLinking we need to
// ensure they are resolved into the dex cache
- const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+ 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());
@@ -1430,7 +1430,7 @@
Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class,
const char* descriptor,
- Class::PrimitiveType type) {
+ Primitive::Type type) {
// TODO: deduce one argument from the other
CHECK(primitive_class != NULL);
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
@@ -1532,7 +1532,7 @@
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
new_class->SetVTable(java_lang_Object->GetVTable());
- new_class->SetPrimitiveType(Class::kPrimNot);
+ new_class->SetPrimitiveType(Primitive::kPrimNot);
new_class->SetClassLoader(component_type->GetClassLoader());
new_class->SetStatus(Class::kStatusInitialized);
// don't need to set new_class->SetObjectSize(..)
@@ -1582,25 +1582,27 @@
}
Class* ClassLinker::FindPrimitiveClass(char type) {
- switch (type) {
- case 'B':
+ switch (Primitive::GetType(type)) {
+ case Primitive::kPrimByte:
return GetClassRoot(kPrimitiveByte);
- case 'C':
+ case Primitive::kPrimChar:
return GetClassRoot(kPrimitiveChar);
- case 'D':
+ case Primitive::kPrimDouble:
return GetClassRoot(kPrimitiveDouble);
- case 'F':
+ case Primitive::kPrimFloat:
return GetClassRoot(kPrimitiveFloat);
- case 'I':
+ case Primitive::kPrimInt:
return GetClassRoot(kPrimitiveInt);
- case 'J':
+ case Primitive::kPrimLong:
return GetClassRoot(kPrimitiveLong);
- case 'S':
+ case Primitive::kPrimShort:
return GetClassRoot(kPrimitiveShort);
- case 'Z':
+ case Primitive::kPrimBoolean:
return GetClassRoot(kPrimitiveBoolean);
- case 'V':
+ case Primitive::kPrimVoid:
return GetClassRoot(kPrimitiveVoid);
+ case Primitive::kPrimNot:
+ break;
}
std::string printable_type(PrintableChar(type));
ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str());
@@ -2419,12 +2421,12 @@
struct LinkFieldsComparator {
bool operator()(const Field* field1, const Field* field2) {
// First come reference fields, then 64-bit, and finally 32-bit
- const Class* type1 = field1->GetTypeDuringLinking();
- const Class* type2 = field2->GetTypeDuringLinking();
- bool isPrimitive1 = type1 != NULL && type1->IsPrimitive();
- bool isPrimitive2 = type2 != NULL && type2->IsPrimitive();
- bool is64bit1 = isPrimitive1 && (type1->IsPrimitiveLong() || type1->IsPrimitiveDouble());
- bool is64bit2 = isPrimitive2 && (type2->IsPrimitiveLong() || type2->IsPrimitiveDouble());
+ Primitive::Type type1 = field1->GetPrimitiveType();
+ Primitive::Type type2 = field2->GetPrimitiveType();
+ bool isPrimitive1 = type1 != Primitive::kPrimNot;
+ bool isPrimitive2 = type2 != Primitive::kPrimNot;
+ bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
+ bool is64bit2 = isPrimitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
int order1 = (!isPrimitive1 ? 0 : (is64bit1 ? 1 : 2));
int order2 = (!isPrimitive2 ? 0 : (is64bit2 ? 1 : 2));
if (order1 != order2) {
@@ -2477,9 +2479,8 @@
size_t num_reference_fields = 0;
for (; current_field < num_fields; current_field++) {
Field* field = grouped_and_sorted_fields.front();
- const Class* type = field->GetTypeDuringLinking();
- // if a field's type at this point is NULL it isn't primitive
- bool isPrimitive = type != NULL && type->IsPrimitive();
+ Primitive::Type type = field->GetPrimitiveType();
+ bool isPrimitive = type != Primitive::kPrimNot;
if (isPrimitive) {
break; // past last reference, move on to the next phase
}
@@ -2496,10 +2497,9 @@
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];
- const Class* type = field->GetTypeDuringLinking();
- CHECK(type != NULL); // should only be working on primitive types
- DCHECK(type->IsPrimitive());
- if (type->IsPrimitiveLong() || type->IsPrimitiveDouble()) {
+ Primitive::Type type = field->GetPrimitiveType();
+ CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
+ if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
continue;
}
fields->Set(current_field++, field);
@@ -2518,13 +2518,12 @@
while (!grouped_and_sorted_fields.empty()) {
Field* field = grouped_and_sorted_fields.front();
grouped_and_sorted_fields.pop_front();
- const Class* type = field->GetTypeDuringLinking();
- CHECK(type != NULL); // should only be working on primitive types
- DCHECK(type->IsPrimitive());
+ Primitive::Type type = field->GetPrimitiveType();
+ CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
fields->Set(current_field, field);
field->SetOffset(field_offset);
field_offset = MemberOffset(field_offset.Uint32Value() +
- ((type->IsPrimitiveLong() || type->IsPrimitiveDouble())
+ ((type == Primitive::kPrimLong || type == Primitive::kPrimDouble)
? sizeof(uint64_t)
: sizeof(uint32_t)));
current_field++;
@@ -2551,8 +2550,8 @@
<< " field=" << PrettyField(field)
<< " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
}
- const Class* type = field->GetTypeDuringLinking();
- bool is_primitive = (type != NULL && type->IsPrimitive());
+ Primitive::Type type = field->GetPrimitiveType();
+ bool is_primitive = type != Primitive::kPrimNot;
if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
is_primitive = true; // We lied above, so we have to expect a lie here.
}
@@ -2727,23 +2726,18 @@
return NULL;
}
- const char* name = dex_file.dexStringById(field_id.name_idx_);
- Class* field_type = ResolveType(dex_file, field_id.type_idx_, dex_cache, class_loader);
- if (field_type == NULL) {
- // TODO: LinkageError?
- UNIMPLEMENTED(WARNING) << "Failed to resolve type of field " << name
- << " in " << PrettyClass(klass);
- return NULL;
-}
+ const char* name = dex_file.GetFieldName(field_id);
+ const char* type = dex_file.GetFieldTypeDescriptor(field_id);
if (is_static) {
- resolved = klass->FindStaticField(name, field_type);
+ resolved = klass->FindStaticField(name, type);
} else {
- resolved = klass->FindInstanceField(name, field_type);
+ resolved = klass->FindInstanceField(name, type);
}
if (resolved != NULL) {
dex_cache->SetResolvedField(field_idx, resolved);
} else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ DCHECK(Thread::Current()->IsExceptionPending())
+ << PrettyClass(klass) << " " << name << " " << type << " " << is_static;
}
return resolved;
}
diff --git a/src/class_linker.h b/src/class_linker.h
index dd78174..e2c5921 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -265,13 +265,12 @@
CodeAndDirectMethods* AllocCodeAndDirectMethods(size_t length);
InterfaceEntry* AllocInterfaceEntry(Class* interface);
- Class* CreatePrimitiveClass(const char* descriptor,
- Class::PrimitiveType type) {
+ Class* CreatePrimitiveClass(const char* descriptor, Primitive::Type type) {
return InitializePrimitiveClass(AllocClass(sizeof(Class)), descriptor, type);
}
Class* InitializePrimitiveClass(Class* primitive_class,
const char* descriptor,
- Class::PrimitiveType type);
+ Primitive::Type type);
Class* CreateArrayClass(const std::string& descriptor,
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 1b43825..54da19f 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -235,6 +235,7 @@
EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
+ ASSERT_TRUE(!field->IsPrimitiveType());
Class* field_type = field->GetType();
ASSERT_TRUE(field_type != NULL);
ASSERT_TRUE(!field_type->IsPrimitive());
@@ -243,7 +244,7 @@
Field* field = klass->GetInstanceField(i);
Class* field_type = field->GetType();
ASSERT_TRUE(field_type != NULL);
- if (!field_type->IsPrimitive()) {
+ if (!field->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");
@@ -830,49 +831,49 @@
EXPECT_EQ(9U, statics->NumStaticFields());
- Field* s0 = statics->FindStaticField("s0", class_linker_->FindClass("Z", class_loader.get()));
+ Field* s0 = statics->FindStaticField("s0", "Z");
EXPECT_TRUE(s0->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Field;"));
- EXPECT_TRUE(s0->GetType()->IsPrimitiveBoolean());
+ EXPECT_TRUE(s0->GetPrimitiveType() == Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(NULL));
s0->SetBoolean(NULL, false);
- Field* s1 = statics->FindStaticField("s1", class_linker_->FindClass("B", class_loader.get()));
- EXPECT_TRUE(s1->GetType()->IsPrimitiveByte());
+ Field* s1 = statics->FindStaticField("s1", "B");
+ EXPECT_TRUE(s1->GetPrimitiveType() == Primitive::kPrimByte);
EXPECT_EQ(5, s1->GetByte(NULL));
s1->SetByte(NULL, 6);
- Field* s2 = statics->FindStaticField("s2", class_linker_->FindClass("C", class_loader.get()));
- EXPECT_TRUE(s2->GetType()->IsPrimitiveChar());
+ Field* s2 = statics->FindStaticField("s2", "C");
+ EXPECT_TRUE(s2->GetPrimitiveType() == Primitive::kPrimChar);
EXPECT_EQ('a', s2->GetChar(NULL));
s2->SetChar(NULL, 'b');
- Field* s3 = statics->FindStaticField("s3", class_linker_->FindClass("S", class_loader.get()));
- EXPECT_TRUE(s3->GetType()->IsPrimitiveShort());
+ Field* s3 = statics->FindStaticField("s3", "S");
+ EXPECT_TRUE(s3->GetPrimitiveType() == Primitive::kPrimShort);
EXPECT_EQ(-536, s3->GetShort(NULL));
s3->SetShort(NULL, -535);
- Field* s4 = statics->FindStaticField("s4", class_linker_->FindClass("I", class_loader.get()));
- EXPECT_TRUE(s4->GetType()->IsPrimitiveInt());
+ Field* s4 = statics->FindStaticField("s4", "I");
+ EXPECT_TRUE(s4->GetPrimitiveType() == Primitive::kPrimInt);
EXPECT_EQ(2000000000, s4->GetInt(NULL));
s4->SetInt(NULL, 2000000001);
- Field* s5 = statics->FindStaticField("s5", class_linker_->FindClass("J", class_loader.get()));
- EXPECT_TRUE(s5->GetType()->IsPrimitiveLong());
+ Field* s5 = statics->FindStaticField("s5", "J");
+ EXPECT_TRUE(s5->GetPrimitiveType() == Primitive::kPrimLong);
EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL));
s5->SetLong(NULL, 0x34567890abcdef12LL);
- Field* s6 = statics->FindStaticField("s6", class_linker_->FindClass("F", class_loader.get()));
- EXPECT_TRUE(s6->GetType()->IsPrimitiveFloat());
+ Field* s6 = statics->FindStaticField("s6", "F");
+ EXPECT_TRUE(s6->GetPrimitiveType() == Primitive::kPrimFloat);
EXPECT_EQ(0.5, s6->GetFloat(NULL));
s6->SetFloat(NULL, 0.75);
- Field* s7 = statics->FindStaticField("s7", class_linker_->FindClass("D", class_loader.get()));
- EXPECT_TRUE(s7->GetType()->IsPrimitiveDouble());
+ Field* s7 = statics->FindStaticField("s7", "D");
+ EXPECT_TRUE(s7->GetPrimitiveType() == Primitive::kPrimDouble);
EXPECT_EQ(16777217, s7->GetDouble(NULL));
s7->SetDouble(NULL, 16777219);
- Field* s8 = statics->FindStaticField("s8", class_linker_->FindClass("Ljava/lang/String;", class_loader.get()));
- EXPECT_FALSE(s8->GetType()->IsPrimitive());
+ Field* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
+ EXPECT_TRUE(s8->GetPrimitiveType() == Primitive::kPrimNot);
EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android"));
s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
diff --git a/src/common_test.h b/src/common_test.h
index 3f56aab..928cb51 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -288,7 +288,7 @@
const StringPiece& field_name) {
for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
- if (class_descriptor == dex_file.GetFieldClassDescriptor(field_id)
+ if (class_descriptor == dex_file.GetFieldDeclaringClassDescriptor(field_id)
&& field_name == dex_file.GetFieldName(field_id)) {
return i;
}
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 35da6f2..d1b377a 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -91,18 +91,18 @@
for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Method* method = dex_cache->GetResolvedMethod(i);
EXPECT_TRUE(method != NULL) << "method_idx=" << i
- << " " << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+ << " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
EXPECT_TRUE(method->GetCode() != NULL) << "method_idx=" << i
<< " "
- << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+ << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
}
EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
Field* field = dex_cache->GetResolvedField(i);
EXPECT_TRUE(field != NULL) << "field_idx=" << i
- << " " << dex->GetFieldClassDescriptor(dex->GetFieldId(i))
+ << " " << dex->GetFieldDeclaringClassDescriptor(dex->GetFieldId(i))
<< " " << dex->GetFieldName(dex->GetFieldId(i));
}
diff --git a/src/dex_file.h b/src/dex_file.h
index c30c5ca..3acd79f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -425,19 +425,25 @@
return dexStringById(type_id.descriptor_idx_);
}
- // Returns the class descriptor string of a field id.
- const char* GetFieldClassDescriptor(const FieldId& field_id) const {
+ // Returns the declaring class descriptor string of a field id.
+ const char* GetFieldDeclaringClassDescriptor(const FieldId& field_id) const {
const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
return GetTypeDescriptor(type_id);
}
+ // Returns the class descriptor string of a field id.
+ const char* GetFieldTypeDescriptor(const FieldId& field_id) const {
+ const DexFile::TypeId& type_id = GetTypeId(field_id.type_idx_);
+ return GetTypeDescriptor(type_id);
+ }
+
// Returns the name of a field id.
const char* GetFieldName(const FieldId& field_id) const {
return dexStringById(field_id.name_idx_);
}
- // Returns the class descriptor string of a method id.
- const char* GetMethodClassDescriptor(const MethodId& method_id) const {
+ // Returns the declaring class descriptor string of a method id.
+ const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
return GetTypeDescriptor(type_id);
}
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index da7f63f..e4d9f84 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -289,18 +289,18 @@
}
}
-static RegType::Type RegTypeFromPrimitiveType(Class::PrimitiveType prim_type) {
+static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
switch (prim_type) {
- case Class::kPrimBoolean: return RegType::kRegTypeBoolean;
- case Class::kPrimByte: return RegType::kRegTypeByte;
- case Class::kPrimShort: return RegType::kRegTypeShort;
- case Class::kPrimChar: return RegType::kRegTypeChar;
- case Class::kPrimInt: return RegType::kRegTypeInteger;
- case Class::kPrimLong: return RegType::kRegTypeLongLo;
- case Class::kPrimFloat: return RegType::kRegTypeFloat;
- case Class::kPrimDouble: return RegType::kRegTypeDoubleLo;
- case Class::kPrimVoid:
- default: return RegType::kRegTypeUnknown;
+ case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
+ case Primitive::kPrimByte: return RegType::kRegTypeByte;
+ case Primitive::kPrimShort: return RegType::kRegTypeShort;
+ case Primitive::kPrimChar: return RegType::kRegTypeChar;
+ case Primitive::kPrimInt: return RegType::kRegTypeInteger;
+ case Primitive::kPrimLong: return RegType::kRegTypeLongLo;
+ case Primitive::kPrimFloat: return RegType::kRegTypeFloat;
+ case Primitive::kPrimDouble: return RegType::kRegTypeDoubleLo;
+ case Primitive::kPrimVoid:
+ default: return RegType::kRegTypeUnknown;
}
}
@@ -2134,7 +2134,7 @@
if (array_data[0] != Instruction::kArrayDataSignature) {
Fail(VERIFY_ERROR_GENERIC) << "invalid magic for array-data";
} else {
- size_t elem_width = component_type->PrimitiveSize();
+ size_t elem_width = Primitive::ComponentSize(component_type->GetPrimitiveType());
// Since we don't compress the data in Dex, expect to see equal width of data stored
// in the table and expected from the array class.
if (array_data[1] != elem_width) {
@@ -2952,7 +2952,7 @@
DCHECK(failure_ != VERIFY_ERROR_NONE);
return NULL;
}
- const char* name = dex_file_->dexStringById(method_id.name_idx_);
+ const char* name = dex_file_->GetMethodName(method_id);
std::string signature(dex_file_->CreateMethodDescriptor(method_id.proto_idx_, NULL));
if (is_direct) {
res_method = klass->FindDirectMethod(name, signature);
@@ -2989,7 +2989,7 @@
const DexFile::MethodId& method_id = dex_file_->GetMethodId(dec_insn.vB_);
const char* method_name = dex_file_->GetMethodName(method_id);
std::string method_signature = dex_file_->GetMethodSignature(method_id);
- const char* class_descriptor = dex_file_->GetMethodClassDescriptor(method_id);
+ const char* class_descriptor = dex_file_->GetMethodDeclaringClassDescriptor(method_id);
Fail(VERIFY_ERROR_GENERIC) << "unable to resolve method " << dec_insn.vB_ << ": "
<< class_descriptor << "." << method_name << " " << method_signature;
return NULL;
@@ -3236,7 +3236,7 @@
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
Fail(VERIFY_ERROR_NO_FIELD) << "unable to resolve static field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
- << dex_file_->GetFieldClassDescriptor(field_id);
+ << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
return NULL;
@@ -3357,7 +3357,7 @@
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
Fail(VERIFY_ERROR_NO_FIELD) << "unable to resolve instance field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
- << dex_file_->GetFieldClassDescriptor(field_id);
+ << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
return NULL;
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 3a614d5..0d86eb5 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -35,7 +35,7 @@
/*
* RegType holds information about the type of data held in a register. For most types it's a simple
- * enum. For reference types it holds a pointer to the ClassObject, and for uninitialized references
+ * enum. For reference types it holds a pointer to the Class*, and for uninitialized references
* it holds an index into the UninitInstanceMap.
*/
class RegType {
diff --git a/src/heap.cc b/src/heap.cc
index 01ba840..bd6d009 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -16,6 +16,10 @@
namespace art {
+bool Heap::is_verbose_heap_ = false;
+
+bool Heap::is_verbose_gc_ = false;
+
std::vector<Space*> Heap::spaces_;
Space* Heap::alloc_space_ = NULL;
@@ -58,10 +62,14 @@
}
};
-void Heap::Init(size_t initial_size, size_t maximum_size,
+void Heap::Init(bool is_verbose_heap, bool is_verbose_gc,
+ size_t initial_size, size_t maximum_size,
const std::vector<std::string>& image_file_names) {
+ is_verbose_heap_ = is_verbose_heap;
+ is_verbose_gc_ = is_verbose_gc;
+
const Runtime* runtime = Runtime::Current();
- if (runtime->IsVerboseStartup()) {
+ if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::Init entering";
}
@@ -132,7 +140,7 @@
// make it clear that you can't use locks during heap initialization.
lock_ = new Mutex("Heap lock");
- if (runtime->IsVerboseStartup()) {
+ if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::Init exiting";
}
}
@@ -283,7 +291,7 @@
void Heap::RecordImageAllocations(Space* space) {
const Runtime* runtime = Runtime::Current();
- if (runtime->IsVerboseStartup()) {
+ if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::RecordImageAllocations entering";
}
DCHECK(!Runtime::Current()->IsStarted());
@@ -296,7 +304,7 @@
live_bitmap_->Set(obj);
current += RoundUp(obj->SizeOf(), kObjectAlignment);
}
- if (runtime->IsVerboseStartup()) {
+ if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::RecordImageAllocations exiting";
}
}
@@ -344,14 +352,12 @@
++Runtime::Current()->GetStats()->gc_for_alloc_count;
++Thread::Current()->GetStats()->gc_for_alloc_count;
}
- LOG(INFO) << "GC_FOR_ALLOC: AllocWithoutGrowth: TODO: test";
CollectGarbageInternal();
ptr = space->AllocWithoutGrowth(size);
if (ptr != NULL) {
return ptr;
}
- LOG(INFO) << "GC_FOR_ALLOC: AllocWithGrowth: TODO: test";
// Even that didn't work; this is an exceptional state.
// Try harder, growing the heap if necessary.
ptr = space->AllocWithGrowth(size);
@@ -361,8 +367,10 @@
// OLD-TODO: may want to grow a little bit more so that the amount of
// free space is equal to the old free space + the
// utilization slop for the new allocation.
- LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
- << "for " << size << "-byte allocation";
+ if (is_verbose_gc_) {
+ LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
+ << "for " << size << "-byte allocation";
+ }
return ptr;
}
@@ -373,8 +381,10 @@
// cleared before throwing an OOME.
// OLD-TODO: wait for the finalizers from the previous GC to finish
- LOG(INFO) << "Forcing collection of SoftReferences for "
- << size << "-byte allocation";
+ if (is_verbose_gc_) {
+ LOG(INFO) << "Forcing collection of SoftReferences for "
+ << size << "-byte allocation";
+ }
CollectGarbageInternal();
ptr = space->AllocWithGrowth(size);
if (ptr != NULL) {
@@ -512,11 +522,15 @@
size_t percentFree = 100 - static_cast<size_t>(100.0f * float(num_bytes_allocated_) / footprint);
uint32_t duration = (t1 - t0)/1000/1000;
- LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
- << percentFree << "% free "
- << (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, "
- << "paused " << duration << "ms";
- timings.Dump();
+ if (is_verbose_gc_) {
+ LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
+ << percentFree << "% free "
+ << (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, "
+ << "paused " << duration << "ms";
+ }
+ if (is_verbose_heap_) {
+ timings.Dump();
+ }
}
void Heap::WaitForConcurrentGcToComplete() {
@@ -547,8 +561,10 @@
void Heap::SetIdealFootprint(size_t max_allowed_footprint)
{
if (max_allowed_footprint > Heap::maximum_size_) {
- LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
- << " to " << Heap::maximum_size_;
+ if (is_verbose_gc_) {
+ LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
+ << " to " << Heap::maximum_size_;
+ }
max_allowed_footprint = Heap::maximum_size_;
}
diff --git a/src/heap.h b/src/heap.h
index 433bf6a..9e21272 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -45,11 +45,20 @@
// Create a heap with the requested sizes. The possible empty
// image_file_names names specify Spaces to load based on
// ImageWriter output.
- static void Init(size_t starting_size, size_t maximum_size,
+ static void Init(bool is_verbose_heap, bool is_verbose_gc,
+ size_t starting_size, size_t maximum_size,
const std::vector<std::string>& image_file_names);
static void Destroy();
+ static bool IsVerboseHeap() {
+ return is_verbose_heap_;
+ }
+
+ static bool IsVerboseGc() {
+ return is_verbose_gc_;
+ }
+
// Allocates and initializes storage for an object instance.
static Object* AllocObject(Class* klass, size_t num_bytes);
@@ -187,6 +196,10 @@
static Mutex* lock_;
+ static bool is_verbose_heap_;
+
+ static bool is_verbose_gc_;
+
static std::vector<Space*> spaces_;
// default Space for allocations
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index 7d43b2e..a2f09e7 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -30,39 +30,39 @@
}
bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
- switch (f->GetType()->GetPrimitiveType()) {
- case Class::kPrimBoolean:
+ switch (f->GetPrimitiveType()) {
+ case Primitive::kPrimBoolean:
value.z = f->GetBoolean(o);
return true;
- case Class::kPrimByte:
+ case Primitive::kPrimByte:
value.b = f->GetByte(o);
return true;
- case Class::kPrimChar:
+ case Primitive::kPrimChar:
value.c = f->GetChar(o);
return true;
- case Class::kPrimDouble:
+ case Primitive::kPrimDouble:
value.d = f->GetDouble(o);
return true;
- case Class::kPrimFloat:
+ case Primitive::kPrimFloat:
value.f = f->GetFloat(o);
return true;
- case Class::kPrimInt:
+ case Primitive::kPrimInt:
value.i = f->GetInt(o);
return true;
- case Class::kPrimLong:
+ case Primitive::kPrimLong:
value.j = f->GetLong(o);
return true;
- case Class::kPrimShort:
+ case Primitive::kPrimShort:
value.s = f->GetShort(o);
return true;
- case Class::kPrimNot:
+ case Primitive::kPrimNot:
if (allow_references) {
value.l = f->GetObject(o);
return true;
}
// Else break to report an error.
break;
- case Class::kPrimVoid:
+ case Primitive::kPrimVoid:
// Never okay.
break;
}
@@ -101,7 +101,8 @@
// Widen it if necessary (and possible).
JValue wide_value;
Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
- if (!ConvertPrimitiveValue(f->GetType(), dst_type, field_value, wide_value)) {
+ if (!ConvertPrimitiveValue(f->GetPrimitiveType(), dst_type->GetPrimitiveType(),
+ field_value, wide_value)) {
return JValue();
}
return wide_value;
@@ -140,38 +141,38 @@
}
void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_references) {
- switch (f->GetType()->GetPrimitiveType()) {
- case Class::kPrimBoolean:
+ switch (f->GetPrimitiveType()) {
+ case Primitive::kPrimBoolean:
f->SetBoolean(o, new_value.z);
break;
- case Class::kPrimByte:
+ case Primitive::kPrimByte:
f->SetByte(o, new_value.b);
break;
- case Class::kPrimChar:
+ case Primitive::kPrimChar:
f->SetChar(o, new_value.c);
break;
- case Class::kPrimDouble:
+ case Primitive::kPrimDouble:
f->SetDouble(o, new_value.d);
break;
- case Class::kPrimFloat:
+ case Primitive::kPrimFloat:
f->SetFloat(o, new_value.f);
break;
- case Class::kPrimInt:
+ case Primitive::kPrimInt:
f->SetInt(o, new_value.i);
break;
- case Class::kPrimLong:
+ case Primitive::kPrimLong:
f->SetLong(o, new_value.j);
break;
- case Class::kPrimShort:
+ case Primitive::kPrimShort:
f->SetShort(o, new_value.s);
break;
- case Class::kPrimNot:
+ case Primitive::kPrimNot:
if (allow_references) {
f->SetObject(o, new_value.l);
break;
}
// Else fall through to report an error.
- case Class::kPrimVoid:
+ case Primitive::kPrimVoid:
// Never okay.
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"Not a primitive field: %s", PrettyField(f).c_str());
@@ -195,7 +196,8 @@
// Widen the value if necessary (and possible).
JValue wide_value;
Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
- if (!ConvertPrimitiveValue(src_type, f->GetType(), new_value, wide_value)) {
+ if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), f->GetPrimitiveType(),
+ new_value, wide_value)) {
return;
}
@@ -282,7 +284,7 @@
if (!GetFieldValue(o, f, value, true)) {
return NULL;
}
- BoxPrimitive(env, f->GetType(), value);
+ BoxPrimitive(env, f->GetPrimitiveType(), value);
return AddLocalReference<jobject>(env, value.l);
}
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0ece455..0982f83 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -336,10 +336,11 @@
"\"%s\" or its superclasses", sig, name, class_descriptor.c_str());
return NULL;
}
+ std::string field_type_descriptor = field_type->GetDescriptor()->ToModifiedUtf8();
if (is_static) {
- field = c->FindStaticField(name, field_type);
+ field = c->FindStaticField(name, field_type_descriptor);
} else {
- field = c->FindInstanceField(name, field_type);
+ field = c->FindInstanceField(name, field_type_descriptor);
}
if (field == NULL) {
std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index d70d10d..4cc6b22 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -110,7 +110,9 @@
finger_ = reinterpret_cast<Object*>(~0);
ProcessMarkStack();
timings.AddSplit("ProcessMarkStack");
- timings.Dump();
+ if (Heap::IsVerboseHeap()) {
+ timings.Dump();
+ }
}
void MarkSweep::ReMarkRoots() {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 73b92a0..02aecfc 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -328,9 +328,6 @@
StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
} else if (obj->IsField()) {
Field* field = obj->AsField();
- Class* type = field->GetType();
- std::string type_string;
- type_string += (type == NULL) ? "<UNKNOWN>" : type->GetDescriptor()->ToModifiedUtf8();
StringAppendF(&summary, "FIELD %s", PrettyField(field).c_str());
} else if (obj->IsArrayInstance()) {
StringAppendF(&summary, "ARRAY %d", obj->AsArray()->GetLength());
diff --git a/src/object.cc b/src/object.cc
index ab95885..91328aa 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -102,6 +102,31 @@
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.dexStringByTypeIdx(GetTypeIdx());
+ DCHECK(descriptor != NULL);
+ return descriptor;
+}
+
Class* Field::GetType() const {
if (type_ == NULL) {
type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
@@ -120,11 +145,11 @@
}
void Field::InitJavaFieldsLocked() {
- GetType(); // Sets type_ as a side-effect. May throw.
+ GetType(); // Resolves type as a side-effect. May throw.
}
uint32_t Field::Get32(const Object* object) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -132,7 +157,7 @@
}
void Field::Set32(Object* object, uint32_t new_value) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -140,7 +165,7 @@
}
uint64_t Field::Get64(const Object* object) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -148,7 +173,7 @@
}
void Field::Set64(Object* object, uint64_t new_value) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -156,7 +181,7 @@
}
Object* Field::GetObj(const Object* object) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -164,7 +189,7 @@
}
void Field::SetObj(Object* object, const Object* new_value) const {
- CHECK((object == NULL) == IsStatic());
+ CHECK((object == NULL) == IsStatic()) << PrettyField(this);
if (IsStatic()) {
object = declaring_class_;
}
@@ -172,100 +197,100 @@
}
bool Field::GetBoolean(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveBoolean());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
return Get32(object);
}
void Field::SetBoolean(Object* object, bool z) const {
- DCHECK(GetType()->IsPrimitiveBoolean());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
Set32(object, z);
}
int8_t Field::GetByte(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveByte());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
return Get32(object);
}
void Field::SetByte(Object* object, int8_t b) const {
- DCHECK(GetType()->IsPrimitiveByte());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
Set32(object, b);
}
uint16_t Field::GetChar(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveChar());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
return Get32(object);
}
void Field::SetChar(Object* object, uint16_t c) const {
- DCHECK(GetType()->IsPrimitiveChar());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
Set32(object, c);
}
int16_t Field::GetShort(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveShort());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
return Get32(object);
}
void Field::SetShort(Object* object, int16_t s) const {
- DCHECK(GetType()->IsPrimitiveShort());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
Set32(object, s);
}
int32_t Field::GetInt(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveInt());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
return Get32(object);
}
void Field::SetInt(Object* object, int32_t i) const {
- DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this);
+ DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
Set32(object, i);
}
int64_t Field::GetLong(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveLong());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
return Get64(object);
}
void Field::SetLong(Object* object, int64_t j) const {
- DCHECK(GetType()->IsPrimitiveLong());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
Set64(object, j);
}
float Field::GetFloat(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveFloat());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
JValue float_bits;
float_bits.i = Get32(object);
return float_bits.f;
}
void Field::SetFloat(Object* object, float f) const {
- DCHECK(GetType()->IsPrimitiveFloat());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
JValue float_bits;
float_bits.f = f;
Set32(object, float_bits.i);
}
double Field::GetDouble(const Object* object) const {
- DCHECK(GetType()->IsPrimitiveDouble());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
JValue double_bits;
double_bits.j = Get64(object);
return double_bits.d;
}
void Field::SetDouble(Object* object, double d) const {
- DCHECK(GetType()->IsPrimitiveDouble());
+ DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
JValue double_bits;
double_bits.d = d;
Set64(object, double_bits.j);
}
Object* Field::GetObject(const Object* object) const {
- CHECK(!GetType()->IsPrimitive());
+ CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
return GetObj(object);
}
void Field::SetObject(Object* object, const Object* l) const {
- CHECK(!GetType()->IsPrimitive());
+ CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
SetObj(object, l);
}
@@ -828,44 +853,6 @@
new_reference_offsets, false);
}
-size_t Class::PrimitiveSize() const {
- switch (GetPrimitiveType()) {
- case kPrimBoolean:
- case kPrimByte: return 1;
- case kPrimChar:
- case kPrimShort: return 2;
- case kPrimInt:
- case kPrimFloat: return 4;
- case kPrimLong:
- case kPrimDouble: return 8;
- default:
- LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
- return 0;
- }
-}
-
-size_t Class::PrimitiveFieldSize() const {
- return PrimitiveSize() <= 4 ? 4 : 8;
-}
-
-size_t Class::GetTypeSize(const String* descriptor) {
- switch (descriptor->CharAt(0)) {
- case 'B': return 1; // byte
- case 'C': return 2; // char
- case 'D': return 8; // double
- case 'F': return 4; // float
- case 'I': return 4; // int
- case 'J': return 8; // long
- case 'S': return 2; // short
- case 'Z': return 1; // boolean
- case 'L': return sizeof(Object*);
- case '[': return sizeof(Array*);
- default:
- LOG(ERROR) << "Unknown type " << descriptor;
- return 0;
- }
-}
-
bool Class::Implements(const Class* klass) const {
DCHECK(klass != NULL);
DCHECK(klass->IsInterface()) << PrettyClass(this);
@@ -1089,9 +1076,6 @@
Method* method = GetVirtualMethod(i);
if (method->GetName() == name && method->GetSignature() == signature) {
return method;
- } else {
- LOG(INFO) << "Find (" << name->ToModifiedUtf8() << ", " << signature->ToModifiedUtf8()
- << ") != " << PrettyMethod(method);
}
}
return NULL;
@@ -1117,19 +1101,32 @@
return NULL;
}
-Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
+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.
for (size_t i = 0; i < NumInstanceFields(); ++i) {
Field* f = GetInstanceField(i);
- if (f->GetName()->Equals(name) && type == f->GetType()) {
+ if (f->GetName()->Equals(name) &&
+ StringPiece(f->GetTypeDescriptor()) == type) {
return f;
}
}
return NULL;
}
-Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
+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())) {
+ return f;
+ }
+ }
+ return NULL;
+}
+
+Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& 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()) {
@@ -1141,18 +1138,64 @@
return NULL;
}
-Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
- DCHECK(type != NULL);
- for (size_t i = 0; i < NumStaticFields(); ++i) {
- Field* f = GetStaticField(i);
- if (f->GetName()->Equals(name) && f->GetType() == type) {
+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::FindStaticField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) {
+ DCHECK(type != NULL);
+ 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())) {
+ return f;
+ }
+ }
+ return NULL;
+}
+
+Field* Class::FindStaticField(const StringPiece& name, const StringPiece& 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;
+}
+
+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()) {
diff --git a/src/object.h b/src/object.h
index 752d405..cabaac2 100644
--- a/src/object.h
+++ b/src/object.h
@@ -29,6 +29,7 @@
#include "logging.h"
#include "macros.h"
#include "offsets.h"
+#include "primitive.h"
#include "runtime.h"
#include "stringpiece.h"
#include "thread.h"
@@ -425,6 +426,14 @@
// 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() const;
@@ -492,9 +501,9 @@
Object* generic_type_;
- const String* name_;
+ String* name_;
- // Type of the field
+ // The possibly null type of the field
mutable Class* type_;
uint32_t generic_types_are_initialized_;
@@ -1263,19 +1272,6 @@
kStatusInitialized = 7, // ready to go
};
- enum PrimitiveType {
- kPrimNot = 0,
- kPrimBoolean,
- kPrimByte,
- kPrimChar,
- kPrimShort,
- kPrimInt,
- kPrimLong,
- kPrimFloat,
- kPrimDouble,
- kPrimVoid,
- };
-
Status GetStatus() const {
DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false));
@@ -1383,62 +1379,58 @@
return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
}
- PrimitiveType GetPrimitiveType() const {
- DCHECK_EQ(sizeof(PrimitiveType), sizeof(int32_t));
- return static_cast<PrimitiveType>(
+ Primitive::Type GetPrimitiveType() const {
+ DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
+ return static_cast<Primitive::Type>(
GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
}
- void SetPrimitiveType(PrimitiveType new_type) {
- DCHECK_EQ(sizeof(PrimitiveType), sizeof(int32_t));
+ void SetPrimitiveType(Primitive::Type new_type) {
+ DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false);
}
// Returns true if the class is a primitive type.
bool IsPrimitive() const {
- return GetPrimitiveType() != kPrimNot;
+ return GetPrimitiveType() != Primitive::kPrimNot;
}
bool IsPrimitiveBoolean() const {
- return GetPrimitiveType() == kPrimBoolean;
+ return GetPrimitiveType() == Primitive::kPrimBoolean;
}
bool IsPrimitiveByte() const {
- return GetPrimitiveType() == kPrimByte;
+ return GetPrimitiveType() == Primitive::kPrimByte;
}
bool IsPrimitiveChar() const {
- return GetPrimitiveType() == kPrimChar;
+ return GetPrimitiveType() == Primitive::kPrimChar;
}
bool IsPrimitiveShort() const {
- return GetPrimitiveType() == kPrimShort;
+ return GetPrimitiveType() == Primitive::kPrimShort;
}
bool IsPrimitiveInt() const {
- return GetPrimitiveType() == kPrimInt;
+ return GetPrimitiveType() == Primitive::kPrimInt;
}
bool IsPrimitiveLong() const {
- return GetPrimitiveType() == kPrimLong;
+ return GetPrimitiveType() == Primitive::kPrimLong;
}
bool IsPrimitiveFloat() const {
- return GetPrimitiveType() == kPrimFloat;
+ return GetPrimitiveType() == Primitive::kPrimFloat;
}
bool IsPrimitiveDouble() const {
- return GetPrimitiveType() == kPrimDouble;
+ return GetPrimitiveType() == Primitive::kPrimDouble;
}
bool IsPrimitiveVoid() const {
- return GetPrimitiveType() == kPrimVoid;
+ return GetPrimitiveType() == Primitive::kPrimVoid;
}
- size_t PrimitiveFieldSize() const;
-
- size_t PrimitiveSize() const;
-
// Depth of class from java.lang.Object
size_t Depth() {
size_t depth = 0;
@@ -1463,7 +1455,7 @@
}
size_t GetComponentSize() const {
- return GetTypeSize(GetComponentType()->GetDescriptor());
+ return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
}
bool IsObjectClass() const {
@@ -1473,8 +1465,6 @@
// Creates a raw object instance but does not invoke the default constructor.
Object* AllocObject();
- static size_t GetTypeSize(const String* descriptor);
-
const String* GetDescriptor() const {
const String* result = GetFieldObject<const String*>(
OFFSET_OF_OBJECT_MEMBER(Class, descriptor_), false);
@@ -1923,14 +1913,18 @@
void SetReferenceStaticOffsets(uint32_t new_reference_offsets);
// Finds the given instance field in this class or a superclass.
- Field* FindInstanceField(const StringPiece& name, Class* type);
+ Field* FindInstanceField(const StringPiece& name, const StringPiece& type);
+ Field* FindInstanceField(String* name, String* type);
- Field* FindDeclaredInstanceField(const StringPiece& name, Class* 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, Class* type);
+ Field* FindStaticField(const StringPiece& name, const StringPiece& type);
+ Field* FindStaticField(String* name, String* type);
- Field* FindDeclaredStaticField(const StringPiece& name, Class* type);
+ Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type);
+ Field* FindDeclaredStaticField(String* name, String* type);
pid_t GetClinitThreadId() const {
DCHECK(IsIdxLoaded() || IsErroneous());
@@ -2058,8 +2052,8 @@
// See also class_size_.
size_t object_size_;
- // primitive type index, or kPrimNot (0); set for generated prim classes
- PrimitiveType primitive_type_;
+ // primitive type index, or Primitive::kPrimNot (0); set for generated prim classes
+ Primitive::Type primitive_type_;
// Bitmap of offsets of ifields.
uint32_t reference_instance_offsets_;
@@ -2178,8 +2172,8 @@
inline void Field::SetOffset(MemberOffset num_bytes) {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- Class* type = GetTypeDuringLinking();
- if (type != NULL && (type->IsPrimitiveDouble() || type->IsPrimitiveLong())) {
+ Primitive::Type type = GetPrimitiveType();
+ if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
}
SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
diff --git a/src/object_test.cc b/src/object_test.cc
index db1d331..b09cff1 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -434,16 +434,16 @@
ASSERT_TRUE(c != NULL);
// Wrong type.
- EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
- EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("count", "J") == NULL);
+ EXPECT_TRUE(c->FindInstanceField("count", "J") == NULL);
// Wrong name.
- EXPECT_TRUE(c->FindDeclaredInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
- EXPECT_TRUE(c->FindInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("Count", "I") == NULL);
+ EXPECT_TRUE(c->FindInstanceField("Count", "I") == NULL);
// Right name and type.
- Field* f1 = c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I"));
- Field* f2 = c->FindInstanceField("count", class_linker_->FindSystemClass("I"));
+ Field* f1 = c->FindDeclaredInstanceField("count", "I");
+ Field* f2 = c->FindInstanceField("count", "I");
EXPECT_TRUE(f1 != NULL);
EXPECT_TRUE(f2 != NULL);
EXPECT_EQ(f1, f2);
@@ -454,9 +454,9 @@
c = class_linker_->FindSystemClass("Ljava/lang/StringBuilder;");
ASSERT_TRUE(c != NULL);
// No StringBuilder.count...
- EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I")) == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == NULL);
// ...but there is an AbstractStringBuilder.count.
- EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("I")) != NULL);
+ EXPECT_TRUE(c->FindInstanceField("count", "I") != NULL);
}
TEST_F(ObjectTest, FindStaticField) {
@@ -466,16 +466,16 @@
ASSERT_TRUE(c != NULL);
// Wrong type.
- EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
- EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
+ EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
+ EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
// Wrong name.
- EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
- EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
+ EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
+ EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
// Right name and type.
- Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
- Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
+ Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+ Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
EXPECT_TRUE(f1 != NULL);
EXPECT_TRUE(f2 != NULL);
EXPECT_EQ(f1, f2);
diff --git a/src/primitive.h b/src/primitive.h
new file mode 100644
index 0000000..259378d
--- /dev/null
+++ b/src/primitive.h
@@ -0,0 +1,120 @@
+/*
+ * 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_PRIMITIVE_H_
+#define ART_SRC_PRIMITIVE_H_
+
+#include <sys/types.h>
+
+#include "logging.h"
+#include "macros.h"
+
+namespace art {
+
+class Object;
+
+class Primitive {
+ public:
+ enum Type {
+ kPrimNot = 0,
+ kPrimBoolean,
+ kPrimByte,
+ kPrimChar,
+ kPrimShort,
+ kPrimInt,
+ kPrimLong,
+ kPrimFloat,
+ kPrimDouble,
+ kPrimVoid,
+ };
+
+ static Type GetType(char type) {
+ switch (type) {
+ case 'B':
+ return kPrimByte;
+ case 'C':
+ return kPrimChar;
+ case 'D':
+ return kPrimDouble;
+ case 'F':
+ return kPrimFloat;
+ case 'I':
+ return kPrimInt;
+ case 'J':
+ return kPrimLong;
+ case 'S':
+ return kPrimShort;
+ case 'Z':
+ return kPrimBoolean;
+ case 'V':
+ return kPrimVoid;
+ default:
+ return kPrimNot;
+ }
+ }
+
+ static size_t ComponentSize(Type type) {
+ switch (type) {
+ case kPrimBoolean:
+ case kPrimByte: return 1;
+ case kPrimChar:
+ case kPrimShort: return 2;
+ case kPrimInt:
+ case kPrimFloat: return 4;
+ case kPrimLong:
+ case kPrimDouble: return 8;
+ case kPrimNot: return sizeof(Object*);
+ default:
+ LOG(FATAL) << "Invalid type " << static_cast<int>(type);
+ return 0;
+ }
+ }
+
+ static size_t FieldSize(Type type) {
+ return ComponentSize(type) <= 4 ? 4 : 8;
+ }
+
+ static char DescriptorChar(Type type) {
+ switch (type) {
+ case kPrimBoolean:
+ return 'Z';
+ case kPrimByte:
+ return 'B';
+ case kPrimChar:
+ return 'C';
+ case kPrimShort:
+ return 'S';
+ case kPrimInt:
+ return 'I';
+ case kPrimFloat:
+ return 'J';
+ case kPrimLong:
+ return 'J';
+ case kPrimDouble:
+ return 'D';
+ default:
+ LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
+ return 0;
+ }
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
+};
+
+} // namespace art
+
+#endif // ART_SRC_PRIMITIVE_H_
diff --git a/src/reflection.cc b/src/reflection.cc
index 86b4b09..b367ad3 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -114,7 +114,7 @@
}
// Box if necessary and return.
- BoxPrimitive(env, m->GetReturnType(), value);
+ BoxPrimitive(env, m->GetReturnType()->GetPrimitiveType(), value);
return AddLocalReference<jobject>(env, value.l);
}
@@ -153,66 +153,65 @@
* Returns the width in 32-bit words of the destination primitive, or
* -1 if the conversion is not allowed.
*/
-bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src, JValue& dst) {
- Class::PrimitiveType srcType = src_class->GetPrimitiveType();
- Class::PrimitiveType dstType = dst_class->GetPrimitiveType();
+bool ConvertPrimitiveValue(Primitive::Type srcType, Primitive::Type dstType,
+ const JValue& src, JValue& dst) {
switch (dstType) {
- case Class::kPrimBoolean:
- case Class::kPrimChar:
- case Class::kPrimByte:
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimChar:
+ case Primitive::kPrimByte:
if (srcType == dstType) {
dst.i = src.i;
return true;
}
break;
- case Class::kPrimShort:
- if (srcType == Class::kPrimByte || srcType == Class::kPrimShort) {
+ case Primitive::kPrimShort:
+ if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimShort) {
dst.i = src.i;
return true;
}
break;
- case Class::kPrimInt:
- if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
- srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+ case Primitive::kPrimInt:
+ if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+ srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
dst.i = src.i;
return true;
}
break;
- case Class::kPrimLong:
- if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
- srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+ case Primitive::kPrimLong:
+ if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+ srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
dst.j = src.i;
return true;
- } else if (srcType == Class::kPrimLong) {
+ } else if (srcType == Primitive::kPrimLong) {
dst.j = src.j;
return true;
}
break;
- case Class::kPrimFloat:
- if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
- srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+ case Primitive::kPrimFloat:
+ if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+ srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
dst.f = src.i;
return true;
- } else if (srcType == Class::kPrimLong) {
+ } else if (srcType == Primitive::kPrimLong) {
dst.f = src.j;
return true;
- } else if (srcType == Class::kPrimFloat) {
+ } else if (srcType == Primitive::kPrimFloat) {
dst.i = src.i;
return true;
}
break;
- case Class::kPrimDouble:
- if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
- srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+ case Primitive::kPrimDouble:
+ if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+ srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
dst.d = src.i;
return true;
- } else if (srcType == Class::kPrimLong) {
+ } else if (srcType == Primitive::kPrimLong) {
dst.d = src.j;
return true;
- } else if (srcType == Class::kPrimFloat) {
+ } else if (srcType == Primitive::kPrimFloat) {
dst.d = src.f;
return true;
- } else if (srcType == Class::kPrimDouble) {
+ } else if (srcType == Primitive::kPrimDouble) {
dst.j = src.j;
return true;
}
@@ -221,59 +220,59 @@
break;
}
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
- "invalid primitive conversion from %s to %s",
- PrettyDescriptor(src_class->GetDescriptor()).c_str(),
- PrettyDescriptor(dst_class->GetDescriptor()).c_str());
+ "invalid primitive conversion from %s to %s",
+ PrettyDescriptor(srcType).c_str(),
+ PrettyDescriptor(dstType).c_str());
return false;
}
-void BoxPrimitive(JNIEnv* env, Class* src_class, JValue& value) {
- if (!src_class->IsPrimitive()) {
+void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value) {
+ if (src_class == Primitive::kPrimNot) {
return;
}
Method* m = NULL;
UniquePtr<byte[]> args(new byte[8]);
memset(&args[0], 0, 8);
- switch (src_class->GetPrimitiveType()) {
- case Class::kPrimBoolean:
+ switch (src_class) {
+ case Primitive::kPrimBoolean:
m = gBoolean_valueOf;
*reinterpret_cast<uint32_t*>(&args[0]) = value.z;
break;
- case Class::kPrimByte:
+ case Primitive::kPrimByte:
m = gByte_valueOf;
*reinterpret_cast<uint32_t*>(&args[0]) = value.b;
break;
- case Class::kPrimChar:
+ case Primitive::kPrimChar:
m = gCharacter_valueOf;
*reinterpret_cast<uint32_t*>(&args[0]) = value.c;
break;
- case Class::kPrimDouble:
+ case Primitive::kPrimDouble:
m = gDouble_valueOf;
*reinterpret_cast<double*>(&args[0]) = value.d;
break;
- case Class::kPrimFloat:
+ case Primitive::kPrimFloat:
m = gFloat_valueOf;
*reinterpret_cast<float*>(&args[0]) = value.f;
break;
- case Class::kPrimInt:
+ case Primitive::kPrimInt:
m = gInteger_valueOf;
*reinterpret_cast<uint32_t*>(&args[0]) = value.i;
break;
- case Class::kPrimLong:
+ case Primitive::kPrimLong:
m = gLong_valueOf;
*reinterpret_cast<uint64_t*>(&args[0]) = value.j;
break;
- case Class::kPrimShort:
+ case Primitive::kPrimShort:
m = gShort_valueOf;
*reinterpret_cast<uint32_t*>(&args[0]) = value.s;
break;
- case Class::kPrimVoid:
+ case Primitive::kPrimVoid:
// There's no such thing as a void field, and void methods invoked via reflection return null.
value.l = NULL;
return;
default:
- LOG(FATAL) << PrettyClass(src_class);
+ LOG(FATAL) << static_cast<int>(src_class);
}
Thread* self = Thread::Current();
@@ -282,7 +281,7 @@
}
bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value) {
- if (dst_class->GetPrimitiveType() == Class::kPrimNot) {
+ if (!dst_class->IsPrimitive()) {
if (o != NULL && !o->InstanceOf(dst_class)) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"expected object of type %s, but got %s",
@@ -292,7 +291,7 @@
}
unboxed_value.l = o;
return true;
- } else if (dst_class->GetPrimitiveType() == Class::kPrimVoid) {
+ } else if (dst_class->GetPrimitiveType() == Primitive::kPrimVoid) {
Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
"can't unbox to void");
return false;
@@ -339,7 +338,8 @@
return false;
}
- return ConvertPrimitiveValue(src_class, dst_class, boxed_value, unboxed_value);
+ return ConvertPrimitiveValue(src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(),
+ boxed_value, unboxed_value);
}
} // namespace art
diff --git a/src/reflection.h b/src/reflection.h
index 2d18331..e0263bd 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -18,6 +18,7 @@
#define ART_SRC_REFLECTION_H_
#include "jni.h"
+#include "primitive.h"
namespace art {
@@ -26,10 +27,10 @@
class Object;
void InitBoxingMethods(JNIEnv* env);
-void BoxPrimitive(JNIEnv* env, Class* src_class, JValue& value);
+void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value);
bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value);
-bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src, JValue& dst);
+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);
diff --git a/src/runtime.cc b/src/runtime.cc
index 5f2eddd..c777fa1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -495,7 +495,11 @@
thread_list_ = new ThreadList(options->IsVerbose("thread"));
intern_table_ = new InternTable;
- Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, options->images_);
+ Heap::Init(options->IsVerbose("heap"),
+ options->IsVerbose("gc"),
+ options->heap_initial_size_,
+ options->heap_maximum_size_,
+ options->images_);
BlockSignals();
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index c7140f1..35d1103 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -184,7 +184,7 @@
const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
const DexFile::FieldId& id = dex_file.GetFieldId(ref);
- std::string class_name(PrettyDescriptor(dex_file.GetFieldClassDescriptor(id)));
+ std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
const char* field_name = dex_file.dexStringById(id.name_idx_);
if (!access) {
return class_name + "." + field_name;
@@ -206,7 +206,7 @@
const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
const DexFile::MethodId& id = dex_file.GetMethodId(ref);
- std::string class_name(PrettyDescriptor(dex_file.GetMethodClassDescriptor(id)));
+ std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
const char* method_name = dex_file.dexStringById(id.name_idx_);
if (!access) {
return class_name + "." + method_name;
@@ -496,16 +496,14 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+ if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
return field->Get32(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- Class* type = field->GetType();
- if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
+ if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 32-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -520,16 +518,14 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+ if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
return field->Get64(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- Class* type = field->GetType();
- if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+ if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 64-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -544,16 +540,14 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(!type->IsPrimitive())) {
+ if (LIKELY(!field->IsPrimitiveType())) {
return field->GetObj(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- Class* type = field->GetType();
- if (type->IsPrimitive()) {
+ if (field->IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of reference on primitive field '%s'",
PrettyField(field, true).c_str());
@@ -568,8 +562,7 @@
uint32_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+ if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
field->Set32(NULL, new_value);
return 0; // success
}
@@ -577,8 +570,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- Class* type = field->GetType();
- if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
+ if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 32-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -594,8 +586,7 @@
uint64_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+ if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
field->Set64(NULL, new_value);
return 0; // success
}
@@ -603,8 +594,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (UNLIKELY(!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t))) {
+ if (UNLIKELY(!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t))) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 64-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -620,8 +610,7 @@
Object* new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- Class* type = field->GetType();
- if (LIKELY(!type->IsPrimitive())) {
+ if (LIKELY(!field->IsPrimitiveType())) {
field->SetObj(NULL, new_value);
return 0; // success
}
@@ -629,8 +618,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- Class* type = field->GetType();
- if (type->IsPrimitive()) {
+ if (field->IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of reference to primitive field '%s'",
PrettyField(field, true).c_str());
@@ -1021,7 +1009,7 @@
uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize));
val.j = (val.j & 0xffffffffULL) | (high_half << 32);
}
- BoxPrimitive(env, param_type, val);
+ BoxPrimitive(env, param_type->GetPrimitiveType(), val);
if (self->IsExceptionPending()) {
return;
}
@@ -1040,7 +1028,7 @@
obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
} else {
JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
- BoxPrimitive(env, param_type, val);
+ BoxPrimitive(env, param_type->GetPrimitiveType(), val);
if (self->IsExceptionPending()) {
return;
}
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 851aab7..41d0fe4 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -116,9 +116,11 @@
runtime->Dump(os);
- std::string maps;
- if (ReadFileToString("/proc/self/maps", &maps)) {
- os << "/proc/self/maps:\n" << maps;
+ if (false) {
+ std::string maps;
+ if (ReadFileToString("/proc/self/maps", &maps)) {
+ os << "/proc/self/maps:\n" << maps;
+ }
}
os << "----- end " << getpid() << " -----\n";
diff --git a/src/thread.cc b/src/thread.cc
index 2736140..f4ca2ab 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -642,9 +642,9 @@
}
// TODO: make more accessible?
-Field* FindFieldOrDie(Class* c, const char* name, Class* type) {
- Field* f = c->FindDeclaredInstanceField(name, type);
- CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << PrettyClass(type);
+Field* FindFieldOrDie(Class* c, const char* name, const char* descriptor) {
+ Field* f = c->FindDeclaredInstanceField(name, descriptor);
+ CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor;
return f;
}
@@ -659,25 +659,21 @@
// Now the ClassLinker is ready, we can find the various Class*, Field*, and Method*s we need.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* boolean_class = FindPrimitiveClassOrDie(class_linker, 'Z');
- Class* int_class = FindPrimitiveClassOrDie(class_linker, 'I');
- Class* ClassLoader_class = FindClassOrDie(class_linker, "Ljava/lang/ClassLoader;");
- Class* String_class = FindClassOrDie(class_linker, "Ljava/lang/String;");
Class* Thread_class = FindClassOrDie(class_linker, "Ljava/lang/Thread;");
Class* ThreadGroup_class = FindClassOrDie(class_linker, "Ljava/lang/ThreadGroup;");
Class* UncaughtExceptionHandler_class = FindClassOrDie(class_linker, "Ljava/lang/Thread$UncaughtExceptionHandler;");
gThreadLock = FindClassOrDie(class_linker, "Ljava/lang/ThreadLock;");
gThrowable = FindClassOrDie(class_linker, "Ljava/lang/Throwable;");
- gThread_daemon = FindFieldOrDie(Thread_class, "daemon", boolean_class);
- gThread_group = FindFieldOrDie(Thread_class, "group", ThreadGroup_class);
- gThread_lock = FindFieldOrDie(Thread_class, "lock", gThreadLock);
- gThread_name = FindFieldOrDie(Thread_class, "name", String_class);
- gThread_priority = FindFieldOrDie(Thread_class, "priority", int_class);
- gThread_uncaughtHandler = FindFieldOrDie(Thread_class, "uncaughtHandler", UncaughtExceptionHandler_class);
- gThread_vmData = FindFieldOrDie(Thread_class, "vmData", int_class);
- gThreadGroup_name = FindFieldOrDie(ThreadGroup_class, "name", String_class);
- gThreadLock_thread = FindFieldOrDie(gThreadLock, "thread", Thread_class);
+ gThread_daemon = FindFieldOrDie(Thread_class, "daemon", "Z");
+ gThread_group = FindFieldOrDie(Thread_class, "group", "Ljava/lang/ThreadGroup;");
+ gThread_lock = FindFieldOrDie(Thread_class, "lock", "Ljava/lang/ThreadLock;");
+ gThread_name = FindFieldOrDie(Thread_class, "name", "Ljava/lang/String;");
+ gThread_priority = FindFieldOrDie(Thread_class, "priority", "I");
+ gThread_uncaughtHandler = FindFieldOrDie(Thread_class, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
+ gThread_vmData = FindFieldOrDie(Thread_class, "vmData", "I");
+ gThreadGroup_name = FindFieldOrDie(ThreadGroup_class, "name", "Ljava/lang/String;");
+ gThreadLock_thread = FindFieldOrDie(gThreadLock, "thread", "Ljava/lang/Thread;");
gThread_run = FindMethodOrDie(Thread_class, "run", "()V");
gThreadGroup_removeThread = FindMethodOrDie(ThreadGroup_class, "removeThread", "(Ljava/lang/Thread;)V");
@@ -688,7 +684,7 @@
Thread* self = Thread::Current();
self->CreatePeer("main", false);
- const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", ClassLoader_class);
+ const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", "Ljava/lang/ClassLoader;");
Thread_contextClassLoader->SetObject(self->GetPeer(), self->GetClassLoaderOverride());
}
@@ -1235,7 +1231,15 @@
}
void Thread::DumpFromGdb() const {
- Dump(std::cerr);
+ std::ostringstream ss;
+ Dump(ss);
+ std::string str = ss.str();
+ // log to stderr for debugging command line processes
+ std::cerr << str;
+#ifdef HAVE_ANDROID_OS
+ // log to logcat for debugging frameworks processes
+ LOG(INFO) << str;
+#endif
}
class CatchBlockStackVisitor : public Thread::StackVisitor {
diff --git a/src/utils.cc b/src/utils.cc
index 3922033..a74e231 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -110,13 +110,19 @@
return result;
}
+std::string PrettyDescriptor(Primitive::Type type) {
+ char descriptor_char = Primitive::DescriptorChar(type);
+ std::string descriptor_string(1, descriptor_char);
+ return PrettyDescriptor(descriptor_string);
+}
+
std::string PrettyField(const Field* f, bool with_type) {
if (f == NULL) {
return "null";
}
std::string result;
if (with_type) {
- result += PrettyDescriptor(f->GetType()->GetDescriptor());
+ result += PrettyDescriptor(f->GetTypeDescriptor());
result += ' ';
}
result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor());
diff --git a/src/utils.h b/src/utils.h
index 53a0378..66cda54 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -5,6 +5,7 @@
#include "globals.h"
#include "logging.h"
+#include "primitive.h"
#include "stringpiece.h"
#include "stringprintf.h"
@@ -156,6 +157,7 @@
// "java.lang.String[]", and so forth.
std::string PrettyDescriptor(const String* descriptor);
std::string PrettyDescriptor(const std::string& descriptor);
+std::string PrettyDescriptor(Primitive::Type type);
// 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/src/utils_test.cc b/src/utils_test.cc
index f1944f0..df47d79 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -92,14 +92,12 @@
EXPECT_EQ("null", PrettyField(NULL));
Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;");
- Class* int_class = class_linker_->FindPrimitiveClass('I');
- Class* char_array_class = class_linker_->FindSystemClass("[C");
Field* f;
- f = java_lang_String->FindDeclaredInstanceField("count", int_class);
+ f = java_lang_String->FindDeclaredInstanceField("count", "I");
EXPECT_EQ("int java.lang.String.count", PrettyField(f));
EXPECT_EQ("java.lang.String.count", PrettyField(f, false));
- f = java_lang_String->FindDeclaredInstanceField("value", char_array_class);
+ f = java_lang_String->FindDeclaredInstanceField("value", "[C");
EXPECT_EQ("char[] java.lang.String.value", PrettyField(f));
EXPECT_EQ("java.lang.String.value", PrettyField(f, false));
}