Changeset 224838 in webkit for trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp
- Timestamp:
- Nov 14, 2017, 1:16:24 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp
r217108 r224838 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "JSDollarVM.h" 28 28 29 #include "CodeBlock.h" 30 #include "FunctionCodeBlock.h" 29 31 #include "JSCInlines.h" 32 #include "VMInspector.h" 33 #include <wtf/DataLog.h> 34 #include <wtf/ProcessID.h> 35 #include <wtf/StringPrintStream.h> 30 36 31 37 namespace JSC { … … 33 39 const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) }; 34 40 41 void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments) 42 { 43 Identifier identifier = Identifier::fromString(&vm, name); 44 putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function)); 45 } 46 47 // Triggers a crash immediately. 48 // Usage: $vm.crash() 49 static EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*) 50 { 51 CRASH(); 52 return JSValue::encode(jsUndefined()); 53 } 54 55 // Returns true if the current frame is a DFG frame. 56 // Usage: isDFG = $vm.dfgTrue() 57 static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*) 58 { 59 return JSValue::encode(jsBoolean(false)); 60 } 61 62 class CallerFrameJITTypeFunctor { 63 public: 64 CallerFrameJITTypeFunctor() 65 : m_currentFrame(0) 66 , m_jitType(JITCode::None) 67 { 68 } 69 70 StackVisitor::Status operator()(StackVisitor& visitor) const 71 { 72 if (m_currentFrame++ > 1) { 73 m_jitType = visitor->codeBlock()->jitType(); 74 return StackVisitor::Done; 75 } 76 return StackVisitor::Continue; 77 } 78 79 JITCode::JITType jitType() { return m_jitType; } 80 81 private: 82 mutable unsigned m_currentFrame; 83 mutable JITCode::JITType m_jitType; 84 }; 85 86 // Returns true if the current frame is a LLInt frame. 87 // Usage: isLLInt = $vm.llintTrue() 88 static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec) 89 { 90 if (!exec) 91 return JSValue::encode(jsUndefined()); 92 CallerFrameJITTypeFunctor functor; 93 exec->iterate(functor); 94 return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk)); 95 } 96 97 // Returns true if the current frame is a baseline JIT frame. 98 // Usage: isBaselineJIT = $vm.jitTrue() 99 static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec) 100 { 101 if (!exec) 102 return JSValue::encode(jsUndefined()); 103 CallerFrameJITTypeFunctor functor; 104 exec->iterate(functor); 105 return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT)); 106 } 107 108 // Runs a full GC synchronously. 109 // Usage: $vm.gc() 110 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec) 111 { 112 VMInspector::gc(exec); 113 return JSValue::encode(jsUndefined()); 114 } 115 116 // Runs the edenGC synchronously. 117 // Usage: $vm.edenGC() 118 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec) 119 { 120 VMInspector::edenGC(exec); 121 return JSValue::encode(jsUndefined()); 122 } 123 124 // Gets a token for the CodeBlock for a specified frame index. 125 // Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top frame. 126 static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(ExecState* exec) 127 { 128 if (exec->argumentCount() < 1) 129 return JSValue::encode(jsUndefined()); 130 131 JSValue value = exec->uncheckedArgument(0); 132 if (!value.isUInt32()) 133 return JSValue::encode(jsUndefined()); 134 135 // We need to inc the frame number because the caller would consider 136 // its own frame as frame 0. Hence, we need discount the frame for this 137 // function. 138 unsigned frameNumber = value.asUInt32() + 1; 139 CodeBlock* codeBlock = VMInspector::codeBlockForFrame(exec, frameNumber); 140 // Though CodeBlock is a JSCell, it is not safe to return it directly back to JS code 141 // as it is an internal type that the JS code cannot handle. Hence, we first encode the 142 // CodeBlock* as a double token (which is safe for JS code to handle) before returning it. 143 return JSValue::encode(JSValue(bitwise_cast<double>(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(codeBlock))))); 144 } 145 146 static CodeBlock* codeBlockFromArg(ExecState* exec) 147 { 148 VM& vm = exec->vm(); 149 if (exec->argumentCount() < 1) 150 return nullptr; 151 152 JSValue value = exec->uncheckedArgument(0); 153 CodeBlock* candidateCodeBlock = nullptr; 154 if (value.isCell()) { 155 JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell()); 156 if (func) { 157 if (func->isHostFunction()) 158 candidateCodeBlock = nullptr; 159 else 160 candidateCodeBlock = func->jsExecutable()->eitherCodeBlock(); 161 } 162 } else if (value.isDouble()) { 163 // If the value is a double, it may be an encoded CodeBlock* that came from 164 // $vm.codeBlockForFrame(). We'll treat it as a candidate codeBlock and check if it's 165 // valid below before using. 166 candidateCodeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble())); 167 } 168 169 if (candidateCodeBlock && VMInspector::isValidCodeBlock(exec, candidateCodeBlock)) 170 return candidateCodeBlock; 171 172 if (candidateCodeBlock) 173 dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n"); 174 else 175 dataLog("Invalid codeBlock: ", value, "\n"); 176 return nullptr; 177 } 178 179 // Usage: print("codeblock = " + $vm.codeBlockFor(functionObj)) 180 // Usage: print("codeblock = " + $vm.codeBlockFor(codeBlockToken)) 181 static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(ExecState* exec) 182 { 183 CodeBlock* codeBlock = codeBlockFromArg(exec); 184 WTF::StringPrintStream stream; 185 if (codeBlock) { 186 stream.print(*codeBlock); 187 return JSValue::encode(jsString(exec, stream.toString())); 188 } 189 return JSValue::encode(jsUndefined()); 190 } 191 192 // Usage: $vm.printSourceFor(functionObj) 193 // Usage: $vm.printSourceFor(codeBlockToken) 194 static EncodedJSValue JSC_HOST_CALL functionPrintSourceFor(ExecState* exec) 195 { 196 CodeBlock* codeBlock = codeBlockFromArg(exec); 197 if (codeBlock) 198 codeBlock->dumpSource(); 199 return JSValue::encode(jsUndefined()); 200 } 201 202 // Usage: $vm.printBytecodeFor(functionObj) 203 // Usage: $vm.printBytecode(codeBlockToken) 204 static EncodedJSValue JSC_HOST_CALL functionPrintBytecodeFor(ExecState* exec) 205 { 206 CodeBlock* codeBlock = codeBlockFromArg(exec); 207 if (codeBlock) 208 codeBlock->dumpBytecode(); 209 return JSValue::encode(jsUndefined()); 210 } 211 212 // Prints a series of comma separate strings without inserting a newline. 213 // Usage: $vm.print(str1, str2, str3) 214 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) 215 { 216 auto scope = DECLARE_THROW_SCOPE(exec->vm()); 217 for (unsigned i = 0; i < exec->argumentCount(); ++i) { 218 String argStr = exec->uncheckedArgument(i).toWTFString(exec); 219 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 220 dataLog(argStr); 221 } 222 return JSValue::encode(jsUndefined()); 223 } 224 225 // Prints the current CallFrame. 226 // Usage: $vm.printCallFrame() 227 static EncodedJSValue JSC_HOST_CALL functionPrintCallFrame(ExecState* exec) 228 { 229 // When the callers call this function, they are expecting to print their 230 // own frame. So skip 1 for this frame. 231 VMInspector::printCallFrame(exec, 1); 232 return JSValue::encode(jsUndefined()); 233 } 234 235 // Prints the JS stack. 236 // Usage: $vm.printStack() 237 static EncodedJSValue JSC_HOST_CALL functionPrintStack(ExecState* exec) 238 { 239 // When the callers call this function, they are expecting to print the 240 // stack starting their own frame. So skip 1 for this frame. 241 VMInspector::printStack(exec, 1); 242 return JSValue::encode(jsUndefined()); 243 } 244 245 // Gets the dataLog dump of a given JS value as a string. 246 // Usage: print("value = " + $vm.value(jsValue)) 247 static EncodedJSValue JSC_HOST_CALL functionValue(ExecState* exec) 248 { 249 WTF::StringPrintStream stream; 250 for (unsigned i = 0; i < exec->argumentCount(); ++i) { 251 if (i) 252 stream.print(", "); 253 stream.print(exec->uncheckedArgument(i)); 254 } 255 256 return JSValue::encode(jsString(exec, stream.toString())); 257 } 258 259 // Gets the pid of the current process. 260 // Usage: print("pid = " + $vm.getpid()) 261 static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*) 262 { 263 return JSValue::encode(jsNumber(getCurrentProcessID())); 264 } 265 266 void JSDollarVM::finishCreation(VM& vm, JSGlobalObject* globalObject) 267 { 268 Base::finishCreation(vm); 269 270 addFunction(vm, globalObject, "crash", functionCrash, 0); 271 272 putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum)); 273 274 addFunction(vm, globalObject, "llintTrue", functionLLintTrue, 0); 275 addFunction(vm, globalObject, "jitTrue", functionJITTrue, 0); 276 277 addFunction(vm, globalObject, "gc", functionGC, 0); 278 addFunction(vm, globalObject, "edenGC", functionEdenGC, 0); 279 280 addFunction(vm, globalObject, "codeBlockFor", functionCodeBlockFor, 1); 281 addFunction(vm, globalObject, "codeBlockForFrame", functionCodeBlockForFrame, 1); 282 addFunction(vm, globalObject, "printSourceFor", functionPrintSourceFor, 1); 283 addFunction(vm, globalObject, "printBytecodeFor", functionPrintBytecodeFor, 1); 284 285 addFunction(vm, globalObject, "print", functionPrint, 1); 286 addFunction(vm, globalObject, "printCallFrame", functionPrintCallFrame, 0); 287 addFunction(vm, globalObject, "printStack", functionPrintStack, 0); 288 289 addFunction(vm, globalObject, "value", functionValue, 1); 290 addFunction(vm, globalObject, "getpid", functionGetPID, 0); 291 } 292 35 293 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.