[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