Merge "Turn free functions that take a JdwpState* into member functions." into dalvik-dev
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 00aa8cf..50c05ab 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -49,12 +49,12 @@
$(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT_DEPENDENCY)
@echo "host dex2oat: $@ ($?)"
@mkdir -p $(dir $@)
- $(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(HOST_CORE_IMG) --base=$(IMG_HOST_BASE_ADDRESS)
+ $(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(HOST_CORE_IMG) --base=$(IMG_HOST_BASE_ADDRESS)
$(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT_DEPENDENCY)
@echo "target dex2oat: $@ ($?)"
@mkdir -p $(dir $@)
- $(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
+ $(hide) $(DEX2OAT) --runtime-arg -Xms32m --runtime-arg -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
$(HOST_CORE_IMG): $(HOST_CORE_OAT)
@@ -70,6 +70,6 @@
$(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT_DEPENDENCY)
@echo "target dex2oat: $@ ($?)"
@mkdir -p $(dir $@)
- $(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
+ $(hide) $(DEX2OAT) --runtime-arg -Xms256m --runtime-arg -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
$(TARGET_BOOT_IMG): $(TARGET_BOOT_OAT)
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 21a82d4..7233f08 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -40,7 +40,7 @@
define build-art-oat
$(2): $(1) $(3) $(DEX2OAT_DEPENDENCY)
@echo "target dex2oat: $$@ ($$?)"
- $(hide) $(DEX2OAT) -Xms16m -Xmx16m --boot-image=$(3) $(addprefix --dex-file=,$$<) --oat=$$@ --host-prefix=$(PRODUCT_OUT)
+ $(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(3) $(addprefix --dex-file=,$$<) --oat=$$@ --host-prefix=$(PRODUCT_OUT)
endef
########################################################################
@@ -71,9 +71,12 @@
ART_TEST_OAT_TARGETS += test-art-target-oat-$(1)
endef
-$(eval $(call declare-test-test-target,ExceptionTest,))
-$(eval $(call declare-test-test-target,Fibonacci,10))
+# Delcare the simplest test first
$(eval $(call declare-test-test-target,HelloWorld,))
+$(eval $(call declare-test-test-target,Fibonacci,10))
+
+# The rest are alphabetical
+$(eval $(call declare-test-test-target,ExceptionTest,))
$(eval $(call declare-test-test-target,IntMath,))
$(eval $(call declare-test-test-target,Invoke,))
$(eval $(call declare-test-test-target,MemUsage,))
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..7c07f00 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
@@ -567,8 +567,8 @@
execl("/system/bin/dex2oatd",
"/system/bin/dex2oatd",
- "-Xms64m",
- "-Xmx64m",
+ "--runtime-arg", "-Xms64m",
+ "--runtime-arg", "-Xmx64m",
boot_image_option.c_str(),
dex_file_option.c_str(),
oat_file_option.c_str(),
@@ -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/dex2oat.cc b/src/dex2oat.cc
index 455b8b9..6a39241 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -52,14 +52,10 @@
" Example: --host-prefix=out/target/product/crespo\n"
"\n");
fprintf(stderr,
- " -Xms<n> may be used to specify an initial heap size for the runtime used to\n"
- " run dex2oat\n"
- " Example: -Xms256m\n"
- "\n");
- fprintf(stderr,
- " -Xmx<n> may be used to specify a maximum heap size for the runtime used to\n"
- " run dex2oat\n"
- " Example: -Xmx256m\n"
+ " --runtime-arg <argument>: used to specify various arguments for the runtime,\n"
+ " such as initial heap size, maximum heap size, and verbose output.\n"
+ " Use a separate --runtime-arg switch for each argument.\n"
+ " Example: --runtime-arg -Xms256m\n"
"\n");
exit(EXIT_FAILURE);
}
@@ -81,9 +77,7 @@
std::string boot_image_option;
uintptr_t image_base = 0;
std::string host_prefix;
- const char* Xms = NULL;
- const char* Xmx = NULL;
- const char* verbose = NULL;
+ std::vector<const char*> runtime_args;
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
@@ -113,12 +107,12 @@
boot_image_option += boot_image_filename;
} else if (option.starts_with("--host-prefix=")) {
host_prefix = option.substr(strlen("--host-prefix=")).data();
- } else if (option.starts_with("-Xms")) {
- Xms = option.data();
- } else if (option.starts_with("-Xmx")) {
- Xmx = option.data();
- } else if (option.starts_with("-verbose:")) {
- verbose = option.data();
+ } else if (option == "--runtime-arg") {
+ if (++i >= argc) {
+ fprintf(stderr, "Missing required argument for --runtime-arg\n");
+ usage();
+ }
+ runtime_args.push_back(argv[i]);
} else {
fprintf(stderr, "unknown argument %s\n", option.data());
usage();
@@ -161,18 +155,12 @@
} else {
options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
}
- if (Xms != NULL) {
- options.push_back(std::make_pair(Xms, reinterpret_cast<void*>(NULL)));
- }
- if (Xmx != NULL) {
- options.push_back(std::make_pair(Xmx, reinterpret_cast<void*>(NULL)));
- }
- if (verbose != NULL) {
- options.push_back(std::make_pair(verbose, reinterpret_cast<void*>(NULL)));
- }
if (!host_prefix.empty()) {
options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
}
+ for (size_t i = 0; i < runtime_args.size(); i++) {
+ options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
+ }
UniquePtr<Runtime> runtime(Runtime::Create(options, false));
if (runtime.get() == NULL) {
fprintf(stderr, "could not create runtime\n");
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_instruction.cc b/src/dex_instruction.cc
index eb8e96e..6a3f538 100644
--- a/src/dex_instruction.cc
+++ b/src/dex_instruction.cc
@@ -254,22 +254,25 @@
return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
}
-void Instruction::DumpHex(std::ostream& os, size_t code_units) const {
+std::string Instruction::DumpHex(size_t code_units) const {
size_t inst_length = SizeInCodeUnits();
if (inst_length > code_units) {
inst_length = code_units;
}
+ std::ostringstream os;
const uint16_t* insn = reinterpret_cast<const uint16_t*>(this);
for (size_t i = 0; i < inst_length; i++) {
- os << "0x" << StringPrintf("0x%04X", insn[i]) << " ";
+ os << StringPrintf("0x%04x", insn[i]) << " ";
}
for (size_t i = inst_length; i < code_units; i++) {
os << " ";
}
+ return os.str();
}
-void Instruction::Dump(std::ostream& os, const DexFile* file) const {
+std::string Instruction::DumpString(const DexFile* file) const {
DecodedInstruction insn(this);
+ std::ostringstream os;
const char* opcode = kInstructionNames[insn.opcode_];
switch (Format()) {
case k10x: os << opcode; break;
@@ -318,12 +321,9 @@
}
case k3rc: os << opcode << " {v" << insn.vC_ << " .. v" << (insn.vC_+ insn.vA_ - 1) << "}, method@" << insn.vB_; break;
case k51l: os << opcode << " v" << insn.vA_ << ", #+" << insn.vB_; break;
+ default: os << " unknown format (" << DumpHex(5) << ")"; break;
}
-}
-
-std::ostream& operator<<(std::ostream& os, const Instruction& rhs) {
- rhs.Dump(os, NULL);
- return os;
+ return os.str();
}
} // namespace art
diff --git a/src/dex_instruction.h b/src/dex_instruction.h
index 36ea295..5cfd7ef 100644
--- a/src/dex_instruction.h
+++ b/src/dex_instruction.h
@@ -189,11 +189,11 @@
kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
}
- // Dump code_units worth of this instruction, padding to code_units for shorter instructions
- void DumpHex(std::ostream& os, size_t code_units) const;
-
// Dump decoded version of instruction
- void Dump(std::ostream& os, const DexFile*) const;
+ std::string DumpString(const DexFile*) const;
+
+ // Dump code_units worth of this instruction, padding to code_units for shorter instructions
+ std::string DumpHex(size_t code_units) const;
private:
static const char* const kInstructionNames[];
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 878069b..e4d9f84 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -17,23 +17,27 @@
namespace art {
namespace verifier {
+static const bool gDebugVerify = false;
+
std::ostream& operator<<(std::ostream& os, const VerifyError& rhs) {
return os << (int)rhs;
}
static const char type_chars[RegType::kRegTypeMAX + 1 /* for '\0' */ ] = "UX01ZyYhHcibBsSCIFNnJjDdL";
-void RegType::Dump(std::ostream& os) const {
+std::string RegType::Dump() const {
DCHECK(type_ < kRegTypeMAX);
+ std::ostringstream os;
os << type_chars[type_];
if (type_ == kRegTypeReference) {
if (IsUninitializedReference()) {
- os << "[uninitialized-" << PrettyClass(GetClass())
+ os << "[uninitialized-" << PrettyDescriptor(GetClass()->GetDescriptor())
<< ", allocated@" << allocation_pc_ <<"]";
} else {
os << "[" << PrettyDescriptor(GetClass()->GetDescriptor()) << "]";
}
}
+ return os.str();
}
const RegType& RegType::HighHalf(RegTypeCache* cache) const {
@@ -146,7 +150,10 @@
return check_type;
} else if (IsUninitializedReference()) {
return reg_types->Conflict(); // Nonsensical to Join two uninitialized classes
- } else if (IsReference() && check_type.GetClass()->IsAssignableFrom(GetClass())) {
+ } else if (IsReference() && (check_type.GetClass()->IsAssignableFrom(GetClass()) ||
+ (GetClass()->IsObjectClass() && check_type.GetClass()->IsInterface()))) {
+ // Either we're assignable or this is trying to assign Object to an Interface, which
+ // is allowed (see comment in ClassJoin)
return check_type;
} else {
return reg_types->Conflict();
@@ -282,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;
}
}
@@ -319,7 +326,7 @@
}
std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
- rhs.Dump(os);
+ os << rhs.Dump();
return os;
}
@@ -353,9 +360,14 @@
}
}
Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
- RegType* entry = new RegType(type, klass, RegType::kInitArgAddr, entries_.size());
- entries_.push_back(entry);
- return *entry;
+ if (klass != NULL) {
+ RegType* entry = new RegType(type, klass, RegType::kInitArgAddr, entries_.size());
+ entries_.push_back(entry);
+ return *entry;
+ } else {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return FromType(RegType::kRegTypeUnknown);
+ }
}
}
@@ -778,7 +790,7 @@
}
std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs) {
- rhs.Dump(os);
+ os << rhs.Dump();
return os;
}
@@ -864,7 +876,9 @@
} else {
LOG(INFO) << "Verification error in " << PrettyMethod(method) << " "
<< verifier.fail_messages_.str() << std::endl << verifier.info_messages_.str();
- verifier.Dump(std::cout);
+ if (gDebugVerify) {
+ verifier.Dump(std::cout);
+ }
DCHECK_EQ(verifier.failure_, VERIFY_ERROR_GENERIC);
}
return success;
@@ -993,7 +1007,8 @@
uint32_t insns_size = code_item_->insns_size_in_code_units_;
for(uint32_t dex_pc = 0; dex_pc < insns_size;) {
if (!VerifyInstruction(inst, dex_pc)) {
- Fail(VERIFY_ERROR_GENERIC) << "rejecting opcode " << inst->Name() << " at " << dex_pc;
+ DCHECK_NE(failure_, VERIFY_ERROR_NONE);
+ fail_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_) << " at " << dex_pc;
return false;
}
/* Flag instructions that are garbage collection points */
@@ -1399,7 +1414,8 @@
/* Initialize register types of method arguments. */
if (!SetTypesFromSignature()) {
- Fail(VERIFY_ERROR_GENERIC) << "bad signature in " << PrettyMethod(method_);
+ DCHECK_NE(failure_, VERIFY_ERROR_NONE);
+ fail_messages_ << "Bad signature in " << PrettyMethod(method_);
return false;
}
/* Perform code flow verification. */
@@ -1428,19 +1444,11 @@
const Instruction* inst = Instruction::At(code_item_->insns_);
for (size_t dex_pc = 0; dex_pc < code_item_->insns_size_in_code_units_;
dex_pc += insn_flags_[dex_pc].GetLengthInCodeUnits()) {
- std::ios::fmtflags saved_flags(os.flags());
- os << std::hex << std::showbase << std::setfill('0') << std::setw(4) << dex_pc << ": ";
- os.flags(saved_flags);
- insn_flags_[dex_pc].Dump(os);
- os << " ";
- inst->DumpHex(os, 5);
- os << " ";
- inst->Dump(os, dex_file_);
- os << std::endl;
+ os << StringPrintf("0x%04x", dex_pc) << ": " << insn_flags_[dex_pc].Dump()
+ << " " << inst->DumpHex(5) << " " << inst->DumpString(dex_file_) << std::endl;
RegisterLine* reg_line = reg_table_.GetLine(dex_pc);
if (reg_line != NULL) {
- reg_line->Dump(os);
- os << std::endl;
+ os << reg_line->Dump() << std::endl;
}
inst = inst->Next();
}
@@ -1507,14 +1515,15 @@
{
const RegType& reg_type =
reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
- if (reg_type.IsUnknown()) {
+ if (!reg_type.IsUnknown()) {
+ reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
+ } else {
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
- Fail(VERIFY_ERROR_GENERIC)
- << "Unable to resolve descriptor in signature " << descriptor;
- return false;
+ LOG(WARNING) << "Unable to resolve descriptor in signature " << descriptor
+ << " using Object";
+ reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.JavaLangObject());
}
- reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
}
break;
case 'Z':
@@ -1726,9 +1735,9 @@
int32_t branch_target = 0;
bool just_set_result = false;
- if (false) {
+ if (gDebugVerify) {
// Generate processing back trace to debug verifier
- LogVerifyInfo() << "Processing " << *inst << std::endl << *work_line_.get();
+ LogVerifyInfo() << "Processing " << inst->DumpString(dex_file_) << std::endl << *work_line_.get();
}
/*
@@ -2125,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) {
@@ -2675,7 +2684,7 @@
case Instruction::UNUSED_7A:
case Instruction::UNUSED_EC:
case Instruction::UNUSED_FF:
- Fail(VERIFY_ERROR_GENERIC) << "Unexpected opcode " << *inst;
+ Fail(VERIFY_ERROR_GENERIC) << "Unexpected opcode " << inst->DumpString(dex_file_);
break;
/*
@@ -2687,11 +2696,11 @@
if (failure_ != VERIFY_ERROR_NONE) {
if (failure_ == VERIFY_ERROR_GENERIC) {
/* immediate failure, reject class */
- fail_messages_ << std::endl << "Rejecting opcode " << *inst;
+ fail_messages_ << std::endl << "Rejecting opcode " << inst->DumpString(dex_file_);
return false;
} else {
/* replace opcode and continue on */
- fail_messages_ << std::endl << "Replacing opcode " << *inst;
+ fail_messages_ << std::endl << "Replacing opcode " << inst->DumpString(dex_file_);
ReplaceFailingInstruction();
/* IMPORTANT: method->insns may have been changed */
insns = code_item_->insns_ + work_insn_idx_;
@@ -2943,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);
@@ -2980,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;
@@ -3103,9 +3112,12 @@
if (reg_type.IsUnknown()) {
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
- Fail(VERIFY_ERROR_GENERIC) << "Rejecting invocation of " << PrettyMethod(res_method)
- << " bad descriptor '" << descriptor << "' in signature " << sig;
- return NULL;
+ LOG(WARNING) << "Unable to resolve descriptor in signature " << descriptor
+ << " using Object";
+ uint32_t get_reg = is_range ? dec_insn.vC_ + actual_args : dec_insn.arg_[actual_args];
+ if (!work_line_->VerifyRegisterType(get_reg, reg_types_.JavaLangObject())) {
+ return NULL;
+ }
} else {
uint32_t get_reg = is_range ? dec_insn.vC_ + actual_args : dec_insn.arg_[actual_args];
if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
@@ -3224,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;
@@ -3287,14 +3299,30 @@
return;
}
Class* field_class = field->GetType();
+ const RegType& field_type = reg_types_.FromClass(field_class);
Class* insn_class = insn_type.GetClass();
if (is_primitive) {
- if (field_class == insn_class ||
- (field_class->IsPrimitiveFloat() && insn_class->IsPrimitiveInt()) ||
- (field_class->IsPrimitiveDouble() && insn_class->IsPrimitiveLong())) {
- // expected that read is of the correct primitive type or that int reads are reading
- // floats or long reads are reading doubles
+ // Primitive field assignability rules are weaker than regular assignability rules
+ bool instruction_compatible;
+ bool value_compatible;
+ const RegType& value_type = work_line_->GetRegisterType(dec_insn.vA_);
+ if (field_type.IsIntegralTypes()) {
+ instruction_compatible = insn_type.IsIntegralTypes();
+ value_compatible = value_type.IsIntegralTypes();
+ } else if (field_type.IsFloat()) {
+ instruction_compatible = insn_type.IsInteger(); // no sput-float, so expect sput-int
+ value_compatible = value_type.IsFloatTypes();
+ } else if (field_type.IsLong()) {
+ instruction_compatible = insn_type.IsLong();
+ value_compatible = value_type.IsLongTypes();
+ } else if (field_type.IsDouble()) {
+ instruction_compatible = insn_type.IsLong(); // no sput-double, so expect sput-long
+ value_compatible = value_type.IsDoubleTypes();
} else {
+ instruction_compatible = false; // reference field with primitive store
+ value_compatible = false; // unused
+ }
+ if (!instruction_compatible) {
// This is a global failure rather than a class change failure as the instructions and
// the descriptors for the type should have been consistent within the same file at
// compile time
@@ -3303,6 +3331,13 @@
<< " but found type " << PrettyClass(field_class) << " in sput";
return;
}
+ if (!value_compatible) {
+ Fail(VERIFY_ERROR_GENERIC) << "unexpected value in v" << dec_insn.vA_
+ << " of type " << value_type
+ << " but expected " << field_type
+ << " for store to " << PrettyField(field) << " in sput";
+ return;
+ }
} else {
if (!insn_class->IsAssignableFrom(field_class)) {
Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
@@ -3311,8 +3346,8 @@
<< " in sput-object";
return;
}
+ work_line_->VerifyRegisterType(dec_insn.vA_, field_type);
}
- work_line_->VerifyRegisterType(dec_insn.vA_, reg_types_.FromClass(field_class));
}
}
@@ -3322,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;
@@ -3364,7 +3399,6 @@
const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
Field* field = GetInstanceField(object_type, dec_insn.vC_);
if (field != NULL) {
- DCHECK(field->GetDeclaringClass()->IsResolved());
Class* field_class = field->GetType();
Class* insn_class = insn_type.GetClass();
if (is_primitive) {
@@ -3399,21 +3433,36 @@
const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
Field* field = GetInstanceField(object_type, dec_insn.vC_);
if (field != NULL) {
- DCHECK(field->GetDeclaringClass()->IsResolved());
if (field->IsFinal() && field->GetDeclaringClass() != method_->GetDeclaringClass()) {
Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
<< " from other class " << PrettyClass(method_->GetDeclaringClass());
return;
}
Class* field_class = field->GetType();
+ const RegType& field_type = reg_types_.FromClass(field_class);
Class* insn_class = insn_type.GetClass();
if (is_primitive) {
- if (field_class == insn_class ||
- (field_class->IsPrimitiveFloat() && insn_class->IsPrimitiveInt()) ||
- (field_class->IsPrimitiveDouble() && insn_class->IsPrimitiveLong())) {
- // expected that read is of the correct primitive type or that int reads are reading
- // floats or long reads are reading doubles
+ // Primitive field assignability rules are weaker than regular assignability rules
+ bool instruction_compatible;
+ bool value_compatible;
+ const RegType& value_type = work_line_->GetRegisterType(dec_insn.vA_);
+ if (field_type.IsIntegralTypes()) {
+ instruction_compatible = insn_type.IsIntegralTypes();
+ value_compatible = value_type.IsIntegralTypes();
+ } else if (field_type.IsFloat()) {
+ instruction_compatible = insn_type.IsInteger(); // no iput-float, so expect iput-int
+ value_compatible = value_type.IsFloatTypes();
+ } else if (field_type.IsLong()) {
+ instruction_compatible = insn_type.IsLong();
+ value_compatible = value_type.IsLongTypes();
+ } else if (field_type.IsDouble()) {
+ instruction_compatible = insn_type.IsLong(); // no iput-double, so expect iput-long
+ value_compatible = value_type.IsDoubleTypes();
} else {
+ instruction_compatible = false; // reference field with primitive store
+ value_compatible = false; // unused
+ }
+ if (!instruction_compatible) {
// This is a global failure rather than a class change failure as the instructions and
// the descriptors for the type should have been consistent within the same file at
// compile time
@@ -3422,16 +3471,23 @@
<< " but found type " << PrettyClass(field_class) << " in iput";
return;
}
+ if (!value_compatible) {
+ Fail(VERIFY_ERROR_GENERIC) << "unexpected value in v" << dec_insn.vA_
+ << " of type " << value_type
+ << " but expected " << field_type
+ << " for store to " << PrettyField(field) << " in iput";
+ return;
+ }
} else {
if (!insn_class->IsAssignableFrom(field_class)) {
Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
- << " to be compatible with type " << PrettyClass(insn_class)
- << " but found type " << PrettyClass(field_class)
- << " in iput-object";
+ << " to be compatible with type " << insn_type
+ << " but found type " << PrettyClass(field_class)
+ << " in iput-object";
return;
}
+ work_line_->VerifyRegisterType(dec_insn.vA_, field_type);
}
- work_line_->VerifyRegisterType(dec_insn.vA_, reg_types_.FromClass(field_class));
}
}
@@ -3525,7 +3581,7 @@
ref_type = VERIFY_ERROR_REF_METHOD;
break;
default:
- LOG(FATAL) << "Error: verifier asked to replace instruction " << *inst;
+ LOG(FATAL) << "Error: verifier asked to replace instruction " << inst->DumpString(dex_file_);
return;
}
uint16_t* insns = const_cast<uint16_t*>(code_item_->insns_);
@@ -3565,7 +3621,7 @@
if (failure_ != VERIFY_ERROR_NONE) {
return false;
}
- if (changed) {
+ if (gDebugVerify && changed) {
LogVerifyInfo() << "Merging at [" << (void*)work_insn_idx_ << "] to [" <<(void*)next_insn << "]: " << std::endl
<< *copy.get() << " MERGE" << std::endl
<< *merge_line << " ==" << std::endl
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 1f28204..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 {
@@ -117,7 +117,7 @@
return type_;
}
- void Dump(std::ostream& os) const;
+ std::string Dump() const;
Class* GetClass() const {
DCHECK(klass_ != NULL);
@@ -254,6 +254,7 @@
RegType(Type type, Class* klass, uint32_t allocation_pc, uint16_t cache_id) :
type_(type), klass_(klass), allocation_pc_(allocation_pc), cache_id_(cache_id) {
DCHECK(type >= kRegTypeReference || allocation_pc_ == kInitArgAddr);
+ if (type >= kRegTypeReference) DCHECK(klass != NULL);
}
const Type type_; // The current type of the register
@@ -411,7 +412,7 @@
return IsVisited() || IsChanged();
}
- void Dump(std::ostream& os) {
+ std::string Dump() {
char encoding[6];
if (!IsOpcode()) {
strncpy(encoding, "XXXXX", sizeof(encoding));
@@ -423,7 +424,7 @@
if (IsVisited()) encoding[kInsnFlagVisited] = 'V';
if (IsChanged()) encoding[kInsnFlagChanged] = 'C';
}
- os << encoding;
+ return std::string(encoding);
}
private:
enum InsnFlag {
@@ -569,10 +570,12 @@
reg_to_lock_depths_ = src->reg_to_lock_depths_;
}
- void Dump(std::ostream& os) const {
+ std::string Dump() const {
+ std::string result;
for (size_t i = 0; i < num_regs_; i++) {
- GetRegisterType(i).Dump(os);
+ result += GetRegisterType(i).Dump();
}
+ return result;
}
void FillWithGarbage() {
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/oatopt.cc b/src/oatopt.cc
index 133af59..c792b4d 100644
--- a/src/oatopt.cc
+++ b/src/oatopt.cc
@@ -51,8 +51,8 @@
execl("/system/bin/dex2oatd",
"/system/bin/dex2oatd",
- "-Xms64m",
- "-Xmx64m",
+ "--runtime-arg", "-Xms64m",
+ "--runtime-arg", "-Xmx64m",
"--boot-image=/data/art-cache/boot.art",
dex_file_option.c_str(),
oat_file_option.c_str(),
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));
}
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build
index 47abae2..d5aa786 100644
--- a/test/003-omnibus-opcodes/build
+++ b/test/003-omnibus-opcodes/build
@@ -24,9 +24,3 @@
dx -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-
-dex2oatd -Xms16m -Xmx16m \
- --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art \
- --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar \
- --oat=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat \
- --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build
index 171eaae..ebe722e 100644
--- a/test/023-many-interfaces/build
+++ b/test/023-many-interfaces/build
@@ -26,9 +26,3 @@
dx --debug --dex --dump-to=classes.lst --output=classes.dex classes
zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-
-dex2oatd -Xms16m -Xmx16m \
- --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art \
- --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar \
- --oat=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat \
- --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build
index d7a8268..a563cd0 100644
--- a/test/056-const-string-jumbo/build
+++ b/test/056-const-string-jumbo/build
@@ -45,9 +45,3 @@
dx -JXmx500m --debug --dex --no-optimize --positions=none --no-locals \
--dump-to=classes.lst --output=classes.dex classes
zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-
-dex2oatd -Xms16m -Xmx16m \
- --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art \
- --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar \
- --oat=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat \
- --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build
index 32f7a86..b7e12ae 100644
--- a/test/085-old-style-inner-class/build
+++ b/test/085-old-style-inner-class/build
@@ -27,9 +27,3 @@
--dump-width=1000 classes 2>/dev/null
zip ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar classes.dex
-
-dex2oatd -Xms16m -Xmx16m \
- --boot-image=${ANDROID_PRODUCT_OUT}/data/art-test/core.art \
- --dex-file=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar \
- --oat=${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat \
- --host-prefix=${ANDROID_PRODUCT_OUT}
diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc
index 6a23d1f..ad9c674 100644
--- a/test/StackWalk/stack_walk_jni.cc
+++ b/test/StackWalk/stack_walk_jni.cc
@@ -44,7 +44,7 @@
// 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") == 0) {
+ if (m_name->Equals("f")) {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(1U, m->ToDexPC(pc));
CHECK_REGS(1);
@@ -53,7 +53,7 @@
CHECK_EQ(5U, m->ToDexPC(pc));
CHECK_REGS(1);
}
- } else if (m_name->Equals("g") == 0) {
+ } else if (m_name->Equals("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 +62,7 @@
CHECK_EQ(0xcU, m->ToDexPC(pc));
CHECK_REGS(0, 2);
}
- } else if (m_name->Equals("shlemiel") == 0) {
+ } else if (m_name->Equals("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);