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/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h
index 19c42ac..ecd0fb0 100644
--- a/src/invoke_arg_array_builder.h
+++ b/src/invoke_arg_array_builder.h
@@ -42,170 +42,240 @@
 class ArgArray {
  public:
   explicit ArgArray(const char* shorty, uint32_t shorty_len)
-      : shorty_(shorty), shorty_len_(shorty_len) {
-    if (shorty_len - 1 < kSmallArgArraySize) {
+      : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) {
+    // TODO: This code is conservative. The multiply by 2 is to handle the case where all args are
+    // doubles or longs. We could scan the shorty to use the arg array more often.
+    if (shorty_len * 2 <= kSmallArgArraySize) {
       arg_array_ = small_arg_array_;
     } else {
-      large_arg_array_.reset(new JValue[shorty_len_ - 1]);
+      large_arg_array_.reset(new uint32_t[shorty_len_ * 2]);
       arg_array_ = large_arg_array_.get();
     }
   }
 
-  JValue* get() {
+  uint32_t* GetArray() {
     return arg_array_;
   }
 
-  void BuildArgArray(const ScopedObjectAccess& soa, va_list ap)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
-      switch (shorty_[i]) {
-        case 'Z':
-          arg_array_[offset].SetZ(va_arg(ap, jint));
-          break;
-        case 'B':
-          arg_array_[offset].SetB(va_arg(ap, jint));
-          break;
-        case 'C':
-          arg_array_[offset].SetC(va_arg(ap, jint));
-          break;
-        case 'S':
-          arg_array_[offset].SetS(va_arg(ap, jint));
-          break;
-        case 'I':
-          arg_array_[offset].SetI(va_arg(ap, jint));
-          break;
-        case 'F':
-          arg_array_[offset].SetF(va_arg(ap, jdouble));
-          break;
-        case 'L':
-          arg_array_[offset].SetL(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
-          break;
-        case 'D':
-          arg_array_[offset].SetD(va_arg(ap, jdouble));
-          break;
-        case 'J':
-          arg_array_[offset].SetJ(va_arg(ap, jlong));
-          break;
-      }
-    }
+  uint32_t GetNumBytes() {
+    return num_bytes_;
   }
 
-  void BuildArgArray(const ScopedObjectAccess& soa, jvalue* args)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
-      switch (shorty_[i]) {
-        case 'Z':
-          arg_array_[offset].SetZ(args[offset].z);
-          break;
-        case 'B':
-          arg_array_[offset].SetB(args[offset].b);
-          break;
-        case 'C':
-          arg_array_[offset].SetC(args[offset].c);
-          break;
-        case 'S':
-          arg_array_[offset].SetS(args[offset].s);
-          break;
-        case 'I':
-          arg_array_[offset].SetI(args[offset].i);
-          break;
-        case 'F':
-          arg_array_[offset].SetF(args[offset].f);
-          break;
-        case 'L':
-          arg_array_[offset].SetL(soa.Decode<mirror::Object*>(args[offset].l));
-          break;
-        case 'D':
-          arg_array_[offset].SetD(args[offset].d);
-          break;
-        case 'J':
-          arg_array_[offset].SetJ(args[offset].j);
-          break;
-      }
-    }
+  void Append(uint32_t value) {
+    arg_array_[num_bytes_ / 4] = value;
+    num_bytes_ += 4;
   }
 
-  void BuildArgArray(const ShadowFrame& shadow_frame, uint32_t range_start)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
-      switch (shorty_[i]) {
-        case 'Z':
-          arg_array_[i - 1].SetZ(shadow_frame.GetVReg(range_start + offset));
-          break;
-        case 'B':
-          arg_array_[i - 1].SetB(shadow_frame.GetVReg(range_start + offset));
-          break;
-        case 'C':
-          arg_array_[i - 1].SetC(shadow_frame.GetVReg(range_start + offset));
-          break;
-        case 'S':
-          arg_array_[i - 1].SetS(shadow_frame.GetVReg(range_start + offset));
-          break;
-        case 'I':
-          arg_array_[i - 1].SetI(shadow_frame.GetVReg(range_start + offset));
-          break;
-        case 'F':
-          arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(range_start + offset));
-          break;
-        case 'L':
-          arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(range_start + offset));
-          break;
-        case 'D':
-          arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(range_start + offset));
-          offset++;
-          break;
-        case 'J':
-          arg_array_[i - 1].SetJ(shadow_frame.GetVRegLong(range_start + offset));
-          offset++;
-          break;
-      }
-    }
+  void AppendWide(uint64_t value) {
+    arg_array_[num_bytes_ / 4] = value;
+    arg_array_[(num_bytes_ / 4) + 1] = value >> 32;
+    num_bytes_ += 8;
   }
 
