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 <stdint.h>
18
19 #include "art_field-inl.h"
20 #include "art_method-inl.h"
21 #include "callee_save_frame.h"
22 #include "dex_file-inl.h"
23 #include "entrypoints/entrypoint_utils-inl.h"
24 #include "gc_root-inl.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/object_reference.h"
27
28 namespace art {
29
FindFieldTypeIsRead(FindFieldType type)30 inline constexpr bool FindFieldTypeIsRead(FindFieldType type) {
31 return type == InstanceObjectRead ||
32 type == InstancePrimitiveRead ||
33 type == StaticObjectRead ||
34 type == StaticPrimitiveRead;
35 }
36
37 // Helper function to do a null check after trying to resolve the field. Not for statics since obj
38 // does not exist there. There is a suspend check, object is a double pointer to update the value
39 // in the caller in case it moves.
40 template<FindFieldType type, bool kAccessCheck>
FindInstanceField(uint32_t field_idx,ArtMethod * referrer,Thread * self,size_t size,mirror::Object ** obj)41 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
42 ArtMethod* referrer,
43 Thread* self,
44 size_t size,
45 mirror::Object** obj)
46 REQUIRES(!Roles::uninterruptible_)
47 SHARED_REQUIRES(Locks::mutator_lock_) {
48 StackHandleScope<1> hs(self);
49 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
50 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
51 if (LIKELY(field != nullptr) && UNLIKELY(h.Get() == nullptr)) {
52 ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type));
53 return nullptr;
54 }
55 return field;
56 }
57
artGetByteStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)58 extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx,
59 ArtMethod* referrer,
60 Thread* self)
61 SHARED_REQUIRES(Locks::mutator_lock_) {
62 ScopedQuickEntrypointChecks sqec(self);
63 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
64 if (LIKELY(field != nullptr)) {
65 return field->GetByte(field->GetDeclaringClass());
66 }
67 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
68 if (LIKELY(field != nullptr)) {
69 return field->GetByte(field->GetDeclaringClass());
70 }
71 return 0; // Will throw exception by checking with Thread::Current.
72 }
73
artGetBooleanStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)74 extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx,
75 ArtMethod* referrer,
76 Thread* self)
77 SHARED_REQUIRES(Locks::mutator_lock_) {
78 ScopedQuickEntrypointChecks sqec(self);
79 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
80 if (LIKELY(field != nullptr)) {
81 return field->GetBoolean(field->GetDeclaringClass());
82 }
83 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
84 if (LIKELY(field != nullptr)) {
85 return field->GetBoolean(field->GetDeclaringClass());
86 }
87 return 0; // Will throw exception by checking with Thread::Current.
88 }
89
artGetShortStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)90 extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx,
91 ArtMethod* referrer,
92 Thread* self)
93 SHARED_REQUIRES(Locks::mutator_lock_) {
94 ScopedQuickEntrypointChecks sqec(self);
95 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
96 if (LIKELY(field != nullptr)) {
97 return field->GetShort(field->GetDeclaringClass());
98 }
99 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
100 if (LIKELY(field != nullptr)) {
101 return field->GetShort(field->GetDeclaringClass());
102 }
103 return 0; // Will throw exception by checking with Thread::Current.
104 }
105
artGetCharStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)106 extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx,
107 ArtMethod* referrer,
108 Thread* self)
109 SHARED_REQUIRES(Locks::mutator_lock_) {
110 ScopedQuickEntrypointChecks sqec(self);
111 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
112 if (LIKELY(field != nullptr)) {
113 return field->GetChar(field->GetDeclaringClass());
114 }
115 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
116 if (LIKELY(field != nullptr)) {
117 return field->GetChar(field->GetDeclaringClass());
118 }
119 return 0; // Will throw exception by checking with Thread::Current.
120 }
121
artGet32StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)122 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
123 ArtMethod* referrer,
124 Thread* self)
125 SHARED_REQUIRES(Locks::mutator_lock_) {
126 ScopedQuickEntrypointChecks sqec(self);
127 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t));
128 if (LIKELY(field != nullptr)) {
129 return field->Get32(field->GetDeclaringClass());
130 }
131 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
132 if (LIKELY(field != nullptr)) {
133 return field->Get32(field->GetDeclaringClass());
134 }
135 return 0; // Will throw exception by checking with Thread::Current.
136 }
137
artGet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)138 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
139 ArtMethod* referrer,
140 Thread* self)
141 SHARED_REQUIRES(Locks::mutator_lock_) {
142 ScopedQuickEntrypointChecks sqec(self);
143 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t));
144 if (LIKELY(field != nullptr)) {
145 return field->Get64(field->GetDeclaringClass());
146 }
147 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
148 if (LIKELY(field != nullptr)) {
149 return field->Get64(field->GetDeclaringClass());
150 }
151 return 0; // Will throw exception by checking with Thread::Current.
152 }
153
artGetObjStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)154 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
155 ArtMethod* referrer,
156 Thread* self)
157 SHARED_REQUIRES(Locks::mutator_lock_) {
158 ScopedQuickEntrypointChecks sqec(self);
159 ArtField* field = FindFieldFast(field_idx,
160 referrer,
161 StaticObjectRead,
162 sizeof(mirror::HeapReference<mirror::Object>));
163 if (LIKELY(field != nullptr)) {
164 return field->GetObj(field->GetDeclaringClass());
165 }
166 field = FindFieldFromCode<StaticObjectRead, true>(field_idx,
167 referrer,
168 self,
169 sizeof(mirror::HeapReference<mirror::Object>));
170 if (LIKELY(field != nullptr)) {
171 return field->GetObj(field->GetDeclaringClass());
172 }
173 return nullptr; // Will throw exception by checking with Thread::Current.
174 }
175
artGetByteInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)176 extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx,
177 mirror::Object* obj,
178 ArtMethod* referrer,
179 Thread* self)
180 SHARED_REQUIRES(Locks::mutator_lock_) {
181 ScopedQuickEntrypointChecks sqec(self);
182 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
183 if (LIKELY(field != nullptr && obj != nullptr)) {
184 return field->GetByte(obj);
185 }
186 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
187 referrer,
188 self,
189 sizeof(int8_t),
190 &obj);
191 if (LIKELY(field != nullptr)) {
192 return field->GetByte(obj);
193 }
194 return 0; // Will throw exception by checking with Thread::Current.
195 }
196
artGetBooleanInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)197 extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx,
198 mirror::Object* obj,
199 ArtMethod* referrer,
200 Thread* self)
201 SHARED_REQUIRES(Locks::mutator_lock_) {
202 ScopedQuickEntrypointChecks sqec(self);
203 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
204 if (LIKELY(field != nullptr && obj != nullptr)) {
205 return field->GetBoolean(obj);
206 }
207 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
208 referrer,
209 self,
210 sizeof(int8_t),
211 &obj);
212 if (LIKELY(field != nullptr)) {
213 return field->GetBoolean(obj);
214 }
215 return 0; // Will throw exception by checking with Thread::Current.
216 }
artGetShortInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)217 extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx,
218 mirror::Object* obj,
219 ArtMethod* referrer,
220 Thread* self)
221 SHARED_REQUIRES(Locks::mutator_lock_) {
222 ScopedQuickEntrypointChecks sqec(self);
223 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
224 if (LIKELY(field != nullptr && obj != nullptr)) {
225 return field->GetShort(obj);
226 }
227 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
228 referrer,
229 self,
230 sizeof(int16_t),
231 &obj);
232 if (LIKELY(field != nullptr)) {
233 return field->GetShort(obj);
234 }
235 return 0; // Will throw exception by checking with Thread::Current.
236 }
237
artGetCharInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)238 extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx,
239 mirror::Object* obj,
240 ArtMethod* referrer,
241 Thread* self)
242 SHARED_REQUIRES(Locks::mutator_lock_) {
243 ScopedQuickEntrypointChecks sqec(self);
244 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
245 if (LIKELY(field != nullptr && obj != nullptr)) {
246 return field->GetChar(obj);
247 }
248 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
249 referrer,
250 self,
251 sizeof(int16_t),
252 &obj);
253 if (LIKELY(field != nullptr)) {
254 return field->GetChar(obj);
255 }
256 return 0; // Will throw exception by checking with Thread::Current.
257 }
258
artGet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)259 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx,
260 mirror::Object* obj,
261 ArtMethod* referrer,
262 Thread* self)
263 SHARED_REQUIRES(Locks::mutator_lock_) {
264 ScopedQuickEntrypointChecks sqec(self);
265 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
266 if (LIKELY(field != nullptr && obj != nullptr)) {
267 return field->Get32(obj);
268 }
269 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
270 referrer,
271 self,
272 sizeof(int32_t),
273 &obj);
274 if (LIKELY(field != nullptr)) {
275 return field->Get32(obj);
276 }
277 return 0; // Will throw exception by checking with Thread::Current.
278 }
279
artGet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)280 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx,
281 mirror::Object* obj,
282 ArtMethod* referrer,
283 Thread* self)
284 SHARED_REQUIRES(Locks::mutator_lock_) {
285 ScopedQuickEntrypointChecks sqec(self);
286 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
287 if (LIKELY(field != nullptr && obj != nullptr)) {
288 return field->Get64(obj);
289 }
290 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
291 referrer,
292 self,
293 sizeof(int64_t),
294 &obj);
295 if (LIKELY(field != nullptr)) {
296 return field->Get64(obj);
297 }
298 return 0; // Will throw exception by checking with Thread::Current.
299 }
300
artGetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)301 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx,
302 mirror::Object* obj,
303 ArtMethod* referrer,
304 Thread* self)
305 SHARED_REQUIRES(Locks::mutator_lock_) {
306 ScopedQuickEntrypointChecks sqec(self);
307 ArtField* field = FindFieldFast(field_idx,
308 referrer,
309 InstanceObjectRead,
310 sizeof(mirror::HeapReference<mirror::Object>));
311 if (LIKELY(field != nullptr && obj != nullptr)) {
312 return field->GetObj(obj);
313 }
314 field = FindInstanceField<InstanceObjectRead, true>(field_idx,
315 referrer,
316 self,
317 sizeof(mirror::HeapReference<mirror::Object>),
318 &obj);
319 if (LIKELY(field != nullptr)) {
320 return field->GetObj(obj);
321 }
322 return nullptr; // Will throw exception by checking with Thread::Current.
323 }
324
artSet8StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)325 extern "C" int artSet8StaticFromCode(uint32_t field_idx,
326 uint32_t new_value,
327 ArtMethod* referrer,
328 Thread* self)
329 SHARED_REQUIRES(Locks::mutator_lock_) {
330 ScopedQuickEntrypointChecks sqec(self);
331 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t));
332 if (LIKELY(field != nullptr)) {
333 Primitive::Type type = field->GetTypeAsPrimitiveType();
334 // Compiled code can't use transactional mode.
335 if (type == Primitive::kPrimBoolean) {
336 field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
337 } else {
338 DCHECK_EQ(Primitive::kPrimByte, type);
339 field->SetByte<false>(field->GetDeclaringClass(), new_value);
340 }
341 return 0; // success
342 }
343 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int8_t));
344 if (LIKELY(field != nullptr)) {
345 Primitive::Type type = field->GetTypeAsPrimitiveType();
346 // Compiled code can't use transactional mode.
347 if (type == Primitive::kPrimBoolean) {
348 field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
349 } else {
350 DCHECK_EQ(Primitive::kPrimByte, type);
351 field->SetByte<false>(field->GetDeclaringClass(), new_value);
352 }
353 return 0; // success
354 }
355 return -1; // failure
356 }
357
artSet16StaticFromCode(uint32_t field_idx,uint16_t new_value,ArtMethod * referrer,Thread * self)358 extern "C" int artSet16StaticFromCode(uint32_t field_idx,
359 uint16_t new_value,
360 ArtMethod* referrer,
361 Thread* self)
362 SHARED_REQUIRES(Locks::mutator_lock_) {
363 ScopedQuickEntrypointChecks sqec(self);
364 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t));
365 if (LIKELY(field != nullptr)) {
366 Primitive::Type type = field->GetTypeAsPrimitiveType();
367 // Compiled code can't use transactional mode.
368 if (type == Primitive::kPrimChar) {
369 field->SetChar<false>(field->GetDeclaringClass(), new_value);
370 } else {
371 DCHECK_EQ(Primitive::kPrimShort, type);
372 field->SetShort<false>(field->GetDeclaringClass(), new_value);
373 }
374 return 0; // success
375 }
376 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int16_t));
377 if (LIKELY(field != nullptr)) {
378 Primitive::Type type = field->GetTypeAsPrimitiveType();
379 // Compiled code can't use transactional mode.
380 if (type == Primitive::kPrimChar) {
381 field->SetChar<false>(field->GetDeclaringClass(), new_value);
382 } else {
383 DCHECK_EQ(Primitive::kPrimShort, type);
384 field->SetShort<false>(field->GetDeclaringClass(), new_value);
385 }
386 return 0; // success
387 }
388 return -1; // failure
389 }
390
artSet32StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)391 extern "C" int artSet32StaticFromCode(uint32_t field_idx,
392 uint32_t new_value,
393 ArtMethod* referrer,
394 Thread* self)
395 SHARED_REQUIRES(Locks::mutator_lock_) {
396 ScopedQuickEntrypointChecks sqec(self);
397 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
398 if (LIKELY(field != nullptr)) {
399 // Compiled code can't use transactional mode.
400 field->Set32<false>(field->GetDeclaringClass(), new_value);
401 return 0; // success
402 }
403 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
404 if (LIKELY(field != nullptr)) {
405 // Compiled code can't use transactional mode.
406 field->Set32<false>(field->GetDeclaringClass(), new_value);
407 return 0; // success
408 }
409 return -1; // failure
410 }
411
artSet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,uint64_t new_value,Thread * self)412 extern "C" int artSet64StaticFromCode(uint32_t field_idx,
413 ArtMethod* referrer,
414 uint64_t new_value,
415 Thread* self)
416 SHARED_REQUIRES(Locks::mutator_lock_) {
417 ScopedQuickEntrypointChecks sqec(self);
418 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
419 if (LIKELY(field != nullptr)) {
420 // Compiled code can't use transactional mode.
421 field->Set64<false>(field->GetDeclaringClass(), new_value);
422 return 0; // success
423 }
424 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
425 if (LIKELY(field != nullptr)) {
426 // Compiled code can't use transactional mode.
427 field->Set64<false>(field->GetDeclaringClass(), new_value);
428 return 0; // success
429 }
430 return -1; // failure
431 }
432
artSetObjStaticFromCode(uint32_t field_idx,mirror::Object * new_value,ArtMethod * referrer,Thread * self)433 extern "C" int artSetObjStaticFromCode(uint32_t field_idx,
434 mirror::Object* new_value,
435 ArtMethod* referrer,
436 Thread* self)
437 SHARED_REQUIRES(Locks::mutator_lock_) {
438 ScopedQuickEntrypointChecks sqec(self);
439 ArtField* field = FindFieldFast(field_idx,
440 referrer,
441 StaticObjectWrite,
442 sizeof(mirror::HeapReference<mirror::Object>));
443 if (LIKELY(field != nullptr)) {
444 if (LIKELY(!field->IsPrimitiveType())) {
445 // Compiled code can't use transactional mode.
446 field->SetObj<false>(field->GetDeclaringClass(), new_value);
447 return 0; // success
448 }
449 }
450 {
451 StackHandleScope<1> hs(self);
452 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&new_value));
453 field = FindFieldFromCode<StaticObjectWrite, true>(
454 field_idx,
455 referrer,
456 self,
457 sizeof(mirror::HeapReference<mirror::Object>));
458 }
459 if (LIKELY(field != nullptr)) {
460 // Compiled code can't use transactional mode.
461 field->SetObj<false>(field->GetDeclaringClass(), new_value);
462 return 0; // success
463 }
464 return -1; // failure
465 }
466
artSet8InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,ArtMethod * referrer,Thread * self)467 extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
468 mirror::Object* obj,
469 uint8_t new_value,
470 ArtMethod* referrer,
471 Thread* self)
472 SHARED_REQUIRES(Locks::mutator_lock_) {
473 ScopedQuickEntrypointChecks sqec(self);
474 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
475 if (LIKELY(field != nullptr && obj != nullptr)) {
476 Primitive::Type type = field->GetTypeAsPrimitiveType();
477 // Compiled code can't use transactional mode.
478 if (type == Primitive::kPrimBoolean) {
479 field->SetBoolean<false>(obj, new_value);
480 } else {
481 DCHECK_EQ(Primitive::kPrimByte, type);
482 field->SetByte<false>(obj, new_value);
483 }
484 return 0; // success
485 }
486 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
487 referrer,
488 self,
489 sizeof(int8_t),
490 &obj);
491 if (LIKELY(field != nullptr)) {
492 Primitive::Type type = field->GetTypeAsPrimitiveType();
493 // Compiled code can't use transactional mode.
494 if (type == Primitive::kPrimBoolean) {
495 field->SetBoolean<false>(obj, new_value);
496 } else {
497 field->SetByte<false>(obj, new_value);
498 }
499 return 0; // success
500 }
501 return -1; // failure
502 }
503
artSet16InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,ArtMethod * referrer,Thread * self)504 extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
505 mirror::Object* obj,
506 uint16_t new_value,
507 ArtMethod* referrer,
508 Thread* self)
509 SHARED_REQUIRES(Locks::mutator_lock_) {
510 ScopedQuickEntrypointChecks sqec(self);
511 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t));
512 if (LIKELY(field != nullptr && obj != nullptr)) {
513 Primitive::Type type = field->GetTypeAsPrimitiveType();
514 // Compiled code can't use transactional mode.
515 if (type == Primitive::kPrimChar) {
516 field->SetChar<false>(obj, new_value);
517 } else {
518 DCHECK_EQ(Primitive::kPrimShort, type);
519 field->SetShort<false>(obj, new_value);
520 }
521 return 0; // success
522 }
523 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
524 referrer,
525 self,
526 sizeof(int16_t),
527 &obj);
528 if (LIKELY(field != nullptr)) {
529 Primitive::Type type = field->GetTypeAsPrimitiveType();
530 // Compiled code can't use transactional mode.
531 if (type == Primitive::kPrimChar) {
532 field->SetChar<false>(obj, new_value);
533 } else {
534 DCHECK_EQ(Primitive::kPrimShort, type);
535 field->SetShort<false>(obj, new_value);
536 }
537 return 0; // success
538 }
539 return -1; // failure
540 }
541
artSet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint32_t new_value,ArtMethod * referrer,Thread * self)542 extern "C" int artSet32InstanceFromCode(uint32_t field_idx,
543 mirror::Object* obj,
544 uint32_t new_value,
545 ArtMethod* referrer,
546 Thread* self)
547 SHARED_REQUIRES(Locks::mutator_lock_) {
548 ScopedQuickEntrypointChecks sqec(self);
549 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
550 if (LIKELY(field != nullptr && obj != nullptr)) {
551 // Compiled code can't use transactional mode.
552 field->Set32<false>(obj, new_value);
553 return 0; // success
554 }
555 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
556 referrer,
557 self,
558 sizeof(int32_t),
559 &obj);
560 if (LIKELY(field != nullptr)) {
561 // Compiled code can't use transactional mode.
562 field->Set32<false>(obj, new_value);
563 return 0; // success
564 }
565 return -1; // failure
566 }
567
artSet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint64_t new_value,ArtMethod * referrer,Thread * self)568 extern "C" int artSet64InstanceFromCode(uint32_t field_idx,
569 mirror::Object* obj,
570 uint64_t new_value,
571 ArtMethod* referrer,
572 Thread* self)
573 SHARED_REQUIRES(Locks::mutator_lock_) {
574 ScopedQuickEntrypointChecks sqec(self);
575 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
576 if (LIKELY(field != nullptr && obj != nullptr)) {
577 // Compiled code can't use transactional mode.
578 field->Set64<false>(obj, new_value);
579 return 0; // success
580 }
581 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
582 referrer,
583 self,
584 sizeof(int64_t),
585 &obj);
586 if (LIKELY(field != nullptr)) {
587 // Compiled code can't use transactional mode.
588 field->Set64<false>(obj, new_value);
589 return 0;
590 }
591 return -1; // failure
592 }
593
artSetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::Object * new_value,ArtMethod * referrer,Thread * self)594 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx,
595 mirror::Object* obj,
596 mirror::Object* new_value,
597 ArtMethod* referrer,
598 Thread* self)
599 SHARED_REQUIRES(Locks::mutator_lock_) {
600 ScopedQuickEntrypointChecks sqec(self);
601 ArtField* field = FindFieldFast(field_idx,
602 referrer,
603 InstanceObjectWrite,
604 sizeof(mirror::HeapReference<mirror::Object>));
605 if (LIKELY(field != nullptr && obj != nullptr)) {
606 // Compiled code can't use transactional mode.
607 field->SetObj<false>(obj, new_value);
608 return 0; // success
609 }
610 {
611 StackHandleScope<2> hs(self);
612 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
613 HandleWrapper<mirror::Object> h_new_value(hs.NewHandleWrapper(&new_value));
614 field = FindFieldFromCode<InstanceObjectWrite, true>(
615 field_idx,
616 referrer,
617 self,
618 sizeof(mirror::HeapReference<mirror::Object>));
619 }
620 if (LIKELY(field != nullptr)) {
621 if (UNLIKELY(obj == nullptr)) {
622 ThrowNullPointerExceptionForFieldAccess(field, false);
623 } else {
624 // Compiled code can't use transactional mode.
625 field->SetObj<false>(obj, new_value);
626 return 0; // success
627 }
628 }
629 return -1; // failure
630 }
631
artReadBarrierMark(mirror::Object * obj)632 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
633 DCHECK(kEmitCompilerReadBarrier);
634 return ReadBarrier::Mark(obj);
635 }
636
artReadBarrierSlow(mirror::Object * ref ATTRIBUTE_UNUSED,mirror::Object * obj,uint32_t offset)637 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
638 mirror::Object* obj,
639 uint32_t offset) {
640 DCHECK(kEmitCompilerReadBarrier);
641 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
642 mirror::HeapReference<mirror::Object>* ref_addr =
643 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
644 constexpr ReadBarrierOption kReadBarrierOption =
645 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
646 mirror::Object* result =
647 ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj,
648 MemberOffset(offset),
649 ref_addr);
650 return result;
651 }
652
artReadBarrierForRootSlow(GcRoot<mirror::Object> * root)653 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
654 DCHECK(kEmitCompilerReadBarrier);
655 return root->Read();
656 }
657
658 } // namespace art
659