Merge "Compile less stuff" into dalvik-dev
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 7faf452..59426a4 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -14,10 +14,10 @@
 # limitations under the License.
 #
 
-ART_SLOW_MODE := false
-ifneq ($(wildcard art/SLOW_ART),)
-$(info Enabling ART_SLOW_MODE because of existence of art/SLOW_ART)
-ART_SLOW_MODE := true
+ART_LIGHT_MODE := false
+ifneq ($(wildcard art/LIGHT_ART),)
+$(info Enabling ART_LIGHT_MODE because of existence of art/LIGHT_ART)
+ART_LIGHT_MODE := true
 endif
 
 ART_USE_PORTABLE_COMPILER := false
@@ -58,8 +58,8 @@
 	-Wstrict-aliasing=3 \
 	-fstrict-aliasing
 
-ifeq ($(ART_SLOW_MODE),true)
-  art_cflags += -DART_SLOW_MODE=1
+ifeq ($(ART_LIGHT_MODE),true)
+  art_cflags += -DART_LIGHT_MODE=1
 endif
 
 # TODO: enable -std=gnu++0x for auto support when on Ubuntu 12.04 LTS (Precise Pangolin)
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 4774c63..7dcd511 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -954,10 +954,11 @@
 
   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(class_roots->Get(kJavaLangString));
+  mirror::String::SetClass(GetClassRoot(kJavaLangString));
 
   CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
            static_cast<uint32_t>(dex_caches->GetLength()));
@@ -978,6 +979,11 @@
     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_);
@@ -994,8 +1000,6 @@
   DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
   // String class root was set above
   mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
-  mirror::AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor),
-                             GetClassRoot(kJavaLangReflectMethod));
   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
   mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -1029,6 +1033,15 @@
     DCHECK(existing == NULL) << kh.GetDescriptor();
     return;
   }
+
+  // Check if object is an uncompiled method and point the to the interpreter entry point.
+  if (obj->IsMethod()) {
+    mirror::AbstractMethod* method = obj->AsMethod();
+    if (method->GetCode() == NULL) {
+      const void* interpreter_entry = GetInterpreterEntryPoint();
+      method->SetCode(interpreter_entry);
+    }
+  }
 }
 
 // Keep in sync with InitCallback. Anything we visit, we need to
diff --git a/src/common_test.h b/src/common_test.h
index 4f91717..68b0cf6 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -212,7 +212,7 @@
           compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(&dex_file,
                                                                               method->GetDexMethodIndex()));
 
-#ifndef ART_SLOW_MODE
+#ifndef ART_LIGHT_MODE
       CHECK(compiled_method != NULL) << PrettyMethod(method);
 #endif
     }
@@ -373,8 +373,8 @@
     }
     class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
     image_classes_.reset(new std::set<std::string>);
-    compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false, image_classes_.get(),
-                                              true, true));
+    compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false, false,
+                                              image_classes_.get(), true, true));
 
     // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
     // pool is created by the runtime.
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 204f639..f08e629 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -284,9 +284,9 @@
 }
 
 CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set,
-                               bool image, size_t thread_count, bool support_debugging,
-                               const std::set<std::string>* image_classes, bool dump_stats,
-                               bool dump_timings)
+                               bool image, size_t thread_count, bool support_debugging, bool light_mode,
+                               const std::set<std::string>* image_classes, 
+                               bool dump_stats, bool dump_timings)
     : compiler_backend_(compiler_backend),
       instruction_set_(instruction_set),
       freezing_constructor_lock_("freezing constructor lock"),
@@ -295,6 +295,7 @@
       image_(image),
       thread_count_(thread_count),
       support_debugging_(support_debugging),
+      light_mode_(light_mode),
       start_ns_(0),
       stats_(new AOTCompilationStats),
       dump_stats_(dump_stats),
@@ -1612,10 +1613,15 @@
     CHECK(compiled_method != NULL);
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
-    bool dont_compile = false;
-#if ART_SLOW_MODE
-    dont_compile = (image_classes_ == NULL) || (image_classes_->size() == 0);
-#endif // ART_SLOW_MODE
+    std::string method_name(PrettyMethod(method_idx, dex_file, false));
+    // In light mode we only compile image classes.
+    bool dont_compile = light_mode_ && ((image_classes_ == NULL) || (image_classes_->size() == 0));
+
+    // Don't compile class initializers, ever.
+    if ((access_flags & kAccConstructor) && (access_flags & kAccStatic)) {
+      dont_compile = true;
+    }
+
     if (!dont_compile) {
       compiled_method = (*compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
           method_idx, class_loader, dex_file);
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index 385bc00..fae6902 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -67,9 +67,9 @@
   // can assume will be in the image, with NULL implying all available
   // classes.
   explicit CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set, bool image,
-                          size_t thread_count, bool support_debugging,
-                          const std::set<std::string>* image_classes, bool dump_stats,
-                          bool dump_timings);
+                          size_t thread_count, bool support_debugging, bool light_mode,
+                          const std::set<std::string>* image_classes, 
+                          bool dump_stats, bool dump_timings);
 
   ~CompilerDriver();
 
@@ -84,6 +84,10 @@
     return support_debugging_;
   }
 
+  bool IsLightMode() const {
+    return light_mode_;
+  }
+
   InstructionSet GetInstructionSet() const {
     return instruction_set_;
   }
@@ -340,6 +344,7 @@
   bool image_;
   size_t thread_count_;
   bool support_debugging_;
+  const bool light_mode_;
   uint64_t start_ns_;
 
   UniquePtr<AOTCompilationStats> stats_;
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index ecba628..97212ce 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -137,6 +137,8 @@
   UsageError("      Use a separate --runtime-arg switch for each argument.");
   UsageError("      Example: --runtime-arg -Xms256m");
   UsageError("");
+  UsageError("  --light-mode: compile only if generating image file");
+  UsageError("");
   std::cerr << "See log for usage error information\n";
   exit(EXIT_FAILURE);
 }
@@ -144,14 +146,15 @@
 class Dex2Oat {
  public:
   static bool Create(Dex2Oat** p_dex2oat, Runtime::Options& options, CompilerBackend compiler_backend,
-                     InstructionSet instruction_set, size_t thread_count, bool support_debugging)
+                     InstructionSet instruction_set, size_t thread_count, bool support_debugging,
+                     bool light_mode)
       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
     if (!CreateRuntime(options, instruction_set)) {
       *p_dex2oat = NULL;
       return false;
     }
     *p_dex2oat = new Dex2Oat(Runtime::Current(), compiler_backend, instruction_set, thread_count,
-                             support_debugging);
+                             support_debugging, light_mode);
     return true;
   }
 
@@ -160,6 +163,7 @@
     LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) << " (threads: " << thread_count_ << ")";
   }
 
+
   // Make a list of descriptors for classes to include in the image
   const std::set<std::string>* GetImageClassDescriptors(const char* image_classes_filename)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -261,6 +265,7 @@
                                                         image,
                                                         thread_count_,
                                                         support_debugging_,
+                                                        light_mode_,
                                                         image_classes,
                                                         dump_stats,
                                                         dump_timings));
@@ -339,14 +344,23 @@
     return true;
   }
 
+  void SetLightMode(bool light_mode) {
+    light_mode_ = light_mode;
+  }
+
+  bool GetLightMode() {
+    return light_mode_;
+  }
+
  private:
   explicit Dex2Oat(Runtime* runtime, CompilerBackend compiler_backend, InstructionSet instruction_set,
-                   size_t thread_count, bool support_debugging)
+                   size_t thread_count, bool support_debugging, bool light_mode)
       : compiler_backend_(compiler_backend),
         instruction_set_(instruction_set),
         runtime_(runtime),
         thread_count_(thread_count),
         support_debugging_(support_debugging),
+        light_mode_(light_mode),
         start_ns_(NanoTime()) {
   }
 
@@ -484,6 +498,7 @@
   Runtime* runtime_;
   size_t thread_count_;
   bool support_debugging_;
+  bool light_mode_;
   uint64_t start_ns_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
@@ -671,6 +686,7 @@
   std::vector<const char*> runtime_args;
   int thread_count = sysconf(_SC_NPROCESSORS_CONF);
   bool support_debugging = false;
+  bool light_mode = false;
 #if defined(ART_USE_PORTABLE_COMPILER)
   CompilerBackend compiler_backend = kPortable;
 #else
@@ -690,6 +706,10 @@
   bool dump_timings = kIsDebugBuild;
   bool watch_dog_enabled = !kIsTargetBuild;
 
+#if ART_LIGHT_MODE
+  light_mode = true;
+#endif // ART_LIGHT_MODE
+
   for (int i = 0; i < argc; i++) {
     const StringPiece option(argv[i]);
     bool log_options = false;
@@ -718,6 +738,8 @@
       }
     } else if (option == "-g") {
       support_debugging = true;
+    } else if (option == "--light-mode") {
+      light_mode = true;
     } else if (option == "--watch-dog") {
       watch_dog_enabled = true;
     } else if (option == "--no-watch-dog") {
@@ -923,7 +945,7 @@
   }
 
   Dex2Oat* p_dex2oat;
-  if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging)) {
+  if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging, light_mode)) {
     LOG(ERROR) << "Failed to create dex2oat";
     return EXIT_FAILURE;
   }
@@ -970,6 +992,7 @@
     }
   }
 
+
   UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
                                                                   host_prefix.get(),
                                                                   android_root,
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 75a9dbb..5d6edf2 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -76,7 +76,8 @@
 #else
     CompilerBackend compiler_backend = kQuick;
 #endif
-    compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, NULL, true, true));
+    compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, false,
+                                              NULL, true, true));
     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
   }