blob: b1af6d596fb3672facc7aa4b64afebad0ac8290e [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)
Jeff Hao5d917302013-02-27 17:57:33 -080078 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -070079 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -080080 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -070081 for (size_t i = 1; i < shorty_len_; ++i) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070082 switch (shorty_[i]) {
83 case 'Z':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070084 case 'B':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070085 case 'C':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070086 case 'S':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070087 case 'I':
Jeff Haoaabe8ad2013-03-18 12:28:09 -070088 Append(va_arg(ap, jint));
Jeff Hao5d917302013-02-27 17:57:33 -080089 break;
90 case 'F': {
91 JValue value;
92 value.SetF(va_arg(ap, jdouble));
Jeff Haoaabe8ad2013-03-18 12:28:09 -070093 Append(value.GetI());
Jeff Hao5d917302013-02-27 17:57:33 -080094 break;
95 }
96 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -070097 Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject))));
Jeff Hao5d917302013-02-27 17:57:33 -080098 break;
99 case 'D': {
100 JValue value;
101 value.SetD(va_arg(ap, jdouble));
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700102 AppendWide(value.GetJ());
Jeff Hao5d917302013-02-27 17:57:33 -0800103 break;
104 }
105 case 'J': {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700106 AppendWide(va_arg(ap, jlong));
Jeff Hao5d917302013-02-27 17:57:33 -0800107 break;
108 }
109 }
110 }
Jeff Hao5d917302013-02-27 17:57:33 -0800111 }
112
113 void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
114 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
115 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800116 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700117 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800118 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700119 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800120 switch (shorty_[i]) {
121 case 'Z':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700122 Append(args[args_offset].z);
Jeff Hao5d917302013-02-27 17:57:33 -0800123 break;
124 case 'B':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700125 Append(args[args_offset].b);
Jeff Hao5d917302013-02-27 17:57:33 -0800126 break;
127 case 'C':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700128 Append(args[args_offset].c);
Jeff Hao5d917302013-02-27 17:57:33 -0800129 break;
130 case 'S':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700131 Append(args[args_offset].s);
Jeff Hao5d917302013-02-27 17:57:33 -0800132 break;
133 case 'I':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700134 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700135 Append(args[args_offset].i);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700136 break;
137 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700138 Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l)));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700139 break;
140 case 'D':
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700141 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700142 AppendWide(args[args_offset].j);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700143 break;
144 }
145 }
Jeff Hao5d917302013-02-27 17:57:33 -0800146 }
147
148 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, uint32_t range_start)
149 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
150 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800151 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700152 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800153 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700154 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800155 switch (shorty_[i]) {
156 case 'Z':
Jeff Hao5d917302013-02-27 17:57:33 -0800157 case 'B':
Jeff Hao5d917302013-02-27 17:57:33 -0800158 case 'C':
Jeff Hao5d917302013-02-27 17:57:33 -0800159 case 'S':
Jeff Hao5d917302013-02-27 17:57:33 -0800160 case 'I':
Jeff Hao5d917302013-02-27 17:57:33 -0800161 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700162 Append(shadow_frame.GetVReg(range_start + reg_offset));
Jeff Hao5d917302013-02-27 17:57:33 -0800163 break;
164 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700165 Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(range_start + reg_offset)));
Jeff Hao5d917302013-02-27 17:57:33 -0800166 break;
167 case 'D':
Jeff Hao5d917302013-02-27 17:57:33 -0800168 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700169 AppendWide(shadow_frame.GetVRegLong(range_start + reg_offset));
Jeff Hao5d917302013-02-27 17:57:33 -0800170 reg_offset++;
Jeff Hao5d917302013-02-27 17:57:33 -0800171 break;
172 }
173 }
Jeff Hao5d917302013-02-27 17:57:33 -0800174 }
175
176 void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, const uint32_t* arg_regs)
177 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
178 // Set receiver if non-null (method is not static)
Jeff Hao5d917302013-02-27 17:57:33 -0800179 if (receiver != NULL) {
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700180 Append(reinterpret_cast<int32_t>(receiver));
Jeff Hao5d917302013-02-27 17:57:33 -0800181 }
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700182 for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) {
Jeff Hao5d917302013-02-27 17:57:33 -0800183 switch (shorty_[i]) {
184 case 'Z':
Jeff Hao5d917302013-02-27 17:57:33 -0800185 case 'B':
Jeff Hao5d917302013-02-27 17:57:33 -0800186 case 'C':
Jeff Hao5d917302013-02-27 17:57:33 -0800187 case 'S':
Jeff Hao5d917302013-02-27 17:57:33 -0800188 case 'I':
Jeff Hao5d917302013-02-27 17:57:33 -0800189 case 'F':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700190 Append(shadow_frame.GetVReg(arg_regs[reg_offset]));
Jeff Hao5d917302013-02-27 17:57:33 -0800191 break;
192 case 'L':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700193 Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(arg_regs[reg_offset])));
Jeff Hao5d917302013-02-27 17:57:33 -0800194 break;
195 case 'D':
Jeff Hao5d917302013-02-27 17:57:33 -0800196 case 'J':
Jeff Haoaabe8ad2013-03-18 12:28:09 -0700197 AppendWide(shadow_frame.GetVRegLong(arg_regs[reg_offset]));
Jeff Hao5d917302013-02-27 17:57:33 -0800198 reg_offset++;
199 break;
200 }
201 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700202 }
203
204 private:
205 enum { kSmallArgArraySize = 16 };
206 const char* const shorty_;
207 const uint32_t shorty_len_;
Jeff Hao5d917302013-02-27 17:57:33 -0800208 uint32_t num_bytes_;
209 uint32_t* arg_array_;
210 uint32_t small_arg_array_[kSmallArgArraySize];
211 UniquePtr<uint32_t[]> large_arg_array_;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700212};
213
214} // namespace art
215
216#endif // ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_