/*
 * 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.
 */

#include "class_linker.h"

#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <deque>
#include <string>
#include <utility>
#include <vector>

#include "base/casts.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "debugger.h"
#include "dex_file-inl.h"
#include "gc/card_table-inl.h"
#include "heap.h"
#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "leb128.h"
#include "oat.h"
#include "oat_file.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache.h"
#include "mirror/field-inl.h"
#include "mirror/iftable-inl.h"
#include "mirror/abstract_method.h"
#include "mirror/abstract_method-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
#include "mirror/stack_trace_element.h"
#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "runtime_support.h"
#if defined(ART_USE_PORTABLE_COMPILER)
#include "compiler/llvm/runtime_support_llvm.h"
#endif
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
#include "sirt_ref.h"
#include "gc/space.h"
#include "gc/space_bitmap.h"
#include "stack_indirect_reference_table.h"
#include "thread.h"
#include "UniquePtr.h"
#include "utils.h"
#include "verifier/method_verifier.h"
#include "well_known_classes.h"

namespace art {

static void ThrowNoClassDefFoundError(const char* fmt, ...)
    __attribute__((__format__(__printf__, 1, 2)))
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void ThrowNoClassDefFoundError(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  Thread* self = Thread::Current();
  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
  self->ThrowNewExceptionV(throw_location, "Ljava/lang/NoClassDefFoundError;", fmt, args);
  va_end(args);
}

static void ThrowEarlierClassFailure(mirror::Class* c)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  // The class failed to initialize on a previous attempt, so we want to throw
  // a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
  // failed in verification, in which case v2 5.4.1 says we need to re-throw
  // the previous error.
  if (!Runtime::Current()->IsCompiler()) {  // Give info if this occurs at runtime.
    LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c);
  }

  CHECK(c->IsErroneous()) << PrettyClass(c) << " " << c->GetStatus();
  Thread* self = Thread::Current();
  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
  if (c->GetVerifyErrorClass() != NULL) {
    // TODO: change the verifier to store an _instance_, with a useful detail message?
    ClassHelper ve_ch(c->GetVerifyErrorClass());
    self->ThrowNewException(throw_location, ve_ch.GetDescriptor(), PrettyDescriptor(c).c_str());
  } else {
    self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
                            PrettyDescriptor(c).c_str());
  }
}

static void WrapExceptionInInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  Thread* self = Thread::Current();
  JNIEnv* env = self->GetJniEnv();

  ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
  CHECK(cause.get() != NULL);

  env->ExceptionClear();
  bool is_error = env->IsInstanceOf(cause.get(), WellKnownClasses::java_lang_Error);
  env->Throw(cause.get());

  // We only wrap non-Error exceptions; an Error can just be used as-is.
  if (!is_error) {
    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    self->ThrowNewWrappedException(throw_location, "Ljava/lang/ExceptionInInitializerError;", NULL);
  }
}

static size_t Hash(const char* s) {
  // This is the java.lang.String hashcode for convenience, not interoperability.
  size_t hash = 0;
  for (; *s != '\0'; ++s) {
    hash = hash * 31 + *s;
  }
  return hash;
}

const char* ClassLinker::class_roots_descriptors_[] = {
  "Ljava/lang/Class;",
  "Ljava/lang/Object;",
  "[Ljava/lang/Class;",
  "[Ljava/lang/Object;",
  "Ljava/lang/String;",
  "Ljava/lang/DexCache;",
  "Ljava/lang/ref/Reference;",
  "Ljava/lang/reflect/Constructor;",
  "Ljava/lang/reflect/Field;",
  "Ljava/lang/reflect/AbstractMethod;",
  "Ljava/lang/reflect/Method;",
  "Ljava/lang/reflect/Proxy;",
  "[Ljava/lang/String;",
  "[Ljava/lang/reflect/AbstractMethod;",
  "[Ljava/lang/reflect/Field;",
  "[Ljava/lang/reflect/Method;",
  "Ljava/lang/ClassLoader;",
  "Ljava/lang/Throwable;",
  "Ljava/lang/ClassNotFoundException;",
  "Ljava/lang/StackTraceElement;",
  "Z",
  "B",
  "C",
  "D",
  "F",
  "I",
  "J",
  "S",
  "V",
  "[Z",
  "[B",
  "[C",
  "[D",
  "[F",
  "[I",
  "[J",
  "[S",
  "[Ljava/lang/StackTraceElement;",
};

ClassLinker* ClassLinker::CreateFromCompiler(const std::vector<const DexFile*>& boot_class_path,
                                             InternTable* intern_table) {
  CHECK_NE(boot_class_path.size(), 0U);
  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
  class_linker->InitFromCompiler(boot_class_path);
  return class_linker.release();
}

ClassLinker* ClassLinker::CreateFromImage(InternTable* intern_table) {
  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
  class_linker->InitFromImage();
  return class_linker.release();
}

ClassLinker::ClassLinker(InternTable* intern_table)
    // dex_lock_ is recursive as it may be used in stack dumping.
    : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel, true),
      class_roots_(NULL),
      array_iftable_(NULL),
      init_done_(false),
      is_dirty_(false),
      intern_table_(intern_table) {
  CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
}

void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
  VLOG(startup) << "ClassLinker::Init";
  CHECK(Runtime::Current()->IsCompiler());

  CHECK(!init_done_);

  // java_lang_Class comes first, it's needed for AllocClass
  Thread* self = Thread::Current();
  Heap* heap = Runtime::Current()->GetHeap();
  SirtRef<mirror::Class>
      java_lang_Class(self,
                      down_cast<mirror::Class*>(heap->AllocObject(self, NULL,
                                                                  sizeof(mirror::ClassClass))));
  CHECK(java_lang_Class.get() != NULL);
  mirror::Class::SetClassClass(java_lang_Class.get());
  java_lang_Class->SetClass(java_lang_Class.get());
  java_lang_Class->SetClassSize(sizeof(mirror::ClassClass));
  // AllocClass(mirror::Class*) can now be used

  // Class[] is used for reflection support.
  SirtRef<mirror::Class> class_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  class_array_class->SetComponentType(java_lang_Class.get());

  // java_lang_Object comes next so that object_array_class can be created.
  SirtRef<mirror::Class> java_lang_Object(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  CHECK(java_lang_Object.get() != NULL);
  // backfill Object as the super class of Class.
  java_lang_Class->SetSuperClass(java_lang_Object.get());
  java_lang_Object->SetStatus(mirror::Class::kStatusLoaded);

  // Object[] next to hold class roots.
  SirtRef<mirror::Class> object_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  object_array_class->SetComponentType(java_lang_Object.get());

  // Setup the char class to be used for char[].
  SirtRef<mirror::Class> char_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));

  // Setup the char[] class to be used for String.
  SirtRef<mirror::Class> char_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  char_array_class->SetComponentType(char_class.get());
  mirror::CharArray::SetArrayClass(char_array_class.get());

  // Setup String.
  SirtRef<mirror::Class> java_lang_String(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::StringClass)));
  mirror::String::SetClass(java_lang_String.get());
  java_lang_String->SetObjectSize(sizeof(mirror::String));
  java_lang_String->SetStatus(mirror::Class::kStatusResolved);

  // Create storage for root classes, save away our work so far (requires descriptors).
  class_roots_ = mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.get(), kClassRootsMax);
  CHECK(class_roots_ != NULL);
  SetClassRoot(kJavaLangClass, java_lang_Class.get());
  SetClassRoot(kJavaLangObject, java_lang_Object.get());
  SetClassRoot(kClassArrayClass, class_array_class.get());
  SetClassRoot(kObjectArrayClass, object_array_class.get());
  SetClassRoot(kCharArrayClass, char_array_class.get());
  SetClassRoot(kJavaLangString, java_lang_String.get());

  // Setup the primitive type classes.
  SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
  SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte));
  SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort));
  SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt));
  SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong));
  SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat));
  SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble));
  SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid));

  // Create array interface entries to populate once we can load system classes.
  array_iftable_ = AllocIfTable(self, 2);

  // Create int array type for AllocDexCache (done in AppendToBootClassPath).
  SirtRef<mirror::Class> int_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
  mirror::IntArray::SetArrayClass(int_array_class.get());
  SetClassRoot(kIntArrayClass, int_array_class.get());

  // now that these are registered, we can use AllocClass() and AllocObjectArray

  // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache.
  SirtRef<mirror::Class>
      java_lang_DexCache(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::DexCacheClass)));
  SetClassRoot(kJavaLangDexCache, java_lang_DexCache.get());
  java_lang_DexCache->SetObjectSize(sizeof(mirror::DexCacheClass));
  java_lang_DexCache->SetStatus(mirror::Class::kStatusResolved);

  // Constructor, Field, Method, and AbstractMethod are necessary so that FindClass can link members.
  SirtRef<mirror::Class> java_lang_reflect_Field(self, AllocClass(self, java_lang_Class.get(),
                                                          sizeof(mirror::FieldClass)));
  CHECK(java_lang_reflect_Field.get() != NULL);
  java_lang_reflect_Field->SetObjectSize(sizeof(mirror::Field));
  SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field.get());
  java_lang_reflect_Field->SetStatus(mirror::Class::kStatusResolved);
  mirror::Field::SetClass(java_lang_reflect_Field.get());

  SirtRef<mirror::Class> java_lang_reflect_AbstractMethod(self, AllocClass(self, java_lang_Class.get(),
                                                                           sizeof(mirror::AbstractMethodClass)));
  CHECK(java_lang_reflect_AbstractMethod.get() != NULL);
  java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(mirror::AbstractMethod));
  SetClassRoot(kJavaLangReflectAbstractMethod, java_lang_reflect_AbstractMethod.get());
  java_lang_reflect_AbstractMethod->SetStatus(mirror::Class::kStatusResolved);

  SirtRef<mirror::Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(),
                                                                        sizeof(mirror::AbstractMethodClass)));
  CHECK(java_lang_reflect_Constructor.get() != NULL);
  java_lang_reflect_Constructor->SetObjectSize(sizeof(mirror::Constructor));
  java_lang_reflect_Constructor->SetSuperClass(java_lang_reflect_AbstractMethod.get());
  SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
  java_lang_reflect_Constructor->SetStatus(mirror::Class::kStatusResolved);

  SirtRef<mirror::Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(),
                                                                   sizeof(mirror::AbstractMethodClass)));
  CHECK(java_lang_reflect_Method.get() != NULL);
  java_lang_reflect_Method->SetObjectSize(sizeof(mirror::Method));
  java_lang_reflect_Method->SetSuperClass(java_lang_reflect_AbstractMethod.get());
  SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
  java_lang_reflect_Method->SetStatus(mirror::Class::kStatusResolved);

  mirror::AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(),
                                     java_lang_reflect_Method.get());

  // Set up array classes for string, field, method
  SirtRef<mirror::Class> object_array_string(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  object_array_string->SetComponentType(java_lang_String.get());
  SetClassRoot(kJavaLangStringArrayClass, object_array_string.get());

  SirtRef<mirror::Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
  SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());

  SirtRef<mirror::Class> object_array_field(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  object_array_field->SetComponentType(java_lang_reflect_Field.get());
  SetClassRoot(kJavaLangReflectFieldArrayClass, object_array_field.get());

  SirtRef<mirror::Class> object_array_method(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class)));
  object_array_method->SetComponentType(java_lang_reflect_Method.get());
  SetClassRoot(kJavaLangReflectMethodArrayClass, object_array_method.get());

  // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
  // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
  // these roots.
  CHECK_NE(0U, boot_class_path.size());
  for (size_t i = 0; i != boot_class_path.size(); ++i) {
    const DexFile* dex_file = boot_class_path[i];
    CHECK(dex_file != NULL);
    AppendToBootClassPath(*dex_file);
  }

  // now we can use FindSystemClass

  // run char class through InitializePrimitiveClass to finish init
  InitializePrimitiveClass(char_class.get(), Primitive::kPrimChar);
  SetClassRoot(kPrimitiveChar, char_class.get());  // needs descriptor

  // Object, String and DexCache need to be rerun through FindSystemClass to finish init
  java_lang_Object->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* Object_class = FindSystemClass("Ljava/lang/Object;");
  CHECK_EQ(java_lang_Object.get(), Object_class);
  CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(mirror::Object));
  java_lang_String->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* String_class = FindSystemClass("Ljava/lang/String;");
  CHECK_EQ(java_lang_String.get(), String_class);
  CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(mirror::String));
  java_lang_DexCache->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;");
  CHECK_EQ(java_lang_String.get(), String_class);
  CHECK_EQ(java_lang_DexCache.get(), DexCache_class);
  CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(mirror::DexCache));

  // Setup the primitive array type classes - can't be done until Object has a vtable.
  SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
  mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));

  SetClassRoot(kByteArrayClass, FindSystemClass("[B"));
  mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));

  mirror::Class* found_char_array_class = FindSystemClass("[C");
  CHECK_EQ(char_array_class.get(), found_char_array_class);

  SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
  mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));

  mirror::Class* found_int_array_class = FindSystemClass("[I");
  CHECK_EQ(int_array_class.get(), found_int_array_class);

  SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
  mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));

  SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
  mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));

  SetClassRoot(kDoubleArrayClass, FindSystemClass("[D"));
  mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));

  mirror::Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;");
  CHECK_EQ(class_array_class.get(), found_class_array_class);

  mirror::Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
  CHECK_EQ(object_array_class.get(), found_object_array_class);

  // Setup the single, global copy of "iftable".
  mirror::Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
  CHECK(java_lang_Cloneable != NULL);
  mirror::Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
  CHECK(java_io_Serializable != NULL);
  // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
  // crawl up and explicitly list all of the supers as well.
  array_iftable_->SetInterface(0, java_lang_Cloneable);
  array_iftable_->SetInterface(1, java_io_Serializable);

  // Sanity check Class[] and Object[]'s interfaces.
  ClassHelper kh(class_array_class.get(), this);
  CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
  CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
  kh.ChangeClass(object_array_class.get());
  CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
  CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
  // Run Class, Constructor, Field, and Method through FindSystemClass. This initializes their
  // dex_cache_ fields and register them in classes_.
  mirror::Class* Class_class = FindSystemClass("Ljava/lang/Class;");
  CHECK_EQ(java_lang_Class.get(), Class_class);

  java_lang_reflect_AbstractMethod->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* Abstract_method_class = FindSystemClass("Ljava/lang/reflect/AbstractMethod;");
  CHECK_EQ(java_lang_reflect_AbstractMethod.get(), Abstract_method_class);

  // Method extends AbstractMethod so must reset after.
  java_lang_reflect_Method->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
  CHECK_EQ(java_lang_reflect_Method.get(), Method_class);

  // Constructor extends AbstractMethod so must reset after.
  java_lang_reflect_Constructor->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;");
  CHECK_EQ(java_lang_reflect_Constructor.get(), Constructor_class);

  java_lang_reflect_Field->SetStatus(mirror::Class::kStatusNotReady);
  mirror::Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
  CHECK_EQ(java_lang_reflect_Field.get(), Field_class);

  mirror::Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]);
  CHECK_EQ(object_array_string.get(), String_array_class);

  mirror::Class* Abstract_method_array_class =
      FindSystemClass(class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]);
  CHECK_EQ(object_array_abstract_method.get(), Abstract_method_array_class);

  mirror::Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]);
  CHECK_EQ(object_array_field.get(), Field_array_class);

  mirror::Class* Method_array_class =
      FindSystemClass(class_roots_descriptors_[kJavaLangReflectMethodArrayClass]);
  CHECK_EQ(object_array_method.get(), Method_array_class);

  // End of special init trickery, subsequent classes may be loaded via FindSystemClass.

  // Create java.lang.reflect.Proxy root.
  mirror::Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;");
  SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);

  // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
  mirror::Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
  SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference);
  mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
  java_lang_ref_FinalizerReference->SetAccessFlags(
      java_lang_ref_FinalizerReference->GetAccessFlags() |
          kAccClassIsReference | kAccClassIsFinalizerReference);
  mirror::Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;");
  java_lang_ref_PhantomReference->SetAccessFlags(
      java_lang_ref_PhantomReference->GetAccessFlags() |
          kAccClassIsReference | kAccClassIsPhantomReference);
  mirror::Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;");
  java_lang_ref_SoftReference->SetAccessFlags(
      java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference);
  mirror::Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;");
  java_lang_ref_WeakReference->SetAccessFlags(
      java_lang_ref_WeakReference->GetAccessFlags() |
          kAccClassIsReference | kAccClassIsWeakReference);

  // Setup the ClassLoader, verifying the object_size_.
  mirror::Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;");
  CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(mirror::ClassLoader));
  SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);

  // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
  // java.lang.StackTraceElement as a convenience.
  SetClassRoot(kJavaLangThrowable, FindSystemClass("Ljava/lang/Throwable;"));
  mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
  SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass("Ljava/lang/ClassNotFoundException;"));
  SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;"));
  SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;"));
  mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));

  FinishInit();

  VLOG(startup) << "ClassLinker::InitFromCompiler exiting";
}

