From: dcarney@chromium.org Date: Tue, 17 Sep 2013 12:37:22 +0000 (+0000) Subject: new gc callbacks with isolate parameters X-Git-Tag: upstream/4.7.83~12454 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f34340033e4fc3aa88a15aa952663dc00235e7fd;p=platform%2Fupstream%2Fv8.git new gc callbacks with isolate parameters R=svenpanne@chromium.org BUG= Review URL: https://codereview.chromium.org/24065005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16770 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/include/v8.h b/include/v8.h index 92bfa45..79f4478 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3871,8 +3871,6 @@ enum GCCallbackFlags { typedef void (*GCPrologueCallback)(GCType type, GCCallbackFlags flags); typedef void (*GCEpilogueCallback)(GCType type, GCCallbackFlags flags); -typedef void (*GCCallback)(); - /** * Collection of V8 heap information. @@ -4056,6 +4054,51 @@ class V8_EXPORT Isolate { void SetReference(const Persistent& parent, const Persistent& child); + typedef void (*GCPrologueCallback)(Isolate* isolate, + GCType type, + GCCallbackFlags flags); + typedef void (*GCEpilogueCallback)(Isolate* isolate, + GCType type, + GCCallbackFlags flags); + + /** + * Enables the host application to receive a notification before a + * garbage collection. Allocations are not allowed in the + * callback function, you therefore cannot manipulate objects (set + * or delete properties for example) since it is possible such + * operations will result in the allocation of objects. It is possible + * to specify the GCType filter for your callback. But it is not possible to + * register the same callback function two times with different + * GCType filters. + */ + void AddGCPrologueCallback( + GCPrologueCallback callback, GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes callback which was installed by + * AddGCPrologueCallback function. + */ + void RemoveGCPrologueCallback(GCPrologueCallback callback); + + /** + * Enables the host application to receive a notification after a + * garbage collection. Allocations are not allowed in the + * callback function, you therefore cannot manipulate objects (set + * or delete properties for example) since it is possible such + * operations will result in the allocation of objects. It is possible + * to specify the GCType filter for your callback. But it is not possible to + * register the same callback function two times with different + * GCType filters. + */ + void AddGCEpilogueCallback( + GCEpilogueCallback callback, GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes callback which was installed by + * AddGCEpilogueCallback function. + */ + void RemoveGCEpilogueCallback(GCEpilogueCallback callback); + private: Isolate(); Isolate(const Isolate&); @@ -4413,16 +4456,6 @@ class V8_EXPORT V8 { static void RemoveGCPrologueCallback(GCPrologueCallback callback); /** - * The function is deprecated. Please use AddGCPrologueCallback instead. - * Enables the host application to receive a notification before a - * garbage collection. Allocations are not allowed in the - * callback function, you therefore cannot manipulate objects (set - * or delete properties for example) since it is possible such - * operations will result in the allocation of objects. - */ - V8_DEPRECATED(static void SetGlobalGCPrologueCallback(GCCallback)); - - /** * Enables the host application to receive a notification after a * garbage collection. Allocations are not allowed in the * callback function, you therefore cannot manipulate objects (set @@ -4442,16 +4475,6 @@ class V8_EXPORT V8 { static void RemoveGCEpilogueCallback(GCEpilogueCallback callback); /** - * The function is deprecated. Please use AddGCEpilogueCallback instead. - * Enables the host application to receive a notification after a - * major garbage collection. Allocations are not allowed in the - * callback function, you therefore cannot manipulate objects (set - * or delete properties for example) since it is possible such - * operations will result in the allocation of objects. - */ - V8_DEPRECATED(static void SetGlobalGCEpilogueCallback(GCCallback)); - - /** * Enables the host application to provide a mechanism to be notified * and perform custom logging when V8 Allocates Executable Memory. */ diff --git a/src/api.cc b/src/api.cc index 45c9f04..e79b340 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6685,45 +6685,65 @@ void Isolate::SetReference(const Persistent& parent, } -void V8::SetGlobalGCPrologueCallback(GCCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCPrologueCallback()")) return; - isolate->heap()->SetGlobalGCPrologueCallback(callback); +void Isolate::AddGCPrologueCallback(GCPrologueCallback callback, + GCType gc_type) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->AddGCPrologueCallback(callback, gc_type); } -void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { - i::Isolate* isolate = i::Isolate::Current(); - if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCEpilogueCallback()")) return; - isolate->heap()->SetGlobalGCEpilogueCallback(callback); +void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->RemoveGCPrologueCallback(callback); +} + + +void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback, + GCType gc_type) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->AddGCEpilogueCallback(callback, gc_type); +} + + +void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->RemoveGCEpilogueCallback(callback); } void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) { i::Isolate* isolate = i::Isolate::Current(); if (IsDeadCheck(isolate, "v8::V8::AddGCPrologueCallback()")) return; - isolate->heap()->AddGCPrologueCallback(callback, gc_type); + isolate->heap()->AddGCPrologueCallback( + reinterpret_cast(callback), + gc_type, + false); } void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) { i::Isolate* isolate = i::Isolate::Current(); if (IsDeadCheck(isolate, "v8::V8::RemoveGCPrologueCallback()")) return; - isolate->heap()->RemoveGCPrologueCallback(callback); + isolate->heap()->RemoveGCPrologueCallback( + reinterpret_cast(callback)); } void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { i::Isolate* isolate = i::Isolate::Current(); if (IsDeadCheck(isolate, "v8::V8::AddGCEpilogueCallback()")) return; - isolate->heap()->AddGCEpilogueCallback(callback, gc_type); + isolate->heap()->AddGCEpilogueCallback( + reinterpret_cast(callback), + gc_type, + false); } void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { i::Isolate* isolate = i::Isolate::Current(); if (IsDeadCheck(isolate, "v8::V8::RemoveGCEpilogueCallback()")) return; - isolate->heap()->RemoveGCEpilogueCallback(callback); + isolate->heap()->RemoveGCEpilogueCallback( + reinterpret_cast(callback)); } diff --git a/src/heap.cc b/src/heap.cc index 86c2b4a..b3e8cd7 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -129,8 +129,6 @@ Heap::Heap() old_gen_exhausted_(false), store_buffer_rebuilder_(store_buffer()), hidden_string_(NULL), - global_gc_prologue_callback_(NULL), - global_gc_epilogue_callback_(NULL), gc_safe_size_of_old_object_(NULL), total_regexp_code_generated_(0), tracer_(NULL), @@ -1055,12 +1053,17 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { - if (gc_type == kGCTypeMarkSweepCompact && global_gc_prologue_callback_) { - global_gc_prologue_callback_(); - } for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { if (gc_type & gc_prologue_callbacks_[i].gc_type) { - gc_prologue_callbacks_[i].callback(gc_type, flags); + if (!gc_prologue_callbacks_[i].pass_isolate_) { + v8::GCPrologueCallback callback = + reinterpret_cast( + gc_prologue_callbacks_[i].callback); + callback(gc_type, flags); + } else { + v8::Isolate* isolate = reinterpret_cast(this->isolate()); + gc_prologue_callbacks_[i].callback(isolate, gc_type, flags); + } } } } @@ -1069,12 +1072,18 @@ void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { void Heap::CallGCEpilogueCallbacks(GCType gc_type) { for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { if (gc_type & gc_epilogue_callbacks_[i].gc_type) { - gc_epilogue_callbacks_[i].callback(gc_type, kNoGCCallbackFlags); + if (!gc_epilogue_callbacks_[i].pass_isolate_) { + v8::GCPrologueCallback callback = + reinterpret_cast( + gc_epilogue_callbacks_[i].callback); + callback(gc_type, kNoGCCallbackFlags); + } else { + v8::Isolate* isolate = reinterpret_cast(this->isolate()); + gc_epilogue_callbacks_[i].callback( + isolate, gc_type, kNoGCCallbackFlags); + } } } - if (gc_type == kGCTypeMarkSweepCompact && global_gc_epilogue_callback_) { - global_gc_epilogue_callback_(); - } } @@ -7071,15 +7080,17 @@ void Heap::TearDown() { } -void Heap::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) { +void Heap::AddGCPrologueCallback(v8::Isolate::GCPrologueCallback callback, + GCType gc_type, + bool pass_isolate) { ASSERT(callback != NULL); - GCPrologueCallbackPair pair(callback, gc_type); + GCPrologueCallbackPair pair(callback, gc_type, pass_isolate); ASSERT(!gc_prologue_callbacks_.Contains(pair)); return gc_prologue_callbacks_.Add(pair); } -void Heap::RemoveGCPrologueCallback(GCPrologueCallback callback) { +void Heap::RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback) { ASSERT(callback != NULL); for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { if (gc_prologue_callbacks_[i].callback == callback) { @@ -7091,15 +7102,17 @@ void Heap::RemoveGCPrologueCallback(GCPrologueCallback callback) { } -void Heap::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { +void Heap::AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback, + GCType gc_type, + bool pass_isolate) { ASSERT(callback != NULL); - GCEpilogueCallbackPair pair(callback, gc_type); + GCEpilogueCallbackPair pair(callback, gc_type, pass_isolate); ASSERT(!gc_epilogue_callbacks_.Contains(pair)); return gc_epilogue_callbacks_.Add(pair); } -void Heap::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { +void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback) { ASSERT(callback != NULL); for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { if (gc_epilogue_callbacks_[i].callback == callback) { diff --git a/src/heap.h b/src/heap.h index 4dfa076..2f91ebc 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1272,22 +1272,15 @@ class Heap { void GarbageCollectionGreedyCheck(); #endif - void AddGCPrologueCallback( - GCPrologueCallback callback, GCType gc_type_filter); - void RemoveGCPrologueCallback(GCPrologueCallback callback); + void AddGCPrologueCallback(v8::Isolate::GCPrologueCallback callback, + GCType gc_type_filter, + bool pass_isolate = true); + void RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback); - void AddGCEpilogueCallback( - GCEpilogueCallback callback, GCType gc_type_filter); - void RemoveGCEpilogueCallback(GCEpilogueCallback callback); - - void SetGlobalGCPrologueCallback(GCCallback callback) { - ASSERT((callback == NULL) ^ (global_gc_prologue_callback_ == NULL)); - global_gc_prologue_callback_ = callback; - } - void SetGlobalGCEpilogueCallback(GCCallback callback) { - ASSERT((callback == NULL) ^ (global_gc_epilogue_callback_ == NULL)); - global_gc_epilogue_callback_ = callback; - } + void AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback, + GCType gc_type_filter, + bool pass_isolate = true); + void RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback); // Heap root getters. We have versions with and without type::cast() here. // You can't use type::cast during GC because the assert fails. @@ -2032,32 +2025,37 @@ class Heap { // GC callback function, called before and after mark-compact GC. // Allocations in the callback function are disallowed. struct GCPrologueCallbackPair { - GCPrologueCallbackPair(GCPrologueCallback callback, GCType gc_type) - : callback(callback), gc_type(gc_type) { + GCPrologueCallbackPair(v8::Isolate::GCPrologueCallback callback, + GCType gc_type, + bool pass_isolate) + : callback(callback), gc_type(gc_type), pass_isolate_(pass_isolate) { } bool operator==(const GCPrologueCallbackPair& pair) const { return pair.callback == callback; } - GCPrologueCallback callback; + v8::Isolate::GCPrologueCallback callback; GCType gc_type; + // TODO(dcarney): remove variable + bool pass_isolate_; }; List gc_prologue_callbacks_; struct GCEpilogueCallbackPair { - GCEpilogueCallbackPair(GCEpilogueCallback callback, GCType gc_type) - : callback(callback), gc_type(gc_type) { + GCEpilogueCallbackPair(v8::Isolate::GCPrologueCallback callback, + GCType gc_type, + bool pass_isolate) + : callback(callback), gc_type(gc_type), pass_isolate_(pass_isolate) { } bool operator==(const GCEpilogueCallbackPair& pair) const { return pair.callback == callback; } - GCEpilogueCallback callback; + v8::Isolate::GCPrologueCallback callback; GCType gc_type; + // TODO(dcarney): remove variable + bool pass_isolate_; }; List gc_epilogue_callbacks_; - GCCallback global_gc_prologue_callback_; - GCCallback global_gc_epilogue_callback_; - // Support for computing object sizes during GC. HeapObjectCallback gc_safe_size_of_old_object_; static int GcSafeSizeOfOldObject(HeapObject* object); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index ff8c00f..1c24017 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -17705,32 +17705,73 @@ TEST(Regress618) { } } +v8::Isolate* gc_callbacks_isolate = NULL; int prologue_call_count = 0; int epilogue_call_count = 0; int prologue_call_count_second = 0; int epilogue_call_count_second = 0; -void PrologueCallback(v8::GCType, v8::GCCallbackFlags) { +void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); ++prologue_call_count; } -void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) { +void PrologueCallback(v8::Isolate* isolate, + v8::GCType, + v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); + ++prologue_call_count; +} + + +void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); ++epilogue_call_count; } -void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) { +void EpilogueCallback(v8::Isolate* isolate, + v8::GCType, + v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); + ++epilogue_call_count; +} + + +void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + ++prologue_call_count_second; +} + + +void PrologueCallbackSecond(v8::Isolate* isolate, + v8::GCType, + v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); ++prologue_call_count_second; } -void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) { +void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); ++epilogue_call_count_second; } -TEST(GCCallbacks) { +void EpilogueCallbackSecond(v8::Isolate* isolate, + v8::GCType, + v8::GCCallbackFlags flags) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); + ++epilogue_call_count_second; +} + + +TEST(GCCallbacksOld) { LocalContext context; v8::V8::AddGCPrologueCallback(PrologueCallback); @@ -17764,6 +17805,41 @@ TEST(GCCallbacks) { } +TEST(GCCallbacks) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + gc_callbacks_isolate = isolate; + isolate->AddGCPrologueCallback(PrologueCallback); + isolate->AddGCEpilogueCallback(EpilogueCallback); + CHECK_EQ(0, prologue_call_count); + CHECK_EQ(0, epilogue_call_count); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + CHECK_EQ(1, prologue_call_count); + CHECK_EQ(1, epilogue_call_count); + isolate->AddGCPrologueCallback(PrologueCallbackSecond); + isolate->AddGCEpilogueCallback(EpilogueCallbackSecond); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + CHECK_EQ(2, prologue_call_count); + CHECK_EQ(2, epilogue_call_count); + CHECK_EQ(1, prologue_call_count_second); + CHECK_EQ(1, epilogue_call_count_second); + isolate->RemoveGCPrologueCallback(PrologueCallback); + isolate->RemoveGCEpilogueCallback(EpilogueCallback); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + CHECK_EQ(2, prologue_call_count); + CHECK_EQ(2, epilogue_call_count); + CHECK_EQ(2, prologue_call_count_second); + CHECK_EQ(2, epilogue_call_count_second); + isolate->RemoveGCPrologueCallback(PrologueCallbackSecond); + isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + CHECK_EQ(2, prologue_call_count); + CHECK_EQ(2, epilogue_call_count); + CHECK_EQ(2, prologue_call_count_second); + CHECK_EQ(2, epilogue_call_count_second); +} + + THREADED_TEST(AddToJSFunctionResultCache) { i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index f6e703b..c089871 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -267,39 +267,6 @@ TEST(MapCompact) { } #endif -static int gc_starts = 0; -static int gc_ends = 0; - -static void GCPrologueCallbackFunc() { - CHECK(gc_starts == gc_ends); - gc_starts++; -} - - -static void GCEpilogueCallbackFunc() { - CHECK(gc_starts == gc_ends + 1); - gc_ends++; -} - - -TEST(GCCallback) { - i::FLAG_stress_compaction = false; - CcTest::InitializeVM(); - - HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc); - HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc); - - // Scavenge does not call GC callback functions. - HEAP->PerformScavenge(); - - CHECK_EQ(0, gc_starts); - CHECK_EQ(gc_ends, gc_starts); - - HEAP->CollectGarbage(OLD_POINTER_SPACE); - CHECK_EQ(1, gc_starts); - CHECK_EQ(gc_ends, gc_starts); -} - static int NumberOfWeakCalls = 0; static void WeakPointerCallback(v8::Isolate* isolate,