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