summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
commit881da28418d380042aa95a97f0cbd42560a64f7c (patch)
treea794dff3274695e99c651902dde93d934ea7a5af /Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h
parent7e104c57a70fdf551bb3d22a5d637cdcbc69dbea (diff)
parent0fcedcd17cc00d3dd44c718b3cb36c1033319671 (diff)
downloadqtwebkit-881da28418d380042aa95a97f0cbd42560a64f7c.tar.gz
Merge 'wip/next' into dev
Change-Id: Iff9ee5e23bb326c4371ec8ed81d56f2f05d680e9
Diffstat (limited to 'Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h')
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h305
1 files changed, 305 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h b/Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h
new file mode 100644
index 000000000..e25a6ea98
--- /dev/null
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerPrinter.h
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+#ifndef MacroAssemblerPrinter_h
+#define MacroAssemblerPrinter_h
+
+#if ENABLE(MASM_PROBE)
+
+#include "MacroAssembler.h"
+
+namespace JSC {
+
+// What is MacroAssembler::print()?
+// ===============================
+// The MacroAsssembler::print() makes it easy to add print logging
+// from JIT compiled code, and can be used to print all types of values
+// at runtime e.g. CPU register values being operated on by the compiled
+// code.
+//
+// print() is built on top of MacroAsssembler::probe(), and hence
+// inserting logging in JIT compiled code will not perturb register values.
+// The only register value that is perturbed is the PC (program counter)
+// since there is now more compiled code to do the printing.
+//
+// How to use the MacroAssembler print()?
+// =====================================
+// 1. #include "MacroAssemblerPrinter.h" in the JIT file where you want to use print().
+//
+// 2. Add print() calls like these in your JIT code:
+//
+// jit.print("Hello world\n"); // Emits code to print the string.
+//
+// CodeBlock* cb = ...;
+// jit.print(cb, "\n"); // Emits code to print the pointer value.
+//
+// RegisterID regID = ...;
+// jit.print(regID, "\n"); // 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
+// // ...
+// // }
+// jit.print(AllRegisters());
+//
+// jit.print(MemWord<uint8_t>(regID), "\n"); // Emits code to print a byte pointed to by the register.
+// jit.print(MemWord<uint32_t>(regID), "\n"); // Emits code to print a 32-bit word pointed to by the register.
+//
+// jit.print(MemWord<uint8_t>(Address(regID, 23), "\n"); // Emits code to print a byte at the address.
+// jit.print(MemWord<intptr_t>(AbsoluteAddress(&cb), "\n"); // Emits code to print an intptr_t sized word at the address.
+//
+// jit.print(Memory(reg, 100), "\n"); // Emits code to print a 100 bytes at the address pointed by the register.
+// jit.print(Memory(Address(reg, 4), 100), "\n"); // Emits code to print a 100 bytes at the address.
+//
+// // Print multiple things at once. This incurs the probe overhead only once
+// // to print all the items.
+// jit.print("cb:", cb, " regID:", regID, " cpu:\n", AllRegisters());
+//
+// The type of values that can be printed is encapsulated in the PrintArg struct below.
+//
+// Note: print() does not automatically insert a '\n' at the end of the line.
+// If you want a '\n', you'll have to add it explicitly (as in the examples above).
+
+
+// This is a marker type only used with MacroAssemblerPrinter::print().
+// See MacroAssemblerPrinter::print() below for details.
+struct AllRegisters { };
+struct PCRegister { };
+
+struct Memory {
+ using Address = MacroAssembler::Address;
+ using AbsoluteAddress = MacroAssembler::AbsoluteAddress;
+ using RegisterID = MacroAssembler::RegisterID;
+
+ enum class AddressType {
+ Address,
+ AbsoluteAddress,
+ };
+
+ enum DumpStyle {
+ SingleWordDump,
+ GenericDump,
+ };
+
+ Memory(RegisterID& reg, size_t bytes, DumpStyle style = GenericDump)
+ : addressType(AddressType::Address)
+ , dumpStyle(style)
+ , numBytes(bytes)
+ {
+ u.address = Address(reg, 0);
+ }
+
+ Memory(const Address& address, size_t bytes, DumpStyle style = GenericDump)
+ : addressType(AddressType::Address)
+ , dumpStyle(style)
+ , numBytes(bytes)
+ {
+ u.address = address;
+ }
+
+ Memory(const AbsoluteAddress& address, size_t bytes, DumpStyle style = GenericDump)
+ : addressType(AddressType::AbsoluteAddress)
+ , dumpStyle(style)
+ , numBytes(bytes)
+ {
+ u.absoluteAddress = address;
+ }
+
+ AddressType addressType;
+ DumpStyle dumpStyle;
+ size_t numBytes;
+ union UnionedAddress {
+ UnionedAddress() { }
+
+ Address address;
+ AbsoluteAddress absoluteAddress;
+ } u;
+};
+
+template <typename IntType>
+struct MemWord : public Memory {
+ MemWord(RegisterID& reg)
+ : Memory(reg, sizeof(IntType), Memory::SingleWordDump)
+ { }
+
+ MemWord(const Address& address)
+ : Memory(address, sizeof(IntType), Memory::SingleWordDump)
+ { }
+
+ MemWord(const AbsoluteAddress& address)
+ : Memory(address, sizeof(IntType), Memory::SingleWordDump)
+ { }
+};
+
+
+class MacroAssemblerPrinter {
+ using CPUState = MacroAssembler::CPUState;
+ using ProbeContext = MacroAssembler::ProbeContext;
+ using RegisterID = MacroAssembler::RegisterID;
+ using FPRegisterID = MacroAssembler::FPRegisterID;
+
+public:
+ template<typename... Arguments>
+ static void print(MacroAssembler* masm, Arguments... args)
+ {
+ auto argsList = std::make_unique<PrintArgsList>();
+ appendPrintArg(argsList.get(), args...);
+ masm->probe(printCallback, argsList.release(), 0);
+ }
+
+private:
+ struct PrintArg {
+
+ enum class Type {
+ AllRegisters,
+ PCRegister,
+ RegisterID,
+ FPRegisterID,
+ Memory,
+ ConstCharPtr,
+ ConstVoidPtr,
+ IntptrValue,
+ UintptrValue,
+ };
+
+ PrintArg(AllRegisters&)
+ : type(Type::AllRegisters)
+ {
+ }
+
+ PrintArg(PCRegister&)
+ : type(Type::PCRegister)
+ {
+ }
+
+ PrintArg(RegisterID regID)
+ : type(Type::RegisterID)
+ {
+ u.gpRegisterID = regID;
+ }
+
+ PrintArg(FPRegisterID regID)
+ : type(Type::FPRegisterID)
+ {
+ u.fpRegisterID = regID;
+ }
+
+ PrintArg(const Memory& memory)
+ : type(Type::Memory)
+ {
+ u.memory = memory;
+ }
+
+ PrintArg(const char* ptr)
+ : type(Type::ConstCharPtr)
+ {
+ u.constCharPtr = ptr;
+ }
+
+ PrintArg(const void* ptr)
+ : type(Type::ConstVoidPtr)
+ {
+ u.constVoidPtr = ptr;
+ }
+
+ PrintArg(int value)
+ : type(Type::IntptrValue)
+ {
+ u.intptrValue = value;
+ }
+
+ PrintArg(unsigned value)
+ : type(Type::UintptrValue)
+ {
+ u.intptrValue = value;
+ }
+
+ PrintArg(intptr_t value)
+ : type(Type::IntptrValue)
+ {
+ u.intptrValue = value;
+ }
+
+ PrintArg(uintptr_t value)
+ : type(Type::UintptrValue)
+ {
+ u.uintptrValue = value;
+ }
+
+ Type type;
+ union Value {
+ Value() { }
+
+ RegisterID gpRegisterID;
+ FPRegisterID fpRegisterID;
+ Memory memory;
+ const char* constCharPtr;
+ const void* constVoidPtr;
+ intptr_t intptrValue;
+ uintptr_t uintptrValue;
+ } u;
+ };
+
+ typedef Vector<PrintArg> PrintArgsList;
+
+ template<typename FirstArg, typename... Arguments>
+ static void appendPrintArg(PrintArgsList* argsList, FirstArg& firstArg, Arguments... otherArgs)
+ {
+ argsList->append(PrintArg(firstArg));
+ appendPrintArg(argsList, otherArgs...);
+ }
+
+ static void appendPrintArg(PrintArgsList*) { }
+
+private:
+ static void printCallback(ProbeContext*);
+};
+
+template<typename... Arguments>
+void MacroAssembler::print(Arguments... args)
+{
+ MacroAssemblerPrinter::print(this, args...);
+}
+
+
+// These printers will print a block of information. That block may be
+// indented with the specified indentation.
+void printCPU(MacroAssembler::CPUState&, int indentation = 0);
+void printCPURegisters(MacroAssembler::CPUState&, int indentation = 0);
+
+// These printers will print the specified information in line in the
+// print stream. Hence, no indentation will be applied.
+void printRegister(MacroAssembler::CPUState&, MacroAssembler::RegisterID);
+void printRegister(MacroAssembler::CPUState&, MacroAssembler::FPRegisterID);
+void printMemory(MacroAssembler::CPUState&, const Memory&);
+
+} // namespace JSC
+
+#endif // ENABLE(MASM_PROBE)
+
+#endif // MacroAssemblerPrinter_h