Add --image-classes to dex2oat

Change-Id: Ia88f9d302e0f9cd72be2199ee46d212d99864c67
diff --git a/src/compiler.h b/src/compiler.h
index a8ea205..5203ffb 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -13,6 +13,7 @@
 #include "runtime.h"
 #include "unordered_map.h"
 
+#include <set>
 #include <string>
 
 namespace art {
@@ -20,13 +21,18 @@
 class Compiler {
  public:
   // Create a compiler targeting the requested "instruction_set".
-  // "image" should be true if image specific optimizations should be enabled.
-  explicit Compiler(InstructionSet instruction_set, bool image);
+  // "image" should be true if image specific optimizations should be
+  // 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,
+                    const std::set<std::string>* image_classes);
 
   ~Compiler();
 
   void CompileAll(const ClassLoader* class_loader,
-                  const std::vector<const DexFile*>& class_path);
+                  const std::vector<const DexFile*>& dex_files);
 
   // Compile a single Method
   void CompileOne(const Method* method);
@@ -65,20 +71,29 @@
 
   // Callbacks from OAT/ART compiler to see what runtime checks must be generated
   bool CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache, uint32_t type_idx) const {
-    return IsImage() && dex_cache->GetResolvedTypes()->Get(type_idx) != NULL;
+    if (!IsImage()) {
+      return false;
+    }
+    Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
+    if (resolved_class == NULL) {
+      return false;
+    }
+    return IsImageClass(resolved_class->GetDescriptor()->ToModifiedUtf8());
   }
   bool CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache, uint32_t string_idx) const {
-    return IsImage() && dex_cache->GetStrings()->Get(string_idx) != NULL;
+    // TODO: Add support for loading strings referenced by image_classes_
+    // See also Compiler::ResolveDexFile
+    return IsImage() && image_classes_ == NULL && dex_cache->GetResolvedString(string_idx) != NULL;
   }
   bool CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
                                   const DexFile& dex_file, uint32_t type_idx) const {
-    Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
+    Class* resolved_class = dex_cache->GetResolvedType(type_idx);
     // We should never ask whether a type needs access checks to raise a verification error,
     // all other cases where this following test could fail should have been rewritten by the
     // verifier to verification errors. Also need to handle a lack of knowledge at compile time.
 #ifndef NDEBUG
-    Class* referrer_class = dex_cache->GetResolvedTypes()
-        ->Get(dex_file.GetMethodId(referrer_idx).class_idx_);
+    const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
+    Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
     DCHECK(resolved_class == NULL || referrer_class == NULL ||
            referrer_class->CanAccess(resolved_class));
 #endif
@@ -86,19 +101,27 @@
   }
 
  private:
+
+  // Checks if class specified by type_idx is one of the image_classes_
+  bool IsImageClass(const std::string& descriptor) const;
+
+  void PreCompile(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files);
+  void PostCompile(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files);
+
   // Attempt to resolve all type, methods, fields, and strings
   // referenced from code in the dex file following PathClassLoader
   // ordering semantics.
-  void Resolve(const ClassLoader* class_loader);
+  void Resolve(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files);
   void ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
 
-  void Verify(const ClassLoader* class_loader);
+  void Verify(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files);
   void VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
 
-  void InitializeClassesWithoutClinit(const ClassLoader* class_loader);
+  void InitializeClassesWithoutClinit(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files);
   void InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file);
 
-  void Compile(const ClassLoader* class_loader);
+  void Compile(const ClassLoader* class_loader,
+               const std::vector<const DexFile*>& dex_files);
   void CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
   void CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
                     const DexFile& dex_file);
@@ -107,7 +130,7 @@
 
   // After compiling, walk all the DexCaches and set the code and
   // method pointers of CodeAndDirectMethods entries in the DexCaches.
-  void SetCodeAndDirectMethods(const ClassLoader* class_loader);
+  void SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files);
   void SetCodeAndDirectMethodsDexFile(const DexFile& dex_file);
 
   void InsertInvokeStub(bool is_static, const char* shorty,
@@ -139,6 +162,8 @@
 
   bool image_;
 
+  const std::set<std::string>* image_classes_;
+
   bool verbose_;
 
   DISALLOW_COPY_AND_ASSIGN(Compiler);