blob: e965a1ad182073cdb4088905ac3d180cfaacf153 [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
20#include "object.h"
21#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.
34 num_bytes += sizeof(Object*);
35 } 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':
81 arg_array_[offset].SetL(soa.Decode<Object*>(va_arg(ap, jobject)));
82 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':
116 arg_array_[offset].SetL(soa.Decode<Object*>(args[offset].l));
117 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_) {
130 for (size_t i = 1, offset = range_start; i < shorty_len_; ++i, ++offset) {
131 switch (shorty_[i]) {
132 case 'Z':
133 arg_array_[offset].SetZ(shadow_frame.GetVReg(offset));
134 break;
135 case 'B':
136 arg_array_[offset].SetB(shadow_frame.GetVReg(offset));
137 break;
138 case 'C':
139 arg_array_[offset].SetC(shadow_frame.GetVReg(offset));
140 break;
141 case 'S':
142 arg_array_[offset].SetS(shadow_frame.GetVReg(offset));
143 break;
144 case 'I':
145 arg_array_[offset].SetI(shadow_frame.GetVReg(offset));
146 break;
147 case 'F':
148 arg_array_[offset].SetF(shadow_frame.GetVRegFloat(offset));
149 break;
150 case 'L':
151 arg_array_[offset].SetL(shadow_frame.GetReference(offset));
152 break;
153 case 'D':
154 arg_array_[offset].SetD(shadow_frame.GetVRegDouble(offset));
155 offset++;
156 break;
157 case 'J':
158 arg_array_[offset].SetJ(shadow_frame.GetVRegLong(offset));
159 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':
170 arg_array_[offset].SetZ(shadow_frame.GetVReg(arg_regs[offset]));
171 break;
172 case 'B':
173 arg_array_[offset].SetB(shadow_frame.GetVReg(arg_regs[offset]));
174 break;
175 case 'C':
176 arg_array_[offset].SetC(shadow_frame.GetVReg(arg_regs[offset]));
177 break;
178 case 'S':
179 arg_array_[offset].SetS(shadow_frame.GetVReg(arg_regs[offset]));
180 break;
181 case 'I':
182 arg_array_[offset].SetI(shadow_frame.GetVReg(arg_regs[offset]));
183 break;
184 case 'F':
185 arg_array_[offset].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
186 break;
187 case 'L':
188 arg_array_[offset].SetL(shadow_frame.GetReference(arg_regs[offset]));
189 break;
190 case 'D':
191 arg_array_[offset].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
192 offset++;
193 break;
194 case 'J':
195 arg_array_[offset].SetJ(shadow_frame.GetVRegLong(arg_regs[offset]));
196 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_