[heap] fix invocation of NearHeapLimitCallback
This patch makes sure that NearHeapLimitCallback can invoke operations that trigger garbage collections. In addition this adds code to make the tracers aware of NearHeapLimitCallback. Bug: v8:12777 Change-Id: I959a23a3e0224ba536cb18b14933813e56fc5292 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3575468 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Joyee Cheung <joyee@igalia.com> Cr-Commit-Position: refs/heads/main@{#79934}
This commit is contained in:
parent
26d6f9ebcc
commit
4c29cf1b78
@ -4342,6 +4342,9 @@ void Heap::AutomaticallyRestoreInitialHeapLimit(double threshold_percent) {
|
||||
|
||||
bool Heap::InvokeNearHeapLimitCallback() {
|
||||
if (near_heap_limit_callbacks_.size() > 0) {
|
||||
AllowGarbageCollection allow_gc;
|
||||
TRACE_GC(tracer(), GCTracer::Scope::HEAP_EXTERNAL_NEAR_HEAP_LIMIT);
|
||||
VMState<EXTERNAL> callback_state(isolate());
|
||||
HandleScope scope(isolate());
|
||||
v8::NearHeapLimitCallback callback =
|
||||
near_heap_limit_callbacks_.back().first;
|
||||
|
@ -527,6 +527,7 @@
|
||||
F(HEAP_EPILOGUE_REDUCE_NEW_SPACE) \
|
||||
F(HEAP_EPILOGUE_SAFEPOINT) \
|
||||
F(HEAP_EXTERNAL_EPILOGUE) \
|
||||
F(HEAP_EXTERNAL_NEAR_HEAP_LIMIT) \
|
||||
F(HEAP_EXTERNAL_PROLOGUE) \
|
||||
F(HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES) \
|
||||
F(HEAP_PROLOGUE) \
|
||||
|
@ -1272,6 +1272,62 @@ UNINITIALIZED_TEST(Regress10843) {
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
size_t near_heap_limit_invocation_count = 0;
|
||||
size_t InvokeGCNearHeapLimitCallback(void* data, size_t current_heap_limit,
|
||||
size_t initial_heap_limit) {
|
||||
near_heap_limit_invocation_count++;
|
||||
if (near_heap_limit_invocation_count > 1) {
|
||||
// We are already in a GC triggered in this callback, raise the limit
|
||||
// to avoid an OOM.
|
||||
return current_heap_limit * 5;
|
||||
}
|
||||
|
||||
DCHECK_EQ(near_heap_limit_invocation_count, 1);
|
||||
// Operations that may cause GC (e.g. taking heap snapshots) in the
|
||||
// near heap limit callback should not hit the AllowGarbageCollection
|
||||
// assertion.
|
||||
static_cast<v8::Isolate*>(data)->GetHeapProfiler()->TakeHeapSnapshot();
|
||||
return current_heap_limit * 5;
|
||||
}
|
||||
|
||||
UNINITIALIZED_TEST(Regress12777) {
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.constraints.set_max_old_generation_size_in_bytes(10 * i::MB);
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
|
||||
isolate->AddNearHeapLimitCallback(InvokeGCNearHeapLimitCallback, isolate);
|
||||
|
||||
{
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
|
||||
Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
|
||||
// Allocate data to trigger the NearHeapLimitCallback.
|
||||
HandleScope scope(i_isolate);
|
||||
int length = 2 * i::MB / i::kTaggedSize;
|
||||
std::vector<Handle<FixedArray>> arrays;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
arrays.push_back(i_isolate->factory()->NewFixedArray(length));
|
||||
}
|
||||
CcTest::CollectAllGarbage(i_isolate);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
arrays.push_back(i_isolate->factory()->NewFixedArray(length));
|
||||
}
|
||||
CcTest::CollectAllGarbage(i_isolate);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
arrays.push_back(i_isolate->factory()->NewFixedArray(length));
|
||||
}
|
||||
|
||||
// The work done above should trigger the heap limit callback at least
|
||||
// twice to prove that the callback can raise the limit in the second
|
||||
// or later calls to avoid an OOM.
|
||||
CHECK_GE(near_heap_limit_invocation_count, 2);
|
||||
}
|
||||
|
||||
isolate->GetHeapProfiler()->DeleteAllHeapSnapshots();
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
#ifndef V8_LITE_MODE
|
||||
|
||||
TEST(TestOptimizeAfterBytecodeFlushingCandidate) {
|
||||
|
Loading…
Reference in New Issue
Block a user