blob: ecd0fb07c3f99794e0e0e6ecfdec6eb1510f599d [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) {
70 arg_array_[num_bytes_ / 4] = value;
71 arg_array_[(num_bytes_ / 4) + 1] = value >> 32;
72 num_bytes_ += 8;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070073 }
74
Jeff Hao5d917302013-02-27 17:57:33 -080075 void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, va_list ap)
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070076 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Jeff Hao5d917302013-02-27 17:57:33 -080077 // Set receiver if non-null (method is not static)
78 size_t offset = 0;
79 if (receiver != NULL) {
80 arg_array_[0] = reinterpret_cast<int32_t>(receiver);
81 offset++;
82 }
83 for (size_t i = 1; i < shorty_len_; ++i, ++offset) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070084 switch (shorty_[i]) {
85 case 'Z':
Jeff Hao5d917302013-02-27 17:57:33 -080086 arg_array_[offset] = va_arg(ap, jint);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070087 break;
88 case 'B':
Jeff Hao5d917302013-02-27 17:57:33 -080089 arg_array_[offset] = va_arg(ap, jint);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070090 break;
91 case 'C':
Jeff Hao5d917302013-02-27 17:57:33 -080092 arg_array_[offset] = va_arg(ap, jint);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070093 break;
94 case 'S':
Jeff Hao5d917302013-02-27 17:57:33 -080095 arg_array_[offset] = va_arg(ap, jint);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070096 break;
97 case 'I':
Jeff Hao5d917302013-02-27 17:57:33 -080098 arg_array_[offset] = va_arg(ap, jint);
99 break;
100 case 'F': {
101 JValue value;
102 value.SetF(va_arg(ap, jdouble));
103 arg_array_[offset] = value.GetI();
104 break;
105 }
106 case 'L':
107 arg_array_[offset] = reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
108 break;
109 case 'D': {
110 JValue value;
111 value.SetD(va_arg(ap, jdouble));
112 arg_array_[offset] = value.GetJ();
113 arg_array_[offset + 1] = value.GetJ() >> 32;
114 offset++;
115 break;
116 }
117 case 'J': {
118 long long l = va_arg(ap, jlong);
119 arg_array_[offset] = l;
120 arg_array_[offset + 1] = l >> 32;
121 offset++;
122 break;
123 }
124 }
125 }
126 num_bytes_ += 4 * offset;
127 }
128
129 void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
130 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
131 // Set receiver if non-null (method is not static)
132 size_t offset = 0;
133 if (receiver != NULL) {
134 arg_array_[0] = reinterpret_cast<int32_t>(receiver);
135 offset++;
136 }
137 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++offset, ++args_offset) {
138 switch (shorty_[i]) {
139 case 'Z':
140 arg_array_[offset] = args[args_offset].z;
141 break;
142 case 'B':
143 arg_array_[offset] = args[args_offset].b;
144 break;
145 case 'C':
146 arg_array_[offset] = args[args_offset].c;
147 break;
148 case 'S':
149 arg_array_[offset] = args[args_offset].s;
150 break;
151 case 'I':
152 arg_array_[offset] = args[args_offset].i;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700153 break;
154 case 'F':
Jeff Hao5d917302013-02-27 17:57:33 -0800155 arg_array_[offset] = args[args_offset].i;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700156 break;
157 case 'L':
Jeff Hao5d917302013-02-27 17:57:33 -0800158 arg_array_[offset] = reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700159 break;
160 case 'D':
Jeff Hao5d917302013-02-27 17:57:33 -0800161 arg_array_[offset] = args[args_offset].j;
162 arg_array_[offset + 1] = args[args_offset].j >> 32;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700163 offset++;
164 break;
165 case 'J':
Jeff Hao5d917302013-02-27 17:57:33 -0800166 arg_array_[offset] = args[args_offset].j;
167 arg_array_[offset + 1] = args[args_offset].j >> 32;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700168 offset++;
169 break;
170 }
171 }
Jeff Hao5d917302013-02-27 17:57:33 -0800172 num_bytes_ += 4 * offset;
173 }
174
175 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, uint32_t range_start)
176 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
177 // Set receiver if non-null (method is not static)
178 size_t offset = 0;
179 if (receiver != NULL) {
180 arg_array_[0] = reinterpret_cast<int32_t>(receiver);
181 offset++;
182 }
183 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++offset, ++reg_offset) {
184 switch (shorty_[i]) {
185 case 'Z':
186 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
187 break;
188 case 'B':
189 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
190 break;
191 case 'C':
192 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
193 break;
194 case 'S':
195 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
196 break;
197 case 'I':
198 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
199 break;
200 case 'F':
201 arg_array_[offset] = shadow_frame.GetVReg(range_start + reg_offset);
202 break;
203 case 'L':
204 arg_array_[offset] = reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(range_start + reg_offset));
205 break;
206 case 'D':
207 arg_array_[offset] = shadow_frame.GetVRegLong(range_start + reg_offset);
208 arg_array_[offset + 1] = shadow_frame.GetVRegLong(range_start + reg_offset) >> 32;
209 reg_offset++;
210 offset++;
211 break;
212 case 'J':
213 arg_array_[offset] = shadow_frame.GetVRegLong(range_start + reg_offset);
214 arg_array_[offset + 1] = shadow_frame.GetVRegLong(range_start + reg_offset) >> 32;
215 reg_offset++;
216 offset++;
217 break;
218 }
219 }
220 num_bytes_ += 4 * offset;
221 }
222
223 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, const uint32_t* arg_regs)
224 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
225 // Set receiver if non-null (method is not static)
226 size_t offset = 0;
227 if (receiver != NULL) {
228 arg_array_[0] = reinterpret_cast<int32_t>(receiver);
229 offset++;
230 }
231 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++offset, ++reg_offset) {
232 switch (shorty_[i]) {
233 case 'Z':
234 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
235 break;
236 case 'B':
237 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
238 break;
239 case 'C':
240 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
241 break;
242 case 'S':
243 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
244 break;
245 case 'I':
246 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
247 break;
248 case 'F':
249 arg_array_[offset] = shadow_frame.GetVReg(arg_regs[reg_offset]);
250 break;
251 case 'L':
252 arg_array_[offset] = reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(arg_regs[reg_offset]));
253 break;
254 case 'D':
255 arg_array_[offset] = shadow_frame.GetVRegLong(arg_regs[reg_offset]);
256 arg_array_[offset + 1] = shadow_frame.GetVRegLong(arg_regs[reg_offset]) >> 32;
257 offset++;
258 reg_offset++;
259 break;
260 case 'J':
261 arg_array_[offset] = shadow_frame.GetVRegLong(arg_regs[reg_offset]);
262 arg_array_[offset + 1] = shadow_frame.GetVRegLong(arg_regs[reg_offset]) >> 32;
263 offset++;
264 reg_offset++;
265 break;
266 }
267 }
268 num_bytes_ += 4 * offset;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700269 }
270
271 private:
272 enum { kSmallArgArraySize = 16 };
273 const char* const shorty_;
274 const uint32_t shorty_len_;
Jeff Hao5d917302013-02-27 17:57:33 -0800275 uint32_t num_bytes_;
276 uint32_t* arg_array_;
277 uint32_t small_arg_array_[kSmallArgArraySize];
278 UniquePtr<uint32_t[]> large_arg_array_;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700279};
280
281} // namespace art
282
283#endif // ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_