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
|
// 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.
#ifndef V8_SANDBOX_EXTERNAL_POINTER_INL_H_
#define V8_SANDBOX_EXTERNAL_POINTER_INL_H_
#include "include/v8-internal.h"
#include "src/base/atomic-utils.h"
#include "src/execution/isolate.h"
#include "src/sandbox/external-pointer-table-inl.h"
#include "src/sandbox/external-pointer.h"
namespace v8 {
namespace internal {
#ifdef V8_ENABLE_SANDBOX
template <ExternalPointerTag tag>
const ExternalPointerTable& GetExternalPointerTable(const Isolate* isolate) {
return IsSharedExternalPointerType(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
template <ExternalPointerTag tag>
ExternalPointerTable& GetExternalPointerTable(Isolate* isolate) {
return IsSharedExternalPointerType(tag)
? isolate->shared_external_pointer_table()
: isolate->external_pointer_table();
}
#endif // V8_ENABLE_SANDBOX
template <ExternalPointerTag tag>
V8_INLINE void InitExternalPointerField(Address field_address, Isolate* isolate,
Address value) {
#ifdef V8_ENABLE_SANDBOX
if (IsSandboxedExternalPointerType(tag)) {
ExternalPointerTable& table = GetExternalPointerTable<tag>(isolate);
ExternalPointerHandle handle =
table.AllocateAndInitializeEntry(isolate, value, tag);
// Use a Release_Store to ensure that the store of the pointer into the
// table is not reordered after the store of the handle. Otherwise, other
// threads may access an uninitialized table entry and crash.
auto location = reinterpret_cast<ExternalPointerHandle*>(field_address);
base::AsAtomic32::Release_Store(location, handle);
return;
}
#endif // V8_ENABLE_SANDBOX
WriteExternalPointerField<tag>(field_address, isolate, value);
}
template <ExternalPointerTag tag>
V8_INLINE Address ReadExternalPointerField(Address field_address,
const Isolate* isolate) {
#ifdef V8_ENABLE_SANDBOX
if (IsSandboxedExternalPointerType(tag)) {
// Handles may be written to objects from other threads so the handle needs
// to be loaded atomically. We assume that the load from the table cannot
// be reordered before the load of the handle due to the data dependency
// between the two loads and therefore use relaxed memory ordering.
auto location = reinterpret_cast<ExternalPointerHandle*>(field_address);
ExternalPointerHandle handle = base::AsAtomic32::Relaxed_Load(location);
return GetExternalPointerTable<tag>(isolate).Get(handle, tag);
}
#endif // V8_ENABLE_SANDBOX
return ReadMaybeUnalignedValue<Address>(field_address);
}
template <ExternalPointerTag tag>
V8_INLINE void WriteExternalPointerField(Address field_address,
Isolate* isolate, Address value) {
#ifdef V8_ENABLE_SANDBOX
if (IsSandboxedExternalPointerType(tag)) {
// See comment above for why this is a Relaxed_Load.
auto location = reinterpret_cast<ExternalPointerHandle*>(field_address);
ExternalPointerHandle handle = base::AsAtomic32::Relaxed_Load(location);
GetExternalPointerTable<tag>(isolate).Set(handle, value, tag);
return;
}
#endif // V8_ENABLE_SANDBOX
WriteMaybeUnalignedValue<Address>(field_address, value);
}
template <ExternalPointerTag tag>
V8_INLINE void WriteLazilyInitializedExternalPointerField(Address field_address,
Isolate* isolate,
Address value) {
#ifdef V8_ENABLE_SANDBOX
if (IsSandboxedExternalPointerType(tag)) {
// See comment above for why this uses a Relaxed_Load and Release_Store.
ExternalPointerTable& table = GetExternalPointerTable<tag>(isolate);
auto location = reinterpret_cast<ExternalPointerHandle*>(field_address);
ExternalPointerHandle handle = base::AsAtomic32::Relaxed_Load(location);
if (handle == kNullExternalPointerHandle) {
// Field has not been initialized yet.
ExternalPointerHandle handle =
table.AllocateAndInitializeEntry(isolate, value, tag);
base::AsAtomic32::Release_Store(location, handle);
} else {
table.Set(handle, value, tag);
}
return;
}
#endif // V8_ENABLE_SANDBOX
WriteMaybeUnalignedValue<Address>(field_address, value);
}
} // namespace internal
} // namespace v8
#endif // V8_SANDBOX_EXTERNAL_POINTER_INL_H_
|