WebKit Bugzilla
Attachment 343406 Details for
Bug 186947
: Add more debugging features to $vm.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
proposed patch.
bug-186947.patch (text/plain), 12.88 KB, created by
Mark Lam
on 2018-06-22 18:17:51 PDT
(
hide
)
Description:
proposed patch.
Filename:
MIME Type:
Creator:
Mark Lam
Created:
2018-06-22 18:17:51 PDT
Size:
12.88 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 233115) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,57 @@ >+2018-06-22 Mark Lam <mark.lam@apple.com> >+ >+ Add more debugging features to $vm. >+ https://bugs.webkit.org/show_bug.cgi?id=186947 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adding the following features: >+ >+ // We now have println in addition to print. >+ // println automatically adds a '\n' at the end. >+ $vm.println("Hello"); >+ >+ // We can now capture some info about a stack frame. >+ var currentFrame = $vm.callFrame(); // Same as $vm.callFrame(0); >+ var callerCallerFrame = $vm.callFrame(2); >+ >+ // We can inspect the following values associated with the frame: >+ if (currentFrame.valid) { >+ $vm.println("name is ", currentFrame.name)); >+ $vm.println("callee is ", $vm.value(currentFrame.callee)); >+ $vm.println("codeBlock is ", currentFrame.codeBlock); >+ $vm.println("unlinkedCodeBlock is ", currentFrame.unlinkedCodeBlock); >+ $vm.println("executable is ", currentFrame.executable); >+ } >+ >+ // Note that callee is a JSObject. I printed its $vm.value() because I wanted >+ // to dataLog its JSValue instead of its toString() result. >+ >+ // Note that $vm.println() (and $vm.print()) can now print internal JSCells >+ // (and Symbols) as JSValue dumps. It won't just fail on trying to do a >+ // toString on a non-object. >+ >+ // Does what it says about enabling/disabling debugger mode. >+ $vm.enableDebuggerModeWhenIdle(); >+ $vm.disableDebuggerModeWhenIdle(); >+ >+ * tools/JSDollarVM.cpp: >+ (WTF::JSDollarVMCallFrame::JSDollarVMCallFrame): >+ (WTF::JSDollarVMCallFrame::createStructure): >+ (WTF::JSDollarVMCallFrame::create): >+ (WTF::JSDollarVMCallFrame::finishCreation): >+ (WTF::JSDollarVMCallFrame::addProperty): >+ (JSC::functionCallFrame): >+ (JSC::functionCodeBlockForFrame): >+ (JSC::codeBlockFromArg): >+ (JSC::doPrintln): >+ (JSC::functionPrint): >+ (JSC::functionPrintln): >+ (JSC::changeDebuggerModeWhenIdle): >+ (JSC::functionEnableDebuggerModeWhenIdle): >+ (JSC::functionDisableDebuggerModeWhenIdle): >+ (JSC::JSDollarVM::finishCreation): >+ > 2018-06-22 Mark Lam <mark.lam@apple.com> > > PropertyCondition::isValidValueForAttributes() should also consider deleted values. >Index: Source/JavaScriptCore/tools/JSDollarVM.cpp >=================================================================== >--- Source/JavaScriptCore/tools/JSDollarVM.cpp (revision 233107) >+++ Source/JavaScriptCore/tools/JSDollarVM.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2015-2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2015-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -56,6 +56,71 @@ using namespace WTF; > > namespace { > >+class JSDollarVMCallFrame : public JSDestructibleObject { >+ using Base = JSDestructibleObject; >+public: >+ JSDollarVMCallFrame(VM& vm, Structure* structure) >+ : Base(vm, structure) >+ { } >+ >+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) >+ { >+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); >+ } >+ >+ static JSDollarVMCallFrame* create(ExecState* exec, unsigned requestedFrameIndex) >+ { >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); >+ Structure* structure = createStructure(vm, globalObject, jsNull()); >+ JSDollarVMCallFrame* frame = new (NotNull, allocateCell<JSDollarVMCallFrame>(vm.heap, sizeof(JSDollarVMCallFrame))) JSDollarVMCallFrame(vm, structure); >+ frame->finishCreation(vm, exec, requestedFrameIndex); >+ return frame; >+ } >+ >+ void finishCreation(VM& vm, CallFrame* frame, unsigned requestedFrameIndex) >+ { >+ Base::finishCreation(vm); >+ >+ auto addProperty = [&] (VM& vm, const char* name, JSValue value) { >+ JSDollarVMCallFrame::addProperty(vm, name, value); >+ }; >+ >+ unsigned frameIndex = 0; >+ bool isValid = false; >+ frame->iterate([&] (StackVisitor& visitor) { >+ >+ if (frameIndex++ != requestedFrameIndex) >+ return StackVisitor::Continue; >+ >+ if (visitor->callee().isCell()) >+ addProperty(vm, "callee", visitor->callee().asCell()); >+ >+ addProperty(vm, "name", jsString(&vm, visitor->functionName())); >+ CodeBlock* codeBlock = visitor->codeBlock(); >+ addProperty(vm, "codeBlock", codeBlock); >+ addProperty(vm, "unlinkedCodeBlock", codeBlock->unlinkedCodeBlock()); >+ addProperty(vm, "executable", codeBlock->ownerExecutable()); >+ isValid = true; >+ >+ return StackVisitor::Done; >+ }); >+ >+ addProperty(vm, "valid", jsBoolean(isValid)); >+ } >+ >+ DECLARE_INFO; >+ >+private: >+ void addProperty(VM& vm, const char* name, JSValue value) >+ { >+ Identifier identifier = Identifier::fromString(&vm, name); >+ putDirect(vm, identifier, value); >+ } >+}; >+ >+const ClassInfo JSDollarVMCallFrame::s_info = { "CallFrame", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVMCallFrame) }; >+ > class ElementHandleOwner; > class Root; > >@@ -1245,26 +1310,45 @@ static EncodedJSValue JSC_HOST_CALL func > return JSValue::encode(jsUndefined()); > } > >+// Gets a JSDollarVMCallFrame for a specified frame index. >+// Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame. >+// Usage: var callFrame = $vm.callFrame() // implies frame 0 i.e. current frame. >+static EncodedJSValue JSC_HOST_CALL functionCallFrame(ExecState* exec) >+{ >+ unsigned frameNumber = 1; >+ if (exec->argumentCount() >= 1) { >+ JSValue value = exec->uncheckedArgument(0); >+ if (!value.isUInt32()) >+ return JSValue::encode(jsUndefined()); >+ >+ // We need to inc the frame number because the caller would consider >+ // its own frame as frame 0. Hence, we need discount the frame for this >+ // function. >+ frameNumber = value.asUInt32() + 1; >+ } >+ >+ return JSValue::encode(JSDollarVMCallFrame::create(exec, frameNumber)); >+} >+ > // Gets a token for the CodeBlock for a specified frame index. > // Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top frame. >+// Usage: codeBlockToken = $vm.codeBlockForFrame() // implies frame 0 i.e. current frame. > static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(ExecState* exec) > { >- if (exec->argumentCount() < 1) >- return JSValue::encode(jsUndefined()); >- >- JSValue value = exec->uncheckedArgument(0); >- if (!value.isUInt32()) >- return JSValue::encode(jsUndefined()); >+ unsigned frameNumber = 1; >+ if (exec->argumentCount() >= 1) { >+ JSValue value = exec->uncheckedArgument(0); >+ if (!value.isUInt32()) >+ return JSValue::encode(jsUndefined()); >+ >+ // We need to inc the frame number because the caller would consider >+ // its own frame as frame 0. Hence, we need discount the frame for this >+ // function. >+ frameNumber = value.asUInt32() + 1; >+ } > >- // We need to inc the frame number because the caller would consider >- // its own frame as frame 0. Hence, we need discount the frame for this >- // function. >- unsigned frameNumber = value.asUInt32() + 1; > CodeBlock* codeBlock = VMInspector::codeBlockForFrame(exec, frameNumber); >- // Though CodeBlock is a JSCell, it is not safe to return it directly back to JS code >- // as it is an internal type that the JS code cannot handle. Hence, we first encode the >- // CodeBlock* as a double token (which is safe for JS code to handle) before returning it. >- return JSValue::encode(JSValue(bitwise_cast<double>(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(codeBlock))))); >+ return JSValue::encode(codeBlock); > } > > static CodeBlock* codeBlockFromArg(ExecState* exec) >@@ -1282,12 +1366,8 @@ static CodeBlock* codeBlockFromArg(ExecS > candidateCodeBlock = nullptr; > else > candidateCodeBlock = func->jsExecutable()->eitherCodeBlock(); >- } >- } else if (value.isDouble()) { >- // If the value is a double, it may be an encoded CodeBlock* that came from >- // $vm.codeBlockForFrame(). We'll treat it as a candidate codeBlock and check if it's >- // valid below before using. >- candidateCodeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble())); >+ } else >+ candidateCodeBlock = reinterpret_cast<CodeBlock*>(value.asCell()); > } > > if (candidateCodeBlock && VMInspector::isValidCodeBlock(exec, candidateCodeBlock)) >@@ -1333,19 +1413,43 @@ static EncodedJSValue JSC_HOST_CALL func > return JSValue::encode(jsUndefined()); > } > >-// Prints a series of comma separate strings without inserting a newline. >-// Usage: $vm.print(str1, str2, str3) >-static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) >+static EncodedJSValue doPrintln(ExecState* exec, bool addLineFeed) > { > auto scope = DECLARE_THROW_SCOPE(exec->vm()); > for (unsigned i = 0; i < exec->argumentCount(); ++i) { >+ JSValue arg = exec->uncheckedArgument(i); >+ if (arg.isCell() >+ && !arg.isObject() >+ && !arg.isString() >+ && !arg.isBigInt()) { >+ dataLog(arg); >+ continue; >+ } > String argStr = exec->uncheckedArgument(i).toWTFString(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > dataLog(argStr); > } >+ if (addLineFeed) >+ dataLog("\n"); > return JSValue::encode(jsUndefined()); > } > >+// Prints a series of comma separate strings without appending a newline. >+// Usage: $vm.print(str1, str2, str3) >+static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) >+{ >+ const bool addLineFeed = false; >+ return doPrintln(exec, addLineFeed); >+} >+ >+// Prints a series of comma separate strings and appends a newline. >+// Usage: $vm.println(str1, str2, str3) >+static EncodedJSValue JSC_HOST_CALL functionPrintln(ExecState* exec) >+{ >+ const bool addLineFeed = true; >+ return doPrintln(exec, addLineFeed); >+} >+ > // Prints the current CallFrame. > // Usage: $vm.printCallFrame() > static EncodedJSValue JSC_HOST_CALL functionPrintCallFrame(ExecState* exec) >@@ -1717,6 +1821,30 @@ static EncodedJSValue JSC_HOST_CALL func > return JSValue::encode(jsUndefined()); > } > >+static EncodedJSValue changeDebuggerModeWhenIdle(ExecState* exec, DebuggerMode mode) >+{ >+ bool newDebuggerMode = (mode == DebuggerOn); >+ if (Options::forceDebuggerBytecodeGeneration() == newDebuggerMode) >+ return JSValue::encode(jsUndefined()); >+ >+ VM* vm = &exec->vm(); >+ vm->whenIdle([=] () { >+ Options::forceDebuggerBytecodeGeneration() = newDebuggerMode; >+ vm->deleteAllCode(PreventCollectionAndDeleteAllCode); >+ }); >+ return JSValue::encode(jsUndefined()); >+} >+ >+static EncodedJSValue JSC_HOST_CALL functionEnableDebuggerModeWhenIdle(ExecState* exec) >+{ >+ return changeDebuggerModeWhenIdle(exec, DebuggerOn); >+} >+ >+static EncodedJSValue JSC_HOST_CALL functionDisableDebuggerModeWhenIdle(ExecState* exec) >+{ >+ return changeDebuggerModeWhenIdle(exec, DebuggerOff); >+} >+ > static EncodedJSValue JSC_HOST_CALL functionGlobalObjectCount(ExecState* exec) > { > return JSValue::encode(jsNumber(exec->vm().heap.globalObjectCount())); >@@ -1832,12 +1960,14 @@ void JSDollarVM::finishCreation(VM& vm) > addFunction(vm, "gc", functionGC, 0); > addFunction(vm, "edenGC", functionEdenGC, 0); > >+ addFunction(vm, "callFrame", functionCallFrame, 1); > addFunction(vm, "codeBlockFor", functionCodeBlockFor, 1); > addFunction(vm, "codeBlockForFrame", functionCodeBlockForFrame, 1); > addFunction(vm, "printSourceFor", functionPrintSourceFor, 1); > addFunction(vm, "printBytecodeFor", functionPrintBytecodeFor, 1); > > addFunction(vm, "print", functionPrint, 1); >+ addFunction(vm, "println", functionPrintln, 1); > addFunction(vm, "printCallFrame", functionPrintCallFrame, 0); > addFunction(vm, "printStack", functionPrintStack, 0); > >@@ -1882,6 +2012,9 @@ void JSDollarVM::finishCreation(VM& vm) > > addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0); > >+ addFunction(vm, "enableDebuggerModeWhenIdle", functionEnableDebuggerModeWhenIdle, 0); >+ addFunction(vm, "disableDebuggerModeWhenIdle", functionDisableDebuggerModeWhenIdle, 0); >+ > addFunction(vm, "globalObjectCount", functionGlobalObjectCount, 0); > addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1); >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
keith_miller
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186947
: 343406