[sandbox] Store waiter queue node of JS Atomic.Mutex in shared table
The waiter queue node of JS Atomics.Mutex is now stored in the shared external pointer table. Bug: v8:12547 Change-Id: I2f4ce1c705d5e710b49872942702f60edf6c4043 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3721696 Reviewed-by: Shu-yu Guo <syg@chromium.org> Reviewed-by: Omer Katz <omerkatz@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Patrick Thier <pthier@chromium.org> Cr-Commit-Position: refs/heads/main@{#81380}
This commit is contained in:
parent
39f6787a19
commit
8933f9fe8e
@ -308,10 +308,10 @@ constexpr uint64_t kExternalPointerTagShift = 48;
|
||||
enum ExternalPointerTag : uint64_t {
|
||||
kExternalPointerNullTag = MAKE_TAG(0b0000000000000000),
|
||||
kExternalPointerFreeEntryTag = MAKE_TAG(0b0111111100000000),
|
||||
kWaiterQueueNodeTag = MAKE_TAG(0b1000000111111111),
|
||||
// Begin shared external object tags
|
||||
// Update kSharedExternalObjectMask and kSharedExternalObjectTag when new
|
||||
// tags are shared.
|
||||
kWaiterQueueNodeTag = MAKE_TAG(0b1000000111111111),
|
||||
kExternalStringResourceTag = MAKE_TAG(0b1000001011111111),
|
||||
kExternalStringResourceDataTag = MAKE_TAG(0b1000001101111111),
|
||||
// End shared external object tags
|
||||
@ -330,8 +330,8 @@ enum ExternalPointerTag : uint64_t {
|
||||
|
||||
// Shared external pointers can be access from shared isolates. They are stored
|
||||
// in a shared external pointer table.
|
||||
constexpr uint64_t kSharedExternalObjectMask = MAKE_TAG(0b1111111001111111);
|
||||
constexpr uint64_t kSharedExternalObjectTag = MAKE_TAG(0b1000001001111111);
|
||||
constexpr uint64_t kSharedExternalObjectMask = MAKE_TAG(0b1111110001111111);
|
||||
constexpr uint64_t kSharedExternalObjectTag = MAKE_TAG(0b1000000001111111);
|
||||
|
||||
#undef MAKE_TAG
|
||||
|
||||
|
@ -3559,7 +3559,7 @@ void Isolate::Deinit() {
|
||||
|
||||
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
external_pointer_table().TearDown();
|
||||
if (OwnsStringTables()) {
|
||||
if (owns_shareable_data()) {
|
||||
shared_external_pointer_table().TearDown();
|
||||
delete isolate_data_.shared_external_pointer_table_;
|
||||
isolate_data_.shared_external_pointer_table_ = nullptr;
|
||||
@ -4120,7 +4120,7 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
|
||||
|
||||
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
external_pointer_table().Init(this);
|
||||
if (OwnsStringTables()) {
|
||||
if (owns_shareable_data()) {
|
||||
isolate_data_.shared_external_pointer_table_ = new ExternalPointerTable();
|
||||
shared_external_pointer_table().Init(this);
|
||||
} else {
|
||||
@ -5762,19 +5762,18 @@ void Isolate::DetachFromSharedIsolate() {
|
||||
ExternalPointer_t Isolate::EncodeWaiterQueueNodeAsExternalPointer(
|
||||
Address node) {
|
||||
DCHECK_NE(kNullAddress, node);
|
||||
Isolate* shared = shared_isolate();
|
||||
uint32_t index;
|
||||
ExternalPointer_t ext;
|
||||
if (waiter_queue_node_external_pointer_.IsJust()) {
|
||||
ext = waiter_queue_node_external_pointer_.FromJust();
|
||||
index = ext >> kExternalPointerIndexShift;
|
||||
} else {
|
||||
index = shared->external_pointer_table().Allocate();
|
||||
index = shared_external_pointer_table().Allocate();
|
||||
ext = index << kExternalPointerIndexShift;
|
||||
waiter_queue_node_external_pointer_ = Just(ext);
|
||||
}
|
||||
DCHECK_NE(0, index);
|
||||
shared->external_pointer_table().Set(index, node, kWaiterQueueNodeTag);
|
||||
shared_external_pointer_table().Set(index, node, kWaiterQueueNodeTag);
|
||||
return ext;
|
||||
}
|
||||
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
|
@ -2002,10 +2002,14 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
DCHECK_NULL(shared_isolate_);
|
||||
DCHECK(!attached_to_shared_isolate_);
|
||||
shared_isolate_ = shared_isolate;
|
||||
owns_shareable_data_ = false;
|
||||
}
|
||||
|
||||
GlobalSafepoint* global_safepoint() const { return global_safepoint_.get(); }
|
||||
|
||||
bool owns_shareable_data() { return owns_shareable_data_; }
|
||||
// TODO(pthier): Unify with owns_shareable_data() once the flag
|
||||
// --shared-string-table is removed.
|
||||
bool OwnsStringTables() { return !FLAG_shared_string_table || is_shared(); }
|
||||
|
||||
#if USE_SIMULATOR
|
||||
@ -2271,6 +2275,10 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
// favor memory over runtime performance.
|
||||
bool memory_savings_mode_active_ = false;
|
||||
|
||||
// Indicates wether the isolate owns shareable data.
|
||||
// Only false for client isolates attached to a shared isolate.
|
||||
bool owns_shareable_data_ = true;
|
||||
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
// Base address of the pointer compression cage containing external code
|
||||
// space, when external code space is enabled.
|
||||
|
@ -2083,11 +2083,11 @@ void MarkCompactCollector::MarkObjectsFromClientHeaps() {
|
||||
// Custom marking for the external pointer table entry used to hold
|
||||
// client Isolates' WaiterQueueNode, which is used by JS mutexes and
|
||||
// condition variables.
|
||||
DCHECK(!IsExternalPointerTagShareable(kWaiterQueueNodeTag));
|
||||
DCHECK(IsExternalPointerTagShareable(kWaiterQueueNodeTag));
|
||||
ExternalPointer_t waiter_queue_ext;
|
||||
if (client->GetWaiterQueueNodeExternalPointer().To(&waiter_queue_ext)) {
|
||||
uint32_t index = waiter_queue_ext >> kExternalPointerIndexShift;
|
||||
client->shared_isolate()->external_pointer_table().Mark(index);
|
||||
client->shared_external_pointer_table().Mark(index);
|
||||
}
|
||||
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
});
|
||||
@ -2747,7 +2747,7 @@ void MarkCompactCollector::ClearNonLiveReferences() {
|
||||
TRACE_GC(heap()->tracer(),
|
||||
GCTracer::Scope::MC_SWEEP_EXTERNAL_POINTER_TABLE);
|
||||
isolate()->external_pointer_table().Sweep(isolate());
|
||||
if (isolate()->OwnsStringTables()) {
|
||||
if (isolate()->owns_shareable_data()) {
|
||||
isolate()->shared_external_pointer_table().Sweep(isolate());
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace detail {
|
||||
// list per waiter (i.e. mutex or condition variable). There is a per-thread
|
||||
// node allocated on the stack when the thread goes to sleep during waiting. In
|
||||
// the case of sandboxed pointers, the access to the on-stack node is indirected
|
||||
// through the shared Isolate's external pointer table.
|
||||
// through the shared external pointer table.
|
||||
class V8_NODISCARD WaiterQueueNode final {
|
||||
public:
|
||||
template <typename T>
|
||||
@ -47,14 +47,13 @@ class V8_NODISCARD WaiterQueueNode final {
|
||||
static WaiterQueueNode* DestructivelyDecodeHead(Isolate* requester,
|
||||
typename T::StateT state) {
|
||||
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
Isolate* shared_isolate = requester->shared_isolate();
|
||||
ExternalPointer_t ptr =
|
||||
static_cast<ExternalPointer_t>(state & T::kWaiterQueueHeadMask);
|
||||
if (ptr == 0) return nullptr;
|
||||
// The external pointer is cleared after decoding to prevent reuse by
|
||||
// multiple mutexes in case of heap corruption.
|
||||
return reinterpret_cast<WaiterQueueNode*>(DecodeAndClearExternalPointer(
|
||||
shared_isolate, ptr, kWaiterQueueNodeTag));
|
||||
return reinterpret_cast<WaiterQueueNode*>(
|
||||
DecodeAndClearExternalPointer(requester, ptr, kWaiterQueueNodeTag));
|
||||
#else
|
||||
return base::bit_cast<WaiterQueueNode*>(state & T::kWaiterQueueHeadMask);
|
||||
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
|
Loading…
Reference in New Issue
Block a user