Changeset 176233 in webkit


Ignore:
Timestamp:
Nov 17, 2014 2:03:04 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Add printing functionality in JITted code for debugging purposes.
<https://webkit.org/b/138660>

Reviewed by Geoffrey Garen.

Sometimes, for debugging, it'd be nice to be able to just print the
values of constants or registers used in JITted code, or even just
a string to log that certain pieces of JITted code have been executed.
Using the JIT probe mechanism, we can make this happen.

  • assembler/ARMv7Assembler.h:
  • assembler/AbstractMacroAssembler.h:

(JSC::AbstractMacroAssembler::CPUState::registerName):
(JSC::AbstractMacroAssembler::CPUState::registerValue):
(JSC::AbstractMacroAssembler::print):
(JSC::AbstractMacroAssembler::PrintArg::PrintArg):
(JSC::AbstractMacroAssembler::appendPrintArg):
(JSC::AbstractMacroAssembler::printInternal):
(JSC::AbstractMacroAssembler::printCallback):

  • assembler/MacroAssemblerARM.cpp:

(JSC::MacroAssemblerARM::printCPURegisters):
(JSC::MacroAssemblerARM::printRegister):

  • assembler/MacroAssemblerARM.h:
  • assembler/MacroAssemblerARMv7.cpp:

(JSC::MacroAssemblerARMv7::printCPURegisters):
(JSC::MacroAssemblerARMv7::printRegister):

  • assembler/MacroAssemblerARMv7.h:
  • assembler/MacroAssemblerX86Common.cpp:

(JSC::MacroAssemblerX86Common::printRegister):

  • assembler/MacroAssemblerX86Common.h:
Location:
trunk/Source/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r176219 r176233  
     12014-11-17  Mark Lam  <mark.lam@apple.com>
     2
     3        Add printing functionality in JITted code for debugging purposes.
     4        <https://webkit.org/b/138660>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Sometimes, for debugging, it'd be nice to be able to just print the
     9        values of constants or registers used in JITted code, or even just
     10        a string to log that certain pieces of JITted code have been executed.
     11        Using the JIT probe mechanism, we can make this happen.
     12
     13        * assembler/ARMv7Assembler.h:
     14        * assembler/AbstractMacroAssembler.h:
     15        (JSC::AbstractMacroAssembler::CPUState::registerName):
     16        (JSC::AbstractMacroAssembler::CPUState::registerValue):
     17        (JSC::AbstractMacroAssembler::print):
     18        (JSC::AbstractMacroAssembler::PrintArg::PrintArg):
     19        (JSC::AbstractMacroAssembler::appendPrintArg):
     20        (JSC::AbstractMacroAssembler::printInternal):
     21        (JSC::AbstractMacroAssembler::printCallback):
     22        * assembler/MacroAssemblerARM.cpp:
     23        (JSC::MacroAssemblerARM::printCPURegisters):
     24        (JSC::MacroAssemblerARM::printRegister):
     25        * assembler/MacroAssemblerARM.h:
     26        * assembler/MacroAssemblerARMv7.cpp:
     27        (JSC::MacroAssemblerARMv7::printCPURegisters):
     28        (JSC::MacroAssemblerARMv7::printRegister):
     29        * assembler/MacroAssemblerARMv7.h:
     30        * assembler/MacroAssemblerX86Common.cpp:
     31        (JSC::MacroAssemblerX86Common::printRegister):
     32        * assembler/MacroAssemblerX86Common.h:
     33
    1342014-11-17  Anders Carlsson  <andersca@apple.com>
    235
  • trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h

    r176151 r176233  
    206206    }
    207207
    208 } // namespace ARMRegister
     208} // namespace ARMRegisters
    209209
    210210class ARMv7Assembler;
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r176134 r176233  
    845845        FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
    846846        #undef DECLARE_REGISTER
     847
     848        static const char* registerName(RegisterID regID)
     849        {
     850            switch (regID) {
     851                #define DECLARE_REGISTER(_type, _regName) \
     852                case RegisterID::_regName: \
     853                    return #_regName;
     854                FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
     855                #undef DECLARE_REGISTER
     856            }
     857            RELEASE_ASSERT_NOT_REACHED();
     858        }
     859
     860        static const char* registerName(FPRegisterID regID)
     861        {
     862            switch (regID) {
     863                #define DECLARE_REGISTER(_type, _regName) \
     864                case FPRegisterID::_regName: \
     865                    return #_regName;
     866                FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
     867                #undef DECLARE_REGISTER
     868            }
     869            RELEASE_ASSERT_NOT_REACHED();
     870        }
     871
     872        void* registerValue(RegisterID regID)
     873        {
     874            switch (regID) {
     875                #define DECLARE_REGISTER(_type, _regName) \
     876                case RegisterID::_regName: \
     877                    return _regName;
     878                FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
     879                #undef DECLARE_REGISTER
     880            }
     881            RELEASE_ASSERT_NOT_REACHED();
     882        }
     883
     884        double registerValue(FPRegisterID regID)
     885        {
     886            switch (regID) {
     887                #define DECLARE_REGISTER(_type, _regName) \
     888                case FPRegisterID::_regName: \
     889                    return _regName;
     890                FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
     891                #undef DECLARE_REGISTER
     892            }
     893            RELEASE_ASSERT_NOT_REACHED();
     894        }
     895
    847896    };
    848897
     
    892941    }
    893942
     943    // This is a marker type only used with print(). See print() below for details.
     944    struct AllRegisters { };
     945
     946    // Emits code which will print debugging info at runtime. The type of values that
     947    // can be printed is encapsulated in the PrintArg struct below. Here are some
     948    // examples:
     949    //
     950    //      print("Hello world\n"); // Emits code to print the string.
     951    //
     952    //      CodeBlock* cb = ...;
     953    //      print(cb);              // Emits code to print the pointer value.
     954    //
     955    //      RegisterID regID = ...;
     956    //      print(regID);           // Emits code to print the register value (not the id).
     957    //
     958    //      // Emits code to print all registers.  Unlike other items, this prints
     959    //      // multiple lines as follows:
     960    //      //      cpu {
     961    //      //          eax: 0x123456789
     962    //      //          ebx: 0x000000abc
     963    //      //          ...
     964    //      //      }
     965    //      print(AllRegisters());
     966    //
     967    //      // Print multiple things at once. This incurs the probe overhead only once
     968    //      // to print all the items.
     969    //      print("cb:", cb, " regID:", regID, " cpu:\n", AllRegisters());
     970
     971    template<typename... Arguments>
     972    void print(Arguments... args)
     973    {
     974        printInternal(static_cast<MacroAssemblerType*>(this), args...);
     975    }
    894976
    895977    // This function will be called by printCPU() to print the contents of the
    896     // target specific registers which are saved away in the CPUInfo struct.
     978    // target specific registers which are saved away in the CPUState struct.
    897979    // printCPURegisters() should make use of printIndentation() to print the
    898980    // registers with the appropriate amount of indentation.
     
    904986    static void printCPURegisters(CPUState&, int indentation = 0);
    905987
    906     // This function emits code to preserve the CPUInfo (e.g. registers),
    907     // call a user supplied probe function, and restore the CPUInfo before
     988    // This function will be called by print() to print the contents of a
     989    // specific register (from the CPUState) in line with other items in the
     990    // print stream. Hence, no indentation is needed.
     991    //
     992    // Note: printRegister() should be implemented by the target specific
     993    // MacroAssembler. These prototypes are only provided here to document their
     994    // interface.
     995
     996    static void printRegister(CPUState&, RegisterID);
     997    static void printRegister(CPUState&, FPRegisterID);
     998
     999    // This function emits code to preserve the CPUState (e.g. registers),
     1000    // call a user supplied probe function, and restore the CPUState before
    9081001    // continuing with other JIT generated code.
    9091002    //
    9101003    // The user supplied probe function will be called with a single pointer to
    9111004    // a ProbeContext struct (defined above) which contains, among other things,
    912     // the preserved CPUInfo. This allows the user probe function to inspect
    913     // the CPUInfo at that point in the JIT generated code.
     1005    // the preserved CPUState. This allows the user probe function to inspect
     1006    // the CPUState at that point in the JIT generated code.
    9141007    //
    9151008    // If the user probe function alters the register values in the ProbeContext,
     
    10861179        AssemblerType::replaceWithAddressComputation(label.dataLocation());
    10871180    }
    1088 };
     1181
     1182private:
     1183
     1184#if ENABLE(MASM_PROBE)
     1185
     1186    struct PrintArg {
     1187   
     1188        enum class Type {
     1189            AllRegisters,
     1190            RegisterID,
     1191            FPRegisterID,
     1192            ConstCharPtr,
     1193            ConstVoidPtr,
     1194            IntptrValue,
     1195            UintptrValue,
     1196        };
     1197
     1198        PrintArg(AllRegisters&)
     1199            : type(Type::AllRegisters)
     1200        {
     1201        }
     1202
     1203        PrintArg(RegisterID regID)
     1204            : type(Type::RegisterID)
     1205        {
     1206            u.gpRegisterID = regID;
     1207        }
     1208
     1209        PrintArg(FPRegisterID regID)
     1210            : type(Type::FPRegisterID)
     1211        {
     1212            u.fpRegisterID = regID;
     1213        }
     1214
     1215        PrintArg(const char* ptr)
     1216            : type(Type::ConstCharPtr)
     1217        {
     1218            u.constCharPtr = ptr;
     1219        }
     1220
     1221        PrintArg(const void* ptr)
     1222            : type(Type::ConstVoidPtr)
     1223        {
     1224            u.constVoidPtr = ptr;
     1225        }
     1226
     1227        PrintArg(int value)
     1228            : type(Type::IntptrValue)
     1229        {
     1230            u.intptrValue = value;
     1231        }
     1232
     1233        PrintArg(unsigned value)
     1234            : type(Type::UintptrValue)
     1235        {
     1236            u.intptrValue = value;
     1237        }
     1238
     1239        PrintArg(intptr_t value)
     1240            : type(Type::IntptrValue)
     1241        {
     1242            u.intptrValue = value;
     1243        }
     1244
     1245        PrintArg(uintptr_t value)
     1246            : type(Type::UintptrValue)
     1247        {
     1248            u.uintptrValue = value;
     1249        }
     1250
     1251        Type type;
     1252        union {
     1253            RegisterID gpRegisterID;
     1254            FPRegisterID fpRegisterID;
     1255            const char* constCharPtr;
     1256            const void* constVoidPtr;
     1257            intptr_t intptrValue;
     1258            uintptr_t uintptrValue;
     1259        } u;
     1260    };
     1261
     1262    typedef Vector<PrintArg> PrintArgsList;
     1263
     1264    template<typename FirstArg, typename... Arguments>
     1265    static void appendPrintArg(PrintArgsList* argsList, FirstArg& firstArg, Arguments... otherArgs)
     1266    {
     1267        argsList->append(PrintArg(firstArg));
     1268        appendPrintArg(argsList, otherArgs...);
     1269    }
     1270
     1271    static void appendPrintArg(PrintArgsList*) { }
     1272
     1273   
     1274    template<typename... Arguments>
     1275    static void printInternal(MacroAssemblerType* masm, Arguments... args)
     1276    {
     1277        auto argsList = std::make_unique<PrintArgsList>();
     1278        appendPrintArg(argsList.get(), args...);
     1279        masm->probe(printCallback, argsList.release());
     1280    }
     1281
     1282    static void printCallback(ProbeContext* context)
     1283    {
     1284        typedef PrintArg Arg;
     1285        PrintArgsList& argsList =
     1286            *reinterpret_cast<PrintArgsList*>(context->arg1);
     1287        for (size_t i = 0; i < argsList.size(); i++) {
     1288            auto& arg = argsList[i];
     1289            switch (arg.type) {
     1290            case Arg::Type::AllRegisters:
     1291                MacroAssemblerType::printCPU(context->cpu);
     1292                break;
     1293            case Arg::Type::RegisterID:
     1294                MacroAssemblerType::printRegister(context->cpu, arg.u.gpRegisterID);
     1295                break;
     1296            case Arg::Type::FPRegisterID:
     1297                MacroAssemblerType::printRegister(context->cpu, arg.u.fpRegisterID);
     1298                break;
     1299            case Arg::Type::ConstCharPtr:
     1300                dataLog(arg.u.constCharPtr);
     1301                break;
     1302            case Arg::Type::ConstVoidPtr:
     1303                dataLogF("%p", arg.u.constVoidPtr);
     1304                break;
     1305            case Arg::Type::IntptrValue:
     1306                dataLog(arg.u.intptrValue);
     1307                break;
     1308            case Arg::Type::UintptrValue:
     1309                dataLog(arg.u.uintptrValue);
     1310                break;
     1311            }
     1312        }
     1313    }
     1314
     1315#endif // ENABLE(MASM_PROBE)
     1316
     1317}; // class AbstractMacroAssembler
    10891318
    10901319} // namespace JSC
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp

    r176134 r176233  
    102102void MacroAssemblerARM::printCPURegisters(CPUState& cpu, int indentation)
    103103{
    104     #define DUMP_GPREGISTER(_type, _regName) { \
     104    #define PRINT_GPREGISTER(_type, _regName) { \
    105105        int32_t value = reinterpret_cast<int32_t>(cpu._regName); \
    106106        INDENT, dataLogF("%5s: 0x%08x  %d\n", #_regName, value, value) ; \
    107107    }
    108     FOR_EACH_CPU_GPREGISTER(DUMP_GPREGISTER)
    109     FOR_EACH_CPU_SPECIAL_REGISTER(DUMP_GPREGISTER)
    110     #undef DUMP_GPREGISTER
     108    FOR_EACH_CPU_GPREGISTER(PRINT_GPREGISTER)
     109    FOR_EACH_CPU_SPECIAL_REGISTER(PRINT_GPREGISTER)
     110    #undef PRINT_GPREGISTER
    111111
    112     #define DUMP_FPREGISTER(_type, _regName) { \
     112    #define PRINT_FPREGISTER(_type, _regName) { \
    113113        uint64_t* u = reinterpret_cast<uint64_t*>(&cpu._regName); \
    114114        double* d = reinterpret_cast<double*>(&cpu._regName); \
    115115        INDENT, dataLogF("%5s: 0x%016llx  %.13g\n", #_regName, *u, *d); \
    116116    }
    117     FOR_EACH_CPU_FPREGISTER(DUMP_FPREGISTER)
    118     #undef DUMP_FPREGISTER
     117    FOR_EACH_CPU_FPREGISTER(PRINT_FPREGISTER)
     118    #undef PRINT_FPREGISTER
    119119}
    120120
    121121#undef INDENT
     122
     123void MacroAssemblerARM::printRegister(MacroAssemblerARM::CPUState& cpu, RegisterID regID)
     124{
     125    const char* name = CPUState::registerName(regID);
     126    union {
     127        void* voidPtr;
     128        intptr_t intptrValue;
     129    } u;
     130    u.voidPtr = cpu.registerValue(regID);
     131    dataLogF("%s:<%p %ld>", name, u.voidPtr, u.intptrValue);
     132}
     133
     134void MacroAssemblerARM::printRegister(MacroAssemblerARM::CPUState& cpu, FPRegisterID regID)
     135{
     136    const char* name = CPUState::registerName(regID);
     137    union {
     138        double doubleValue;
     139        uint64_t uint64Value;
     140    } u;
     141    u.doubleValue = cpu.registerValue(regID);
     142    dataLogF("%s:<0x%016llx %.13g>", name, u.uint64Value, u.doubleValue);
     143}
    122144
    123145extern "C" void ctiMasmProbeTrampoline();
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h

    r176134 r176233  
    14371437    // AbstractMacroAssembler.h.
    14381438    static void printCPURegisters(CPUState&, int indentation = 0);
     1439    static void printRegister(CPUState&, RegisterID);
     1440    static void printRegister(CPUState&, FPRegisterID);
    14391441    void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
    14401442#endif // ENABLE(MASM_PROBE)
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp

    r176134 r176233  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3737void MacroAssemblerARMv7::printCPURegisters(CPUState& cpu, int indentation)
    3838{
    39     #define DUMP_GPREGISTER(_type, _regName) { \
     39    #define PRINT_GPREGISTER(_type, _regName) { \
    4040        int32_t value = reinterpret_cast<int32_t>(cpu._regName); \
    4141        INDENT, dataLogF("%5s: 0x%08x  %d\n", #_regName, value, value) ; \
    4242    }
    43     FOR_EACH_CPU_GPREGISTER(DUMP_GPREGISTER)
    44     FOR_EACH_CPU_SPECIAL_REGISTER(DUMP_GPREGISTER)
    45     #undef DUMP_GPREGISTER
     43    FOR_EACH_CPU_GPREGISTER(PRINT_GPREGISTER)
     44    FOR_EACH_CPU_SPECIAL_REGISTER(PRINT_GPREGISTER)
     45    #undef PRINT_GPREGISTER
    4646
    47     #define DUMP_FPREGISTER(_type, _regName) { \
     47    #define PRINT_FPREGISTER(_type, _regName) { \
    4848        uint64_t* u = reinterpret_cast<uint64_t*>(&cpu._regName); \
    4949        double* d = reinterpret_cast<double*>(&cpu._regName); \
    5050        INDENT, dataLogF("%5s: 0x%016llx  %.13g\n", #_regName, *u, *d); \
    5151    }
    52     FOR_EACH_CPU_FPREGISTER(DUMP_FPREGISTER)
    53     #undef DUMP_FPREGISTER
     52    FOR_EACH_CPU_FPREGISTER(PRINT_FPREGISTER)
     53    #undef PRINT_FPREGISTER
    5454}
    5555
    5656#undef INDENT
     57
     58void MacroAssemblerARMv7::printRegister(MacroAssemblerARMv7::CPUState& cpu, RegisterID regID)
     59{
     60    const char* name = CPUState::registerName(regID);
     61    union {
     62        void* voidPtr;
     63        intptr_t intptrValue;
     64    } u;
     65    u.voidPtr = cpu.registerValue(regID);
     66    dataLogF("%s:<%p %ld>", name, u.voidPtr, u.intptrValue);
     67}
     68
     69void MacroAssemblerARMv7::printRegister(MacroAssemblerARMv7::CPUState& cpu, FPRegisterID regID)
     70{
     71    const char* name = CPUState::registerName(regID);
     72    union {
     73        double doubleValue;
     74        uint64_t uint64Value;
     75    } u;
     76    u.doubleValue = cpu.registerValue(regID);
     77    dataLogF("%s:<0x%016llx %.13g>", name, u.uint64Value, u.doubleValue);
     78}
    5779
    5880extern "C" void ctiMasmProbeTrampoline();
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r176134 r176233  
    19061906    // AbstractMacroAssembler.h.
    19071907    static void printCPURegisters(CPUState&, int indentation = 0);
     1908    static void printRegister(CPUState&, RegisterID);
     1909    static void printRegister(CPUState&, FPRegisterID);
    19081910    void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
    19091911#endif // ENABLE(MASM_PROBE)
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp

    r176134 r176233  
    6262
    6363#undef INDENT
     64
     65void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState& cpu, RegisterID regID)
     66{
     67    const char* name = CPUState::registerName(regID);
     68    union {
     69        void* voidPtr;
     70        intptr_t intptrValue;
     71    } u;
     72    u.voidPtr = cpu.registerValue(regID);
     73    dataLogF("%s:<%p %ld>", name, u.voidPtr, u.intptrValue);
     74}
     75
     76void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState& cpu, FPRegisterID regID)
     77{
     78    const char* name = CPUState::registerName(regID);
     79    union {
     80        double doubleValue;
     81        uint64_t uint64Value;
     82    } u;
     83    u.doubleValue = cpu.registerValue(regID);
     84    dataLogF("%s:<0x%016llx %.13g>", name, u.uint64Value, u.doubleValue);
     85}
    6486
    6587extern "C" void ctiMasmProbeTrampoline();
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r176134 r176233  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    14741474    // AbstractMacroAssembler.h.
    14751475    static void printCPURegisters(CPUState&, int indentation = 0);
     1476    static void printRegister(CPUState&, RegisterID);
     1477    static void printRegister(CPUState&, FPRegisterID);
    14761478    void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
    14771479#endif // ENABLE(MASM_PROBE)
Note: See TracChangeset for help on using the changeset viewer.