blob: 822c5a8d9da716477cc6b29635d85c1605a556be [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
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
Roland Levillain0d5a2812015-11-13 10:07:31 +000017#include <stdint.h>
18
Mathieu Chartierc7853442015-03-27 14:35:38 -070019#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070020#include "art_method-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070021#include "callee_save_frame.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070022#include "dex_file-inl.h"
Mingyao Yang98d1cc82014-05-15 17:02:16 -070023#include "entrypoints/entrypoint_utils-inl.h"
Roland Levillain0d5a2812015-11-13 10:07:31 +000024#include "gc_root-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080025#include "mirror/class-inl.h"
Roland Levillain0d5a2812015-11-13 10:07:31 +000026#include "mirror/object_reference.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070027
28namespace art {
29
Mathieu Chartiera61347b2016-02-05 13:47:06 -080030inline 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.
Mathieu Chartierbf369182016-02-04 18:13:32 -080040template<FindFieldType type, bool kAccessCheck>
41ALWAYS_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_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070047 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbf369182016-02-04 18:13:32 -080048 StackHandleScope<1> hs(self);
49 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
50 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
Andreas Gampefa4333d2017-02-14 11:10:34 -080051 if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
Mathieu Chartierbf369182016-02-04 18:13:32 -080052 ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type));
53 return nullptr;
54 }
55 return field;
56}
57
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000058static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
59 if (kIsDebugBuild) {
60 // stub_test doesn't call this code with a proper frame, so get the outer, and if
61 // it does not have compiled code return it.
62 ArtMethod* outer = GetCalleeSaveOuterMethod(self, Runtime::kSaveRefsOnly);
63 if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) {
64 return outer;
65 }
Fred Shih37f05ef2014-07-16 18:38:08 -070066 }
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000067 return GetCalleeSaveMethodCallerAndOuterMethod(self, Runtime::kSaveRefsOnly).caller;
Fred Shih37f05ef2014-07-16 18:38:08 -070068}
69
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000070#define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \
71 PrimitiveOrObject, IsObject, Ptr) \
72 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \
73 ArtMethod* referrer, \
74 Thread* self) \
75 REQUIRES_SHARED(Locks::mutator_lock_) { \
76 ScopedQuickEntrypointChecks sqec(self); \
77 ArtField* field = FindFieldFast( \
78 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \
79 sizeof(PrimitiveType)); \
80 if (LIKELY(field != nullptr)) { \
81 return field->Get ## Kind (field->GetDeclaringClass())Ptr; \
82 } \
83 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \
84 field_idx, referrer, self, sizeof(PrimitiveType)); \
85 if (LIKELY(field != nullptr)) { \
86 return field->Get ## Kind (field->GetDeclaringClass())Ptr; \
87 } \
88 /* Will throw exception by checking with Thread::Current. */ \
89 return 0; \
90 } \
91 \
92 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \
93 mirror::Object* obj, \
94 ArtMethod* referrer, \
95 Thread* self) \
96 REQUIRES_SHARED(Locks::mutator_lock_) { \
97 ScopedQuickEntrypointChecks sqec(self); \
98 ArtField* field = FindFieldFast( \
99 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \
100 sizeof(PrimitiveType)); \
101 if (LIKELY(field != nullptr) && obj != nullptr) { \
102 return field->Get ## Kind (obj)Ptr; \
103 } \
104 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \
105 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \
106 if (LIKELY(field != nullptr)) { \
107 return field->Get ## Kind (obj)Ptr; \
108 } \
109 /* Will throw exception by checking with Thread::Current. */ \
110 return 0; \
111 } \
112 \
113 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \
114 SetType new_value, \
115 ArtMethod* referrer, \
116 Thread* self) \
117 REQUIRES_SHARED(Locks::mutator_lock_) { \
118 ScopedQuickEntrypointChecks sqec(self); \
119 ArtField* field = FindFieldFast( \
120 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \
121 sizeof(PrimitiveType)); \
122 if (LIKELY(field != nullptr)) { \
123 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
124 return 0; \
125 } \
126 if (IsObject) { \
127 StackHandleScope<1> hs(self); \
128 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
129 reinterpret_cast<mirror::Object**>(&new_value))); \
130 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
131 field_idx, referrer, self, sizeof(PrimitiveType)); \
132 } else { \
133 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
134 field_idx, referrer, self, sizeof(PrimitiveType)); \
135 } \
136 if (LIKELY(field != nullptr)) { \
137 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
138 return 0; \
139 } \
140 return -1; \
141 } \
142 \
143 extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx, \
144 mirror::Object* obj, \
145 SetType new_value, \
146 ArtMethod* referrer, \
147 Thread* self) \
148 REQUIRES_SHARED(Locks::mutator_lock_) { \
149 ScopedQuickEntrypointChecks sqec(self); \
150 ArtField* field = FindFieldFast( \
151 field_idx, referrer, Instance ## PrimitiveOrObject ## Write, \
152 sizeof(PrimitiveType)); \
153 if (LIKELY(field != nullptr && obj != nullptr)) { \
154 field->Set ## Kind <false>(obj, new_value); \
155 return 0; \
156 } \
157 if (IsObject) { \
158 StackHandleScope<1> hs(self); \
159 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
160 reinterpret_cast<mirror::Object**>(&new_value))); \
161 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
162 field_idx, \
163 referrer, \
164 self, \
165 sizeof(PrimitiveType), \
166 &obj); \
167 } else { \
168 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
169 field_idx, \
170 referrer, \
171 self, \
172 sizeof(PrimitiveType), \
173 &obj); \
174 } \
175 if (LIKELY(field != nullptr)) { \
176 field->Set ## Kind<false>(obj, new_value); \
177 return 0; \
178 } \
179 return -1; \
180 } \
181 \
182 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \
183 uint32_t field_idx, \
184 Thread* self) \
185 REQUIRES_SHARED(Locks::mutator_lock_) { \
186 return artGet ## Kind ## StaticFromCode( \
187 field_idx, GetReferrer(self), self); \
188 } \
189 \
190 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \
191 uint32_t field_idx, \
192 mirror::Object* obj, \
193 Thread* self) \
194 REQUIRES_SHARED(Locks::mutator_lock_) { \
195 return artGet ## Kind ## InstanceFromCode( \
196 field_idx, obj, GetReferrer(self), self); \
197 } \
198 \
199 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \
200 uint32_t field_idx, \
201 SetType new_value, \
202 Thread* self) \
203 REQUIRES_SHARED(Locks::mutator_lock_) { \
204 return artSet ## Kind ## StaticFromCode( \
205 field_idx, new_value, GetReferrer(self), self); \
206 } \
207 \
208 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \
209 uint32_t field_idx, \
210 mirror::Object* obj, \
211 SetType new_value, \
212 Thread* self) \
213 REQUIRES_SHARED(Locks::mutator_lock_) { \
214 return artSet ## Kind ## InstanceFromCode( \
215 field_idx, obj, new_value, GetReferrer(self), self); \
216 }
217
218ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
219ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
220ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
221ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
222ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
223ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
224ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
225 mirror::Object*, Object, true, .Ptr())
226
227
228// To cut on the number of entrypoints, we have shared entries for
229// byte/boolean and char/short for setting an instance or static field. We just
230// forward those to the unsigned variant.
231extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
232 uint32_t new_value,
233 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700234 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000235 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700236}
237
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000238extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
239 uint16_t new_value,
Andreas Gampe67409972016-07-19 22:34:53 -0700240 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700241 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000242 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700243}
244
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000245extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800246 mirror::Object* obj,
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000247 uint8_t new_value,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800248 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700249 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000250 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700251}
252
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000253extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
254 mirror::Object* obj,
255 uint16_t new_value,
256 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700257 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000258 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700259}
260
Mathieu Chartierbf369182016-02-04 18:13:32 -0800261extern "C" int artSet8StaticFromCode(uint32_t field_idx,
262 uint32_t new_value,
263 ArtMethod* referrer,
264 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700265 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000266 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700267}
268
Mathieu Chartierbf369182016-02-04 18:13:32 -0800269extern "C" int artSet16StaticFromCode(uint32_t field_idx,
270 uint16_t new_value,
271 ArtMethod* referrer,
272 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700273 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000274 return artSetCharStaticFromCode(field_idx, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700275}
276
Mathieu Chartierbf369182016-02-04 18:13:32 -0800277extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
278 mirror::Object* obj,
279 uint8_t new_value,
280 ArtMethod* referrer,
281 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700282 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000283 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700284}
285
Mathieu Chartierbf369182016-02-04 18:13:32 -0800286extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
287 mirror::Object* obj,
288 uint16_t new_value,
289 ArtMethod* referrer,
290 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700291 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000292 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700293}
294
Roland Levillain7c1559a2015-12-15 10:55:36 +0000295extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
296 DCHECK(kEmitCompilerReadBarrier);
297 return ReadBarrier::Mark(obj);
298}
299
Man Cao1aee9002015-07-14 22:31:42 -0700300extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
Roland Levillain0d5a2812015-11-13 10:07:31 +0000301 mirror::Object* obj,
302 uint32_t offset) {
303 DCHECK(kEmitCompilerReadBarrier);
Man Cao1aee9002015-07-14 22:31:42 -0700304 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
305 mirror::HeapReference<mirror::Object>* ref_addr =
Roland Levillain0d5a2812015-11-13 10:07:31 +0000306 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
307 constexpr ReadBarrierOption kReadBarrierOption =
308 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
309 mirror::Object* result =
Hiroshi Yamauchicc78f3f2015-12-11 15:51:04 -0800310 ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj,
311 MemberOffset(offset),
312 ref_addr);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000313 return result;
314}
315
316extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
317 DCHECK(kEmitCompilerReadBarrier);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000318 return root->Read();
Man Cao1aee9002015-07-14 22:31:42 -0700319}
320
Ian Rogers57b86d42012-03-27 16:05:41 -0700321} // namespace art