Discussion of Lifecycle between JS and Native objects

Hi all, I am one of the maintainers of Cocos2d-X JSB. I wish to discuss the issue the title says with you.

Currently, we are using the c*+ object’s lifecycle to control JS object’s.
Why?
Once a c*+ object is not needed, I mean that its reference count is 0, the memory of c*+ objects will be removed immediately.
In the destructor of Object, it will unroot the JS object. In that case, the JS object will be controlled by Garbage Collection again.
Side effect:
If a node is not added to other node, the corresponding c*+ object will be deleted at the end of current rendering frame.
When we use it again in JS, it will cause Invaild native Objects error.
To fix that, retain needs to called in JS, and when that object is not needed, developer has to release it manually. Otherwise, it will cause memory leaks.
As you know, retain, release stuff are not Javascript Friendly and it’s not compatible with cocos2d-html5. Do we need to get rid of them in JSB?

Solution:

Try to use JS object’s lifecycle to control native object’s.

void js_XXX_XXX_finalize(JSFreeOp *fop, JSObject *obj) {
// Release native objects here.
}

Problems:

A lot of memory of c*+ objects will be allocated if GC doesn’t come. It’s because Spidermonkey don’t know how much memory c*+ allocated. It just take care of the memory of JS objects.
In this way, the memory will grow very fast.

This issue might be resolved after Cocos2d-X has its own memory manager. Memory Manager will count the the cost of memory of c*+ objects.
And if JS find that the memory in c*+ is too much, then it will try to do a GC operation.

Any suggestion will be appreciated. :slight_smile:

James

Thanks for starting this discussion. I have faced a lot of issues because of this.

Is it not possible to set the JS object to null from C++ if the object gets released?

Thanks for the explanation.

I had my own explanation like this.
For a Node instance, when i remove a child and do not add it to other Node in this frame, it will be no longer useable, even though there is other reference in javascript.
Because there is no C*+ reference and C*+ do not know the javascript reference. To fix that, use retain and release to manually control it but do not forget to release the memory.

For other binding C*+ object, it should be hold in scene or layer or sprite or other static instance. We can not keep it only in a javascript variable.
Is there any mistake above?

In my project, i use the fmod library for a sound system. I create a static instance for fmod, and use a static binding method to access it in javascript.
Can it work like this? And where should i handle the release method? I think it is not correct in applicationDidEnterBackground.
In android, it maybe correct that write a jni method in OnDestroy. But how do it all in C*+ code, since i know nothing about IOS. Or should i Keep it in the Director?

Shuja Shabandri wrote:

Thanks for starting this discussion. I have faced a lot of issues because of this.
>
Is it not possible to set the JS object to null from C++ if the object gets released?

Good point. But I didn’t find the Spidermonkey API to set JS object to null. :frowning:

James Chen wrote:

Good point. But I didn’t find the Spidermonkey API to set JS object to null. :frowning:

If we keep a pointer to JSObject which is created in the bindings by defining a *jsref in base Object class, which by default points to nothing of course.

When the object’s destructor is called, can we not call jsref destructor? Would that work?

Shuja Shabandri wrote:

James Chen wrote:
> Good point. But I didn’t find the Spidermonkey API to set JS object to null. :frowning:
>
If we keep a pointer to JSObject which is created in the bindings by defining a jsref in base Object class, which by default points to nothing of course.
>
When the object’s destructor is called, can we not call jsref destructor? Would that work?
What did you mean
jsref* ?

James Chen wrote:

What did you mean jsref ?

What I mean is the JSObject which is returned by JS_NewObject API

Maybe it’s a good idea to just set js object to null when c++ release the object.