Changeset 147858 in webkit


Ignore:
Timestamp:
Apr 6, 2013, 3:47:56 PM (12 years ago)
Author:
[email protected]
Message:

Unify the many and varied stack trace mechanisms, and make the result sane.
https://bugs.webkit.org/show_bug.cgi?id=114072

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Makes JSC::StackFrame record the bytecode offset and other necessary data
rather than requiring us to perform eager evaluation of the line number, etc.
Then remove most of the users of retrieveLastCaller, as most of them were
using it to create a stack trace in a fairly incomplete and inefficient way.

StackFrame now also has a couple of helpers to get the line and column info.

  • API/JSContextRef.cpp:

(JSContextCreateBacktrace):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitDebugHook):

  • interpreter/Interpreter.cpp:

(JSC):
(JSC::Interpreter::dumpRegisters):
(JSC::Interpreter::unwindCallFrame):
(JSC::getBytecodeOffsetForCallFrame):
(JSC::getCallerInfo):
(JSC::StackFrame::line):
(JSC::StackFrame::column):
(JSC::StackFrame::expressionInfo):
(JSC::StackFrame::toString):
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::addStackTraceIfNecessary):
(JSC::Interpreter::retrieveCallerFromVMCode):

  • interpreter/Interpreter.h:

(StackFrame):
(Interpreter):

  • runtime/Error.cpp:

(JSC::throwError):

  • runtime/JSGlobalData.h:

(JSC):
(JSGlobalData):

  • runtime/JSGlobalObject.cpp:

(JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope):

Source/WebCore:

Now that we've fleshed out the StackFrames from Interpreter::getStackTrace
WebCore can just ask us for a stack trace rather than implementing its own
stack walking.

  • bindings/js/ScriptCallStackFactory.cpp:

(WebCore::createScriptCallStack):

  • inspector/ScriptCallFrame.cpp:

(WebCore::ScriptCallFrame::isEqual):

  • inspector/ScriptCallFrame.h:

(ScriptCallFrame):
(WebCore::ScriptCallFrame::columnNumber):

Tools:

The commandline jsc executable no longer requires arguments, so
I've made run-jsc work without them.

  • Scripts/run-jsc:
Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSContextRef.cpp

    r147846 r147858  
    3737#include "JSObject.h"
    3838#include "Operations.h"
     39#include "SourceProvider.h"
    3940#include <wtf/text/StringBuilder.h>
    4041#include <wtf/text/StringHash.h>
     
    176177    ExecState* exec = toJS(ctx);
    177178    JSLockHolder lock(exec);
    178 
    179     unsigned count = 0;
    180179    StringBuilder builder;
    181     CallFrame* callFrame = exec;
    182     String functionName;
    183     if (exec->callee()) {
    184         if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) {
    185             functionName = asInternalFunction(exec->callee())->name(exec);
    186             builder.appendLiteral("#0 ");
    187             builder.append(functionName);
    188             builder.appendLiteral("() ");
    189             count++;
    190         }
    191     }
    192     while (true) {
    193         RELEASE_ASSERT(callFrame);
    194         int signedLineNumber;
    195         intptr_t sourceID;
     180    Vector<StackFrame> stackTrace;
     181    Interpreter::getStackTrace(&exec->globalData(), stackTrace, maxStackSize);
     182
     183    for (size_t i = 0; i < stackTrace.size(); i++) {
    196184        String urlString;
    197         JSValue function;
    198 
    199         exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
    200 
    201         if (function)
    202             functionName = jsCast<JSFunction*>(function)->name(exec);
     185        String functionName;
     186        StackFrame& frame = stackTrace[i];
     187        JSValue function = frame.callee.get();
     188        if (frame.callee)
     189            functionName = frame.friendlyFunctionName(exec);
    203190        else {
    204191            // Caller is unknown, but if frame is empty we should still add the frame, because
    205192            // something called us, and gave us arguments.
    206             if (count)
     193            if (i)
    207194                break;
    208195        }
    209         unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
     196        unsigned lineNumber = frame.line();
    210197        if (!builder.isEmpty())
    211198            builder.append('\n');
    212199        builder.append('#');
    213         builder.appendNumber(count);
     200        builder.appendNumber(i);
    214201        builder.append(' ');
    215202        builder.append(functionName);
    216203        builder.appendLiteral("() at ");
    217204        builder.append(urlString);
    218         builder.append(':');
    219         builder.appendNumber(lineNumber);
    220         if (!function || ++count == maxStackSize)
     205        if (frame.codeType != StackFrameNativeCode) {
     206            builder.append(':');
     207            builder.appendNumber(lineNumber);
     208        }
     209        if (!function)
    221210            break;
    222         callFrame = callFrame->callerFrame();
    223211    }
    224212    return OpaqueJSString::create(builder.toString()).leakRef();
  • trunk/Source/JavaScriptCore/ChangeLog

    r147857 r147858  
     12013-04-06  Oliver Hunt  <[email protected]>
     2
     3        Unify the many and varied stack trace mechanisms, and make the result sane.
     4        https://bugs.webkit.org/show_bug.cgi?id=114072
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Makes JSC::StackFrame record the bytecode offset and other necessary data
     9        rather than requiring us to perform eager evaluation of the line number, etc.
     10        Then remove most of the users of retrieveLastCaller, as most of them were
     11        using it to create a stack trace in a fairly incomplete and inefficient way.
     12
     13        StackFrame now also has a couple of helpers to get the line and column info.
     14
     15        * API/JSContextRef.cpp:
     16        (JSContextCreateBacktrace):
     17        * bytecompiler/BytecodeGenerator.cpp:
     18        (JSC::BytecodeGenerator::emitDebugHook):
     19        * interpreter/Interpreter.cpp:
     20        (JSC):
     21        (JSC::Interpreter::dumpRegisters):
     22        (JSC::Interpreter::unwindCallFrame):
     23        (JSC::getBytecodeOffsetForCallFrame):
     24        (JSC::getCallerInfo):
     25        (JSC::StackFrame::line):
     26        (JSC::StackFrame::column):
     27        (JSC::StackFrame::expressionInfo):
     28        (JSC::StackFrame::toString):
     29        (JSC::Interpreter::getStackTrace):
     30        (JSC::Interpreter::addStackTraceIfNecessary):
     31        (JSC::Interpreter::retrieveCallerFromVMCode):
     32        * interpreter/Interpreter.h:
     33        (StackFrame):
     34        (Interpreter):
     35        * runtime/Error.cpp:
     36        (JSC::throwError):
     37        * runtime/JSGlobalData.h:
     38        (JSC):
     39        (JSGlobalData):
     40        * runtime/JSGlobalObject.cpp:
     41        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope):
     42
    1432013-04-06  Geoffrey Garen  <[email protected]>
    244
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreExports.def

    r147849 r147858  
    238238    ?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z
    239239    ?getID@SourceProvider@JSC@@AAEXXZ
    240     ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@AAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
    241240    ?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ
    242241    ?getObjectType@MemoryInstrumentation@WTF@@CAPBDPAVMemoryObjectInfo@2@@Z
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r147846 r147858  
    20562056        return;
    20572057#endif
     2058    emitExpressionInfo(charPosition, 0, 0);
    20582059    emitOpcode(op_debug);
    20592060    instructions().append(debugHookID);
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r147851 r147858  
    200200
    201201
    202 static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset, CodeBlock*& callerOut);
     202static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, unsigned& bytecodeOffset, CodeBlock*& callerOut);
    203203
    204204// Returns the depth of the scope chain within a given call frame.
     
    423423    unsigned bytecodeOffset = 0;
    424424    int line = 0;
    425     CodeBlock* unusedCallerCodeBlock = 0;
    426     getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset, unusedCallerCodeBlock);
     425    CodeBlock* callerCodeBlock = 0;
     426    getCallerInfo(&callFrame->globalData(), callFrame, bytecodeOffset, callerCodeBlock);
     427    line = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
    427428    dataLogF("[ReturnVPC]                | %10p | %d (line %d)\n", it, bytecodeOffset, line);
    428429    ++it;
     
    508509    if (callerFrame->hasHostCallFrameFlag())
    509510        return false;
    510     int unusedLineNumber = 0;
    511     callFrame = getCallerInfo(&callFrame->globalData(), callFrame, unusedLineNumber, bytecodeOffset, codeBlock);
     511    callFrame = getCallerInfo(&callFrame->globalData(), callFrame, bytecodeOffset, codeBlock);
    512512    return true;
    513513}
     
    565565}
    566566
    567 static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFrame)
    568 {
    569     UNUSED_PARAM(globalData);
     567static unsigned getBytecodeOffsetForCallFrame(CallFrame* callFrame)
     568{
    570569    callFrame = callFrame->removeHostCallFrameFlag();
    571570    CodeBlock* codeBlock = callFrame->codeBlock();
    572571    if (!codeBlock)
    573         return -1;
    574 #if ENABLE(JIT) || ENABLE(LLINT)
     572        return 0;
     573#if ENABLE(JIT)
    575574#if ENABLE(DFG_JIT)
    576575    if (codeBlock->getJITType() == JITCode::DFGJIT)
    577         return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex);
    578 #endif
    579     return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode());
     576        return codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex;
     577#endif
     578    return callFrame->bytecodeOffsetForNonDFGCode();
    580579#else
    581580    return 0;
     
    583582}
    584583
    585 static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset, CodeBlock*& caller)
     584static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, unsigned& bytecodeOffset, CodeBlock*& caller)
    586585{
    587586    ASSERT_UNUSED(globalData, globalData);
    588587    bytecodeOffset = 0;
    589     lineNumber = -1;
    590588    ASSERT(!callFrame->hasHostCallFrameFlag());
    591589    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
     
    657655    RELEASE_ASSERT(callerCodeBlock);
    658656    caller = callerCodeBlock;
    659     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
    660657    return callerFrame;
    661658}
     
    683680}
    684681
    685 void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
     682unsigned StackFrame::line()
     683{
     684    return codeBlock ? codeBlock->lineNumberForBytecodeOffset(bytecodeOffset) + lineOffset : 0;
     685}
     686
     687unsigned StackFrame::column()
     688{
     689    if (!code)
     690        return 0;
     691    int divot = 0;
     692    int unusedStartOffset = 0;
     693    int unusedEndOffset = 0;
     694    expressionInfo(divot, unusedStartOffset, unusedEndOffset);
     695    return code->charPositionToColumnNumber(divot);
     696}
     697
     698void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset)
     699{
     700    codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset);
     701    divot += startOffset;
     702}
     703
     704String StackFrame::toString(CallFrame* callFrame)
     705{
     706    StringBuilder traceBuild;
     707    String functionName = friendlyFunctionName(callFrame);
     708    String sourceURL = friendlySourceURL();
     709    traceBuild.append(functionName);
     710    if (!sourceURL.isEmpty()) {
     711        if (!functionName.isEmpty())
     712            traceBuild.append('@');
     713        traceBuild.append(sourceURL);
     714        if (codeType != StackFrameNativeCode) {
     715            traceBuild.append(':');
     716            traceBuild.appendNumber(line());
     717        }
     718    }
     719    return traceBuild.toString().impl();
     720}
     721
     722void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results, size_t maxStackSize)
    686723{
    687724    CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
    688725    if (!callFrame || callFrame == CallFrame::noCaller())
    689726        return;
    690     int line = getLineNumberForCallFrame(globalData, callFrame);
    691 
     727    unsigned bytecodeOffset = getBytecodeOffsetForCallFrame(callFrame);
    692728    callFrame = callFrame->trueCallFrameFromVMCode();
    693729    if (!callFrame)
    694730        return;
    695 
    696     while (callFrame && callFrame != CallFrame::noCaller()) {
     731    CodeBlock* callerCodeBlock = callFrame->codeBlock();
     732
     733    while (callFrame && callFrame != CallFrame::noCaller() && maxStackSize--) {
    697734        String sourceURL;
    698         if (callFrame->codeBlock()) {
     735        if (callerCodeBlock) {
    699736            sourceURL = getSourceURLFromCallFrame(callFrame);
    700             StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL};
     737            StackFrame s = {
     738                Strong<JSObject>(*globalData, callFrame->callee()),
     739                getStackFrameCodeType(callFrame),
     740                Strong<ExecutableBase>(*globalData, callerCodeBlock->ownerExecutable()),
     741                Strong<UnlinkedCodeBlock>(*globalData, callerCodeBlock->unlinkedCodeBlock()),
     742                callerCodeBlock->source(),
     743                callerCodeBlock->ownerExecutable()->lineNo(),
     744                callerCodeBlock->sourceOffset(),
     745                bytecodeOffset,
     746                sourceURL
     747            };
    701748            results.append(s);
    702749        } else {
    703             StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, String()};
     750            StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, String()};
    704751            results.append(s);
    705752        }
    706         unsigned unusedBytecodeOffset = 0;
    707         CodeBlock* unusedCallerCodeBlock = 0;
    708         callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset, unusedCallerCodeBlock);
    709     }
    710 }
    711 
    712 void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
     753        callFrame = getCallerInfo(globalData, callFrame, bytecodeOffset, callerCodeBlock);
     754    }
     755}
     756
     757void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSValue error)
    713758{
    714759    JSGlobalData* globalData = &callFrame->globalData();
    715760    ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
    716     if (error->hasProperty(callFrame, globalData->propertyNames->stack))
    717         return;
    718761
    719762    Vector<StackFrame> stackTrace;
    720763    getStackTrace(&callFrame->globalData(), stackTrace);
    721764   
    722     if (stackTrace.isEmpty())
     765    if (stackTrace.isEmpty() || !error.isObject())
    723766        return;
    724    
     767    JSObject* errorObject = asObject(error);
    725768    JSGlobalObject* globalObject = 0;
    726769    if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
    727770        globalObject = globalData->dynamicGlobalObject;
    728771    else
    729         globalObject = error->globalObject();
     772        globalObject = errorObject->globalObject();
    730773
    731774    // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
     
    736779            builder.append('\n');
    737780    }
    738    
    739     error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, builder.toString()), ReadOnly | DontDelete);
     781
     782    if (errorObject->hasProperty(callFrame, globalData->propertyNames->stack))
     783        return;
     784    errorObject->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, builder.toString()), ReadOnly | DontDelete);
    740785}
    741786
     
    13801425        return jsNull();
    13811426   
    1382     int lineNumber;
    13831427    unsigned bytecodeOffset;
    13841428    CodeBlock* unusedCallerCodeBlock = 0;
    1385     CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset, unusedCallerCodeBlock);
     1429    CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, bytecodeOffset, unusedCallerCodeBlock);
    13861430    if (!callerFrame)
    13871431        return jsNull();
     
    13931437    ASSERT(caller.isObject());
    13941438    while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
    1395         callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset, unusedCallerCodeBlock);
     1439        callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, bytecodeOffset, unusedCallerCodeBlock);
    13961440        if (!callerFrame)
    13971441            return jsNull();
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r147846 r147858  
    8080        StackFrameCodeType codeType;
    8181        Strong<ExecutableBase> executable;
    82         int line;
     82        Strong<UnlinkedCodeBlock> codeBlock;
     83        RefPtr<SourceProvider> code;
     84        int lineOffset;
     85        unsigned characterOffset;
     86        unsigned bytecodeOffset;
    8387        String sourceURL;
    84         String toString(CallFrame* callFrame) const
    85         {
    86             StringBuilder traceBuild;
    87             String functionName = friendlyFunctionName(callFrame);
    88             String sourceURL = friendlySourceURL();
    89             traceBuild.append(functionName);
    90             if (!sourceURL.isEmpty()) {
    91                 if (!functionName.isEmpty())
    92                     traceBuild.append('@');
    93                 traceBuild.append(sourceURL);
    94                 if (line > -1) {
    95                     traceBuild.append(':');
    96                     traceBuild.appendNumber(line);
    97                 }
    98             }
    99             return traceBuild.toString().impl();
    100         }
     88        JS_EXPORT_PRIVATE String toString(CallFrame*);
    10189        String friendlySourceURL() const
    10290        {
     
    138126            return traceLine.isNull() ? emptyString() : traceLine;
    139127        }
    140         unsigned friendlyLineNumber() const
    141         {
    142             return line > -1 ? line : 0;
    143         }
     128        JS_EXPORT_PRIVATE unsigned line();
     129        JS_EXPORT_PRIVATE unsigned column();
     130        JS_EXPORT_PRIVATE void expressionInfo(int& divot, int& startOffset, int& endOffset);
    144131    };
    145132
     
    233220        NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column);
    234221        static const String getTraceLine(CallFrame*, StackFrameCodeType, const String&, int);
    235         JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results);
    236         static void addStackTraceIfNecessary(CallFrame*, JSObject* error);
     222        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
     223        static void addStackTraceIfNecessary(CallFrame*, JSValue error);
    237224
    238225        void dumpSampleData(ExecState* exec);
  • trunk/Source/JavaScriptCore/runtime/Error.cpp

    r147846 r147858  
    156156JSValue throwError(ExecState* exec, JSValue error)
    157157{
    158     if (error.isObject())
    159         return throwError(exec, asObject(error));
     158    Interpreter::addStackTraceIfNecessary(exec, error);
    160159    exec->globalData().exception = error;
    161160    return error;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.h

    r147846 r147858  
    5555#include <wtf/Forward.h>
    5656#include <wtf/HashMap.h>
     57#include <wtf/RefCountedArray.h>
    5758#include <wtf/SimpleStats.h>
    5859#include <wtf/ThreadSafeRefCounted.h>
     
    8283    class SourceProvider;
    8384    class SourceProviderCache;
     85    struct StackFrame;
    8486    class Stringifier;
    8587    class Structure;
     
    329331
    330332        JSValue exception;
     333        RefCountedArray<StackFrame> exceptionStack;
    331334
    332335        const ClassInfo* const jsArrayClassInfo;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r147846 r147858  
    598598        globalData.resetDateCache();
    599599    }
     600    // Clear the exception stack between entries
     601    globalData.exceptionStack = RefCountedArray<StackFrame>();
    600602}
    601603
  • trunk/Source/WebCore/ChangeLog

    r147857 r147858  
     12013-04-06  Oliver Hunt  <[email protected]>
     2
     3        Unify the many and varied stack trace mechanisms, and make the result sane.
     4        https://bugs.webkit.org/show_bug.cgi?id=114072
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Now that we've fleshed out the StackFrames from Interpreter::getStackTrace
     9        WebCore can just ask us for a stack trace rather than implementing its own
     10        stack walking.
     11
     12        * bindings/js/ScriptCallStackFactory.cpp:
     13        (WebCore::createScriptCallStack):
     14        * inspector/ScriptCallFrame.cpp:
     15        (WebCore::ScriptCallFrame::isEqual):
     16        * inspector/ScriptCallFrame.h:
     17        (ScriptCallFrame):
     18        (WebCore::ScriptCallFrame::columnNumber):
     19
    1202013-04-06  Geoffrey Garen  <[email protected]>
    221
  • trunk/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp

    r147846 r147858  
    5959    if (JSC::ExecState* exec = JSMainThreadExecState::currentState()) {
    6060        Vector<StackFrame> stackTrace;
    61         Interpreter::getStackTrace(&exec->globalData(), stackTrace);
    62         for (Vector<StackFrame>::const_iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
    63             frames.append(ScriptCallFrame(iter->friendlyFunctionName(exec), iter->friendlySourceURL(), iter->friendlyLineNumber()));
    64             if (frames.size() >= maxStackSize)
    65                 break;
    66         }
     61        Interpreter::getStackTrace(&exec->globalData(), stackTrace, maxStackSize);
     62        for (size_t i = 0; i < stackTrace.size(); i++)
     63            frames.append(ScriptCallFrame(stackTrace[i].friendlyFunctionName(exec), stackTrace[i].friendlySourceURL(), stackTrace[i].line(), stackTrace[i].column()));
    6764    }
    6865    if (frames.isEmpty() && !emptyIsAllowed) {
     
    7067        // a bound function is called from native code for example.
    7168        // Fallback to setting lineNumber to 0, and source and function name to "undefined".
    72         frames.append(ScriptCallFrame("undefined", "undefined", 0));
     69        frames.append(ScriptCallFrame("undefined", "undefined", 0, 0));
    7370    }
    7471    return ScriptCallStack::create(frames);
     
    7875{
    7976    Vector<ScriptCallFrame> frames;
    80     CallFrame* callFrame = exec;
    81     while (true) {
    82         ASSERT(callFrame);
    83         int signedLineNumber;
    84         intptr_t sourceID;
    85         String urlString;
    86         JSValue function;
     77    Vector<StackFrame> stackTrace;
     78    Interpreter::getStackTrace(&exec->globalData(), stackTrace, maxStackSize + 1);
     79    for (size_t i = stackTrace.size() == 1 ? 0 : 1; i < stackTrace.size(); i++) {
     80        // This early exit is necessary to maintain our old behaviour
     81        // but the stack trace we produce now is complete and handles all
     82        // ways in which code may be running
     83        if (!stackTrace[i].callee && frames.size())
     84            break;
    8785
    88         exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
    89         String functionName;
    90         if (function)
    91             functionName = jsCast<JSFunction*>(function)->name(exec);
    92         else {
    93             // Caller is unknown, but if frames is empty we should still add the frame, because
    94             // something called us, and gave us arguments.
    95             if (!frames.isEmpty())
    96                 break;
    97         }
    98         unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
    99         frames.append(ScriptCallFrame(functionName, urlString, lineNumber));
    100         if (!function || frames.size() == maxStackSize)
    101             break;
    102         callFrame = callFrame->callerFrame();
     86        String functionName = stackTrace[i].friendlyFunctionName(exec);
     87        frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, stackTrace[i].line(), stackTrace[i].column()));
    10388    }
     89
    10490    return ScriptCallStack::create(frames);
    10591}
  • trunk/Source/WebCore/inspector/ScriptCallFrame.cpp

    r147846 r147858  
    5454    return m_functionName == o.m_functionName
    5555        && m_scriptName == o.m_scriptName
    56         && m_lineNumber == o.m_lineNumber;
     56        && m_lineNumber == o.m_lineNumber
     57        && m_column == o.m_column;
    5758}
    5859
  • trunk/Source/WebCore/inspector/ScriptCallFrame.h

    r147846 r147858  
    4545class ScriptCallFrame  {
    4646public:
    47     ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column = 0);
     47    ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column);
    4848    ~ScriptCallFrame();
    4949
     
    5151    const String& sourceURL() const { return m_scriptName; }
    5252    unsigned lineNumber() const { return m_lineNumber; }
     53    unsigned columnNumber() const { return m_column; }
    5354
    5455    bool isEqual(const ScriptCallFrame&) const;
  • trunk/Tools/ChangeLog

    r147854 r147858  
     12013-04-06  Oliver Hunt  <[email protected]>
     2
     3        Unify the many and varied stack trace mechanisms, and make the result sane.
     4        https://bugs.webkit.org/show_bug.cgi?id=114072
     5
     6        Reviewed by Filip Pizlo.
     7
     8        The commandline jsc executable no longer requires arguments, so
     9        I've made run-jsc work without them.
     10
     11        * Scripts/run-jsc:
     12
    1132013-04-06  Ed Bartosh  <[email protected]>
    214
  • trunk/Tools/Scripts/run-jsc

    r147846 r147858  
    4343GetOptions("count|c=i" => \$count,
    4444           "verbose|v" => \$verbose);
    45 die "$usage\n" if (@ARGV < 1);
    4645
    4746my $jsc = jscProductDir() . "/jsc @ARGV";
Note: See TracChangeset for help on using the changeset viewer.