1// Copyright 2020 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "include/cppgc/internal/pointer-policies.h" 6 7#include "include/cppgc/internal/caged-heap-local-data.h" 8#include "include/cppgc/internal/persistent-node.h" 9#include "src/base/logging.h" 10#include "src/base/macros.h" 11#include "src/base/platform/platform.h" 12#include "src/heap/cppgc/heap-object-header.h" 13#include "src/heap/cppgc/heap-page.h" 14#include "src/heap/cppgc/heap.h" 15#include "src/heap/cppgc/page-memory.h" 16#include "src/heap/cppgc/prefinalizer-handler.h" 17#include "src/heap/cppgc/process-heap.h" 18 19namespace cppgc { 20namespace internal { 21 22namespace { 23 24#if defined(DEBUG) 25bool IsOnStack(const void* address) { 26 return v8::base::Stack::GetCurrentStackPosition() <= address && 27 address < v8::base::Stack::GetStackStart(); 28} 29#endif // defined(DEBUG) 30 31} // namespace 32 33void SameThreadEnabledCheckingPolicyBase::CheckPointerImpl( 34 const void* ptr, bool points_to_payload, bool check_off_heap_assignments) { 35 // `ptr` must not reside on stack. 36 DCHECK(!IsOnStack(ptr)); 37 // Check for the most commonly used wrong sentinel value (-1). 38 DCHECK_NE(reinterpret_cast<void*>(-1), ptr); 39 auto* base_page = BasePage::FromPayload(ptr); 40 // Large objects do not support mixins. This also means that `base_page` is 41 // valid for large objects. 42 DCHECK_IMPLIES(base_page->is_large(), points_to_payload); 43 44 // References cannot change their heap association which means that state is 45 // immutable once it is set. 46 bool is_on_heap = true; 47 if (!heap_) { 48 heap_ = &base_page->heap(); 49 if (!heap_->page_backend()->Lookup(reinterpret_cast<Address>(this))) { 50 // If `this` is not contained within the heap of `ptr`, we must deal with 51 // an on-stack or off-heap reference. For both cases there should be no 52 // heap registered. 53 is_on_heap = false; 54 CHECK(!HeapRegistry::TryFromManagedPointer(this)); 55 } 56 } 57 58 // Member references should never mix heaps. 59 DCHECK_EQ(heap_, &base_page->heap()); 60 61 DCHECK_EQ(heap_->GetCreationThreadId(), v8::base::OS::GetCurrentThreadId()); 62 63 // Header checks. 64 const HeapObjectHeader* header = nullptr; 65 if (points_to_payload) { 66 header = &HeapObjectHeader::FromObject(ptr); 67 } else { 68 // Mixin case. Access the ObjectStartBitmap atomically since sweeping can be 69 // in progress. 70 header = &base_page->ObjectHeaderFromInnerAddress<AccessMode::kAtomic>(ptr); 71 DCHECK_LE(header->ObjectStart(), ptr); 72 DCHECK_GT(header->ObjectEnd(), ptr); 73 } 74 if (header) { 75 DCHECK(!header->IsFree()); 76 } 77 78#ifdef CPPGC_VERIFY_HEAP 79 if (check_off_heap_assignments || is_on_heap) { 80 if (heap_->prefinalizer_handler()->IsInvokingPreFinalizers()) { 81 // Slot can be in a large object. 82 const auto* slot_page = BasePage::FromInnerAddress(heap_, this); 83 // Off-heap slots (from other heaps or on-stack) are considered live. 84 bool slot_is_live = 85 !slot_page || 86 slot_page->ObjectHeaderFromInnerAddress(this).IsMarked(); 87 // During prefinalizers invocation, check that if the slot is live then 88 // |ptr| refers to a live object. 89 DCHECK_IMPLIES(slot_is_live, header->IsMarked()); 90 USE(slot_is_live); 91 } 92 } 93#else 94 USE(is_on_heap); 95#endif // CPPGC_VERIFY_HEAP 96} 97 98PersistentRegion& StrongPersistentPolicy::GetPersistentRegion( 99 const void* object) { 100 return BasePage::FromPayload(object)->heap().GetStrongPersistentRegion(); 101} 102 103PersistentRegion& WeakPersistentPolicy::GetPersistentRegion( 104 const void* object) { 105 return BasePage::FromPayload(object)->heap().GetWeakPersistentRegion(); 106} 107 108CrossThreadPersistentRegion& 109StrongCrossThreadPersistentPolicy::GetPersistentRegion(const void* object) { 110 return BasePage::FromPayload(object) 111 ->heap() 112 .GetStrongCrossThreadPersistentRegion(); 113} 114 115CrossThreadPersistentRegion& 116WeakCrossThreadPersistentPolicy::GetPersistentRegion(const void* object) { 117 return BasePage::FromPayload(object) 118 ->heap() 119 .GetWeakCrossThreadPersistentRegion(); 120} 121 122} // namespace internal 123} // namespace cppgc 124