Revision: 4805
Author: [email protected]
Date: Mon Jun 7 01:49:07 2010
Log: Add an API to control the disposal of external string resources
A new callback have been added which - if set - will be called to dispose
of external string resources passed from the embedder to the V8 engine.
Review URL: http://codereview.chromium.org/2645004
http://code.google.com/p/v8/source/detail?r=4805
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/heap-inl.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Fri Jun 4 04:49:44 2010
+++ /branches/bleeding_edge/include/v8.h Mon Jun 7 01:49:07 2010
@@ -1122,11 +1122,13 @@
/**
* Creates a new external string using the data defined in the given
- * resource. The resource is deleted when the external string is no
- * longer live on V8's heap. The caller of this function should not
- * delete or modify the resource. Neither should the underlying buffer be
- * deallocated or modified except through the destructor of the
- * external string resource.
+ * resource. When the external string is no longer live on V8's heap the
+ * resource will be disposed. If a disposal callback has been set using
+ * SetExternalStringDiposeCallback this callback will be called to
dispose
+ * the resource. Otherwise, V8 will dispose the resource using the C++
delete
+ * operator. The caller of this function should not otherwise delete or
+ * modify the resource. Neither should the underlying buffer be
deallocated
+ * or modified except through the destructor of the external string
resource.
*/
static Local<String> NewExternal(ExternalStringResource* resource);
@@ -1136,17 +1138,20 @@
* will use the external string resource. The external string resource's
* character contents needs to be equivalent to this string.
* Returns true if the string has been changed to be an external string.
- * The string is not modified if the operation fails.
+ * The string is not modified if the operation fails. See NewExternal for
+ * information on the lifetime of the resource.
*/
bool MakeExternal(ExternalStringResource* resource);
/**
* Creates a new external string using the ascii data defined in the
given
- * resource. The resource is deleted when the external string is no
- * longer live on V8's heap. The caller of this function should not
- * delete or modify the resource. Neither should the underlying buffer be
- * deallocated or modified except through the destructor of the
- * external string resource.
+ * resource. When the external string is no longer live on V8's heap the
+ * resource will be disposed. If a disposal callback has been set using
+ * SetExternalStringDiposeCallback this callback will be called to
dispose
+ * the resource. Otherwise, V8 will dispose the resource using the C++
delete
+ * operator. The caller of this function should not otherwise delete or
+ * modify the resource. Neither should the underlying buffer be
deallocated
+ * or modified except through the destructor of the external string
resource.
*/
static Local<String> NewExternal(ExternalAsciiStringResource* resource);
@@ -1156,7 +1161,8 @@
* will use the external string resource. The external string resource's
* character contents needs to be equivalent to this string.
* Returns true if the string has been changed to be an external string.
- * The string is not modified if the operation fails.
+ * The string is not modified if the operation fails. See NewExternal for
+ * information on the lifetime of the resource.
*/
bool MakeExternal(ExternalAsciiStringResource* resource);
@@ -1245,6 +1251,10 @@
};
+typedef void (*ExternalStringDiposeCallback)
+ (String::ExternalStringResourceBase* resource);
+
+
/**
* A JavaScript number value (ECMA-262, 4.3.20)
*/
@@ -2461,6 +2471,15 @@
*/
static void RemoveMessageListeners(MessageCallback that);
+ /**
+ * Set a callback to be called when an external string is no longer live
on
+ * V8's heap. The resource will no longer be needed by V8 and the
embedder
+ * can dispose of if. If this callback is not set V8 will free the
resource
+ * using the C++ delete operator.
+ */
+ static void SetExternalStringDiposeCallback(
+ ExternalStringDiposeCallback that);
+
/**
* Sets V8 flags from a string.
*/
=======================================
--- /branches/bleeding_edge/src/api.cc Fri Jun 4 04:49:44 2010
+++ /branches/bleeding_edge/src/api.cc Mon Jun 7 01:49:07 2010
@@ -3690,6 +3690,14 @@
}
}
}
+
+
+void V8::SetExternalStringDiposeCallback(
+ ExternalStringDiposeCallback callback) {
+ if (IsDeadCheck("v8::V8::SetExternalStringDiposeCallback()"))
+ return;
+ i::Heap::SetExternalStringDiposeCallback(callback);
+}
void V8::SetCounterFunction(CounterLookupCallback callback) {
=======================================
--- /branches/bleeding_edge/src/heap-inl.h Thu May 27 05:30:45 2010
+++ /branches/bleeding_edge/src/heap-inl.h Mon Jun 7 01:49:07 2010
@@ -117,7 +117,14 @@
reinterpret_cast<byte*>(string) +
ExternalString::kResourceOffset -
kHeapObjectTag);
- delete *resource_addr;
+
+ // Dispose of the C++ object.
+ if (external_string_dispose_callback_ != NULL) {
+ external_string_dispose_callback_(*resource_addr);
+ } else {
+ delete *resource_addr;
+ }
+
// Clear the resource pointer in the string.
*resource_addr = NULL;
}
=======================================
--- /branches/bleeding_edge/src/heap.cc Fri Jun 4 04:57:01 2010
+++ /branches/bleeding_edge/src/heap.cc Mon Jun 7 01:49:07 2010
@@ -98,6 +98,8 @@
// set up by ConfigureHeap otherwise.
int Heap::reserved_semispace_size_ = Heap::max_semispace_size_;
+ExternalStringDiposeCallback Heap::external_string_dispose_callback_ =
NULL;
+
List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_;
List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_;
=======================================
--- /branches/bleeding_edge/src/heap.h Thu May 27 05:30:45 2010
+++ /branches/bleeding_edge/src/heap.h Mon Jun 7 01:49:07 2010
@@ -689,6 +689,11 @@
// Utility used with flag gc-greedy.
static bool GarbageCollectionGreedyCheck();
#endif
+
+ static void SetExternalStringDiposeCallback(
+ ExternalStringDiposeCallback callback) {
+ external_string_dispose_callback_ = callback;
+ }
static void AddGCPrologueCallback(
GCEpilogueCallback callback, GCType gc_type_filter);
@@ -1138,6 +1143,9 @@
// any string when looked up in properties.
static String* hidden_symbol_;
+ static ExternalStringDiposeCallback
+ external_string_dispose_callback_;
+
// GC callback function, called before and after mark-compact GC.
// Allocations in the callback function are disallowed.
struct GCPrologueCallbackPair {
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Mon Jun 7 01:27:32 2010
+++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Jun 7 01:49:07 2010
@@ -610,6 +610,71 @@
i::Heap::CollectGarbage(0, in_new_space ? i::NEW_SPACE :
i::OLD_DATA_SPACE);
CHECK_EQ(1, TestAsciiResource::dispose_count);
}
+
+
+static int dispose_count = 0;
+static void DisposeExternalStringCount(
+ String::ExternalStringResourceBase* resource) {
+ dispose_count++;
+}
+
+
+static void DisposeExternalStringDeleteAndCount(
+ String::ExternalStringResourceBase* resource) {
+ delete resource;
+ dispose_count++;
+}
+
+
+TEST(ExternalStringWithResourceDisposeCallback) {
+ const char* c_source = "1 + 2 * 3";
+
+ // Set an external string collected callback which does not delete the
object.
+ v8::V8::SetExternalStringDiposeCallback(DisposeExternalStringCount);
+
+ // Use a stack allocated external string resource allocated object.
+ dispose_count = 0;
+ TestAsciiResource::dispose_count = 0;
+ TestAsciiResource res_stack(i::StrDup(c_source));
+ {
+ v8::HandleScope scope;
+ LocalContext env;
+ Local<String> source = String::NewExternal(&res_stack);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> value = script->Run();
+ CHECK(value->IsNumber());
+ CHECK_EQ(7, value->Int32Value());
+ v8::internal::Heap::CollectAllGarbage(false);
+ CHECK_EQ(0, TestAsciiResource::dispose_count);
+ }
+ v8::internal::CompilationCache::Clear();
+ v8::internal::Heap::CollectAllGarbage(false);
+ CHECK_EQ(1, dispose_count);
+ CHECK_EQ(0, TestAsciiResource::dispose_count);
+
+ // Set an external string collected callback which does delete the
object.
+
v8::V8::SetExternalStringDiposeCallback(DisposeExternalStringDeleteAndCount);
+
+ // Use a heap allocated external string resource allocated object.
+ dispose_count = 0;
+ TestAsciiResource::dispose_count = 0;
+ TestAsciiResource* res_heap = new TestAsciiResource(i::StrDup(c_source));
+ {
+ v8::HandleScope scope;
+ LocalContext env;
+ Local<String> source = String::NewExternal(res_heap);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> value = script->Run();
+ CHECK(value->IsNumber());
+ CHECK_EQ(7, value->Int32Value());
+ v8::internal::Heap::CollectAllGarbage(false);
+ CHECK_EQ(0, TestAsciiResource::dispose_count);
+ }
+ v8::internal::CompilationCache::Clear();
+ v8::internal::Heap::CollectAllGarbage(false);
+ CHECK_EQ(1, dispose_count);
+ CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
THREADED_TEST(StringConcat) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev