[Webkit-unassigned] [Bug 136313] New: ASSERTION FAILED: from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer<To>::type::info()) in JSC::jsCast(JSC::JSValue) [with To = JSC::JSScope*]

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Aug 27 14:47:22 PDT 2014


           Summary: ASSERTION FAILED: from.isCell() &&
                    >::type::info()) in JSC::jsCast(JSC::JSValue) [with To
                    = JSC::JSScope*]
           Product: WebKit
           Version: 528+ (Nightly build)
          Platform: Unspecified
        OS/Version: Unspecified
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: JavaScriptCore
        AssignedTo: webkit-unassigned at lists.webkit.org
        ReportedBy: akiss at inf.u-szeged.hu
                CC: ossy at webkit.org, zandobersek at gmail.com,
                    msaboff at apple.com, gyuyoung.kim at webkit.org

When running tests on EFL/ARM64 (compiled with gcc), jsc segfaults on scripts containing eval() with "ASSERTION FAILED: from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer<To>::type::info())". The simplest test case to cause the assertion is:

var c = "";

The backtrace is always as follows:

Program received signal SIGSEGV, Segmentation fault.
0x0000000001098298 in WTFCrash () at /home/akiss/devel/WebKit/Source/WTF/wtf/Assertions.cpp:329
329        *(int *)(uintptr_t)0xbbadbeef = 0;
(gdb) bt
#0  0x0000000001098298 in WTFCrash ()
    at /home/akiss/devel/WebKit/Source/WTF/wtf/Assertions.cpp:329
#1  0x0000000000aed314 in JSC::jsCast<JSC::JSScope*> (from=...)
    at /home/akiss/devel/WebKit/Source/JavaScriptCore/runtime/JSCell.h:241
#2  0x0000000000ae8270 in JSC::Register::scope (this=0x7fffffe598)
    at /home/akiss/devel/WebKit/Source/JavaScriptCore/runtime/JSScope.h:236
#3  0x0000000000ae3d38 in JSC::ExecState::scope (this=0x7fffffe580)
    at /home/akiss/devel/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h:50
#4  0x0000000000bdd8dc in JSC::eval (callFrame=0x7fffffe550)
    at /home/akiss/devel/WebKit/Source/JavaScriptCore/interpreter/Interpreter.cpp:108
#5  0x0000000000c24fbc in JSC::operationCallEval (exec=0x7fffffe5a0, execCallee=0x7fffffe550)
    at /home/akiss/devel/WebKit/Source/JavaScriptCore/jit/JITOperations.cpp:619
#6  0x0000007fb4ca3cec in ?? ()
#7  0x0000007fb43ff970 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

It seems that for JSC:eval the callFrame parameter is not set up properly: its CallerFrameAndPC component is not filled in. A little bit of analysis follows.

The bytecode for the script is:

[   0] enter             
[   1] mov               loc0, Undefined(@k0)
[   4] resolve_scope     loc1, c(@id0), 1<ThrowIfNotFound|GlobalVar>, 0
[  10] put_to_scope      loc1, c(@id0), String (atomic) (identifier): , ID: 5(@k1), 65537<DoNotThrowIfNotFound|GlobalVar>, <structure>, 26182392
[  17] resolve_scope     loc3, eval(@id1), 0<ThrowIfNotFound|GlobalProperty>, 0
[  23] get_from_scope    loc1, loc3, eval(@id1), 0<ThrowIfNotFound|GlobalProperty>, <structure>, 120
[  31] resolve_scope     loc2, c(@id0), 1<ThrowIfNotFound|GlobalVar>, 0
[  37] get_from_scope    loc2, loc2, c(@id0), 1<ThrowIfNotFound|GlobalVar>, <structure>, 26182392
[  45] call_eval         loc0, loc1, 2, 10    Original; predicting None
[  54] end               loc0

The relevant JIT code compiled for the script:

[  45] call_eval         loc0, loc1, 2, 10    Original; predicting None
        0x7fb4ca3ca4:    sub    sp, fp, #64        // fp already points to the current ExecState, this will be exec for operationCallEval; start making space for execCallee on the stack (however, sp does *not* point to execCallee but to &(execCallee + JSStack::CallerFrameAndPCSize) )
        0x7fb4ca3ca8:    mov    w16, #0x2
        0x7fb4ca3cac:    stur   w16, [sp, #24]        // execCallee[JSStack::ArgumentCount] = 2
        0x7fb4ca3cb0:    movk   w16, #45
        0x7fb4ca3cb4:    stur   w16, [fp, #44]
        0x7fb4ca3cb8:    ldur   x0, [fp, #-16]
        0x7fb4ca3cbc:    stur   x0, [sp, #16]        // execCallee[JSStack::Callee] = loc1
        0x7fb4ca3cc0:    sub    x1, sp, #16        // now, x1 *does* point to the right place, i.e., to execCallee
        0x7fb4ca3cc4:    mov    x0, fp            // x0 points to exec
        0x7fb4ca3cc8:    movk   w16, #46
        0x7fb4ca3ccc:    stur   w16, [fp, #44]
        0x7fb4ca3cd0:    movz   x17, #55504
        0x7fb4ca3cd4:    movk   x17, #397, lsl #16
        0x7fb4ca3cd8:    str    fp, [x17, xzr]
        0x7fb4ca3cdc:    movz   x16, #20176        // 20176 = 0x4ed0
        0x7fb4ca3ce0:    movk   x16, #194, lsl #16    // 194 = 0xc2
        0x7fb4ca3ce4:    movk   x16, #0, lsl #32
        0x7fb4ca3ce8:    blr    x16             // call JSC::operationCallEval (exec=x0, execCallee=x1)

Then, in operationCallEval:

EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
    // ...
    // ...
    JSValue result = eval(execCallee);

So, the rest of execCallee is set up "below sp", but CallerFrameAndPC is *not*, because the call to operationCallEval and its prologue is expected to put the return address on top of sp, and the caller frame on top of that, thus making execCallee complete. However, the prologue does not behave as expected (at least on ARM/EFL, and compiled with gcc). The disassembled code starts with:

Dump of assembler code for function JSC::operationCallEval(JSC::ExecState*, JSC::ExecState*):
   0x0000000000c24ed0 <+0>:    stp    x29, x30, [sp,#-64]!
   0x0000000000c24ed4 <+4>:    mov    x29, sp
   0x0000000000c24ed8 <+8>:    str    x0, [x29,#24]
   0x0000000000c24edc <+12>:    str    x1, [x29,#16]
   0x0000000000c24ee0 <+16>:    ldr    x0, [x29,#24]

That is, sp is "hoisted too much" in one step, making space for fp/x29 (the pointer to caller frame) and lr/x30 (the return address), which is good, and for whatever temporary space is needed (which is bad). "stp fp, lr, [sp, #-16]!" would be the expected first step here, it seems. However, this is in the hands of the compiler...

Fortunately, the first parameter of operationCallEval, exec, points to the frame we need, so adding "execCallee->setCallerFrame(static_cast<CallFrame*>(exec));" to operationCallEval might solve the problem. (If I'm right.) The return address is still not set by this approach, however.

This issue seems to be related to https://bugs.webkit.org/show_bug.cgi?id=127777 , which is fixed (with workaround) in https://bugs.webkit.org/show_bug.cgi?id=127898 and in https://bugs.webkit.org/show_bug.cgi?id=127909 , by passing -fno-omit-frame-pointer to gcc.

Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

More information about the webkit-unassigned mailing list