Don't fork dex2oat process on target device.

Change-Id: I35370d328aaa1aaaed5b56e62e51c4c74afa9cba
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 8f41c24..c950298 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -66,7 +66,7 @@
 
 ART_HOST_CFLAGS := $(art_cflags) -DANDROID_SMP=1
 
-ART_TARGET_CFLAGS := $(art_cflags)
+ART_TARGET_CFLAGS := $(art_cflags) -DART_TARGET
 ifeq ($(TARGET_CPU_SMP),true)
   ART_TARGET_CFLAGS += -DANDROID_SMP=1
 else
diff --git a/src/compiler.h b/src/compiler.h
index 9b8a3ab..c0732aa 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -176,6 +176,10 @@
     return compiler_context_;
   }
 
+  size_t GetThreadCount() const {
+    return thread_count_;
+  }
+
   class PatchInformation {
    public:
     DexCache* GetDexCache() const {
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 1c47392..10844b8 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -166,9 +166,14 @@
 }
 
 
-bool CompilationUnit::Materialize() {
+bool CompilationUnit::Materialize(size_t thread_count) {
   MutexLock GUARD(cunit_lock_);
 
+  if (thread_count == 1) {
+    llvm::raw_string_ostream str_os(elf_image_);
+    return MaterializeToFile(str_os, insn_set_);
+  }
+
   // Prepare the pipe between parent process and child process
   int pipe_fd[2];
   if (pipe(pipe_fd) == -1) {
@@ -191,9 +196,11 @@
     // Change process groups, so we don't get ripped by ProcessManager
     setpgid(0, 0);
 
+    llvm::raw_fd_ostream fd_os(pipe_fd[1], /* shouldClose */true);
+
     // TODO: Should use exec* family instead of invoking a function.
     // Forward our compilation request to bcc.
-    exit(static_cast<int>(!MaterializeToFile(pipe_fd[1], insn_set_)));
+    exit(static_cast<int>(!MaterializeToFile(fd_os, insn_set_)));
 
   } else { // Parent process
     // Close the unused pipe write end
@@ -219,7 +226,7 @@
       }
 
       // Append to the end of the elf_image_
-      elf_image_.insert(elf_image_.end(), buf.begin(), buf.begin() + nread);
+      elf_image_.append(buf.begin(), buf.begin() + nread);
 
       if (nread < static_cast<ssize_t>(buf_size)) { // EOF reached!
         break;
@@ -274,7 +281,7 @@
   }
 }
 
-bool CompilationUnit::MaterializeToFile(int output_fd,
+bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream,
                                         InstructionSet insn_set) {
   // Initialize the LLVM first
   llvm::InitializeAllTargets();
@@ -357,8 +364,7 @@
 
   // Add passes to emit ELF image
   {
-    llvm::formatted_raw_ostream formatted_os(
-      *(new llvm::raw_fd_ostream(output_fd, /* shouldClose */false)), true);
+    llvm::formatted_raw_ostream formatted_os(out_stream, false);
 
     // Ask the target to add backend passes as necessary.
     if (target_machine->addPassesToEmitFile(pm,
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index a464df0..a92dabe 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -38,6 +38,7 @@
   class Function;
   class LLVMContext;
   class Module;
+  class raw_ostream;
 }
 
 namespace art {
@@ -89,7 +90,7 @@
 
   bool WriteBitcodeToFile(const std::string& bitcode_filename);
 
-  bool Materialize();
+  bool Materialize(size_t thread_count);
 
   bool IsMaterialized() const {
     MutexLock GUARD(cunit_lock_);
@@ -121,14 +122,15 @@
   UniquePtr<RuntimeSupportBuilder> runtime_support_;
   llvm::Module* module_;
 
-  std::vector<uint8_t> elf_image_;
+  std::string elf_image_;
 
   SafeMap<const llvm::Function*, CompiledMethod*> compiled_methods_map_;
 
   size_t mem_usage_;
   uint16_t num_elf_funcs_;
 
-  bool MaterializeToFile(int output_fd, InstructionSet insn_set);
+  bool MaterializeToFile(llvm::raw_ostream& out_stream,
+                         InstructionSet insn_set);
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index ca0a4da..681b367 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -183,7 +183,7 @@
   }
 
   // Materialize the llvm::Module into ELF object file
-  cunit->Materialize();
+  cunit->Materialize(compiler_->GetThreadCount());
 
   // Load ELF image when automatic ELF loading is enabled
   if (IsAutoElfLoadingEnabled()) {
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 0d3fa58..42a3266 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -561,6 +561,12 @@
   thread_count = 1;
 #endif
 
+#if defined(ART_USE_LLVM_COMPILER) && defined(ART_TARGET)
+  // To avoid high memory usage, always run dex2oat in single thread mode when
+  // we are using LLVM-based compiler.
+  thread_count = 1;
+#endif
+
   if (oat_filename.empty() && oat_fd == -1) {
     Usage("Output must be supplied with either --oat-file or --oat-fd");
   }
diff --git a/src/elf_image.h b/src/elf_image.h
index 79bd84e..79bfd90 100644
--- a/src/elf_image.h
+++ b/src/elf_image.h
@@ -18,6 +18,7 @@
 #define ART_SRC_ELF_IMAGE_H_
 
 #include "globals.h"
+#include <string>
 #include <vector>
 
 namespace art {
@@ -28,6 +29,10 @@
       : begin_(&*v.begin()), size_(v.size()) {
   }
 
+  explicit ElfImage(const std::string& s)
+      : begin_(reinterpret_cast<const uint8_t*>(s.data())), size_(s.size()) {
+  }
+
   explicit ElfImage(const byte* begin, size_t size)
       : begin_(begin), size_(size) {
   }