void ClassLinker::FinishInit() {
  VLOG(startup) << "ClassLinker::FinishInit entering";

  // Let the heap know some key offsets into java.lang.ref instances
  // Note: we hard code the field indexes here rather than using FindInstanceField
  // as the types of the field can't be resolved prior to the runtime being
  // fully initialized
  mirror::Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference);
  mirror::Class* java_lang_ref_ReferenceQueue = FindSystemClass("Ljava/lang/ref/ReferenceQueue;");
  mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");

  const DexFile& java_lang_dex = *java_lang_ref_Reference->GetDexCache()->GetDexFile();

  mirror::Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
  FieldHelper fh(pendingNext, this);
  CHECK_STREQ(fh.GetName(), "pendingNext");
  CHECK_EQ(java_lang_dex.GetFieldId(pendingNext->GetDexFieldIndex()).type_idx_,
           java_lang_ref_Reference->GetDexTypeIndex());

  mirror::Field* queue = java_lang_ref_Reference->GetInstanceField(1);
  fh.ChangeField(queue);
  CHECK_STREQ(fh.GetName(), "queue");
  CHECK_EQ(java_lang_dex.GetFieldId(queue->GetDexFieldIndex()).type_idx_,
           java_lang_ref_ReferenceQueue->GetDexTypeIndex());

  mirror::Field* queueNext = java_lang_ref_Reference->GetInstanceField(2);
  fh.ChangeField(queueNext);
  CHECK_STREQ(fh.GetName(), "queueNext");
  CHECK_EQ(java_lang_dex.GetFieldId(queueNext->GetDexFieldIndex()).type_idx_,
           java_lang_ref_Reference->GetDexTypeIndex());

  mirror::Field* referent = java_lang_ref_Reference->GetInstanceField(3);
  fh.ChangeField(referent);
  CHECK_STREQ(fh.GetName(), "referent");
  CHECK_EQ(java_lang_dex.GetFieldId(referent->GetDexFieldIndex()).type_idx_,
           GetClassRoot(kJavaLangObject)->GetDexTypeIndex());

  mirror::Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
  fh.ChangeField(zombie);
  CHECK_STREQ(fh.GetName(), "zombie");
  CHECK_EQ(java_lang_dex.GetFieldId(zombie->GetDexFieldIndex()).type_idx_,
           GetClassRoot(kJavaLangObject)->GetDexTypeIndex());

  Heap* heap = Runtime::Current()->GetHeap();
  heap->SetReferenceOffsets(referent->GetOffset(),
                            queue->GetOffset(),
                            queueNext->GetOffset(),
                            pendingNext->GetOffset(),
                            zombie->GetOffset());

  // ensure all class_roots_ are initialized
  for (size_t i = 0; i < kClassRootsMax; i++) {
    ClassRoot class_root = static_cast<ClassRoot>(i);
    mirror::Class* klass = GetClassRoot(class_root);
    CHECK(klass != NULL);
    DCHECK(klass->IsArrayClass() || klass->IsPrimitive() || klass->GetDexCache() != NULL);
    // note SetClassRoot does additional validation.
    // if possible add new checks there to catch errors early
  }

  CHECK(array_iftable_ != NULL);

  // disable the slow paths in FindClass and CreatePrimitiveClass now
  // that Object, Class, and Object[] are setup
  init_done_ = true;

  VLOG(startup) << "ClassLinker::FinishInit exiting";
}

void ClassLinker::RunRootClinits() {
  Thread* self = Thread::Current();
  for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
    mirror::Class* c = GetClassRoot(ClassRoot(i));
    if (!c->IsArrayClass() && !c->IsPrimitive()) {
      EnsureInitialized(GetClassRoot(ClassRoot(i)), true, true);
      self->AssertNoPendingException();
    }
  }
}

bool ClassLinker::GenerateOatFile(const std::string& dex_filename,
                                  int oat_fd,
                                  const std::string& oat_cache_filename) {
  std::string dex2oat_string(GetAndroidRoot());
  dex2oat_string += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
  const char* dex2oat = dex2oat_string.c_str();

  const char* class_path = Runtime::Current()->GetClassPathString().c_str();

  Heap* heap = Runtime::Current()->GetHeap();
  std::string boot_image_option_string("--boot-image=");
  boot_image_option_string += heap->GetImageSpace()->GetImageFilename();
  const char* boot_image_option = boot_image_option_string.c_str();

  std::string dex_file_option_string("--dex-file=");
  dex_file_option_string += dex_filename;
  const char* dex_file_option = dex_file_option_string.c_str();

  std::string oat_fd_option_string("--oat-fd=");
  StringAppendF(&oat_fd_option_string, "%d", oat_fd);
  const char* oat_fd_option = oat_fd_option_string.c_str();

  std::string oat_location_option_string("--oat-location=");
  oat_location_option_string += oat_cache_filename;
  const char* oat_location_option = oat_location_option_string.c_str();

  // fork and exec dex2oat
  pid_t pid = fork();
  if (pid == 0) {
    // no allocation allowed between fork and exec

    // change process groups, so we don't get reaped by ProcessManager
    setpgid(0, 0);

    VLOG(class_linker) << dex2oat
                       << " --runtime-arg -Xms64m"
                       << " --runtime-arg -Xmx64m"
                       << " --runtime-arg -classpath"
                       << " --runtime-arg " << class_path
#if !defined(ART_TARGET)
                       << " --host"
#endif
                       << " " << boot_image_option
                       << " " << dex_file_option
                       << " " << oat_fd_option
                       << " " << oat_location_option;

    execl(dex2oat, dex2oat,
          "--runtime-arg", "-Xms64m",
          "--runtime-arg", "-Xmx64m",
          "--runtime-arg", "-classpath",
          "--runtime-arg", class_path,
#if !defined(ART_TARGET)
          "--host",
#endif
          boot_image_option,
          dex_file_option,
          oat_fd_option,
          oat_location_option,
          NULL);

    PLOG(FATAL) << "execl(" << dex2oat << ") failed";
    return false;
  } else {
    // wait for dex2oat to finish
    int status;
    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
    if (got_pid != pid) {
      PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid;
      return false;
    }
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
      LOG(ERROR) << dex2oat << " failed with dex-file=" << dex_filename;
      return false;
    }
  }
  return true;
}

void ClassLinker::RegisterOatFile(const OatFile& oat_file) {
  MutexLock mu(Thread::Current(), dex_lock_);
  RegisterOatFileLocked(oat_file);
}

void ClassLinker::RegisterOatFileLocked(const OatFile& oat_file) {
  dex_lock_.AssertHeld(Thread::Current());
#ifndef NDEBUG
  for (size_t i = 0; i < oat_files_.size(); ++i) {
    CHECK_NE(&oat_file, oat_files_[i]) << oat_file.GetLocation();
  }
#endif
  oat_files_.push_back(&oat_file);
}

OatFile* ClassLinker::OpenOat(const ImageSpace* space) {
  MutexLock mu(Thread::Current(), dex_lock_);
  const Runtime* runtime = Runtime::Current();
  const ImageHeader& image_header = space->GetImageHeader();
  // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
  // check the down cast
  mirror::String* oat_location =
      down_cast<mirror::String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
  std::string oat_filename;
  oat_filename += runtime->GetHostPrefix();
  oat_filename += oat_location->ToModifiedUtf8();
  runtime->GetHeap()->UnReserveOatFileAddressRange();
  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin());
  VLOG(startup) << "ClassLinker::OpenOat entering oat_filename=" << oat_filename;
  if (oat_file == NULL) {
    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
    return NULL;
  }
  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
  uint32_t image_oat_checksum = image_header.GetOatChecksum();
  if (oat_checksum != image_oat_checksum) {
    LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
               << " to expected oat checksum " << std::hex << image_oat_checksum
               << " in image";
    return NULL;
  }
  RegisterOatFileLocked(*oat_file);
  VLOG(startup) << "ClassLinker::OpenOat exiting";
  return oat_file;
}

const OatFile* ClassLinker::FindOpenedOatFileForDexFile(const DexFile& dex_file) {
  MutexLock mu(Thread::Current(), dex_lock_);
  return FindOpenedOatFileFromDexLocation(dex_file.GetLocation());
}

const OatFile* ClassLinker::FindOpenedOatFileFromDexLocation(const std::string& dex_location) {
  for (size_t i = 0; i < oat_files_.size(); i++) {
    const OatFile* oat_file = oat_files_[i];
    DCHECK(oat_file != NULL);
    const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location, false);
    if (oat_dex_file != NULL) {
      return oat_file;
    }
  }
  return NULL;
}

static const DexFile* FindDexFileInOatLocation(const std::string& dex_location,
                                               uint32_t dex_location_checksum,
                                               const std::string& oat_location) {
  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL));
  if (oat_file.get() == NULL) {
    return NULL;
  }
  Runtime* runtime = Runtime::Current();
  const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
  if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
    return NULL;
  }
  if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
      != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) {
    return NULL;
  }
  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
  if (oat_dex_file == NULL) {
    return NULL;
  }
  if (oat_dex_file->GetDexFileLocationChecksum() != dex_location_checksum) {
    return NULL;
  }
  runtime->GetClassLinker()->RegisterOatFile(*oat_file.release());
  return oat_dex_file->OpenDexFile();
}

const DexFile* ClassLinker::FindOrCreateOatFileForDexLocation(const std::string& dex_location,
                                                              const std::string& oat_location) {
  MutexLock mu(Thread::Current(), dex_lock_);
  return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_location);
}

const DexFile* ClassLinker::FindOrCreateOatFileForDexLocationLocked(const std::string& dex_location,
                                                                    const std::string& oat_location) {
  uint32_t dex_location_checksum;
  if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
    LOG(ERROR) << "Failed to compute checksum '" << dex_location << "'";
    return NULL;
  }

  // Check if we already have an up-to-date output file
  const DexFile* dex_file = FindDexFileInOatLocation(dex_location,
                                                     dex_location_checksum,
                                                     oat_location);
  if (dex_file != NULL) {
    return dex_file;
  }

  // Generate the output oat file for the dex file
  UniquePtr<File> file(OS::OpenFile(oat_location.c_str(), true));
  if (file.get() == NULL) {
    LOG(ERROR) << "Failed to create oat file: " << oat_location;
    return NULL;
  }
  if (!GenerateOatFile(dex_location, file->Fd(), oat_location)) {
    LOG(ERROR) << "Failed to generate oat file: " << oat_location;
    return NULL;
  }
  const OatFile* oat_file = OatFile::Open(oat_location, oat_location, NULL);
  if (oat_file == NULL) {
    LOG(ERROR) << "Failed to open generated oat file: " << oat_location;
    return NULL;
  }
  RegisterOatFileLocked(*oat_file);
  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
  if (oat_dex_file == NULL) {
    LOG(ERROR) << "Failed to find dex file in generated oat file: " << oat_location;
    return NULL;
  }
  return oat_dex_file->OpenDexFile();
}

bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
                                         const std::string& dex_location,
                                         uint32_t dex_location_checksum) {
  Runtime* runtime = Runtime::Current();
  const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
  uint32_t image_oat_checksum = image_header.GetOatChecksum();
  uint32_t image_oat_data_begin = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
  bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
                      && (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin() == image_oat_data_begin));

  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
  if (oat_dex_file == NULL) {
    LOG(ERROR) << ".oat file " << oat_file->GetLocation()
               << " does not contain contents for " << dex_location;
    std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles();
    for (size_t i = 0; i < oat_dex_files.size(); i++) {
      const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
      LOG(ERROR) << ".oat file " << oat_file->GetLocation()
                 << " contains contents for " << oat_dex_file->GetDexFileLocation();
    }
    return false;
  }
  bool dex_check = dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum();

  if (image_check && dex_check) {
    return true;
  }

  if (!image_check) {
    std::string image_file(image_header.GetImageRoot(
        ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
    LOG(WARNING) << ".oat file " << oat_file->GetLocation()
                 << " mismatch ( " << std::hex << oat_file->GetOatHeader().GetImageFileLocationOatChecksum()
                 << ", " << oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
                 << ") with " << image_file
                 << " (" << image_oat_checksum << ", " << std::hex << image_oat_data_begin << ")";
  }
  if (!dex_check) {
    LOG(WARNING) << ".oat file " << oat_file->GetLocation()
                 << " mismatch ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
                 << ") with " << dex_location
                 << " (" << std::hex << dex_location_checksum << ")";
  }
  return false;
}

const DexFile* ClassLinker::VerifyAndOpenDexFileFromOatFile(const OatFile* oat_file,
                                                            const std::string& dex_location,
                                                            uint32_t dex_location_checksum) {
  bool verified = VerifyOatFileChecksums(oat_file, dex_location, dex_location_checksum);
  if (!verified) {
    return NULL;
  }
  RegisterOatFileLocked(*oat_file);
  return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
}

const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) {
  MutexLock mu(Thread::Current(), dex_lock_);

  const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location);
  if (open_oat_file != NULL) {
    return open_oat_file->GetOatDexFile(dex_location)->OpenDexFile();
  }

  // Look for an existing file next to dex. for example, for
  // /foo/bar/baz.jar, look for /foo/bar/baz.jar.oat.
  std::string oat_filename(OatFile::DexFilenameToOatFilename(dex_location));
  const OatFile* oat_file = FindOatFileFromOatLocationLocked(oat_filename);
  if (oat_file != NULL) {
    uint32_t dex_location_checksum;
    if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
      // If no classes.dex found in dex_location, it has been stripped, assume oat is up-to-date.
      // This is the common case in user builds for jar's and apk's in the /system directory.
      const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
      CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
      RegisterOatFileLocked(*oat_file);
      return oat_dex_file->OpenDexFile();
    }
    const DexFile* dex_file = VerifyAndOpenDexFileFromOatFile(oat_file,
                                                              dex_location,
                                                              dex_location_checksum);
    if (dex_file != NULL) {
      return dex_file;
    }
  }
  // Look for an existing file in the art-cache, validating the result if found
  // not found in /foo/bar/baz.oat? try /data/art-cache/foo@bar@baz.oat
  std::string cache_location(GetArtCacheFilenameOrDie(oat_filename));
  oat_file = FindOatFileFromOatLocationLocked(cache_location);
  if (oat_file != NULL) {
    uint32_t dex_location_checksum;
    if (!DexFile::GetChecksum(dex_location, dex_location_checksum)) {
      LOG(WARNING) << "Failed to compute checksum: " << dex_location;
      return NULL;
    }
    const DexFile* dex_file = VerifyAndOpenDexFileFromOatFile(oat_file,
                                                              dex_location,
                                                              dex_location_checksum);
    if (dex_file != NULL) {
      return dex_file;
    }
    if (TEMP_FAILURE_RETRY(unlink(oat_file->GetLocation().c_str())) != 0) {
      PLOG(FATAL) << "Failed to remove obsolete .oat file " << oat_file->GetLocation();
    }
  }
  LOG(INFO) << "Failed to open oat file from " << oat_filename << " or " << cache_location << ".";

  // Try to generate oat file if it wasn't found or was obsolete.
  std::string oat_cache_filename(GetArtCacheFilenameOrDie(oat_filename));
  return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_cache_filename);
}

const OatFile* ClassLinker::FindOpenedOatFileFromOatLocation(const std::string& oat_location) {
  for (size_t i = 0; i < oat_files_.size(); i++) {
    const OatFile* oat_file = oat_files_[i];
    DCHECK(oat_file != NULL);
    if (oat_file->GetLocation() == oat_location) {
      return oat_file;
    }
  }
  return NULL;
}

const OatFile* ClassLinker::FindOatFileFromOatLocation(const std::string& oat_location) {
  MutexLock mu(Thread::Current(), dex_lock_);
  return FindOatFileFromOatLocationLocked(oat_location);
}

const OatFile* ClassLinker::FindOatFileFromOatLocationLocked(const std::string& oat_location) {
  const OatFile* oat_file = FindOpenedOatFileFromOatLocation(oat_location);
  if (oat_file != NULL) {
    return oat_file;
  }

  oat_file = OatFile::Open(oat_location, oat_location, NULL);
  if (oat_file == NULL) {
    return NULL;
  }
  return oat_file;
}

