@ricardo wrote:
Hey @pandamicro @zhangxm and rest of the team. I have the following questions:
1) Allocation / Deallocation inconsistencies
Why the deallocation of the proxy is invoked byRef::~Ref()
and not byjs_cocos2d_xxx_finalize()
?The allocation is invoked in the
js_cocos2dx_xxx_constructor()
... so it makes sense to have the deallocation injs_cocos2d_xxx_finalize()
.Example:
bool js_cocos2dx_Sprite_constructor(JSContext *cx, uint32_t argc, jsval *vp) { ... js_proxy_t* p = jsb_new_proxy(cobj, obj); AddNamedObjectRoot(cx, &p->obj, "cocos2d::Sprite"); ... } // finalize is empty void js_cocos2d_Sprite_finalize(JSFreeOp *fop, JSObject *obj) { CCLOGINFO("jsbindings: finalizing JS object %p (Sprite)", obj); } // ~Ref calls this function... in any case, finalize should call it void ScriptingCore::removeScriptObjectByObject(Ref* pObj) { ... jsproxy = jsb_get_js_proxy(nproxy->obj); RemoveObjectRoot(cx, &jsproxy->obj); jsb_remove_proxy(nproxy, jsproxy); ... }
This asymmetric allocation/deallocation is confusing.
2) we should avoid
dynamic_cast
The automatic bindings are doing something like this:cocos2d::Sprite* cobj = new (std::nothrow) cocos2d::Sprite(); cocos2d::Ref *_ccobj = dynamic_cast<cocos2d::Ref *>(cobj); if (_ccobj) { _ccobj->autorelease(); }
There two "bugs" here:
Ref
is a base class, so there is no need is doing a dynamic cast.dynamic_cast
is super expensive... we should avoid it.I guess that code was added in case the
Sprite
is not a subclass ofRef
, but that should be solved in another way... perhaps by adding a parameter in the config file saying "do not callautorelease()
. As it is now, it is not optimal.
But if there are objects that are not subclass ofRef
that are being used here, then they will leak since only~Ref
deallocs the proxy (see question #1)I'm researching how to remove
retain/release
from JS, so expect from me more questions about Spidermonkey/bindings.
Posts: 10
Participants: 3