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 "art_field-inl.h"
18 #include "art_method-inl.h"
19 #include "callee_save_frame.h"
20 #include "dex_file-inl.h"
21 #include "entrypoints/entrypoint_utils-inl.h"
22 #include "mirror/class-inl.h"
23 
24 #include <stdint.h>
25 
26 namespace art {
27 
artGetByteStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)28 extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
29                                            Thread* self)
30     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
31   ScopedQuickEntrypointChecks sqec(self);
32   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
33   if (LIKELY(field != nullptr)) {
34     return field->GetByte(field->GetDeclaringClass());
35   }
36   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
37   if (LIKELY(field != nullptr)) {
38     return field->GetByte(field->GetDeclaringClass());
39   }
40   return 0;  // Will throw exception by checking with Thread::Current.
41 }
42 
artGetBooleanStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)43 extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
44                                                Thread* self)
45     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
46   ScopedQuickEntrypointChecks sqec(self);
47   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
48   if (LIKELY(field != nullptr)) {
49     return field->GetBoolean(field->GetDeclaringClass());
50   }
51   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
52   if (LIKELY(field != nullptr)) {
53     return field->GetBoolean(field->GetDeclaringClass());
54   }
55   return 0;  // Will throw exception by checking with Thread::Current.
56 }
57 
artGetShortStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)58 extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
59                                              Thread* self)
60     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
61   ScopedQuickEntrypointChecks sqec(self);
62   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
63   if (LIKELY(field != nullptr)) {
64     return field->GetShort(field->GetDeclaringClass());
65   }
66   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
67   if (LIKELY(field != nullptr)) {
68     return field->GetShort(field->GetDeclaringClass());
69   }
70   return 0;  // Will throw exception by checking with Thread::Current.
71 }
72 
artGetCharStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)73 extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx,
74                                              ArtMethod* referrer,
75                                              Thread* self)
76     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
77   ScopedQuickEntrypointChecks sqec(self);
78   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
79   if (LIKELY(field != nullptr)) {
80     return field->GetChar(field->GetDeclaringClass());
81   }
82   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
83   if (LIKELY(field != nullptr)) {
84     return field->GetChar(field->GetDeclaringClass());
85   }
86   return 0;  // Will throw exception by checking with Thread::Current.
87 }
88 
artGet32StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)89 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
90                                            ArtMethod* referrer,
91                                            Thread* self)
92     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
93   ScopedQuickEntrypointChecks sqec(self);
94   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t));
95   if (LIKELY(field != nullptr)) {
96     return field->Get32(field->GetDeclaringClass());
97   }
98   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
99   if (LIKELY(field != nullptr)) {
100     return field->Get32(field->GetDeclaringClass());
101   }
102   return 0;  // Will throw exception by checking with Thread::Current.
103 }
104 
artGet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)105 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
106                                            ArtMethod* referrer,
107                                            Thread* self)
108     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
109   ScopedQuickEntrypointChecks sqec(self);
110   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t));
111   if (LIKELY(field != nullptr)) {
112     return field->Get64(field->GetDeclaringClass());
113   }
114   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
115   if (LIKELY(field != nullptr)) {
116     return field->Get64(field->GetDeclaringClass());
117   }
118   return 0;  // Will throw exception by checking with Thread::Current.
119 }
120 
artGetObjStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)121 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
122                                                    ArtMethod* referrer,
123                                                    Thread* self)
124     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
125   ScopedQuickEntrypointChecks sqec(self);
126   ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
127                                   sizeof(mirror::HeapReference<mirror::Object>));
128   if (LIKELY(field != nullptr)) {
129     return field->GetObj(field->GetDeclaringClass());
130   }
131   field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
132                                                     sizeof(mirror::HeapReference<mirror::Object>));
133   if (LIKELY(field != nullptr)) {
134     return field->GetObj(field->GetDeclaringClass());
135   }
136   return nullptr;  // Will throw exception by checking with Thread::Current.
137 }
138 
artGetByteInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)139 extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
140                                              ArtMethod* referrer, Thread* self)
141     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
142   ScopedQuickEntrypointChecks sqec(self);
143   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
144   if (LIKELY(field != nullptr && obj != nullptr)) {
145     return field->GetByte(obj);
146   }
147   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
148                                                          sizeof(int8_t));
149   if (LIKELY(field != nullptr)) {
150     if (UNLIKELY(obj == nullptr)) {
151       ThrowNullPointerExceptionForFieldAccess(field, true);
152     } else {
153       return field->GetByte(obj);
154     }
155   }
156   return 0;  // Will throw exception by checking with Thread::Current.
157 }
158 
artGetBooleanInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)159 extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
160                                                  ArtMethod* referrer, Thread* self)
161     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
162   ScopedQuickEntrypointChecks sqec(self);
163   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
164   if (LIKELY(field != nullptr && obj != nullptr)) {
165     return field->GetBoolean(obj);
166   }
167   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
168                                                          sizeof(int8_t));
169   if (LIKELY(field != nullptr)) {
170     if (UNLIKELY(obj == nullptr)) {
171       ThrowNullPointerExceptionForFieldAccess(field, true);
172     } else {
173       return field->GetBoolean(obj);
174     }
175   }
176   return 0;  // Will throw exception by checking with Thread::Current.
177 }
artGetShortInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)178 extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
179                                                ArtMethod* referrer, Thread* self)
180     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
181   ScopedQuickEntrypointChecks sqec(self);
182   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
183   if (LIKELY(field != nullptr && obj != nullptr)) {
184     return field->GetShort(obj);
185   }
186   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
187                                                          sizeof(int16_t));
188   if (LIKELY(field != nullptr)) {
189     if (UNLIKELY(obj == nullptr)) {
190       ThrowNullPointerExceptionForFieldAccess(field, true);
191     } else {
192       return field->GetShort(obj);
193     }
194   }
195   return 0;  // Will throw exception by checking with Thread::Current.
196 }
197 
artGetCharInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)198 extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
199                                                ArtMethod* referrer, Thread* self)
200     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
201   ScopedQuickEntrypointChecks sqec(self);
202   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
203   if (LIKELY(field != nullptr && obj != nullptr)) {
204     return field->GetChar(obj);
205   }
206   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
207                                                          sizeof(int16_t));
208   if (LIKELY(field != nullptr)) {
209     if (UNLIKELY(obj == nullptr)) {
210       ThrowNullPointerExceptionForFieldAccess(field, true);
211     } else {
212       return field->GetChar(obj);
213     }
214   }
215   return 0;  // Will throw exception by checking with Thread::Current.
216 }
217 
artGet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)218 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
219                                              ArtMethod* referrer, Thread* self)
220     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
221   ScopedQuickEntrypointChecks sqec(self);
222   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
223   if (LIKELY(field != nullptr && obj != nullptr)) {
224     return field->Get32(obj);
225   }
226   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
227                                                          sizeof(int32_t));
228   if (LIKELY(field != nullptr)) {
229     if (UNLIKELY(obj == nullptr)) {
230       ThrowNullPointerExceptionForFieldAccess(field, true);
231     } else {
232       return field->Get32(obj);
233     }
234   }
235   return 0;  // Will throw exception by checking with Thread::Current.
236 }
237 
artGet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)238 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
239                                              ArtMethod* referrer, Thread* self)
240     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
241   ScopedQuickEntrypointChecks sqec(self);
242   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
243   if (LIKELY(field != nullptr && obj != nullptr)) {
244     return field->Get64(obj);
245   }
246   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
247                                                          sizeof(int64_t));
248   if (LIKELY(field != nullptr)) {
249     if (UNLIKELY(obj == nullptr)) {
250       ThrowNullPointerExceptionForFieldAccess(field, true);
251     } else {
252       return field->Get64(obj);
253     }
254   }
255   return 0;  // Will throw exception by checking with Thread::Current.
256 }
257 
artGetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)258 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
259                                                      ArtMethod* referrer,
260                                                      Thread* self)
261     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
262   ScopedQuickEntrypointChecks sqec(self);
263   ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
264                                   sizeof(mirror::HeapReference<mirror::Object>));
265   if (LIKELY(field != nullptr && obj != nullptr)) {
266     return field->GetObj(obj);
267   }
268   field = FindFieldFromCode<InstanceObjectRead, true>(
269       field_idx, referrer, self, sizeof(mirror::HeapReference<mirror::Object>));
270   if (LIKELY(field != nullptr)) {
271     if (UNLIKELY(obj == nullptr)) {
272       ThrowNullPointerExceptionForFieldAccess(field, true);
273     } else {
274       return field->GetObj(obj);
275     }
276   }
277   return nullptr;  // Will throw exception by checking with Thread::Current.
278 }
279 
artSet8StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)280 extern "C" int artSet8StaticFromCode(uint32_t field_idx, uint32_t new_value,
281                                      ArtMethod* referrer, Thread* self)
282     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
283   ScopedQuickEntrypointChecks sqec(self);
284   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t));
285   if (LIKELY(field != nullptr)) {
286     Primitive::Type type = field->GetTypeAsPrimitiveType();
287     // Compiled code can't use transactional mode.
288     if (type == Primitive::kPrimBoolean) {
289       field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
290     } else {
291       DCHECK_EQ(Primitive::kPrimByte, type);
292       field->SetByte<false>(field->GetDeclaringClass(), new_value);
293     }
294     return 0;  // success
295   }
296   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int8_t));
297   if (LIKELY(field != nullptr)) {
298     Primitive::Type type = field->GetTypeAsPrimitiveType();
299     // Compiled code can't use transactional mode.
300     if (type == Primitive::kPrimBoolean) {
301       field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
302     } else {
303       DCHECK_EQ(Primitive::kPrimByte, type);
304       field->SetByte<false>(field->GetDeclaringClass(), new_value);
305     }
306     return 0;  // success
307   }
308   return -1;  // failure
309 }
310 
artSet16StaticFromCode(uint32_t field_idx,uint16_t new_value,ArtMethod * referrer,Thread * self)311 extern "C" int artSet16StaticFromCode(uint32_t field_idx, uint16_t new_value,
312                                       ArtMethod* referrer, Thread* self)
313     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
314   ScopedQuickEntrypointChecks sqec(self);
315   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t));
316   if (LIKELY(field != nullptr)) {
317     Primitive::Type type = field->GetTypeAsPrimitiveType();
318     // Compiled code can't use transactional mode.
319     if (type == Primitive::kPrimChar) {
320       field->SetChar<false>(field->GetDeclaringClass(), new_value);
321     } else {
322       DCHECK_EQ(Primitive::kPrimShort, type);
323       field->SetShort<false>(field->GetDeclaringClass(), new_value);
324     }
325     return 0;  // success
326   }
327   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int16_t));
328   if (LIKELY(field != nullptr)) {
329     Primitive::Type type = field->GetTypeAsPrimitiveType();
330     // Compiled code can't use transactional mode.
331     if (type == Primitive::kPrimChar) {
332       field->SetChar<false>(field->GetDeclaringClass(), new_value);
333     } else {
334       DCHECK_EQ(Primitive::kPrimShort, type);
335       field->SetShort<false>(field->GetDeclaringClass(), new_value);
336     }
337     return 0;  // success
338   }
339   return -1;  // failure
340 }
341 
artSet32StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)342 extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
343                                       ArtMethod* referrer, Thread* self)
344     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
345   ScopedQuickEntrypointChecks sqec(self);
346   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
347   if (LIKELY(field != nullptr)) {
348     // Compiled code can't use transactional mode.
349     field->Set32<false>(field->GetDeclaringClass(), new_value);
350     return 0;  // success
351   }
352   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
353   if (LIKELY(field != nullptr)) {
354     // Compiled code can't use transactional mode.
355     field->Set32<false>(field->GetDeclaringClass(), new_value);
356     return 0;  // success
357   }
358   return -1;  // failure
359 }
360 
artSet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,uint64_t new_value,Thread * self)361 extern "C" int artSet64StaticFromCode(uint32_t field_idx, ArtMethod* referrer,
362                                       uint64_t new_value, Thread* self)
363     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
364   ScopedQuickEntrypointChecks sqec(self);
365   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
366   if (LIKELY(field != nullptr)) {
367     // Compiled code can't use transactional mode.
368     field->Set64<false>(field->GetDeclaringClass(), new_value);
369     return 0;  // success
370   }
371   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
372   if (LIKELY(field != nullptr)) {
373     // Compiled code can't use transactional mode.
374     field->Set64<false>(field->GetDeclaringClass(), new_value);
375     return 0;  // success
376   }
377   return -1;  // failure
378 }
379 
artSetObjStaticFromCode(uint32_t field_idx,mirror::Object * new_value,ArtMethod * referrer,Thread * self)380 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
381                                        ArtMethod* referrer, Thread* self)
382     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
383   ScopedQuickEntrypointChecks sqec(self);
384   ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
385                                   sizeof(mirror::HeapReference<mirror::Object>));
386   if (LIKELY(field != nullptr)) {
387     if (LIKELY(!field->IsPrimitiveType())) {
388       // Compiled code can't use transactional mode.
389       field->SetObj<false>(field->GetDeclaringClass(), new_value);
390       return 0;  // success
391     }
392   }
393   field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
394                                                      sizeof(mirror::HeapReference<mirror::Object>));
395   if (LIKELY(field != nullptr)) {
396     // Compiled code can't use transactional mode.
397     field->SetObj<false>(field->GetDeclaringClass(), new_value);
398     return 0;  // success
399   }
400   return -1;  // failure
401 }
402 
artSet8InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,ArtMethod * referrer,Thread * self)403 extern "C" int artSet8InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint8_t new_value,
404                                        ArtMethod* referrer, Thread* self)
405     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
406   ScopedQuickEntrypointChecks sqec(self);
407   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
408   if (LIKELY(field != nullptr && obj != nullptr)) {
409     Primitive::Type type = field->GetTypeAsPrimitiveType();
410     // Compiled code can't use transactional mode.
411     if (type == Primitive::kPrimBoolean) {
412       field->SetBoolean<false>(obj, new_value);
413     } else {
414       DCHECK_EQ(Primitive::kPrimByte, type);
415       field->SetByte<false>(obj, new_value);
416     }
417     return 0;  // success
418   }
419   {
420     StackHandleScope<1> hs(self);
421     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
422     field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
423                                                             sizeof(int8_t));
424   }
425   if (LIKELY(field != nullptr)) {
426     if (UNLIKELY(obj == nullptr)) {
427       ThrowNullPointerExceptionForFieldAccess(field, false);
428     } else {
429       Primitive::Type type = field->GetTypeAsPrimitiveType();
430       // Compiled code can't use transactional mode.
431       if (type == Primitive::kPrimBoolean) {
432         field->SetBoolean<false>(obj, new_value);
433       } else {
434         field->SetByte<false>(obj, new_value);
435       }
436       return 0;  // success
437     }
438   }
439   return -1;  // failure
440 }
441 
artSet16InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,ArtMethod * referrer,Thread * self)442 extern "C" int artSet16InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint16_t new_value,
443                                         ArtMethod* referrer, Thread* self)
444     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
445   ScopedQuickEntrypointChecks sqec(self);
446   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t));
447   if (LIKELY(field != nullptr && obj != nullptr)) {
448     Primitive::Type type = field->GetTypeAsPrimitiveType();
449     // Compiled code can't use transactional mode.
450     if (type == Primitive::kPrimChar) {
451       field->SetChar<false>(obj, new_value);
452     } else {
453       DCHECK_EQ(Primitive::kPrimShort, type);
454       field->SetShort<false>(obj, new_value);
455     }
456     return 0;  // success
457   }
458   {
459     StackHandleScope<1> hs(self);
460     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
461     field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
462                                                             sizeof(int16_t));
463   }
464   if (LIKELY(field != nullptr)) {
465     if (UNLIKELY(obj == nullptr)) {
466       ThrowNullPointerExceptionForFieldAccess(field, false);
467     } else {
468       Primitive::Type type = field->GetTypeAsPrimitiveType();
469       // Compiled code can't use transactional mode.
470       if (type == Primitive::kPrimChar) {
471         field->SetChar<false>(obj, new_value);
472       } else {
473         DCHECK_EQ(Primitive::kPrimShort, type);
474         field->SetShort<false>(obj, new_value);
475       }
476       return 0;  // success
477     }
478   }
479   return -1;  // failure
480 }
481 
artSet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint32_t new_value,ArtMethod * referrer,Thread * self)482 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
483                                         ArtMethod* referrer, Thread* self)
484     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
485   ScopedQuickEntrypointChecks sqec(self);
486   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
487   if (LIKELY(field != nullptr && obj != nullptr)) {
488     // Compiled code can't use transactional mode.
489     field->Set32<false>(obj, new_value);
490     return 0;  // success
491   }
492   {
493     StackHandleScope<1> hs(self);
494     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
495     field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
496                                                             sizeof(int32_t));
497   }
498   if (LIKELY(field != nullptr)) {
499     if (UNLIKELY(obj == nullptr)) {
500       ThrowNullPointerExceptionForFieldAccess(field, false);
501     } else {
502       // Compiled code can't use transactional mode.
503       field->Set32<false>(obj, new_value);
504       return 0;  // success
505     }
506   }
507   return -1;  // failure
508 }
509 
artSet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint64_t new_value,ArtMethod * referrer,Thread * self)510 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint64_t new_value,
511                                         ArtMethod* referrer, Thread* self)
512     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
513   ScopedQuickEntrypointChecks sqec(self);
514   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
515   if (LIKELY(field != nullptr  && obj != nullptr)) {
516     // Compiled code can't use transactional mode.
517     field->Set64<false>(obj, new_value);
518     return 0;  // success
519   }
520   field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
521                                                           sizeof(int64_t));
522   if (LIKELY(field != nullptr)) {
523     if (UNLIKELY(obj == nullptr)) {
524       ThrowNullPointerExceptionForFieldAccess(field, false);
525     } else {
526       // Compiled code can't use transactional mode.
527       field->Set64<false>(obj, new_value);
528       return 0;  // success
529     }
530   }
531   return -1;  // failure
532 }
533 
artSetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::Object * new_value,ArtMethod * referrer,Thread * self)534 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
535                                          mirror::Object* new_value,
536                                          ArtMethod* referrer, Thread* self)
537     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
538   ScopedQuickEntrypointChecks sqec(self);
539   ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
540                                   sizeof(mirror::HeapReference<mirror::Object>));
541   if (LIKELY(field != nullptr && obj != nullptr)) {
542     // Compiled code can't use transactional mode.
543     field->SetObj<false>(obj, new_value);
544     return 0;  // success
545   }
546   field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
547                                                        sizeof(mirror::HeapReference<mirror::Object>));
548   if (LIKELY(field != nullptr)) {
549     if (UNLIKELY(obj == nullptr)) {
550       ThrowNullPointerExceptionForFieldAccess(field, false);
551     } else {
552       // Compiled code can't use transactional mode.
553       field->SetObj<false>(obj, new_value);
554       return 0;  // success
555     }
556   }
557   return -1;  // failure
558 }
559 
560 }  // namespace art
561