Interpreter.

The opcodes filled-new-array and packed-switch aren't implemented but
are trivial given that they are variants of implemented opcodes.
Refactor Field::Get routines to take the declaring class in the case of
static field accesses. This avoids a check on every use of a field.
Refactor arg array builder to be shared by JNI invokes and invocations
into the interpreter.
Fix benign bug in const decoding in the verifier.

Change-Id: I8dee6c1f4b7f033e6c003422c56e9471cfaccda8
diff --git a/src/object.cc b/src/object.cc
index 5fdea71..9189f03 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -29,6 +29,7 @@
 #include "dex_file.h"
 #include "globals.h"
 #include "heap.h"
+#include "interpreter/interpreter.h"
 #include "intern_table.h"
 #include "logging.h"
 #include "monitor.h"
@@ -42,11 +43,52 @@
 
 namespace art {
 
+BooleanArray* Object::AsBooleanArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
+  return down_cast<BooleanArray*>(this);
+}
+
+ByteArray* Object::AsByteArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte());
+  return down_cast<ByteArray*>(this);
+}
+
+CharArray* Object::AsCharArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
+  return down_cast<CharArray*>(this);
+}
+
+ShortArray* Object::AsShortArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort());
+  return down_cast<ShortArray*>(this);
+}
+
+IntArray* Object::AsIntArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt());
+  return down_cast<IntArray*>(this);
+}
+
+LongArray* Object::AsLongArray() {
+  DCHECK(GetClass()->IsArrayClass());
+  DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong());
+  return down_cast<LongArray*>(this);
+}
+
 String* Object::AsString() {
   DCHECK(GetClass()->IsStringClass());
   return down_cast<String*>(this);
 }
 
+Throwable* Object::AsThrowable() {
+  DCHECK(GetClass()->IsThrowableClass());
+  return down_cast<Throwable*>(this);
+}
+
 Object* Object::Clone(Thread* self) {
   Class* c = GetClass();
   DCHECK(!c->IsClassClass());
@@ -188,50 +230,38 @@
 }
 
 uint32_t Field::Get32(const Object* object) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   return object->GetField32(GetOffset(), IsVolatile());
 }
 
 void Field::Set32(Object* object, uint32_t new_value) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   object->SetField32(GetOffset(), new_value, IsVolatile());
 }
 
 uint64_t Field::Get64(const Object* object) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   return object->GetField64(GetOffset(), IsVolatile());
 }
 
 void Field::Set64(Object* object, uint64_t new_value) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   object->SetField64(GetOffset(), new_value, IsVolatile());
 }
 
 Object* Field::GetObj(const Object* object) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
 }
 
 void Field::SetObj(Object* object, const Object* new_value) const {
-  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
-  if (IsStatic()) {
-    object = declaring_class_;
-  }
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(IsStatic() == (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   object->SetFieldObject(GetOffset(), new_value, IsVolatile());
 }
 
@@ -603,7 +633,7 @@
   return DexFile::kDexNoIndex;
 }
 
-void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) const {
+void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) {
   if (kIsDebugBuild) {
     self->AssertThreadSuspensionIsAllowable();
     CHECK_EQ(kRunnable, self->GetState());
@@ -617,26 +647,35 @@
   // Pass everything as arguments.
   AbstractMethod::InvokeStub* stub = GetInvokeStub();
 
-  bool have_executable_code = (GetCode() != NULL);
 
-  if (Runtime::Current()->IsStarted() && have_executable_code && stub != NULL) {
-    bool log = false;
-    if (log) {
-      LOG(INFO) << StringPrintf("invoking %s code=%p stub=%p",
-                                PrettyMethod(this).c_str(), GetCode(), stub);
-    }
-    (*stub)(this, receiver, self, args, result);
-    if (log) {
-      LOG(INFO) << StringPrintf("returned %s code=%p stub=%p",
-                                PrettyMethod(this).c_str(), GetCode(), stub);
-    }
-  } else {
-    LOG(INFO) << StringPrintf("not invoking %s code=%p stub=%p started=%s",
-                              PrettyMethod(this).c_str(), GetCode(), stub,
-                              Runtime::Current()->IsStarted() ? "true" : "false");
+  if (UNLIKELY(!Runtime::Current()->IsStarted())){
+    LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started.";
     if (result != NULL) {
       result->SetJ(0);
     }
+  } else {
+    if (GetCode() != NULL && stub != NULL) {
+      bool log = false;
+      if (log) {
+        LOG(INFO) << StringPrintf("invoking %s code=%p stub=%p",
+                                  PrettyMethod(this).c_str(), GetCode(), stub);
+      }
+      (*stub)(this, receiver, self, args, result);
+      if (log) {
+        LOG(INFO) << StringPrintf("returned %s code=%p stub=%p",
+                                  PrettyMethod(this).c_str(), GetCode(), stub);
+      }
+    } else {
+      LOG(INFO) << "Not invoking " << PrettyMethod(this)
+          << " code=" << reinterpret_cast<const void*>(GetCode())
+          << " stub=" << reinterpret_cast<void*>(stub);
+      const bool kInterpretMethodsWithNoCode = false;
+      if (kInterpretMethodsWithNoCode) {
+        art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args, result);
+      } else if (result != NULL) {
+          result->SetJ(0);
+      }
+    }
   }
 
   // Pop transition.