[webkit-gtk] JavaScriptCore GObject Bindings - Memory Management

Carlos Garcia Campos cgarcia at igalia.com
Fri Mar 17 01:52:20 PDT 2017


El mié, 15-03-2017 a las 14:54 +0900, Yusuke SUZUKI escribió:
> On Fri, Mar 10, 2017 at 9:49 PM, tevaum at gmail.com <tevaum at gmail.com>
> wrote:
> > Hi. I started implementing a JavaScriptCore GObject binding in [1].
> > This API provides two main objects: JSCContext, representing
> > JSGlobalContextRef, and JSCValue, representing JSValueRef. It's a
> > first patch and does't do any memory management, because I wasn't
> > really aware of how JSC handles JSValueRefs and stuff.
> > 
> > Asking on JSC list they replied that JSValues are garbage collected
> > and when you need to keep a reference to it in the heap you should
> > protect them. [2]
> > 
> 
> Yes. JSValues are GC-managed ones. So if it is on machine stack /
> registers, it will be marked and kept alive.
> And once it becomes unreachable, GC automatically collects these
> values.

Thanks for your help Yusuke, we really need help to understand how
things work in JSC to design our API.

> Note that JSValueRef is actually the value type rather than the
> pointer to something. (Internally, it something the pointer to the
> JSString*, JSObject*.)
> It should be always copied. And it should not be allocated in heap
> usually.
>  
> > This is already done by the bindings: JSValueRefs are protected on
> > contruction of JSCValue and unprotected on destruction, but
> > JSCValues were implemented as initially owned and noone's keeping
> > their reference to unref them when needed.
> > 
> 
> I think we should not protect/unprotect in API side automatically.
> And I think we should not represent JSCValue as heap allocated one.
> JSCValue should be represented like gint64 (value type).

What we really have is not a heap allocated JSValueRef, but a heap
allocated GObject wrapper for a JSValueRef. Similar to what JSValue is
in the Objc API, a NSObject wrapping a JSValueRef. So, for example:

JSCValue *jsc_boolean_new (JSCContext *, gboolean);

JSCValue is the wrapper, and this simply calls JSValueMakeBoolean to
create the JSVAlueRef wrapped by this GObject.

In the Objc API values are always protected on construction and
unprotected on destruction. However, it also has API to create managed
values, that I think they are like a weak ref.

> Or if we would like to do that, I think we should separate it from
> the usual JSValue class.
> They are responsibility of API users.
> Consider the following case,
> 
> std::vector<JSValueRef> vector;
> 
> In that case, the elements of the vector is allocated in the heap.
> And GC does not know about this heap area.
> So GC does not mark objects in this heap area. In that case, users
> should protect them.

What we have is something like this:

typedef struct _JSCValuePrivate {
    JSCContext* context;
    JSValueRef value;
} JSCValuePrivate;

And yes, that struct is always heap allocated.

> But if you use JSValueRef usually (not holding it in heap), we do not
> need to protect it explicitly. GC will see your stack and registers.
> 
> I think the above use case is relatively rare: Usually, we create the
> JSValue on the stack and pass it though the registers.
> When we would like to store these values in the heap, we should store
> it in JSArray (js managed object) instead of users' vector or
> something.
> 
> Protecting and unprotecting are just adding and removing the value to
> the set of the GC root set.

So, I guess that if I create a JSValue that is heap allocated on a
context, and then I unprotect it, forcing a full GC would delete the
JSValue immediately, right? I think I tried this for testing when we
started to work on this API and didn't work for me, that's why I'm
asking.

> It is not free, it adds and drops the cell to and from the hash set.
> This is similar to V8's Persistent<>.
>  
> > So in the current state, we are leaking JSCValues and, as JSCValues
> > protect JSValueRefs, memory is never freed.
> > 
> > JavaScriptCore doesn't have any API to directly free JSValueRefs,
> > so JSCValues needs to be destructed to unprotect JSValueRefs.
> > 
> > My thought is to Adopt JSCValues when they are created using a
> > private API in the JSCContext (jscContextAdoptJSCValue(JSCValue*)
> > ?). As JSCValues have a JSCContext reference, we can call
> > jscContextAdoptJSCValue in JSCValue's constructed callback. With
> > this private API, JSCContext will get a JSCValue reference and add
> > it to a HashMap that will map the JSValueRef to the JSCValue. When
> > added to the HashMap, JSCValue will be owned by the context and
> > will be freed when the context is unrefed.
> > 
> > What do you think about this idea?
> > 
> > [1] https://bugs.webkit.org/show_bug.cgi?id=164061
> > [2] https://lists.webkit.org/pipermail/jsc-dev/2016-November/000084
> > .html
> > 
> > _______________________________________________
> > webkit-gtk mailing list
> > webkit-gtk at lists.webkit.org
> > https://lists.webkit.org/mailman/listinfo/webkit-gtk
> > 
> 
> _______________________________________________
> webkit-gtk mailing list
> webkit-gtk at lists.webkit.org
> https://lists.webkit.org/mailman/listinfo/webkit-gtk
-- 
Carlos Garcia Campos
http://pgp.rediris.es:11371/pks/lookup?op=get&search=0xF3D322D0EC4582C3
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 224 bytes
Desc: This is a digitally signed message part
URL: <https://lists.webkit.org/pipermail/webkit-gtk/attachments/20170317/352f87a8/attachment.sig>


More information about the webkit-gtk mailing list