Where to detect JS::HeapValue.ptr change?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Where to detect JS::HeapValue.ptr change?

answerwinner
Hi
I'm using SpiderMonkey 33 with --enable-generational and --enable-exactrooting.

I have 2 maps:
------------------------------------------
typedef int JSOBJID;
map<JSOBJID, JS::HeapValue> map1;
map<uint64 /* this is JS::Value.asRawBits() */ , JSOBJID> map2;
------------------------------------------

I want to maintain map1 and map2 exactly one to one.
I know that HeapValue.ptr can be modified during GC,
so I think I have to REBUILD map2 whenever HeapValue.ptr in map1 changed.

Where do I put the REBUILD code? i.e. where can I detect HeapValue.ptr has been changed???

I've tried these 2 ways, but they didn't work correctly:
-----------------------------------------------------------------------
// rebuild map2 in GC callback
void MyJSGCCallback(JSRuntime *rt, JSGCStatus status, void *data)
{
        if (status == JSGC_BEGIN)
                clearMap2();
        else if (status == JSGC_END)
                rebuildMap2();
}
JS_SetGCCallback(rt, MyJSGCCallback, 0);

// rebuild map2 in Finalize Callback
void MyJSFinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartment, void *data)
{
        if (status == JSFINALIZE_GROUP_START)
                clearMap2();
        else if (status == JSFINALIZE_COLLECTION_END)
                rebuildMap2();
}
JS_AddFinalizeCallback(rt, MyJSFinalizeCallback, 0);

-----------------------------------------------------------------------

Thank you for your help!
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Where to detect JS::HeapValue.ptr change?

Terrence Cole-3
Neither of those callbacks are called during minor collections. You will
want to instead use JS_SetObjectsTenuredCallback.

Cheers,
Terrence

On Sun, Mar 13, 2016 at 11:11 PM, <[hidden email]> wrote:

> Hi
> I'm using SpiderMonkey 33 with --enable-generational and
> --enable-exactrooting.
>
> I have 2 maps:
> ------------------------------------------
> typedef int JSOBJID;
> map<JSOBJID, JS::HeapValue> map1;
> map<uint64 /* this is JS::Value.asRawBits() */ , JSOBJID> map2;
> ------------------------------------------
>
> I want to maintain map1 and map2 exactly one to one.
> I know that HeapValue.ptr can be modified during GC,
> so I think I have to REBUILD map2 whenever HeapValue.ptr in map1 changed.
>
> Where do I put the REBUILD code? i.e. where can I detect HeapValue.ptr has
> been changed???
>
> I've tried these 2 ways, but they didn't work correctly:
> -----------------------------------------------------------------------
> // rebuild map2 in GC callback
> void MyJSGCCallback(JSRuntime *rt, JSGCStatus status, void *data)
> {
>         if (status == JSGC_BEGIN)
>                 clearMap2();
>         else if (status == JSGC_END)
>                 rebuildMap2();
> }
> JS_SetGCCallback(rt, MyJSGCCallback, 0);
>
> // rebuild map2 in Finalize Callback
> void MyJSFinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool
> isCompartment, void *data)
> {
>         if (status == JSFINALIZE_GROUP_START)
>                 clearMap2();
>         else if (status == JSFINALIZE_COLLECTION_END)
>                 rebuildMap2();
> }
> JS_AddFinalizeCallback(rt, MyJSFinalizeCallback, 0);
>
> -----------------------------------------------------------------------
>
> Thank you for your help!
> _______________________________________________
> dev-tech-js-engine mailing list
> [hidden email]
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Where to detect JS::HeapValue.ptr change?

Steve Fink-4
In reply to this post by answerwinner
Except that this is SM 33, and doubt JS_SetObjectsTenuredCallback
existed back then.

What you're doing sounds pretty funky. Just to maintain map1, you're
going to have to trace all of its contents, which means keeping them all
alive. Or if you mean map1 to hold them weakly, you'll still need to
sweep map1 (calling isAboutToBeFinalized on every value and removing the
entry if it returns true -- iATBF will update the pointer as a side
effect). But I would guess that map1 can hold objects from multiple
compartments, which requires special handling that I don't even want to
think about right now.

And then you have map2, which has mostly the same problems. Though if
you can get away with rebuilding it on every GC (including minor GCs), I
guess you're ok. (Or alternatively, if only certain objects need your
JSOBJIDs, make sure they are pre-tenured (aka never allocated in the
nursery). Then at least you don't need to worry about minor GCs.).

And while funky, note that Terrence implemented something very similar
in Firefox 44, bug 1196847. It gives objects unique ids, but just those
objects that need it (as in, they are placed into a map that keys off of
the object's identity.) Previously, we "rekeyed" all collections that
were keyed off of movable pointers. You might want to look at what he
did there to see how to handle all of the tricky bits, or perhaps
upgrade to a newer version and use his uids as part of your stuff.

On 03/14/2016 09:30 AM, Terrence Cole wrote:

> Neither of those callbacks are called during minor collections. You will
> want to instead use JS_SetObjectsTenuredCallback.
>
> Cheers,
> Terrence
>
> On Sun, Mar 13, 2016 at 11:11 PM, <[hidden email]> wrote:
>
>> Hi
>> I'm using SpiderMonkey 33 with --enable-generational and
>> --enable-exactrooting.
>>
>> I have 2 maps:
>> ------------------------------------------
>> typedef int JSOBJID;
>> map<JSOBJID, JS::HeapValue> map1;
>> map<uint64 /* this is JS::Value.asRawBits() */ , JSOBJID> map2;
>> ------------------------------------------
>>
>> I want to maintain map1 and map2 exactly one to one.
>> I know that HeapValue.ptr can be modified during GC,
>> so I think I have to REBUILD map2 whenever HeapValue.ptr in map1 changed.
>>
>> Where do I put the REBUILD code? i.e. where can I detect HeapValue.ptr has
>> been changed???
>>
>> I've tried these 2 ways, but they didn't work correctly:
>> -----------------------------------------------------------------------
>> // rebuild map2 in GC callback
>> void MyJSGCCallback(JSRuntime *rt, JSGCStatus status, void *data)
>> {
>>          if (status == JSGC_BEGIN)
>>                  clearMap2();
>>          else if (status == JSGC_END)
>>                  rebuildMap2();
>> }
>> JS_SetGCCallback(rt, MyJSGCCallback, 0);
>>
>> // rebuild map2 in Finalize Callback
>> void MyJSFinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool
>> isCompartment, void *data)
>> {
>>          if (status == JSFINALIZE_GROUP_START)
>>                  clearMap2();
>>          else if (status == JSFINALIZE_COLLECTION_END)
>>                  rebuildMap2();
>> }
>> JS_AddFinalizeCallback(rt, MyJSFinalizeCallback, 0);
>>
>> -----------------------------------------------------------------------
>>
>> Thank you for your help!
>> _______________________________________________
>> dev-tech-js-engine mailing list
>> [hidden email]
>> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>>

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine