Changeset 108112 in webkit


Ignore:
Timestamp:
Feb 17, 2012 1:17:59 PM (12 years ago)
Author:
oliver@apple.com
Message:

Implement Error.stack
https://bugs.webkit.org/show_bug.cgi?id=66994

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Implement support for stack traces on exception objects. This is a rewrite
of the core portion of the last stack walking logic, but the mechanical work
of adding the information to an exception comes from the original work by
Juan Carlos Montemayor Elosua.

  • interpreter/Interpreter.cpp:

(JSC::getCallerInfo):
(JSC):
(JSC::getSourceURLFromCallFrame):
(JSC::getStackFrameCodeType):
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):

  • interpreter/Interpreter.h:

(JSC):
(StackFrame):
(JSC::StackFrame::toString):
(Interpreter):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionJSCStack):

  • parser/Nodes.h:

(JSC::FunctionBodyNode::setInferredName):

  • parser/Parser.h:

(JSC::::parse):

  • runtime/CommonIdentifiers.h:
  • runtime/Error.cpp:

(JSC::addErrorInfo):

  • runtime/Error.h:

(JSC):

LayoutTests:

Add testcases for producing a stack trace on exception objects.

  • fast/js/exception-properties-expected.txt:
  • fast/js/script-tests/exception-properties.js:
  • fast/js/script-tests/stack-trace.js: Added.

(printStack):
(hostThrower):
(callbacker):
(outer):
(inner):
(evaler):
(normalOuter):
(normalInner):
(scripterInner):
(scripterOuter):
(selfRecursive1):
(selfRecursive2):
(selfRecursive3):
(throwError):
(object.get getter1.o.valueOf):
(object.get getter1):
(object.get getter2):
(object.get getter3.o2.valueOf):
(object.get getter3):
(object.nonInlineable.callCount):
(object.nonInlineable):
(object.inlineable):
(yetAnotherInlinedCall):
(makeInlinableCall):
(.try.g):
(h):
(mapTest):
(mapTestDriver):
(dfgFunction):
(try.f):

  • fast/js/stack-trace-expected.txt: Added.
  • fast/js/stack-trace.html: Added.