-  void BuildArgArray(const ShadowFrame& shadow_frame, const uint32_t* arg_regs)
+  void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, va_list ap)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
+    // Set receiver if non-null (method is not static)
+    size_t offset = 0;
+    if (receiver != NULL) {
+      arg_array_[0] = reinterpret_cast<int32_t>(receiver);
+      offset++;
+    }
+    for (size_t i = 1; i < shorty_len_; ++i, ++offset) {
       switch (shorty_[i]) {
         case 'Z':
-          arg_array_[i - 1].SetZ(shadow_frame.GetVReg(arg_regs[offset]));
+          arg_array_[offset] = va_arg(ap, jint);
           break;
         case 'B':
-          arg_array_[i - 1].SetB(shadow_frame.GetVReg(arg_regs[offset]));
+          arg_array_[offset] = va_arg(ap, jint);
           break;
         case 'C':
-          arg_array_[i - 1].SetC(shadow_frame.GetVReg(arg_regs[offset]));
+          arg_array_[offset] = va_arg(ap, jint);
           break;
         case 'S':
-          arg_array_[i - 1].SetS(shadow_frame.GetVReg(arg_regs[offset]));
+          arg_array_[offset] = va_arg(ap, jint);
           break;
         case 'I':
-          arg_array_[i - 1].SetI(shadow_frame.GetVReg(arg_regs[offset]));
+          arg_array_[offset] = va_arg(ap, jint);
+          break;
+        case 'F': {
+          JValue value;
+          value.SetF(va_arg(ap, jdouble));
+          arg_array_[offset] = value.GetI();
+          break;
+        }
+        case 'L':
+          arg_array_[offset] = reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
+          break;
+        case 'D': {
+          JValue value;
+          value.SetD(va_arg(ap, jdouble));
+          arg_array_[offset] = value.GetJ();
+          arg_array_[offset + 1] = value.GetJ() >> 32;
+          offset++;
+          break;
+        }
+        case 'J': {
+          long long l = va_arg(ap, jlong);
+          arg_array_[offset] = l;
+          arg_array_[offset + 1] = l >> 32;
+          offset++;
+          break;
+        }
+      }
+    }
+    num_bytes_ += 4 * offset;
+  }
+
+  void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Set receiver if non-null (method is not static)
+    size_t offset = 0;
+    if (receiver != NULL) {
+      arg_array_[0] = reinterpret_cast<int32_t>(receiver);
+      offset++;
+    }
+    for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++offset, ++args_offset) {
+      switch (shorty_[i]) {
+        case 'Z':
+          arg_array_[offset] = args[args_offset].z;
+          break;
+        case 'B':
+          arg_array_[offset] = args[args_offset].b;
+          break;
+        case 'C':
+          arg_array_[offset] = args[args_offset].c;
+          break;
+        case 'S':
+          arg_array_[offset] = args[args_offset].s;
+          break;
+        case 'I':
+          arg_array_[offset] = args[args_offset].i;
           break;
         case 'F':
-          arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
+          arg_array_[offset] = args[args_offset].i;
           break;
         case 'L':
-          arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(arg_regs[offset]));
+          arg_array_[offset] = reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l));
           break;
         case 'D':
-          arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
+          arg_array_[offset] = args[args_offset].j;
+          arg_array_[offset + 1] = args[args_offset].j >> 32;
           offset++;
           break;
         case 'J':
-          arg_array_[i - 1].SetJ(shadow_frame.GetVRegLong(arg_regs[offset]));
+          arg_array_[offset] = args[args_offset].j;
+          arg_array_[offset + 1] = args[args_offset].j >> 32;
           offset++;
           break;
       }
     }
+    num_bytes_ += 4 * offset;
+  }
+
+  void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, uint32_t range_start)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Set receiver if non-null (method is not static)
+    size_t offset = 0;
+    if (receiver != NULL) {
+      arg_array_[0] = reinterpret_cast<int32_t>(receiver);
+      offset++;
+    }
+    for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++offset, ++reg_offset) {
+      switch (shorty_[i]) {
+        case 'Z':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'B':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'C':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'S':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'I':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'F':
+          arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
+          break;
+        case 'L':
+          arg_array_[offset] = reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(range_start + reg_offset));
+          break;
+        case 'D':
+          arg_array_[offset] = shadow_frame.GetVRegLong(range_start + reg_offset);
+          arg_array_[offset + 1] = shadow_frame.GetVRegLong(range_start + reg_offset) >> 32;
+          reg_offset++;
+          offset++;
+          break;
+        case 'J':
+          arg_array_[offset] = shadow_frame.GetVRegLong(range_start + reg_offset);
+          arg_array_[offset + 1] = shadow_frame.GetVRegLong(range_start + reg_offset) >> 32;
+          reg_offset++;
+          offset++;
+          break;
+      }
+    }
+    num_bytes_ += 4 * offset;
+  }
+
+  void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, const uint32_t* arg_regs)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Set receiver if non-null (method is not static)
+    size_t offset = 0;
+    if (receiver != NULL) {
+      arg_array_[0] = reinterpret_cast<int32_t>(receiver);
+      offset++;
+    }
+    for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++offset, ++reg_offset) {
+      switch (shorty_[i]) {
+        case 'Z':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'B':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'C':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'S':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'I':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'F':
+          arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
+          break;
+        case 'L':
+          arg_array_[offset] = reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(arg_regs[reg_offset]));
+          break;
+        case 'D':
+          arg_array_[offset] = shadow_frame.GetVRegLong(arg_regs[reg_offset]);
+          arg_array_[offset + 1] = shadow_frame.GetVRegLong(arg_regs[reg_offset]) >> 32;
+          offset++;
+          reg_offset++;
+          break;
+        case 'J':
+          arg_array_[offset] = shadow_frame.GetVRegLong(arg_regs[reg_offset]);
+          arg_array_[offset + 1] = shadow_frame.GetVRegLong(arg_regs[reg_offset]) >> 32;
+          offset++;
+          reg_offset++;
+          break;
+      }
+    }
+    num_bytes_ += 4 * offset;
   }
 
  private:
   enum { kSmallArgArraySize = 16 };
   const char* const shorty_;
   const uint32_t shorty_len_;
-  JValue* arg_array_;
-  JValue small_arg_array_[kSmallArgArraySize];
-  UniquePtr<JValue[]> large_arg_array_;
+  uint32_t num_bytes_;
+  uint32_t* arg_array_;
+  uint32_t small_arg_array_[kSmallArgArraySize];
+  UniquePtr<uint32_t[]> large_arg_array_;
 };
 
 }  // namespace art