Changeset 96131 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Sep 27, 2011, 10:58:55 AM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r96087 r96131 1 2011-09-27 Juan Carlos Montemayor Elosua <[email protected]> 2 3 Implement Error.stack 4 https://bugs.webkit.org/show_bug.cgi?id=66994 5 6 Reviewed by Oliver Hunt. 7 8 This patch utilizes topCallFrame to create a stack trace when 9 an error is thrown. Users will also be able to use the stack() 10 command in jsc to get arrays with stack trace information. 11 12 * JavaScriptCore.exp: 13 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: 14 * interpreter/Interpreter.cpp: 15 (JSC::getCallerLine): 16 (JSC::getSourceURLFromCallFrame): 17 (JSC::getStackFrameCodeType): 18 (JSC::Interpreter::getStackTrace): 19 (JSC::Interpreter::throwException): 20 * interpreter/Interpreter.h: 21 (JSC::StackFrame::toString): 22 * jsc.cpp: 23 (GlobalObject::finishCreation): 24 (functionJSCStack): 25 * parser/Parser.h: 26 (JSC::Parser::parse): 27 * runtime/CommonIdentifiers.h: 28 * runtime/Error.cpp: 29 (JSC::addErrorInfo): 30 * runtime/Error.h: 31 1 32 2011-09-27 Carlos Garcia Campos <[email protected]> 2 33 -
trunk/Source/JavaScriptCore/JavaScriptCore.exp
r96045 r96131 115 115 __ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE 116 116 __ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE 117 __ZN3JSC11Interpreter13getStackTraceEPNS_12JSGlobalDataEiRN3WTF6VectorINS_10StackFrameELm0EEE 117 118 __ZN3JSC11JSByteArray13s_defaultInfoE 118 119 __ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataEPNS_14JSGlobalObjectENS_7JSValueEPKNS_9ClassInfoE -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
r96045 r96131 212 212 ?getPropertyNames@JSObject@JSC@@UAEXPAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z 213 213 ?getSlice@ArgList@JSC@@QBEXHAAV12@@Z 214 ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@HAAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z 214 215 ?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z 215 216 ?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r95901 r96131 46 46 #include "JSArray.h" 47 47 #include "JSByteArray.h" 48 #include "JSFunction.h"49 48 #include "JSNotAnObject.h" 50 49 #include "JSPropertyNameIterator.h" … … 688 687 } 689 688 689 static void getCallerLine(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber) 690 { 691 (void)globalData; 692 unsigned bytecodeOffset; 693 lineNumber = -1; 694 callFrame = callFrame->removeHostCallFrameFlag(); 695 696 if (callFrame->callerFrame() == CallFrame::noCaller() || callFrame->callerFrame()->hasHostCallFrameFlag()) 697 return; 698 699 CodeBlock* callerCodeBlock = callFrame->callerFrame()->removeHostCallFrameFlag()->codeBlock(); 700 701 #if ENABLE(INTERPRETER) 702 if (!globalData->canUseJIT()) 703 bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC()); 704 #if ENABLE(JIT) 705 else 706 bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC()); 707 #endif 708 #else 709 bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC()); 710 #endif 711 712 lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); 713 } 714 715 static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame) 716 { 717 if (callFrame->hasHostCallFrameFlag()) 718 return UString(); 719 #if ENABLE(INTERPRETER) 720 if (!callFrame->globalData().canUseJIT()) 721 return callFrame->codeBlock()->source()->url(); 722 #if ENABLE(JIT) 723 return callFrame->codeBlock()->ownerExecutable()->sourceURL(); 724 #endif 725 #else 726 return callFrame->codeBlock()->ownerExecutable()->sourceURL(); 727 #endif 728 } 729 730 static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame) 731 { 732 if (callFrame->hasHostCallFrameFlag()) 733 return StackFrameNativeCode; 734 735 switch (callFrame->codeBlock()->codeType()) { 736 case EvalCode: 737 return StackFrameEvalCode; 738 case FunctionCode: 739 return StackFrameFunctionCode; 740 case GlobalCode: 741 return StackFrameGlobalCode; 742 } 743 ASSERT_NOT_REACHED(); 744 return StackFrameGlobalCode; 745 } 746 747 void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results) 748 { 749 int stackLimit = 15; 750 CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag(); 751 if (!callFrame || callFrame == CallFrame::noCaller() || !callFrame->codeBlock()) 752 return; 753 UString sourceURL; 754 UString traceLevel; 755 756 for (int i = 0; i < stackLimit; ++i) { 757 if (!callFrame || callFrame == CallFrame::noCaller()) 758 break; 759 if (callFrame->codeBlock()) { 760 sourceURL = getSourceURLFromCallFrame(callFrame); 761 762 StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), Strong<CallFrame>(*globalData, callFrame), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL}; 763 764 results.append(s); 765 } 766 getCallerLine(globalData, callFrame, line); 767 callFrame = callFrame->callerFrame()->removeHostCallFrameFlag(); 768 } 769 } 770 690 771 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset) 691 772 { … … 706 787 // FIXME: should only really be adding these properties to VM generated exceptions, 707 788 // but the inspector currently requires these for all thrown objects. 708 addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source()); 789 Vector<StackFrame> stackTrace; 790 getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace); 791 addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace); 709 792 } 710 793 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.h
r95901 r96131 32 32 #include "ArgList.h" 33 33 #include "JSCell.h" 34 #include "JSFunction.h" 34 35 #include "JSValue.h" 35 36 #include "JSObject.h" … … 43 44 class CodeBlock; 44 45 class EvalExecutable; 46 class ExecutableBase; 45 47 class FunctionExecutable; 46 class JSFunction;47 48 class JSGlobalObject; 48 49 class ProgramExecutable; … … 63 64 }; 64 65 66 enum StackFrameCodeType { 67 StackFrameGlobalCode, 68 StackFrameEvalCode, 69 StackFrameFunctionCode, 70 StackFrameNativeCode 71 }; 72 73 struct StackFrame { 74 Strong<JSObject> callee; 75 Strong<CallFrame> callFrame; 76 StackFrameCodeType codeType; 77 Strong<ExecutableBase> executable; 78 int line; 79 UString sourceURL; 80 UString toString() const 81 { 82 bool hasSourceURLInfo = !sourceURL.isNull() && !sourceURL.isEmpty(); 83 bool hasLineInfo = line > -1; 84 String traceLine; 85 JSObject* stackFrameCallee = callee.get(); 86 87 switch (codeType) { 88 case StackFrameEvalCode: 89 if (hasSourceURLInfo) 90 traceLine = hasLineInfo ? String::format("eval at %s:%d", sourceURL.ascii().data(), line) 91 : String::format("eval at %s", sourceURL.ascii().data()); 92 else 93 traceLine = String::format("eval"); 94 break; 95 case StackFrameNativeCode: 96 traceLine = "Native code"; 97 break; 98 case StackFrameFunctionCode: 99 if (stackFrameCallee && stackFrameCallee->inherits(&JSFunction::s_info)) { 100 UString functionName = asFunction(stackFrameCallee)->name(callFrame.get()); 101 if (hasSourceURLInfo) 102 traceLine = hasLineInfo ? String::format("%s at %s:%d", functionName.ascii().data(), sourceURL.ascii().data(), line) 103 : String::format("%s at %s", functionName.ascii().data(), sourceURL.ascii().data()); 104 else 105 traceLine = String::format("%s\n", functionName.ascii().data()); 106 break; 107 } 108 case StackFrameGlobalCode: 109 traceLine = hasLineInfo ? String::format("at %s:%d", sourceURL.ascii().data(), line) 110 : String::format("at %s", sourceURL.ascii().data()); 111 } 112 return traceLine.impl(); 113 } 114 }; 115 65 116 class TopCallFrameSetter { 66 117 public: … … 129 180 NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset); 130 181 NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); 182 static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int); 183 static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results); 131 184 132 185 void dumpSampleData(ExecState* exec); -
trunk/Source/JavaScriptCore/jsc.cpp
r95751 r96131 28 28 #include "ExceptionHelpers.h" 29 29 #include "InitializeThreading.h" 30 #include "Interpreter.h" 30 31 #include "JSArray.h" 31 32 #include "JSFunction.h" … … 74 75 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*); 75 76 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*); 77 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); 76 78 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*); 77 79 #ifndef NDEBUG … … 175 177 addFunction(globalData, "load", functionLoad, 1); 176 178 addFunction(globalData, "checkSyntax", functionCheckSyntax, 1); 179 addFunction(globalData, "jscStack", functionJSCStack, 1); 177 180 addFunction(globalData, "readline", functionReadline, 0); 178 181 addFunction(globalData, "preciseTime", functionPreciseTime, 0); … … 219 222 { 220 223 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data()); 224 return JSValue::encode(jsUndefined()); 225 } 226 227 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec) 228 { 229 String trace = "--> Stack trace:\n"; 230 Vector<StackFrame> stackTrace; 231 Interpreter::getStackTrace(&exec->globalData(), -1, stackTrace); 232 int i = 0; 233 234 for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) { 235 StackFrame level = *iter; 236 trace += String::format(" %i %s\n", i, level.toString().utf8().data()); 237 i++; 238 } 239 fprintf(stderr, "%s", trace.utf8().data()); 221 240 return JSValue::encode(jsUndefined()); 222 241 } -
trunk/Source/JavaScriptCore/parser/Parser.h
r90159 r96131 115 115 *exception = createSyntaxError(lexicalGlobalObject, errMsg); 116 116 else 117 *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source );117 *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source, Vector<StackFrame>()); 118 118 } 119 119 -
trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h
r95751 r96131 53 53 macro(isArray) \ 54 54 macro(isPrototypeOf) \ 55 macro(jscStack) \ 55 56 macro(length) \ 56 57 macro(message) \ -
trunk/Source/JavaScriptCore/runtime/Error.cpp
r95108 r96131 27 27 #include "ConstructData.h" 28 28 #include "ErrorConstructor.h" 29 #include "JSArray.h" 29 30 #include "JSFunction.h" 30 31 #include "JSGlobalObject.h" … … 117 118 } 118 119 119 JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source )120 JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace) 120 121 { 121 122 intptr_t sourceID = source.provider()->asID(); … … 128 129 if (!sourceURL.isNull()) 129 130 error->putWithAttributes(globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete); 131 if (!stackTrace.isEmpty()) { 132 JSArray* stackTraceArray = JSArray::create(*globalData, globalData->dynamicGlobalObject->arrayStructure()); 133 for (unsigned i = 0; i < stackTrace.size(); i++) { 134 UString stackLevel = stackTrace[i].toString(); 135 stackTraceArray->push(globalData->topCallFrame, jsString(globalData, stackLevel)); 136 } 137 error->putWithAttributes(globalData, globalData->propertyNames->jscStack, stackTraceArray, ReadOnly | DontDelete); 138 } 130 139 131 140 return error; 132 141 } 133 142 134 JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source )135 { 136 return addErrorInfo(&exec->globalData(), error, line, source );143 JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace) 144 { 145 return addErrorInfo(&exec->globalData(), error, line, source, stackTrace); 137 146 } 138 147 -
trunk/Source/JavaScriptCore/runtime/Error.h
r72050 r96131 24 24 #define Error_h 25 25 26 #include "Interpreter.h" 26 27 #include "JSObject.h" 27 28 #include <stdint.h> … … 56 57 // Methods to add 57 58 bool hasErrorInfo(ExecState*, JSObject* error); 58 JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode& );59 JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&); 59 60 // ExecState wrappers. 60 JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode& );61 JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&); 61 62 62 63 // Methods to throw Errors.
Note:
See TracChangeset
for help on using the changeset viewer.