1 /*
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 #include "callee_save_frame.h"
18 #include "dex_file-inl.h"
19 #include "entrypoints/entrypoint_utils-inl.h"
20 #include "mirror/art_field-inl.h"
21 #include "mirror/art_method-inl.h"
22 #include "mirror/class-inl.h"
23
24 #include <stdint.h>
25
26 namespace art {
27
artGet32StaticFromCode(uint32_t field_idx,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)28 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
29 mirror::ArtMethod* referrer,
30 Thread* self, StackReference<mirror::ArtMethod>* sp)
31 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
32 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
33 sizeof(int32_t));
34 if (LIKELY(field != NULL)) {
35 return field->Get32(field->GetDeclaringClass());
36 }
37 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
38 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
39 if (LIKELY(field != NULL)) {
40 return field->Get32(field->GetDeclaringClass());
41 }
42 return 0; // Will throw exception by checking with Thread::Current
43 }
44
artGet64StaticFromCode(uint32_t field_idx,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)45 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
46 mirror::ArtMethod* referrer,
47 Thread* self, StackReference<mirror::ArtMethod>* sp)
48 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
50 sizeof(int64_t));
51 if (LIKELY(field != NULL)) {
52 return field->Get64(field->GetDeclaringClass());
53 }
54 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
55 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
56 if (LIKELY(field != NULL)) {
57 return field->Get64(field->GetDeclaringClass());
58 }
59 return 0; // Will throw exception by checking with Thread::Current
60 }
61
artGetObjStaticFromCode(uint32_t field_idx,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)62 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
63 mirror::ArtMethod* referrer,
64 Thread* self,
65 StackReference<mirror::ArtMethod>* sp)
66 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
67 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
68 sizeof(mirror::HeapReference<mirror::Object>));
69 if (LIKELY(field != NULL)) {
70 return field->GetObj(field->GetDeclaringClass());
71 }
72 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
73 field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
74 sizeof(mirror::HeapReference<mirror::Object>));
75 if (LIKELY(field != NULL)) {
76 return field->GetObj(field->GetDeclaringClass());
77 }
78 return NULL; // Will throw exception by checking with Thread::Current
79 }
80
artGet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)81 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
82 mirror::ArtMethod* referrer, Thread* self,
83 StackReference<mirror::ArtMethod>* sp)
84 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
85 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
86 sizeof(int32_t));
87 if (LIKELY(field != NULL && obj != NULL)) {
88 return field->Get32(obj);
89 }
90 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
91 field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
92 sizeof(int32_t));
93 if (LIKELY(field != NULL)) {
94 if (UNLIKELY(obj == NULL)) {
95 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
96 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
97 } else {
98 return field->Get32(obj);
99 }
100 }
101 return 0; // Will throw exception by checking with Thread::Current
102 }
103
artGet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)104 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
105 mirror::ArtMethod* referrer, Thread* self,
106 StackReference<mirror::ArtMethod>* sp)
107 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
108 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
109 sizeof(int64_t));
110 if (LIKELY(field != NULL && obj != NULL)) {
111 return field->Get64(obj);
112 }
113 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
114 field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
115 sizeof(int64_t));
116 if (LIKELY(field != NULL)) {
117 if (UNLIKELY(obj == NULL)) {
118 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
119 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
120 } else {
121 return field->Get64(obj);
122 }
123 }
124 return 0; // Will throw exception by checking with Thread::Current
125 }
126
artGetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)127 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
128 mirror::ArtMethod* referrer,
129 Thread* self,
130 StackReference<mirror::ArtMethod>* sp)
131 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
132 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
133 sizeof(mirror::HeapReference<mirror::Object>));
134 if (LIKELY(field != NULL && obj != NULL)) {
135 return field->GetObj(obj);
136 }
137 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
138 field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
139 sizeof(mirror::HeapReference<mirror::Object>));
140 if (LIKELY(field != NULL)) {
141 if (UNLIKELY(obj == NULL)) {
142 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
143 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
144 } else {
145 return field->GetObj(obj);
146 }
147 }
148 return NULL; // Will throw exception by checking with Thread::Current
149 }
150
artSet32StaticFromCode(uint32_t field_idx,uint32_t new_value,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)151 extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
152 mirror::ArtMethod* referrer, Thread* self,
153 StackReference<mirror::ArtMethod>* sp)
154 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
155 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
156 sizeof(int32_t));
157 if (LIKELY(field != NULL)) {
158 // Compiled code can't use transactional mode.
159 field->Set32<false>(field->GetDeclaringClass(), new_value);
160 return 0; // success
161 }
162 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
163 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
164 if (LIKELY(field != NULL)) {
165 // Compiled code can't use transactional mode.
166 field->Set32<false>(field->GetDeclaringClass(), new_value);
167 return 0; // success
168 }
169 return -1; // failure
170 }
171
artSet64StaticFromCode(uint32_t field_idx,mirror::ArtMethod * referrer,uint64_t new_value,Thread * self,StackReference<mirror::ArtMethod> * sp)172 extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
173 uint64_t new_value, Thread* self,
174 StackReference<mirror::ArtMethod>* sp)
175 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
176 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
177 sizeof(int64_t));
178 if (LIKELY(field != NULL)) {
179 // Compiled code can't use transactional mode.
180 field->Set64<false>(field->GetDeclaringClass(), new_value);
181 return 0; // success
182 }
183 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
184 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
185 if (LIKELY(field != NULL)) {
186 // Compiled code can't use transactional mode.
187 field->Set64<false>(field->GetDeclaringClass(), new_value);
188 return 0; // success
189 }
190 return -1; // failure
191 }
192
artSetObjStaticFromCode(uint32_t field_idx,mirror::Object * new_value,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)193 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
194 mirror::ArtMethod* referrer, Thread* self,
195 StackReference<mirror::ArtMethod>* sp)
196 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
197 mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
198 sizeof(mirror::HeapReference<mirror::Object>));
199 if (LIKELY(field != NULL)) {
200 if (LIKELY(!field->IsPrimitiveType())) {
201 // Compiled code can't use transactional mode.
202 field->SetObj<false>(field->GetDeclaringClass(), new_value);
203 return 0; // success
204 }
205 }
206 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
207 field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
208 sizeof(mirror::HeapReference<mirror::Object>));
209 if (LIKELY(field != NULL)) {
210 // Compiled code can't use transactional mode.
211 field->SetObj<false>(field->GetDeclaringClass(), new_value);
212 return 0; // success
213 }
214 return -1; // failure
215 }
216
artSet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint32_t new_value,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)217 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
218 mirror::ArtMethod* referrer, Thread* self,
219 StackReference<mirror::ArtMethod>* sp)
220 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
221 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
222 sizeof(int32_t));
223 if (LIKELY(field != NULL && obj != NULL)) {
224 // Compiled code can't use transactional mode.
225 field->Set32<false>(obj, new_value);
226 return 0; // success
227 }
228 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
229 {
230 StackHandleScope<1> hs(self);
231 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
232 field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
233 sizeof(int32_t));
234 }
235 if (LIKELY(field != NULL)) {
236 if (UNLIKELY(obj == NULL)) {
237 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
238 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
239 } else {
240 // Compiled code can't use transactional mode.
241 field->Set32<false>(obj, new_value);
242 return 0; // success
243 }
244 }
245 return -1; // failure
246 }
247
artSet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint64_t new_value,Thread * self,StackReference<mirror::ArtMethod> * sp)248 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint64_t new_value,
249 Thread* self, StackReference<mirror::ArtMethod>* sp)
250 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
251 constexpr size_t frame_size = GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kRefsOnly);
252 mirror::ArtMethod* referrer =
253 reinterpret_cast<StackReference<mirror::ArtMethod>*>(
254 reinterpret_cast<uint8_t*>(sp) + frame_size)->AsMirrorPtr();
255 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
256 sizeof(int64_t));
257 if (LIKELY(field != NULL && obj != NULL)) {
258 // Compiled code can't use transactional mode.
259 field->Set64<false>(obj, new_value);
260 return 0; // success
261 }
262 sp->Assign(Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly));
263 self->SetTopOfStack(sp, 0);
264 field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
265 sizeof(int64_t));
266 if (LIKELY(field != NULL)) {
267 if (UNLIKELY(obj == NULL)) {
268 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
269 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
270 } else {
271 // Compiled code can't use transactional mode.
272 field->Set64<false>(obj, new_value);
273 return 0; // success
274 }
275 }
276 return -1; // failure
277 }
278
artSetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::Object * new_value,mirror::ArtMethod * referrer,Thread * self,StackReference<mirror::ArtMethod> * sp)279 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
280 mirror::Object* new_value,
281 mirror::ArtMethod* referrer, Thread* self,
282 StackReference<mirror::ArtMethod>* sp)
283 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
284 mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
285 sizeof(mirror::HeapReference<mirror::Object>));
286 if (LIKELY(field != NULL && obj != NULL)) {
287 // Compiled code can't use transactional mode.
288 field->SetObj<false>(obj, new_value);
289 return 0; // success
290 }
291 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
292 field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
293 sizeof(mirror::HeapReference<mirror::Object>));
294 if (LIKELY(field != NULL)) {
295 if (UNLIKELY(obj == NULL)) {
296 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
297 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
298 } else {
299 // Compiled code can't use transactional mode.
300 field->SetObj<false>(obj, new_value);
301 return 0; // success
302 }
303 }
304 return -1; // failure
305 }
306
307 } // namespace art
308