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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4805 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ff61618c4b
commit
09acdc8446
43
include/v8.h
43
include/v8.h
@ -1122,11 +1122,13 @@ class V8EXPORT String : public Primitive {
|
||||
|
||||
/**
|
||||
* 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 @@ class V8EXPORT String : public Primitive {
|
||||
* 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 @@ class V8EXPORT String : public Primitive {
|
||||
* 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 @@ class V8EXPORT String : public Primitive {
|
||||
};
|
||||
|
||||
|
||||
typedef void (*ExternalStringDiposeCallback)
|
||||
(String::ExternalStringResourceBase* resource);
|
||||
|
||||
|
||||
/**
|
||||
* A JavaScript number value (ECMA-262, 4.3.20)
|
||||
*/
|
||||
@ -2461,6 +2471,15 @@ class V8EXPORT V8 {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -3692,6 +3692,14 @@ void V8::RemoveMessageListeners(MessageCallback that) {
|
||||
}
|
||||
|
||||
|
||||
void V8::SetExternalStringDiposeCallback(
|
||||
ExternalStringDiposeCallback callback) {
|
||||
if (IsDeadCheck("v8::V8::SetExternalStringDiposeCallback()"))
|
||||
return;
|
||||
i::Heap::SetExternalStringDiposeCallback(callback);
|
||||
}
|
||||
|
||||
|
||||
void V8::SetCounterFunction(CounterLookupCallback callback) {
|
||||
if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
|
||||
i::StatsTable::SetCounterFunction(callback);
|
||||
|
@ -117,7 +117,14 @@ void Heap::FinalizeExternalString(String* string) {
|
||||
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;
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ size_t Heap::code_range_size_ = 0;
|
||||
// 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_;
|
||||
|
||||
|
@ -690,6 +690,11 @@ class Heap : public AllStatic {
|
||||
static bool GarbageCollectionGreedyCheck();
|
||||
#endif
|
||||
|
||||
static void SetExternalStringDiposeCallback(
|
||||
ExternalStringDiposeCallback callback) {
|
||||
external_string_dispose_callback_ = callback;
|
||||
}
|
||||
|
||||
static void AddGCPrologueCallback(
|
||||
GCEpilogueCallback callback, GCType gc_type_filter);
|
||||
static void RemoveGCPrologueCallback(GCEpilogueCallback callback);
|
||||
@ -1138,6 +1143,9 @@ class Heap : public AllStatic {
|
||||
// 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 {
|
||||
|
@ -612,6 +612,71 @@ THREADED_TEST(ScavengeExternalAsciiString) {
|
||||
}
|
||||
|
||||
|
||||
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::HandleScope scope;
|
||||
|
Loading…
Reference in New Issue
Block a user