Check FastInstance() early for special getters and setters.

Perform the FastInstance() check for getters and setters
when they are detected by the inliner. This will help avoid
the FastInstance() check for inlining.

We also record the field offset and whether the field is
volatile and whether the method is static for use when
inlining or generating the special accessors.

Change-Id: I3f832fc9ae263883b8a984be89a3b7793398b55a
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 9f48351..5b9d66c 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -29,6 +29,7 @@
 #include "dex_file-inl.h"
 #include "dex/verification_results.h"
 #include "dex/verified_method.h"
+#include "dex/quick/dex_file_method_inliner.h"
 #include "jni_internal.h"
 #include "object_utils.h"
 #include "runtime.h"
@@ -49,6 +50,7 @@
 #include "thread_pool.h"
 #include "trampolines/trampoline_compiler.h"
 #include "verifier/method_verifier.h"
+#include "verifier/method_verifier-inl.h"
 
 #if defined(ART_USE_PORTABLE_COMPILER)
 #include "elf_writer_mclinker.h"
@@ -995,6 +997,30 @@
                                                 class_loader, NULL, type);
 }
 
+bool CompilerDriver::ComputeSpecialAccessorInfo(uint32_t field_idx, bool is_put,
+                                                verifier::MethodVerifier* verifier,
+                                                InlineIGetIPutData* result) {
+  mirror::DexCache* dex_cache = verifier->GetDexCache();
+  uint32_t method_idx = verifier->GetMethodReference().dex_method_index;
+  mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
+  mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
+  if (method == nullptr || field == nullptr) {
+    return false;
+  }
+  mirror::Class* method_class = method->GetDeclaringClass();
+  mirror::Class* field_class = field->GetDeclaringClass();
+  if (!method_class->CanAccessResolvedField(field_class, field, dex_cache, field_idx) ||
+      (is_put && field->IsFinal() && method_class != field_class)) {
+    return false;
+  }
+  DCHECK_GE(field->GetOffset().Int32Value(), 0);
+  result->method_is_static = method->IsStatic();
+  result->field_idx = field_idx;
+  result->field_offset = field->GetOffset().Int32Value();
+  result->is_volatile = field->IsVolatile();
+  return true;
+}
+
 bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit,
                                               bool is_put, int* field_offset, bool* is_volatile) {
   ScopedObjectAccess soa(Thread::Current());