Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (224837 => 224838)
--- trunk/Source/_javascript_Core/ChangeLog 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1,3 +1,73 @@
+2017-11-14 Mark Lam <mark....@apple.com>
+
+ Remove JSDollarVMPrototype.
+ https://bugs.webkit.org/show_bug.cgi?id=179685
+
+ Reviewed by Saam Barati.
+
+ 1. Move the JSDollarVMPrototype C++ utility functions into VMInspector.cpp.
+
+ This allows us to call these functions during lldb debugging sessions using
+ VMInspector::foo() instead of JSDollarVMPrototype::foo(). It makes sense that
+ VMInspector provides VM debugging utility methods. It doesn't make sense to
+ have a JSDollarVMPrototype object provide these methods.
+
+ Plus, it's shorter to type VMInspector than JSDollarVMPrototype.
+
+ 2. Move the JSDollarVMPrototype JS functions into JSDollarVM.cpp.
+
+ JSDollarVM is a special object used only for debugging purposes. There's no
+ gain in requiring its methods to be stored in a prototype object other than to
+ conform to typical JS convention. We can remove this complexity.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * Sources.txt:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ * tools/JSDollarVM.cpp:
+ (JSC::JSDollarVM::addFunction):
+ (JSC::functionCrash):
+ (JSC::functionDFGTrue):
+ (JSC::CallerFrameJITTypeFunctor::CallerFrameJITTypeFunctor):
+ (JSC::CallerFrameJITTypeFunctor::operator() const):
+ (JSC::CallerFrameJITTypeFunctor::jitType):
+ (JSC::functionLLintTrue):
+ (JSC::functionJITTrue):
+ (JSC::functionGC):
+ (JSC::functionEdenGC):
+ (JSC::functionCodeBlockForFrame):
+ (JSC::codeBlockFromArg):
+ (JSC::functionCodeBlockFor):
+ (JSC::functionPrintSourceFor):
+ (JSC::functionPrintBytecodeFor):
+ (JSC::functionPrint):
+ (JSC::functionPrintCallFrame):
+ (JSC::functionPrintStack):
+ (JSC::functionValue):
+ (JSC::functionGetPID):
+ (JSC::JSDollarVM::finishCreation):
+ * tools/JSDollarVM.h:
+ (JSC::JSDollarVM::create):
+ * tools/JSDollarVMPrototype.cpp: Removed.
+ * tools/JSDollarVMPrototype.h: Removed.
+ * tools/VMInspector.cpp:
+ (JSC::VMInspector::currentThreadOwnsJSLock):
+ (JSC::ensureCurrentThreadOwnsJSLock):
+ (JSC::VMInspector::gc):
+ (JSC::VMInspector::edenGC):
+ (JSC::VMInspector::isInHeap):
+ (JSC::CellAddressCheckFunctor::CellAddressCheckFunctor):
+ (JSC::CellAddressCheckFunctor::operator() const):
+ (JSC::VMInspector::isValidCell):
+ (JSC::VMInspector::isValidCodeBlock):
+ (JSC::VMInspector::codeBlockForFrame):
+ (JSC::PrintFrameFunctor::PrintFrameFunctor):
+ (JSC::PrintFrameFunctor::operator() const):
+ (JSC::VMInspector::printCallFrame):
+ (JSC::VMInspector::printStack):
+ (JSC::VMInspector::printValue):
+ * tools/VMInspector.h:
+
2017-11-14 Joseph Pecoraro <pecor...@apple.com>
Web Inspector: Add a ServiceWorker domain to get information about an inspected ServiceWorker
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (224837 => 224838)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1716,7 +1716,6 @@
FE318FE01CAC982F00DFCC54 /* ECMAScriptSpecInternalFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE318FDE1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.h */; };
FE3422121D6B81C30032BE88 /* ThrowScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3422111D6B818C0032BE88 /* ThrowScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
- FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE3A06A61C10B72D00390FDD /* JITBitOrGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06A41C10B70800390FDD /* JITBitOrGenerator.h */; };
FE3A06A81C10BC8100390FDD /* JITBitBinaryOpGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06A71C10BC7400390FDD /* JITBitBinaryOpGenerator.h */; };
FE3A06B21C10CB8900390FDD /* JITBitAndGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06AE1C10CB6F00390FDD /* JITBitAndGenerator.h */; };
@@ -3181,9 +3180,9 @@
530A66B51FA3E77D0026A545 /* UnifiedSource5-mm.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UnifiedSource5-mm.mm"; sourceTree = "<group>"; };
530A66B61FA3E77D0026A545 /* UnifiedSource142.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource142.cpp; sourceTree = "<group>"; };
530A66B71FA3E77D0026A545 /* UnifiedSource143.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource143.cpp; sourceTree = "<group>"; };
- 530A66B81FA3E77E0026A545 /* UnifiedSource4-mm.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UnifiedSource4-mm.mm"; sourceTree = "<group>"; };
- 530A66CC1FB1346D0026A545 /* SuperSamplerBytecodeScope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SuperSamplerBytecodeScope.h; sourceTree = "<group>"; };
- 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmWorklist.h; sourceTree = "<group>"; };
+ 530A66B81FA3E77E0026A545 /* UnifiedSource4-mm.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UnifiedSource4-mm.mm"; sourceTree = "<group>"; };
+ 530A66CC1FB1346D0026A545 /* SuperSamplerBytecodeScope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SuperSamplerBytecodeScope.h; sourceTree = "<group>"; };
+ 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmWorklist.h; sourceTree = "<group>"; };
530FB3031E7A1146003C19DD /* WasmWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmWorklist.cpp; sourceTree = "<group>"; };
5311BD481EA581E500525281 /* WasmOMGPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOMGPlan.cpp; sourceTree = "<group>"; };
5311BD491EA581E500525281 /* WasmOMGPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOMGPlan.h; sourceTree = "<group>"; };
@@ -4584,8 +4583,6 @@
FE3422111D6B818C0032BE88 /* ThrowScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThrowScope.h; sourceTree = "<group>"; };
FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; };
FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVM.h; sourceTree = "<group>"; };
- FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVMPrototype.cpp; sourceTree = "<group>"; };
- FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVMPrototype.h; sourceTree = "<group>"; };
FE3A06A31C10B70800390FDD /* JITBitOrGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITBitOrGenerator.cpp; sourceTree = "<group>"; };
FE3A06A41C10B70800390FDD /* JITBitOrGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITBitOrGenerator.h; sourceTree = "<group>"; };
FE3A06A71C10BC7400390FDD /* JITBitBinaryOpGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITBitBinaryOpGenerator.h; sourceTree = "<group>"; };
@@ -6899,8 +6896,6 @@
FE1BD0231E72052F00134BC9 /* HeapVerifier.h */,
FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */,
FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */,
- FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */,
- FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */,
86B5822C14D22F5F00A9C306 /* ProfileTreeNode.h */,
FE3022D01E3D739600BAC493 /* SigillCrashAnalyzer.cpp */,
FE3022D11E3D739600BAC493 /* SigillCrashAnalyzer.h */,
@@ -8780,7 +8775,6 @@
C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
0F7DF13C1E2971130095951B /* JSDestructibleObjectSubspace.h in Headers */,
FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */,
- FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */,
86E3C614167BABD7006D760A /* JSExport.h in Headers */,
A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */,
798937791DCAB57300F8D4FB /* JSFixedArray.h in Headers */,
Modified: trunk/Source/_javascript_Core/Sources.txt (224837 => 224838)
--- trunk/Source/_javascript_Core/Sources.txt 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/Sources.txt 2017-11-14 21:16:24 UTC (rev 224838)
@@ -932,7 +932,6 @@
tools/FunctionWhitelist.cpp
tools/HeapVerifier.cpp
tools/JSDollarVM.cpp
-tools/JSDollarVMPrototype.cpp
tools/SigillCrashAnalyzer.cpp
tools/VMInspector.cpp
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (224837 => 224838)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2017-11-14 21:16:24 UTC (rev 224838)
@@ -85,7 +85,6 @@
#include "JSDataView.h"
#include "JSDataViewPrototype.h"
#include "JSDollarVM.h"
-#include "JSDollarVMPrototype.h"
#include "JSFunction.h"
#include "JSGeneratorFunction.h"
#include "JSGenericTypedArrayViewConstructorInlines.h"
@@ -896,9 +895,8 @@
m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::ThrowTypeErrorFunction)] = m_throwTypeErrorFunction.get();
if (UNLIKELY(Options::useDollarVM())) {
- JSDollarVMPrototype* dollarVMPrototype = JSDollarVMPrototype::create(vm, this, JSDollarVMPrototype::createStructure(vm, this, m_objectPrototype.get()));
- m_dollarVMStructure.set(vm, this, JSDollarVM::createStructure(vm, this, dollarVMPrototype));
- JSDollarVM* dollarVM = JSDollarVM::create(vm, m_dollarVMStructure.get());
+ m_dollarVMStructure.set(vm, this, JSDollarVM::createStructure(vm, this, m_objectPrototype.get()));
+ JSDollarVM* dollarVM = JSDollarVM::create(vm, this, m_dollarVMStructure.get());
GlobalPropertyInfo extraStaticGlobals[] = {
GlobalPropertyInfo(vm.propertyNames->builtinNames().dollarVMPrivateName(), dollarVM, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.cpp (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/JSDollarVM.cpp 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.cpp 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,10 +26,268 @@
#include "config.h"
#include "JSDollarVM.h"
+#include "CodeBlock.h"
+#include "FunctionCodeBlock.h"
#include "JSCInlines.h"
+#include "VMInspector.h"
+#include <wtf/DataLog.h>
+#include <wtf/ProcessID.h>
+#include <wtf/StringPrintStream.h>
namespace JSC {
const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) };
+void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
+{
+ Identifier identifier = Identifier::fromString(&vm, name);
+ putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
+}
+
+// Triggers a crash immediately.
+// Usage: $vm.crash()
+static EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*)
+{
+ CRASH();
+ return JSValue::encode(jsUndefined());
+}
+
+// Returns true if the current frame is a DFG frame.
+// Usage: isDFG = $vm.dfgTrue()
+static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
+{
+ return JSValue::encode(jsBoolean(false));
+}
+
+class CallerFrameJITTypeFunctor {
+public:
+ CallerFrameJITTypeFunctor()
+ : m_currentFrame(0)
+ , m_jitType(JITCode::None)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor) const
+ {
+ if (m_currentFrame++ > 1) {
+ m_jitType = visitor->codeBlock()->jitType();
+ return StackVisitor::Done;
+ }
+ return StackVisitor::Continue;
+ }
+
+ JITCode::JITType jitType() { return m_jitType; }
+
+private:
+ mutable unsigned m_currentFrame;
+ mutable JITCode::JITType m_jitType;
+};
+
+// Returns true if the current frame is a LLInt frame.
+// Usage: isLLInt = $vm.llintTrue()
+static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec)
+{
+ if (!exec)
+ return JSValue::encode(jsUndefined());
+ CallerFrameJITTypeFunctor functor;
+ exec->iterate(functor);
+ return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk));
+}
+
+// Returns true if the current frame is a baseline JIT frame.
+// Usage: isBaselineJIT = $vm.jitTrue()
+static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec)
+{
+ if (!exec)
+ return JSValue::encode(jsUndefined());
+ CallerFrameJITTypeFunctor functor;
+ exec->iterate(functor);
+ return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT));
+}
+
+// Runs a full GC synchronously.
+// Usage: $vm.gc()
+static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
+{
+ VMInspector::gc(exec);
+ return JSValue::encode(jsUndefined());
+}
+
+// Runs the edenGC synchronously.
+// Usage: $vm.edenGC()
+static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
+{
+ VMInspector::edenGC(exec);
+ return JSValue::encode(jsUndefined());
+}
+
+// Gets a token for the CodeBlock for a specified frame index.
+// Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top 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());
+
+ // 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)))));
+}
+
+static CodeBlock* codeBlockFromArg(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ if (exec->argumentCount() < 1)
+ return nullptr;
+
+ JSValue value = exec->uncheckedArgument(0);
+ CodeBlock* candidateCodeBlock = nullptr;
+ if (value.isCell()) {
+ JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell());
+ if (func) {
+ if (func->isHostFunction())
+ 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()));
+ }
+
+ if (candidateCodeBlock && VMInspector::isValidCodeBlock(exec, candidateCodeBlock))
+ return candidateCodeBlock;
+
+ if (candidateCodeBlock)
+ dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n");
+ else
+ dataLog("Invalid codeBlock: ", value, "\n");
+ return nullptr;
+}
+
+// Usage: print("codeblock = " + $vm.codeBlockFor(functionObj))
+// Usage: print("codeblock = " + $vm.codeBlockFor(codeBlockToken))
+static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(ExecState* exec)
+{
+ CodeBlock* codeBlock = codeBlockFromArg(exec);
+ WTF::StringPrintStream stream;
+ if (codeBlock) {
+ stream.print(*codeBlock);
+ return JSValue::encode(jsString(exec, stream.toString()));
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+// Usage: $vm.printSourceFor(functionObj)
+// Usage: $vm.printSourceFor(codeBlockToken)
+static EncodedJSValue JSC_HOST_CALL functionPrintSourceFor(ExecState* exec)
+{
+ CodeBlock* codeBlock = codeBlockFromArg(exec);
+ if (codeBlock)
+ codeBlock->dumpSource();
+ return JSValue::encode(jsUndefined());
+}
+
+// Usage: $vm.printBytecodeFor(functionObj)
+// Usage: $vm.printBytecode(codeBlockToken)
+static EncodedJSValue JSC_HOST_CALL functionPrintBytecodeFor(ExecState* exec)
+{
+ CodeBlock* codeBlock = codeBlockFromArg(exec);
+ if (codeBlock)
+ codeBlock->dumpBytecode();
+ 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)
+{
+ auto scope = DECLARE_THROW_SCOPE(exec->vm());
+ for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+ String argStr = exec->uncheckedArgument(i).toWTFString(exec);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ dataLog(argStr);
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+// Prints the current CallFrame.
+// Usage: $vm.printCallFrame()
+static EncodedJSValue JSC_HOST_CALL functionPrintCallFrame(ExecState* exec)
+{
+ // When the callers call this function, they are expecting to print their
+ // own frame. So skip 1 for this frame.
+ VMInspector::printCallFrame(exec, 1);
+ return JSValue::encode(jsUndefined());
+}
+
+// Prints the JS stack.
+// Usage: $vm.printStack()
+static EncodedJSValue JSC_HOST_CALL functionPrintStack(ExecState* exec)
+{
+ // When the callers call this function, they are expecting to print the
+ // stack starting their own frame. So skip 1 for this frame.
+ VMInspector::printStack(exec, 1);
+ return JSValue::encode(jsUndefined());
+}
+
+// Gets the dataLog dump of a given JS value as a string.
+// Usage: print("value = " + $vm.value(jsValue))
+static EncodedJSValue JSC_HOST_CALL functionValue(ExecState* exec)
+{
+ WTF::StringPrintStream stream;
+ for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+ if (i)
+ stream.print(", ");
+ stream.print(exec->uncheckedArgument(i));
+ }
+
+ return JSValue::encode(jsString(exec, stream.toString()));
+}
+
+// Gets the pid of the current process.
+// Usage: print("pid = " + $vm.getpid())
+static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*)
+{
+ return JSValue::encode(jsNumber(getCurrentProcessID()));
+}
+
+void JSDollarVM::finishCreation(VM& vm, JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+
+ addFunction(vm, globalObject, "crash", functionCrash, 0);
+
+ putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
+
+ addFunction(vm, globalObject, "llintTrue", functionLLintTrue, 0);
+ addFunction(vm, globalObject, "jitTrue", functionJITTrue, 0);
+
+ addFunction(vm, globalObject, "gc", functionGC, 0);
+ addFunction(vm, globalObject, "edenGC", functionEdenGC, 0);
+
+ addFunction(vm, globalObject, "codeBlockFor", functionCodeBlockFor, 1);
+ addFunction(vm, globalObject, "codeBlockForFrame", functionCodeBlockForFrame, 1);
+ addFunction(vm, globalObject, "printSourceFor", functionPrintSourceFor, 1);
+ addFunction(vm, globalObject, "printBytecodeFor", functionPrintBytecodeFor, 1);
+
+ addFunction(vm, globalObject, "print", functionPrint, 1);
+ addFunction(vm, globalObject, "printCallFrame", functionPrintCallFrame, 0);
+ addFunction(vm, globalObject, "printStack", functionPrintStack, 0);
+
+ addFunction(vm, globalObject, "value", functionValue, 1);
+ addFunction(vm, globalObject, "getpid", functionGetPID, 0);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.h (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/JSDollarVM.h 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.h 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,11 +39,11 @@
{
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
-
- static JSDollarVM* create(VM& vm, Structure* structure)
+
+ static JSDollarVM* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
{
JSDollarVM* instance = new (NotNull, allocateCell<JSDollarVM>(vm.heap)) JSDollarVM(vm, structure);
- instance->finishCreation(vm);
+ instance->finishCreation(vm, globalObject);
return instance;
}
@@ -52,6 +52,9 @@
: Base(vm, structure)
{
}
+
+ void finishCreation(VM&, JSGlobalObject*);
+ void addFunction(VM&, JSGlobalObject*, const char* name, NativeFunction, unsigned arguments);
};
} // namespace JSC
Deleted: trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.cpp (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.cpp 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.cpp 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSDollarVMPrototype.h"
-
-#include "CodeBlock.h"
-#include "FunctionCodeBlock.h"
-#include "Heap.h"
-#include "HeapIterationScope.h"
-#include "JSCInlines.h"
-#include "JSFunction.h"
-#include "MarkedSpaceInlines.h"
-#include "StackVisitor.h"
-#include <wtf/DataLog.h>
-#include <wtf/ProcessID.h>
-#include <wtf/StringPrintStream.h>
-
-namespace JSC {
-
-const ClassInfo JSDollarVMPrototype::s_info = { "DollarVMPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVMPrototype) };
-
-
-bool JSDollarVMPrototype::currentThreadOwnsJSLock(ExecState* exec)
-{
- return exec->vm().currentThreadIsHoldingAPILock();
-}
-
-static bool ensureCurrentThreadOwnsJSLock(ExecState* exec)
-{
- if (JSDollarVMPrototype::currentThreadOwnsJSLock(exec))
- return true;
- dataLog("ERROR: current thread does not own the JSLock\n");
- return false;
-}
-
-void JSDollarVMPrototype::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
-{
- Identifier identifier = Identifier::fromString(&vm, name);
- putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
-}
-
-static EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*)
-{
- CRASH();
- return JSValue::encode(jsUndefined());
-}
-
-static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
-{
- return JSValue::encode(jsBoolean(false));
-}
-
-class CallerFrameJITTypeFunctor {
-public:
- CallerFrameJITTypeFunctor()
- : m_currentFrame(0)
- , m_jitType(JITCode::None)
- {
- }
-
- StackVisitor::Status operator()(StackVisitor& visitor) const
- {
- if (m_currentFrame++ > 1) {
- m_jitType = visitor->codeBlock()->jitType();
- return StackVisitor::Done;
- }
- return StackVisitor::Continue;
- }
-
- JITCode::JITType jitType() { return m_jitType; }
-
-private:
- mutable unsigned m_currentFrame;
- mutable JITCode::JITType m_jitType;
-};
-
-static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec)
-{
- if (!exec)
- return JSValue::encode(jsUndefined());
- CallerFrameJITTypeFunctor functor;
- exec->iterate(functor);
- return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk));
-}
-
-static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec)
-{
- if (!exec)
- return JSValue::encode(jsUndefined());
- CallerFrameJITTypeFunctor functor;
- exec->iterate(functor);
- return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT));
-}
-
-void JSDollarVMPrototype::gc(ExecState* exec)
-{
- VM& vm = exec->vm();
- if (!ensureCurrentThreadOwnsJSLock(exec))
- return;
- vm.heap.collectNow(Sync, CollectionScope::Full);
-}
-
-static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
-{
- JSDollarVMPrototype::gc(exec);
- return JSValue::encode(jsUndefined());
-}
-
-void JSDollarVMPrototype::edenGC(ExecState* exec)
-{
- VM& vm = exec->vm();
- if (!ensureCurrentThreadOwnsJSLock(exec))
- return;
- vm.heap.collectSync(CollectionScope::Eden);
-}
-
-static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
-{
- JSDollarVMPrototype::edenGC(exec);
- return JSValue::encode(jsUndefined());
-}
-
-bool JSDollarVMPrototype::isInHeap(Heap* heap, void* ptr)
-{
- return isInObjectSpace(heap, ptr) || isInStorageSpace(heap, ptr);
-}
-
-bool JSDollarVMPrototype::isInObjectSpace(Heap* heap, void* ptr)
-{
- MarkedBlock* candidate = MarkedBlock::blockFor(ptr);
- if (heap->objectSpace().blocks().set().contains(candidate))
- return true;
- for (LargeAllocation* allocation : heap->objectSpace().largeAllocations()) {
- if (allocation->contains(ptr))
- return true;
- }
- return false;
-}
-
-bool JSDollarVMPrototype::isInStorageSpace(Heap*, void*)
-{
- // FIXME: Do something with this.
- // https://bugs.webkit.org/show_bug.cgi?id=161753
- return false;
-}
-
-struct CellAddressCheckFunctor : MarkedBlock::CountFunctor {
- CellAddressCheckFunctor(JSCell* candidate)
- : candidate(candidate)
- {
- }
-
- IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
- {
- if (cell == candidate) {
- found = true;
- return IterationStatus::Done;
- }
- return IterationStatus::Continue;
- }
-
- JSCell* candidate;
- mutable bool found { false };
-};
-
-bool JSDollarVMPrototype::isValidCell(Heap* heap, JSCell* candidate)
-{
- HeapIterationScope iterationScope(*heap);
- CellAddressCheckFunctor functor(candidate);
- heap->objectSpace().forEachLiveCell(iterationScope, functor);
- return functor.found;
-}
-
-bool JSDollarVMPrototype::isValidCodeBlock(ExecState* exec, CodeBlock* candidate)
-{
- if (!ensureCurrentThreadOwnsJSLock(exec))
- return false;
-
- struct CodeBlockValidationFunctor {
- CodeBlockValidationFunctor(CodeBlock* candidate)
- : candidate(candidate)
- {
- }
-
- bool operator()(CodeBlock* codeBlock) const
- {
- if (codeBlock == candidate)
- found = true;
- return found;
- }
-
- CodeBlock* candidate;
- mutable bool found { false };
- };
-
- VM& vm = exec->vm();
- CodeBlockValidationFunctor functor(candidate);
- vm.heap.forEachCodeBlock(functor);
- return functor.found;
-}
-
-CodeBlock* JSDollarVMPrototype::codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber)
-{
- if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
- return nullptr;
-
- if (!topCallFrame)
- return nullptr;
-
- struct FetchCodeBlockFunctor {
- public:
- FetchCodeBlockFunctor(unsigned targetFrameNumber)
- : targetFrame(targetFrameNumber)
- {
- }
-
- StackVisitor::Status operator()(StackVisitor& visitor) const
- {
- currentFrame++;
- if (currentFrame == targetFrame) {
- codeBlock = visitor->codeBlock();
- return StackVisitor::Done;
- }
- return StackVisitor::Continue;
- }
-
- unsigned targetFrame;
- mutable unsigned currentFrame { 0 };
- mutable CodeBlock* codeBlock { nullptr };
- };
-
- FetchCodeBlockFunctor functor(frameNumber);
- topCallFrame->iterate(functor);
- return functor.codeBlock;
-}
-
-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());
-
- // 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 = JSDollarVMPrototype::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)))));
-}
-
-static CodeBlock* codeBlockFromArg(ExecState* exec)
-{
- VM& vm = exec->vm();
- if (exec->argumentCount() < 1)
- return nullptr;
-
- JSValue value = exec->uncheckedArgument(0);
- CodeBlock* candidateCodeBlock = nullptr;
- if (value.isCell()) {
- JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell());
- if (func) {
- if (func->isHostFunction())
- 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()));
- }
-
- if (candidateCodeBlock && JSDollarVMPrototype::isValidCodeBlock(exec, candidateCodeBlock))
- return candidateCodeBlock;
-
- if (candidateCodeBlock)
- dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n");
- else
- dataLog("Invalid codeBlock: ", value, "\n");
- return nullptr;
-}
-
-static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(ExecState* exec)
-{
- CodeBlock* codeBlock = codeBlockFromArg(exec);
- WTF::StringPrintStream stream;
- if (codeBlock) {
- stream.print(*codeBlock);
- return JSValue::encode(jsString(exec, stream.toString()));
- }
- return JSValue::encode(jsUndefined());
-}
-
-static EncodedJSValue JSC_HOST_CALL functionPrintSourceFor(ExecState* exec)
-{
- CodeBlock* codeBlock = codeBlockFromArg(exec);
- if (codeBlock)
- codeBlock->dumpSource();
- return JSValue::encode(jsUndefined());
-}
-
-static EncodedJSValue JSC_HOST_CALL functionPrintByteCodeFor(ExecState* exec)
-{
- CodeBlock* codeBlock = codeBlockFromArg(exec);
- if (codeBlock)
- codeBlock->dumpBytecode();
- return JSValue::encode(jsUndefined());
-}
-
-static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
-{
- auto scope = DECLARE_THROW_SCOPE(exec->vm());
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- String argStr = exec->uncheckedArgument(i).toWTFString(exec);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- dataLog(argStr);
- }
- return JSValue::encode(jsUndefined());
-}
-
-class PrintFrameFunctor {
-public:
- enum Action {
- PrintOne,
- PrintAll
- };
-
- PrintFrameFunctor(Action action, unsigned framesToSkip)
- : m_action(action)
- , m_framesToSkip(framesToSkip)
- {
- }
-
- StackVisitor::Status operator()(StackVisitor& visitor) const
- {
- m_currentFrame++;
- if (m_currentFrame > m_framesToSkip) {
- visitor->dump(WTF::dataFile(), Indenter(2), [&] (PrintStream& out) {
- out.print("[", (m_currentFrame - m_framesToSkip - 1), "] ");
- });
- }
- if (m_action == PrintOne && m_currentFrame > m_framesToSkip)
- return StackVisitor::Done;
- return StackVisitor::Continue;
- }
-
-private:
- Action m_action;
- unsigned m_framesToSkip;
- mutable unsigned m_currentFrame { 0 };
-};
-
-static void printCallFrame(CallFrame* callFrame, unsigned framesToSkip)
-{
- if (!ensureCurrentThreadOwnsJSLock(callFrame))
- return;
- PrintFrameFunctor functor(PrintFrameFunctor::PrintOne, framesToSkip);
- callFrame->iterate(functor);
-}
-
-void JSDollarVMPrototype::printCallFrame(CallFrame* callFrame)
-{
- JSC::printCallFrame(callFrame, 0);
-}
-
-static void printStack(CallFrame* topCallFrame, unsigned framesToSkip)
-{
- if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
- return;
- if (!topCallFrame)
- return;
- PrintFrameFunctor functor(PrintFrameFunctor::PrintAll, framesToSkip);
- topCallFrame->iterate(functor);
-}
-
-void JSDollarVMPrototype::printStack(CallFrame* topCallFrame)
-{
- JSC::printStack(topCallFrame, 0);
-}
-
-static EncodedJSValue JSC_HOST_CALL functionPrintCallFrame(ExecState* exec)
-{
- // When the callers call this function, they are expecting to print their
- // own frame. So skip 1 for this frame.
- printCallFrame(exec, 1);
- return JSValue::encode(jsUndefined());
-}
-
-static EncodedJSValue JSC_HOST_CALL functionPrintStack(ExecState* exec)
-{
- // When the callers call this function, they are expecting to print the
- // stack starting their own frame. So skip 1 for this frame.
- printStack(exec, 1);
- return JSValue::encode(jsUndefined());
-}
-
-void JSDollarVMPrototype::printValue(JSValue value)
-{
- dataLog(value);
-}
-
-static EncodedJSValue JSC_HOST_CALL functionValue(ExecState* exec)
-{
- WTF::StringPrintStream stream;
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- if (i)
- stream.print(", ");
- stream.print(exec->uncheckedArgument(i));
- }
-
- return JSValue::encode(jsString(exec, stream.toString()));
-}
-
-static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*)
-{
- return JSValue::encode(jsNumber(getCurrentProcessID()));
-}
-
-void JSDollarVMPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
-{
- Base::finishCreation(vm);
-
- addFunction(vm, globalObject, "crash", functionCrash, 0);
-
- putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
-
- addFunction(vm, globalObject, "llintTrue", functionLLintTrue, 0);
- addFunction(vm, globalObject, "jitTrue", functionJITTrue, 0);
-
- addFunction(vm, globalObject, "gc", functionGC, 0);
- addFunction(vm, globalObject, "edenGC", functionEdenGC, 0);
-
- addFunction(vm, globalObject, "codeBlockFor", functionCodeBlockFor, 1);
- addFunction(vm, globalObject, "codeBlockForFrame", functionCodeBlockForFrame, 1);
- addFunction(vm, globalObject, "printSourceFor", functionPrintSourceFor, 1);
- addFunction(vm, globalObject, "printByteCodeFor", functionPrintByteCodeFor, 1);
-
- addFunction(vm, globalObject, "print", functionPrint, 1);
- addFunction(vm, globalObject, "printCallFrame", functionPrintCallFrame, 0);
- addFunction(vm, globalObject, "printStack", functionPrintStack, 0);
-
- addFunction(vm, globalObject, "value", functionValue, 1);
- addFunction(vm, globalObject, "getpid", functionGetPID, 0);
-}
-
-} // namespace JSC
Deleted: trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.h (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.h 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/JSDollarVMPrototype.h 2017-11-14 21:16:24 UTC (rev 224838)
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "JSObject.h"
-
-namespace JSC {
-
-class Heap;
-
-class JSDollarVMPrototype : public JSNonFinalObject {
-public:
- typedef JSNonFinalObject Base;
-
- DECLARE_INFO;
-
- static JSDollarVMPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
- {
- JSDollarVMPrototype* prototype = new (NotNull, allocateCell<JSDollarVMPrototype>(vm.heap)) JSDollarVMPrototype(vm, structure);
- prototype->finishCreation(vm, globalObject);
- return prototype;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
- }
-
- // The following are exported because they are designed to be callable from
- // lldb. The JS versions are implemented on top of these.
-
- JS_EXPORT_PRIVATE static bool currentThreadOwnsJSLock(ExecState*);
- JS_EXPORT_PRIVATE static void gc(ExecState*);
- JS_EXPORT_PRIVATE static void edenGC(ExecState*);
- JS_EXPORT_PRIVATE static bool isInHeap(Heap*, void*);
- JS_EXPORT_PRIVATE static bool isInObjectSpace(Heap*, void*);
- JS_EXPORT_PRIVATE static bool isInStorageSpace(Heap*, void*);
- JS_EXPORT_PRIVATE static bool isValidCell(Heap*, JSCell*);
- JS_EXPORT_PRIVATE static bool isValidCodeBlock(ExecState*, CodeBlock*);
- JS_EXPORT_PRIVATE static CodeBlock* codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber);
- JS_EXPORT_PRIVATE static void printCallFrame(CallFrame*);
- JS_EXPORT_PRIVATE static void printStack(CallFrame* topCallFrame);
- JS_EXPORT_PRIVATE static void printValue(JSValue);
-
-private:
- JSDollarVMPrototype(VM& vm, Structure* structure)
- : Base(vm, structure)
- {
- }
-
- void finishCreation(VM&, JSGlobalObject*);
- void addFunction(VM&, JSGlobalObject*, const char* name, NativeFunction, unsigned arguments);
-};
-
-} // namespace JSC
Modified: trunk/Source/_javascript_Core/tools/VMInspector.cpp (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/VMInspector.cpp 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/VMInspector.cpp 2017-11-14 21:16:24 UTC (rev 224838)
@@ -29,7 +29,10 @@
#include "CodeBlock.h"
#include "CodeBlockSet.h"
#include "HeapInlines.h"
+#include "HeapIterationScope.h"
#include "MachineContext.h"
+#include "MarkedSpaceInlines.h"
+#include "StackVisitor.h"
#include <mutex>
#include <wtf/Expected.h>
@@ -194,4 +197,190 @@
#endif
}
+bool VMInspector::currentThreadOwnsJSLock(ExecState* exec)
+{
+ return exec->vm().currentThreadIsHoldingAPILock();
+}
+
+static bool ensureCurrentThreadOwnsJSLock(ExecState* exec)
+{
+ if (VMInspector::currentThreadOwnsJSLock(exec))
+ return true;
+ dataLog("ERROR: current thread does not own the JSLock\n");
+ return false;
+}
+
+void VMInspector::gc(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return;
+ vm.heap.collectNow(Sync, CollectionScope::Full);
+}
+
+void VMInspector::edenGC(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return;
+ vm.heap.collectSync(CollectionScope::Eden);
+}
+
+bool VMInspector::isInHeap(Heap* heap, void* ptr)
+{
+ MarkedBlock* candidate = MarkedBlock::blockFor(ptr);
+ if (heap->objectSpace().blocks().set().contains(candidate))
+ return true;
+ for (LargeAllocation* allocation : heap->objectSpace().largeAllocations()) {
+ if (allocation->contains(ptr))
+ return true;
+ }
+ return false;
+}
+
+struct CellAddressCheckFunctor : MarkedBlock::CountFunctor {
+ CellAddressCheckFunctor(JSCell* candidate)
+ : candidate(candidate)
+ {
+ }
+
+ IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
+ {
+ if (cell == candidate) {
+ found = true;
+ return IterationStatus::Done;
+ }
+ return IterationStatus::Continue;
+ }
+
+ JSCell* candidate;
+ mutable bool found { false };
+};
+
+bool VMInspector::isValidCell(Heap* heap, JSCell* candidate)
+{
+ HeapIterationScope iterationScope(*heap);
+ CellAddressCheckFunctor functor(candidate);
+ heap->objectSpace().forEachLiveCell(iterationScope, functor);
+ return functor.found;
+}
+
+bool VMInspector::isValidCodeBlock(ExecState* exec, CodeBlock* candidate)
+{
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return false;
+
+ struct CodeBlockValidationFunctor {
+ CodeBlockValidationFunctor(CodeBlock* candidate)
+ : candidate(candidate)
+ {
+ }
+
+ bool operator()(CodeBlock* codeBlock) const
+ {
+ if (codeBlock == candidate)
+ found = true;
+ return found;
+ }
+
+ CodeBlock* candidate;
+ mutable bool found { false };
+ };
+
+ VM& vm = exec->vm();
+ CodeBlockValidationFunctor functor(candidate);
+ vm.heap.forEachCodeBlock(functor);
+ return functor.found;
+}
+
+CodeBlock* VMInspector::codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber)
+{
+ if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
+ return nullptr;
+
+ if (!topCallFrame)
+ return nullptr;
+
+ struct FetchCodeBlockFunctor {
+ public:
+ FetchCodeBlockFunctor(unsigned targetFrameNumber)
+ : targetFrame(targetFrameNumber)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor) const
+ {
+ auto currentFrame = nextFrame++;
+ if (currentFrame == targetFrame) {
+ codeBlock = visitor->codeBlock();
+ return StackVisitor::Done;
+ }
+ return StackVisitor::Continue;
+ }
+
+ unsigned targetFrame;
+ mutable unsigned nextFrame { 0 };
+ mutable CodeBlock* codeBlock { nullptr };
+ };
+
+ FetchCodeBlockFunctor functor(frameNumber);
+ topCallFrame->iterate(functor);
+ return functor.codeBlock;
+}
+
+class PrintFrameFunctor {
+public:
+ enum Action {
+ PrintOne,
+ PrintAll
+ };
+
+ PrintFrameFunctor(Action action, unsigned framesToSkip)
+ : m_action(action)
+ , m_framesToSkip(framesToSkip)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor) const
+ {
+ m_currentFrame++;
+ if (m_currentFrame > m_framesToSkip) {
+ visitor->dump(WTF::dataFile(), Indenter(2), [&] (PrintStream& out) {
+ out.print("[", (m_currentFrame - m_framesToSkip - 1), "] ");
+ });
+ }
+ if (m_action == PrintOne && m_currentFrame > m_framesToSkip)
+ return StackVisitor::Done;
+ return StackVisitor::Continue;
+ }
+
+private:
+ Action m_action;
+ unsigned m_framesToSkip;
+ mutable unsigned m_currentFrame { 0 };
+};
+
+void VMInspector::printCallFrame(CallFrame* callFrame, unsigned framesToSkip)
+{
+ if (!ensureCurrentThreadOwnsJSLock(callFrame))
+ return;
+ PrintFrameFunctor functor(PrintFrameFunctor::PrintOne, framesToSkip);
+ callFrame->iterate(functor);
+}
+
+void VMInspector::printStack(CallFrame* topCallFrame, unsigned framesToSkip)
+{
+ if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
+ return;
+ if (!topCallFrame)
+ return;
+ PrintFrameFunctor functor(PrintFrameFunctor::PrintAll, framesToSkip);
+ topCallFrame->iterate(functor);
+}
+
+void VMInspector::printValue(JSValue value)
+{
+ dataLog(value);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/tools/VMInspector.h (224837 => 224838)
--- trunk/Source/_javascript_Core/tools/VMInspector.h 2017-11-14 21:14:57 UTC (rev 224837)
+++ trunk/Source/_javascript_Core/tools/VMInspector.h 2017-11-14 21:16:24 UTC (rev 224838)
@@ -25,6 +25,7 @@
#pragma once
+#include "CallFrame.h"
#include "VM.h"
#include <wtf/DoublyLinkedList.h>
#include <wtf/Expected.h>
@@ -61,6 +62,17 @@
Expected<bool, Error> isValidExecutableMemory(const Locker&, void*);
Expected<CodeBlock*, Error> codeBlockForMachinePC(const Locker&, void*);
+ JS_EXPORT_PRIVATE static bool currentThreadOwnsJSLock(ExecState*);
+ JS_EXPORT_PRIVATE static void gc(ExecState*);
+ JS_EXPORT_PRIVATE static void edenGC(ExecState*);
+ JS_EXPORT_PRIVATE static bool isInHeap(Heap*, void*);
+ JS_EXPORT_PRIVATE static bool isValidCell(Heap*, JSCell*);
+ JS_EXPORT_PRIVATE static bool isValidCodeBlock(ExecState*, CodeBlock*);
+ JS_EXPORT_PRIVATE static CodeBlock* codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber);
+ JS_EXPORT_PRIVATE static void printCallFrame(CallFrame*, unsigned framesToSkip);
+ JS_EXPORT_PRIVATE static void printStack(CallFrame* topCallFrame, unsigned framesToSkip);
+ JS_EXPORT_PRIVATE static void printValue(JSValue);
+
private:
template <typename Functor> void iterate(const Functor& functor)
{