void ClassLinker::InitFromImage() {
  VLOG(startup) << "ClassLinker::InitFromImage entering";
  CHECK(!init_done_);

  Heap* heap = Runtime::Current()->GetHeap();
  ImageSpace* space = heap->GetImageSpace();
  OatFile* oat_file = OpenOat(space);
  CHECK(oat_file != NULL) << "Failed to open oat file for image";
  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0U);
  CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty());
  mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
  mirror::ObjectArray<mirror::DexCache>* dex_caches =
      dex_caches_object->AsObjectArray<mirror::DexCache>();

  mirror::ObjectArray<mirror::Class>* class_roots =
      space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<mirror::Class>();
  class_roots_ = class_roots;

  // Special case of setting up the String class early so that we can test arbitrary objects
  // as being Strings or not
  mirror::String::SetClass(GetClassRoot(kJavaLangString));

  CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
           static_cast<uint32_t>(dex_caches->GetLength()));
  Thread* self = Thread::Current();
  for (int i = 0; i < dex_caches->GetLength(); i++) {
    SirtRef<mirror::DexCache> dex_cache(self, dex_caches->Get(i));
    const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
    const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
    CHECK(oat_dex_file != NULL) << oat_file->GetLocation() << " " << dex_file_location;
    const DexFile* dex_file = oat_dex_file->OpenDexFile();
    if (dex_file == NULL) {
      LOG(FATAL) << "Failed to open dex file " << dex_file_location
                 << " from within oat file " << oat_file->GetLocation();
    }

    CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());

    AppendToBootClassPath(*dex_file, dex_cache);
  }

  // Set classes on AbstractMethod early so that IsMethod tests can be performed during the live
  // bitmap walk.
  mirror::AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor),
                                     GetClassRoot(kJavaLangReflectMethod));

  // reinit clases_ table
  {
    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
    heap->FlushAllocStack();
    heap->GetLiveBitmap()->Walk(InitFromImageCallback, this);
  }

  // reinit class_roots_
  mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass));
  class_roots_ = class_roots;

  // reinit array_iftable_ from any array class instance, they should be ==
  array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable();
  DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
  // String class root was set above
  mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
  mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
  mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
  mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
  mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
  mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
  mirror::IntArray::SetArrayClass(GetClassRoot(kIntArrayClass));
  mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
  mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
  mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
  mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));

  FinishInit();

  VLOG(startup) << "ClassLinker::InitFromImage exiting";
}

void ClassLinker::InitFromImageCallback(mirror::Object* obj, void* arg) {
  DCHECK(obj != NULL);
  DCHECK(arg != NULL);
  ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);

  if (obj->GetClass()->IsStringClass()) {
    class_linker->intern_table_->RegisterStrong(obj->AsString());
    return;
  }
  if (obj->IsClass()) {
    // restore class to ClassLinker::classes_ table
    mirror::Class* klass = obj->AsClass();
    ClassHelper kh(klass, class_linker);
    mirror::Class* existing = class_linker->InsertClass(kh.GetDescriptor(), klass, true);
    DCHECK(existing == NULL) << kh.GetDescriptor();
    return;
  }

  // Check if object is a method without its code set and point it to the resolution trampoline.
  if (obj->IsMethod()) {
    mirror::AbstractMethod* method = obj->AsMethod();
    if (method->GetCode() == NULL) {
      method->SetCode(GetResolutionTrampoline());
    }
  }
}

// Keep in sync with InitCallback. Anything we visit, we need to
// reinit references to when reinitializing a ClassLinker from a
// mapped image.
void ClassLinker::VisitRoots(RootVisitor* visitor, void* arg) {
  visitor(class_roots_, arg);
  Thread* self = Thread::Current();
  {
    MutexLock mu(self, dex_lock_);
    for (size_t i = 0; i < dex_caches_.size(); i++) {
      visitor(dex_caches_[i], arg);
    }
  }

  {
    MutexLock mu(self, *Locks::classlinker_classes_lock_);
    typedef Table::const_iterator It;  // TODO: C++0x auto
    for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
      visitor(it->second, arg);
    }

    // We deliberately ignore the class roots in the image since we
    // handle image roots by using the MS/CMS rescanning of dirty cards.
  }

  visitor(array_iftable_, arg);
  is_dirty_ = false;
}

void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const {
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  typedef Table::const_iterator It;  // TODO: C++0x auto
  for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
    if (!visitor(it->second, arg)) {
      return;
    }
  }
  for (It it = image_classes_.begin(), end = image_classes_.end(); it != end; ++it) {
    if (!visitor(it->second, arg)) {
      return;
    }
  }
}

static bool GetClassesVisitor(mirror::Class* c, void* arg) {
  std::set<mirror::Class*>* classes = reinterpret_cast<std::set<mirror::Class*>*>(arg);
  classes->insert(c);
  return true;
}

void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) const {
  std::set<mirror::Class*> classes;
  VisitClasses(GetClassesVisitor, &classes);
  typedef std::set<mirror::Class*>::const_iterator It;  // TODO: C++0x auto
  for (It it = classes.begin(), end = classes.end(); it != end; ++it) {
    if (!visitor(*it, arg)) {
      return;
    }
  }
}


ClassLinker::~ClassLinker() {
  mirror::Class::ResetClass();
  mirror::String::ResetClass();
  mirror::Field::ResetClass();
  mirror::AbstractMethod::ResetClasses();
  mirror::BooleanArray::ResetArrayClass();
  mirror::ByteArray::ResetArrayClass();
  mirror::CharArray::ResetArrayClass();
  mirror::DoubleArray::ResetArrayClass();
  mirror::FloatArray::ResetArrayClass();
  mirror::IntArray::ResetArrayClass();
  mirror::LongArray::ResetArrayClass();
  mirror::ShortArray::ResetArrayClass();
  mirror::Throwable::ResetClass();
  mirror::StackTraceElement::ResetClass();
  STLDeleteElements(&boot_class_path_);
  STLDeleteElements(&oat_files_);
}

mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) {
  Heap* heap = Runtime::Current()->GetHeap();
  mirror::Class* dex_cache_class = GetClassRoot(kJavaLangDexCache);
  SirtRef<mirror::DexCache> dex_cache(self,
                              down_cast<mirror::DexCache*>(heap->AllocObject(self, dex_cache_class,
                                                                dex_cache_class->GetObjectSize())));
  if (dex_cache.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::String>
      location(self, intern_table_->InternStrong(dex_file.GetLocation().c_str()));
  if (location.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::ObjectArray<mirror::String> >
      strings(self, AllocStringArray(self, dex_file.NumStringIds()));
  if (strings.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::ObjectArray<mirror::Class> >
      types(self, AllocClassArray(self, dex_file.NumTypeIds()));
  if (types.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::ObjectArray<mirror::AbstractMethod> >
      methods(self, AllocAbstractMethodArray(self, dex_file.NumMethodIds()));
  if (methods.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::ObjectArray<mirror::Field> >
      fields(self, AllocFieldArray(self, dex_file.NumFieldIds()));
  if (fields.get() == NULL) {
    return NULL;
  }
  SirtRef<mirror::ObjectArray<mirror::StaticStorageBase> >
      initialized_static_storage(self,
                          AllocObjectArray<mirror::StaticStorageBase>(self, dex_file.NumTypeIds()));
  if (initialized_static_storage.get() == NULL) {
    return NULL;
  }

  dex_cache->Init(&dex_file,
                  location.get(),
                  strings.get(),
                  types.get(),
                  methods.get(),
                  fields.get(),
                  initialized_static_storage.get());
  return dex_cache.get();
}

mirror::Class* ClassLinker::AllocClass(Thread* self, mirror::Class* java_lang_Class,
                                       size_t class_size) {
  DCHECK_GE(class_size, sizeof(mirror::Class));
  Heap* heap = Runtime::Current()->GetHeap();
  SirtRef<mirror::Class> klass(self,
                       heap->AllocObject(self, java_lang_Class, class_size)->AsClass());
  klass->SetPrimitiveType(Primitive::kPrimNot);  // default to not being primitive
  klass->SetClassSize(class_size);
  return klass.get();
}

mirror::Class* ClassLinker::AllocClass(Thread* self, size_t class_size) {
  return AllocClass(self, GetClassRoot(kJavaLangClass), class_size);
}

mirror::Field* ClassLinker::AllocField(Thread* self) {
  return down_cast<mirror::Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject(self));
}

mirror::Method* ClassLinker::AllocMethod(Thread* self) {
  return down_cast<mirror::Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject(self));
}

mirror::Constructor* ClassLinker::AllocConstructor(Thread* self) {
  return down_cast<mirror::Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject(self));
}

mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(Thread* self,
                                                                                         size_t length) {
  return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(self,
                                                               GetClassRoot(kJavaLangStackTraceElementArrayClass),
                                                               length);
}

static mirror::Class* EnsureResolved(Thread* self, mirror::Class* klass)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(klass != NULL);
  // Wait for the class if it has not already been linked.
  if (!klass->IsResolved() && !klass->IsErroneous()) {
    ObjectLock lock(self, klass);
    // Check for circular dependencies between classes.
    if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
      ThrowClassCircularityError(klass);
      klass->SetStatus(mirror::Class::kStatusError);
      return NULL;
    }
    // Wait for the pending initialization to complete.
    while (!klass->IsResolved() && !klass->IsErroneous()) {
      lock.WaitIgnoringInterrupts();
    }
  }
  if (klass->IsErroneous()) {
    ThrowEarlierClassFailure(klass);
    return NULL;
  }
  // Return the loaded class.  No exceptions should be pending.
  CHECK(klass->IsResolved()) << PrettyClass(klass);
  self->AssertNoPendingException();
  return klass;
}

mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) {
  return FindClass(descriptor, NULL);
}

mirror::Class* ClassLinker::FindClass(const char* descriptor, mirror::ClassLoader* class_loader) {
  DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
  Thread* self = Thread::Current();
  DCHECK(self != NULL);
  self->AssertNoPendingException();
  if (descriptor[1] == '\0') {
    // only the descriptors of primitive types should be 1 character long, also avoid class lookup
    // for primitive classes that aren't backed by dex files.
    return FindPrimitiveClass(descriptor[0]);
  }
  // Find the class in the loaded classes table.
  mirror::Class* klass = LookupClass(descriptor, class_loader);
  if (klass != NULL) {
    return EnsureResolved(self, klass);
  }
  // Class is not yet loaded.
  if (descriptor[0] == '[') {
    return CreateArrayClass(descriptor, class_loader);

  } else if (class_loader == NULL) {
    DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
    if (pair.second != NULL) {
      return DefineClass(descriptor, NULL, *pair.first, *pair.second);
    }

  } else if (Runtime::Current()->UseCompileTimeClassPath()) {
    // first try the boot class path
    mirror::Class* system_class = FindSystemClass(descriptor);
    if (system_class != NULL) {
      return system_class;
    }
    CHECK(self->IsExceptionPending());
    self->ClearException();

    // next try the compile time class path
    const std::vector<const DexFile*>* class_path;
    {
      ScopedObjectAccessUnchecked soa(Thread::Current());
      ScopedLocalRef<jobject> jclass_loader(soa.Env(), soa.AddLocalReference<jobject>(class_loader));
      class_path = &Runtime::Current()->GetCompileTimeClassPath(jclass_loader.get());
    }

    DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, *class_path);
    if (pair.second != NULL) {
      return DefineClass(descriptor, class_loader, *pair.first, *pair.second);
    }

  } else {
    ScopedObjectAccessUnchecked soa(self->GetJniEnv());
    ScopedLocalRef<jobject> class_loader_object(soa.Env(),
                                                soa.AddLocalReference<jobject>(class_loader));
    std::string class_name_string(DescriptorToDot(descriptor));
    ScopedLocalRef<jobject> result(soa.Env(), NULL);
    {
      ScopedThreadStateChange tsc(self, kNative);
      ScopedLocalRef<jobject> class_name_object(soa.Env(),
                                                soa.Env()->NewStringUTF(class_name_string.c_str()));
      if (class_name_object.get() == NULL) {
        return NULL;
      }
      CHECK(class_loader_object.get() != NULL);
      result.reset(soa.Env()->CallObjectMethod(class_loader_object.get(),
                                               WellKnownClasses::java_lang_ClassLoader_loadClass,
                                               class_name_object.get()));
    }
    if (soa.Self()->IsExceptionPending()) {
      // If the ClassLoader threw, pass that exception up.
      return NULL;
    } else if (result.get() == NULL) {
      // broken loader - throw NPE to be compatible with Dalvik
      ThrowNullPointerException(NULL, StringPrintf("ClassLoader.loadClass returned null for %s",
                                                   class_name_string.c_str()).c_str());
      return NULL;
    } else {
      // success, return mirror::Class*
      return soa.Decode<mirror::Class*>(result.get());
    }
  }

  ThrowNoClassDefFoundError("Class %s not found", PrintableString(descriptor).c_str());
  return NULL;
}

mirror::Class* ClassLinker::DefineClass(const StringPiece& descriptor,
                                        mirror::ClassLoader* class_loader,
                                        const DexFile& dex_file,
                                        const DexFile::ClassDef& dex_class_def) {
  Thread* self = Thread::Current();
  SirtRef<mirror::Class> klass(self, NULL);
  // Load the class from the dex file.
  if (!init_done_) {
    // finish up init of hand crafted class_roots_
    if (descriptor == "Ljava/lang/Object;") {
      klass.reset(GetClassRoot(kJavaLangObject));
    } else if (descriptor == "Ljava/lang/Class;") {
      klass.reset(GetClassRoot(kJavaLangClass));
    } else if (descriptor == "Ljava/lang/String;") {
      klass.reset(GetClassRoot(kJavaLangString));
    } else if (descriptor == "Ljava/lang/DexCache;") {
      klass.reset(GetClassRoot(kJavaLangDexCache));
    } else if (descriptor == "Ljava/lang/reflect/Field;") {
      klass.reset(GetClassRoot(kJavaLangReflectField));
    } else if (descriptor == "Ljava/lang/reflect/AbstractMethod;") {
      klass.reset(GetClassRoot(kJavaLangReflectAbstractMethod));
    } else if (descriptor == "Ljava/lang/reflect/Constructor;") {
      klass.reset(GetClassRoot(kJavaLangReflectConstructor));
    } else if (descriptor == "Ljava/lang/reflect/Method;") {
      klass.reset(GetClassRoot(kJavaLangReflectMethod));
    } else {
      klass.reset(AllocClass(self, SizeOfClass(dex_file, dex_class_def)));
    }
  } else {
    klass.reset(AllocClass(self, SizeOfClass(dex_file, dex_class_def)));
  }
  klass->SetDexCache(FindDexCache(dex_file));
  LoadClass(dex_file, dex_class_def, klass, class_loader);
  // Check for a pending exception during load
  if (self->IsExceptionPending()) {
    klass->SetStatus(mirror::Class::kStatusError);
    return NULL;
  }
  ObjectLock lock(self, klass.get());
  klass->SetClinitThreadId(self->GetTid());
  // Add the newly loaded class to the loaded classes table.
  SirtRef<mirror::Class> existing(self, InsertClass(descriptor, klass.get(), false));
  if (existing.get() != NULL) {
    // We failed to insert because we raced with another thread.
    return EnsureResolved(self, existing.get());
  }
  // Finish loading (if necessary) by finding parents
  CHECK(!klass->IsLoaded());
  if (!LoadSuperAndInterfaces(klass, dex_file)) {
    // Loading failed.
    klass->SetStatus(mirror::Class::kStatusError);
    lock.NotifyAll();
    return NULL;
  }
  CHECK(klass->IsLoaded());
  // Link the class (if necessary)
  CHECK(!klass->IsResolved());
  if (!LinkClass(klass, NULL)) {
    // Linking failed.
    klass->SetStatus(mirror::Class::kStatusError);
    lock.NotifyAll();
    return NULL;
  }
  CHECK(klass->IsResolved());

  /*
   * We send CLASS_PREPARE events to the debugger from here.  The
   * definition of "preparation" is creating the static fields for a
   * class and initializing them to the standard default values, but not
   * executing any code (that comes later, during "initialization").
   *
   * We did the static preparation in LinkClass.
   *
   * The class has been prepared and resolved but possibly not yet verified
   * at this point.
   */
  Dbg::PostClassPrepare(klass.get());

  return klass.get();
}

// Precomputes size that will be needed for Class, matching LinkStaticFields
size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
                                const DexFile::ClassDef& dex_class_def) {
  const byte* class_data = dex_file.GetClassData(dex_class_def);
  size_t num_ref = 0;
  size_t num_32 = 0;
  size_t num_64 = 0;
  if (class_data != NULL) {
    for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
      const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
      const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
      char c = descriptor[0];
      if (c == 'L' || c == '[') {
        num_ref++;
      } else if (c == 'J' || c == 'D') {
        num_64++;
      } else {
        num_32++;
      }
    }
  }
  // start with generic class data
  size_t size = sizeof(mirror::Class);
  // follow with reference fields which must be contiguous at start
  size += (num_ref * sizeof(uint32_t));
  // if there are 64-bit fields to add, make sure they are aligned
  if (num_64 != 0 && size != RoundUp(size, 8)) { // for 64-bit alignment
    if (num_32 != 0) {
      // use an available 32-bit field for padding
      num_32--;
    }
    size += sizeof(uint32_t);  // either way, we are adding a word
    DCHECK_EQ(size, RoundUp(size, 8));
  }
  // tack on any 64-bit fields now that alignment is assured
  size += (num_64 * sizeof(uint64_t));
  // tack on any remaining 32-bit fields
  size += (num_32 * sizeof(uint32_t));
  return size;
}

const OatFile::OatClass* ClassLinker::GetOatClass(const DexFile& dex_file, const char* descriptor) {
  DCHECK(descriptor != NULL);
  const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file);
  CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << descriptor;
  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
  CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << descriptor;
  uint32_t class_def_index;
  bool found = dex_file.FindClassDefIndex(descriptor, class_def_index);
  CHECK(found) << dex_file.GetLocation() << " " << descriptor;
  const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_index);
  CHECK(oat_class != NULL) << dex_file.GetLocation() << " " << descriptor;
  return oat_class;
}

