[pypy-svn] pypy lltrace: Support for generating trace events from inside the assembler
arigo
commits-noreply at bitbucket.org
Tue Feb 22 14:59:54 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: lltrace
Changeset: r42211:296023b39a57
Date: 2011-02-22 14:58 +0100
http://bitbucket.org/pypy/pypy/changeset/296023b39a57/
Log: Support for generating trace events from inside the assembler
produced by the JIT.
diff --git a/pypy/jit/backend/llsupport/trace.py b/pypy/jit/backend/llsupport/trace.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/llsupport/trace.py
@@ -0,0 +1,17 @@
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.objectmodel import CDefinedIntSymbolic, we_are_translated
+
+
+# Calling this function adds an entry in the buffer maintained by
+# src/debug_lltrace.h. Arguments: addr, newvalue, mark.
+trace_set = rffi.llexternal("_RPyTraceSet",
+ [rffi.CCHARP, rffi.LONG, rffi.LONG],
+ lltype.Void,
+ _callable = lambda a, n, m: None,
+ _nowrapper = True)
+
+_is_tracing = CDefinedIntSymbolic('RPY_IS_TRACING', default=0)
+addr_of_trace_set = CDefinedIntSymbolic('((long)&_RPyTraceSet)', default=0)
+
+def is_tracing():
+ return we_are_translated() and _is_tracing != 0
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -39,6 +39,7 @@
from pypy.jit.metainterp.history import ConstInt, BoxInt
from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.codewriter import longlong
+from pypy.jit.backend.llsupport import trace
# darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
# better safe than sorry
@@ -1253,7 +1254,30 @@
else:
not_implemented("load_from_mem size = %d" % size)
- def save_into_mem(self, dest_addr, value_loc, size_loc):
+ def generate_ll_trace(self, dest_addr, value_loc):
+ # XXX for now, we only trace 32-bit pointer-sized writes
+ self.mc.PUSH_r(eax.value)
+ self.mc.PUSH_r(ecx.value)
+ self.mc.PUSH_r(edx.value)
+ self.mc.PUSH_r(edx.value)
+ self.mc.PUSH_r(edx.value) # 5 pushes + 3 args, keeps 16-bytes alignment
+ # use the current address as the mark
+ self.mc.CALL_l(0) # this is equivalent to "PUSH(IP)"
+ # push the newvalue
+ self.mc.PUSH(value_loc)
+ # push the address in which we are about to write
+ self.mc.LEA(eax, dest_addr)
+ self.mc.PUSH_r(eax.value)
+ # call (as an indirect call, to avoid needing a relative displacement)
+ self.mc.MOV_ri(eax.value, trace.addr_of_trace_set)
+ self.mc.CALL_r(eax.value)
+ # cancel the 8 pushes
+ self.mc.ADD_ri(esp.value, 5 * WORD)
+ self.mc.POP_r(edx.value)
+ self.mc.POP_r(ecx.value)
+ self.mc.POP_r(eax.value)
+
+ def save_into_mem(self, dest_addr, value_loc, size_loc, is_gc):
size = size_loc.value
if isinstance(value_loc, RegLoc) and value_loc.is_xmm:
self.mc.MOVSD(dest_addr, value_loc)
@@ -1262,6 +1286,8 @@
elif size == 2:
self.mc.MOV16(dest_addr, value_loc)
elif size == 4:
+ if IS_X86_32 and trace.is_tracing() and is_gc:
+ self.generate_ll_trace(dest_addr, value_loc)
self.mc.MOV32(dest_addr, value_loc)
elif size == 8:
if IS_X86_64:
@@ -1298,7 +1324,8 @@
base_loc, ofs_loc, size_loc, value_loc = arglocs
assert isinstance(size_loc, ImmedLoc)
dest_addr = AddressLoc(base_loc, ofs_loc)
- self.save_into_mem(dest_addr, value_loc, size_loc)
+ self.save_into_mem(dest_addr, value_loc, size_loc,
+ op.getopnum() == rop.SETFIELD_GC)
def genop_discard_setarrayitem_gc(self, op, arglocs):
base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
@@ -1306,7 +1333,8 @@
assert isinstance(size_loc, ImmedLoc)
scale = _get_scale(size_loc.value)
dest_addr = AddressLoc(base_loc, ofs_loc, scale, baseofs.value)
- self.save_into_mem(dest_addr, value_loc, size_loc)
+ self.save_into_mem(dest_addr, value_loc, size_loc,
+ op.getopnum() == rop.SETARRAYITEM_GC)
def genop_discard_strsetitem(self, op, arglocs):
base_loc, ofs_loc, val_loc = arglocs
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -18,6 +18,7 @@
from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr
from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr
from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
+from pypy.jit.backend.llsupport.trace import trace_set
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -325,6 +326,9 @@
ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
+ if lltype.typeOf(gcref) is not lltype.Signed:
+ trace_set(rffi.ptradd(items, itemindex * size),
+ rffi.cast(rffi.LONG, newvalue), -100-size)
for TYPE, _, itemsize in unroll_basic_sizes:
if size == itemsize:
items = rffi.cast(rffi.CArrayPtr(TYPE), items)
@@ -339,6 +343,8 @@
self.gc_ll_descr.do_write_barrier(gcref, newvalue)
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
+ trace_set(rffi.ptradd(items, itemindex * WORD),
+ rffi.cast(rffi.LONG, newvalue), -99)
items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
items[itemindex] = self.cast_gcref_to_int(newvalue)
# --- end of GC unsafe code ---
@@ -348,6 +354,9 @@
ofs = self.unpack_arraydescr(arraydescr)
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
+ if lltype.typeOf(gcref) is not lltype.Signed:
+ trace_set(rffi.ptradd(items, itemindex * symbolic.SIZEOF_FLOAT),
+ rffi.cast(rffi.LONG, newvalue), -98)
items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
items[itemindex] = newvalue
# --- end of GC unsafe code ---
@@ -426,6 +435,8 @@
ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
+ if lltype.typeOf(struct) is not lltype.Signed:
+ trace_set(fieldptr, rffi.cast(rffi.LONG, newvalue), -10)
for TYPE, _, itemsize in unroll_basic_sizes:
if size == itemsize:
fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)
@@ -443,6 +454,7 @@
self.gc_ll_descr.do_write_barrier(struct, newvalue)
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
+ trace_set(fieldptr, rffi.cast(rffi.LONG, newvalue), -9)
fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)
fieldptr[0] = self.cast_gcref_to_int(newvalue)
# --- end of GC unsafe code ---
@@ -452,6 +464,8 @@
ofs = self.unpack_fielddescr(fielddescr)
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
+ if lltype.typeOf(struct) is not lltype.Signed:
+ trace_set(fieldptr, rffi.cast(rffi.LONG, newvalue), -8)
fieldptr = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), fieldptr)
fieldptr[0] = newvalue
# --- end of GC unsafe code ---
diff --git a/pypy/translator/c/src/debug_lltrace.h b/pypy/translator/c/src/debug_lltrace.h
--- a/pypy/translator/c/src/debug_lltrace.h
+++ b/pypy/translator/c/src/debug_lltrace.h
@@ -1,18 +1,21 @@
-void _RPyTraceSet(void *addr, long newvalue, int mark);
+void _RPyTraceSet(void *addr, long newvalue, long mark);
#ifndef RPY_LL_TRACE /****************************************/
+
+# define RPY_IS_TRACING 0
# define RPyTraceSet(ptr, mark) /* nothing */
# ifndef PYPY_NOT_MAIN_FILE
-void _RPyTraceSet(void *addr, long newvalue, int mark) { }
+void _RPyTraceSet(void *addr, long newvalue, long mark) { }
# endif
#else /*******************************************************/
+# define RPY_IS_TRACING 1
# define RPyTraceSet(ptr, mark) _RPyTraceSet(&(ptr), (long)(ptr), mark)
# ifndef PYPY_NOT_MAIN_FILE
@@ -26,15 +29,15 @@
static struct _RPyTrace_s *_RPyTrace_start = NULL;
static struct _RPyTrace_s *_RPyTrace_stop = NULL;
static struct _RPyTrace_s *_RPyTrace_current = NULL;
-static int _RPyTrace_default_size = 134217728;
+static const long _RPyTrace_default_size = 134217728;
void _RPyTrace_WrapAround(void)
{
if (_RPyTrace_start == NULL)
{
- char *csize = getenv("PYPYTRACE");
- int size = csize ? atoi(csize) : 0;
- if (size <= 0)
+ char *csize = getenv("PYPYTRACEBUF");
+ long size = csize ? atol(csize) : 0;
+ if (size <= 1)
size = _RPyTrace_default_size;
_RPyTrace_start = malloc(size * sizeof(struct _RPyTrace_s));
RPyAssert(_RPyTrace_start, "not enough memory to allocate the trace");
@@ -46,7 +49,7 @@
(long)(_RPyTrace_stop - _RPyTrace_start));
}
-void _RPyTraceSet(void *addr, long newvalue, int mark)
+void _RPyTraceSet(void *addr, long newvalue, long mark)
{
if (_RPyTrace_current == _RPyTrace_stop)
_RPyTrace_WrapAround();
diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py
--- a/pypy/jit/backend/x86/test/test_ztranslation.py
+++ b/pypy/jit/backend/x86/test/test_ztranslation.py
@@ -36,6 +36,11 @@
def __init__(self, i):
self.i = i
+ self.a = None
+
+ class A(object):
+ def __init__(self, next):
+ self.next = next
@dont_look_inside
def myabs(x):
@@ -64,6 +69,7 @@
k = myabs(j)
if k - abs(j): raise ValueError
if k - abs(-j): raise ValueError
+ frame.a = A(frame.a)
return total * 10
#
from pypy.rpython.lltypesystem import lltype, rffi
More information about the Pypy-commit
mailing list