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/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h
new file mode 100644
index 0000000..e965a1a
--- /dev/null
+++ b/src/invoke_arg_array_builder.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_
+#define ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_
+
+#include "object.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+
+static inline size_t NumArgArrayBytes(const char* shorty, uint32_t shorty_len) {
+ size_t num_bytes = 0;
+ for (size_t i = 1; i < shorty_len; ++i) {
+ char ch = shorty[i];
+ if (ch == 'D' || ch == 'J') {
+ num_bytes += 8;
+ } else if (ch == 'L') {
+ // Argument is a reference or an array. The shorty descriptor
+ // does not distinguish between these types.
+ num_bytes += sizeof(Object*);
+ } else {
+ num_bytes += 4;
+ }
+ }
+ return num_bytes;
+}
+
+class ArgArray {
+ public:
+ explicit ArgArray(const char* shorty, uint32_t shorty_len)
+ : shorty_(shorty), shorty_len_(shorty_len) {
+ if (shorty_len - 1 < kSmallArgArraySize) {
+ arg_array_ = small_arg_array_;
+ } else {
+ large_arg_array_.reset(new JValue[shorty_len_ - 1]);
+ arg_array_ = large_arg_array_.get();
+ }
+ }
+
+ JValue* get() {
+ 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<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;
+ }
+ }
+ }
+
+ 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<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 BuildArgArray(const ShadowFrame& shadow_frame, uint32_t range_start)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ for (size_t i = 1, offset = range_start; i < shorty_len_; ++i, ++offset) {
+ switch (shorty_[i]) {
+ case 'Z':
+ arg_array_[offset].SetZ(shadow_frame.GetVReg(offset));
+ break;
+ case 'B':
+ arg_array_[offset].SetB(shadow_frame.GetVReg(offset));
+ break;
+ case 'C':
+ arg_array_[offset].SetC(shadow_frame.GetVReg(offset));
+ break;
+ case 'S':
+ arg_array_[offset].SetS(shadow_frame.GetVReg(offset));
+ break;
+ case 'I':
+ arg_array_[offset].SetI(shadow_frame.GetVReg(offset));
+ break;
+ case 'F':
+ arg_array_[offset].SetF(shadow_frame.GetVRegFloat(offset));
+ break;
+ case 'L':
+ arg_array_[offset].SetL(shadow_frame.GetReference(offset));
+ break;
+ case 'D':
+ arg_array_[offset].SetD(shadow_frame.GetVRegDouble(offset));
+ offset++;
+ break;
+ case 'J':
+ arg_array_[offset].SetJ(shadow_frame.GetVRegLong(offset));
+ offset++;
+ break;
+ }
+ }
+ }
+
+ void BuildArgArray(const ShadowFrame& shadow_frame, const uint32_t* arg_regs)
+ 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(shadow_frame.GetVReg(arg_regs[offset]));
+ break;
+ case 'B':
+ arg_array_[offset].SetB(shadow_frame.GetVReg(arg_regs[offset]));
+ break;
+ case 'C':
+ arg_array_[offset].SetC(shadow_frame.GetVReg(arg_regs[offset]));
+ break;
+ case 'S':
+ arg_array_[offset].SetS(shadow_frame.GetVReg(arg_regs[offset]));
+ break;
+ case 'I':
+ arg_array_[offset].SetI(shadow_frame.GetVReg(arg_regs[offset]));
+ break;
+ case 'F':
+ arg_array_[offset].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
+ break;
+ case 'L':
+ arg_array_[offset].SetL(shadow_frame.GetReference(arg_regs[offset]));
+ break;
+ case 'D':
+ arg_array_[offset].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
+ offset++;
+ break;
+ case 'J':
+ arg_array_[offset].SetJ(shadow_frame.GetVRegLong(arg_regs[offset]));
+ offset++;
+ break;
+ }
+ }
+ }
+
+ 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_;
+};
+
+} // namespace art
+
+#endif // ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_