New feature: handle eternalization

354 views
Skip to first unread message

Dan Carney

unread,
Aug 7, 2013, 4:46:53 AM8/7/13
to v8-u...@googlegroups.com
Hi all,

as part of the refactor of v8::Persistent, I've added the ability to store and fetch a handle which will live for the lifetime of the Isolate, but which has none of the complexity and overhead (and problems) of a Persistent.  This can be useful for things like ObjectTemplates and FunctionTemplates which you might lazily initialize, but need forever once they have been initialized.  There are probably other use cases out there as well.

The API is simple:

int eternal_index = v8::kUninitializedEternalIndex; // always initialize to this value
{
  HandleScope scope(isolate);
  Local<Object> local = .... // some v8 code
  eternal_index = local.Eternalize(isolate);
}

// Note:  don't actually need a HandleScope to simply get an eternal
Local<Object> local = Local<Object>::GetEternal(isolate, eternal_index);

Any place where you can Eternalize a handle, it's probably best to do so, as Persistents that live forever can potentially hold on to a lot of memory in internal data structures.

Cheers,
Dan

Ben Noordhuis

unread,
Aug 7, 2013, 6:56:15 AM8/7/13
to v8-u...@googlegroups.com
Hi Dan,

I saw the patches land in the last few days, looks like a useful
addition to the API.

Quick question (and one I suspect I know the answer to): how do
eternal handles interact with contexts?

The eternal handles list is a per-isolate property. If I create and
eternalize a handle in context A, then it won't be usable in context B
unless the security tokens match, right?

Thanks,

Ben

Dan Carney

unread,
Aug 7, 2013, 7:19:28 AM8/7/13
to v8-u...@googlegroups.com

Quick question (and one I suspect I know the answer to): how do
eternal handles interact with contexts?

There's nothing special about eternal handles.  They are like any other type of handle, so any interaction they have with contexts will remain unchanged.

I mentioned them being useful for Object- and FunctionTemplate because those are context independent and likely to persistent for the lifetime of an isolate, but I think anything that doesn't extend v8::Object is also context independent.

Mike Moening

unread,
Aug 9, 2013, 2:54:31 PM8/9/13
to v8-u...@googlegroups.com
I know this may sound stupid... but how can I kill an eternal?
Really nothing lives forever.
I can think of a case where i might want to destroy one.

Stephan Beal

unread,
Aug 9, 2013, 3:27:11 PM8/9/13
to v8-u...@googlegroups.com
This should do the trick:

exit(0);

;)

--
----- stephan beal
http://wanderinghorse.net/home/stephan/

Michael Schwartz

unread,
Aug 9, 2013, 4:01:50 PM8/9/13
to v8-u...@googlegroups.com
--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Dan Carney

unread,
Aug 11, 2013, 11:59:39 AM8/11/13
to v8-u...@googlegroups.com
I can think of a case where i might want to destroy one.

Destronying a eternal can only be done via Isolate::Dispose() 

If you can think of a reason to destroy an eternal, you probably don't want one in the first place.  You probably want a strong Persistent and an explicit Dispose() somewhere.


Dan Carney

unread,
Aug 23, 2013, 2:58:37 AM8/23/13
to v8-u...@googlegroups.com
We've discussed the api a bit more, and decided that it really needs to look more like Local and Persistent.  I apologize to anyone who may have already started to use the original api.  This change will land next week and will remove the original.

The new api is used as follows:


Eternal<FunctionTemplate> eternal;

....

Local<FunctionTemplate> function_template;
if (eternal.IsSet()) {
  function_template = eternal.Get(isolate);
} else {
  HandleScope scope(isolate);
  function_template = BuildFunctionTemplate();
  eternal.Set(isolate, function_template);
}



Ben Noordhuis

unread,
Aug 23, 2013, 4:59:16 AM8/23/13
to v8-u...@googlegroups.com
Suggestion: lower the cognitive barrier, rename IsSet() to IsEmpty() -
unless it does something completely different from
Handle<T>::IsEmpty(), of course.

Dan Carney

unread,
Aug 26, 2013, 7:39:45 AM8/26/13
to v8-u...@googlegroups.com

Suggestion: lower the cognitive barrier, rename IsSet() to IsEmpty() -  

Thanks for the suggestion!  It will be in the next v8 release.

Mike Moening

unread,
Aug 28, 2013, 2:27:58 AM8/28/13
to v8-u...@googlegroups.com
Dan, 

Did the new Eternal land yet?
I'm porting code now and would like to use it.

Mike M.

Dan Carney

unread,
Aug 28, 2013, 2:54:26 AM8/28/13
to v8-u...@googlegroups.com
Did the new Eternal land yet?

Yes, it's in. 

Mike Moening

unread,
Aug 28, 2013, 3:35:29 AM8/28/13
to v8-u...@googlegroups.com
Dan,

Can you provide a complete example of creating a ObjectTemplate with eternal, storing it and then later retrieving it?
Something is escaping me...

Thanks!

Mike Moening

unread,
Aug 28, 2013, 4:38:03 PM8/28/13
to v8-u...@googlegroups.com
Can I still do this?
  Local<Object> local = .... // some v8 code
  index = local.Eternalize(isolate);

  Local<Object> local = Local<Object>::GetEternal(isolate, eternal_index);

