Assertion failure on debug, what is wrong?

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

Assertion failure on debug, what is wrong?

Mihai Dobrescu
Hello,

I've compiled SpiderMonkey 45 against mingw with debug activated.
I have the following error at runtime in my test project, under Windows:

Assertion failure: stackRoots_[i] == nullptr

The code looks like this:

// The class of the global object.
static JSClass global_class = {
    "global",
    JSCLASS_GLOBAL_FLAGS,
    0,                        //JSAddPropertyOp
    0,                        //JSDeletePropertyOp
    0,                        //JSGetterOp
    0,                        //JSSetterOp
    0,                        //JSEnumerateOp
    0,                        //JSResolveOp
    0,                        //JSMayResolveOp
    0,                        //FinalizeOpType
    0,                        //JSNative
    0,                        //JSHasInstanceOp
    0,                        //JSNative
    JS_GlobalObjectTraceHook, //JSTraceOp <-- this is to avoid another assertion failure
};

int main(int argc, const char *argv[])
{
    JS::RootedObject *global;

    JS_Init();

    JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024);
    if (!rt)
        return 1;

    /*JSErrorReporter er = */JS_SetErrorReporter(rt, &dispatchError);

    JSContext *cx = JS_NewContext(rt, 8192);
    if (!cx)
        return 1;

    // Scope for our various stack objects (JSAutoRequest, RootedObject), so they all go
    // out of scope before we JS_DestroyContext.
    {
        JSAutoRequest ar(cx); // In practice, you would want to exit this any
                              // time you're spinning the event loop

        //JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
        global = new JS::RootedObject(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
        if (!global)
            return 1;

        JS::RootedValue rval(cx);

        // Scope for JSAutoCompartment
        {
            JSAutoCompartment ac(cx, *global);
            JS_InitStandardClasses(cx, *global);

            //ok = JS_DefineFunction(cx, global, "doit", doit, 2, 0);
            /*bool ok = JS_DefineFunctions(cx, *global, my_functions);
            if (!ok)
                return 1;*/

            JSObject *fProtoObj = JS_InitClass(cx, *global, nullptr, &test_class,
                /*class_construct*/ NULL, 0,
                NULL, test_class_functions, NULL, NULL);
            if (!fProtoObj)
                return 1;

            jsClass::DefineClasses(cx, *global);

            //const char *script = "var x = 'hello' + 'world, it is ' + new Date(); y = doit(2, 3); x + '\\n' + String(y); ";

            //const char *script = "var x = 'hello' + 'world, it is ' + new Date(); y = doit(2, 3); x + '\\n' + String(y);";
            //const char *script = "var x = 'hello' + 'world, it is ' + new Date(); y = TestClass.doit(2, 3); x + '\\n' + String(y);";

            //const char *script = "var r = new AIRealPoint(1, 1); String(r.h);";
            const char *script = "var r = 2.2; r.toString();";

            //
            //            const char *script = "/*\
            //var abruzzi = new person();\
            //            abruzzi.name = \"abruzzi\";\
            //            abruzzi.address = \"Huang Quan Road\";\
            //            */\
            //\
            //                //undefined of course\
            //                person.print();\
            //\
            //            //person.name = \"abruzzi\";\
            //            //person.address = \"Huang Quan Road\";\
            //\
            //            person.setName(\"abruzzi\");\
            //            person.setAddress(\"HuangQuan Road\");\
            //\
            //            person.print();\
            //\
            //            (function() {\
            //                return person.getName() + \" : \" + person.getAddress();\
            //            })();\
            // ";

            const char *filename = "noname";
            int lineno = 1;

            JS::CompileOptions opts(cx);
            opts.setFileAndLine(filename, lineno);
            bool ok = JS::Evaluate(cx/*, *global*/, opts, script, strlen(script), &rval);
            if (!ok)
                return 1;
        }

        if (rval.isString())
        {
            JSString *str = rval.toString();
            if (str)
                printf("%s\n", JS_EncodeString(cx, str));
        }
    }

    JS_DestroyContext(cx);

    JS_DestroyRuntime(rt);
    JS_ShutDown();

    global = NULL;

    wait();

    return 0;
}

What did I do wrong?

Thank you.
_______________________________________________
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: Assertion failure on debug, what is wrong?

Nicolas B. Pierron
On 08/27/2016 09:06 AM, Mihai Dobrescu wrote:
> Assertion failure: stackRoots_[i] == nullptr
>
 > […]
 >
>          global = new JS::RootedObject(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook));
>          if (!global)
>              return 1;

The problem might comes from here.

>
> What did I do wrong?


Rooted are meant to live on the stack. When the are constructed, they push
they address into a linked list of rooted values. The assertion you got is
likely coming from the pop-ing mechanism not working as a stack.

You should rewrite you code as follow:

     // no pointer, as this is already a pointer to a null global object.
     RootedGlobal global(cx);

     […]

     global = JS_NewGlobalObject(cx, &global_class, nullptr,
                                 JS::FireOnNewGlobalHook);
     if (!global)
         return 1;

--
Nicolas B. Pierron
_______________________________________________
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: Assertion failure on debug, what is wrong?

Mihai Dobrescu
True in this case.

But what if I need to make a class with a "global" member?
_______________________________________________
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: Assertion failure on debug, what is wrong?

Boris Zbarsky
On 8/29/16 10:13 AM, Mihai Dobrescu wrote:
> But what if I need to make a class with a "global" member?

Then you either use a PersistentRooted<JSObject*> member (if you want it
to be a permanent GC root until the class instance is destroyed) or a
Heap<JSObject*> and trace it if you want to participate in GC.

-Boris

_______________________________________________
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: Assertion failure on debug, what is wrong?

Mihai Dobrescu
On Monday, August 29, 2016 at 6:59:50 PM UTC+3, Boris Zbarsky wrote:
> On 8/29/16 10:13 AM, Mihai Dobrescu wrote:
> > But what if I need to make a class with a "global" member?
>
> Then you either use a PersistentRooted<JSObject*> member (if you want it
> to be a permanent GC root until the class instance is destroyed) or a
> Heap<JSObject*> and trace it if you want to participate in GC.
>
> -Boris

If you're suggesting using JS::PersistentRootedObject, I don't get it working in debug, I got assertions failures all the time, what is the "protocol" using it in my case? Is there a consistent sample somewhere?
_______________________________________________
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: Assertion failure on debug, what is wrong?

Steve Fink-4
On 08/30/2016 10:16 PM, Mihai Dobrescu wrote:

> On Monday, August 29, 2016 at 6:59:50 PM UTC+3, Boris Zbarsky wrote:
>> On 8/29/16 10:13 AM, Mihai Dobrescu wrote:
>>> But what if I need to make a class with a "global" member?
>>
>> Then you either use a PersistentRooted<JSObject*> member (if you want it
>> to be a permanent GC root until the class instance is destroyed) or a
>> Heap<JSObject*> and trace it if you want to participate in GC.
>>
>> -Boris
>
> If you're suggesting using JS::PersistentRootedObject, I don't get it working in debug, I got assertions failures all the time, what is the "protocol" using it in my case? Is there a consistent sample somewhere?


What assertions?

To use PersistentRooted, make it a field of your class/struct and
initialize it with a cx or rt in the constructor of your class/struct.

struct MyThing {
   PersistentRootedObject global;

   MyThing(JSContext* cx) : global(cx) {}
};

It's not the greatest code to read in general, but js/src/shell/js.cpp
has some examples of using PersistentRooted things.

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