@@ -3082,13 +3082,81 @@ i::Handle<i::String> NewExternalAsciiStringHandle(
30823082}
30833083
30843084
3085+ static void DisposeExternalString (v8::Persistent<v8::Value> obj,
3086+ void * parameter) {
3087+ ENTER_V8;
3088+ i::ExternalTwoByteString* str =
3089+ i::ExternalTwoByteString::cast (*Utils::OpenHandle (*obj));
3090+
3091+ // External symbols are deleted when they are pruned out of the symbol
3092+ // table. Generally external symbols are not registered with the weak handle
3093+ // callbacks unless they are upgraded to a symbol after being externalized.
3094+ if (!str->IsSymbol ()) {
3095+ v8::String::ExternalStringResource* resource =
3096+ reinterpret_cast <v8::String::ExternalStringResource*>(parameter);
3097+ if (resource != NULL ) {
3098+ const int total_size =
3099+ static_cast <int >(resource->length () * sizeof (*resource->data ()));
3100+ i::Counters::total_external_string_memory.Decrement (total_size);
3101+
3102+ // The object will continue to live in the JavaScript heap until the
3103+ // handle is entirely cleaned out by the next GC. For example the
3104+ // destructor for the resource below could bring it back to life again.
3105+ // Which is why we make sure to not have a dangling pointer here.
3106+ str->set_resource (NULL );
3107+ delete resource;
3108+ }
3109+ }
3110+
3111+ // In any case we do not need this handle any longer.
3112+ obj.Dispose ();
3113+ }
3114+
3115+
3116+ static void DisposeExternalAsciiString (v8::Persistent<v8::Value> obj,
3117+ void * parameter) {
3118+ ENTER_V8;
3119+ i::ExternalAsciiString* str =
3120+ i::ExternalAsciiString::cast (*Utils::OpenHandle (*obj));
3121+
3122+ // External symbols are deleted when they are pruned out of the symbol
3123+ // table. Generally external symbols are not registered with the weak handle
3124+ // callbacks unless they are upgraded to a symbol after being externalized.
3125+ if (!str->IsSymbol ()) {
3126+ v8::String::ExternalAsciiStringResource* resource =
3127+ reinterpret_cast <v8::String::ExternalAsciiStringResource*>(parameter);
3128+ if (resource != NULL ) {
3129+ const int total_size =
3130+ static_cast <int >(resource->length () * sizeof (*resource->data ()));
3131+ i::Counters::total_external_string_memory.Decrement (total_size);
3132+
3133+ // The object will continue to live in the JavaScript heap until the
3134+ // handle is entirely cleaned out by the next GC. For example the
3135+ // destructor for the resource below could bring it back to life again.
3136+ // Which is why we make sure to not have a dangling pointer here.
3137+ str->set_resource (NULL );
3138+ delete resource;
3139+ }
3140+ }
3141+
3142+ // In any case we do not need this handle any longer.
3143+ obj.Dispose ();
3144+ }
3145+
3146+
30853147Local<String> v8::String::NewExternal (
30863148 v8::String::ExternalStringResource* resource) {
30873149 EnsureInitialized (" v8::String::NewExternal()" );
30883150 LOG_API (" String::NewExternal" );
30893151 ENTER_V8;
3152+ const int total_size =
3153+ static_cast <int >(resource->length () * sizeof (*resource->data ()));
3154+ i::Counters::total_external_string_memory.Increment (total_size);
30903155 i::Handle<i::String> result = NewExternalStringHandle (resource);
3091- i::ExternalStringTable::AddString (*result);
3156+ i::Handle<i::Object> handle = i::GlobalHandles::Create (*result);
3157+ i::GlobalHandles::MakeWeak (handle.location (),
3158+ resource,
3159+ &DisposeExternalString);
30923160 return Utils::ToLocal (result);
30933161}
30943162
@@ -3100,7 +3168,13 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
31003168 i::Handle<i::String> obj = Utils::OpenHandle (this );
31013169 bool result = obj->MakeExternal (resource);
31023170 if (result && !obj->IsSymbol ()) {
3103- i::ExternalStringTable::AddString (*obj);
3171+ // Operation was successful and the string is not a symbol. In this case
3172+ // we need to make sure that the we call the destructor for the external
3173+ // resource when no strong references to the string remain.
3174+ i::Handle<i::Object> handle = i::GlobalHandles::Create (*obj);
3175+ i::GlobalHandles::MakeWeak (handle.location (),
3176+ resource,
3177+ &DisposeExternalString);
31043178 }
31053179 return result;
31063180}
@@ -3111,8 +3185,14 @@ Local<String> v8::String::NewExternal(
31113185 EnsureInitialized (" v8::String::NewExternal()" );
31123186 LOG_API (" String::NewExternal" );
31133187 ENTER_V8;
3188+ const int total_size =
3189+ static_cast <int >(resource->length () * sizeof (*resource->data ()));
3190+ i::Counters::total_external_string_memory.Increment (total_size);
31143191 i::Handle<i::String> result = NewExternalAsciiStringHandle (resource);
3115- i::ExternalStringTable::AddString (*result);
3192+ i::Handle<i::Object> handle = i::GlobalHandles::Create (*result);
3193+ i::GlobalHandles::MakeWeak (handle.location (),
3194+ resource,
3195+ &DisposeExternalAsciiString);
31163196 return Utils::ToLocal (result);
31173197}
31183198
@@ -3125,7 +3205,13 @@ bool v8::String::MakeExternal(
31253205 i::Handle<i::String> obj = Utils::OpenHandle (this );
31263206 bool result = obj->MakeExternal (resource);
31273207 if (result && !obj->IsSymbol ()) {
3128- i::ExternalStringTable::AddString (*obj);
3208+ // Operation was successful and the string is not a symbol. In this case
3209+ // we need to make sure that the we call the destructor for the external
3210+ // resource when no strong references to the string remain.
3211+ i::Handle<i::Object> handle = i::GlobalHandles::Create (*obj);
3212+ i::GlobalHandles::MakeWeak (handle.location (),
3213+ resource,
3214+ &DisposeExternalAsciiString);
31293215 }
31303216 return result;
31313217}
0 commit comments