Met a serious problem in JSB memory model research

75 views
Skip to first unread message

huabi...@cocos2d-x.org

unread,
Jul 28, 2014, 10:56:37 PM7/28/14
to cocos2d-...@googlegroups.com
Hi, all,

I'm trying to change the memory model in JSB. In fact, there are always two garbage collection systems in JSB: Cocos2d-x's reference count system and SpiderMonkey's GC.

General Problem: 
There are actually two objects for one node created in JSB, the native object and the js object, today we control mainly the native object, but we don't have a solution to release the js object while releasing native object. So we often need to use retain/release explicitly in js to keep native object alive to avoid being releasing while we still need those object in js. As js developers are not so familiar with reference count GC system, they don't know how to use correctly retain/release, this due to many memory releasing/leaking problems.

Solution:
The idea is to manager native object by js object life cycle, so I try to retain automatically the native object during creation, and release them during "finalize" hook function of SpiderMonkey (it will be invoked while the corresponding js object being garbage collected). Detailed document can be found here: 

The issue I met:
I found that extended classes in JS won't have the finalize hook, so when user inherit "cc.Layer" in JS, the custom layer class won't release the native object during GC. I succeeded in replace the prototype of custom classes with the following implementation :

// jsb.create_prototype(superProto);

bool jsb_create_prototype(JSContext *cx, uint32_t argc, jsval *vp)

{

    jsval *argv = JS_ARGV(cx, vp);


    JSObject *super_prototype;
    super_prototype
= JSVAL_TO_OBJECT(argv[0]);

    const JSClass *super_class = JS_GetClass(super_prototype);


    JSObject *global = ScriptingCore::getInstance()->getGlobalObject();

    JSClass *js_class;

    js_class = (JSClass *)calloc(1, sizeof(JSClass));

    js_class->name = "";

    js_class->addProperty = JS_PropertyStub;

    js_class->delProperty = JS_DeletePropertyStub;

    js_class->getProperty = JS_PropertyStub;

    js_class->setProperty = JS_StrictPropertyStub;

    js_class->enumerate = JS_EnumerateStub;

    js_class->resolve = JS_ResolveStub;

    js_class->convert = JS_ConvertStub;

    // Important!

    js_class->finalize = super_class->finalize;

    js_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);


    JSObject *jsb_prototype = JS_InitClass(

        cx, global,

        super_prototype,

        js_class,

        NULL, 0, // constructor

        NULL, NULL, NULL, NULL);


    jsval jsret = JSVAL_NULL;

    if (jsb_prototype) {

        jsret = OBJECT_TO_JSVAL(jsb_prototype);

    }


    JS_SET_RVAL(cx, vp, jsret);

    return true;

}


And I tested the result, user custom classes now have the correct finalize function registered, but the "finalize" functions are still not invoked, so I'm trapped here

Can anyone help me with this annoying issue ?

Thanks in advance!

Huabin

Xiaoming Zhang

unread,
Jul 29, 2014, 1:53:46 AM7/29/14
to huabi...@cocos2d-x.org, cocos2d-...@googlegroups.com
It is better to have a survey in forum for changing memory model during doing the task.
Lua binding has a survey for changing memory model.
Because some developers suggestion not modifying current design.
They concern the stability and efficiency after changing.

Best Regards
Minggo




--
You received this message because you are subscribed to the Google Groups "cocos2d JS development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cocos2d-js-dev...@googlegroups.com.
To post to this group, send email to cocos2d-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

LING HUABIN

unread,
Jul 29, 2014, 2:07:09 AM7/29/14
to Xiaoming Zhang, cocos2d-...@googlegroups.com
Thanks for your suggestion Minggo

You are right I will find a way to collection feedbacks from important users, unfortunately, I don't think our js forum is active enough to have a high quality discussion on it. Still I will try to find a way.
And I'm still working on crucial technique obstacles like this one, and only after this, I can have real data on stability and efficiency. I think discussion based on concrete results will be better.

Best regards
Huabin

Ricardo Quesada

unread,
Aug 21, 2014, 6:14:44 PM8/21/14
to LING HUABIN, Xiaoming Zhang, cocos2d-...@googlegroups.com
Hi,

<meta discussion>
As it was discussed on yesterday's meeting, lets continue this discussion on the cocos2d-x forum.
What is the category created for that ?
</meta discussion>


Ling,
So, if the "finalize" callback is not being called, it means either that:
 a) There is a bug in the SpiderMonkey VM. SpiderMonkey is leaking memory. It doesn't matter what memory model we use, it means that SpiderMonkey, right now, is leaking memory.
 b) or that we are not using the correct API.

Is that correct ?

Perhaps it is a bug in the SpiderMonkey that we are using, but I remember that the "finalize" callback was being called in my objects.
My suggestion is to double-check that we are using the correct API.
Just put some breakpoints on some "finalize" callbacks from JS objects, like JS_Number and see if it is being called when you force the Collect in the GC.
If finalize is being called, then it means that "finalize" works, but we are not using the API in the correct way.
if finalize is not being called, it means that we are using an unstable version of SpiderMonkey and we should upgrade it.


Regarding whether to implement retain/release, yes, we need to do that.

Thanks.

PS: Please, once the "development" category is created in the cocos2d-x forum, please create a post there and let's continue this discussion there.

huabi...@cocos2d-x.org

unread,
Aug 22, 2014, 12:12:31 AM8/22/14
to cocos2d-...@googlegroups.com, huabi...@cocos2d-x.org, xiaomin...@cocos2d-x.org
Hi, Riq

Thanks for your reply.

Finalize function if the only GC hook function linked with JSClass, but you are right, maybe I can also link the hook with objects, I will look into it.
I think what I met is a bug of SpiderMonkey, there is no issue when a engine class object get released by the GC, its finalize function will get invoked, but when user extend from our engine classes, like the following example

```
var sprite = new cc.Sprite();

var MySprite = cc.Sprite.extend({
    ...
})
var mySprite = new MySprite();
```

Then when sprite get garbage collected, it will trigger the finalize function, but mySprite won't trigger the finalize. This is normal, because prototypes don't share finalize function, and finalize function is not visible in javascript scope so our extend can not copy it neither.
That's why I came up with the previous solution described in this topic, unfortunately, even if I succeed in injecting the finalize function hook into MySprite.prototype, this function still don't get invoked. I believe this is a strange issue in SpiderMonkey.

I will look into object's finalize hook, and try to upgrade SpiderMonkey when v31 available, I will also post a topic in Mozilla's dev group.

btw. About forum, You mean we should move this topic to Cocos2d-x forum ?

Bests

Huabin

Ricardo Quesada

unread,
Aug 26, 2014, 3:05:15 PM8/26/14
to LING HUABIN, cocos2d-...@googlegroups.com, XiaoMing Zhang
Hi,

Thanks. Yes, asking in the Mozilla forum could help. They also have an IRC chat, but I don't expect that you will find the answer in the IRC.

Regarding the forum, yes: we should stop using this list to discuss development stuff. Instead we should use the cocos2d-x forum. But the "development" category needs to be created first.

Thanks.

huabi...@cocos2d-x.org

unread,
Aug 27, 2014, 6:02:00 AM8/27/14
to cocos2d-...@googlegroups.com, huabi...@cocos2d-x.org, xiaomin...@cocos2d-x.org
OK, no problem, I will send the mail to Mozilla once our release tasks get done.

And I will create a new post in the development when it's available.

Huabin
Reply all
Reply to author
Forward
0 new messages