Start parallelizing dex2oat.

This is enough to perform type resolution and verification in parallel.

There appears to be a bug in InitCpu --- if you start enough threads
at once, the CHECK at the end starts to fail, with self_check == NULL; I've
commented it out for now, but this will cause test failures until it's fixed.

Change-Id: I4919682520bc01d3262c6b3d00c7bd2c2860a52e
diff --git a/src/compiler.cc b/src/compiler.cc
index 02367d3..41d2f6a 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -16,7 +16,10 @@
 
 #include "compiler.h"
 
+#include <vector>
+
 #include <sys/mman.h>
+#include <unistd.h>
 
 #include "assembler.h"
 #include "class_linker.h"
@@ -176,18 +179,17 @@
 }
 
 void Compiler::Resolve(const ClassLoader* class_loader,
-                       const std::vector<const DexFile*>& dex_files) {
+                       const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
   for (size_t i = 0; i != dex_files.size(); ++i) {
     const DexFile* dex_file = dex_files[i];
     CHECK(dex_file != NULL);
-    ResolveDexFile(class_loader, *dex_file);
+    ResolveDexFile(class_loader, *dex_file, timings);
   }
 }
 
 void Compiler::PreCompile(const ClassLoader* class_loader,
                           const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
-  Resolve(class_loader, dex_files);
-  timings.AddSplit("PreCompile.Resolve");
+  Resolve(class_loader, dex_files, timings);
 
   Verify(class_loader, dex_files);
   timings.AddSplit("PreCompile.Verify");
@@ -246,8 +248,150 @@
   return true;
 }
 
-void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
+struct Context {
+  ClassLinker* class_linker;
+  const ClassLoader* class_loader;
+  DexCache* dex_cache;
+  const DexFile* dex_file;
+};
+
+typedef void Callback(Context* context, size_t index);
+
+class WorkerThread {
+ public:
+  WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe)
+      : context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
+    CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Init, this), "compiler worker thread");
+  }
+
+  ~WorkerThread() {
+    CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
+  }
+
+ private:
+  static void* Init(void* arg) {
+    WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
+    Runtime* runtime = Runtime::Current();
+    runtime->AttachCurrentThread("Compiler Worker", true);
+    Thread::Current()->SetState(Thread::kRunnable);
+    worker->Run();
+    Thread::Current()->SetState(Thread::kNative);
+    runtime->DetachCurrentThread();
+    return NULL;
+  }
+
+  void Run() {
+    for (size_t i = begin_; i < end_; i += stripe_) {
+      callback_(context_, i);
+    }
+  }
+
+  pthread_t pthread_;
+  Thread* thread_;
+
+  Context* context_;
+  size_t begin_;
+  size_t end_;
+  Callback* callback_;
+  size_t stripe_;
+};
+
+class Workers {
+ public:
+  Workers(Context* context, size_t begin, size_t end, Callback callback) {
+    const size_t thread_count = static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
+    for (size_t i = 0; i < thread_count; ++i) {
+      threads_.push_back(new WorkerThread(context, begin + i, end, callback, thread_count));
+    }
+  }
+
+  ~Workers() {
+    STLDeleteElements(&threads_);
+  }
+
+ private:
+  std::vector<WorkerThread*> threads_;
+};
+
+static void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
+  const DexFile& dex_file = *context->dex_file;
+
+  // Method and Field are the worst. We can't resolve without either
+  // context from the code use (to disambiguate virtual vs direct
+  // method and instance vs static field) or from class
+  // definitions. While the compiler will resolve what it can as it
+  // needs it, here we try to resolve fields and methods used in class
+  // definitions, since many of them many never be referenced by
+  // generated code.
+  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
+  if (SkipClass(context->class_loader, dex_file, class_def)) {
+    return;
+  }
+
+  // Note the class_data pointer advances through the headers,
+  // static fields, instance fields, direct methods, and virtual
+  // methods.
+  const byte* class_data = dex_file.GetClassData(class_def);
+  if (class_data == NULL) {
+    // empty class such as a marker interface
+    return;
+  }
   Thread* self = Thread::Current();
+  ClassLinker* class_linker = context->class_linker;
+  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
+  ClassDataItemIterator it(dex_file, class_data);
+  while (it.HasNextStaticField()) {
+    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+                                              context->class_loader, true);
+    if (field == NULL) {
+      CHECK(self->IsExceptionPending());
+      self->ClearException();
+    }
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+                                              context->class_loader, false);
+    if (field == NULL) {
+      CHECK(self->IsExceptionPending());
+      self->ClearException();
+    }
+    it.Next();
+  }
+  while (it.HasNextDirectMethod()) {
+    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                 context->class_loader, true);
+    if (method == NULL) {
+      CHECK(self->IsExceptionPending());
+      self->ClearException();
+    }
+    it.Next();
+  }
+  while (it.HasNextVirtualMethod()) {
+    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                 context->class_loader, false);
+    if (method == NULL) {
+      CHECK(self->IsExceptionPending());
+      self->ClearException();
+    }
+    it.Next();
+  }
+  DCHECK(!it.HasNext());
+}
+
+static void ResolveType(Context* context, size_t type_idx) {
+  // Class derived values are more complicated, they require the linker and loader.
+  Thread* self = Thread::Current();
+  ClassLinker* class_linker = context->class_linker;
+  const DexFile& dex_file = *context->dex_file;
+  Class* klass = class_linker->ResolveType(dex_file, type_idx, context->dex_cache, context->class_loader);
+  if (klass == NULL) {
+    CHECK(self->IsExceptionPending());
+    Thread::Current()->ClearException();
+  }
+}
+
+void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = class_linker->FindDexCache(dex_file);
 
