blob: e251e33a2cdd50baddae670c394097e035a5992f [file] [log] [blame]
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_
18#define ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_
19
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/object.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070021#include "scoped_thread_state_change.h"
22
23namespace art {
24
25static inline size_t NumArgArrayBytes(const char* shorty, uint32_t shorty_len) {
26 size_t num_bytes = 0;
27 for (size_t i = 1; i < shorty_len; ++i) {
28 char ch = shorty[i];
29 if (ch == 'D' || ch == 'J') {
30 num_bytes += 8;
31 } else if (ch == 'L') {
32 // Argument is a reference or an array. The shorty descriptor
33 // does not distinguish between these types.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034 num_bytes += sizeof(mirror::Object*);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070035 } else {
36 num_bytes += 4;
37 }
38 }
39 return num_bytes;
40}
41
42class ArgArray {
43 public:
44 explicit ArgArray(const char* shorty, uint32_t shorty_len)
Jeff Hao5d917302013-02-27 17:57:33 -080045 : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) {
46 // TODO: This code is conservative. The multiply by 2 is to handle the case where all args are
47 // doubles or longs. We could scan the shorty to use the arg array more often.
48 if (shorty_len * 2 <= kSmallArgArraySize) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070049 arg_array_ = small_arg_array_;
50 } else {
Jeff Hao5d917302013-02-27 17:57:33 -080051 large_arg_array_.reset(new uint32_t[shorty_len_ * 2]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070052 arg_array_ = large_arg_array_.get();
53 }
54 }
55
Jeff Hao5d917302013-02-27 17:57:33 -080056 uint32_t* GetArray() {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070057 return arg_array_;
58 }
59
Jeff Hao5d917302013-02-27 17:57:33 -080060 uint32_t GetNumBytes() {
61 return num_bytes_;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070062 }
63
Jeff Hao5d917302013-02-27 17:57:33 -080064 void Append(uint32_t value) {
65 arg_array_[num_bytes_ / 4] = value;
66 num_bytes_ += 4;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070067 }
68
Jeff Hao5d917302013-02-27 17:57:33 -080069 void AppendWide(uint64_t value) {
Jeff Hao6474d192013-03-26 14:08:09 -070070 // For ARM and MIPS portable, align wide values to 8 bytes (ArgArray starts at offset of 4).
71#if defined(ART_USE_PORTABLE_COMPILER) && (TARGET_ARCH == arm || TARGET_ARCH == mips)
72 if (num_bytes_ % 8 == 0) {
73 num_bytes_ += 4;
74 }
75#endif
Jeff Hao5d917302013-02-27 17:57:33 -080076 arg_array_[num_bytes_ / 4] = value;
77 arg_array_[(num_bytes_ / 4) + 1] = value >> 32;
78 num_bytes_ += 8;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070079 }
80
Jeff Hao5d917302013-02-27 17:57:33 -080081 void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, va_list ap)
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070082 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Jeff Hao5d917302013-02-27 17:57:33 -080083 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -080084 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -070085 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -080086 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -070087 for (size_t i = 1; i < shorty_len_; ++i) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070088 switch (shorty_[i]) {
89 case 'Z':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070090 case 'B':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070091 case 'C':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070092 case 'S':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070093 case 'I':
Jeff Haoaabe8ad2013-03-18 12:28:09 -070094 Append(va_arg(ap, jint));
Jeff Hao5d917302013-02-27 17:57:33 -080095 break;
96 case 'F': {
97 JValue value;
98 value.SetF(va_arg(ap, jdouble));
Jeff Haoaabe8ad2013-03-18 12:28:09 -070099 Append(value.GetI());
Jeff Hao5d917302013-02-27 17:57:33 -0800100 break;
101 }
102 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700103 Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject))));
Jeff Hao5d917302013-02-27 17:57:33 -0800104 break;
105 case 'D': {
106 JValue value;
107 value.SetD(va_arg(ap, jdouble));
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700108 AppendWide(value.GetJ());
Jeff Hao5d917302013-02-27 17:57:33 -0800109 break;
110 }
111 case 'J': {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700112 AppendWide(va_arg(ap, jlong));
Jeff Hao5d917302013-02-27 17:57:33 -0800113 break;
114 }
115 }
116 }
Jeff Hao5d917302013-02-27 17:57:33 -0800117 }
118
119 void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
121 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800122 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700123 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800124 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700125 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800126 switch (shorty_[i]) {
127 case 'Z':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700128 Append(args[args_offset].z);
Jeff Hao5d917302013-02-27 17:57:33 -0800129 break;
130 case 'B':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700131 Append(args[args_offset].b);
Jeff Hao5d917302013-02-27 17:57:33 -0800132 break;
133 case 'C':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700134 Append(args[args_offset].c);
Jeff Hao5d917302013-02-27 17:57:33 -0800135 break;
136 case 'S':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700137 Append(args[args_offset].s);
Jeff Hao5d917302013-02-27 17:57:33 -0800138 break;
139 case 'I':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700140 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700141 Append(args[args_offset].i);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700142 break;
143 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700144 Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l)));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700145 break;
146 case 'D':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700147 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700148 AppendWide(args[args_offset].j);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700149 break;
150 }
151 }
Jeff Hao5d917302013-02-27 17:57:33 -0800152 }
153
154 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, uint32_t range_start)
155 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
156 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800157 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700158 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800159 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700160 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800161 switch (shorty_[i]) {
162 case 'Z':
Jeff Hao5d917302013-02-27 17:57:33 -0800163 case 'B':
Jeff Hao5d917302013-02-27 17:57:33 -0800164 case 'C':
Jeff Hao5d917302013-02-27 17:57:33 -0800165 case 'S':
Jeff Hao5d917302013-02-27 17:57:33 -0800166 case 'I':
Jeff Hao5d917302013-02-27 17:57:33 -0800167 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700168 Append(shadow_frame.GetVReg(range_start + reg_offset));
Jeff Hao5d917302013-02-27 17:57:33 -0800169 break;
170 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700171 Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(range_start + reg_offset)));
Jeff Hao5d917302013-02-27 17:57:33 -0800172 break;
173 case 'D':
Jeff Hao5d917302013-02-27 17:57:33 -0800174 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700175 AppendWide(shadow_frame.GetVRegLong(range_start + reg_offset));
Jeff Hao5d917302013-02-27 17:57:33 -0800176 reg_offset++;
Jeff Hao5d917302013-02-27 17:57:33 -0800177 break;
178 }
179 }
Jeff Hao5d917302013-02-27 17:57:33 -0800180 }
181
182 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, const uint32_t* arg_regs)
183 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
184 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800185 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700186 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800187 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700188 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800189 switch (shorty_[i]) {
190 case 'Z':
Jeff Hao5d917302013-02-27 17:57:33 -0800191 case 'B':
Jeff Hao5d917302013-02-27 17:57:33 -0800192 case 'C':
Jeff Hao5d917302013-02-27 17:57:33 -0800193 case 'S':
Jeff Hao5d917302013-02-27 17:57:33 -0800194 case 'I':
Jeff Hao5d917302013-02-27 17:57:33 -0800195 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700196 Append(shadow_frame.GetVReg(arg_regs[reg_offset]));
Jeff Hao5d917302013-02-27 17:57:33 -0800197 break;
198 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700199 Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(arg_regs[reg_offset])));
Jeff Hao5d917302013-02-27 17:57:33 -0800200 break;
201 case 'D':
Jeff Hao5d917302013-02-27 17:57:33 -0800202 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700203 AppendWide(shadow_frame.GetVRegLong(arg_regs[reg_offset]));
Jeff Hao5d917302013-02-27 17:57:33 -0800204 reg_offset++;
205 break;
206 }
207 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700208 }
209
210 private:
211 enum { kSmallArgArraySize = 16 };
212 const char* const shorty_;
213 const uint32_t shorty_len_;
Jeff Hao5d917302013-02-27 17:57:33 -0800214 uint32_t num_bytes_;
215 uint32_t* arg_array_;
216 uint32_t small_arg_array_[kSmallArgArraySize];
217 UniquePtr<uint32_t[]> large_arg_array_;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700218};
219
220} // namespace art
221
222#endif // ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_