• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 namespace cppgc {
20 namespace internal {
21 
22 namespace {
23 
24 #if defined(DEBUG)
IsOnStack(const void * address)25 bool 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 
CheckPointerImpl(const void * ptr,bool points_to_payload,bool check_off_heap_assignments)33 void 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 
GetPersistentRegion(const void * object)98 PersistentRegion& StrongPersistentPolicy::GetPersistentRegion(
99     const void* object) {
100   return BasePage::FromPayload(object)->heap().GetStrongPersistentRegion();
101 }
102 
GetPersistentRegion(const void * object)103 PersistentRegion& WeakPersistentPolicy::GetPersistentRegion(
104     const void* object) {
105   return BasePage::FromPayload(object)->heap().GetWeakPersistentRegion();
106 }
107 
108 CrossThreadPersistentRegion&
GetPersistentRegion(const void * object)109 StrongCrossThreadPersistentPolicy::GetPersistentRegion(const void* object) {
110   return BasePage::FromPayload(object)
111       ->heap()
112       .GetStrongCrossThreadPersistentRegion();
113 }
114 
115 CrossThreadPersistentRegion&
GetPersistentRegion(const void * object)116 WeakCrossThreadPersistentPolicy::GetPersistentRegion(const void* object) {
117   return BasePage::FromPayload(object)
118       ->heap()
119       .GetWeakCrossThreadPersistentRegion();
120 }
121 
122 }  // namespace internal
123 }  // namespace cppgc
124