Location:
trunk
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r108111 r108112  
     12012-02-16  Oliver Hunt  <oliver@apple.com>
     2
     3        Implement Error.stack
     4        https://bugs.webkit.org/show_bug.cgi?id=66994
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Add testcases for producing a stack trace on exception objects.
     9
     10        * fast/js/exception-properties-expected.txt:
     11        * fast/js/script-tests/exception-properties.js:
     12        * fast/js/script-tests/stack-trace.js: Added.
     13        (printStack):
     14        (hostThrower):
     15        (callbacker):
     16        (outer):
     17        (inner):
     18        (evaler):
     19        (normalOuter):
     20        (normalInner):
     21        (scripterInner):
     22        (scripterOuter):
     23        (selfRecursive1):
     24        (selfRecursive2):
     25        (selfRecursive3):
     26        (throwError):
     27        (object.get getter1.o.valueOf):
     28        (object.get getter1):
     29        (object.get getter2):
     30        (object.get getter3.o2.valueOf):
     31        (object.get getter3):
     32        (object.nonInlineable.callCount):
     33        (object.nonInlineable):
     34        (object.inlineable):
     35        (yetAnotherInlinedCall):
     36        (makeInlinableCall):
     37        (.try.g):
     38        (h):
     39        (mapTest):
     40        (mapTestDriver):
     41        (dfgFunction):
     42        (try.f):
     43        * fast/js/stack-trace-expected.txt: Added.
     44        * fast/js/stack-trace.html: Added.
     45
    1462012-01-23  Robert Hogan  <robert@webkit.org>
    247
  • trunk/LayoutTests/fast/js/exception-properties-expected.txt

    r108036 r108112  
    55
    66PASS enumerableProperties(error) is []
    7 PASS enumerableProperties(nativeError) is ["line", "sourceURL"]
     7PASS enumerableProperties(nativeError) is ["line", "sourceURL", "stack"]
    88PASS Object.getPrototypeOf(nativeError).name is "RangeError"
    99PASS Object.getPrototypeOf(nativeError).message is ""
  • trunk/LayoutTests/fast/js/script-tests/exception-properties.js

    r108036 r108112  
    1717
    1818    shouldBe('enumerableProperties(error)', '[]');
    19     shouldBe('enumerableProperties(nativeError)', '["line", "sourceURL"]');
     19    shouldBe('enumerableProperties(nativeError)', '["line", "sourceURL", "stack"]');
    2020
    2121    shouldBe('Object.getPrototypeOf(nativeError).name', '"RangeError"');
  • trunk/Source/JavaScriptCore/ChangeLog

    r108107 r108112  
     12012-02-16  Oliver Hunt  <oliver@apple.com>
     2
     3        Implement Error.stack
     4        https://bugs.webkit.org/show_bug.cgi?id=66994
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Implement support for stack traces on exception objects.  This is a rewrite
     9        of the core portion of the last stack walking logic, but the mechanical work
     10        of adding the information to an exception comes from the original work by
     11        Juan Carlos Montemayor Elosua.
     12
     13        * interpreter/Interpreter.cpp:
     14        (JSC::getCallerInfo):
     15        (JSC):
     16        (JSC::getSourceURLFromCallFrame):
     17        (JSC::getStackFrameCodeType):
     18        (JSC::Interpreter::getStackTrace):
     19        (JSC::Interpreter::throwException):
     20        (JSC::Interpreter::privateExecute):
     21        * interpreter/Interpreter.h:
     22        (JSC):
     23        (StackFrame):
     24        (JSC::StackFrame::toString):
     25        (Interpreter):
     26        * jsc.cpp:
     27        (GlobalObject::finishCreation):
     28        (functionJSCStack):
     29        * parser/Nodes.h:
     30        (JSC::FunctionBodyNode::setInferredName):
     31        * parser/Parser.h:
     32        (JSC::::parse):
     33        * runtime/CommonIdentifiers.h:
     34        * runtime/Error.cpp:
     35        (JSC::addErrorInfo):
     36        * runtime/Error.h:
     37        (JSC):
     38
    1392012-02-17  Mark Hahnenberg  <mhahnenberg@apple.com>
    240
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r108036 r108112  
    210210    ?getPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
    211211    ?getSlice@ArgList@JSC@@QBEXHAAV12@@Z
     212    ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@HAAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
    212213    ?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z
    213214    ?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r108036 r108112  
    4646#include "JSArray.h"
    4747#include "JSByteArray.h"
    48 #include "JSFunction.h"
    4948#include "JSNotAnObject.h"
    5049#include "JSPropertyNameIterator.h"
     
    6160#include "SamplingTool.h"
    6261#include "StrictEvalActivation.h"
     62#include "StrongInlines.h"
    6363#include "UStringConcatenate.h"
    6464#include <limits.h>
     
    791791}
    792792
     793static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber)
     794{
     795    UNUSED_PARAM(globalData);
     796    unsigned bytecodeOffset = 0;
     797    lineNumber = -1;
     798    ASSERT(!callFrame->hasHostCallFrameFlag());
     799    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : 0;
     800    bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
     801    ASSERT(!callerFrame->hasHostCallFrameFlag());
     802
     803    if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock())
     804        return callerFrame;
     805
     806    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
     807
     808    if (callframeIsHost) {
     809        // Don't need to deal with inline callframes here as by definition we haven't
     810        // inlined a call with an intervening native call frame.
     811#if ENABLE(INTERPRETER)
     812        if (!globalData->canUseJIT()) {
     813            bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
     814            lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     815            return callerFrame;
     816        }
     817#endif
     818#if ENABLE(JIT)
     819#if ENABLE(DFG_JIT)
     820        if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT)
     821            bytecodeOffset = callerCodeBlock->codeOrigin(callerFrame->codeOriginIndexForDFG()).bytecodeIndex;
     822        else
     823#endif
     824            bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
     825#endif
     826    } else {
     827#if ENABLE(INTERPRETER)
     828        if (!globalData->canUseJIT()) {
     829            bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
     830            lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     831            return callerFrame;
     832        }
     833#endif
     834#if ENABLE(JIT)
     835    #if ENABLE(DFG_JIT)
     836        if (callFrame->isInlineCallFrame()) {
     837            InlineCallFrame* icf = callFrame->inlineCallFrame();
     838            bytecodeOffset = icf->caller.bytecodeIndex;
     839            if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
     840                FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
     841                CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
     842                ASSERT(newCodeBlock);
     843                ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
     844                callerCodeBlock = newCodeBlock;
     845            }
     846        } else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
     847            CodeOrigin origin;
     848            if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin))
     849                ASSERT_NOT_REACHED();
     850            bytecodeOffset = origin.bytecodeIndex;
     851            if (InlineCallFrame* icf = origin.inlineCallFrame) {
     852                FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
     853                CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
     854                ASSERT(newCodeBlock);
     855                ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
     856                callerCodeBlock = newCodeBlock;
     857            }
     858        } else
     859    #endif
     860            bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
     861#endif
     862    }
     863
     864    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
     865    return callerFrame;
     866}
     867
     868static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame)
     869{
     870    ASSERT(!callFrame->hasHostCallFrameFlag());
     871#if ENABLE(INTERPRETER)
     872#if ENABLE(JIT)
     873    if (callFrame->globalData().canUseJIT())
     874        return callFrame->codeBlock()->ownerExecutable()->sourceURL();
     875#endif
     876    return callFrame->codeBlock()->source()->url();
     877
     878#else
     879    return callFrame->codeBlock()->ownerExecutable()->sourceURL();
     880#endif
     881}
     882
     883static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
     884{
     885    ASSERT(!callFrame->hasHostCallFrameFlag());
     886
     887    switch (callFrame->codeBlock()->codeType()) {
     888    case EvalCode:
     889        return StackFrameEvalCode;
     890    case FunctionCode:
     891        return StackFrameFunctionCode;
     892    case GlobalCode:
     893        return StackFrameGlobalCode;
     894    }
     895    ASSERT_NOT_REACHED();
     896    return StackFrameGlobalCode;
     897}
     898
     899void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results)
     900{
     901    CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag()->trueCallFrameFromVMCode();
     902    if (!callFrame || callFrame == CallFrame::noCaller())
     903        return;
     904
     905    while (callFrame && callFrame != CallFrame::noCaller()) {
     906        UString sourceURL;
     907        if (callFrame->codeBlock()) {
     908            sourceURL = getSourceURLFromCallFrame(callFrame);
     909            StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL};
     910            results.append(s);
     911        } else {
     912            StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, UString()};
     913            results.append(s);
     914        }
     915        callFrame = getCallerInfo(globalData, callFrame, line);
     916    }
     917}
     918
    793919NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
    794920{
     
    809935            // FIXME: should only really be adding these properties to VM generated exceptions,
    810936            // but the inspector currently requires these for all thrown objects.
    811             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
     937            Vector<StackFrame> stackTrace;
     938            getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace);
     939            addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace);
    812940        }
    813941
     
    17441872#endif
    17451873
     1874#define UPDATE_BYTECODE_OFFSET() \
     1875    do {\
     1876        callFrame->setBytecodeOffsetForNonDFGCode(vPC - codeBlock->instructions().data() + 1);\
     1877    } while (0)
     1878
    17461879#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
    17471880    #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
    17481881#if ENABLE(OPCODE_STATS)
    1749     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
     1882    #define DEFINE_OPCODE(opcode) \
     1883        opcode:\
     1884            OpcodeStats::recordInstruction(opcode);\
     1885            UPDATE_BYTECODE_OFFSET();
    17501886#else
    1751     #define DEFINE_OPCODE(opcode) opcode:
     1887    #define DEFINE_OPCODE(opcode) opcode: UPDATE_BYTECODE_OFFSET();
    17521888#endif
    17531889    NEXT_INSTRUCTION();
     
    17551891    #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
    17561892#if ENABLE(OPCODE_STATS)
    1757     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
     1893    #define DEFINE_OPCODE(opcode) \
     1894        case opcode:\
     1895            OpcodeStats::recordInstruction(opcode);\
     1896            UPDATE_BYTECODE_OFFSET();
    17581897#else
    1759     #define DEFINE_OPCODE(opcode) case opcode:
     1898    #define DEFINE_OPCODE(opcode) case opcode: UPDATE_BYTECODE_OFFSET();
    17601899#endif
    17611900    while (1) { // iterator loop begins
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r108036 r108112  
    3232#include "ArgList.h"
    3333#include "JSCell.h"
     34#include "JSFunction.h"
    3435#include "JSValue.h"
    3536#include "JSObject.h"
     
    4344    class CodeBlock;
    4445    class EvalExecutable;
     46    class ExecutableBase;
    4547    class FunctionExecutable;
    46     class JSFunction;
    4748    class JSGlobalObject;
    4849    class ProgramExecutable;
     
    6364    };
    6465
     66    enum StackFrameCodeType {
     67        StackFrameGlobalCode,
     68        StackFrameEvalCode,
     69        StackFrameFunctionCode,
     70        StackFrameNativeCode
     71    };
     72
     73    struct StackFrame {
     74        Strong<JSObject> callee;
     75        StackFrameCodeType codeType;
     76        Strong<ExecutableBase> executable;
     77        int line;
     78        UString sourceURL;
     79        UString toString(CallFrame* callFrame) const
     80        {
     81            bool hasSourceURLInfo = !sourceURL.isNull() && !sourceURL.isEmpty();
     82            bool hasLineInfo = line > -1;
     83            String traceLine;
     84            JSObject* stackFrameCallee = callee.get();
     85
     86            switch (codeType) {
     87            case StackFrameEvalCode:
     88                if (hasSourceURLInfo) {
     89                    traceLine = hasLineInfo ? String::format("eval code@%s:%d", sourceURL.ascii().data(), line)
     90                                            : String::format("eval code@%s", sourceURL.ascii().data());
     91                } else
     92                    traceLine = String::format("eval code");
     93                break;
     94            case StackFrameNativeCode: {
     95                if (callee) {
     96                    UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
     97                    traceLine = String::format("%s@[native code]", functionName.ascii().data());
     98                } else
     99                    traceLine = "[native code]";
     100                break;
     101            }
     102            case StackFrameFunctionCode: {
     103                UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
     104                if (hasSourceURLInfo) {
     105                    traceLine = hasLineInfo ? String::format("%s@%s:%d", functionName.ascii().data(), sourceURL.ascii().data(), line)
     106                                            : String::format("%s@%s", functionName.ascii().data(), sourceURL.ascii().data());
     107                } else
     108                    traceLine = String::format("%s\n", functionName.ascii().data());
     109                break;
     110            }
     111            case StackFrameGlobalCode:
     112                if (hasSourceURLInfo) {
     113                    traceLine = hasLineInfo ? String::format("global code@%s:%d", sourceURL.ascii().data(), line)
     114                                            : String::format("global code@%s", sourceURL.ascii().data());
     115                } else
     116                    traceLine = String::format("global code");
     117                   
     118            }
     119            return traceLine.impl();
     120        }
     121    };
     122
    65123    class TopCallFrameSetter {
    66124    public:
     
    152210        NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
    153211        NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
     212        static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int);
     213        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results);
    154214
    155215        void dumpSampleData(ExecState* exec);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r105636 r108112  
    8181    preserveReturnAddressAfterCall(regT3);
    8282    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
    83 
     83   
     84    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    8485    restoreArgumentReference();
    8586    Call callLazyLinkCall = call();
     
    100101    preserveReturnAddressAfterCall(regT3);
    101102    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
    102 
     103   
     104    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    103105    restoreArgumentReference();
    104106    Call callLazyLinkConstruct = call();
     
    119121    Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
    120122    preserveReturnAddressAfterCall(regT3);
     123    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    121124    restoreArgumentReference();
    122125    Call callCompileCall = call();
     
    141144    Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
    142145    preserveReturnAddressAfterCall(regT3);
     146    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    143147    restoreArgumentReference();
    144148    Call callCompileConstruct = call();
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r105636 r108112  
    8080    preserveReturnAddressAfterCall(regT3);
    8181    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
    82 
     82   
     83    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    8384    restoreArgumentReference();
    8485    Call callLazyLinkCall = call();
     
    99100    preserveReturnAddressAfterCall(regT3);
    100101    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
    101 
     102   
     103    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    102104    restoreArgumentReference();
    103105    Call callLazyLinkConstruct = call();
     
    118120    Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
    119121    preserveReturnAddressAfterCall(regT3);
     122   
     123    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    120124    restoreArgumentReference();
    121125    Call callCompileCall = call();
     
    140144    Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
    141145    preserveReturnAddressAfterCall(regT3);
     146   
     147    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    142148    restoreArgumentReference();
    143149    Call callCompileConstruct = call();
     
    349355    storePtr(regT1, regT2);
    350356    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
    351 
     357   
     358    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    352359    // Set the return address.
    353360    move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     
    485492    storePtr(regT1, regT2);
    486493    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
    487 
     494   
     495    storePtr(callFrameRegister, &m_globalData->topCallFrame);
    488496    // Set the return address.
    489497    move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
  • trunk/Source/JavaScriptCore/jsc.cpp

    r108036 r108112  
    2828#include "ExceptionHelpers.h"
    2929#include "InitializeThreading.h"
     30#include "Interpreter.h"
    3031#include "JSArray.h"
    3132#include "JSFunction.h"
     
    7980static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
    8081static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
     82static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
    8183static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
    8284#ifndef NDEBUG
     
    185187        addFunction(globalData, "load", functionLoad, 1);
    186188        addFunction(globalData, "checkSyntax", functionCheckSyntax, 1);
     189        addFunction(globalData, "jscStack", functionJSCStack, 1);
    187190        addFunction(globalData, "readline", functionReadline, 0);
    188191        addFunction(globalData, "preciseTime", functionPreciseTime, 0);
     
    250253{
    251254    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
     255    return JSValue::encode(jsUndefined());
     256}
     257
     258EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
     259{
     260    String trace = "--> Stack trace:\n";
     261    Vector<StackFrame> stackTrace;
     262    Interpreter::getStackTrace(&exec->globalData(), -1, stackTrace);
     263    int i = 0;
     264
     265    for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
     266        StackFrame level = *iter;
     267        trace += String::format("    %i   %s\n", i, level.toString(exec).utf8().data());
     268        i++;
     269    }
     270    fprintf(stderr, "%s", trace.utf8().data());
    252271    return JSValue::encode(jsUndefined());
    253272}
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r108036 r108112  
    14941494       
    14951495        const Identifier& ident() { return m_ident; }
    1496         void setInferredName(const Identifier& inferredName) { m_inferredName = inferredName; }
     1496        void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; }
    14971497        const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
    14981498
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r108036 r108112  
    10261026            *exception = createSyntaxError(lexicalGlobalObject, errMsg);
    10271027        else
    1028             *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source);
     1028            *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source, Vector<StackFrame>());
    10291029    }
    10301030
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r108036 r108112  
    6363    macro(set) \
    6464    macro(source) \
     65    macro(stack) \
    6566    macro(test) \
    6667    macro(toExponential) \
  • trunk/Source/JavaScriptCore/runtime/Error.cpp

    r108036 r108112  
    2727#include "ConstructData.h"
    2828#include "ErrorConstructor.h"
     29#include "ExceptionHelpers.h"
    2930#include "FunctionPrototype.h"
     31#include "JSArray.h"
    3032#include "JSFunction.h"
    3133#include "JSGlobalObject.h"
     
    117119}
    118120
    119 JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source)
     121JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
    120122{
    121123    const UString& sourceURL = source.provider()->url();
     
    125127    if (!sourceURL.isNull())
    126128        error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
     129    if (!stackTrace.isEmpty()) {
     130        JSGlobalObject* globalObject = 0;
     131        if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
     132            globalObject = globalData->dynamicGlobalObject;
     133        else
     134            globalObject = error->globalObject();
     135        // We use the tryCreateUninitialized creation mechanism and related initialization
     136        // functions as they're the only mechanism we currently have that will guarantee we
     137        // don't call setters on the prototype. Technically it's faster than the alternative,
     138        // but the numerous allocations that take place in this loop makes that last bit
     139        // somewhat moot.
     140        JSArray* stackTraceArray = JSArray::tryCreateUninitialized(*globalData, globalObject->arrayStructure(), stackTrace.size());
     141        if (!stackTraceArray)
     142            return error;
     143        for (unsigned i = 0; i < stackTrace.size(); i++) {
     144            UString stackLevel = stackTrace[i].toString(globalObject->globalExec());
     145            stackTraceArray->initializeIndex(*globalData, i, jsString(globalData, stackLevel));
     146        }
     147        stackTraceArray->completeInitialization(stackTrace.size());
     148        error->putDirect(*globalData, globalData->propertyNames->stack, stackTraceArray, ReadOnly | DontDelete);
     149    }
    127150
    128151    return error;
    129152}
    130153
    131 JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
     154JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
    132155{
    133     return addErrorInfo(&exec->globalData(), error, line, source);
     156    return addErrorInfo(&exec->globalData(), error, line, source, stackTrace);
    134157}
    135158
  • trunk/Source/JavaScriptCore/runtime/Error.h

    r108036 r108112  
    2525
    2626#include "InternalFunction.h"
     27#include "Interpreter.h"
    2728#include "JSObject.h"
    2829#include <stdint.h>
     
    5758    // Methods to add
    5859    bool hasErrorInfo(ExecState*, JSObject* error);
    59     JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&);
     60    JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
    6061    // ExecState wrappers.
    61     JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
     62    JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
    6263
    6364    // Methods to throw Errors.
Note: See TracChangeset for help on using the changeset viewer.