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