xref: /aosp_15_r20/art/runtime/jni/local_reference_table.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_JNI_LOCAL_REFERENCE_TABLE_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_JNI_LOCAL_REFERENCE_TABLE_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <iosfwd>
23*795d594fSAndroid Build Coastguard Worker #include <limits>
24*795d594fSAndroid Build Coastguard Worker #include <string>
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker #include "base/bit_field.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/dchecked_vector.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
36*795d594fSAndroid Build Coastguard Worker #include "gc_root.h"
37*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table.h"
38*795d594fSAndroid Build Coastguard Worker #include "mirror/object_reference.h"
39*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
40*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker class RootInfo;
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker namespace mirror {
47*795d594fSAndroid Build Coastguard Worker class Object;
48*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker namespace jni {
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker // Maintain a table of local JNI references.
53*795d594fSAndroid Build Coastguard Worker //
54*795d594fSAndroid Build Coastguard Worker // The table contains object references that are part of the GC root set. When an object is
55*795d594fSAndroid Build Coastguard Worker // added we return an `IndirectRef` that is not a valid pointer but can be used to find the
56*795d594fSAndroid Build Coastguard Worker // original value in O(1) time. Conversions to and from local JNI references are performed
57*795d594fSAndroid Build Coastguard Worker // on upcalls and downcalls as well as in JNI functions, so they need to be very fast.
58*795d594fSAndroid Build Coastguard Worker //
59*795d594fSAndroid Build Coastguard Worker // To be efficient for JNI local variable storage, we need to provide operations that allow us to
60*795d594fSAndroid Build Coastguard Worker // operate on segments of the table, where segments are pushed and popped as if on a stack. For
61*795d594fSAndroid Build Coastguard Worker // example, deletion of an entry should only succeed if it appears in the current segment, and we
62*795d594fSAndroid Build Coastguard Worker // want to be able to strip off the current segment quickly when a method returns. Additions to the
63*795d594fSAndroid Build Coastguard Worker // table must be made in the current segment even if space is available in an earlier area.
64*795d594fSAndroid Build Coastguard Worker //
65*795d594fSAndroid Build Coastguard Worker // A new segment is created when we call into native code from managed code, or when we handle
66*795d594fSAndroid Build Coastguard Worker // the JNI PushLocalFrame function.
67*795d594fSAndroid Build Coastguard Worker //
68*795d594fSAndroid Build Coastguard Worker // The GC must be able to scan the entire table quickly.
69*795d594fSAndroid Build Coastguard Worker //
70*795d594fSAndroid Build Coastguard Worker // In summary, these must be very fast:
71*795d594fSAndroid Build Coastguard Worker //  - adding or removing a segment
72*795d594fSAndroid Build Coastguard Worker //  - adding references (always adding to the current segment)
73*795d594fSAndroid Build Coastguard Worker //  - converting a local reference back to an Object
74*795d594fSAndroid Build Coastguard Worker // These can be a little slower, but must still be pretty quick:
75*795d594fSAndroid Build Coastguard Worker //  - removing individual references
76*795d594fSAndroid Build Coastguard Worker //  - scanning the entire table straight through
77*795d594fSAndroid Build Coastguard Worker //
78*795d594fSAndroid Build Coastguard Worker // If there's more than one segment, we don't guarantee that the table will fill completely before
79*795d594fSAndroid Build Coastguard Worker // we fail due to lack of space. We do ensure that the current segment will pack tightly, which
80*795d594fSAndroid Build Coastguard Worker // should satisfy JNI requirements (e.g. EnsureLocalCapacity).
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker // To get the desired behavior for JNI locals, we need to know the bottom and top of the current
83*795d594fSAndroid Build Coastguard Worker // "segment". When we call a native method or push a local frame, the current top index gets pushed
84*795d594fSAndroid Build Coastguard Worker // on, and serves as the new bottom. When we pop a frame off, the value from the stack becomes the
85*795d594fSAndroid Build Coastguard Worker // new top index, and the value stored in the previous frame becomes the new bottom.
86*795d594fSAndroid Build Coastguard Worker //
87*795d594fSAndroid Build Coastguard Worker // If we delete entries from the middle of the list, we will be left with "holes" which we track
88*795d594fSAndroid Build Coastguard Worker // with a singly-linked list, so that they can be reused quickly. After a segment has been removed,
89*795d594fSAndroid Build Coastguard Worker // we need to prune removed free entries from the front of this singly-linked list before we can
90*795d594fSAndroid Build Coastguard Worker // reuse a free entry from the current segment. This is linear in the number of entries removed
91*795d594fSAndroid Build Coastguard Worker // and may appear as a slow reference addition but this slow down is attributable to the previous
92*795d594fSAndroid Build Coastguard Worker // removals with a constant time per removal.
93*795d594fSAndroid Build Coastguard Worker //
94*795d594fSAndroid Build Coastguard Worker // Without CheckJNI, we aim for the fastest possible implementation, so there is no error checking
95*795d594fSAndroid Build Coastguard Worker // (in release build) and stale references can be erroneously used, especially after the same slot
96*795d594fSAndroid Build Coastguard Worker // has been reused for another reference which we cannot easily detect (even in debug build).
97*795d594fSAndroid Build Coastguard Worker //
98*795d594fSAndroid Build Coastguard Worker // With CheckJNI, we rotate the slots that we use based on a "serial number".
99*795d594fSAndroid Build Coastguard Worker // This increases the memory use but it allows for decent error detection.
100*795d594fSAndroid Build Coastguard Worker //
101*795d594fSAndroid Build Coastguard Worker // We allow switching between CheckJNI enabled and disabled but entries created with CheckJNI
102*795d594fSAndroid Build Coastguard Worker // disabled shall have weaker checking even after enabling CheckJNI and the switch can also
103*795d594fSAndroid Build Coastguard Worker // prevent reusing a hole that held a reference created with a different CheckJNI setting.
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker // The state of the current segment contains the top index.
106*795d594fSAndroid Build Coastguard Worker struct LRTSegmentState {
107*795d594fSAndroid Build Coastguard Worker   uint32_t top_index;
108*795d594fSAndroid Build Coastguard Worker };
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker // Use as initial value for "cookie", and when table has only one segment.
111*795d594fSAndroid Build Coastguard Worker static constexpr LRTSegmentState kLRTFirstSegment = { 0 };
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker // Each entry in the `LocalReferenceTable` can contain a null (initially or after a `Trim()`)
114*795d594fSAndroid Build Coastguard Worker // or reference, or it can be marked as free and hold the index of the next free entry.
115*795d594fSAndroid Build Coastguard Worker // If CheckJNI is (or was) enabled, some entries can contain serial numbers instead and
116*795d594fSAndroid Build Coastguard Worker // only one other entry in a CheckJNI chunk starting with a serial number is active.
117*795d594fSAndroid Build Coastguard Worker //
118*795d594fSAndroid Build Coastguard Worker // Valid bit patterns:
119*795d594fSAndroid Build Coastguard Worker //                   33222222222211111111110000000000
120*795d594fSAndroid Build Coastguard Worker //                   10987654321098765432109876543210
121*795d594fSAndroid Build Coastguard Worker //   null:           00000000000000000000000000000000  // Only above the top index.
122*795d594fSAndroid Build Coastguard Worker //   reference:      <----- reference value ----->000  // See also `kObjectAlignment`.
123*795d594fSAndroid Build Coastguard Worker //   free:           <-------- next free --------->01
124*795d594fSAndroid Build Coastguard Worker //   serial number:  <------ serial number ------->10  // CheckJNI entry.
125*795d594fSAndroid Build Coastguard Worker // Note that serial number entries can appear only as the first entry of a 16-byte aligned
126*795d594fSAndroid Build Coastguard Worker // chunk of four entries and the serial number in the range [1, 3] specifies which of the
127*795d594fSAndroid Build Coastguard Worker // other three entries in the chunk is currently used.
128*795d594fSAndroid Build Coastguard Worker class LrtEntry {
129*795d594fSAndroid Build Coastguard Worker  public:
130*795d594fSAndroid Build Coastguard Worker   void SetReference(ObjPtr<mirror::Object> ref) REQUIRES_SHARED(Locks::mutator_lock_);
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_);
133*795d594fSAndroid Build Coastguard Worker 
IsNull()134*795d594fSAndroid Build Coastguard Worker   bool IsNull() const {
135*795d594fSAndroid Build Coastguard Worker     return root_.IsNull();
136*795d594fSAndroid Build Coastguard Worker   }
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   void SetNextFree(uint32_t next_free) REQUIRES_SHARED(Locks::mutator_lock_);
139*795d594fSAndroid Build Coastguard Worker 
GetNextFree()140*795d594fSAndroid Build Coastguard Worker   uint32_t GetNextFree() {
141*795d594fSAndroid Build Coastguard Worker     DCHECK(IsFree());
142*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsSerialNumber());
143*795d594fSAndroid Build Coastguard Worker     return NextFreeField::Decode(GetRawValue());
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker 
IsFree()146*795d594fSAndroid Build Coastguard Worker   bool IsFree() {
147*795d594fSAndroid Build Coastguard Worker     return (GetRawValue() & (1u << kFlagFree)) != 0u;
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker   void SetSerialNumber(uint32_t serial_number) REQUIRES_SHARED(Locks::mutator_lock_);
151*795d594fSAndroid Build Coastguard Worker 
GetSerialNumber()152*795d594fSAndroid Build Coastguard Worker   uint32_t GetSerialNumber() {
153*795d594fSAndroid Build Coastguard Worker     DCHECK(IsSerialNumber());
154*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsFree());
155*795d594fSAndroid Build Coastguard Worker     return GetSerialNumberUnchecked();
156*795d594fSAndroid Build Coastguard Worker   }
157*795d594fSAndroid Build Coastguard Worker 
GetSerialNumberUnchecked()158*795d594fSAndroid Build Coastguard Worker   uint32_t GetSerialNumberUnchecked() {
159*795d594fSAndroid Build Coastguard Worker     return SerialNumberField::Decode(GetRawValue());
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
IsSerialNumber()162*795d594fSAndroid Build Coastguard Worker   bool IsSerialNumber() {
163*795d594fSAndroid Build Coastguard Worker     return (GetRawValue() & (1u << kFlagSerialNumber)) != 0u;
164*795d594fSAndroid Build Coastguard Worker   }
165*795d594fSAndroid Build Coastguard Worker 
GetRootAddress()166*795d594fSAndroid Build Coastguard Worker   GcRoot<mirror::Object>* GetRootAddress() {
167*795d594fSAndroid Build Coastguard Worker     return &root_;
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
FreeListEnd()170*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t FreeListEnd() {
171*795d594fSAndroid Build Coastguard Worker     return MaxInt<uint32_t>(kFieldNextFreeBits);
172*795d594fSAndroid Build Coastguard Worker   }
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker  private:
175*795d594fSAndroid Build Coastguard Worker   // Definitions of bit fields and flags.
176*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagFree = 0u;
177*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagSerialNumber = kFlagFree + 1u;
178*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldNextFree = kFlagSerialNumber + 1u;
179*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldNextFreeBits = BitSizeOf<uint32_t>() - kFieldNextFree;
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker   using NextFreeField = BitField<uint32_t, kFieldNextFree, kFieldNextFreeBits>;
182*795d594fSAndroid Build Coastguard Worker   using SerialNumberField = NextFreeField;
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker   static_assert(kObjectAlignment > (1u << kFlagFree));
185*795d594fSAndroid Build Coastguard Worker   static_assert(kObjectAlignment > (1u << kFlagSerialNumber));
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker   void SetVRegValue(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_);
188*795d594fSAndroid Build Coastguard Worker 
GetRawValue()189*795d594fSAndroid Build Coastguard Worker   uint32_t GetRawValue() {
190*795d594fSAndroid Build Coastguard Worker     return root_.AddressWithoutBarrier()->AsVRegValue();
191*795d594fSAndroid Build Coastguard Worker   }
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   // We record the contents as a `GcRoot<>` but it is an actual `GcRoot<>` only if it's below
194*795d594fSAndroid Build Coastguard Worker   // the current segment's top index, it's not a "serial number" or inactive entry in a CheckJNI
195*795d594fSAndroid Build Coastguard Worker   // chunk, and it's not marked as "free". Such entries are never null.
196*795d594fSAndroid Build Coastguard Worker   GcRoot<mirror::Object> root_;
197*795d594fSAndroid Build Coastguard Worker };
198*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(LrtEntry) == sizeof(mirror::CompressedReference<mirror::Object>));
199*795d594fSAndroid Build Coastguard Worker // Assert that the low bits of an `LrtEntry*` are sufficient for encoding the reference kind.
200*795d594fSAndroid Build Coastguard Worker static_assert(enum_cast<uint32_t>(IndirectRefKind::kLastKind) < alignof(LrtEntry));
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker // We initially allocate local reference tables with a small number of entries, packing
204*795d594fSAndroid Build Coastguard Worker // multiple tables into a single page. If we need to expand, we double the capacity,
205*795d594fSAndroid Build Coastguard Worker // first allocating another chunk with the same number of entries as the first chunk
206*795d594fSAndroid Build Coastguard Worker // and then allocating twice as big chunk on each subsequent expansion.
207*795d594fSAndroid Build Coastguard Worker static constexpr size_t kInitialLrtBytes = 512;  // Number of bytes in an initial local table.
208*795d594fSAndroid Build Coastguard Worker static constexpr size_t kSmallLrtEntries = kInitialLrtBytes / sizeof(LrtEntry);
209*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kInitialLrtBytes));
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker static_assert(kMinPageSize % kInitialLrtBytes == 0);
212*795d594fSAndroid Build Coastguard Worker static_assert(kInitialLrtBytes % sizeof(LrtEntry) == 0);
213*795d594fSAndroid Build Coastguard Worker 
214*795d594fSAndroid Build Coastguard Worker // A minimal stopgap allocator for initial small local LRT tables.
215*795d594fSAndroid Build Coastguard Worker class SmallLrtAllocator {
216*795d594fSAndroid Build Coastguard Worker  public:
217*795d594fSAndroid Build Coastguard Worker   SmallLrtAllocator();
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker   // Allocate a small block of `LrtEntries` for the `LocalReferenceTable` table. The `size`
220*795d594fSAndroid Build Coastguard Worker   // must be a power of 2, at least `kSmallLrtEntries`, and requiring less than a page of memory.
221*795d594fSAndroid Build Coastguard Worker   LrtEntry* Allocate(size_t size, std::string* error_msg) REQUIRES(!lock_);
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker   void Deallocate(LrtEntry* unneeded, size_t size) REQUIRES(!lock_);
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker  private:
226*795d594fSAndroid Build Coastguard Worker   // Number of free lists in the allocator.
227*795d594fSAndroid Build Coastguard Worker #ifdef ART_PAGE_SIZE_AGNOSTIC
228*795d594fSAndroid Build Coastguard Worker   const size_t num_lrt_slots_ = (WhichPowerOf2(gPageSize / kInitialLrtBytes));
229*795d594fSAndroid Build Coastguard Worker #else
230*795d594fSAndroid Build Coastguard Worker   static constexpr size_t num_lrt_slots_ = (WhichPowerOf2(gPageSize / kInitialLrtBytes));
231*795d594fSAndroid Build Coastguard Worker #endif
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   size_t GetIndex(size_t size);
234*795d594fSAndroid Build Coastguard Worker 
235*795d594fSAndroid Build Coastguard Worker   // Free lists of small chunks linked through the first word.
236*795d594fSAndroid Build Coastguard Worker   dchecked_vector<void*> free_lists_;
237*795d594fSAndroid Build Coastguard Worker 
238*795d594fSAndroid Build Coastguard Worker   // Repository of MemMaps used for small LRT tables.
239*795d594fSAndroid Build Coastguard Worker   dchecked_vector<MemMap> shared_lrt_maps_;
240*795d594fSAndroid Build Coastguard Worker 
241*795d594fSAndroid Build Coastguard Worker   Mutex lock_;  // Level kGenericBottomLock; acquired before mem_map_lock_, which is a C++ mutex.
242*795d594fSAndroid Build Coastguard Worker };
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker class LocalReferenceTable {
245*795d594fSAndroid Build Coastguard Worker  public:
246*795d594fSAndroid Build Coastguard Worker   explicit LocalReferenceTable(bool check_jni);
247*795d594fSAndroid Build Coastguard Worker   ~LocalReferenceTable();
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker   // Set the CheckJNI enabled status.
250*795d594fSAndroid Build Coastguard Worker   // Called only from the Zygote post-fork callback while the process is single-threaded.
251*795d594fSAndroid Build Coastguard Worker   // Enabling CheckJNI reduces the number of entries that can be stored, thus invalidating
252*795d594fSAndroid Build Coastguard Worker   // guarantees provided by a previous call to `EnsureFreeCapacity()`.
253*795d594fSAndroid Build Coastguard Worker   void SetCheckJniEnabled(bool enabled);
254*795d594fSAndroid Build Coastguard Worker 
255*795d594fSAndroid Build Coastguard Worker   // Returns whether the CheckJNI is enabled for this `LocalReferenceTable`.
IsCheckJniEnabled()256*795d594fSAndroid Build Coastguard Worker   bool IsCheckJniEnabled() const {
257*795d594fSAndroid Build Coastguard Worker     return (free_entries_list_ & (1u << kFlagCheckJni)) != 0u;
258*795d594fSAndroid Build Coastguard Worker   }
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker   // Initialize the `LocalReferenceTable`.
261*795d594fSAndroid Build Coastguard Worker   //
262*795d594fSAndroid Build Coastguard Worker   // Max_count is the requested minimum initial capacity (resizable). The actual initial
263*795d594fSAndroid Build Coastguard Worker   // capacity can be higher to utilize all allocated memory.
264*795d594fSAndroid Build Coastguard Worker   //
265*795d594fSAndroid Build Coastguard Worker   // Returns true on success.
266*795d594fSAndroid Build Coastguard Worker   // On failure, returns false and reports error in `*error_msg`.
267*795d594fSAndroid Build Coastguard Worker   bool Initialize(size_t max_count, std::string* error_msg);
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker   // Add a new entry. The `obj` must be a valid non-null object reference. This function
270*795d594fSAndroid Build Coastguard Worker   // will return null if an error happened (with an appropriate error message set).
271*795d594fSAndroid Build Coastguard Worker   EXPORT IndirectRef Add(ObjPtr<mirror::Object> obj, std::string* error_msg)
272*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker   // Given an `IndirectRef` in the table, return the `Object` it refers to.
275*795d594fSAndroid Build Coastguard Worker   //
276*795d594fSAndroid Build Coastguard Worker   // This function may abort under error conditions in debug build.
277*795d594fSAndroid Build Coastguard Worker   // In release builds, error conditions are unchecked and the function can
278*795d594fSAndroid Build Coastguard Worker   // return old or invalid references from popped segments and deleted entries.
279*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Object> Get(IndirectRef iref) const
280*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE;
281*795d594fSAndroid Build Coastguard Worker 
282*795d594fSAndroid Build Coastguard Worker   // Updates an existing indirect reference to point to a new object.
283*795d594fSAndroid Build Coastguard Worker   // Used exclusively for updating `String` references after calling a `String` constructor.
284*795d594fSAndroid Build Coastguard Worker   void Update(IndirectRef iref, ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
285*795d594fSAndroid Build Coastguard Worker 
286*795d594fSAndroid Build Coastguard Worker   // Remove an existing entry.
287*795d594fSAndroid Build Coastguard Worker   //
288*795d594fSAndroid Build Coastguard Worker   // If the entry is not between the current top index and the bottom index
289*795d594fSAndroid Build Coastguard Worker   // specified by the cookie, we don't remove anything.  This is the behavior
290*795d594fSAndroid Build Coastguard Worker   // required by JNI's DeleteLocalRef function.
291*795d594fSAndroid Build Coastguard Worker   //
292*795d594fSAndroid Build Coastguard Worker   // Returns "false" if nothing was removed.
293*795d594fSAndroid Build Coastguard Worker   bool Remove(IndirectRef iref)
294*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   void AssertEmpty();
297*795d594fSAndroid Build Coastguard Worker 
298*795d594fSAndroid Build Coastguard Worker   void Dump(std::ostream& os) const
299*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_)
300*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::alloc_tracker_lock_);
301*795d594fSAndroid Build Coastguard Worker 
GetKind()302*795d594fSAndroid Build Coastguard Worker   IndirectRefKind GetKind() const {
303*795d594fSAndroid Build Coastguard Worker     return kLocal;
304*795d594fSAndroid Build Coastguard Worker   }
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker   // Return the number of entries in the entire table. This includes holes,
307*795d594fSAndroid Build Coastguard Worker   // and so may be larger than the actual number of "live" entries.
308*795d594fSAndroid Build Coastguard Worker   // The value corresponds to the number of entries for the current CheckJNI setting
309*795d594fSAndroid Build Coastguard Worker   // and may be wrong if there are entries created with a different CheckJNI setting.
Capacity()310*795d594fSAndroid Build Coastguard Worker   size_t Capacity() const {
311*795d594fSAndroid Build Coastguard Worker     if (IsCheckJniEnabled()) {
312*795d594fSAndroid Build Coastguard Worker       DCHECK_ALIGNED(segment_state_.top_index, kCheckJniEntriesPerReference);
313*795d594fSAndroid Build Coastguard Worker       return segment_state_.top_index / kCheckJniEntriesPerReference;
314*795d594fSAndroid Build Coastguard Worker     } else {
315*795d594fSAndroid Build Coastguard Worker       return segment_state_.top_index;
316*795d594fSAndroid Build Coastguard Worker     }
317*795d594fSAndroid Build Coastguard Worker   }
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   // Ensure that at least free_capacity elements are available, or return false.
320*795d594fSAndroid Build Coastguard Worker   // Caller ensures free_capacity > 0.
321*795d594fSAndroid Build Coastguard Worker   bool EnsureFreeCapacity(size_t free_capacity, std::string* error_msg)
322*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
323*795d594fSAndroid Build Coastguard Worker   // See implementation of EnsureFreeCapacity. We'll only state here how much is trivially free,
324*795d594fSAndroid Build Coastguard Worker   // without recovering holes. Thus this is a conservative estimate.
325*795d594fSAndroid Build Coastguard Worker   size_t FreeCapacity() const;
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   EXPORT void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
328*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
329*795d594fSAndroid Build Coastguard Worker 
PushFrame()330*795d594fSAndroid Build Coastguard Worker   LRTSegmentState PushFrame() {
331*795d594fSAndroid Build Coastguard Worker     if (kDebugLRT) {
332*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "+++ Push frame: previous state " << previous_state_.top_index << " -> "
333*795d594fSAndroid Build Coastguard Worker                 << segment_state_.top_index;
334*795d594fSAndroid Build Coastguard Worker     }
335*795d594fSAndroid Build Coastguard Worker     LRTSegmentState result = previous_state_;
336*795d594fSAndroid Build Coastguard Worker     previous_state_ = segment_state_;
337*795d594fSAndroid Build Coastguard Worker     return result;
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker 
PopFrame(LRTSegmentState previous_state)340*795d594fSAndroid Build Coastguard Worker   void PopFrame(LRTSegmentState previous_state) {
341*795d594fSAndroid Build Coastguard Worker     if (kDebugLRT) {
342*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "+++ Pop frame: current state " << segment_state_.top_index << " -> "
343*795d594fSAndroid Build Coastguard Worker                 << previous_state_.top_index << ", previous state -> " << previous_state.top_index;
344*795d594fSAndroid Build Coastguard Worker     }
345*795d594fSAndroid Build Coastguard Worker     segment_state_ = previous_state_;
346*795d594fSAndroid Build Coastguard Worker     previous_state_ = previous_state;
347*795d594fSAndroid Build Coastguard Worker   }
348*795d594fSAndroid Build Coastguard Worker 
PreviousStateOffset()349*795d594fSAndroid Build Coastguard Worker   static MemberOffset PreviousStateOffset() {
350*795d594fSAndroid Build Coastguard Worker     // Note: The `previous_state_` must be before any pointer-size-dependent members, so that
351*795d594fSAndroid Build Coastguard Worker     // `MEMBER_OFFSET()` gives the correct value even for cross-compilation.
352*795d594fSAndroid Build Coastguard Worker     return MemberOffset(OFFSETOF_MEMBER(LocalReferenceTable, previous_state_));
353*795d594fSAndroid Build Coastguard Worker   }
354*795d594fSAndroid Build Coastguard Worker 
SegmentStateOffset()355*795d594fSAndroid Build Coastguard Worker   static MemberOffset SegmentStateOffset() {
356*795d594fSAndroid Build Coastguard Worker     // Note: The `segment_state_` must be before any pointer-size-dependent members, so that
357*795d594fSAndroid Build Coastguard Worker     // `MEMBER_OFFSET()` gives the correct value even for cross-compilation.
358*795d594fSAndroid Build Coastguard Worker     return MemberOffset(OFFSETOF_MEMBER(LocalReferenceTable, segment_state_));
359*795d594fSAndroid Build Coastguard Worker   }
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker   // Release pages past the end of the table that may have previously held references.
362*795d594fSAndroid Build Coastguard Worker   void Trim() REQUIRES_SHARED(Locks::mutator_lock_);
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker   /* Reference validation for CheckJNI and debug build. */
365*795d594fSAndroid Build Coastguard Worker   bool IsValidReference(IndirectRef, /*out*/std::string* error_msg) const
366*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
367*795d594fSAndroid Build Coastguard Worker 
368*795d594fSAndroid Build Coastguard Worker  private:
369*795d594fSAndroid Build Coastguard Worker   static constexpr bool kDebugLRT = false;
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker   // Flags and fields in the `free_entries_list_`.
372*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagCheckJni = 0u;
373*795d594fSAndroid Build Coastguard Worker   // Skip a bit to have the same value range for the "first free" as the "next free" in `LrtEntry`.
374*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagPadding = kFlagCheckJni + 1u;
375*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFirstFree = kFlagPadding + 1u;
376*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFirstFreeSize = BitSizeOf<uint32_t>() - kFieldFirstFree;
377*795d594fSAndroid Build Coastguard Worker 
378*795d594fSAndroid Build Coastguard Worker   using FirstFreeField = BitField<uint32_t, kFieldFirstFree, kFieldFirstFreeSize>;
379*795d594fSAndroid Build Coastguard Worker 
380*795d594fSAndroid Build Coastguard Worker   // The value of `FirstFreeField` in `free_entries_list_` indicating the end of the free list.
381*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kFreeListEnd = LrtEntry::FreeListEnd();
382*795d594fSAndroid Build Coastguard Worker   static_assert(kFreeListEnd == MaxInt<uint32_t>(kFieldFirstFreeSize));
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker   // The value of `free_entries_list_` indicating empty free list and disabled CheckJNI.
385*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kEmptyFreeListAndCheckJniDisabled =
386*795d594fSAndroid Build Coastguard Worker       FirstFreeField::Update(kFreeListEnd, 0u);  // kFlagCheckJni not set.
387*795d594fSAndroid Build Coastguard Worker 
388*795d594fSAndroid Build Coastguard Worker   // The number of entries per reference to detect obsolete reference uses with CheckJNI enabled.
389*795d594fSAndroid Build Coastguard Worker   // The first entry serves as a serial number, one of the remaining entries can hold the actual
390*795d594fSAndroid Build Coastguard Worker   // reference or the next free index.
391*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kCheckJniEntriesPerReference = 4u;
392*795d594fSAndroid Build Coastguard Worker   static_assert(IsPowerOfTwo(kCheckJniEntriesPerReference));
393*795d594fSAndroid Build Coastguard Worker 
394*795d594fSAndroid Build Coastguard Worker   // The maximum total table size we allow.
395*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxTableSizeInBytes = 128 * MB;
396*795d594fSAndroid Build Coastguard Worker   static_assert(IsPowerOfTwo(kMaxTableSizeInBytes));
397*795d594fSAndroid Build Coastguard Worker   static_assert(IsPowerOfTwo(sizeof(LrtEntry)));
398*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxTableSize = kMaxTableSizeInBytes / sizeof(LrtEntry);
399*795d594fSAndroid Build Coastguard Worker 
ToIndirectRef(LrtEntry * entry)400*795d594fSAndroid Build Coastguard Worker   static IndirectRef ToIndirectRef(LrtEntry* entry) {
401*795d594fSAndroid Build Coastguard Worker     // The `IndirectRef` can be used to directly access the underlying `GcRoot<>`.
402*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(reinterpret_cast<GcRoot<mirror::Object>*>(entry), entry->GetRootAddress());
403*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<IndirectRef>(
404*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uintptr_t>(entry) | static_cast<uintptr_t>(kLocal));
405*795d594fSAndroid Build Coastguard Worker   }
406*795d594fSAndroid Build Coastguard Worker 
ToLrtEntry(IndirectRef iref)407*795d594fSAndroid Build Coastguard Worker   static LrtEntry* ToLrtEntry(IndirectRef iref) {
408*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(IndirectReferenceTable::GetIndirectRefKind(iref), kLocal);
409*795d594fSAndroid Build Coastguard Worker     return IndirectReferenceTable::ClearIndirectRefKind<LrtEntry*>(iref);
410*795d594fSAndroid Build Coastguard Worker   }
411*795d594fSAndroid Build Coastguard Worker 
GetTableSize(size_t table_index)412*795d594fSAndroid Build Coastguard Worker   static constexpr size_t GetTableSize(size_t table_index) {
413*795d594fSAndroid Build Coastguard Worker     // First two tables have size `kSmallLrtEntries`, then it doubles for subsequent tables.
414*795d594fSAndroid Build Coastguard Worker     return kSmallLrtEntries << (table_index != 0u ? table_index - 1u : 0u);
415*795d594fSAndroid Build Coastguard Worker   }
416*795d594fSAndroid Build Coastguard Worker 
NumTablesForSize(size_t size)417*795d594fSAndroid Build Coastguard Worker   static constexpr size_t NumTablesForSize(size_t size) {
418*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(size, kSmallLrtEntries);
419*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPowerOfTwo(size));
420*795d594fSAndroid Build Coastguard Worker     return 1u + WhichPowerOf2(size / kSmallLrtEntries);
421*795d594fSAndroid Build Coastguard Worker   }
422*795d594fSAndroid Build Coastguard Worker 
MaxSmallTables()423*795d594fSAndroid Build Coastguard Worker   static size_t MaxSmallTables() {
424*795d594fSAndroid Build Coastguard Worker     return NumTablesForSize(gPageSize / sizeof(LrtEntry));
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker 
GetEntry(size_t entry_index)427*795d594fSAndroid Build Coastguard Worker   LrtEntry* GetEntry(size_t entry_index) const {
428*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(entry_index, max_entries_);
429*795d594fSAndroid Build Coastguard Worker     if (LIKELY(small_table_ != nullptr)) {
430*795d594fSAndroid Build Coastguard Worker       DCHECK_LT(entry_index, kSmallLrtEntries);
431*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(max_entries_, kSmallLrtEntries);
432*795d594fSAndroid Build Coastguard Worker       return &small_table_[entry_index];
433*795d594fSAndroid Build Coastguard Worker     }
434*795d594fSAndroid Build Coastguard Worker     size_t table_start_index =
435*795d594fSAndroid Build Coastguard Worker         (entry_index < kSmallLrtEntries) ? 0u : TruncToPowerOfTwo(entry_index);
436*795d594fSAndroid Build Coastguard Worker     size_t table_index =
437*795d594fSAndroid Build Coastguard Worker         (entry_index < kSmallLrtEntries) ? 0u : NumTablesForSize(table_start_index);
438*795d594fSAndroid Build Coastguard Worker     LrtEntry* table = tables_[table_index];
439*795d594fSAndroid Build Coastguard Worker     return &table[entry_index - table_start_index];
440*795d594fSAndroid Build Coastguard Worker   }
441*795d594fSAndroid Build Coastguard Worker 
442*795d594fSAndroid Build Coastguard Worker   // Get the entry index for a local reference. Note that this may be higher than
443*795d594fSAndroid Build Coastguard Worker   // the current segment state. Returns maximum uint32 value if the reference does not
444*795d594fSAndroid Build Coastguard Worker   // point to one of the internal tables.
445*795d594fSAndroid Build Coastguard Worker   uint32_t GetReferenceEntryIndex(IndirectRef iref) const;
446*795d594fSAndroid Build Coastguard Worker 
GetCheckJniSerialNumberEntry(LrtEntry * entry)447*795d594fSAndroid Build Coastguard Worker   static LrtEntry* GetCheckJniSerialNumberEntry(LrtEntry* entry) {
448*795d594fSAndroid Build Coastguard Worker     return AlignDown(entry, kCheckJniEntriesPerReference * sizeof(LrtEntry));
449*795d594fSAndroid Build Coastguard Worker   }
450*795d594fSAndroid Build Coastguard Worker 
451*795d594fSAndroid Build Coastguard Worker   static uint32_t IncrementSerialNumber(LrtEntry* serial_number_entry)
452*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
453*795d594fSAndroid Build Coastguard Worker 
IsValidSerialNumber(uint32_t serial_number)454*795d594fSAndroid Build Coastguard Worker   static bool IsValidSerialNumber(uint32_t serial_number) {
455*795d594fSAndroid Build Coastguard Worker     return serial_number != 0u && serial_number < kCheckJniEntriesPerReference;
456*795d594fSAndroid Build Coastguard Worker   }
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker   // Debug mode check that the reference is valid.
459*795d594fSAndroid Build Coastguard Worker   void DCheckValidReference(IndirectRef iref) const REQUIRES_SHARED(Locks::mutator_lock_);
460*795d594fSAndroid Build Coastguard Worker 
461*795d594fSAndroid Build Coastguard Worker   // Resize the backing table to be at least `new_size` elements long. The `new_size`
462*795d594fSAndroid Build Coastguard Worker   // must be larger than the current size. After return max_entries_ >= new_size.
463*795d594fSAndroid Build Coastguard Worker   bool Resize(size_t new_size, std::string* error_msg);
464*795d594fSAndroid Build Coastguard Worker 
465*795d594fSAndroid Build Coastguard Worker   // Extract the first free index from `free_entries_list_`.
GetFirstFreeIndex()466*795d594fSAndroid Build Coastguard Worker   uint32_t GetFirstFreeIndex() const {
467*795d594fSAndroid Build Coastguard Worker     return FirstFreeField::Decode(free_entries_list_);
468*795d594fSAndroid Build Coastguard Worker   }
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker   // Remove popped free entries from the list.
471*795d594fSAndroid Build Coastguard Worker   // Called only if `free_entries_list_` points to a popped entry.
472*795d594fSAndroid Build Coastguard Worker   template <typename EntryGetter>
473*795d594fSAndroid Build Coastguard Worker   void PrunePoppedFreeEntries(EntryGetter&& get_entry);
474*795d594fSAndroid Build Coastguard Worker 
475*795d594fSAndroid Build Coastguard Worker   // Helper template function for visiting roots.
476*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
477*795d594fSAndroid Build Coastguard Worker   void VisitRootsInternal(Visitor&& visitor) const REQUIRES_SHARED(Locks::mutator_lock_);
478*795d594fSAndroid Build Coastguard Worker 
479*795d594fSAndroid Build Coastguard Worker   /// semi-public - read/write by jni down calls.
480*795d594fSAndroid Build Coastguard Worker   // These two members need to be before any pointer-size-dependent members, so that
481*795d594fSAndroid Build Coastguard Worker   // `MEMBER_OFFSET()` gives the correct value even for cross-compilation.
482*795d594fSAndroid Build Coastguard Worker   LRTSegmentState previous_state_;
483*795d594fSAndroid Build Coastguard Worker   LRTSegmentState segment_state_;
484*795d594fSAndroid Build Coastguard Worker 
485*795d594fSAndroid Build Coastguard Worker   // The maximum number of entries (modulo resizing).
486*795d594fSAndroid Build Coastguard Worker   uint32_t max_entries_;
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker   // The singly-linked list of free nodes.
489*795d594fSAndroid Build Coastguard Worker   // We use entry indexes instead of pointers and `kFreeListEnd` instead of null indicates
490*795d594fSAndroid Build Coastguard Worker   // the end of the list. See `LocalReferenceTable::GetEntry()` and `LrtEntry::GetNextFree().
491*795d594fSAndroid Build Coastguard Worker   //
492*795d594fSAndroid Build Coastguard Worker   // We use the lowest bit to record whether CheckJNI is enabled. This helps us
493*795d594fSAndroid Build Coastguard Worker   // check that the list is empty and CheckJNI is disabled in a single comparison.
494*795d594fSAndroid Build Coastguard Worker   uint32_t free_entries_list_;
495*795d594fSAndroid Build Coastguard Worker 
496*795d594fSAndroid Build Coastguard Worker   // Individual tables.
497*795d594fSAndroid Build Coastguard Worker   // As long as we have only one small table, we use `small_table_` to avoid an extra load
498*795d594fSAndroid Build Coastguard Worker   // from another heap allocated location, otherwise we set it to null and use `tables_`.
499*795d594fSAndroid Build Coastguard Worker   LrtEntry* small_table_;  // For optimizing the fast-path.
500*795d594fSAndroid Build Coastguard Worker   dchecked_vector<LrtEntry*> tables_;
501*795d594fSAndroid Build Coastguard Worker 
502*795d594fSAndroid Build Coastguard Worker   // Mem maps where we store tables allocated directly with `MemMap`
503*795d594fSAndroid Build Coastguard Worker   // rather than the `SmallLrtAllocator`.
504*795d594fSAndroid Build Coastguard Worker   dchecked_vector<MemMap> table_mem_maps_;
505*795d594fSAndroid Build Coastguard Worker };
506*795d594fSAndroid Build Coastguard Worker 
507*795d594fSAndroid Build Coastguard Worker }  // namespace jni
508*795d594fSAndroid Build Coastguard Worker }  // namespace art
509*795d594fSAndroid Build Coastguard Worker 
510*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_JNI_LOCAL_REFERENCE_TABLE_H_
511