Set vtable in class object to null after linking.

This is follow-up work of embedding imt and vtable for
faster interface/virtual call dispatching.
Once vtable becomes embedded, the original vtable is nulled.

Change-Id: I307696657d1e283654169dbecb8f7815c42bbabc
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 329a984..c3754d7 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -161,6 +161,37 @@
   CHECK(method == GetImTable()->Get(i));
 }
 
+inline bool Class::HasVTable() {
+  return (GetVTable() != nullptr) || ShouldHaveEmbeddedImtAndVTable();
+}
+
+inline int32_t Class::GetVTableLength() {
+  if (ShouldHaveEmbeddedImtAndVTable()) {
+    return GetEmbeddedVTableLength();
+  }
+  return (GetVTable() != nullptr) ? GetVTable()->GetLength() : 0;
+}
+
+inline ArtMethod* Class::GetVTableEntry(uint32_t i) {
+  if (ShouldHaveEmbeddedImtAndVTable()) {
+    return GetEmbeddedVTableEntry(i);
+  }
+  return (GetVTable() != nullptr) ? GetVTable()->Get(i) : nullptr;
+}
+
+inline int32_t Class::GetEmbeddedVTableLength() {
+  return GetField32(EmbeddedVTableLengthOffset());
+}
+
+inline void Class::SetEmbeddedVTableLength(int32_t len) {
+  SetField32<false>(EmbeddedVTableLengthOffset(), len);
+}
+
+inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i) {
+  uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
+  return GetFieldObject<mirror::ArtMethod>(MemberOffset(offset));
+}
+
 inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method) {
   uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
   SetFieldObject<false>(MemberOffset(offset), method);
@@ -340,12 +371,12 @@
   DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
   // The argument method may from a super class.
   // Use the index to a potentially overridden one for this instance's class.
-  return GetVTable()->Get(method->GetMethodIndex());
+  return GetVTableEntry(method->GetMethodIndex());
 }
 
 inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) {
   DCHECK(!method->GetDeclaringClass()->IsInterface());
-  return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
+  return GetSuperClass()->GetVTableEntry(method->GetMethodIndex());
 }
 
 inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) {
@@ -534,13 +565,19 @@
   if (has_embedded_tables) {
     uint32_t embedded_imt_size = kImtSize * sizeof(ImTableEntry);
     uint32_t embedded_vtable_size = num_vtable_entries * sizeof(VTableEntry);
-    size += embedded_imt_size + embedded_vtable_size;
+    size += embedded_imt_size +
+            sizeof(int32_t) /* vtable len */ +
+            embedded_vtable_size;
   }
   // Space used by reference statics.
   size +=  num_ref_static_fields * sizeof(HeapReference<Object>);
   // Possible pad for alignment.
-  if (((size & 7) != 0) && (num_64bit_static_fields > 0) && (num_32bit_static_fields == 0)) {
+  if (((size & 7) != 0) && (num_64bit_static_fields > 0)) {
     size += sizeof(uint32_t);
+    if (num_32bit_static_fields != 0) {
+      // Shuffle one 32 bit static field forward.
+      num_32bit_static_fields--;
+    }
   }
   // Space used for primitive static fields.
   size += (num_32bit_static_fields * sizeof(uint32_t)) +
@@ -574,7 +611,10 @@
     pos += sizeof(ImTableEntry);
   }
 
-  count = ((GetVTable() != NULL) ? GetVTable()->GetLength() : 0);
+  // Skip vtable length.
+  pos += sizeof(int32_t);
+
+  count = GetEmbeddedVTableLength();
   for (size_t i = 0; i < count; ++i) {
     MemberOffset offset = MemberOffset(pos);
     visitor(this, offset, true);