From 5bc51bb454ba4e96e9bcbdc4106b6986a27eed6e Mon Sep 17 00:00:00 2001 From: erikcorry Date: Mon, 11 May 2015 03:57:55 -0700 Subject: [PATCH] Postpone counters triggered during GC, and use a HandleScope when calling back. R=jkummerow@chromium.org,hpayer@chromium.org BUG= Review URL: https://codereview.chromium.org/1125383007 Cr-Commit-Position: refs/heads/master@{#28335} --- include/v8.h | 1 + src/heap/heap.cc | 25 +++++++++++++++++++++++++ src/heap/heap.h | 4 ++++ src/isolate.cc | 11 +++++++++-- test/cctest/test-heap.cc | 25 +++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/include/v8.h b/include/v8.h index 910279b..3e173da 100644 --- a/include/v8.h +++ b/include/v8.h @@ -5107,6 +5107,7 @@ class V8_EXPORT Isolate { kStoreBufferOverflow = 4, kSlotsBufferOverflow = 5, kObjectObserve = 6, + kForcedGC = 7, kUseCounterFeatureCount // This enum value must be last. }; diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 54a8915..2ba75d0 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -395,6 +395,20 @@ void Heap::ReportStatisticsAfterGC() { #else if (FLAG_log_gc) new_space_.ReportStatistics(); #endif // DEBUG + for (int i = 0; i < static_cast(v8::Isolate::kUseCounterFeatureCount); + ++i) { + int count = deferred_counters_[i]; + deferred_counters_[i] = 0; + while (count > 0) { + count--; + isolate()->CountUsage(static_cast(i)); + } + } +} + + +void Heap::IncrementDeferredCount(v8::Isolate::UseCounterFeature feature) { + deferred_counters_[feature]++; } @@ -925,6 +939,11 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, tracer()->Stop(collector); } + if (collector == MARK_COMPACTOR && + (gc_callback_flags & kGCCallbackFlagForced) != 0) { + isolate()->CountUsage(v8::Isolate::kForcedGC); + } + // Start incremental marking for the next cycle. The heap snapshot // generator needs incremental marking to stay off after it aborted. if (!mark_compact_collector()->abort_incremental_marking() && @@ -5422,6 +5441,12 @@ bool Heap::SetUp() { } } + for (int i = 0; i < static_cast(v8::Isolate::kUseCounterFeatureCount); + i++) { + deferred_counters_[i] = 0; + } + + LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); LOG(isolate_, IntPtrTEvent("heap-available", Available())); diff --git a/src/heap/heap.h b/src/heap/heap.h index ff6a11e..58be0a2 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -1311,6 +1311,8 @@ class Heap { // Returns minimal interval between two subsequent collections. double get_min_in_mutator() { return min_in_mutator_; } + void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature); + MarkCompactCollector* mark_compact_collector() { return &mark_compact_collector_; } @@ -2047,6 +2049,8 @@ class Heap { // Total RegExp code ever generated double total_regexp_code_generated_; + int deferred_counters_[v8::Isolate::kUseCounterFeatureCount]; + GCTracer tracer_; // Creates and installs the full-sized number string cache. diff --git a/src/isolate.cc b/src/isolate.cc index d53d0d8..69a4f8d 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -2669,8 +2669,15 @@ void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) { void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) { - if (use_counter_callback_) { - use_counter_callback_(reinterpret_cast(this), feature); + // The counter callback may cause the embedder to call into V8, which is not + // generally possible during GC. + if (heap_.gc_state() == Heap::NOT_IN_GC) { + if (use_counter_callback_) { + HandleScope handle_scope(this); + use_counter_callback_(reinterpret_cast(this), feature); + } + } else { + heap_.IncrementDeferredCount(feature); } } diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index cb08fb4..d8c89ae 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -3203,6 +3203,31 @@ TEST(ReleaseOverReservedPages) { CHECK_EQ(1, old_space->CountTotalPages()); } +static int forced_gc_counter = 0; + +void MockUseCounterCallback(v8::Isolate* isolate, + v8::Isolate::UseCounterFeature feature) { + isolate->GetCallingContext(); + if (feature == v8::Isolate::kForcedGC) { + forced_gc_counter++; + } +} + + +TEST(CountForcedGC) { + i::FLAG_expose_gc = true; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + v8::HandleScope scope(CcTest::isolate()); + + isolate->SetUseCounterCallback(MockUseCounterCallback); + + forced_gc_counter = 0; + const char* source = "gc();"; + CompileRun(source); + CHECK_GT(forced_gc_counter, 0); +} + TEST(Regress2237) { i::FLAG_stress_compaction = false; -- 2.7.4