array.h revision 4e2cb098017bf073335ebb02b1bc0a36828cd720
12dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers/*
22dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Copyright (C) 2011 The Android Open Source Project
32dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers *
42dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
52dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * you may not use this file except in compliance with the License.
62dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * You may obtain a copy of the License at
72dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers *
82dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
92dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers *
102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Unless required by applicable law or agreed to in writing, software
112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
122dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * See the License for the specific language governing permissions and
142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * limitations under the License.
152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers */
162dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_MIRROR_ARRAY_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_MIRROR_ARRAY_H_
192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
2094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi#include "gc_root.h"
21b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "gc/allocator_type.h"
222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "object.h"
2383c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier#include "object_callbacks.h"
242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace art {
26b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
27eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartiertemplate<class T> class Handle;
28b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror {
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersclass MANAGED Array : public Object {
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers public:
3398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // The size of a java.lang.Class representing an array.
34e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  static uint32_t ClassSize(size_t pointer_size);
3598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
36f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi  // Allocates an array with the given properties, if kFillUsable is true the array will be of at
376fac447555dc94a935b78198479cce645c837b89Ian Rogers  // least component_count size, however, if there's usable space at the end of the allocation the
386fac447555dc94a935b78198479cce645c837b89Ian Rogers  // array will fill it.
39f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi  template <bool kIsInstrumented, bool kFillUsable = false>
40f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi  ALWAYS_INLINE static Array* Alloc(Thread* self, Class* array_class, int32_t component_count,
41f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi                                    size_t component_size_shift, gc::AllocatorType allocator_type)
424e2cb098017bf073335ebb02b1bc0a36828cd720Mathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
440cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier  static Array* CreateMultiArray(Thread* self, Handle<Class> element_class,
450cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier                                 Handle<IntArray> dimensions)
464e2cb098017bf073335ebb02b1bc0a36828cd720Mathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
486e83c172f385cb45dd13bbcf41d2df8e410828c6Hiroshi Yamauchi  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
496e83c172f385cb45dd13bbcf41d2df8e410828c6Hiroshi Yamauchi           ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
5090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  size_t SizeOf() SHARED_REQUIRES(Locks::mutator_lock_);
514e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
5290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  ALWAYS_INLINE int32_t GetLength() SHARED_REQUIRES(Locks::mutator_lock_) {
53b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Array, length_));
542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
5690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void SetLength(int32_t length) SHARED_REQUIRES(Locks::mutator_lock_) {
57c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    DCHECK_GE(length, 0);
58d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // We use non transactional version since we can't undo this write. We also disable checking
59d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // since it would fail during a transaction.
60b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers    SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length);
612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
632dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static MemberOffset LengthOffset() {
642dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    return OFFSET_OF_OBJECT_MEMBER(Array, length_);
652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
662dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
677e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  static MemberOffset DataOffset(size_t component_size);
682dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
69ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void* GetRawData(size_t component_size, int32_t index)
7090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
71ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
72ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        + (index * component_size);
732dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    return reinterpret_cast<void*>(data);
742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
752dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
76ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetRawData(size_t component_size, int32_t index) const {
77ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
78ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        + (index * component_size);
79ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return reinterpret_cast<void*>(data);
802dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
82abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz  // Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and
83abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz  // returns false.
844e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
8590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) SHARED_REQUIRES(Locks::mutator_lock_);
862dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
874e2cb098017bf073335ebb02b1bc0a36828cd720Mathieu Chartier  Array* CopyOf(Thread* self, int32_t new_length) SHARED_REQUIRES(Locks::mutator_lock_)
884e2cb098017bf073335ebb02b1bc0a36828cd720Mathieu Chartier      REQUIRES(!Roles::uninterruptible_);
89e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers protected:
9190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void ThrowArrayStoreException(Object* object) SHARED_REQUIRES(Locks::mutator_lock_);
922dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers private:
94ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void ThrowArrayIndexOutOfBoundsException(int32_t index)
9590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
96abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz
972dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  // The number of array elements.
982dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int32_t length_;
992dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  // Marker for the data (used by generated code)
1002dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  uint32_t first_element_[0];
1012dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
1022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  DISALLOW_IMPLICIT_CONSTRUCTORS(Array);
1032dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers};
1042dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
105b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogerstemplate<typename T>
1062dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersclass MANAGED PrimitiveArray : public Array {
1072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers public:
1082dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  typedef T ElementType;
1092dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
1102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
1114e2cb098017bf073335ebb02b1bc0a36828cd720Mathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
1122dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
11390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  const T* GetData() const ALWAYS_INLINE  SHARED_REQUIRES(Locks::mutator_lock_) {
114ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return reinterpret_cast<const T*>(GetRawData(sizeof(T), 0));
1152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
1162dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
11790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  T* GetData() ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
118ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return reinterpret_cast<T*>(GetRawData(sizeof(T), 0));
1192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
1202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
12190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  T Get(int32_t i) ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_);
122abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz
12390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  T GetWithoutChecks(int32_t i) ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_) {
124abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz    DCHECK(CheckIsValidIndex(i));
1252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    return GetData()[i];
1262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
1272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
12890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void Set(int32_t i, T value) ALWAYS_INLINE SHARED_REQUIRES(Locks::mutator_lock_);
129d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
130d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO fix thread safety analysis broken by the use of template. This should be
13190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  // SHARED_REQUIRES(Locks::mutator_lock_).
132d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  template<bool kTransactionActive, bool kCheckTransaction = true>
133b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers  void Set(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
1342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
135d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO fix thread safety analysis broken by the use of template. This should be
13690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  // SHARED_REQUIRES(Locks::mutator_lock_).
1373b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe  template<bool kTransactionActive,
1383b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe           bool kCheckTransaction = true,
1393b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe           VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
140b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers  void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
141abff6439db28fbbed95490bfff7e24d1fdf5b771Sebastien Hertz
142ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  /*
143ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * Works like memmove(), except we guarantee not to allow tearing of array values (ie using
144ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * smaller than element size copies). Arguments are assumed to be within the bounds of the array
145ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * and the arrays non-null.
146ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   */
147ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
14890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
149ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
150ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  /*
151ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * Works like memcpy(), except we guarantee not to allow tearing of array values (ie using
152ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * smaller than element size copies). Arguments are assumed to be within the bounds of the array
153ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   * and the arrays non-null.
154ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers   */
155ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
15690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
157ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
1582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void SetArrayClass(Class* array_class) {
15994f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    CHECK(array_class_.IsNull());
1602d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers    CHECK(array_class != nullptr);
16194f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    array_class_ = GcRoot<Class>(array_class);
1622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
1632dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
16490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  static Class* GetArrayClass() SHARED_REQUIRES(Locks::mutator_lock_) {
16594f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    DCHECK(!array_class_.IsNull());
16694f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    return array_class_.Read();
1672d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers  }
1682d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers
1692dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void ResetArrayClass() {
17094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    CHECK(!array_class_.IsNull());
17194f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    array_class_ = GcRoot<Class>(nullptr);
1722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  }
1732dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
17490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  static void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
175c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier
1762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers private:
17794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi  static GcRoot<Class> array_class_;
1782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
1792dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
1802dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers};
1812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
182e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier// Either an IntArray or a LongArray.
183e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierclass PointerArray : public Array {
184e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier public:
185e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  template<typename T>
186e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  T GetElementPtrSize(uint32_t idx, size_t ptr_size)
18790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
188e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
189e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  template<bool kTransactionActive = false, bool kUnchecked = false, typename T>
190e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void SetElementPtrSize(uint32_t idx, T element, size_t ptr_size)
19190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
192e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier};
193e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
1942dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers}  // namespace mirror
1952dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers}  // namespace art
1962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
197fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_MIRROR_ARRAY_H_
198