Add -j to dex2oat.

Change-Id: I80f3f2605b8afcdf9adf9382716b041f10efa104
diff --git a/src/common_test.h b/src/common_test.h
index 6adb02d..d55dfbd 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -342,7 +342,7 @@
             runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
       }
     }
-    compiler_.reset(new Compiler(instruction_set, false, NULL));
+    compiler_.reset(new Compiler(instruction_set, false, 2, NULL));
 
     Heap::VerifyHeap();  // Check for heap corruption before the test
   }
diff --git a/src/compiler.cc b/src/compiler.cc
index ca9e53e..1f652ef 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -54,8 +54,7 @@
   ByteArray* CreateJniDlsymLookupStub();
 }
 
-Compiler::Compiler(InstructionSet instruction_set,
-                   bool image,
+Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
                    const std::set<std::string>* image_classes)
     : instruction_set_(instruction_set),
       jni_compiler_(instruction_set),
@@ -63,6 +62,7 @@
       compiled_methods_lock_("compiled method lock"),
       compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
       image_(image),
+      thread_count_(thread_count),
       image_classes_(image_classes) {
   CHECK(!Runtime::Current()->IsStarted());
   if (!image_) {
@@ -277,10 +277,9 @@
   size_t stripe_;
 };
 
-void ForAll(Context* context, size_t begin, size_t end, Callback callback) {
+void ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
   std::vector<WorkerThread*> threads;
 
-  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));
   }
@@ -388,10 +387,10 @@
   context.dex_cache = dex_cache;
   context.dex_file = &dex_file;
 
-  ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType);
+  ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
   timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
 
-  ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods);
+  ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
   timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
 }
 
@@ -436,7 +435,7 @@
   context.class_linker = Runtime::Current()->GetClassLinker();
   context.class_loader = class_loader;
   context.dex_file = &dex_file;
-  ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass);
+  ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
 
   dex_file.ChangePermissions(PROT_READ);
 }
@@ -534,7 +533,7 @@
   context.class_loader = class_loader;
   context.compiler = this;
   context.dex_file = &dex_file;
-  ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass);
+  ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
 }
 
 void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
diff --git a/src/compiler.h b/src/compiler.h
index f5f8cfa..4822b9f 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -43,8 +43,7 @@
   // enabled.  "image_classes" lets the compiler know what classes it
   // can assume will be in the image, with NULL implying all available
   // classes.
-  explicit Compiler(InstructionSet instruction_set,
-                    bool image,
+  explicit Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
                     const std::set<std::string>* image_classes);
 
   ~Compiler();
@@ -169,7 +168,7 @@
   InvokeStubTable compiled_invoke_stubs_;
 
   bool image_;
-
+  size_t thread_count_;
   uint64_t start_ns_;
 
   const std::set<std::string>* image_classes_;
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 25c1d82..f78579f 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -100,18 +100,17 @@
 class Dex2Oat {
  public:
 
-  static Dex2Oat* Create(Runtime::Options& options) {
+  static Dex2Oat* Create(Runtime::Options& options, size_t thread_count) {
     UniquePtr<Runtime> runtime(CreateRuntime(options));
     if (runtime.get() == NULL) {
       return NULL;
     }
-    return new Dex2Oat(runtime.release());
+    return new Dex2Oat(runtime.release(), thread_count);
   }
 
   ~Dex2Oat() {
     delete runtime_;
-    const size_t thread_count = static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
-    LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) << " (threads: " << thread_count << ")";
+    LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) << " (threads: " << thread_count_ << ")";
   }
 
   // Make a list of descriptors for classes to include in the image
@@ -199,7 +198,7 @@
       class_loader.get()->reset(PathClassLoader::AllocCompileTime(class_path_files));
     }
 
-    Compiler compiler(instruction_set_, image, image_classes);
+    Compiler compiler(instruction_set_, image, thread_count_, image_classes);
     compiler.CompileAll(class_loader->get(), dex_files);
 
     if (!OatWriter::Create(oat_file, class_loader->get(), dex_files, compiler)) {
@@ -240,7 +239,8 @@
 
  private:
 
-  explicit Dex2Oat(Runtime* runtime) : runtime_(runtime), start_ns_(NanoTime()) {
+  explicit Dex2Oat(Runtime* runtime, size_t thread_count)
+      : runtime_(runtime), thread_count_(thread_count), start_ns_(NanoTime()) {
   }
 
   static Runtime* CreateRuntime(Runtime::Options& options) {
@@ -364,6 +364,7 @@
   static const InstructionSet instruction_set_ = kThumb2;
 
   Runtime* runtime_;
+  size_t thread_count_;
   uint64_t start_ns_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
@@ -416,6 +417,7 @@
   uintptr_t image_base = 0;
   std::string host_prefix;
   std::vector<const char*> runtime_args;
+  int thread_count = 2;
 
   for (int i = 0; i < argc; i++) {
     const StringPiece option(argv[i]);
@@ -441,6 +443,12 @@
         fprintf(stderr, "could not parse --oat-fd argument '%s' as an integer\n", oat_fd_str);
         usage();
       }
+    } else if (option.starts_with("-j")) {
+      const char* thread_count_str = option.substr(strlen("-j")).data();
+      if (!ParseInt(thread_count_str, &thread_count)) {
+        fprintf(stderr, "could not parse -j argument '%s' as an integer\n", thread_count_str);
+        usage();
+      }
     } else if (option.starts_with("--oat-name=")) {
       oat_name = option.substr(strlen("--oat-name=")).data();
     } else if (option.starts_with("--image=")) {
@@ -595,7 +603,7 @@
     options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
   }
 
-  UniquePtr<Dex2Oat> dex2oat(Dex2Oat::Create(options));
+  UniquePtr<Dex2Oat> dex2oat(Dex2Oat::Create(options, thread_count));
 
   // If --image-classes was specified, calculate the full list of classes to include in the image
   UniquePtr<const std::set<std::string> > image_classes(NULL);
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 0fd64ff..7c837d4 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -29,7 +29,7 @@
 
   SirtRef<ClassLoader> class_loader(NULL);
   if (compile) {
-    compiler_.reset(new Compiler(kThumb2, false, NULL));
+    compiler_.reset(new Compiler(kThumb2, false, 2, NULL));
     compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
   }