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