heap: Rework forced GCs

Forced GCs can either be invoked internally or communicate the fact that
they are forced externally via API. Before this CL, all uses were
passing kGCCallbackFlagForced to indicate that the GC was forced.

This flag is used by embedders though to trigger followup actions. E.g.,
it can be used to trigger a follow up call to
GarbageCollectionForTesting() call which requires --expose-gc.

This patch changes the semantics as follows:
- Internal forced GCs use a Heap GC flag (kForcedGC)
- External forced GCs and GC extension use kGCCallbackFlagForced

Bug: chromium:1074061
Change-Id: Ide7ea0ccdf88b8c8cac002289aef5b7eb0f9748c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2172747
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67498}
This commit is contained in:
Michael Lippautz 2020-04-29 17:14:31 +02:00 committed by Commit Bot
parent 3afa7cf0d3
commit fe0c91cb6c
6 changed files with 17 additions and 15 deletions

View File

@ -534,8 +534,7 @@ bool CompilationDependencies::Commit(Handle<Code> code) {
// that triggers its deoptimization. // that triggers its deoptimization.
if (FLAG_stress_gc_during_compilation) { if (FLAG_stress_gc_during_compilation) {
broker_->isolate()->heap()->PreciseCollectAllGarbage( broker_->isolate()->heap()->PreciseCollectAllGarbage(
Heap::kNoGCFlags, GarbageCollectionReason::kTesting, Heap::kForcedGC, GarbageCollectionReason::kTesting, kNoGCCallbackFlags);
kGCCallbackFlagForced);
} }
#ifdef DEBUG #ifdef DEBUG
for (auto dep : dependencies_) { for (auto dep : dependencies_) {

View File

@ -1380,16 +1380,15 @@ void Heap::CollectAllAvailableGarbage(GarbageCollectionReason gc_reason) {
// The optimizing compiler may be unnecessarily holding on to memory. // The optimizing compiler may be unnecessarily holding on to memory.
isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock); isolate()->AbortConcurrentOptimization(BlockingBehavior::kDontBlock);
isolate()->ClearSerializerData(); isolate()->ClearSerializerData();
set_current_gc_flags(kReduceMemoryFootprintMask); set_current_gc_flags(
kReduceMemoryFootprintMask |
(gc_reason == GarbageCollectionReason::kLowMemoryNotification ? kForcedGC
: 0));
isolate_->compilation_cache()->Clear(); isolate_->compilation_cache()->Clear();
const int kMaxNumberOfAttempts = 7; const int kMaxNumberOfAttempts = 7;
const int kMinNumberOfAttempts = 2; const int kMinNumberOfAttempts = 2;
const v8::GCCallbackFlags callback_flags =
gc_reason == GarbageCollectionReason::kLowMemoryNotification
? v8::kGCCallbackFlagForced
: v8::kGCCallbackFlagCollectAllAvailableGarbage;
for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
if (!CollectGarbage(OLD_SPACE, gc_reason, callback_flags) && if (!CollectGarbage(OLD_SPACE, gc_reason, kNoGCCallbackFlags) &&
attempt + 1 >= kMinNumberOfAttempts) { attempt + 1 >= kMinNumberOfAttempts) {
break; break;
} }
@ -1512,7 +1511,8 @@ bool Heap::CollectGarbage(AllocationSpace space,
const v8::GCCallbackFlags gc_callback_flags) { const v8::GCCallbackFlags gc_callback_flags) {
const char* collector_reason = nullptr; const char* collector_reason = nullptr;
GarbageCollector collector = SelectGarbageCollector(space, &collector_reason); GarbageCollector collector = SelectGarbageCollector(space, &collector_reason);
is_current_gc_forced_ = gc_callback_flags & v8::kGCCallbackFlagForced; is_current_gc_forced_ = gc_callback_flags & v8::kGCCallbackFlagForced ||
current_gc_flags_ & kForcedGC;
DevToolsTraceEventScope devtools_trace_event_scope( DevToolsTraceEventScope devtools_trace_event_scope(
this, IsYoungGenerationCollector(collector) ? "MinorGC" : "MajorGC", this, IsYoungGenerationCollector(collector) ? "MinorGC" : "MajorGC",

View File

@ -300,6 +300,9 @@ class Heap {
static const int kNoGCFlags = 0; static const int kNoGCFlags = 0;
static const int kReduceMemoryFootprintMask = 1; static const int kReduceMemoryFootprintMask = 1;
// GCs that are forced, either through testing configurations (requring
// --expose-gc) or through DevTools (using LowMemoryNotificaton).
static const int kForcedGC = 2;
// The minimum size of a HeapObject on the heap. // The minimum size of a HeapObject on the heap.
static const int kMinObjectSizeInTaggedWords = 2; static const int kMinObjectSizeInTaggedWords = 2;

View File

@ -265,8 +265,8 @@ auto Engine::make(own<Config>&& config) -> own<Engine> {
StoreImpl::~StoreImpl() { StoreImpl::~StoreImpl() {
#ifdef DEBUG #ifdef DEBUG
reinterpret_cast<i::Isolate*>(isolate_)->heap()->PreciseCollectAllGarbage( reinterpret_cast<i::Isolate*>(isolate_)->heap()->PreciseCollectAllGarbage(
i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting, i::Heap::kForcedGC, i::GarbageCollectionReason::kTesting,
v8::kGCCallbackFlagForced); v8::kNoGCCallbackFlags);
#endif #endif
context()->Exit(); context()->Exit();
isolate_->Dispose(); isolate_->Dispose();

View File

@ -26850,8 +26850,8 @@ static void CallIsolate2(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Local<v8::Context>::New(isolate_2, context_2); v8::Local<v8::Context>::New(isolate_2, context_2);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
reinterpret_cast<i::Isolate*>(isolate_2)->heap()->CollectAllGarbage( reinterpret_cast<i::Isolate*>(isolate_2)->heap()->CollectAllGarbage(
i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting, i::Heap::kForcedGC, i::GarbageCollectionReason::kTesting,
v8::kGCCallbackFlagForced); v8::kNoGCCallbackFlags);
CompileRun("f2() //# sourceURL=isolate2b"); CompileRun("f2() //# sourceURL=isolate2b");
} }

View File

@ -31,8 +31,8 @@ own<Trap> Stage4_GC(void* env, const Val args[], Val results[]) {
printf("Stage4...\n"); printf("Stage4...\n");
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env);
isolate->heap()->PreciseCollectAllGarbage( isolate->heap()->PreciseCollectAllGarbage(
i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting, i::Heap::kForcedGC, i::GarbageCollectionReason::kTesting,
v8::kGCCallbackFlagForced); v8::kNoGCCallbackFlags);
results[0] = Val::i32(args[0].i32() + 1); results[0] = Val::i32(args[0].i32() + 1);
return nullptr; return nullptr;
} }