object-inl.h revision 4e30541a92381fb280cd0be9a1763b713ee4d64c
1/*
2 * Copyright (C) 2011 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#ifndef ART_RUNTIME_MIRROR_OBJECT_INL_H_
18#define ART_RUNTIME_MIRROR_OBJECT_INL_H_
19
20#include "object.h"
21
22#include "art_field.h"
23#include "art_method.h"
24#include "atomic.h"
25#include "array-inl.h"
26#include "class.h"
27#include "lock_word-inl.h"
28#include "monitor.h"
29#include "runtime.h"
30#include "throwable.h"
31
32namespace art {
33namespace mirror {
34
35template<VerifyObjectFlags kVerifyFlags>
36inline Class* Object::GetClass() {
37  return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
38}
39
40template<VerifyObjectFlags kVerifyFlags>
41inline void Object::SetClass(Class* new_klass) {
42  // new_klass may be NULL prior to class linker initialization.
43  // We don't mark the card as this occurs as part of object allocation. Not all objects have
44  // backing cards, such as large objects.
45  // We use non transactional version since we can't undo this write. We also disable checking as
46  // we may run in transaction mode here.
47  SetFieldObjectWithoutWriteBarrier<false, false,
48      static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
49      OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false);
50}
51
52inline LockWord Object::GetLockWord() {
53  return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true));
54}
55
56inline void Object::SetLockWord(LockWord new_val) {
57  // Force use of non-transactional mode and do not check.
58  SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue(), true);
59}
60
61inline bool Object::CasLockWord(LockWord old_val, LockWord new_val) {
62  // Force use of non-transactional mode and do not check.
63  return CasField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(),
64                                  new_val.GetValue());
65}
66
67inline uint32_t Object::GetLockOwnerThreadId() {
68  return Monitor::GetLockOwnerThreadId(this);
69}
70
71inline mirror::Object* Object::MonitorEnter(Thread* self) {
72  return Monitor::MonitorEnter(self, this);
73}
74
75inline bool Object::MonitorExit(Thread* self) {
76  return Monitor::MonitorExit(self, this);
77}
78
79inline void Object::Notify(Thread* self) {
80  Monitor::Notify(self, this);
81}
82
83inline void Object::NotifyAll(Thread* self) {
84  Monitor::NotifyAll(self, this);
85}
86
87inline void Object::Wait(Thread* self) {
88  Monitor::Wait(self, this, 0, 0, true, kWaiting);
89}
90
91inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
92  Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
93}
94
95template<VerifyObjectFlags kVerifyFlags>
96inline bool Object::VerifierInstanceOf(Class* klass) {
97  DCHECK(klass != NULL);
98  DCHECK(GetClass<kVerifyFlags>() != NULL);
99  return klass->IsInterface() || InstanceOf(klass);
100}
101
102template<VerifyObjectFlags kVerifyFlags>
103inline bool Object::InstanceOf(Class* klass) {
104  DCHECK(klass != NULL);
105  DCHECK(GetClass<kVerifyNone>() != NULL);
106  return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
107}
108
109template<VerifyObjectFlags kVerifyFlags>
110inline bool Object::IsClass() {
111  Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
112  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
113      java_lang_Class;
114}
115
116template<VerifyObjectFlags kVerifyFlags>
117inline Class* Object::AsClass() {
118  DCHECK(IsClass<kVerifyFlags>());
119  return down_cast<Class*>(this);
120}
121
122template<VerifyObjectFlags kVerifyFlags>
123inline bool Object::IsObjectArray() {
124  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
125  return IsArrayInstance<kVerifyFlags>() &&
126      !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
127}
128
129template<class T, VerifyObjectFlags kVerifyFlags>
130inline ObjectArray<T>* Object::AsObjectArray() {
131  DCHECK(IsObjectArray<kVerifyFlags>());
132  return down_cast<ObjectArray<T>*>(this);
133}
134
135template<VerifyObjectFlags kVerifyFlags>
136inline bool Object::IsArrayInstance() {
137  return GetClass<kVerifyFlags>()->IsArrayClass();
138}
139
140template<VerifyObjectFlags kVerifyFlags>
141inline bool Object::IsArtField() {
142  return GetClass<kVerifyFlags>()->IsArtFieldClass();
143}
144
145template<VerifyObjectFlags kVerifyFlags>
146inline ArtField* Object::AsArtField() {
147  DCHECK(IsArtField<kVerifyFlags>());
148  return down_cast<ArtField*>(this);
149}
150
151template<VerifyObjectFlags kVerifyFlags>
152inline bool Object::IsArtMethod() {
153  return GetClass<kVerifyFlags>()->IsArtMethodClass();
154}
155
156template<VerifyObjectFlags kVerifyFlags>
157inline ArtMethod* Object::AsArtMethod() {
158  DCHECK(IsArtMethod<kVerifyFlags>());
159  return down_cast<ArtMethod*>(this);
160}
161
162template<VerifyObjectFlags kVerifyFlags>
163inline bool Object::IsReferenceInstance() {
164  return GetClass<kVerifyFlags>()->IsReferenceClass();
165}
166
167template<VerifyObjectFlags kVerifyFlags>
168inline Array* Object::AsArray() {
169  DCHECK(IsArrayInstance<kVerifyFlags>());
170  return down_cast<Array*>(this);
171}
172
173template<VerifyObjectFlags kVerifyFlags>
174inline BooleanArray* Object::AsBooleanArray() {
175  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
176  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
177  DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
178  return down_cast<BooleanArray*>(this);
179}
180
181template<VerifyObjectFlags kVerifyFlags>
182inline ByteArray* Object::AsByteArray() {
183  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
184  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
185  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
186  return down_cast<ByteArray*>(this);
187}
188
189template<VerifyObjectFlags kVerifyFlags>
190inline ByteArray* Object::AsByteSizedArray() {
191  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
192  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
193  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
194         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
195  return down_cast<ByteArray*>(this);
196}
197
198template<VerifyObjectFlags kVerifyFlags>
199inline CharArray* Object::AsCharArray() {
200  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
201  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
202  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
203  return down_cast<CharArray*>(this);
204}
205
206template<VerifyObjectFlags kVerifyFlags>
207inline ShortArray* Object::AsShortArray() {
208  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
209  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
210  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
211  return down_cast<ShortArray*>(this);
212}
213
214template<VerifyObjectFlags kVerifyFlags>
215inline ShortArray* Object::AsShortSizedArray() {
216  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
217  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
218  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
219         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
220  return down_cast<ShortArray*>(this);
221}
222
223template<VerifyObjectFlags kVerifyFlags>
224inline IntArray* Object::AsIntArray() {
225  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
226  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
227  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
228         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
229  return down_cast<IntArray*>(this);
230}
231
232template<VerifyObjectFlags kVerifyFlags>
233inline LongArray* Object::AsLongArray() {
234  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
235  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
236  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
237         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
238  return down_cast<LongArray*>(this);
239}
240
241template<VerifyObjectFlags kVerifyFlags>
242inline FloatArray* Object::AsFloatArray() {
243  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
244  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
245  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
246  return down_cast<FloatArray*>(this);
247}
248
249template<VerifyObjectFlags kVerifyFlags>
250inline DoubleArray* Object::AsDoubleArray() {
251  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
252  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
253  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
254  return down_cast<DoubleArray*>(this);
255}
256
257template<VerifyObjectFlags kVerifyFlags>
258inline String* Object::AsString() {
259  DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
260  return down_cast<String*>(this);
261}
262
263template<VerifyObjectFlags kVerifyFlags>
264inline Throwable* Object::AsThrowable() {
265  DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
266  return down_cast<Throwable*>(this);
267}
268
269template<VerifyObjectFlags kVerifyFlags>
270inline bool Object::IsWeakReferenceInstance() {
271  return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
272}
273
274template<VerifyObjectFlags kVerifyFlags>
275inline bool Object::IsSoftReferenceInstance() {
276  return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
277}
278
279template<VerifyObjectFlags kVerifyFlags>
280inline bool Object::IsFinalizerReferenceInstance() {
281  return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
282}
283
284template<VerifyObjectFlags kVerifyFlags>
285inline bool Object::IsPhantomReferenceInstance() {
286  return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
287}
288
289template<VerifyObjectFlags kVerifyFlags>
290inline size_t Object::SizeOf() {
291  size_t result;
292  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
293  if (IsArrayInstance<kVerifyFlags>()) {
294    result = AsArray<kNewFlags>()->SizeOf<>();
295  } else if (IsClass<kNewFlags>()) {
296    result = AsClass<kNewFlags>()->SizeOf<kNewFlags>();
297  } else {
298    result = GetClass<kNewFlags>()->GetObjectSize();
299  }
300  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
301  DCHECK(!IsArtField<kNewFlags>()  || result == sizeof(ArtField));
302  DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
303  return result;
304}
305
306template<VerifyObjectFlags kVerifyFlags>
307inline int32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
308  if (kVerifyFlags & kVerifyThis) {
309    VerifyObject(this);
310  }
311  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
312  const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
313  if (UNLIKELY(is_volatile)) {
314    int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
315    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
316    return result;
317  } else {
318    return *word_addr;
319  }
320}
321
322template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
323inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile) {
324  if (kCheckTransaction) {
325    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
326  }
327  if (kTransactionActive) {
328    Runtime::Current()->RecordWriteField32(this, field_offset, GetField32(field_offset, is_volatile),
329                                           is_volatile);
330  }
331  if (kVerifyFlags & kVerifyThis) {
332    VerifyObject(this);
333  }
334  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
335  int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr);
336  if (UNLIKELY(is_volatile)) {
337    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
338    *word_addr = new_value;
339    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
340  } else {
341    *word_addr = new_value;
342  }
343}
344
345template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
346inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) {
347  if (kCheckTransaction) {
348    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
349  }
350  if (kTransactionActive) {
351    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
352  }
353  if (kVerifyFlags & kVerifyThis) {
354    VerifyObject(this);
355  }
356  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
357  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
358  return __sync_bool_compare_and_swap(addr, old_value, new_value);
359}
360
361template<VerifyObjectFlags kVerifyFlags>
362inline int64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
363  if (kVerifyFlags & kVerifyThis) {
364    VerifyObject(this);
365  }
366  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
367  const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
368  if (UNLIKELY(is_volatile)) {
369    int64_t result = QuasiAtomic::Read64(addr);
370    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
371    return result;
372  } else {
373    return *addr;
374  }
375}
376
377template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
378inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile) {
379  if (kCheckTransaction) {
380    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
381  }
382  if (kTransactionActive) {
383    Runtime::Current()->RecordWriteField64(this, field_offset, GetField64(field_offset, is_volatile),
384                                           is_volatile);
385  }
386  if (kVerifyFlags & kVerifyThis) {
387    VerifyObject(this);
388  }
389  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
390  int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
391  if (UNLIKELY(is_volatile)) {
392    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
393    QuasiAtomic::Write64(addr, new_value);
394    if (!QuasiAtomic::LongAtomicsUseMutexes()) {
395      QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
396    } else {
397      // Fence from from mutex is enough.
398    }
399  } else {
400    *addr = new_value;
401  }
402}
403
404template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
405inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) {
406  if (kCheckTransaction) {
407    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
408  }
409  if (kTransactionActive) {
410    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
411  }
412  if (kVerifyFlags & kVerifyThis) {
413    VerifyObject(this);
414  }
415  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
416  volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr);
417  return QuasiAtomic::Cas64(old_value, new_value, addr);
418}
419
420template<class T, VerifyObjectFlags kVerifyFlags>
421inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
422  if (kVerifyFlags & kVerifyThis) {
423    VerifyObject(this);
424  }
425  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
426  HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
427  HeapReference<T> objref = *objref_addr;
428
429  if (UNLIKELY(is_volatile)) {
430    QuasiAtomic::MembarLoadLoad();  // Ensure loads don't re-order.
431  }
432  T* result = objref.AsMirrorPtr();
433  if (kVerifyFlags & kVerifyReads) {
434    VerifyObject(result);
435  }
436  return result;
437}
438
439template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
440inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
441                                                      bool is_volatile) {
442  if (kCheckTransaction) {
443    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
444  }
445  if (kTransactionActive) {
446    Runtime::Current()->RecordWriteFieldReference(this, field_offset,
447                                                  GetFieldObject<Object>(field_offset, is_volatile),
448                                                  true);
449  }
450  if (kVerifyFlags & kVerifyThis) {
451    VerifyObject(this);
452  }
453  if (kVerifyFlags & kVerifyWrites) {
454    VerifyObject(new_value);
455  }
456  HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
457  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
458  HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
459  if (UNLIKELY(is_volatile)) {
460    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
461    objref_addr->Assign(new_value);
462    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any loads.
463  } else {
464    objref_addr->Assign(new_value);
465  }
466}
467
468template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
469inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile) {
470  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
471      field_offset, new_value, is_volatile);
472  if (new_value != nullptr) {
473    CheckFieldAssignment(field_offset, new_value);
474    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
475  }
476}
477
478template <VerifyObjectFlags kVerifyFlags>
479inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
480  if (kVerifyFlags & kVerifyThis) {
481    VerifyObject(this);
482  }
483  return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
484      field_offset.Int32Value());
485}
486
487template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
488inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value,
489                                   Object* new_value) {
490  if (kCheckTransaction) {
491    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
492  }
493  if (kVerifyFlags & kVerifyThis) {
494    VerifyObject(this);
495  }
496  if (kVerifyFlags & kVerifyWrites) {
497    VerifyObject(new_value);
498  }
499  if (kVerifyFlags & kVerifyReads) {
500    VerifyObject(old_value);
501  }
502  if (kTransactionActive) {
503    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
504  }
505  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
506  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
507  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
508  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
509  bool success =  __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_);
510  if (success) {
511    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
512  }
513  return success;
514}
515
516}  // namespace mirror
517}  // namespace art
518
519#endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
520