This looks fine to me. The garbage collector may not have deemed it
worthwhile to collect for whatever reason.

One thing that looks wrong, unrelated to your question, is that you're
creating a new object template in a local handle and then returning it.
Once that Local handle goes out of scope I believe your object is
considered garbage. 

I think v8 has already created an object for you to store your result in
and put it in args.Holder(); What you should do is create a
FunctionTemplate and setup the functiontemplate->InstanceTemplate() like
your objTpl below (give it the appropriate field count, property
handlers, etc). Use the function template instance's ->GetFunction() for
the function used for construction. Then your callhandler should just
store the persistent pointer to the c++ object in args.Holder(), and
return that.

As for why the garbage collector doesn't fire I have no idea. I am not
sure that it should be. Perhaps someone else could step in here?

Best,
Alfred

On Sun, 2010-02-21 at 14:57 -0800, deadmorous wrote:
> Strange, the handler isn't called at all. Here is the code of
> constructor of example JS object:
> ---- 8< ----
> v8::Handle<v8::Value> jsnative_myobj(const v8::Arguments& args) {
>     if( args.IsConstructCall() ) {
>         // Create object template here (well, this is just a test,
> performance doesn't matter)
>         Handle<ObjectTemplate> objTpl = ObjectTemplate::New();
>         objTpl->SetInternalFieldCount( 1 );
>         objTpl->SetNamedPropertyHandler(
>             MyNamedPropertyGetter, MyNamedPropertySetter,
> MyNamedPropertyQuery, MyNamedPropertyDeleter,
> MyNamedPropertyEnumerator );
> 
>         // Create new object instance
>         Local<v8::Object> obj = objTpl->NewInstance();
> 
>         // Store an application-specific pointer in an internal field
> as a persistent handle
>         Persistent< External > hm( External::New( new
> map<string,string>() ) ); // Set handle data
>         hm.MakeWeak( 0, RemoveMyObj ); // Make the handle weak,
> specify the callback
>         obj->SetInternalField( 0, hm ); // Store handle in internal
> field
> 
>         // Return instance just created, which should cause the
> current This object to be discarded.
>         return obj;
>         }
>     else
>         return v8::Undefined();
>     }
> ---- 8< ----
> The corresp. function object is created using a function template and
> set as a global property:
> ---- 8< ----
>         Local<FunctionTemplate> f_myobj =
> FunctionTemplate::New(jsnative_myobj);
>         f_myobj->SetClassName( String::New("MY_OBJ") );
>         context->Global()->Set( String::New("myobj"), f_myobj-
> >GetFunction() );
> ---- 8< ----
> Then I execute the following script:
> ---- 8< ----
> for( i=1; i<1000000; ++i ) {
>       o = new myobj
>       if( i % 100 == 0 )   print( i );
>       o.p1 = "123";
>       o.p2 = i.toString();
>       }
> ---- 8< ----
> I expect that GC would remove instances created in a loop, which
> causes weak handles in internal fields of my instances to die, which
> in turn causes the invocation of the RemoveMyObj() handle.
> Unfortunally, this doesn't happen; task manager shows that memory
> usage constantly grows. What am I doing wrong?
> 
> Regards,
> Deadmorous
> 
> On 22 фев, 00:54, deadmorous <[email protected]> wrote:
> > Yes, exactly; I have smart pointers with reference counting in my app,
> > but this doesn't matter.
> >
> > Actually, as wou warned, my callback hasn't been called in a small
> > example, even though the engine should have shut down (I called
> > Persistent<Context>::Dispose() for the context, and V8::Dispose()
> > afterwards). Still my handler has not been called. Well, if this is
> > just becasue GC hasn't worked a single time, I can of course kill all
> > of my instances after engine shutdown. Will also try running a more
> > memory intensive test script to find out what's going on...
> >
> > On 21 фев, 23:32, Alfred Rossi <[email protected]> wrote:
> >
> > > You should hold your object in a weak persistent reference from the
> > > start.
> >
> > > If I understand you correctly, I think what you actually want to do is
> > > create a Persistent::External for holding your wrapped class pointer,
> > > and call MakeWeak on that. The handler given to MakeWeak should cast the
> > > pointer back to it's original type and delete it. The rest about
> > > deleting after removal is automatic and happens as deemed necessary by
> > > the garbage collector.
> >
> > > On Sun, 2010-02-21 at 12:28 -0800, deadmorous wrote:
> > > > Well, the most important to me is to take some action in responce to
> > > > adding/removing properties, which is done using interceptors. Once a
> > > > JS property is removed, I can reflect that in my own property tree,
> > > > and also call Persistent::MakeWeak() on the object referred to by the
> > > > property that's being removed. Then at some time GC would remove JS
> > > > instance, which in turn would dereference my instance, which in turn
> > > > would typically remove it. At least this is how I see that now - will
> > > > try to implement. V8's API is not obvious, though SpiderMonkey's is
> > > > harder to understand and use)
> >
> > > > On 21 фев, 20:44, Alfred Rossi <[email protected]> wrote:
> > > > > I think global here is referring to the global HandleScope and not the
> > > > > owning object. I suspect that by holding it with a persistent handle
> > > > > you globalize (free it's ties to C++ scope dependent handles like
> > > > > Local) the object. According to the Embedder's Guide:
> >
> > > > > "Persistent handles are not held on a stack and are deleted only when
> > > > > you specifically remove them. Just like a local handle, a persistent
> > > > > handle provides a reference to a heap-allocated object. Use a
> > > > > persistent handle when you need to keep a reference to an object for
> > > > > more than one function call, or when handle lifetimes do not
> > > > > correspond to C++ scopes...."
> >
> > > > > "...A persistent handle can be made weak, using Persistent::MakeWeak,
> > > > > to trigger a callback from the garbage collector when the only
> > > > > references to an object are from weak persistent handles."
> >
> > > > > The comments and documentation leave me with the impression that when
> > > > > one object holds another it does not do so using a weak persistent
> > > > > handle, and thus the garbage collector is prevented from invoking the
> > > > > callback.
> >
> > > > > This gets into internals which I am not too keen on (I am just a user
> > > > > like yourself), but there are developers on this list that can jump in
> > > > > should you like to know more.
> >
> > > > > Best,
> > > > > Alfred
> >
> > > > > On Sun, Feb 21, 2010 at 12:17 PM, deadmorous <[email protected]> 
> > > > > wrote:
> > > > > > Thank you very much, Alfred.
> > > > > > This seems to be exactly what I asked for. :) One thing I still 
> > > > > > don't
> > > > > > understand is the description of "object" parameter in
> > > > > > WeakReferenceCallback, saying "the weak global object to be 
> > > > > > reclaimed
> > > > > > by the garbage collector". Why "global"? What if the object was a
> > > > > > property of some other object, and the property was then removed?
> >
> > > > > > Best regards,
> > > > > > Deadmorous
> >
> > > > > > On 21 фев, 19:32, Alfred Rossi <[email protected]> wrote:
> > > > > >> I apologize, that was supposed to say "The garbage collector is NOT
> > > > > >> guaranteed..."
> >
> > > > > >> Best,
> > > > > >> Alfred
> >
> > > > > >> On Sun, 2010-02-21 at 11:31 -0500, Alfred Rossi wrote:
> > > > > >> > You're looking for Persistent::MakeWeak. You can use MakeWeak to 
> > > > > >> > specify
> > > > > >> > a callback to be invoked when the object is about to be garbage
> > > > > >> > collected.
> >
> > > > > >> > You should be careful about building in an alternate way to free 
> > > > > >> > your C
> > > > > >> > ++ objects. The garbage collector is guaranteed to be run, ever, 
> > > > > >> > even
> > > > > >> > after the context has been disposed.
> >
> > > > > >> > See this for more details:
> > > > > >> >http://stackoverflow.com/questions/173366/how-do-you-free-a-wrapped-c...
> >
> > > > > >> > Best,
> > > > > >> > Alfred
> >
> > > > > >> > On Sun, 2010-02-21 at 08:24 -0800, deadmorous wrote:
> > > > > >> > > Hello,
> > > > > >> > > I'm trying to use V8 to expose functionality of my app to JS.
> > > > > >> > > In my app, there are objects with properties and methods, 
> > > > > >> > > organized as
> > > > > >> > > a tree of properties;
> > > > > >> > > object instances can be created and added to the tree.
> > > > > >> > > I understand how to expose my properties using V8 
> > > > > >> > > interceptors, and
> > > > > >> > > think that it's correct to expose my
> > > > > >> > > methods as properties of prototypes. Further, I would like 
> > > > > >> > > objects to
> > > > > >> > > be creatable from JS code,
> > > > > >> > > so I would expose my native constructors to JS. It happens 
> > > > > >> > > that I have
> > > > > >> > > to have a duality between my instances
> > > > > >> > > and JS instances. In my app, I would put a handle to JS 
> > > > > >> > > instance
> > > > > >> > > corresponding to my instance;
> > > > > >> > > and vice versa, I can put a pointer to my instance into 
> > > > > >> > > corresponding
> > > > > >> > > JS instance, by using
> > > > > >> > > Object::SetInternalField(), and using a value of type External.
> >
> > > > > >> > > Now to my question. What I really don't understand - how can I 
> > > > > >> > > know
> > > > > >> > > that a JS object is being destroyed?
> > > > > >> > > I really need to know that, at least in order to destroy my 
> > > > > >> > > instance
> > > > > >> > > attached to the one being destroyed in JS.
> >
> > > > > > --
> > > > > > v8-users mailing list
> > > > > > [email protected]
> > > > > >http://groups.google.com/group/v8-users
> 


-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users

Reply via email to