[webkit-help] javascriptcore: modified Interpreter::throwException to traverse the whole callstack

Guy Hermann guy.hermann at 4d.com
Tue Feb 19 08:41:01 PST 2013


Hi all,

I've made a slight modification of  Interpreter::throwException method (see below).

The aim is to be able to evaluate if the current CallFrame OR ONE OF ITS CALLERS has an exception handler: the modification consists in a loop that traverses the call stack (frames) to perform this evaluation.
We encounter a pb when the whole call stack consists in pure JavaScript code that calls (thanks to a javascript 'eval' instruction) C++-coded classes which generate an exception.
Indeed the condition that ends the loop  ('if (noCaller || hasHostCallFrame)')is reached although it is perfectly clear that we have not reached the end of the stack.
Furthermore, it seems that, once hasHostCallFrameFlag() is true, the call frame cFrame  is really not usable except for calling hasHostCallFrameFlag(): but it it not the last call frame.

Is this a feature or a known problem?

Is there is another way to traverse the call stack of the current frame even when hasHostCallFrameFlag() is true?

thanks for your help

BR
GH

NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
{
    CodeBlock* codeBlock = callFrame->codeBlock();
    bool isInterrupt = false;

    // Set up the exception object
    if (exceptionValue.isObject()) {
        JSObject* exception = asObject(exceptionValue);

        if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
            appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);

        // Using hasExpressionInfo to imply we are interested in rich exception info.
        if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
            ASSERT(codeBlock->hasLineInfo());

            // FIXME: should only really be adding these properties to VM generated exceptions,
            // but the inspector currently requires these for all thrown objects.
            addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
        }

        ComplType exceptionType = exception->exceptionType();
        isInterrupt = exceptionType == Interrupted || exceptionType == Terminated;
    }

    if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {

/*************    START  MODIFS  ******************/

  bool    hasHandler = false;
  unsigned   bcOffset = bytecodeOffset;
  CodeBlock*   cBlock = codeBlock;
  CallFrame*   cFrame = callFrame;
  while ( cFrame != 0 && cFrame != CallFrame::noCaller() && !cFrame->hasHostCallFrameFlag() )
  {
#if ENABLE(JIT)
   ReturnAddressPtr   returnPC = cFrame->returnPC();
#else
   JSC::Instruction*   returnPC = cFrame-> returnVPC();
#endif
   if ( cBlock == 0 )
    cFrame = 0;
   else
   {
    hasHandler = cBlock->handlerForBytecodeOffset( bcOffset );
    if ( hasHandler )
     break;

    cFrame = cFrame->callerFrame();
    bool noCaller = ( cFrame == CallFrame::noCaller() );
    bool hasHostCallFrame = cFrame->hasHostCallFrameFlag();
    if ( noCaller || hasHostCallFrame )
    {
     break;
    }

    JSObject*   jsFuncCallee = cFrame->callee();
    if ( jsFuncCallee == 0 )
     break;

    cBlock = cFrame->codeBlock();
#if ENABLE(JIT)
    bcOffset = cBlock->bytecodeOffset(ReturnAddressPtr(returnPC));
#else
    bcOffset = cBlock->bytecodeOffset(returnPC);
#endif
   }
  }

/************* END   MODIFS ******************/

        DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
        //bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
        debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler);
    }

    // Calculate an exception handler vPC, unwinding call frames as necessary.
    HandlerInfo* handler = 0;
    while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
            if (Profiler* profiler = *Profiler::enabledProfilerReference())
                profiler->exceptionUnwind(callFrame);
            return 0;
        }
    }

    if (Profiler* profiler = *Profiler::enabledProfilerReference())
        profiler->exceptionUnwind(callFrame);

    // Shrink the JS stack, in case stack overflow made it huge.
    Register* highWaterMark = 0;
    for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
        CodeBlock* codeBlock = callerFrame->codeBlock();
        if (!codeBlock)
            continue;
        Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters;
        highWaterMark = max(highWaterMark, callerHighWaterMark);
    }
    m_registerFile.shrink(highWaterMark);

    // Unwind the scope chain within the exception handler's call frame.
    ScopeChainNode* scopeChain = callFrame->scopeChain();
    int scopeDelta = 0;
    if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
        || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
        scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth;
    ASSERT(scopeDelta >= 0);
    while (scopeDelta--)
        scopeChain = scopeChain->pop();
    callFrame->setScopeChain(scopeChain);

    return handler;
}




[cid:01e447.png at 17f19175.439de047]
Guy Hermann
Développeur Senior
Email : guy.hermann at 4d.com<mailto:guy.hermann at 4d.com>
Web :   www.4D.com<http://www.4D.com>

4D SAS
60, rue d'Alsace
92110 Clichy -
Standard :      +33 1 40 87 92 00




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-help/attachments/20130219/83bd31fe/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 01e447.png
Type: image/png
Size: 4628 bytes
Desc: 01e447.png
URL: <http://lists.webkit.org/pipermail/webkit-help/attachments/20130219/83bd31fe/attachment-0001.png>


More information about the webkit-help mailing list