@@ -259,76 +403,23 @@
       class_linker->ResolveString(dex_file, string_idx, dex_cache);
     }
   }
+  timings.AddSplit("Resolve.Strings");
 
-  // Class derived values are more complicated, they require the linker and loader.
-  for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
-    Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
-    if (klass == NULL) {
-      CHECK(self->IsExceptionPending());
-      Thread::Current()->ClearException();
-    }
+  Context context;
+  context.class_linker = class_linker;
+  context.class_loader = class_loader;
+  context.dex_cache = dex_cache;
+  context.dex_file = &dex_file;
+
+  {
+    Workers workers(&context, 0, dex_cache->NumResolvedTypes(), ResolveType);
   }
+  timings.AddSplit("Resolve.Types");
 
-  // Method and Field are the worst. We can't resolve without either
-  // context from the code use (to disambiguate virtual vs direct
-  // method and instance vs static field) or from class
-  // definitions. While the compiler will resolve what it can as it
-  // needs it, here we try to resolve fields and methods used in class
-  // definitions, since many of them many never be referenced by
-  // generated code.
-  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
-    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-    if (SkipClass(class_loader, dex_file, class_def)) {
-      continue;
-    }
-
-    // Note the class_data pointer advances through the headers,
-    // static fields, instance fields, direct methods, and virtual
-    // methods.
-    const byte* class_data = dex_file.GetClassData(class_def);
-    if (class_data == NULL) {
-      // empty class such as a marker interface
-      continue;
-    }
-    ClassDataItemIterator it(dex_file, class_data);
-    while (it.HasNextStaticField()) {
-      Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
-                                                class_loader, true);
-      if (field == NULL) {
-        CHECK(self->IsExceptionPending());
-        self->ClearException();
-      }
-      it.Next();
-    }
-    while (it.HasNextInstanceField()) {
-      Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
-                                                class_loader, false);
-      if (field == NULL) {
-        CHECK(self->IsExceptionPending());
-        self->ClearException();
-      }
-      it.Next();
-    }
-    while (it.HasNextDirectMethod()) {
-      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
-                                                   class_loader, true);
-      if (method == NULL) {
-        CHECK(self->IsExceptionPending());
-        self->ClearException();
-      }
-      it.Next();
-    }
-    while (it.HasNextVirtualMethod()) {
-      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
-                                                   class_loader, false);
-      if (method == NULL) {
-        CHECK(self->IsExceptionPending());
-        self->ClearException();
-      }
-      it.Next();
-    }
-    DCHECK(!it.HasNext());
+  {
+    Workers workers(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods);
   }
+  timings.AddSplit("Resolve.MethodsAndFields");
 }
 
 void Compiler::Verify(const ClassLoader* class_loader,
@@ -340,33 +431,40 @@
   }
 }
 
+static void VerifyClass(Context* context, size_t class_def_index) {
+  const DexFile::ClassDef& class_def = context->dex_file->GetClassDef(class_def_index);
+  const char* descriptor = context->dex_file->GetClassDescriptor(class_def);
+  Class* klass = context->class_linker->FindClass(descriptor, context->class_loader);
+  if (klass == NULL) {
+    Thread* self = Thread::Current();
+    CHECK(self->IsExceptionPending());
+    self->ClearException();
+    return;
+  }
+  CHECK(klass->IsResolved()) << PrettyClass(klass);
+  context->class_linker->VerifyClass(klass);
+
+  if (klass->IsErroneous()) {
+    // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
+    CHECK(Thread::Current()->IsExceptionPending());
+    Thread::Current()->ClearException();
+    // We want to try verification again at run-time, so move back into the resolved state.
+    klass->SetStatus(Class::kStatusResolved);
+  }
+
+  CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
+  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
+}
+
 void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
   dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
-    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-    const char* descriptor = dex_file.GetClassDescriptor(class_def);
-    Class* klass = class_linker->FindClass(descriptor, class_loader);
-    if (klass == NULL) {
-      Thread* self = Thread::Current();
-      CHECK(self->IsExceptionPending());
-      self->ClearException();
-      continue;
-    }
-    CHECK(klass->IsResolved()) << PrettyClass(klass);
-    class_linker->VerifyClass(klass);
 
-    if (klass->IsErroneous()) {
-      // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
-      CHECK(Thread::Current()->IsExceptionPending());
-      Thread::Current()->ClearException();
-      // We want to try verification again at run-time, so move back into the resolved state.
-      klass->SetStatus(Class::kStatusResolved);
-    }
+  Context context;
+  context.class_linker = Runtime::Current()->GetClassLinker();
+  context.class_loader = class_loader;
+  context.dex_file = &dex_file;
+  Workers workers(&context, 0, dex_file.NumClassDefs(), VerifyClass);
 
-    CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
-    CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
-  }
   dex_file.ChangePermissions(PROT_READ);
 }