nodejs/deps/v8/test/unittests/sandbox/pointer-table-unittest.cc
Michaël Zasso 918fe04351
deps: update V8 to 13.6.233.8
PR-URL: https://github.com/nodejs/node/pull/58070
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2025-05-02 15:06:53 +02:00

100 lines
3.5 KiB
C++

// Copyright 2024 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 "src/common/globals.h"
#include "src/flags/flags.h"
#include "src/handles/handles-inl.h"
#include "src/objects/js-objects.h"
#include "src/sandbox/external-pointer-table.h"
#include "test/unittests/heap/heap-utils.h" // For ManualGCScope
#include "test/unittests/test-utils.h"
#ifdef V8_ENABLE_SANDBOX
namespace v8 {
namespace internal {
using PointerTableTest = TestWithContext;
TEST_F(PointerTableTest, ExternalPointerTableCompaction) {
// This tests ensures that pointer table compaction works as expected and
// that --stress-compaction causes us to compact the table whenever possible.
auto* iso = i_isolate();
auto* heap = iso->heap();
auto* space = heap->old_external_pointer_space();
ManualGCScope manual_gc_scope(iso);
v8_flags.stress_compaction = true;
int* external_1 = new int;
int* external_2 = new int;
{
v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(iso));
// Allocate one segment worth of external pointer table entries and keep the
// host objects in a FixedArray so they and their entries are kept alive.
uint32_t num_entries = space->freelist_length();
DirectHandle<FixedArray> array = iso->factory()->NewFixedArray(num_entries);
{
v8::HandleScope inner_scope(reinterpret_cast<v8::Isolate*>(iso));
for (uint32_t i = 0; i < num_entries; i++) {
DirectHandle<JSObject> obj =
iso->factory()->NewExternal(external_1, AllocationType::kOld);
array->set(i, *obj);
}
CHECK_EQ(0, space->freelist_length());
CHECK_EQ(1, space->NumSegmentsForTesting());
}
{
v8::HandleScope inner_scope(reinterpret_cast<v8::Isolate*>(iso));
// Allocate one additional external poiner table entry, which should now
// end up on a new segment.
CHECK_EQ(1, space->NumSegmentsForTesting());
DirectHandle<JSExternalObject> obj = Cast<JSExternalObject>(
iso->factory()->NewExternal(external_2, AllocationType::kOld));
CHECK_EQ(2, space->NumSegmentsForTesting());
// TODO(saelo): maybe it'd be nice to also automatically generate
// accessors for the underlying table handles.
ExternalPointerHandle original_handle =
obj->ReadField<ExternalPointerHandle>(JSExternalObject::kValueOffset);
// Free one entry in the array so that the table entry can be reclaimed.
array->set(0, *iso->factory()->undefined_value());
// There should be no free entries in the table yet, so nothing can be
// compacted during the first GC.
InvokeMajorGC();
CHECK_EQ(2, space->NumSegmentsForTesting());
ExternalPointerHandle current_handle =
obj->ReadField<ExternalPointerHandle>(JSExternalObject::kValueOffset);
CHECK_EQ(original_handle, current_handle);
CHECK_EQ(obj->value(), external_2);
// Now at least one entry in the first segment must be free, so compaction
// should be possible. This should leave the 2nd segment empty, causing it
// to be deallocated.
InvokeMajorGC();
CHECK_EQ(1, space->NumSegmentsForTesting());
current_handle =
obj->ReadField<ExternalPointerHandle>(JSExternalObject::kValueOffset);
CHECK_NE(original_handle, current_handle);
CHECK_EQ(obj->value(), external_2);
}
}
delete external_1;
delete external_2;
}
} // namespace internal
} // namespace v8
#endif // V8_ENABLE_SANDBOX