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