In other words how does the new Eternal get loaded/saved?
   Eternal<FunctionTemplate> eternal;

The original design is really easy and simple. The Isolate stores my Eternal FunctionTemplate by index and I don't have to keep track of it anymore.
The Eternal is confusing compared to the original idea.

Mike Moening

unread,
Aug 28, 2013, 11:29:03 PM8/28/13
to v8-u...@googlegroups.com
It's getting clearer but less useful.

So the Eternal object stores the index for me. Right?
Doesn't that mean I have to now keep the Eternal object around in my code?
How is keeping an Eternal around better than keeping a Persistent around?

It would be nice if the user could specify the unique index of the eternal.
Then all I ever need to keep is a constant integer value.
const MY_OBJECT_TEMPLATE_ID = 12345;

No extra object to keep around. Once the Local is saved as an eternal I can get it back with a simple hash lookup (GetEternal())

Local<Object> local = Local<Object>::GetEternal(isolate, MY_OBJECT_TEMPLATE_ID );

How does that sound?

Dan Carney

unread,
Aug 29, 2013, 3:09:34 AM8/29/13
to v8-u...@googlegroups.com
No extra object to keep around. Once the Local is saved as an eternal I can get it back with a simple hash lookup (GetEternal())

Local<Object> local = Local<Object>::GetEternal(isolate, MY_OBJECT_TEMPLATE_ID );

How does that sound?


The index is isolate specific and v8 itself uses some internally, so the value of the index cannot be exposed.  It's better than keeping a persistent around for cases where access times matter.  Getting a Local from an Eternal is very fast.

Mike Moening

unread,
Aug 29, 2013, 12:54:45 PM8/29/13
to v8-u...@googlegroups.com
Dan,

I think something is broken in the new Eternal API.
This example code block fails to compile.
Seems ObjectTemplate is missing a Cast method?

   Eternal<ObjectTemplate> eternal;
   Local<ObjectTemplate> tmplXFile;
   tmplXFile = eternal.Get(pIsolate);
   eternal.Set(pIsolate, tmplXFile);

V8\include\v8.h(406) : error C2039: 'Cast' : is not a member of 'v8::ObjectTemplate'
        V8\include\v8.h(3455) : see declaration of 'v8::ObjectTemplate'
        V8\include\v8.h(5697) : see reference to function template instantiation 'v8::Local<T> v8::Local<T>::Cast<v8::Value>(v8::Local<v8::Value>)' being compiled
        with
        [
            T=v8::ObjectTemplate
        ]
        V8\include\v8.h(5696) : while compiling class template member function 'v8::Local<T> v8::Eternal<T>::Get(v8::Isolate *)'
        with
        [
            T=v8::ObjectTemplate
        ]
        .\RXFile.cpp(452) : see reference to class template instantiation 'v8::Eternal<T>' being compiled
        with
        [
            T=v8::ObjectTemplate
        ]
V8\include\v8.h(406) : error C2784: 'v8::Local<T> v8::Local<T>::Cast(v8::Local<S>)' : could not deduce template argument for 'v8::Local<S>' from 'v8::Value *'
        with
        [
            T=v8::ObjectTemplate
        ]
        V8\include\v8.h(400) : see declaration of 'v8::Local<T>::Cast'
        with
        [
            T=v8::ObjectTemplate
        ]
V8\include\v8.h(6285) : error C2440: 'static_cast' : cannot convert from 'v8::ObjectTemplate *' to 'v8::Value *'
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
        V8\include\v8.h(5691) : see reference to function template instantiation 'v8::Value *v8::Value::Cast<T>(T *)' being compiled
        with
        [
            T=v8::ObjectTemplate
        ]
        .\RXFile.cpp(455) : see reference to function template instantiation 'void v8::Eternal<T>::Set<v8::ObjectTemplate>(v8::Isolate *,v8::Local<T>)' being compiled
        with
        [
            T=v8::ObjectTemplate
        ]

Dan Carney

unread,
Aug 29, 2013, 1:53:44 PM8/29/13
to v8-u...@googlegroups.com

I think something is broken in the new Eternal API.
This example code block fails to compile.
Seems ObjectTemplate is missing a Cast method?

Yep.  I'll fix it tomorrow.  Thanks for the report. 

Mike Moening

unread,
Sep 3, 2013, 1:15:03 PM9/3/13
to v8-u...@googlegroups.com
Found another bug in Eternal.

The IsEmpty() method is returning an inverted value.

Broken code:
V8_INLINE(bool IsEmpty()) { return index_ != kInitialValue; }

Should be:
V8_INLINE(bool IsEmpty()) { return index_ == kInitialValue; }

Here is the bug report:

ioannis

unread,
Sep 16, 2013, 7:07:30 PM9/16/13
to v8-u...@googlegroups.com
Shouldn't the use of Handle<> and Local<> be interchangeable ?
Has it been decided which of the two will be depreciated in the end ?

It seems that we cannot assign a Handle<> value to the Eternal and we need to use Local<> instead ...

Dan Carney

unread,
Sep 17, 2013, 3:18:06 AM9/17/13
to v8-u...@googlegroups.com
Handle will go away eventually.  New apis will use Local.  Old apis that use Handle will migrate to Local.  If you have a Handle, you'll have to do Local<X>(handle) where needed.
Reply all
Reply to author
Forward
0 new messages