Add Persistent::ClearAndLeak.

This will be relevant after Persistent is changed to Dispose itself when
destructed. With Persistent::ClearAndLeak, Blink can take the ownership of the
object pointed by a Persistent and avoid it getting destructed.

BUG=
R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/15023010

Patch from Marja Hölttä <marja@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14624 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0b7c1450
...@@ -695,6 +695,16 @@ template <class T> class Persistent // NOLINT ...@@ -695,6 +695,16 @@ template <class T> class Persistent // NOLINT
*/ */
V8_INLINE(void Reset(Isolate* isolate, const Handle<T>& other)); V8_INLINE(void Reset(Isolate* isolate, const Handle<T>& other));
/**
* Returns the underlying raw pointer and clears the handle. The caller is
* responsible of eventually destroying the underlying object (by creating a
* Persistent handle which points to it and Disposing it). In the future,
* destructing a Persistent will also Dispose it. With this function, the
* embedder can let the Persistent go out of scope without it getting
* disposed.
*/
V8_INLINE(T* ClearAndLeak());
#ifndef V8_USE_UNSAFE_HANDLES #ifndef V8_USE_UNSAFE_HANDLES
#ifndef V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT #ifndef V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
...@@ -5383,6 +5393,7 @@ void Persistent<T>::SetWrapperClassId(uint16_t class_id) { ...@@ -5383,6 +5393,7 @@ void Persistent<T>::SetWrapperClassId(uint16_t class_id) {
SetWrapperClassId(Isolate::GetCurrent(), class_id); SetWrapperClassId(Isolate::GetCurrent(), class_id);
} }
template <class T> template <class T>
void Persistent<T>::Reset(Isolate* isolate, const Handle<T>& other) { void Persistent<T>::Reset(Isolate* isolate, const Handle<T>& other) {
Dispose(isolate); Dispose(isolate);
...@@ -5399,6 +5410,21 @@ void Persistent<T>::Reset(Isolate* isolate, const Handle<T>& other) { ...@@ -5399,6 +5410,21 @@ void Persistent<T>::Reset(Isolate* isolate, const Handle<T>& other) {
#endif #endif
} }
template <class T>
T* Persistent<T>::ClearAndLeak() {
T* old;
#ifdef V8_USE_UNSAFE_HANDLES
old = **this;
*this = Persistent<T>();
#else
old = val_;
val_ = NULL;
#endif
return old;
}
template <class T> template <class T>
void Persistent<T>::SetWrapperClassId(Isolate* isolate, uint16_t class_id) { void Persistent<T>::SetWrapperClassId(Isolate* isolate, uint16_t class_id) {
typedef internal::Internals I; typedef internal::Internals I;
......
...@@ -2539,6 +2539,30 @@ THREADED_TEST(ResettingGlobalHandleToEmpty) { ...@@ -2539,6 +2539,30 @@ THREADED_TEST(ResettingGlobalHandleToEmpty) {
} }
THREADED_TEST(ClearAndLeakGlobal) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::internal::GlobalHandles* global_handles = NULL;
int initial_handle_count = 0;
v8::Persistent<String> global;
{
v8::HandleScope scope(isolate);
Local<String> str = v8_str("str");
global_handles =
reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
initial_handle_count = global_handles->NumberOfGlobalHandles();
global = v8::Persistent<String>::New(isolate, str);
}
CHECK_EQ(global_handles->NumberOfGlobalHandles(), initial_handle_count + 1);
String* str = global.ClearAndLeak();
CHECK(global.IsEmpty());
CHECK_EQ(global_handles->NumberOfGlobalHandles(), initial_handle_count + 1);
v8::Persistent<String>* new_global =
reinterpret_cast<v8::Persistent<String>*>(&str);
new_global->Dispose();
CHECK_EQ(global_handles->NumberOfGlobalHandles(), initial_handle_count);
}
THREADED_TEST(LocalHandle) { THREADED_TEST(LocalHandle) {
v8::HandleScope scope(v8::Isolate::GetCurrent()); v8::HandleScope scope(v8::Isolate::GetCurrent());
v8::Local<String> local = v8::Local<String>::New(v8_str("str")); v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment