Ignore:
Timestamp:
Nov 14, 2017, 1:16:24 PM (8 years ago)
Author:
[email protected]
Message:

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.

  1. 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.

  • JavaScriptCore.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:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp

    r217108 r224838  
    11/*
    2  * Copyright (C) 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "JSDollarVM.h"
    2828
     29#include "CodeBlock.h"
     30#include "FunctionCodeBlock.h"
    2931#include "JSCInlines.h"
     32#include "VMInspector.h"
     33#include <wtf/DataLog.h>
     34#include <wtf/ProcessID.h>
     35#include <wtf/StringPrintStream.h>
    3036
    3137namespace JSC {
     
    3339const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) };
    3440
     41void 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()
     49static 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()
     57static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
     58{
     59    return JSValue::encode(jsBoolean(false));
     60}
     61
     62class CallerFrameJITTypeFunctor {
     63public:
     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
     81private:
     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()
     88static 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()
     99static 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()
     110static 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()
     118static 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.
     126static 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
     146static 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))
     181static 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)
     194static 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)
     204static 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)
     214static 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()
     227static 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()
     237static 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))
     247static 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())
     261static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*)
     262{
     263    return JSValue::encode(jsNumber(getCurrentProcessID()));
     264}
     265
     266void 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
    35293} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.