static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint32_t method_idx) {
  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
  const DexFile::TypeId& type_id = dex_file.GetTypeId(method_id.class_idx_);
  const DexFile::ClassDef* class_def = dex_file.FindClassDef(dex_file.GetTypeDescriptor(type_id));
  CHECK(class_def != NULL);
  const byte* class_data = dex_file.GetClassData(*class_def);
  CHECK(class_data != NULL);
  ClassDataItemIterator it(dex_file, class_data);
  // Skip fields
  while (it.HasNextStaticField()) {
    it.Next();
  }
  while (it.HasNextInstanceField()) {
    it.Next();
  }
  // Process methods
  size_t class_def_method_index = 0;
  while (it.HasNextDirectMethod()) {
    if (it.GetMemberIndex() == method_idx) {
      return class_def_method_index;
    }
    class_def_method_index++;
    it.Next();
  }
  while (it.HasNextVirtualMethod()) {
    if (it.GetMemberIndex() == method_idx) {
      return class_def_method_index;
    }
    class_def_method_index++;
    it.Next();
  }
  DCHECK(!it.HasNext());
  LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
  return 0;
}

const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::AbstractMethod* method) {
  // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
  // method for direct methods (or virtual methods made direct).
  mirror::Class* declaring_class = method->GetDeclaringClass();
  size_t oat_method_index;
  if (method->IsStatic() || method->IsDirect()) {
    // Simple case where the oat method index was stashed at load time.
    oat_method_index = method->GetMethodIndex();
  } else {
    // We're invoking a virtual method directly (thanks to sharpening), compute the oat_method_index
    // by search for its position in the declared virtual methods.
    oat_method_index = declaring_class->NumDirectMethods();
    size_t end = declaring_class->NumVirtualMethods();
    bool found = false;
    for (size_t i = 0; i < end; i++) {
      if (declaring_class->GetVirtualMethod(i) == method) {
        found = true;
        break;
      }
      oat_method_index++;
    }
    CHECK(found) << "Didn't find oat method index for virtual method: " << PrettyMethod(method);
  }
  ClassHelper kh(declaring_class);
  UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(kh.GetDexFile(), kh.GetDescriptor()));
  CHECK(oat_class.get() != NULL);
  DCHECK_EQ(oat_method_index,
            GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(),
                                             method->GetDexMethodIndex()));

  return oat_class->GetOatMethod(oat_method_index);
}

// Special case to get oat code without overwriting a trampoline.
const void* ClassLinker::GetOatCodeFor(const mirror::AbstractMethod* method) {
  CHECK(!method->IsAbstract()) << PrettyMethod(method);
  const void* result = GetOatMethodFor(method).GetCode();
  if (result == NULL) {
    // No code? You must mean to go into the interpreter.
    result = GetInterpreterEntryPoint();
  }
  return result;
}

const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint32_t method_idx) {
  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
  const char* descriptor = dex_file.GetTypeDescriptor(dex_file.GetTypeId(method_id.class_idx_));
  uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, method_idx);
  UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, descriptor));
  CHECK(oat_class.get() != NULL);
  return oat_class->GetOatMethod(oat_method_idx).GetCode();
}

void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
  ClassHelper kh(klass);
  const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
  CHECK(dex_class_def != NULL);
  const DexFile& dex_file = kh.GetDexFile();
  const byte* class_data = dex_file.GetClassData(*dex_class_def);
  if (class_data == NULL) {
    return;  // no fields or methods - for example a marker interface
  }
  Runtime* runtime = Runtime::Current();
  if (!runtime->IsStarted() || runtime->UseCompileTimeClassPath()) {
    // OAT file unavailable
    return;
  }
  UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, kh.GetDescriptor()));
  CHECK(oat_class.get() != NULL);
  ClassDataItemIterator it(dex_file, class_data);
  // Skip fields
  while (it.HasNextStaticField()) {
    it.Next();
  }
  while (it.HasNextInstanceField()) {
    it.Next();
  }
  size_t method_index = 0;
  // Link the code of methods skipped by LinkCode
  for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
    mirror::AbstractMethod* method = klass->GetDirectMethod(i);
    if (method->IsStatic()) {
      const void* code = oat_class->GetOatMethod(method_index).GetCode();
      if (code == NULL) {
        // No code? You must mean to go into the interpreter.
        code = GetInterpreterEntryPoint();
      }
      runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
    }
    method_index++;
  }
  // Ignore virtual methods on the iterator.
}

static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::OatClass* oat_class,
                     uint32_t method_index)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  // Method shouldn't have already been linked.
  DCHECK(method->GetCode() == NULL);
  // Every kind of method should at least get an invoke stub from the oat_method.
  // non-abstract methods also get their code pointers.
  const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
  oat_method.LinkMethod(method.get());

  Runtime* runtime = Runtime::Current();
  if (method->IsAbstract()) {
    method->SetCode(GetAbstractMethodErrorStub());
    return;
  }

  if (method->IsStatic() && !method->IsConstructor()) {
    // For static methods excluding the class initializer, install the trampoline.
    method->SetCode(GetResolutionTrampoline());
  }

  if (method->IsNative()) {
    // Unregistering restores the dlsym lookup stub.
    method->UnregisterNative(Thread::Current());
  }

  if (method->GetCode() == NULL) {
    // No code? You must mean to go into the interpreter.
    method->SetCode(GetInterpreterEntryPoint());
  }

  // Allow instrumentation its chance to hijack code.
  runtime->GetInstrumentation()->UpdateMethodsCode(method.get(), method->GetCode());
}

void ClassLinker::LoadClass(const DexFile& dex_file,
                            const DexFile::ClassDef& dex_class_def,
                            SirtRef<mirror::Class>& klass,
                            mirror::ClassLoader* class_loader) {
  CHECK(klass.get() != NULL);
  CHECK(klass->GetDexCache() != NULL);
  CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus());
  const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
  CHECK(descriptor != NULL);

  klass->SetClass(GetClassRoot(kJavaLangClass));
  uint32_t access_flags = dex_class_def.access_flags_;
  // Make sure that none of our runtime-only flags are set.
  // TODO: JACK CLASS ACCESS (HACK TO BE REMOVED)
  CHECK_EQ(access_flags & ~(kAccJavaFlagsMask | kAccClassJack), 0U);
  klass->SetAccessFlags(access_flags);
  klass->SetClassLoader(class_loader);
  DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
  klass->SetStatus(mirror::Class::kStatusIdx);

  klass->SetDexTypeIndex(dex_class_def.class_idx_);

  // Load fields fields.
  const byte* class_data = dex_file.GetClassData(dex_class_def);
  if (class_data == NULL) {
    return;  // no fields or methods - for example a marker interface
  }
  ClassDataItemIterator it(dex_file, class_data);
  Thread* self = Thread::Current();
  if (it.NumStaticFields() != 0) {
    klass->SetSFields(AllocFieldArray(self, it.NumStaticFields()));
  }
  if (it.NumInstanceFields() != 0) {
    klass->SetIFields(AllocFieldArray(self, it.NumInstanceFields()));
  }
  for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
    SirtRef<mirror::Field> sfield(self, AllocField(self));
    klass->SetStaticField(i, sfield.get());
    LoadField(dex_file, it, klass, sfield);
  }
  for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
    SirtRef<mirror::Field> ifield(self, AllocField(self));
    klass->SetInstanceField(i, ifield.get());
    LoadField(dex_file, it, klass, ifield);
  }

  UniquePtr<const OatFile::OatClass> oat_class;
  if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) {
    oat_class.reset(GetOatClass(dex_file, descriptor));
  }

  // Load methods.
  if (it.NumDirectMethods() != 0) {
    // TODO: append direct methods to class object
    klass->SetDirectMethods(AllocAbstractMethodArray(self, it.NumDirectMethods()));
  }
  if (it.NumVirtualMethods() != 0) {
    // TODO: append direct methods to class object
    klass->SetVirtualMethods(AllocMethodArray(self, it.NumVirtualMethods()));
  }
  size_t class_def_method_index = 0;
  for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
    SirtRef<mirror::AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass));
    klass->SetDirectMethod(i, method.get());
    if (oat_class.get() != NULL) {
      LinkCode(method, oat_class.get(), class_def_method_index);
    }
    method->SetMethodIndex(class_def_method_index);
    class_def_method_index++;
  }
  for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
    SirtRef<mirror::AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass));
    klass->SetVirtualMethod(i, method.get());
    DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
    if (oat_class.get() != NULL) {
      LinkCode(method, oat_class.get(), class_def_method_index);
    }
    class_def_method_index++;
  }
  DCHECK(!it.HasNext());
}

void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it,
                            SirtRef<mirror::Class>& klass, SirtRef<mirror::Field>& dst) {
  uint32_t field_idx = it.GetMemberIndex();
  dst->SetDexFieldIndex(field_idx);
  dst->SetDeclaringClass(klass.get());
  dst->SetAccessFlags(it.GetMemberAccessFlags());
}

mirror::AbstractMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file,
                                                const ClassDataItemIterator& it,
                                                SirtRef<mirror::Class>& klass) {
  uint32_t dex_method_idx = it.GetMemberIndex();
  const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
  StringPiece method_name(dex_file.GetMethodName(method_id));

  mirror::AbstractMethod* dst = NULL;
  if (method_name == "<init>") {
    dst = AllocConstructor(self);
  } else {
    dst = AllocMethod(self);
  }
  DCHECK(dst->IsMethod()) << PrettyDescriptor(dst->GetClass());

  const char* old_cause = self->StartAssertNoThreadSuspension("LoadMethod");
  dst->SetDexMethodIndex(dex_method_idx);
  dst->SetDeclaringClass(klass.get());

  if (method_name == "finalize") {
    // Create the prototype for a signature of "()V"
    const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
    if (void_string_id != NULL) {
      const DexFile::TypeId* void_type_id =
          dex_file.FindTypeId(dex_file.GetIndexForStringId(*void_string_id));
      if (void_type_id != NULL) {
        std::vector<uint16_t> no_args;
        const DexFile::ProtoId* finalizer_proto =
            dex_file.FindProtoId(dex_file.GetIndexForTypeId(*void_type_id), no_args);
        if (finalizer_proto != NULL) {
          // We have the prototype in the dex file
          if (klass->GetClassLoader() != NULL) {  // All non-boot finalizer methods are flagged
            klass->SetFinalizable();
          } else {
            StringPiece klass_descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
            // The Enum class declares a "final" finalize() method to prevent subclasses from
            // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
            // subclasses, so we exclude it here.
            // We also want to avoid setting the flag on Object, where we know that finalize() is
            // empty.
            if (klass_descriptor != "Ljava/lang/Object;" &&
                klass_descriptor != "Ljava/lang/Enum;") {
              klass->SetFinalizable();
            }
          }
        }
      }
    }
  }
  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
  dst->SetAccessFlags(it.GetMemberAccessFlags());

  dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
  dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
  dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
  dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());

  CHECK(dst->IsMethod());

  self->EndAssertNoThreadSuspension(old_cause);
  return dst;
}

void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
  Thread* self = Thread::Current();
  SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file));
  AppendToBootClassPath(dex_file, dex_cache);
}

void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
  CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
  boot_class_path_.push_back(&dex_file);
  RegisterDexFile(dex_file, dex_cache);
}

bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const {
  dex_lock_.AssertHeld(Thread::Current());
  for (size_t i = 0; i != dex_caches_.size(); ++i) {
    if (dex_caches_[i]->GetDexFile() == &dex_file) {
      return true;
    }
  }
  return false;
}

bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const {
  MutexLock mu(Thread::Current(), dex_lock_);
  return IsDexFileRegisteredLocked(dex_file);
}

void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
  dex_lock_.AssertHeld(Thread::Current());
  CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
  CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
  dex_caches_.push_back(dex_cache.get());
  dex_cache->SetDexFile(&dex_file);
  Dirty();
}

void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
  Thread* self = Thread::Current();
  {
    MutexLock mu(self, dex_lock_);
    if (IsDexFileRegisteredLocked(dex_file)) {
      return;
    }
  }
  // Don't alloc while holding the lock, since allocation may need to
  // suspend all threads and another thread may need the dex_lock_ to
  // get to a suspend point.
  SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file));
  {
    MutexLock mu(self, dex_lock_);
    if (IsDexFileRegisteredLocked(dex_file)) {
      return;
    }
    RegisterDexFileLocked(dex_file, dex_cache);
  }
}

void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
  MutexLock mu(Thread::Current(), dex_lock_);
  RegisterDexFileLocked(dex_file, dex_cache);
}

mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
  MutexLock mu(Thread::Current(), dex_lock_);
  // Search assuming unique-ness of dex file.
  for (size_t i = 0; i != dex_caches_.size(); ++i) {
    mirror::DexCache* dex_cache = dex_caches_[i];
    if (dex_cache->GetDexFile() == &dex_file) {
      return dex_cache;
    }
  }
  // Search matching by location name.
  std::string location(dex_file.GetLocation());
  for (size_t i = 0; i != dex_caches_.size(); ++i) {
    mirror::DexCache* dex_cache = dex_caches_[i];
    if (dex_cache->GetDexFile()->GetLocation() == location) {
      return dex_cache;
    }
  }
  // Failure, dump diagnostic and abort.
  for (size_t i = 0; i != dex_caches_.size(); ++i) {
    mirror::DexCache* dex_cache = dex_caches_[i];
    LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation();
  }
  LOG(FATAL) << "Failed to find DexCache for DexFile " << location;
  return NULL;
}

void ClassLinker::FixupDexCaches(mirror::AbstractMethod* resolution_method) const {
  MutexLock mu(Thread::Current(), dex_lock_);
  for (size_t i = 0; i != dex_caches_.size(); ++i) {
    dex_caches_[i]->Fixup(resolution_method);
  }
}

mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
  return InitializePrimitiveClass(AllocClass(self, sizeof(mirror::Class)), type);
}

mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) {
  CHECK(primitive_class != NULL);
  // Must hold lock on object when initializing.
  ObjectLock lock(Thread::Current(), primitive_class);
  primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
  primitive_class->SetPrimitiveType(type);
  primitive_class->SetStatus(mirror::Class::kStatusInitialized);
  mirror::Class* existing = InsertClass(Primitive::Descriptor(type), primitive_class, false);
  CHECK(existing == NULL) << "InitPrimitiveClass(" << type << ") failed";
  return primitive_class;
}

// Create an array class (i.e. the class object for the array, not the
// array itself).  "descriptor" looks like "[C" or "[[[[B" or
// "[Ljava/lang/String;".
//
// If "descriptor" refers to an array of primitives, look up the
// primitive type's internally-generated class object.
//
// "class_loader" is the class loader of the class that's referring to
// us.  It's used to ensure that we're looking for the element type in
// the right context.  It does NOT become the class loader for the
// array class; that always comes from the base element class.
//
// Returns NULL with an exception raised on failure.
mirror::Class* ClassLinker::CreateArrayClass(const std::string& descriptor,
                                             mirror::ClassLoader* class_loader) {
  CHECK_EQ('[', descriptor[0]);

  // Identify the underlying component type
  mirror::Class* component_type = FindClass(descriptor.substr(1).c_str(), class_loader);
  if (component_type == NULL) {
    DCHECK(Thread::Current()->IsExceptionPending());
    return NULL;
  }

  // See if the component type is already loaded.  Array classes are
  // always associated with the class loader of their underlying
  // element type -- an array of Strings goes with the loader for
  // java/lang/String -- so we need to look for it there.  (The
  // caller should have checked for the existence of the class
  // before calling here, but they did so with *their* class loader,
  // not the component type's loader.)
  //
  // If we find it, the caller adds "loader" to the class' initiating
  // loader list, which should prevent us from going through this again.
  //
  // This call is unnecessary if "loader" and "component_type->GetClassLoader()"
  // are the same, because our caller (FindClass) just did the
  // lookup.  (Even if we get this wrong we still have correct behavior,
  // because we effectively do this lookup again when we add the new
  // class to the hash table --- necessary because of possible races with
  // other threads.)
  if (class_loader != component_type->GetClassLoader()) {
    mirror::Class* new_class = LookupClass(descriptor.c_str(), component_type->GetClassLoader());
    if (new_class != NULL) {
      return new_class;
    }
  }

  // Fill out the fields in the Class.
  //
  // It is possible to execute some methods against arrays, because
  // all arrays are subclasses of java_lang_Object_, so we need to set
  // up a vtable.  We can just point at the one in java_lang_Object_.
  //
  // Array classes are simple enough that we don't need to do a full
  // link step.
  Thread* self = Thread::Current();
  SirtRef<mirror::Class> new_class(self, NULL);
  if (!init_done_) {
    // Classes that were hand created, ie not by FindSystemClass
    if (descriptor == "[Ljava/lang/Class;") {
      new_class.reset(GetClassRoot(kClassArrayClass));
    } else if (descriptor == "[Ljava/lang/Object;") {
      new_class.reset(GetClassRoot(kObjectArrayClass));
    } else if (descriptor == class_roots_descriptors_[kJavaLangStringArrayClass]) {
      new_class.reset(GetClassRoot(kJavaLangStringArrayClass));
    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]) {
      new_class.reset(GetClassRoot(kJavaLangReflectAbstractMethodArrayClass));
    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectFieldArrayClass]) {
      new_class.reset(GetClassRoot(kJavaLangReflectFieldArrayClass));
    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectMethodArrayClass]) {
      new_class.reset(GetClassRoot(kJavaLangReflectMethodArrayClass));
    } else if (descriptor == "[C") {
      new_class.reset(GetClassRoot(kCharArrayClass));
    } else if (descriptor == "[I") {
      new_class.reset(GetClassRoot(kIntArrayClass));
    }
  }
  if (new_class.get() == NULL) {
    new_class.reset(AllocClass(self, sizeof(mirror::Class)));
    if (new_class.get() == NULL) {
      return NULL;
    }
    new_class->SetComponentType(component_type);
  }
  ObjectLock lock(self, new_class.get());  // Must hold lock on object when initializing.
  DCHECK(new_class->GetComponentType() != NULL);
  mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject);
  new_class->SetSuperClass(java_lang_Object);
  new_class->SetVTable(java_lang_Object->GetVTable());
  new_class->SetPrimitiveType(Primitive::kPrimNot);
  new_class->SetClassLoader(component_type->GetClassLoader());
  new_class->SetStatus(mirror::Class::kStatusInitialized);
  // don't need to set new_class->SetObjectSize(..)
  // because Object::SizeOf delegates to Array::SizeOf


  // All arrays have java/lang/Cloneable and java/io/Serializable as
  // interfaces.  We need to set that up here, so that stuff like
  // "instanceof" works right.
  //
  // Note: The GC could run during the call to FindSystemClass,
  // so we need to make sure the class object is GC-valid while we're in
  // there.  Do this by clearing the interface list so the GC will just
  // think that the entries are null.


  // Use the single, global copies of "interfaces" and "iftable"
  // (remember not to free them for arrays).
  CHECK(array_iftable_ != NULL);
  new_class->SetIfTable(array_iftable_);

  // Inherit access flags from the component type.  Arrays can't be
  // used as a superclass or interface, so we want to add "final"
  // and remove "interface".
  //
  // Don't inherit any non-standard flags (e.g., kAccFinal)
  // from component_type.  We assume that the array class does not
  // override finalize().
  new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() &
                             ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask);

  mirror::Class* existing = InsertClass(descriptor, new_class.get(), false);
  if (existing == NULL) {
    return new_class.get();
  }
  // Another thread must have loaded the class after we
  // started but before we finished.  Abandon what we've
  // done.
  //
  // (Yes, this happens.)

  return existing;
}

mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
  switch (Primitive::GetType(type)) {
    case Primitive::kPrimByte:
      return GetClassRoot(kPrimitiveByte);
    case Primitive::kPrimChar:
      return GetClassRoot(kPrimitiveChar);
    case Primitive::kPrimDouble:
      return GetClassRoot(kPrimitiveDouble);
    case Primitive::kPrimFloat:
      return GetClassRoot(kPrimitiveFloat);
    case Primitive::kPrimInt:
      return GetClassRoot(kPrimitiveInt);
    case Primitive::kPrimLong:
      return GetClassRoot(kPrimitiveLong);
    case Primitive::kPrimShort:
      return GetClassRoot(kPrimitiveShort);
    case Primitive::kPrimBoolean:
      return GetClassRoot(kPrimitiveBoolean);
    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());
  return NULL;
}

mirror::Class* ClassLinker::InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool image_class) {
  if (VLOG_IS_ON(class_linker)) {
    mirror::DexCache* dex_cache = klass->GetDexCache();
    std::string source;
    if (dex_cache != NULL) {
      source += " from ";
      source += dex_cache->GetLocation()->ToModifiedUtf8();
    }
    LOG(INFO) << "Loaded class " << descriptor << source;
  }
  size_t hash = StringPieceHash()(descriptor);
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  Table& classes = image_class ? image_classes_ : classes_;
  mirror::Class* existing = LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, classes);
#ifndef NDEBUG
  // Check we don't have the class in the other table in error
  Table& other_classes = image_class ? classes_ : image_classes_;
  CHECK(LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, other_classes) == NULL);
#endif
  if (existing != NULL) {
    return existing;
  }
  classes.insert(std::make_pair(hash, klass));
  Dirty();
  return NULL;
}

bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader* class_loader) {
  size_t hash = Hash(descriptor);
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  typedef Table::iterator It;  // TODO: C++0x auto
  // TODO: determine if its better to search classes_ or image_classes_ first
  ClassHelper kh;
  for (It it = classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash;
       ++it) {
    mirror::Class* klass = it->second;
    kh.ChangeClass(klass);
    if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
      classes_.erase(it);
      return true;
    }
  }
  for (It it = image_classes_.lower_bound(hash), end = classes_.end();
      it != end && it->first == hash; ++it) {
    mirror::Class* klass = it->second;
    kh.ChangeClass(klass);
    if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
      image_classes_.erase(it);
      return true;
    }
  }
  return false;
}

mirror::Class* ClassLinker::LookupClass(const char* descriptor,
                                        const mirror::ClassLoader* class_loader) {
  size_t hash = Hash(descriptor);
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  // TODO: determine if its better to search classes_ or image_classes_ first
  mirror::Class* klass = LookupClassLocked(descriptor, class_loader, hash, classes_);
  if (klass != NULL) {
    return klass;
  }
  return LookupClassLocked(descriptor, class_loader, hash, image_classes_);
}

mirror::Class* ClassLinker::LookupClassLocked(const char* descriptor,
                                              const mirror::ClassLoader* class_loader,
                                              size_t hash, const Table& classes) {
  ClassHelper kh(NULL, this);
  typedef Table::const_iterator It;  // TODO: C++0x auto
  for (It it = classes.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) {
    mirror::Class* klass = it->second;
    kh.ChangeClass(klass);
    if (strcmp(descriptor, kh.GetDescriptor()) == 0 && klass->GetClassLoader() == class_loader) {
#ifndef NDEBUG
      for (++it; it != end && it->first == hash; ++it) {
        mirror::Class* klass2 = it->second;
        kh.ChangeClass(klass2);
        CHECK(!(strcmp(descriptor, kh.GetDescriptor()) == 0 && klass2->GetClassLoader() == class_loader))
                << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
                << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
      }
#endif
      return klass;
    }
  }
  return NULL;
}

void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& classes) {
  classes.clear();
  size_t hash = Hash(descriptor);
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  typedef Table::const_iterator It;  // TODO: C++0x auto
  // TODO: determine if its better to search classes_ or image_classes_ first
  ClassHelper kh(NULL, this);
  for (It it = classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) {
    mirror::Class* klass = it->second;
    kh.ChangeClass(klass);
    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
      classes.push_back(klass);
    }
  }
  for (It it = image_classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) {
    mirror::Class* klass = it->second;
    kh.ChangeClass(klass);
    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
      classes.push_back(klass);
    }
  }
}

void ClassLinker::VerifyClass(mirror::Class* klass) {
  // TODO: assert that the monitor on the Class is held
  Thread* self = Thread::Current();
  ObjectLock lock(self, klass);

  // Don't attempt to re-verify if already sufficiently verified.
  if (klass->IsVerified() ||
      (klass->IsCompileTimeVerified() && Runtime::Current()->IsCompiler())) {
    return;
  }

  // The class might already be erroneous, for example at compile time if we attempted to verify
  // this class as a parent to another.
  if (klass->IsErroneous()) {
    ThrowEarlierClassFailure(klass);
    return;
  }

  if (klass->GetStatus() == mirror::Class::kStatusResolved) {
    klass->SetStatus(mirror::Class::kStatusVerifying);
  } else {
    CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime)
        << PrettyClass(klass);
    CHECK(!Runtime::Current()->IsCompiler());
    klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime);
  }

  // Verify super class.
  mirror::Class* super = klass->GetSuperClass();
  if (super != NULL) {
    // Acquire lock to prevent races on verifying the super class.
    ObjectLock lock(self, super);

    if (!super->IsVerified() && !super->IsErroneous()) {
      Runtime::Current()->GetClassLinker()->VerifyClass(super);
    }
    if (!super->IsCompileTimeVerified()) {
      std::string error_msg(StringPrintf("Rejecting class %s that attempts to sub-class erroneous class %s",
                                         PrettyDescriptor(klass).c_str(),
                                         PrettyDescriptor(super).c_str()));
      LOG(ERROR) << error_msg  << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
      SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
      if (cause.get() != NULL) {
        self->ClearException();
      }
      ThrowVerifyError(klass, "%s", error_msg.c_str());
      if (cause.get() != NULL) {
        self->GetException(NULL)->SetCause(cause.get());
      }
      klass->SetStatus(mirror::Class::kStatusError);
      return;
    }
  }

  // Try to use verification information from the oat file, otherwise do runtime verification.
  const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
  mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
  bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
  verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
  if (oat_file_class_status == mirror::Class::kStatusError) {
    LOG(WARNING) << "Skipping runtime verification of erroneous class " << PrettyDescriptor(klass)
                 << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
    ThrowVerifyError(klass, "Rejecting class %s because it failed compile-time verification",
                     PrettyDescriptor(klass).c_str());
    klass->SetStatus(mirror::Class::kStatusError);
    return;
  }
  std::string error_msg;
  if (!preverified) {
    verifier_failure = verifier::MethodVerifier::VerifyClass(klass, error_msg, Runtime::Current()->IsCompiler());
  }
  if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
    if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
      LOG(WARNING) << "Soft verification failure in class " << PrettyDescriptor(klass)
          << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
          << " because: " << error_msg;
    }
    self->AssertNoPendingException();
    // Make sure all classes referenced by catch blocks are resolved.
    ResolveClassExceptionHandlerTypes(dex_file, klass);
    if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
      klass->SetStatus(mirror::Class::kStatusVerified);
    } else {
      CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure);
      // Soft failures at compile time should be retried at runtime. Soft
      // failures at runtime will be handled by slow paths in the generated
      // code. Set status accordingly.
      if (Runtime::Current()->IsCompiler()) {
        klass->SetStatus(mirror::Class::kStatusRetryVerificationAtRuntime);
      } else {
        klass->SetStatus(mirror::Class::kStatusVerified);
      }
    }
  } else {
    LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass)
        << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
        << " because: " << error_msg;
    self->AssertNoPendingException();
    ThrowVerifyError(klass, "%s", error_msg.c_str());
    klass->SetStatus(mirror::Class::kStatusError);
  }
}

bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass,
                                          mirror::Class::Status& oat_file_class_status) {
  if (!Runtime::Current()->IsStarted()) {
    return false;
  }
  if (Runtime::Current()->UseCompileTimeClassPath()) {
    return false;
  }
  const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file);
  CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
  CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
  const char* descriptor = ClassHelper(klass).GetDescriptor();
  uint32_t class_def_index;
  bool found = dex_file.FindClassDefIndex(descriptor, class_def_index);
  CHECK(found) << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
  UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
  CHECK(oat_class.get() != NULL)
          << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
  oat_file_class_status = oat_class->GetStatus();
  if (oat_file_class_status == mirror::Class::kStatusVerified ||
      oat_file_class_status == mirror::Class::kStatusInitialized) {
    return true;
  }
  if (oat_file_class_status == mirror::Class::kStatusRetryVerificationAtRuntime) {
    // Compile time verification failed with a soft error. Compile time verification can fail
    // because we have incomplete type information. Consider the following:
    // class ... {
    //   Foo x;
    //   .... () {
    //     if (...) {
    //       v1 gets assigned a type of resolved class Foo
    //     } else {
    //       v1 gets assigned a type of unresolved class Bar
    //     }
    //     iput x = v1
    // } }
    // when we merge v1 following the if-the-else it results in Conflict
    // (see verifier::RegType::Merge) as we can't know the type of Bar and we could possibly be
    // allowing an unsafe assignment to the field x in the iput (javac may have compiled this as
    // it knew Bar was a sub-class of Foo, but for us this may have been moved into a separate apk
    // at compile time).
    return false;
  }
  if (oat_file_class_status == mirror::Class::kStatusError) {
    // Compile time verification failed with a hard error. This is caused by invalid instructions
    // in the class. These errors are unrecoverable.
    return false;
  }
  if (oat_file_class_status == mirror::Class::kStatusNotReady) {
    // Status is uninitialized if we couldn't determine the status at compile time, for example,
    // not loading the class.
    // TODO: when the verifier doesn't rely on Class-es failing to resolve/load the type hierarchy
    // isn't a problem and this case shouldn't occur
    return false;
  }
  LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
             << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;

  return false;
}

void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass) {
  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i));
  }
  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetVirtualMethod(i));
  }
}

void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file,
                                                     mirror::AbstractMethod* method) {
  // similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod.
  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
  if (code_item == NULL) {
    return;  // native or abstract method
  }
  if (code_item->tries_size_ == 0) {
    return;  // nothing to process
  }
  const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
  ClassLinker* linker = Runtime::Current()->GetClassLinker();
  for (uint32_t idx = 0; idx < handlers_size; idx++) {
    CatchHandlerIterator iterator(handlers_ptr);
    for (; iterator.HasNext(); iterator.Next()) {
      // Ensure exception types are resolved so that they don't need resolution to be delivered,
      // unresolved exception types will be ignored by exception delivery
      if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) {
        mirror::Class* exception_type = linker->ResolveType(iterator.GetHandlerTypeIndex(), method);
        if (exception_type == NULL) {
          DCHECK(Thread::Current()->IsExceptionPending());
          Thread::Current()->ClearException();
        }
      }
    }
    handlers_ptr = iterator.EndDataPointer();
  }
}

static void CheckProxyConstructor(mirror::AbstractMethod* constructor);
static void CheckProxyMethod(mirror::AbstractMethod* method,
                             SirtRef<mirror::AbstractMethod>& prototype);

mirror::Class* ClassLinker::CreateProxyClass(mirror::String* name,
                                             mirror::ObjectArray<mirror::Class>* interfaces,
                                             mirror::ClassLoader* loader,
                                             mirror::ObjectArray<mirror::AbstractMethod>* methods,
                                             mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >* throws) {
  Thread* self = Thread::Current();
  SirtRef<mirror::Class> klass(self, AllocClass(self, GetClassRoot(kJavaLangClass),
                                                sizeof(mirror::SynthesizedProxyClass)));
  CHECK(klass.get() != NULL);
  DCHECK(klass->GetClass() != NULL);
  klass->SetObjectSize(sizeof(mirror::Proxy));
  klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal);
  klass->SetClassLoader(loader);
  DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
  klass->SetName(name);
  mirror::Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
  klass->SetDexCache(proxy_class->GetDexCache());

  klass->SetStatus(mirror::Class::kStatusIdx);

  klass->SetDexTypeIndex(DexFile::kDexNoIndex16);

  // Instance fields are inherited, but we add a couple of static fields...
  klass->SetSFields(AllocFieldArray(self, 2));
  // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
  // our proxy, so Class.getInterfaces doesn't return the flattened set.
  SirtRef<mirror::Field> interfaces_sfield(self, AllocField(self));
  klass->SetStaticField(0, interfaces_sfield.get());
  interfaces_sfield->SetDexFieldIndex(0);
  interfaces_sfield->SetDeclaringClass(klass.get());
  interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
  // 2. Create a static field 'throws' that holds exceptions thrown by our methods.
  SirtRef<mirror::Field> throws_sfield(self, AllocField(self));
  klass->SetStaticField(1, throws_sfield.get());
  throws_sfield->SetDexFieldIndex(1);
  throws_sfield->SetDeclaringClass(klass.get());
  throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);

  // Proxies have 1 direct method, the constructor
  klass->SetDirectMethods(AllocAbstractMethodArray(self, 1));
  klass->SetDirectMethod(0, CreateProxyConstructor(self, klass, proxy_class));

  // Create virtual method using specified prototypes
  size_t num_virtual_methods = methods->GetLength();
  klass->SetVirtualMethods(AllocMethodArray(self, num_virtual_methods));
  for (size_t i = 0; i < num_virtual_methods; ++i) {
    SirtRef<mirror::AbstractMethod> prototype(self, methods->Get(i));
    klass->SetVirtualMethod(i, CreateProxyMethod(self, klass, prototype));
  }

  klass->SetSuperClass(proxy_class);  // The super class is java.lang.reflect.Proxy
  klass->SetStatus(mirror::Class::kStatusLoaded);  // Class is now effectively in the loaded state
  self->AssertNoPendingException();

  // Link the fields and virtual methods, creating vtable and iftables
  if (!LinkClass(klass, interfaces)) {
    klass->SetStatus(mirror::Class::kStatusError);
    return NULL;
  }
  {
    ObjectLock lock(self, klass.get());  // Must hold lock on object when initializing.
    interfaces_sfield->SetObject(klass.get(), interfaces);
    throws_sfield->SetObject(klass.get(), throws);
    klass->SetStatus(mirror::Class::kStatusInitialized);
  }

  // sanity checks
  if (kIsDebugBuild) {
    CHECK(klass->GetIFields() == NULL);
    CheckProxyConstructor(klass->GetDirectMethod(0));
    for (size_t i = 0; i < num_virtual_methods; ++i) {
      SirtRef<mirror::AbstractMethod> prototype(self, methods->Get(i));
      CheckProxyMethod(klass->GetVirtualMethod(i), prototype);
    }

    std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
                                                   name->ToModifiedUtf8().c_str()));
    CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name);

    std::string throws_field_name(StringPrintf("java.lang.Class[][] %s.throws",
                                               name->ToModifiedUtf8().c_str()));
    CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name);

    mirror::SynthesizedProxyClass* synth_proxy_class =
        down_cast<mirror::SynthesizedProxyClass*>(klass.get());
    CHECK_EQ(synth_proxy_class->GetInterfaces(), interfaces);
    CHECK_EQ(synth_proxy_class->GetThrows(), throws);
  }
  return klass.get();
}

