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:[email protected]]
Guy Hermann
Développeur Senior
Email : [email protected]<mailto:[email protected]>
Web : www.4D.com<http://www.4D.com>
4D SAS
60, rue d'Alsace
92110 Clichy -
Standard : +33 1 40 87 92 00
<<inline: 01e447.png>>
_______________________________________________ webkit-help mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-help
