blob: 19c42ac9b83ea580e2478536a75098604bd491d9 [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)
45 : shorty_(shorty), shorty_len_(shorty_len) {
46 if (shorty_len - 1 < kSmallArgArraySize) {
47 arg_array_ = small_arg_array_;
48 } else {
49 large_arg_array_.reset(new JValue[shorty_len_ - 1]);
50 arg_array_ = large_arg_array_.get();
51 }
52 }
53
54 JValue* get() {
55 return arg_array_;
56 }
57
58 void BuildArgArray(const ScopedObjectAccess& soa, va_list ap)
59 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
60 for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
61 switch (shorty_[i]) {
62 case 'Z':
63 arg_array_[offset].SetZ(va_arg(ap, jint));
64 break;
65 case 'B':
66 arg_array_[offset].SetB(va_arg(ap, jint));
67 break;
68 case 'C':
69 arg_array_[offset].SetC(va_arg(ap, jint));
70 break;
71 case 'S':
72 arg_array_[offset].SetS(va_arg(ap, jint));
73 break;
74 case 'I':
75 arg_array_[offset].SetI(va_arg(ap, jint));
76 break;
77 case 'F':
78 arg_array_[offset].SetF(va_arg(ap, jdouble));
79 break;
80 case 'L':
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080081 arg_array_[offset].SetL(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070082 break;
83 case 'D':
84 arg_array_[offset].SetD(va_arg(ap, jdouble));
85 break;
86 case 'J':
87 arg_array_[offset].SetJ(va_arg(ap, jlong));
88 break;
89 }
90 }
91 }
92
93 void BuildArgArray(const ScopedObjectAccess& soa, jvalue* args)
94 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
95 for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
96 switch (shorty_[i]) {
97 case 'Z':
98 arg_array_[offset].SetZ(args[offset].z);
99 break;
100 case 'B':
101 arg_array_[offset].SetB(args[offset].b);
102 break;
103 case 'C':
104 arg_array_[offset].SetC(args[offset].c);
105 break;
106 case 'S':
107 arg_array_[offset].SetS(args[offset].s);
108 break;
109 case 'I':
110 arg_array_[offset].SetI(args[offset].i);
111 break;
112 case 'F':
113 arg_array_[offset].SetF(args[offset].f);
114 break;
115 case 'L':
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800116 arg_array_[offset].SetL(soa.Decode<mirror::Object*>(args[offset].l));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700117 break;
118 case 'D':
119 arg_array_[offset].SetD(args[offset].d);
120 break;
121 case 'J':
122 arg_array_[offset].SetJ(args[offset].j);
123 break;
124 }
125 }
126 }
127
128 void BuildArgArray(const ShadowFrame& shadow_frame, uint32_t range_start)
129 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers64b6d142012-10-29 16:34:15 -0700130 for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700131 switch (shorty_[i]) {
132 case 'Z':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800133 arg_array_[i - 1].SetZ(shadow_frame.GetVReg(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700134 break;
135 case 'B':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800136 arg_array_[i - 1].SetB(shadow_frame.GetVReg(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700137 break;
138 case 'C':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800139 arg_array_[i - 1].SetC(shadow_frame.GetVReg(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700140 break;
141 case 'S':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800142 arg_array_[i - 1].SetS(shadow_frame.GetVReg(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700143 break;
144 case 'I':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800145 arg_array_[i - 1].SetI(shadow_frame.GetVReg(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700146 break;
147 case 'F':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800148 arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700149 break;
150 case 'L':
TDYa127ce4cc0d2012-11-18 16:59:53 -0800151 arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700152 break;
153 case 'D':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800154 arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700155 offset++;
156 break;
157 case 'J':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800158 arg_array_[i - 1].SetJ(shadow_frame.GetVRegLong(range_start + offset));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700159 offset++;
160 break;
161 }
162 }
163 }
164
165 void BuildArgArray(const ShadowFrame& shadow_frame, const uint32_t* arg_regs)
166 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
167 for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
168 switch (shorty_[i]) {
169 case 'Z':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800170 arg_array_[i - 1].SetZ(shadow_frame.GetVReg(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700171 break;
172 case 'B':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800173 arg_array_[i - 1].SetB(shadow_frame.GetVReg(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700174 break;
175 case 'C':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800176 arg_array_[i - 1].SetC(shadow_frame.GetVReg(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700177 break;
178 case 'S':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800179 arg_array_[i - 1].SetS(shadow_frame.GetVReg(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700180 break;
181 case 'I':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800182 arg_array_[i - 1].SetI(shadow_frame.GetVReg(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700183 break;
184 case 'F':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800185 arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700186 break;
187 case 'L':
TDYa127ce4cc0d2012-11-18 16:59:53 -0800188 arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700189 break;
190 case 'D':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800191 arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700192 offset++;
193 break;
194 case 'J':
Ian Rogersf1d39fd2012-11-20 16:10:25 -0800195 arg_array_[i - 1].SetJ(shadow_frame.GetVRegLong(arg_regs[offset]));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700196 offset++;
197 break;
198 }
199 }
200 }
201
202 private:
203 enum { kSmallArgArraySize = 16 };
204 const char* const shorty_;
205 const uint32_t shorty_len_;
206 JValue* arg_array_;
207 JValue small_arg_array_[kSmallArgArraySize];
208 UniquePtr<JValue[]> large_arg_array_;
209};
210
211} // namespace art
212
213#endif // ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_