quick_field_entrypoints.cc revision 98d1cc8033251c93786e2fa8c59a2e555a9493be
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
26namespace art {
27
28extern "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
45extern "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
62extern "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
81extern "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
104extern "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
127extern "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
151extern "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
172extern "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
193extern "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
217extern "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
248extern "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
279extern "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