std::string ClassLinker::GetDescriptorForProxy(const mirror::Class* proxy_class) {
  DCHECK(proxy_class->IsProxyClass());
  mirror::String* name = proxy_class->GetName();
  DCHECK(name != NULL);
  return DotToDescriptor(name->ToModifiedUtf8().c_str());
}

mirror::AbstractMethod* ClassLinker::FindMethodForProxy(const mirror::Class* proxy_class,
                                                        const mirror::AbstractMethod* proxy_method) {
  DCHECK(proxy_class->IsProxyClass());
  DCHECK(proxy_method->IsProxyMethod());
  // Locate the dex cache of the original interface/Object
  mirror::DexCache* dex_cache = NULL;
  {
    mirror::ObjectArray<mirror::Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes();
    MutexLock mu(Thread::Current(), dex_lock_);
    for (size_t i = 0; i != dex_caches_.size(); ++i) {
      if (dex_caches_[i]->GetResolvedTypes() == resolved_types) {
        dex_cache = dex_caches_[i];
        break;
      }
    }
  }
  CHECK(dex_cache != NULL);
  uint32_t method_idx = proxy_method->GetDexMethodIndex();
  mirror::AbstractMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx);
  CHECK(resolved_method != NULL);
  return resolved_method;
}


mirror::AbstractMethod* ClassLinker::CreateProxyConstructor(Thread* self,
                                                            SirtRef<mirror::Class>& klass,
                                                            mirror::Class* proxy_class) {
  // Create constructor for Proxy that must initialize h
  mirror::ObjectArray<mirror::AbstractMethod>* proxy_direct_methods =
      proxy_class->GetDirectMethods();
  CHECK_EQ(proxy_direct_methods->GetLength(), 15);
  mirror::AbstractMethod* proxy_constructor = proxy_direct_methods->Get(2);
  // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
  // code_ too)
  mirror::AbstractMethod* constructor =
      down_cast<mirror::AbstractMethod*>(proxy_constructor->Clone(self));
  // Make this constructor public and fix the class to be our Proxy version
  constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
  constructor->SetDeclaringClass(klass.get());
  return constructor;
}

static void CheckProxyConstructor(mirror::AbstractMethod* constructor)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  CHECK(constructor->IsConstructor());
  MethodHelper mh(constructor);
  CHECK_STREQ(mh.GetName(), "<init>");
  CHECK_EQ(mh.GetSignature(), std::string("(Ljava/lang/reflect/InvocationHandler;)V"));
  DCHECK(constructor->IsPublic());
}

mirror::AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass,
                                                       SirtRef<mirror::AbstractMethod>& prototype) {
  // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
  // prototype method
  prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
                                                                   prototype.get());
  // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
  // as necessary
  mirror::AbstractMethod* method = down_cast<mirror::AbstractMethod*>(prototype->Clone(self));

  // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
  // the intersection of throw exceptions as defined in Proxy
  method->SetDeclaringClass(klass.get());
  method->SetAccessFlags((method->GetAccessFlags() & ~kAccAbstract) | kAccFinal);

  // At runtime the method looks like a reference and argument saving method, clone the code
  // related parameters from this method.
  mirror::AbstractMethod* refs_and_args =
      Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
  method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
  method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
  method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
#if !defined(ART_USE_PORTABLE_COMPILER)
  method->SetCode(reinterpret_cast<void*>(art_quick_proxy_invoke_handler));
#else
  method->SetCode(reinterpret_cast<void*>(art_portable_proxy_invoke_handler));
#endif

  return method;
}

static void CheckProxyMethod(mirror::AbstractMethod* method,
                             SirtRef<mirror::AbstractMethod>& prototype)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  // Basic sanity
  CHECK(!prototype->IsFinal());
  CHECK(method->IsFinal());
  CHECK(!method->IsAbstract());

  // The proxy method doesn't have its own dex cache or dex file and so it steals those of its
  // interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
  CHECK_EQ(prototype->GetDexCacheStrings(), method->GetDexCacheStrings());
  CHECK_EQ(prototype->GetDexCacheResolvedMethods(), method->GetDexCacheResolvedMethods());
  CHECK_EQ(prototype->GetDexCacheResolvedTypes(), method->GetDexCacheResolvedTypes());
  CHECK_EQ(prototype->GetDexCacheInitializedStaticStorage(),
           method->GetDexCacheInitializedStaticStorage());
  CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());

  MethodHelper mh(method);
  MethodHelper mh2(prototype.get());
  CHECK_STREQ(mh.GetName(), mh2.GetName());
  CHECK_STREQ(mh.GetShorty(), mh2.GetShorty());
  // More complex sanity - via dex cache
  CHECK_EQ(mh.GetReturnType(), mh2.GetReturnType());
}

bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_run_clinit, bool can_init_statics) {
  CHECK(klass->IsResolved() || klass->IsErroneous())
      << PrettyClass(klass) << ": state=" << klass->GetStatus();

  Thread* self = Thread::Current();

  mirror::AbstractMethod* clinit = NULL;
  {
    // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
    ObjectLock lock(self, klass);

    if (klass->GetStatus() == mirror::Class::kStatusInitialized) {
      return true;
    }

    if (klass->IsErroneous()) {
      ThrowEarlierClassFailure(klass);
      return false;
    }

    if (klass->GetStatus() == mirror::Class::kStatusResolved ||
        klass->GetStatus() == mirror::Class::kStatusRetryVerificationAtRuntime) {
      VerifyClass(klass);
      if (klass->GetStatus() != mirror::Class::kStatusVerified) {
        if (klass->GetStatus() == mirror::Class::kStatusError) {
          CHECK(self->IsExceptionPending());
        }
        return false;
      }
    }

    clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V");
    if (clinit != NULL && !can_run_clinit) {
      // if the class has a <clinit> but we can't run it during compilation,
      // don't bother going to kStatusInitializing. We return false so that
      // sub-classes don't believe this class is initialized.
      // Opportunistically link non-static methods, TODO: don't initialize and dirty pages
      // in second pass.
      return false;
    }

    // If the class is kStatusInitializing, either this thread is
    // initializing higher up the stack or another thread has beat us
    // to initializing and we need to wait. Either way, this
    // invocation of InitializeClass will not be responsible for
    // running <clinit> and will return.
    if (klass->GetStatus() == mirror::Class::kStatusInitializing) {
      // We caught somebody else in the act; was it us?
      if (klass->GetClinitThreadId() == self->GetTid()) {
        // Yes. That's fine. Return so we can continue initializing.
        return true;
      }
      // No. That's fine. Wait for another thread to finish initializing.
      return WaitForInitializeClass(klass, self, lock);
    }

    if (!ValidateSuperClassDescriptors(klass)) {
      klass->SetStatus(mirror::Class::kStatusError);
      lock.NotifyAll();
      return false;
    }

    DCHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass);

    klass->SetClinitThreadId(self->GetTid());
    klass->SetStatus(mirror::Class::kStatusInitializing);
  }

  uint64_t t0 = NanoTime();

  if (!InitializeSuperClass(klass, can_run_clinit, can_init_statics)) {
    // Super class initialization failed, this can be because we can't run
    // super-class class initializers in which case we'll be verified.
    // Otherwise this class is erroneous.
    if (!can_run_clinit) {
      CHECK(klass->IsVerified());
    } else {
      CHECK(klass->IsErroneous());
    }
    // Signal to any waiting threads that saw this class as initializing.
    ObjectLock lock(self, klass);
    lock.NotifyAll();
    return false;
  }

  bool has_static_field_initializers = InitializeStaticFields(klass);

  if (clinit != NULL) {
    if (Runtime::Current()->IsStarted()) {
      JValue result;
      clinit->Invoke(self, NULL, 0, &result, 'V');
    } else {
      art::interpreter::EnterInterpreterFromInvoke(self, clinit, NULL, NULL, NULL);
    }
  }

  FixupStaticTrampolines(klass);

  uint64_t t1 = NanoTime();

  bool success = true;
  {
    ObjectLock lock(self, klass);

    if (self->IsExceptionPending()) {
      WrapExceptionInInitializer();
      klass->SetStatus(mirror::Class::kStatusError);
      success = false;
    } else {
      RuntimeStats* global_stats = Runtime::Current()->GetStats();
      RuntimeStats* thread_stats = self->GetStats();
      ++global_stats->class_init_count;
      ++thread_stats->class_init_count;
      global_stats->class_init_time_ns += (t1 - t0);
      thread_stats->class_init_time_ns += (t1 - t0);
      // Set the class as initialized except if we can't initialize static fields and static field
      // initialization is necessary.
      if (!can_init_statics && has_static_field_initializers) {
        klass->SetStatus(mirror::Class::kStatusVerified);  // Don't leave class in initializing state.
        success = false;
      } else {
        klass->SetStatus(mirror::Class::kStatusInitialized);
      }
      if (VLOG_IS_ON(class_linker)) {
        ClassHelper kh(klass);
        LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
      }
    }
    lock.NotifyAll();
  }
  return success;
}

bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  while (true) {
    self->AssertNoPendingException();
    lock.WaitIgnoringInterrupts();

    // 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()) {
      WrapExceptionInInitializer();
      klass->SetStatus(mirror::Class::kStatusError);
      return false;
    }
    // Spurious wakeup? Go back to waiting.
    if (klass->GetStatus() == mirror::Class::kStatusInitializing) {
      continue;
    }
    if (klass->GetStatus() == mirror::Class::kStatusVerified && Runtime::Current()->IsCompiler()) {
      // Compile time initialization failed.
      return false;
    }
    if (klass->IsErroneous()) {
      // The caller wants an exception, but it was thrown in a
      // different thread.  Synthesize one here.
      ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
                                PrettyDescriptor(klass).c_str());
      return false;
    }
    if (klass->IsInitialized()) {
      return true;
    }
    LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass) << " is " << klass->GetStatus();
  }
  LOG(FATAL) << "Not Reached" << PrettyClass(klass);
}

bool ClassLinker::ValidateSuperClassDescriptors(const mirror::Class* klass) {
  if (klass->IsInterface()) {
    return true;
  }
  // begin with the methods local to the superclass
  if (klass->HasSuperClass() &&
      klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
    const mirror::Class* super = klass->GetSuperClass();
    for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
      const mirror::AbstractMethod* method = klass->GetVTable()->Get(i);
      if (method != super->GetVTable()->Get(i) &&
          !IsSameMethodSignatureInDifferentClassContexts(method, super, klass)) {
        ThrowLinkageError(klass, "Class %s method %s resolves differently in superclass %s",
                          PrettyDescriptor(klass).c_str(), PrettyMethod(method).c_str(),
                          PrettyDescriptor(super).c_str());
        return false;
      }
    }
  }
  mirror::IfTable* iftable = klass->GetIfTable();
  for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
    mirror::Class* interface = iftable->GetInterface(i);
    if (klass->GetClassLoader() != interface->GetClassLoader()) {
      for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
        const mirror::AbstractMethod* method = iftable->GetMethodArray(i)->Get(j);
        if (!IsSameMethodSignatureInDifferentClassContexts(method, interface,
                                                           method->GetDeclaringClass())) {
          ThrowLinkageError(klass, "Class %s method %s resolves differently in interface %s",
                            PrettyDescriptor(method->GetDeclaringClass()).c_str(),
                            PrettyMethod(method).c_str(),
                            PrettyDescriptor(interface).c_str());
          return false;
        }
      }
    }
  }
  return true;
}

// Returns true if classes referenced by the signature of the method are the
// same classes in klass1 as they are in klass2.
bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::AbstractMethod* method,
                                                                const mirror::Class* klass1,
                                                                const mirror::Class* klass2) {
  if (klass1 == klass2) {
    return true;
  }
  const DexFile& dex_file = *method->GetDeclaringClass()->GetDexCache()->GetDexFile();
  const DexFile::ProtoId& proto_id =
      dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
  for (DexFileParameterIterator it(dex_file, 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 (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
        return false;
      }
    }
  }
  // Check the return type
  const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id);
  if (descriptor[0] == 'L' || descriptor[0] == '[') {
    if (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
      return false;
    }
  }
  return true;
}

// Returns true if the descriptor resolves to the same class in the context of klass1 and klass2.
bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor,
                                                           const mirror::Class* klass1,
                                                           const mirror::Class* klass2) {
  CHECK(descriptor != NULL);
  CHECK(klass1 != NULL);
  CHECK(klass2 != NULL);
  if (klass1 == klass2) {
    return true;
  }
  mirror::Class* found1 = FindClass(descriptor, klass1->GetClassLoader());
  if (found1 == NULL) {
    Thread::Current()->ClearException();
  }
  mirror::Class* found2 = FindClass(descriptor, klass2->GetClassLoader());
  if (found2 == NULL) {
    Thread::Current()->ClearException();
  }
  return found1 == found2;
}

bool ClassLinker::InitializeSuperClass(mirror::Class* klass, bool can_run_clinit, bool can_init_fields) {
  CHECK(klass != NULL);
  if (!klass->IsInterface() && klass->HasSuperClass()) {
    mirror::Class* super_class = klass->GetSuperClass();
    if (!super_class->IsInitialized()) {
      CHECK(!super_class->IsInterface());
      // Must hold lock on object when initializing and setting status.
      Thread* self = Thread::Current();
      ObjectLock lock(self, klass);
      bool super_initialized = InitializeClass(super_class, can_run_clinit, can_init_fields);
      // TODO: check for a pending exception
      if (!super_initialized) {
        if (!can_run_clinit) {
          // Don't set status to error when we can't run <clinit>.
          CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusInitializing) << PrettyClass(klass);
          klass->SetStatus(mirror::Class::kStatusVerified);
          return false;
        }
        klass->SetStatus(mirror::Class::kStatusError);
        klass->NotifyAll(self);
        return false;
      }
    }
  }
  return true;
}

bool ClassLinker::EnsureInitialized(mirror::Class* c, bool can_run_clinit, bool can_init_fields) {
  DCHECK(c != NULL);
  if (c->IsInitialized()) {
    return true;
  }

  Thread* self = Thread::Current();
  ScopedThreadStateChange tsc(self, kRunnable);
  bool success = InitializeClass(c, can_run_clinit, can_init_fields);
  if (!success) {
    CHECK(self->IsExceptionPending() || !can_run_clinit) << PrettyClass(c);
  }
  return success;
}

void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
                                    mirror::Class* c, SafeMap<uint32_t, mirror::Field*>& field_map) {
  mirror::ClassLoader* cl = c->GetClassLoader();
  const byte* class_data = dex_file.GetClassData(dex_class_def);
  ClassDataItemIterator it(dex_file, class_data);
  for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
    field_map.Put(i, ResolveField(dex_file, it.GetMemberIndex(), c->GetDexCache(), cl, true));
  }
}

bool ClassLinker::InitializeStaticFields(mirror::Class* klass) {
  size_t num_static_fields = klass->NumStaticFields();
  if (num_static_fields == 0) {
    return false;
  }
  mirror::DexCache* dex_cache = klass->GetDexCache();
  // TODO: this seems like the wrong check. do we really want !IsPrimitive && !IsArray?
  if (dex_cache == NULL) {
    return false;
  }
  ClassHelper kh(klass);
  const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
  CHECK(dex_class_def != NULL);
  const DexFile& dex_file = kh.GetDexFile();
  EncodedStaticFieldValueIterator it(dex_file, dex_cache, klass->GetClassLoader(),
                                     this, *dex_class_def);

  if (it.HasNext()) {
    // We reordered the fields, so we need to be able to map the field indexes to the right fields.
    SafeMap<uint32_t, mirror::Field*> field_map;
    ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
    for (size_t i = 0; it.HasNext(); i++, it.Next()) {
      it.ReadValueToField(field_map.Get(i));
    }
    return true;
  }
  return false;
}

