Add support for linking classes.

Change-Id: I0026be6e4c919f7391fd83c654f58c3bc67f44e1
diff --git a/src/class_linker.cc b/src/class_linker.cc
new file mode 100644
index 0000000..4924810
--- /dev/null
+++ b/src/class_linker.cc
@@ -0,0 +1,891 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: cshapiro@google.com (Carl Shapiro)
+
+#include "src/class_linker.h"
+
+#include <vector>
+#include <utility>
+
+#include "src/dex_verifier.h"
+#include "src/logging.h"
+#include "src/monitor.h"
+#include "src/object.h"
+#include "src/raw_dex_file.h"
+#include "src/scoped_ptr.h"
+#include "src/thread.h"
+#include "src/utils.h"
+
+namespace art {
+
+Class* ClassLinker::FindClass(const char* descriptor,
+                              Object* class_loader,
+                              DexFile* dex_file) {
+  Thread* self = Thread::Self();
+  CHECK(!self->IsExceptionPending());
+  // Find the class in the loaded classes table.
+  Class* klass = LookupClass(descriptor, class_loader);
+  if (klass == NULL) {
+    // Class is not yet loaded.
+    if (dex_file == NULL) {
+      // No .dex file specified, search the class path.
+      dex_file = FindInClassPath(descriptor);
+      if (dex_file == NULL) {
+        LG << "Class really not found";
+        return NULL;
+      }
+    }
+    // Load the class from the dex file.
+    klass = dex_file->LoadClass(descriptor);
+    if (klass == NULL) {
+      // TODO: this occurs only when a dex file is provided.
+      LG << "Class not found";  // TODO: NoClassDefFoundError
+      return NULL;
+    }
+    // Check for a pending exception during load
+    if (self->IsExceptionPending()) {
+      // TODO: free native allocations in klass
+      return NULL;
+    }
+    {
+      ObjectLock lock(klass);
+      klass->clinit_thread_id_ = self->GetThreadId();
+      // Add the newly loaded class to the loaded classes table.
+      bool success = InsertClass(klass);
+      if (!success) {
+        // We may fail to insert if we raced with another thread.
+        klass->clinit_thread_id_ = 0;
+        // TODO: free native allocations in klass
+        klass = LookupClass(descriptor, class_loader);
+        CHECK(klass != NULL);
+      } else {
+        // Link the class.
+        if (!LinkClass(klass)) {
+          // Linking failed.
+          // TODO: CHECK(self->IsExceptionPending());
+          lock.NotifyAll();
+          return NULL;
+        }
+      }
+    }
+  }
+  // Link the class if it has not already been linked.
+  if (!klass->IsLinked() && !klass->IsErroneous()) {
+    ObjectLock lock(klass);
+    // Check for circular dependencies between classes.
+    if (!klass->IsLinked() && klass->clinit_thread_id_ == self->GetThreadId()) {
+      LG << "Recursive link";  // TODO: ClassCircularityError
+      return NULL;
+    }
+    // Wait for the pending initialization to complete.
+    while (!klass->IsLinked() && !klass->IsErroneous()) {
+      lock.Wait();
+    }
+  }
+  if (klass->IsErroneous()) {
+    LG << "EarlierClassFailure";  // TODO: EarlierClassFailure
+    return NULL;
+  }
+  // Return the loaded class.  No exceptions should be pending.
+  CHECK(!self->IsExceptionPending());
+  return klass;
+}
+
+DexFile* ClassLinker::FindInClassPath(const char* descriptor) {
+  for (size_t i = 0; i != class_path_.size(); ++i) {
+    DexFile* dex_file = class_path_[i];
+    if (dex_file->HasClass(descriptor)) {
+      return dex_file;
+    }
+  }
+  return NULL;
+}
+
+void ClassLinker::AppendToClassPath(DexFile* dex_file) {
+  class_path_.push_back(dex_file);
+}
+
+
+Class* ClassLinker::FindPrimitiveClass(const char* descriptor) {
+  return NULL;  // TODO
+}
+
+bool ClassLinker::InsertClass(Class* klass) {
+  // TODO: acquire classes_lock_
+  const char* key = klass->GetDescriptor().data();
+  bool success = classes_.insert(std::make_pair(key, klass)).second;
+  // TODO: release classes_lock_
+  return success;
+}
+
+Class* ClassLinker::LookupClass(const char* descriptor, Object* class_loader) {
+  // TODO: acquire classes_lock_
+  Table::iterator it = classes_.find(descriptor);
+  // TODO: release classes_lock_
+  if (it == classes_.end()) {
+    return NULL;
+  } else {
+    return (*it).second;
+  }
+}
+
+bool ClassLinker::InitializeClass(Class* klass) {
+  CHECK(klass->GetStatus() == Class::kStatusResolved ||
+        klass->GetStatus() == Class::kStatusError);
+
+  Thread* self = Thread::Self();
+
+  {
+    ObjectLock lock(klass);
+
+    if (klass->GetStatus() < Class::kStatusVerified) {
+      if (klass->IsErroneous()) {
+        LG << "re-initializing failed class";  // TODO: throw
+        return false;
+      }
+
+      CHECK(klass->GetStatus() == Class::kStatusResolved);
+
+      klass->status_ = Class::kStatusVerifying;
+      if (!DexVerify::VerifyClass(klass)) {
+        LG << "Verification failed";  // TODO: ThrowVerifyError
+        Object* exception = self->GetException();
+        klass->SetObjectAt(OFFSETOF_MEMBER(Class, verify_error_class_),
+                           exception->GetClass());
+        klass->SetStatus(Class::kStatusError);
+        return false;
+      }
+
+      klass->SetStatus(Class::kStatusVerified);
+    }
+
+    if (klass->status_ == Class::kStatusInitialized) {
+      return true;
+    }
+
+    while (klass->status_ == Class::kStatusInitializing) {
+      // we caught somebody else in the act; was it us?
+      if (klass->clinit_thread_id_ == self->GetThreadId()) {
+        LG << "recursive <clinit>";
+        return true;
+      }
+
+      CHECK(!self->IsExceptionPending());
+
+      lock.Wait();  // TODO: check for interruption
+
+      // When we wake up, repeat the test for init-in-progress.  If
+      // there's an exception pending (only possible if
+      // "interruptShouldThrow" was set), bail out.
+      if (self->IsExceptionPending()) {
+        CHECK(false);
+        LG << "Exception in initialization.";  // TODO: ExceptionInInitializerError
+        klass->SetStatus(Class::kStatusError);
+        return false;
+      }
+      if (klass->GetStatus() == Class::kStatusInitializing) {
+        continue;
+      }
+      assert(klass->GetStatus() == Class::kStatusInitialized ||
+             klass->GetStatus() == Class::kStatusError);
+      if (klass->IsErroneous()) {
+        /*
+         * The caller wants an exception, but it was thrown in a
+         * different thread.  Synthesize one here.
+         */
+        LG << "<clinit> failed";  // TODO: throw UnsatisfiedLinkError
+        return false;
+      }
+      return true;  // otherwise, initialized
+    }
+
+    // see if we failed previously
+    if (klass->IsErroneous()) {
+      // might be wise to unlock before throwing; depends on which class
+      // it is that we have locked
+
+      // TODO: throwEarlierClassFailure(klass);
+      return false;
+    }
+
+    if (!ValidateSuperClassDescriptors(klass)) {
+      klass->SetStatus(Class::kStatusError);
+      return false;
+    }
+
+    assert(klass->status < CLASS_INITIALIZING);
+
+    klass->clinit_thread_id_ = self->GetThreadId();
+    klass->status_ = Class::kStatusInitializing;
+  }
+
+  if (!InitializeSuperClass(klass)) {
+    return false;
+  }
+
+  InitializeStaticFields(klass);
+
+  Method* clinit = klass->FindDirectMethodLocally("<clinit>", "()V");
+  if (clinit != NULL) {
+  } else {
+    // JValue unused;
+    // TODO: dvmCallMethod(self, method, NULL, &unused);
+    CHECK(!"unimplemented");
+  }
+
+  {
+    ObjectLock lock(klass);
+
+    if (self->IsExceptionPending()) {
+      klass->SetStatus(Class::kStatusError);
+    } else {
+      klass->SetStatus(Class::kStatusInitialized);
+    }
+    lock.NotifyAll();
+  }
+
+  return true;
+}
+
+bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) {
+  if (klass->IsInterface()) {
+    return true;
+  }
+  // begin with the methods local to the superclass
+  if (klass->HasSuperClass() &&
+      klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
+    const Class* super = klass->GetSuperClass();
+    for (int i = super->NumVirtualMethods() - 1; i >= 0; --i) {
+      const Method* method = klass->GetVirtualMethod(i);
+      if (method != super->GetVirtualMethod(i) &&
+          !HasSameMethodDescriptorClasses(method, super, klass)) {
+        LG << "Classes resolve differently in superclass";
+        return false;
+      }
+    }
+  }
+  for (size_t i = 0; i < klass->iftable_count_; ++i) {
+    const InterfaceEntry* iftable = &klass->iftable_[i];
+    Class* interface = iftable->GetClass();
+    if (klass->GetClassLoader() != interface->GetClassLoader()) {
+      for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
+        uint32_t vtable_index = iftable->method_index_array_[j];
+        const Method* method = klass->GetVirtualMethod(vtable_index);
+        if (!HasSameMethodDescriptorClasses(method, interface,
+                                            method->GetClass())) {
+          LG << "Classes resolve differently in interface";  // TODO: LinkageError
+          return false;
+        }
+      }
+    }
+  }
+  return true;
+}
+
+bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
+                                                const Class* klass1,
+                                                const Class* klass2) {
+  const RawDexFile* raw = method->GetClass()->GetDexFile()->GetRaw();
+  const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_);
+  RawDexFile::ParameterIterator *it;
+  for (it = raw->GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
+    const char* descriptor = it->GetDescriptor();
+    if (descriptor == NULL) {
+      break;
+    }
+    if (descriptor[0] == 'L' || descriptor[0] == '[') {
+      // Found a non-primitive type.
+      if (!HasSameDescriptorClasses(descriptor, klass1, klass2)) {
+        return false;
+      }
+    }
+  }
+  // Check the return type
+  const char* descriptor = raw->GetReturnTypeDescriptor(proto_id);
+  if (descriptor[0] == 'L' || descriptor[0] == '[') {
+    if (HasSameDescriptorClasses(descriptor, klass1, klass2)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Returns true if classes referenced by the descriptor are the
+// same classes in klass1 as they are in klass2.
+bool ClassLinker::HasSameDescriptorClasses(const char* descriptor,
+                                          const Class* klass1,
+                                          const Class* klass2) {
+  CHECK(descriptor != NULL);
+  CHECK(klass1 != NULL);
+  CHECK(klass2 != NULL);
+#if 0
+  Class* found1 = FindClassNoInit(descriptor, klass1->GetClassLoader());
+  // TODO: found1 == NULL
+  Class* found2 = FindClassNoInit(descriptor, klass2->GetClassLoader());
+  // TODO: found2 == NULL
+  // TODO: lookup found1 in initiating loader list
+  if (found1 == NULL || found2 == NULL) {
+    Thread::Self()->ClearException();
+    if (found1 == found2) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+#endif
+  return true;
+}
+
+bool ClassLinker::InitializeSuperClass(Class* klass) {
+  CHECK(klass != NULL);
+  // TODO: assert klass lock is acquired
+  if (!klass->IsInterface() && klass->HasSuperClass()) {
+    Class* super_class = klass->GetSuperClass();
+    if (super_class->GetStatus() != Class::kStatusInitialized) {
+      CHECK(!super_class->IsInterface());
+      klass->MonitorExit();
+      bool super_initialized = InitializeClass(super_class);
+      klass->MonitorEnter();
+      // TODO: check for a pending exception
+      if (!super_initialized) {
+        klass->SetStatus(Class::kStatusError);
+        klass->NotifyAll();
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+void ClassLinker::InitializeStaticFields(Class* klass) {
+  if (klass->NumStaticFields() == 0) {
+    return;
+  } else {
+    LOG(FATAL) << "Unimplemented";
+  }
+}
+
+bool ClassLinker::LinkClass(Class* klass) {
+  CHECK(klass->status_ == Class::kStatusIdx ||
+        klass->status_ == Class::kStatusLoaded);
+  if (klass->status_ == Class::kStatusIdx) {
+    if (!LinkInterfaces(klass)) {
+      return false;
+    }
+  }
+  if (!LinkSuperClass(klass)) {
+    return false;
+  }
+  if (!LinkMethods(klass)) {
+    return false;
+  }
+  if (!LinkInstanceFields(klass)) {
+    return false;
+  }
+  CreateReferenceOffsets(klass);
+  CHECK_EQ(klass->status_, Class::kStatusLoaded);
+  klass->status_ = Class::kStatusResolved;
+  return true;
+}
+
+bool ClassLinker::LinkInterfaces(Class* klass) {
+  scoped_array<uint32_t> interfaces_idx;
+  // TODO: store interfaces_idx in the Class object
+  // TODO: move this outside of link interfaces
+  if (klass->interface_count_ > 0) {
+    interfaces_idx.reset(new uint32_t[klass->interface_count_]);
+    memcpy(interfaces_idx.get(), klass->interfaces_, klass->interface_count_);
+    memset(klass->interfaces_, 0, klass->interface_count_);
+  }
+  // Mark the class as loaded.
+  klass->status_ = Class::kStatusLoaded;
+  if (klass->super_class_idx_ != RawDexFile::kDexNoIndex) {
+    Class* super_class = ResolveClass(klass, klass->super_class_idx_);
+    if (super_class == NULL) {
+      LG << "Failed to resolve superclass";
+      return false;
+    }
+    klass->super_class_ = super_class;  // TODO: write barrier
+  }
+  if (klass->interface_count_ > 0) {
+    for (size_t i = 0; i < klass->interface_count_; ++i) {
+      uint32_t idx = interfaces_idx[i];
+      klass->interfaces_[i] = ResolveClass(klass, idx);
+      if (klass->interfaces_[i] == NULL) {
+        LG << "Failed to resolve interface";
+        return false;
+      }
+      // Verify
+      if (!klass->CanAccess(klass->interfaces_[i])) {
+        LG << "Inaccessible interface";
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool ClassLinker::LinkSuperClass(Class* klass) {
+  CHECK(!klass->IsPrimitive());
+  const Class* super = klass->GetSuperClass();
+  if (klass->GetDescriptor() == "Ljava/lang/Object;") {
+    if (super != NULL) {
+      LG << "Superclass must not be defined";  // TODO: ClassFormatError
+      return false;
+    }
+    // TODO: clear finalize attribute
+    return true;
+  }
+  if (super == NULL) {
+    LG << "No superclass defined";  // TODO: LinkageError
+    return false;
+  }
+  // Verify
+  if (super->IsFinal()) {
+    LG << "Superclass is declared final";  // TODO: IncompatibleClassChangeError
+    return false;
+  }
+  if (super->IsInterface()) {
+    LG << "Superclass is an interface";  // TODO: IncompatibleClassChangeError
+    return false;
+  }
+  if (!klass->CanAccess(super)) {
+    LG << "Superclass is inaccessible";  // TODO: IllegalAccessError
+    return false;
+  }
+  return true;
+}
+
+// Populate the class vtable and itable.
+bool ClassLinker::LinkMethods(Class* klass) {
+  if (klass->IsInterface()) {
+    // No vtable.
+    size_t count = klass->NumVirtualMethods();
+    if (!IsUint(16, count)) {
+      LG << "Too many methods on interface";  // TODO: VirtualMachineError
+      return false;
+    }
+    for (size_t i = 0; i < count; ++count) {
+      klass->GetVirtualMethod(i)->method_index_ = i;
+    }
+  } else {
+    // Link virtual method tables
+    LinkVirtualMethods(klass);
+
+    // Link interface method tables
+    LinkInterfaceMethods(klass);
+
+    // Insert stubs.
+    LinkAbstractMethods(klass);
+  }
+  return true;
+}
+
+bool ClassLinker::LinkVirtualMethods(Class* klass) {
+  uint32_t max_count = klass->NumVirtualMethods();
+  if (klass->GetSuperClass() != NULL) {
+    max_count += klass->GetSuperClass()->NumVirtualMethods();
+  } else {
+    CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
+  }
+  // TODO: do not assign to the vtable field until it is fully constructed.
+  // TODO: make this a vector<Method*> instead?
+  klass->vtable_ = new Method*[max_count];
+  if (klass->HasSuperClass()) {
+    memcpy(klass->vtable_,
+           klass->GetSuperClass()->vtable_,
+           klass->GetSuperClass()->vtable_count_ * sizeof(Method*));
+    size_t actual_count = klass->GetSuperClass()->vtable_count_;
+    // See if any of our virtual methods override the superclass.
+    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+      Method* local_method = klass->GetVirtualMethod(i);
+      size_t j = 0;
+      for (; j < klass->GetSuperClass()->vtable_count_; ++j) {
+        const Method* super_method = klass->vtable_[j];
+        if (local_method->HasSameNameAndPrototype(super_method)) {
+          // Verify
+          if (super_method->IsFinal()) {
+            LG << "Method overrides final method"; // TODO: VirtualMachineError
+            return false;
+          }
+          klass->vtable_[j] = local_method;
+          local_method->method_index_ = j;
+          break;
+        }
+      }
+      if (j == klass->GetSuperClass()->vtable_count_) {
+        // Not overriding, append.
+        klass->vtable_[actual_count] = local_method;
+        local_method->method_index_ = actual_count;
+        actual_count += 1;
+      }
+    }
+    if (!IsUint(16, actual_count)) {
+      LG << "Too many methods defined on class";  // TODO: VirtualMachineError
+      return false;
+    }
+    CHECK_LE(actual_count, max_count);
+    if (actual_count < max_count) {
+      Method** new_vtable = new Method*[actual_count];
+      memcpy(new_vtable, klass->vtable_, actual_count * sizeof(Method*));
+      delete klass->vtable_;
+      klass->vtable_ = new_vtable;
+      LG << "shrunk vtable: "
+         << "was " << max_count << ", "
+         << "now " << actual_count;
+    }
+    klass->vtable_count_ = actual_count;
+  } else {
+    CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
+    if (!IsUint(16, klass->NumVirtualMethods())) {
+      LG << "Too many methods";  // TODO: VirtualMachineError
+      return false;
+    }
+    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+      klass->vtable_[i] = klass->GetVirtualMethod(i);
+      klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
+    }
+    klass->vtable_count_ = klass->NumVirtualMethods();
+  }
+  return true;
+}
+
+bool ClassLinker::LinkInterfaceMethods(Class* klass) {
+  int pool_offset = 0;
+  int pool_size = 0;
+  int miranda_count = 0;
+  int miranda_alloc = 0;
+  size_t super_ifcount;
+  if (klass->HasSuperClass()) {
+    super_ifcount = klass->GetSuperClass()->iftable_count_;
+  } else {
+    super_ifcount = 0;
+  }
+  size_t ifCount = super_ifcount;
+  ifCount += klass->interface_count_;
+  for (size_t i = 0; i < klass->interface_count_; i++) {
+    ifCount += klass->interfaces_[i]->iftable_count_;
+  }
+  if (ifCount == 0) {
+    assert(klass->iftable_count_ == 0);
+    assert(klass->iftable == NULL);
+    return true;
+  }
+  klass->iftable_ = new InterfaceEntry[ifCount * sizeof(InterfaceEntry)];
+  memset(klass->iftable_, 0x00, sizeof(InterfaceEntry) * ifCount);
+  if (super_ifcount != 0) {
+    memcpy(klass->iftable_, klass->GetSuperClass()->iftable_,
+           sizeof(InterfaceEntry) * super_ifcount);
+  }
+  // Flatten the interface inheritance hierarchy.
+  size_t idx = super_ifcount;
+  for (size_t i = 0; i < klass->interface_count_; i++) {
+    Class* interf = klass->interfaces_[i];
+    assert(interf != NULL);
+    if (!interf->IsInterface()) {
+      LG << "Class implements non-interface class";  // TODO: IncompatibleClassChangeError
+      return false;
+    }
+    klass->iftable_[idx++].SetClass(interf);
+    for (size_t j = 0; j < interf->iftable_count_; j++) {
+      klass->iftable_[idx++].SetClass(interf->iftable_[j].GetClass());
+    }
+  }
+  CHECK_EQ(idx, ifCount);
+  klass->iftable_count_ = ifCount;
+  if (klass->IsInterface() || super_ifcount == ifCount) {
+    return true;
+  }
+  for (size_t i = super_ifcount; i < ifCount; i++) {
+    pool_size += klass->iftable_[i].GetClass()->NumVirtualMethods();
+  }
+  if (pool_size == 0) {
+    return true;
+  }
+  klass->ifvi_pool_count_ = pool_size;
+  klass->ifvi_pool_ = new uint32_t[pool_size];
+  std::vector<Method*> miranda_list;
+  for (size_t i = super_ifcount; i < ifCount; ++i) {
+    klass->iftable_[i].method_index_array_ = klass->ifvi_pool_ + pool_offset;
+    Class* interface = klass->iftable_[i].GetClass();
+    pool_offset += interface->NumVirtualMethods();    // end here
+    for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
+      Method* interface_method = interface->GetVirtualMethod(j);
+      int k;  // must be signed
+      for (k = klass->vtable_count_ - 1; k >= 0; --k) {
+        if (interface_method->HasSameNameAndPrototype(klass->vtable_[k])) {
+          if (klass->vtable_[k]->IsPublic()) {
+            LG << "Implementation not public";
+            return false;
+          }
+          klass->iftable_[i].method_index_array_[j] = k;
+          break;
+        }
+      }
+      if (k < 0) {
+        if (miranda_count == miranda_alloc) {
+          miranda_alloc += 8;
+          if (miranda_list.empty()) {
+            miranda_list.resize(miranda_alloc);
+          } else {
+            miranda_list.resize(miranda_alloc);
+          }
+        }
+        int mir;
+        for (mir = 0; mir < miranda_count; mir++) {
+          if (miranda_list[mir]->HasSameNameAndPrototype(interface_method)) {
+            break;
+          }
+        }
+        // point the interface table at a phantom slot index
+        klass->iftable_[i].method_index_array_[j] = klass->vtable_count_ + mir;
+        if (mir == miranda_count) {
+          miranda_list[miranda_count++] = interface_method;
+        }
+      }
+    }
+  }
+  if (miranda_count != 0) {
+    Method* newVirtualMethods;
+    Method* meth;
+    int oldMethodCount, oldVtableCount;
+    if (klass->virtual_methods_ == NULL) {
+      newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
+
+    } else {
+      newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
+      memcpy(newVirtualMethods,
+             klass->virtual_methods_,
+             klass->NumVirtualMethods() * sizeof(Method));
+
+    }
+    if (newVirtualMethods != klass->virtual_methods_) {
+      Method* meth = newVirtualMethods;
+      for (size_t i = 0; i < klass->NumVirtualMethods(); i++, meth++) {
+        klass->vtable_[meth->method_index_] = meth;
+      }
+    }
+    oldMethodCount = klass->NumVirtualMethods();
+    klass->virtual_methods_ = newVirtualMethods;
+    klass->num_virtual_methods_ += miranda_count;
+
+    CHECK(klass->vtable_ != NULL);
+    oldVtableCount = klass->vtable_count_;
+    klass->vtable_count_ += miranda_count;
+
+    meth = klass->virtual_methods_ + oldMethodCount;
+    for (int i = 0; i < miranda_count; i++, meth++) {
+      memcpy(meth, miranda_list[i], sizeof(Method));
+      meth->klass_ = klass;
+      meth->access_flags_ |= kAccMiranda;
+      meth->method_index_ = 0xFFFF & (oldVtableCount + i);
+      klass->vtable_[oldVtableCount + i] = meth;
+    }
+  }
+  return true;
+}
+
+void ClassLinker::LinkAbstractMethods(Class* klass) {
+  for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+    Method* method = klass->GetVirtualMethod(i);
+    if (method->IsAbstract()) {
+      method->insns_ = reinterpret_cast<uint16_t*>(0xFFFFFFFF);  // TODO: AbstractMethodError
+    }
+  }
+}
+
+bool ClassLinker::LinkInstanceFields(Class* klass) {
+  int fieldOffset;
+  if (klass->GetSuperClass() != NULL) {
+    fieldOffset = klass->GetSuperClass()->object_size_;
+  } else {
+    fieldOffset = OFFSETOF_MEMBER(DataObject, fields_);
+  }
+  // Move references to the front.
+  klass->num_reference_ifields_ = 0;
+  size_t i = 0;
+  size_t j = klass->NumInstanceFields() - 1;
+  for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
+    InstanceField* pField = klass->GetInstanceField(i);
+    char c = pField->GetType();
+
+    if (c != '[' && c != 'L') {
+      while (j > i) {
+        InstanceField* refField = klass->GetInstanceField(j--);
+        char rc = refField->GetType();
+        if (rc == '[' || rc == 'L') {
+          pField->Swap(refField);
+          c = rc;
+          klass->num_reference_ifields_++;
+          break;
+        }
+      }
+    } else {
+      klass->num_reference_ifields_++;
+    }
+    if (c != '[' && c != 'L') {
+      break;
+    }
+    pField->SetOffset(fieldOffset);
+    fieldOffset += sizeof(uint32_t);
+  }
+
+  // Now we want to pack all of the double-wide fields together.  If
+  // we're not aligned, though, we want to shuffle one 32-bit field
+  // into place.  If we can't find one, we'll have to pad it.
+  if (i != klass->NumInstanceFields() && (fieldOffset & 0x04) != 0) {
+    InstanceField* pField = klass->GetInstanceField(i);
+    char c = pField->GetType();
+
+    if (c != 'J' && c != 'D') {
+      // The field that comes next is 32-bit, so just advance past it.
+      assert(c != '[' && c != 'L');
+      pField->SetOffset(fieldOffset);
+      fieldOffset += sizeof(uint32_t);
+      i++;
+    } else {
+      // Next field is 64-bit, so search for a 32-bit field we can
+      // swap into it.
+      bool found = false;
+      j = klass->NumInstanceFields() - 1;
+      while (j > i) {
+        InstanceField* singleField = klass->GetInstanceField(j--);
+        char rc = singleField->GetType();
+        if (rc != 'J' && rc != 'D') {
+          pField->Swap(singleField);
+          pField->SetOffset(fieldOffset);
+          fieldOffset += sizeof(uint32_t);
+          found = true;
+          i++;
+          break;
+        }
+      }
+      if (!found) {
+        fieldOffset += sizeof(uint32_t);
+      }
+    }
+  }
+
+  // Alignment is good, shuffle any double-wide fields forward, and
+  // finish assigning field offsets to all fields.
+  assert(i == klass->NumInstanceFields() || (fieldOffset & 0x04) == 0);
+  j = klass->NumInstanceFields() - 1;
+  for ( ; i < klass->NumInstanceFields(); i++) {
+    InstanceField* pField = klass->GetInstanceField(i);
+    char c = pField->GetType();
+    if (c != 'D' && c != 'J') {
+      while (j > i) {
+        InstanceField* doubleField = klass->GetInstanceField(j--);
+        char rc = doubleField->GetType();
+        if (rc == 'D' || rc == 'J') {
+          pField->Swap(doubleField);
+          c = rc;
+          break;
+        }
+      }
+    } else {
+      // This is a double-wide field, leave it be.
+    }
+
+    pField->SetOffset(fieldOffset);
+    fieldOffset += sizeof(uint32_t);
+    if (c == 'J' || c == 'D')
+      fieldOffset += sizeof(uint32_t);
+  }
+
+#ifndef NDEBUG
+  /* Make sure that all reference fields appear before
+   * non-reference fields, and all double-wide fields are aligned.
+   */
+  j = 0;  // seen non-ref
+  for (i = 0; i < klass->NumInstanceFields(); i++) {
+    InstanceField *pField = &klass->ifields[i];
+    char c = pField->GetType();
+
+    if (c == 'D' || c == 'J') {
+      assert((pField->offset_ & 0x07) == 0);
+    }
+
+    if (c != '[' && c != 'L') {
+      if (!j) {
+        assert(i == klass->num_reference_ifields_);
+        j = 1;
+      }
+    } else if (j) {
+      assert(false);
+    }
+  }
+  if (!j) {
+    assert(klass->num_reference_ifields_ == klass->NumInstanceFields());
+  }
+#endif
+
+  klass->object_size_ = fieldOffset;
+  return true;
+}
+
+//  Set the bitmap of reference offsets, refOffsets, from the ifields
+//  list.
+void ClassLinker::CreateReferenceOffsets(Class* klass) {
+  uint32_t reference_offsets = 0;
+  if (klass->HasSuperClass()) {
+    reference_offsets = klass->GetSuperClass()->GetReferenceOffsets();
+  }
+  // If our superclass overflowed, we don't stand a chance.
+  if (reference_offsets != CLASS_WALK_SUPER) {
+    // All of the fields that contain object references are guaranteed
+    // to be at the beginning of the ifields list.
+    for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
+      // Note that, per the comment on struct InstField, f->byteOffset
+      // is the offset from the beginning of obj, not the offset into
+      // obj->instanceData.
+      const InstanceField* field = klass->GetInstanceField(i);
+      size_t byte_offset = field->GetOffset();
+      CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
+      CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0);
+      if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
+        uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
+        CHECK_NE(new_bit, 0);
+        reference_offsets |= new_bit;
+      } else {
+        reference_offsets = CLASS_WALK_SUPER;
+        break;
+      }
+    }
+    klass->SetReferenceOffsets(reference_offsets);
+  }
+}
+
+Class* ClassLinker::ResolveClass(Class* referrer, uint32_t class_idx) {
+  DexFile* dex_file = referrer->GetDexFile();
+  Class* resolved = dex_file->GetResolvedClass(class_idx);
+  if (resolved != NULL) {
+    return resolved;
+  }
+  const char* descriptor = dex_file->GetRaw()->dexStringByTypeIdx(class_idx);
+  if (descriptor[0] != '\0' && descriptor[1] == '\0') {
+    resolved = FindPrimitiveClass(descriptor);
+  } else {
+    resolved = FindClass(descriptor, referrer->GetClassLoader(), NULL);
+  }
+  if (resolved != NULL) {
+    Class* check = resolved->IsArray() ? resolved->component_type_ : resolved;
+    if (referrer->GetDexFile() != check->GetDexFile()) {
+      if (check->GetClassLoader() != NULL) {
+        LG << "Class resolved by unexpected DEX";  // TODO: IllegalAccessError
+        return NULL;
+      }
+    }
+    dex_file->SetResolvedClass(class_idx, resolved);
+  } else {
+    CHECK(Thread::Self()->IsExceptionPending());
+  }
+  return resolved;
+}
+
+Method* ResolveMethod(const Class* referrer, uint32_t method_idx,
+                      /*MethodType*/ int method_type) {
+  CHECK(false);
+  return NULL;
+}
+
+}  // namespace art