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