Invoke <clinit> where necessary.

This lets us run Long.toString and friends for integral types, though
we'll need a libcore hack to avoid ThreadLocals for the time being.

Change-Id: I04bba5914f1b7d00e4917922e65b9c27302a59ff
diff --git a/src/object.cc b/src/object.cc
index f92f746..8b0c976 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -56,57 +56,48 @@
   return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
 }
 
-uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return 0;
+Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Field* f = class_linker->ResolveField(field_idx, referrer);
+  if (f != NULL) {
+    Class* c = f->GetDeclaringClass();
+    // If the class is already initializing, we must be inside <clinit>, or
+    // we'd still be waiting for the lock.
+    if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c)) {
+      return f;
+    }
   }
+  UNIMPLEMENTED(FATAL) << "throw an error and unwind";
+  return NULL;
+}
+
+uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
   return field->Get32(NULL);
 }
 void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return;
-  }
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
   field->Set32(NULL, new_value);
 }
 uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return 0;
-  }
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
   return field->Get64(NULL);
 }
 void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return;
-  }
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
   field->Set64(NULL, new_value);
 }
 Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return 0;
-  }
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(!field->GetType()->IsPrimitive());
   return field->GetObj(NULL);
 }
 void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) {
-  Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
-  if (field == NULL) {
-    UNIMPLEMENTED(FATAL) << "throw an error";
-    return;
-  }
+  Field* field = FindFieldFromCode(field_idx, referrer);
   DCHECK(!field->GetType()->IsPrimitive());
   field->SetObj(NULL, new_value);
 }
@@ -483,6 +474,28 @@
       OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), invoke_stub, false);
 }
 
+void Method::Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const {
+  // Push a transition back into managed code onto the linked list in thread.
+  CHECK_EQ(Thread::kRunnable, self->GetState());
+  NativeToManagedRecord record;
+  self->PushNativeToManagedRecord(&record);
+
+  // Call the invoke stub associated with the method.
+  // Pass everything as arguments.
+  const Method::InvokeStub* stub = GetInvokeStub();
+  if (HasCode() && stub != NULL) {
+    (*stub)(this, receiver, self, args, result);
+  } else {
+    LOG(WARNING) << "Not invoking method with no associated code: " << PrettyMethod(this);
+    if (result != NULL) {
+      result->j = 0;
+    }
+  }
+
+  // Pop transition.
+  self->PopNativeToManagedRecord(record);
+}
+
 void Class::SetStatus(Status new_status) {
   CHECK(new_status > GetStatus() || new_status == kStatusError ||
         Runtime::Current() == NULL);  // no runtime implies we're not initialized