A bit further along the track of multiple threads.
This also makes valgrind happy, and tsan mostly happy. (The heap, it turns out,
doesn't have a lock yet.)
The DexVerifier changes are just to make valgrind happy, and the code a little
less unidiomatic.
Change-Id: Ic5d436b4863b9d7088eb0b8fe9d32308919899d8
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 14f4883..b533a11 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -633,7 +633,7 @@
} else {
klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
}
- if (!klass->IsLinked()) {
+ if (!klass->IsResolved()) {
klass->SetDexCache(dex_cache);
LoadClass(dex_file, dex_class_def, klass, class_loader);
// Check for a pending exception during load
@@ -663,27 +663,27 @@
}
CHECK(klass->IsLoaded());
// Link the class (if necessary)
- CHECK(!klass->IsLinked());
+ CHECK(!klass->IsResolved());
if (!LinkClass(klass)) {
// Linking failed.
// TODO: CHECK(self->IsExceptionPending());
lock.NotifyAll();
return NULL;
}
- CHECK(klass->IsLinked());
+ CHECK(klass->IsResolved());
}
}
}
// Link the class if it has not already been linked.
- if (!klass->IsLinked() && !klass->IsErroneous()) {
+ if (!klass->IsResolved() && !klass->IsErroneous()) {
ObjectLock lock(klass);
// Check for circular dependencies between classes.
- if (!klass->IsLinked() && klass->GetClinitThreadId() == self->GetTid()) {
+ if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
self->ThrowNewException("Ljava/lang/ClassCircularityError;", NULL); // TODO: detail
return NULL;
}
// Wait for the pending initialization to complete.
- while (!klass->IsLinked() && !klass->IsErroneous()) {
+ while (!klass->IsResolved() && !klass->IsErroneous()) {
lock.Wait();
}
}
@@ -692,7 +692,7 @@
return NULL;
}
// Return the loaded class. No exceptions should be pending.
- CHECK(klass->IsLinked());
+ CHECK(klass->IsResolved());
CHECK(!self->IsExceptionPending());
return klass;
}
@@ -1428,6 +1428,19 @@
return klass;
}
+void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+ Class* c, std::map<int, Field*>& field_map) {
+ const ClassLoader* cl = c->GetClassLoader();
+ const byte* class_data = dex_file.GetClassData(dex_class_def);
+ DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
+ uint32_t last_idx = 0;
+ for (size_t i = 0; i < header.static_fields_size_; ++i) {
+ DexFile::Field dex_field;
+ dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
+ field_map[i] = ResolveField(dex_file, dex_field.field_idx_, c->GetDexCache(), cl, true);
+ }
+}
+
void ClassLinker::InitializeStaticFields(Class* klass) {
size_t num_static_fields = klass->NumStaticFields();
if (num_static_fields == 0) {
@@ -1442,6 +1455,11 @@
const DexFile& dex_file = FindDexFile(dex_cache);
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
CHECK(dex_class_def != NULL);
+
+ // We reordered the fields, so we need to be able to map the field indexes to the right fields.
+ std::map<int, Field*> field_map;
+ ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+
const byte* addr = dex_file.GetEncodedArray(*dex_class_def);
if (addr == NULL) {
// All this class' static fields have default values.
@@ -1449,7 +1467,7 @@
}
size_t array_size = DecodeUnsignedLeb128(&addr);
for (size_t i = 0; i < array_size; ++i) {
- Field* field = klass->GetStaticField(i);
+ Field* field = field_map[i];
JValue value;
DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value);
switch (type) {
@@ -1573,7 +1591,7 @@
#ifndef NDEBUG
// Ensure super classes are fully resolved prior to resolving fields..
while (super != NULL) {
- CHECK(super->IsLinked());
+ CHECK(super->IsResolved());
super = super->GetSuperClass();
}
#endif
@@ -1818,7 +1836,7 @@
return success;
}
-bool ClassLinker::LinkFields(Class *klass, bool instance) {
+bool ClassLinker::LinkFields(Class* klass, bool instance) {
size_t num_fields =
instance ? klass->NumInstanceFields() : klass->NumStaticFields();
@@ -1833,7 +1851,7 @@
if (instance) {
Class* super_class = klass->GetSuperClass();
if (super_class != NULL) {
- CHECK(super_class->IsLinked());
+ CHECK(super_class->IsResolved());
field_offset = MemberOffset(super_class->GetObjectSize());
if (field_offset.Uint32Value() == 0u) {
field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);