Changes to remove need for compiled invoke stubs for quick.

ARM, x86, and MIPS implementation complete, though MIPS is untested.

The ArgArray is changed to be a uint32_t array instead of a JValue array.
Also, a separate result for float/double was needed for x86/MIPS. The invoke
stubs are currently still there, but only used for portable.

Change-Id: I0647f8d5d420cea61370e662e85bdc0c13b5e378
diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc
index 202fa2f..e185c9c 100644
--- a/src/mirror/abstract_method.cc
+++ b/src/mirror/abstract_method.cc
@@ -31,6 +31,9 @@
 namespace art {
 namespace mirror {
 
+extern "C" void art_quick_invoke_stub(AbstractMethod*, uint32_t*, uint32_t,
+                                      Thread*, JValue*, JValue*);
+
 // TODO: get global references for these
 Class* AbstractMethod::java_lang_reflect_Constructor_ = NULL;
 Class* AbstractMethod::java_lang_reflect_Method_ = NULL;
@@ -276,7 +279,8 @@
   return DexFile::kDexNoIndex;
 }
 
-void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) {
+void AbstractMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
+                            JValue* float_result) {
   if (kIsDebugBuild) {
     self->AssertThreadSuspensionIsAllowable();
     CHECK_EQ(kRunnable, self->GetState());
@@ -294,47 +298,83 @@
     LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started";
     if (result != NULL) {
       result->SetJ(0);
+      float_result->SetJ(0);
     }
   } else {
     bool interpret = self->ReadFlag(kEnterInterpreter) && !IsNative() && !IsProxyMethod();
     const bool kLogInvocationStartAndReturn = false;
-    if (!interpret && GetCode() != NULL && stub != NULL) {
-      if (kLogInvocationStartAndReturn) {
-        LOG(INFO) << StringPrintf("Invoking '%s' code=%p stub=%p",
-                                  PrettyMethod(this).c_str(), GetCode(), stub);
-      }
-      (*stub)(this, receiver, self, args, result);
-      if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException()) == -1)) {
-        // Unusual case where we were running LLVM generated code and an
-        // exception was thrown to force the activations to be removed from the
-        // stack. Continue execution in the interpreter.
-        JValue value;
-        self->ClearException();
-        ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(&value);
-        self->SetTopOfShadowStack(shadow_frame);
-        interpreter::EnterInterpreterFromLLVM(self, shadow_frame, result);
-      }
-      if (kLogInvocationStartAndReturn) {
-        LOG(INFO) << StringPrintf("Returned '%s' code=%p stub=%p",
-                                  PrettyMethod(this).c_str(), GetCode(), stub);
-      }
-    } else {
-      const bool kInterpretMethodsWithNoCode = false;
-      if (interpret || kInterpretMethodsWithNoCode) {
+    if (GetCode() != NULL) {
+      if (!interpret) {
+        if (kLogInvocationStartAndReturn) {
+          LOG(INFO) << StringPrintf("Invoking '%s' code=%p stub=%p",
+                                    PrettyMethod(this).c_str(), GetCode(), stub);
+        }
+        // TODO: Temporary to keep portable working while stubs are removed from quick.
+#ifdef ART_USE_PORTABLE_COMPILER
+        MethodHelper mh(this);
+        const char* shorty = mh.GetShorty();
+        uint32_t shorty_len = mh.GetShortyLength();
+        UniquePtr<JValue[]> jvalue_args(new JValue[shorty_len - 1]);
+        Object* receiver = NULL;
+        uint32_t* ptr = args;
+        if (!this->IsStatic()) {
+          receiver = reinterpret_cast<Object*>(*ptr);
+          ptr++;
+        }
+        for (uint32_t i = 1; i < shorty_len; i++) {
+          if ((shorty[i] == 'J') || (shorty[i] == 'D')) {
+            jvalue_args[i - 1].SetJ(*((uint64_t*)ptr));
+            ptr++;
+          } else {
+            jvalue_args[i - 1].SetI(*ptr);
+          }
+          ptr++;
+        }
+        if (mh.IsReturnFloatOrDouble()) {
+          (*stub)(this, receiver, self, jvalue_args.get(), float_result);
+        } else {
+          (*stub)(this, receiver, self, jvalue_args.get(), result);
+        }
+#else
+        (*art_quick_invoke_stub)(this, args, args_size, self, result, float_result);
+#endif
+        if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException()) == -1)) {
+          // Unusual case where we were running LLVM generated code and an
+          // exception was thrown to force the activations to be removed from the
+          // stack. Continue execution in the interpreter.
+          JValue value;
+          self->ClearException();
+          ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(&value);
+          self->SetTopOfShadowStack(shadow_frame);
+          interpreter::EnterInterpreterFromLLVM(self, shadow_frame, result);
+        }
+        if (kLogInvocationStartAndReturn) {
+          LOG(INFO) << StringPrintf("Returned '%s' code=%p stub=%p",
+                                    PrettyMethod(this).c_str(), GetCode(), stub);
+        }
+      } else {
         if (kLogInvocationStartAndReturn) {
           LOG(INFO) << "Interpreting " << PrettyMethod(this) << "'";
         }
-        art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args, result);
+        if (this->IsStatic()) {
+          art::interpreter::EnterInterpreterFromInvoke(self, this, NULL, args,
+                                                       result, float_result);
+        } else {
+          Object* receiver = reinterpret_cast<Object*>(args[0]);
+          art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args + 1,
+                                                       result, float_result);
+        }
         if (kLogInvocationStartAndReturn) {
           LOG(INFO) << "Returned '" << PrettyMethod(this) << "'";
         }
-      } else {
-        LOG(INFO) << "Not invoking '" << PrettyMethod(this)
-              << "' code=" << reinterpret_cast<const void*>(GetCode())
-              << " stub=" << reinterpret_cast<void*>(stub);
-        if (result != NULL) {
-          result->SetJ(0);
-        }
+      }
+    } else {
+      LOG(INFO) << "Not invoking '" << PrettyMethod(this)
+          << "' code=" << reinterpret_cast<const void*>(GetCode())
+          << " stub=" << reinterpret_cast<void*>(stub);
+      if (result != NULL) {
+        result->SetJ(0);
+        float_result->SetJ(0);
       }
     }
   }