fourthTier: Implement a probe mechanism for JIT generated code.
https://bugs.webkit.org/show_bug.cgi?id=115705.

Reviewed by Geoffrey Garen.

The probe is in the form of a MacroAssembler pseudo instruction.
It takes 3 arguments: a ProbeFunction, and 2 void* args.

When inserted into the JIT at some code generation site, the probe
pseudo "instruction" will emit a minimal amount of code to save the
stack pointer, 1 (or more) scratch register(s), and the probe
arguments into a ProbeContext record on the stack. The emitted code
will then call a probe trampoline to do the rest of the work, which
consists of:
1. saving the remaining registers into the ProbeContext.
2. calling the ProbeFunction, and passing it the ProbeContext pointer.
3. restoring the registers from the ProbeContext after the ProbeFunction
   returns, and then returning to the JIT generated code.

The ProbeContext is stack allocated and is only valid for the duration
that the ProbeFunction is executing.

If the user supplied ProbeFunction alters the register values in the
ProbeContext, the new values will be installed into the registers upon
returning from the probe. This can be useful for some debugging or
testing purposes.

The probe mechanism is built conditional on USE(MASM_PROBE) which is
defined in config.h. USE(MASM_PROBE) will off by default.

This changeset only implements the probe mechanism for X86 and X86_64.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/MacroAssembler.h:
(MacroAssembler):
(JSC::MacroAssembler::shouldBlind):
(JSC::MacroAssembler::store32):
* assembler/MacroAssemblerX86.h:
(MacroAssemblerX86):
(JSC::MacroAssemblerX86::trustedImm32FromPtr):
(JSC::MacroAssemblerX86::probe):
* assembler/MacroAssemblerX86Common.cpp: Added.
(JSC::MacroAssemblerX86Common::ProbeContext::dumpCPURegisters):
- CPU specific register dumper called by ProbeContext::dump().
(JSC::MacroAssemblerX86Common::ProbeContext::dump):
- Prints the ProbeContext to the DataLog.
* assembler/MacroAssemblerX86Common.h:
(MacroAssemblerX86Common):
(CPUState): Added.
(ProbeContext): Added.
* assembler/MacroAssemblerX86_64.h:
(MacroAssemblerX86_64):
(JSC::MacroAssemblerX86_64::trustedImm64FromPtr):
(JSC::MacroAssemblerX86_64::probe):
* assembler/X86Assembler.h:
* config.h: Added WTF_USE_MASM_PROBE flag.
* jit/JITStubs.cpp:
* jit/JITStubs.h:
* jit/JITStubsX86.h:
* jit/JITStubsX86Common.h: Added.
* jit/JITStubsX86_64.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153162 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
index 27a030e..c8235e7 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
@@ -30,6 +30,10 @@
 
 #include "MacroAssemblerX86Common.h"
 
+#if USE(MASM_PROBE)
+#include <wtf/StdLibExtras.h>
+#endif
+
 namespace JSC {
 
 class MacroAssemblerX86 : public MacroAssemblerX86Common {
@@ -287,6 +291,26 @@
         X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), 0, address.base);
     }
 
+#if USE(MASM_PROBE)
+    // 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.
+
+    void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
+#endif // USE(MASM_PROBE)
+
 private:
     friend class LinkBuffer;
     friend class RepatchBuffer;
@@ -305,8 +329,81 @@
     {
         X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
     }
+
+#if USE(MASM_PROBE)
+    inline TrustedImm32 trustedImm32FromPtr(void* ptr)
+    {
+        return TrustedImm32(TrustedImmPtr(ptr));
+    }
+
+    inline TrustedImm32 trustedImm32FromPtr(ProbeFunction function)
+    {
+        return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
+    }
+
+    inline TrustedImm32 trustedImm32FromPtr(void (*function)())
+    {
+        return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
+    }
+#endif
 };
 
+#if USE(MASM_PROBE)
+
+extern "C" void ctiMasmProbeTrampoline();
+
+// What code is emitted for the probe?
+// ==================================
+// We want to keep the size of the emitted probe invocation code as compact as
+// possible to minimize the perturbation to the JIT generated code. However,
+// we also need to preserve the CPU registers and set up the ProbeContext to be
+// passed to the user probe function.
+//
+// Hence, we do only the minimum here to preserve the eax (to be used as a
+// scratch register) and esp registers, and pass the probe arguments. We'll let
+// the ctiMasmProbeTrampoline handle the rest of the probe invocation work
+// i.e. saving the CPUState (and setting up the ProbeContext), calling the user
+// probe function, and restoring the CPUState before returning to JIT generated
+// code.
+//
+// What values are in the saved registers?
+// ======================================
+// Conceptually, the saved registers should contain values as if the probe
+// is not present in the JIT generated code. Hence, they should contain values
+// that are expected at the start of the instruction immediately following the
+// probe.
+//
+// Specifcally, the saved esp will point to the stack position before we
+// push the ProbeContext frame. The saved eip will point to the address of
+// the instruction immediately following the probe. 
+
+inline void MacroAssemblerX86::probe(MacroAssemblerX86::ProbeFunction function, void* arg1, void* arg2)
+{
+    RegisterID esp = RegisterID::esp;
+    #define probeContextField(field) Address(esp, offsetof(ProbeContext, field))
+
+    // The X86_64 ABI specifies that the worse case stack alignment requirement
+    // is 32 bytes.
+    const int probeFrameSize = WTF::roundUpToMultipleOf(32, sizeof(ProbeContext));
+    sub32(TrustedImm32(probeFrameSize), esp);
+
+    store32(RegisterID::eax, probeContextField(cpu.eax));
+
+    move(TrustedImm32(probeFrameSize), RegisterID::eax);
+    add32(esp, RegisterID::eax);
+    store32(RegisterID::eax, probeContextField(cpu.esp));
+
+    store32(trustedImm32FromPtr(function), probeContextField(probeFunction));
+    store32(trustedImm32FromPtr(arg1), probeContextField(arg1));
+    store32(trustedImm32FromPtr(arg2), probeContextField(arg2));
+
+    move(trustedImm32FromPtr(ctiMasmProbeTrampoline), RegisterID::eax);
+    call(RegisterID::eax);
+
+    #undef probeContextField
+}
+#endif // USE(MASM_PROBE)
+
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)