+
+#if ENABLE(MASM_PROBE)
+
+ struct CPUState {
+ #define DECLARE_REGISTER(_type, _regName) \
+ _type _regName;
+ FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+
+ static const char* registerName(RegisterID regID)
+ {
+ switch (regID) {
+ #define DECLARE_REGISTER(_type, _regName) \
+ case RegisterID::_regName: \
+ return #_regName;
+ FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ static const char* registerName(FPRegisterID regID)
+ {
+ switch (regID) {
+ #define DECLARE_REGISTER(_type, _regName) \
+ case FPRegisterID::_regName: \
+ return #_regName;
+ FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ void* registerValue(RegisterID regID)
+ {
+ switch (regID) {
+ #define DECLARE_REGISTER(_type, _regName) \
+ case RegisterID::_regName: \
+ return _regName;
+ FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ double registerValue(FPRegisterID regID)
+ {
+ switch (regID) {
+ #define DECLARE_REGISTER(_type, _regName) \
+ case FPRegisterID::_regName: \
+ return _regName;
+ FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ };
+
+ struct ProbeContext;
+ typedef void (*ProbeFunction)(struct ProbeContext*);
+
+ struct ProbeContext {
+ ProbeFunction probeFunction;
+ void* arg1;
+ void* arg2;
+ CPUState cpu;
+
+ void print(int indentation = 0)
+ {
+ #define INDENT MacroAssemblerType::printIndent(indentation)
+
+ INDENT, dataLogF("ProbeContext %p {\n", this);
+ indentation++;
+ {
+ INDENT, dataLogF("probeFunction: %p\n", probeFunction);
+ INDENT, dataLogF("arg1: %p %llu\n", arg1, reinterpret_cast<int64_t>(arg1));
+ INDENT, dataLogF("arg2: %p %llu\n", arg2, reinterpret_cast<int64_t>(arg2));
+ MacroAssemblerType::printCPU(cpu, indentation);
+ }
+ indentation--;
+ INDENT, dataLog("}\n");
+
+ #undef INDENT
+ }
+ };
+
+ static void printIndent(int indentation)
+ {
+ for (; indentation > 0; indentation--)
+ dataLog(" ");
+ }
+
+ static void printCPU(CPUState& cpu, int indentation = 0)
+ {
+ #define INDENT printIndent(indentation)
+
+ INDENT, dataLog("cpu: {\n");
+ MacroAssemblerType::printCPURegisters(cpu, indentation + 1);
+ INDENT, dataLog("}\n");
+
+ #undef INDENT
+ }
+
+ // This is a marker type only used with print(). See print() below for details.
+ struct AllRegisters { };
+
+ // Emits code which will print debugging info at runtime. The type of values that
+ // can be printed is encapsulated in the PrintArg struct below. Here are some
+ // examples:
+ //
+ // print("Hello world\n"); // Emits code to print the string.
+ //
+ // CodeBlock* cb = ...;
+ // print(cb); // Emits code to print the pointer value.
+ //
+ // RegisterID regID = ...;
+ // print(regID); // Emits code to print the register value (not the id).
+ //
+ // // Emits code to print all registers. Unlike other items, this prints
+ // // multiple lines as follows:
+ // // cpu {
+ // // eax: 0x123456789
+ // // ebx: 0x000000abc
+ // // ...
+ // // }
+ // print(AllRegisters());
+ //
+ // // Print multiple things at once. This incurs the probe overhead only once
+ // // to print all the items.
+ // print("cb:", cb, " regID:", regID, " cpu:\n", AllRegisters());
+
+ template<typename... Arguments>
+ void print(Arguments... args)
+ {
+ printInternal(static_cast<MacroAssemblerType*>(this), args...);
+ }
+
+ // This function will be called by printCPU() to print the contents of the
+ // target specific registers which are saved away in the CPUState struct.
+ // printCPURegisters() should make use of printIndentation() to print the
+ // registers with the appropriate amount of indentation.
+ //
+ // Note: printCPURegisters() should be implemented by the target specific
+ // MacroAssembler. This prototype is only provided here to document the
+ // interface.
+
+ static void printCPURegisters(CPUState&, int indentation = 0);
+
+ // This function will be called by print() to print the contents of a
+ // specific register (from the CPUState) in line with other items in the
+ // print stream. Hence, no indentation is needed.
+ //
+ // Note: printRegister() should be implemented by the target specific
+ // MacroAssembler. These prototypes are only provided here to document their
+ // interface.
+
+ static void printRegister(CPUState&, RegisterID);
+ static void printRegister(CPUState&, FPRegisterID);
+
+ // This function emits code to preserve the CPUState (e.g. registers),
+ // call a user supplied probe function, and restore the CPUState before
+ // continuing with other JIT generated code.
+ //
+ // The user supplied probe function will be called with a single pointer to
+ // a ProbeContext struct (defined above) which contains, among other things,
+ // the preserved CPUState. This allows the user probe function to inspect
+ // the CPUState at that point in the JIT generated code.
+ //
+ // If the user probe function alters the register values in the ProbeContext,
+ // the altered values will be loaded into the CPU registers when the probe
+ // returns.
+ //
+ // The ProbeContext is stack allocated and is only valid for the duration
+ // of the call to the user probe function.
+ //
+ // Note: probe() should be implemented by the target specific MacroAssembler.
+ // This prototype is only provided here to document the interface.
+
+ void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
+
+#endif // ENABLE(MASM_PROBE)
+
+ AssemblerType m_assembler;
+