bool ClassLinker::LinkClass(SirtRef<mirror::Class>& klass,
                            mirror::ObjectArray<mirror::Class>* interfaces) {
  CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
  if (!LinkSuperClass(klass)) {
    return false;
  }
  if (!LinkMethods(klass, interfaces)) {
    return false;
  }
  if (!LinkInstanceFields(klass)) {
    return false;
  }
  if (!LinkStaticFields(klass)) {
    return false;
  }
  CreateReferenceInstanceOffsets(klass);
  CreateReferenceStaticOffsets(klass);
  CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
  klass->SetStatus(mirror::Class::kStatusResolved);
  return true;
}

bool ClassLinker::LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file) {
  CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus());
  StringPiece descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
  const DexFile::ClassDef* class_def = dex_file.FindClassDef(descriptor);
  CHECK(class_def != NULL);
  uint16_t super_class_idx = class_def->superclass_idx_;
  if (super_class_idx != DexFile::kDexNoIndex16) {
    mirror::Class* super_class = ResolveType(dex_file, super_class_idx, klass.get());
    if (super_class == NULL) {
      DCHECK(Thread::Current()->IsExceptionPending());
      return false;
    }
    // Verify
    if (!klass->CanAccess(super_class)) {
      ThrowIllegalAccessError(klass.get(), "Class %s extended by class %s is inaccessible",
                              PrettyDescriptor(super_class).c_str(),
                              PrettyDescriptor(klass.get()).c_str());
      return false;
    }
    klass->SetSuperClass(super_class);
  }
  const DexFile::TypeList* interfaces = dex_file.GetInterfacesList(*class_def);
  if (interfaces != NULL) {
    for (size_t i = 0; i < interfaces->Size(); i++) {
      uint16_t idx = interfaces->GetTypeItem(i).type_idx_;
      mirror::Class* interface = ResolveType(dex_file, idx, klass.get());
      if (interface == NULL) {
        DCHECK(Thread::Current()->IsExceptionPending());
        return false;
      }
      // Verify
      if (!klass->CanAccess(interface)) {
        // TODO: the RI seemed to ignore this in my testing.
        ThrowIllegalAccessError(klass.get(), "Interface %s implemented by class %s is inaccessible",
                                PrettyDescriptor(interface).c_str(),
                                PrettyDescriptor(klass.get()).c_str());
        return false;
      }
    }
  }
  // Mark the class as loaded.
  klass->SetStatus(mirror::Class::kStatusLoaded);
  return true;
}

bool ClassLinker::LinkSuperClass(SirtRef<mirror::Class>& klass) {
  CHECK(!klass->IsPrimitive());
  mirror::Class* super = klass->GetSuperClass();
  if (klass.get() == GetClassRoot(kJavaLangObject)) {
    if (super != NULL) {
      ThrowClassFormatError(klass.get(), "java.lang.Object must not have a superclass");
      return false;
    }
    return true;
  }
  if (super == NULL) {
    ThrowLinkageError(klass.get(), "No superclass defined for class %s",
                      PrettyDescriptor(klass.get()).c_str());
    return false;
  }
  // Verify
  if (super->IsFinal() || super->IsInterface()) {
    ThrowIncompatibleClassChangeError(klass.get(), "Superclass %s of %s is %s",
                                      PrettyDescriptor(super).c_str(),
                                      PrettyDescriptor(klass.get()).c_str(),
                                      super->IsFinal() ? "declared final" : "an interface");
    return false;
  }
  if (!klass->CanAccess(super)) {
    ThrowIllegalAccessError(klass.get(), "Superclass %s is inaccessible to class %s",
                            PrettyDescriptor(super).c_str(),
                            PrettyDescriptor(klass.get()).c_str());
    return false;
  }

  // Inherit kAccClassIsFinalizable from the superclass in case this class doesn't override finalize.
  if (super->IsFinalizable()) {
    klass->SetFinalizable();
  }

  // Inherit reference flags (if any) from the superclass.
  int reference_flags = (super->GetAccessFlags() & kAccReferenceFlagsMask);
  if (reference_flags != 0) {
    klass->SetAccessFlags(klass->GetAccessFlags() | reference_flags);
  }
  // Disallow custom direct subclasses of java.lang.ref.Reference.
  if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) {
    ThrowLinkageError(klass.get(),
                      "Class %s attempts to subclass java.lang.ref.Reference, which is not allowed",
                      PrettyDescriptor(klass.get()).c_str());
    return false;
  }

#ifndef NDEBUG
  // Ensure super classes are fully resolved prior to resolving fields..
  while (super != NULL) {
    CHECK(super->IsResolved());
    super = super->GetSuperClass();
  }
#endif
  return true;
}

// Populate the class vtable and itable. Compute return type indices.
bool ClassLinker::LinkMethods(SirtRef<mirror::Class>& klass,
                              mirror::ObjectArray<mirror::Class>* interfaces) {
  if (klass->IsInterface()) {
    // No vtable.
    size_t count = klass->NumVirtualMethods();
    if (!IsUint(16, count)) {
      ThrowClassFormatError(klass.get(), "Too many methods on interface: %zd", count);
      return false;
    }
    for (size_t i = 0; i < count; ++i) {
      klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
    }
    // Link interface method tables
    return LinkInterfaceMethods(klass, interfaces);
  } else {
    // Link virtual and interface method tables
    return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass, interfaces);
  }
  return true;
}

bool ClassLinker::LinkVirtualMethods(SirtRef<mirror::Class>& klass) {
  Thread* self = Thread::Current();
  if (klass->HasSuperClass()) {
    uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
    size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength();
    CHECK_LE(actual_count, max_count);
    // TODO: do not assign to the vtable field until it is fully constructed.
    SirtRef<mirror::ObjectArray<mirror::AbstractMethod> >
      vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(self, max_count));
    // See if any of our virtual methods override the superclass.
    MethodHelper local_mh(NULL, this);
    MethodHelper super_mh(NULL, this);
    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
      mirror::AbstractMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
      local_mh.ChangeMethod(local_method);
      size_t j = 0;
      for (; j < actual_count; ++j) {
        mirror::AbstractMethod* super_method = vtable->Get(j);
        super_mh.ChangeMethod(super_method);
        if (local_mh.HasSameNameAndSignature(&super_mh)) {
          if (klass->CanAccessMember(super_method->GetDeclaringClass(), super_method->GetAccessFlags())) {
            if (super_method->IsFinal()) {
              ThrowLinkageError(klass.get(), "Method %s overrides final method in class %s",
                                PrettyMethod(local_method).c_str(),
                                super_mh.GetDeclaringClassDescriptor());
              return false;
            }
            vtable->Set(j, local_method);
            local_method->SetMethodIndex(j);
            break;
          } else {
            LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(local_method)
                         << " would have incorrectly overridden the package-private method in "
                         << PrettyDescriptor(super_mh.GetDeclaringClassDescriptor());
          }
        }
      }
      if (j == actual_count) {
        // Not overriding, append.
        vtable->Set(actual_count, local_method);
        local_method->SetMethodIndex(actual_count);
        actual_count += 1;
      }
    }
    if (!IsUint(16, actual_count)) {
      ThrowClassFormatError(klass.get(), "Too many methods defined on class: %zd", actual_count);
      return false;
    }
    // Shrink vtable if possible
    CHECK_LE(actual_count, max_count);
    if (actual_count < max_count) {
      vtable.reset(vtable->CopyOf(self, actual_count));
    }
    klass->SetVTable(vtable.get());
  } else {
    CHECK(klass.get() == GetClassRoot(kJavaLangObject));
    uint32_t num_virtual_methods = klass->NumVirtualMethods();
    if (!IsUint(16, num_virtual_methods)) {
      ThrowClassFormatError(klass.get(), "Too many methods: %d", num_virtual_methods);
      return false;
    }
    SirtRef<mirror::ObjectArray<mirror::AbstractMethod> >
        vtable(self, AllocMethodArray(self, num_virtual_methods));
    for (size_t i = 0; i < num_virtual_methods; ++i) {
      mirror::AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
      vtable->Set(i, virtual_method);
      virtual_method->SetMethodIndex(i & 0xFFFF);
    }
    klass->SetVTable(vtable.get());
  }
  return true;
}

bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
                                       mirror::ObjectArray<mirror::Class>* interfaces) {
  size_t super_ifcount;
  if (klass->HasSuperClass()) {
    super_ifcount = klass->GetSuperClass()->GetIfTableCount();
  } else {
    super_ifcount = 0;
  }
  size_t ifcount = super_ifcount;
  ClassHelper kh(klass.get(), this);
  uint32_t num_interfaces = interfaces == NULL ? kh.NumDirectInterfaces() : interfaces->GetLength();
  ifcount += num_interfaces;
  for (size_t i = 0; i < num_interfaces; i++) {
    mirror::Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i);
    ifcount += interface->GetIfTableCount();
  }
  if (ifcount == 0) {
    // Class implements no interfaces.
    DCHECK_EQ(klass->GetIfTableCount(), 0);
    DCHECK(klass->GetIfTable() == NULL);
    return true;
  }
  if (ifcount == super_ifcount) {
    // Class implements same interfaces as parent, are any of these not marker interfaces?
    bool has_non_marker_interface = false;
    mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable();
    for (size_t i = 0; i < ifcount; ++i) {
      if (super_iftable->GetMethodArrayCount(i) > 0) {
        has_non_marker_interface = true;
        break;
      }
    }
    if (!has_non_marker_interface) {
      // Class just inherits marker interfaces from parent so recycle parent's iftable.
      klass->SetIfTable(super_iftable);
      return true;
    }
  }
  Thread* self = Thread::Current();
  SirtRef<mirror::IfTable> iftable(self, AllocIfTable(self, ifcount));
  if (super_ifcount != 0) {
    mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable();
    for (size_t i = 0; i < super_ifcount; i++) {
      mirror::Class* super_interface = super_iftable->GetInterface(i);
      iftable->SetInterface(i, super_interface);
    }
  }
  // Flatten the interface inheritance hierarchy.
  size_t idx = super_ifcount;
  for (size_t i = 0; i < num_interfaces; i++) {
    mirror::Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i);
    DCHECK(interface != NULL);
    if (!interface->IsInterface()) {
      ClassHelper ih(interface);
      ThrowIncompatibleClassChangeError(klass.get(), "Class %s implements non-interface class %s",
                                        PrettyDescriptor(klass.get()).c_str(),
                                        PrettyDescriptor(ih.GetDescriptor()).c_str());
      return false;
    }
    // Check if interface is already in iftable
    bool duplicate = false;
    for (size_t j = 0; j < idx; j++) {
      mirror::Class* existing_interface = iftable->GetInterface(j);
      if (existing_interface == interface) {
        duplicate = true;
        break;
      }
    }
    if (!duplicate) {
      // Add this non-duplicate interface.
      iftable->SetInterface(idx++, interface);
      // Add this interface's non-duplicate super-interfaces.
      for (int32_t j = 0; j < interface->GetIfTableCount(); j++) {
        mirror::Class* super_interface = interface->GetIfTable()->GetInterface(j);
        bool super_duplicate = false;
        for (size_t k = 0; k < idx; k++) {
          mirror::Class* existing_interface = iftable->GetInterface(k);
          if (existing_interface == super_interface) {
            super_duplicate = true;
            break;
          }
        }
        if (!super_duplicate) {
          iftable->SetInterface(idx++, super_interface);
        }
      }
    }
  }
  // Shrink iftable in case duplicates were found
  if (idx < ifcount) {
    iftable.reset(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
    ifcount = idx;
  } else {
    CHECK_EQ(idx, ifcount);
  }
  klass->SetIfTable(iftable.get());

  // If we're an interface, we don't need the vtable pointers, so we're done.
  if (klass->IsInterface()) {
    return true;
  }
  std::vector<mirror::AbstractMethod*> miranda_list;
  MethodHelper vtable_mh(NULL, this);
  MethodHelper interface_mh(NULL, this);
  for (size_t i = 0; i < ifcount; ++i) {
    mirror::Class* interface = iftable->GetInterface(i);
    size_t num_methods = interface->NumVirtualMethods();
    if (num_methods > 0) {
      mirror::ObjectArray<mirror::AbstractMethod>* method_array =
          AllocMethodArray(self, num_methods);
      iftable->SetMethodArray(i, method_array);
      mirror::ObjectArray<mirror::AbstractMethod>* vtable = klass->GetVTableDuringLinking();
      for (size_t j = 0; j < num_methods; ++j) {
        mirror::AbstractMethod* interface_method = interface->GetVirtualMethod(j);
        interface_mh.ChangeMethod(interface_method);
        int32_t k;
        // For each method listed in the interface's method list, find the
        // matching method in our class's method list.  We want to favor the
        // subclass over the superclass, which just requires walking
        // back from the end of the vtable.  (This only matters if the
        // superclass defines a private method and this class redefines
        // it -- otherwise it would use the same vtable slot.  In .dex files
        // those don't end up in the virtual method table, so it shouldn't
        // matter which direction we go.  We walk it backward anyway.)
        for (k = vtable->GetLength() - 1; k >= 0; --k) {
          mirror::AbstractMethod* vtable_method = vtable->Get(k);
          vtable_mh.ChangeMethod(vtable_method);
          if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
            if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
              ThrowIllegalAccessError(klass.get(),
                                      "Method '%s' implementing interface method '%s' is not public",
                                      PrettyMethod(vtable_method).c_str(),
                                      PrettyMethod(interface_method).c_str());
              return false;
            }
            method_array->Set(j, vtable_method);
            break;
          }
        }
        if (k < 0) {
          SirtRef<mirror::AbstractMethod> miranda_method(self, NULL);
          for (size_t mir = 0; mir < miranda_list.size(); mir++) {
            mirror::AbstractMethod* mir_method = miranda_list[mir];
            vtable_mh.ChangeMethod(mir_method);
            if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
              miranda_method.reset(miranda_list[mir]);
              break;
            }
          }
          if (miranda_method.get() == NULL) {
            // point the interface table at a phantom slot
            miranda_method.reset(down_cast<mirror::AbstractMethod*>(interface_method->Clone(self)));
            miranda_list.push_back(miranda_method.get());
          }
          method_array->Set(j, miranda_method.get());
        }
      }
    }
  }
  if (!miranda_list.empty()) {
    int old_method_count = klass->NumVirtualMethods();
    int new_method_count = old_method_count + miranda_list.size();
    klass->SetVirtualMethods((old_method_count == 0)
                             ? AllocMethodArray(self, new_method_count)
                             : klass->GetVirtualMethods()->CopyOf(self, new_method_count));

    SirtRef<mirror::ObjectArray<mirror::AbstractMethod> >
        vtable(self, klass->GetVTableDuringLinking());
    CHECK(vtable.get() != NULL);
    int old_vtable_count = vtable->GetLength();
    int new_vtable_count = old_vtable_count + miranda_list.size();
    vtable.reset(vtable->CopyOf(self, new_vtable_count));
    for (size_t i = 0; i < miranda_list.size(); ++i) {
      mirror::AbstractMethod* method = miranda_list[i];
      // Leave the declaring class alone as type indices are relative to it
      method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
      method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
      klass->SetVirtualMethod(old_method_count + i, method);
      vtable->Set(old_vtable_count + i, method);
    }
    // TODO: do not assign to the vtable field until it is fully constructed.
    klass->SetVTable(vtable.get());
  }

  mirror::ObjectArray<mirror::AbstractMethod>* vtable = klass->GetVTableDuringLinking();
  for (int i = 0; i < vtable->GetLength(); ++i) {
    CHECK(vtable->Get(i) != NULL);
  }

//  klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);

  return true;
}

bool ClassLinker::LinkInstanceFields(SirtRef<mirror::Class>& klass) {
  CHECK(klass.get() != NULL);
  return LinkFields(klass, false);
}

bool ClassLinker::LinkStaticFields(SirtRef<mirror::Class>& klass) {
  CHECK(klass.get() != NULL);
  size_t allocated_class_size = klass->GetClassSize();
  bool success = LinkFields(klass, true);
  CHECK_EQ(allocated_class_size, klass->GetClassSize());
  return success;
}

struct LinkFieldsComparator {
  explicit LinkFieldsComparator(FieldHelper* fh)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
      : fh_(fh) {}
  // No thread safety analysis as will be called from STL. Checked lock held in constructor.
  bool operator()(const mirror::Field* field1, const mirror::Field* field2)
      NO_THREAD_SAFETY_ANALYSIS {
    // First come reference fields, then 64-bit, and finally 32-bit
    fh_->ChangeField(field1);
    Primitive::Type type1 = fh_->GetTypeAsPrimitiveType();
    fh_->ChangeField(field2);
    Primitive::Type type2 = fh_->GetTypeAsPrimitiveType();
    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) {
      return order1 < order2;
    }

    // same basic group? then sort by string.
    fh_->ChangeField(field1);
    StringPiece name1(fh_->GetName());
    fh_->ChangeField(field2);
    StringPiece name2(fh_->GetName());
    return name1 < name2;
  }

  FieldHelper* fh_;
};

bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
  size_t num_fields =
      is_static ? klass->NumStaticFields() : klass->NumInstanceFields();

  mirror::ObjectArray<mirror::Field>* fields =
      is_static ? klass->GetSFields() : klass->GetIFields();

  // Initialize size and field_offset
  size_t size;
  MemberOffset field_offset(0);
  if (is_static) {
    size = klass->GetClassSize();
    field_offset = mirror::Class::FieldsOffset();
  } else {
    mirror::Class* super_class = klass->GetSuperClass();
    if (super_class != NULL) {
      CHECK(super_class->IsResolved());
      field_offset = MemberOffset(super_class->GetObjectSize());
    }
    size = field_offset.Uint32Value();
  }

  CHECK_EQ(num_fields == 0, fields == NULL);

  // we want a relatively stable order so that adding new fields
  // minimizes disruption of C++ version such as Class and Method.
  std::deque<mirror::Field*> grouped_and_sorted_fields;
  for (size_t i = 0; i < num_fields; i++) {
    grouped_and_sorted_fields.push_back(fields->Get(i));
  }
  FieldHelper fh(NULL, this);
  std::sort(grouped_and_sorted_fields.begin(),
            grouped_and_sorted_fields.end(),
            LinkFieldsComparator(&fh));

  // References should be at the front.
  size_t current_field = 0;
  size_t num_reference_fields = 0;
  for (; current_field < num_fields; current_field++) {
    mirror::Field* field = grouped_and_sorted_fields.front();
    fh.ChangeField(field);
    Primitive::Type type = fh.GetTypeAsPrimitiveType();
    bool isPrimitive = type != Primitive::kPrimNot;
    if (isPrimitive) {
      break; // past last reference, move on to the next phase
    }
    grouped_and_sorted_fields.pop_front();
    num_reference_fields++;
    fields->Set(current_field, field);
    field->SetOffset(field_offset);
    field_offset = MemberOffset(field_offset.Uint32Value() + 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 (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) {
    for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) {
      mirror::Field* field = grouped_and_sorted_fields[i];
      fh.ChangeField(field);
      Primitive::Type type = fh.GetTypeAsPrimitiveType();
      CHECK(type != Primitive::kPrimNot);  // should only be working on primitive types
      if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
        continue;
      }
      fields->Set(current_field++, field);
      field->SetOffset(field_offset);
      // drop the consumed field
      grouped_and_sorted_fields.erase(grouped_and_sorted_fields.begin() + i);
      break;
    }
    // whether we found a 32-bit field for padding or not, we advance
    field_offset = MemberOffset(field_offset.Uint32Value() + sizeof(uint32_t));
  }

  // Alignment is good, shuffle any double-wide fields forward, and
  // finish assigning field offsets to all fields.
  DCHECK(current_field == num_fields || IsAligned<8>(field_offset.Uint32Value()));
  while (!grouped_and_sorted_fields.empty()) {
    mirror::Field* field = grouped_and_sorted_fields.front();
    grouped_and_sorted_fields.pop_front();
    fh.ChangeField(field);
    Primitive::Type type = fh.GetTypeAsPrimitiveType();
    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 == Primitive::kPrimLong || type == Primitive::kPrimDouble)
                                 ? sizeof(uint64_t)
                                 : sizeof(uint32_t)));
    current_field++;
  }

  // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
  if (!is_static &&
      StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;") {
    // We know there are no non-reference fields in the Reference classes, and we know
    // that 'referent' is alphabetically last, so this is easy...
    CHECK_EQ(num_reference_fields, num_fields);
    fh.ChangeField(fields->Get(num_fields - 1));
    CHECK_STREQ(fh.GetName(), "referent");
    --num_reference_fields;
  }

#ifndef NDEBUG
  // Make sure that all reference fields appear before
  // non-reference fields, and all double-wide fields are aligned.
  bool seen_non_ref = false;
  for (size_t i = 0; i < num_fields; i++) {
    mirror::Field* field = fields->Get(i);
    if (false) {  // enable to debug field layout
      LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
                << " class=" << PrettyClass(klass.get())
                << " field=" << PrettyField(field)
                << " offset=" << field->GetField32(MemberOffset(mirror::Field::OffsetOffset()),
                                                   false);
    }
    fh.ChangeField(field);
    Primitive::Type type = fh.GetTypeAsPrimitiveType();
    bool is_primitive = type != Primitive::kPrimNot;
    if (StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;" &&
        StringPiece(fh.GetName()) == "referent") {
      is_primitive = true; // We lied above, so we have to expect a lie here.
    }
    if (is_primitive) {
      if (!seen_non_ref) {
        seen_non_ref = true;
        DCHECK_EQ(num_reference_fields, i);
      }
    } else {
      DCHECK(!seen_non_ref);
    }
  }
  if (!seen_non_ref) {
    DCHECK_EQ(num_fields, num_reference_fields);
  }
#endif
  size = field_offset.Uint32Value();
  // Update klass
  if (is_static) {
    klass->SetNumReferenceStaticFields(num_reference_fields);
    klass->SetClassSize(size);
  } else {
    klass->SetNumReferenceInstanceFields(num_reference_fields);
    if (!klass->IsVariableSize()) {
      klass->SetObjectSize(size);
    }
  }
  return true;
}

//  Set the bitmap of reference offsets, refOffsets, from the ifields
//  list.
void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass) {
  uint32_t reference_offsets = 0;
  mirror::Class* super_class = klass->GetSuperClass();
  if (super_class != NULL) {
    reference_offsets = super_class->GetReferenceInstanceOffsets();
    // If our superclass overflowed, we don't stand a chance.
    if (reference_offsets == CLASS_WALK_SUPER) {
      klass->SetReferenceInstanceOffsets(reference_offsets);
      return;
    }
  }
  CreateReferenceOffsets(klass, false, reference_offsets);
}

void ClassLinker::CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass) {
  CreateReferenceOffsets(klass, true, 0);
}

void ClassLinker::CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static,
                                         uint32_t reference_offsets) {
  size_t num_reference_fields =
      is_static ? klass->NumReferenceStaticFieldsDuringLinking()
                : klass->NumReferenceInstanceFieldsDuringLinking();
  const mirror::ObjectArray<mirror::Field>* fields =
      is_static ? klass->GetSFields() : klass->GetIFields();
  // All of the fields that contain object references are guaranteed
  // to be at the beginning of the fields list.
  for (size_t i = 0; i < num_reference_fields; ++i) {
    // Note that byte_offset is the offset from the beginning of
    // object, not the offset into instance data
    const mirror::Field* field = fields->Get(i);
    MemberOffset byte_offset = field->GetOffsetDuringLinking();
    CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
    if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) {
      uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset.Uint32Value());
      CHECK_NE(new_bit, 0U);
      reference_offsets |= new_bit;
    } else {
      reference_offsets = CLASS_WALK_SUPER;
      break;
    }
  }
  // Update fields in klass
  if (is_static) {
    klass->SetReferenceStaticOffsets(reference_offsets);
  } else {
    klass->SetReferenceInstanceOffsets(reference_offsets);
  }
}

mirror::String* ClassLinker::ResolveString(const DexFile& dex_file,
                                           uint32_t string_idx, mirror::DexCache* dex_cache) {
  DCHECK(dex_cache != NULL);
  mirror::String* resolved = dex_cache->GetResolvedString(string_idx);
  if (resolved != NULL) {
    return resolved;
  }
  const DexFile::StringId& string_id = dex_file.GetStringId(string_idx);
  int32_t utf16_length = dex_file.GetStringLength(string_id);
  const char* utf8_data = dex_file.GetStringData(string_id);
  mirror::String* string = intern_table_->InternStrong(utf16_length, utf8_data);
  dex_cache->SetResolvedString(string_idx, string);
  return string;
}

mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file,
                                        uint16_t type_idx,
                                        mirror::DexCache* dex_cache,
                                        mirror::ClassLoader* class_loader) {
  DCHECK(dex_cache != NULL);
  mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
  if (resolved == NULL) {
    const char* descriptor = dex_file.StringByTypeIdx(type_idx);
    resolved = FindClass(descriptor, class_loader);
    if (resolved != NULL) {
      // TODO: we used to throw here if resolved's class loader was not the
      //       boot class loader. This was to permit different classes with the
      //       same name to be loaded simultaneously by different loaders
      dex_cache->SetResolvedType(type_idx, resolved);
    } else {
      Thread* self = Thread::Current();
      CHECK(self->IsExceptionPending())
          << "Expected pending exception for failed resolution of: " << descriptor;
      // Convert a ClassNotFoundException to a NoClassDefFoundError.
      SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
      if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
        Thread::Current()->ClearException();
        ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
        self->GetException(NULL)->SetCause(cause.get());
      }
    }
  }
  return resolved;
}

mirror::AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
                                                   uint32_t method_idx,
                                                   mirror::DexCache* dex_cache,
                                                   mirror::ClassLoader* class_loader,
                                                   const mirror::AbstractMethod* referrer,
                                                   InvokeType type) {
  DCHECK(dex_cache != NULL);
  // Check for hit in the dex cache.
  mirror::AbstractMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
  if (resolved != NULL) {
    return resolved;
  }
  // Fail, get the declaring class.
  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
  mirror::Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader);
  if (klass == NULL) {
    DCHECK(Thread::Current()->IsExceptionPending());
    return NULL;
  }
  // Scan using method_idx, this saves string compares but will only hit for matching dex
  // caches/files.
  switch (type) {
    case kDirect:  // Fall-through.
    case kStatic:
      resolved = klass->FindDirectMethod(dex_cache, method_idx);
      break;
    case kInterface:
      resolved = klass->FindInterfaceMethod(dex_cache, method_idx);
      DCHECK(resolved == NULL || resolved->GetDeclaringClass()->IsInterface());
      break;
    case kSuper:  // Fall-through.
    case kVirtual:
      resolved = klass->FindVirtualMethod(dex_cache, method_idx);
      break;
    default:
      LOG(FATAL) << "Unreachable - invocation type: " << type;
  }
  if (resolved == NULL) {
    // Search by name, which works across dex files.
    const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
    std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL));
    switch (type) {
      case kDirect:  // Fall-through.
      case kStatic:
        resolved = klass->FindDirectMethod(name, signature);
        break;
      case kInterface:
        resolved = klass->FindInterfaceMethod(name, signature);
        DCHECK(resolved == NULL || resolved->GetDeclaringClass()->IsInterface());
        break;
      case kSuper:  // Fall-through.
      case kVirtual:
        resolved = klass->FindVirtualMethod(name, signature);
        break;
    }
  }
  if (resolved != NULL) {
    // We found a method, check for incompatible class changes.
    if (resolved->CheckIncompatibleClassChange(type)) {
      resolved = NULL;
    }
  }
  if (resolved != NULL) {
    // Be a good citizen and update the dex cache to speed subsequent calls.
    dex_cache->SetResolvedMethod(method_idx, resolved);
    return resolved;
  } else {
    // We failed to find the method which means either an access error, an incompatible class
    // change, or no such method. First try to find the method among direct and virtual methods.
    const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
    std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL));
    switch (type) {
      case kDirect:
      case kStatic:
        resolved = klass->FindVirtualMethod(name, signature);
        break;
      case kInterface:
      case kVirtual:
      case kSuper:
        resolved = klass->FindDirectMethod(name, signature);
        break;
    }

    // If we found something, check that it can be accessed by the referrer.
    if (resolved != NULL && referrer != NULL) {
      mirror::Class* methods_class = resolved->GetDeclaringClass();
      mirror::Class* referring_class = referrer->GetDeclaringClass();
      if (!referring_class->CanAccess(methods_class)) {
        ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
                                                      referrer, resolved, type);
        return NULL;
      } else if (!referring_class->CanAccessMember(methods_class,
                                                   resolved->GetAccessFlags())) {
        ThrowIllegalAccessErrorMethod(referring_class, resolved);
        return NULL;
      }
    }

    // Otherwise, throw an IncompatibleClassChangeError if we found something, and check interface
    // methods and throw if we find the method there. If we find nothing, throw a NoSuchMethodError.
    switch (type) {
      case kDirect:
      case kStatic:
        if (resolved != NULL) {
          ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
        } else {
          resolved = klass->FindInterfaceMethod(name, signature);
          if (resolved != NULL) {
            ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
          } else {
            ThrowNoSuchMethodError(type, klass, name, signature);
          }
        }
        break;
      case kInterface:
        if (resolved != NULL) {
          ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
        } else {
          resolved = klass->FindVirtualMethod(name, signature);
          if (resolved != NULL) {
            ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
          } else {
            ThrowNoSuchMethodError(type, klass, name, signature);
          }
        }
        break;
      case kSuper:
        ThrowNoSuchMethodError(type, klass, name, signature);
        break;
      case kVirtual:
        if (resolved != NULL) {
          ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
        } else {
          resolved = klass->FindInterfaceMethod(name, signature);
          if (resolved != NULL) {
            ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
          } else {
            ThrowNoSuchMethodError(type, klass, name, signature);
          }
        }
        break;
    }
    DCHECK(Thread::Current()->IsExceptionPending());
    return NULL;
  }
}

mirror::Field* ClassLinker::ResolveField(const DexFile& dex_file,
                                         uint32_t field_idx,
                                         mirror::DexCache* dex_cache,
                                         mirror::ClassLoader* class_loader,
                                         bool is_static) {
  DCHECK(dex_cache != NULL);
  mirror::Field* resolved = dex_cache->GetResolvedField(field_idx);
  if (resolved != NULL) {
    return resolved;
  }
  const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
  mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
  if (klass == NULL) {
    DCHECK(Thread::Current()->IsExceptionPending());
    return NULL;
  }

  if (is_static) {
    resolved = klass->FindStaticField(dex_cache, field_idx);
  } else {
    resolved = klass->FindInstanceField(dex_cache, field_idx);
  }

  if (resolved == NULL) {
    const char* name = dex_file.GetFieldName(field_id);
    const char* type = dex_file.GetFieldTypeDescriptor(field_id);
    if (is_static) {
      resolved = klass->FindStaticField(name, type);
    } else {
      resolved = klass->FindInstanceField(name, type);
    }
    if (resolved == NULL) {
      ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name);
      return NULL;
    }
  }
  dex_cache->SetResolvedField(field_idx, resolved);
  return resolved;
}

mirror::Field* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
                                            uint32_t field_idx,
                                            mirror::DexCache* dex_cache,
                                            mirror::ClassLoader* class_loader) {
  DCHECK(dex_cache != NULL);
  mirror::Field* resolved = dex_cache->GetResolvedField(field_idx);
  if (resolved != NULL) {
    return resolved;
  }
  const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
  mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
  if (klass == NULL) {
    DCHECK(Thread::Current()->IsExceptionPending());
    return NULL;
  }

  const char* name = dex_file.GetFieldName(field_id);
  const char* type = dex_file.GetFieldTypeDescriptor(field_id);
  resolved = klass->FindField(name, type);
  if (resolved != NULL) {
    dex_cache->SetResolvedField(field_idx, resolved);
  } else {
    ThrowNoSuchFieldError("", klass, type, name);
  }
  return resolved;
}

const char* ClassLinker::MethodShorty(uint32_t method_idx, mirror::AbstractMethod* referrer,
                                      uint32_t* length) {
  mirror::Class* declaring_class = referrer->GetDeclaringClass();
  mirror::DexCache* dex_cache = declaring_class->GetDexCache();
  const DexFile& dex_file = *dex_cache->GetDexFile();
  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
  return dex_file.GetMethodShorty(method_id, length);
}

void ClassLinker::DumpAllClasses(int flags) const {
  // TODO: at the time this was written, it wasn't safe to call PrettyField with the ClassLinker
  // lock held, because it might need to resolve a field's type, which would try to take the lock.
  std::vector<mirror::Class*> all_classes;
  {
    MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
    typedef Table::const_iterator It;  // TODO: C++0x auto
    for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
      all_classes.push_back(it->second);
    }
    for (It it = image_classes_.begin(), end = image_classes_.end(); it != end; ++it) {
      all_classes.push_back(it->second);
    }
  }

  for (size_t i = 0; i < all_classes.size(); ++i) {
    all_classes[i]->DumpClass(std::cerr, flags);
  }
}

void ClassLinker::DumpForSigQuit(std::ostream& os) const {
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  os << "Loaded classes: " << image_classes_.size() << " image classes; "
     << classes_.size() << " allocated classes\n";
}

size_t ClassLinker::NumLoadedClasses() const {
  MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  return classes_.size() + image_classes_.size();
}

pid_t ClassLinker::GetClassesLockOwner() {
  return Locks::classlinker_classes_lock_->GetExclusiveOwnerTid();
}

pid_t ClassLinker::GetDexLockOwner() {
  return dex_lock_.GetExclusiveOwnerTid();
}

void ClassLinker::SetClassRoot(ClassRoot class_root, mirror::Class* klass) {
  DCHECK(!init_done_);

  DCHECK(klass != NULL);
  DCHECK(klass->GetClassLoader() == NULL);

  DCHECK(class_roots_ != NULL);
  DCHECK(class_roots_->Get(class_root) == NULL);
  class_roots_->Set(class_root, klass);
}

}  // namespace art
