Add access check slow paths to field accesses

This check makes the verifier, compiler and runtime agree with who
should perform access checks and fixes compliance for these
instructions.

Introduce new "fast" sget/sput that just get the static storage base
from a method's declaring class when the static field is within the same
class. Saves a load and branch in the common case.

Fold gen routines for wide and not wide together.

Fix bug where sub-classes could appear intialized in the image but their
parents were only verified.

Extra debug output for test case 075.

Change-Id: I934da3624ed8fa8e026b2c95d936d04b1af022ef
diff --git a/src/compiler.h b/src/compiler.h
index 1165161..d966b02 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -35,6 +35,7 @@
 
 class Context;
 class TimingLogger;
+typedef struct CompilationUnit CompilationUnit;
 
 class Compiler {
  public:
@@ -85,43 +86,29 @@
   const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
 
   // Callbacks from OAT/ART compiler to see what runtime checks must be generated
-  bool CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache, uint32_t type_idx) const;
-  bool CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache, uint32_t string_idx) const {
-    // 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->GetResolvedType(type_idx);
-    if (resolved_class == NULL) {
-      return false;  // Unknown class needs access checks.
-    }
-    const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
-    Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
-    if (referrer_class == NULL) {
-      return false;  // Incomplete referrer knowledge needs access check.
-    }
-    // Perform access check, will return true if access is ok or false if we're going to have to
-    // check this at runtime (for example for class loaders).
-    return referrer_class->CanAccess(resolved_class);
-  }
 
+  bool CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache, uint32_t type_idx) const;
+
+  bool CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache, uint32_t string_idx) const;
+
+  // Are runtime access checks necessary in the compiled code?
+  bool CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
+                                  const DexFile& dex_file, uint32_t type_idx) const;
+
+  // Are runtime access and instantiable checks necessary in the code?
   bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
-                                              const DexFile& dex_file, uint32_t type_idx) const {
-    Class* resolved_class = dex_cache->GetResolvedType(type_idx);
-    if (resolved_class == NULL) {
-      return false;  // Unknown class needs access checks.
-    }
-    const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
-    Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
-    if (referrer_class == NULL) {
-      return false;  // Incomplete referrer knowledge needs access check.
-    }
-    // Perform access check, will return true if access is ok or false if we're going to have to
-    // check this at runtime (for example for class loaders).
-    return referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
-  }
+                                              const DexFile& dex_file, uint32_t type_idx) const;
+
+  // Can we fast path instance field access? Computes field's offset and volatility
+  bool ComputeInstanceFieldInfo(uint32_t field_idx, CompilationUnit* cUnit,
+                                int& field_offset, bool& is_volatile) const;
+
+  // Can we fastpath static field access? Computes field's offset, volatility and whether the
+  // field is within the referrer (which can avoid checking class initialization)
+  bool ComputeStaticFieldInfo(uint32_t field_idx, CompilationUnit* cUnit,
+                              int& field_offset, int& ssb_index,
+                              bool& is_referrers_class, bool& is_volatile) const;
+
  private:
 
   // Checks if class specified by type_idx is one of the image_classes_