[pypy-commit] pypy improve-gc-tracing-hooks: Simplify custom tracers with gc._trace_callback(). Port jitframe.
arigo
noreply at buildbot.pypy.org
Tue Oct 21 15:20:26 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: improve-gc-tracing-hooks
Changeset: r74037:9ec0a7216835
Date: 2014-10-21 15:20 +0200
http://bitbucket.org/pypy/pypy/changeset/9ec0a7216835/
Log: Simplify custom tracers with gc._trace_callback(). Port jitframe.
diff --git a/rpython/jit/backend/llsupport/jitframe.py b/rpython/jit/backend/llsupport/jitframe.py
--- a/rpython/jit/backend/llsupport/jitframe.py
+++ b/rpython/jit/backend/llsupport/jitframe.py
@@ -3,6 +3,7 @@
from rpython.rlib.objectmodel import specialize
from rpython.rlib.debug import ll_assert
from rpython.rlib.objectmodel import enforceargs
+from rpython.rlib import rgc
SIZEOFSIGNED = rffi.sizeof(lltype.Signed)
IS_32BIT = (SIZEOFSIGNED == 4)
@@ -45,6 +46,7 @@
# detailed explanation how it is on your architecture
def jitframe_allocate(frame_info):
+ rgc.register_custom_trace_hook(JITFRAME, lambda_jitframe_trace)
frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth)
frame.jf_frame_info = frame_info
frame.jf_extra_stack_depth = 0
@@ -80,8 +82,6 @@
('jf_guard_exc', llmemory.GCREF),
# in case the frame got reallocated, we have to forward it somewhere
('jf_forward', lltype.Ptr(JITFRAME)),
- # absolutely useless field used to make up for tracing hooks inflexibilities
- ('jf_gc_trace_state', lltype.Signed),
# the actual frame
('jf_frame', lltype.Array(lltype.Signed)),
# note that we keep length field, because it's crucial to have the data
@@ -105,75 +105,38 @@
UNSIGN_SIZE = llmemory.sizeof(lltype.Unsigned)
STACK_DEPTH_OFS = getofs('jf_extra_stack_depth')
-def jitframe_trace(obj_addr, prev):
- if prev == llmemory.NULL:
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -1
- return obj_addr + getofs('jf_descr')
- fld = (obj_addr + getofs('jf_gc_trace_state')).signed[0]
- if fld < 0:
- if fld == -1:
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -2
- return obj_addr + getofs('jf_force_descr')
- elif fld == -2:
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -3
- return obj_addr + getofs('jf_savedata')
- elif fld == -3:
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -4
- return obj_addr + getofs('jf_guard_exc')
- elif fld == -4:
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -5
- return obj_addr + getofs('jf_forward')
- else:
- if not (obj_addr + getofs('jf_gcmap')).address[0]:
- return llmemory.NULL # done
- else:
- fld = 0 # fall-through
- # bit pattern
- # decode the pattern
+def jitframe_trace(gc, obj_addr, callback, arg):
+ gc._trace_callback(callback, arg, obj_addr + getofs('jf_descr'))
+ gc._trace_callback(callback, arg, obj_addr + getofs('jf_force_descr'))
+ gc._trace_callback(callback, arg, obj_addr + getofs('jf_savedata'))
+ gc._trace_callback(callback, arg, obj_addr + getofs('jf_guard_exc'))
+ gc._trace_callback(callback, arg, obj_addr + getofs('jf_forward'))
+
if IS_32BIT:
- # 32 possible bits
- state = fld & 0x1f
- no = fld >> 5
MAX = 32
else:
- # 64 possible bits
- state = fld & 0x3f
- no = fld >> 6
MAX = 64
gcmap = (obj_addr + getofs('jf_gcmap')).address[0]
+ if not gcmap:
+ return # done
gcmap_lgt = (gcmap + GCMAPLENGTHOFS).signed[0]
+ no = 0
while no < gcmap_lgt:
cur = (gcmap + GCMAPBASEOFS + UNSIGN_SIZE * no).unsigned[0]
- while not (cur & (1 << state)):
- state += 1
- if state == MAX:
- no += 1
- state = 0
- break # next iteration of the outermost loop
- else:
- # found it
- index = no * SIZEOFSIGNED * 8 + state
- # save new state
- state += 1
- if state == MAX:
- no += 1
- state = 0
- if IS_32BIT:
- new_state = state | (no << 5)
- else:
- new_state = state | (no << 6)
- (obj_addr + getofs('jf_gc_trace_state')).signed[0] = new_state
- # sanity check
- frame_lgt = (obj_addr + getofs('jf_frame') + LENGTHOFS).signed[0]
- ll_assert(index < frame_lgt, "bogus frame field get")
- return (obj_addr + getofs('jf_frame') + BASEITEMOFS + SIGN_SIZE *
- (index))
- return llmemory.NULL
-
-CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
- llmemory.Address)
-jitframe_trace_ptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), jitframe_trace)
-
-lltype.attachRuntimeTypeInfo(JITFRAME, customtraceptr=jitframe_trace_ptr)
+ bitindex = 0
+ while bitindex < MAX:
+ if cur & (1 << bitindex):
+ # the 'bitindex' is set in 'cur'
+ index = no * SIZEOFSIGNED * 8 + bitindex
+ # sanity check
+ frame_lgt = (obj_addr + getofs('jf_frame') + LENGTHOFS) \
+ .signed[0]
+ ll_assert(index < frame_lgt, "bogus frame field get")
+ gc._trace_callback(callback, arg,
+ obj_addr + getofs('jf_frame') +
+ BASEITEMOFS + SIGN_SIZE * index)
+ bitindex += 1
+ no += 1
+lambda_jitframe_trace = lambda: jitframe_trace
JITFRAMEPTR = lltype.Ptr(JITFRAME)
diff --git a/rpython/jit/backend/llsupport/test/test_gc.py b/rpython/jit/backend/llsupport/test/test_gc.py
--- a/rpython/jit/backend/llsupport/test/test_gc.py
+++ b/rpython/jit/backend/llsupport/test/test_gc.py
@@ -254,11 +254,15 @@
frame.jf_gcmap[2] = r_uint(2 | 16 | 32 | 128)
frame.jf_gcmap[3] = r_uint(0)
frame_adr = llmemory.cast_ptr_to_adr(frame)
+ #
all_addrs = []
- next = jitframe.jitframe_trace(frame_adr, llmemory.NULL)
- while next:
- all_addrs.append(next)
- next = jitframe.jitframe_trace(frame_adr, next)
+ class FakeGC:
+ def _trace_callback(self, callback, arg, addr):
+ assert callback == "hello"
+ assert arg == "world"
+ all_addrs.append(addr)
+ jitframe.jitframe_trace(FakeGC(), frame_adr, "hello", "world")
+ #
counter = 0
for name in jitframe.JITFRAME._names:
TP = getattr(jitframe.JITFRAME, name)
@@ -297,12 +301,12 @@
frame.jf_gcmap[0] = r_uint(18446744073441116160)
frame.jf_gcmap[1] = r_uint(18446740775107559407)
frame.jf_gcmap[2] = r_uint(3)
- all_addrs = []
frame_adr = llmemory.cast_ptr_to_adr(frame)
- next = jitframe.jitframe_trace(frame_adr, llmemory.NULL)
- while next:
- all_addrs.append(next)
- next = jitframe.jitframe_trace(frame_adr, next)
+ class FakeGC:
+ def _trace_callback(self, callback, arg, addr):
+ assert callback == "hello"
+ assert arg == "world"
+ jitframe.jitframe_trace(FakeGC(), frame_adr, "hello", "world")
# assert did not hang
lltype.free(frame_info, flavor='raw')
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -224,6 +224,11 @@
self.custom_trace_dispatcher(obj, typeid, callback, arg)
_trace_slow_path._annspecialcase_ = 'specialize:arg(2)'
+ def _trace_callback(self, callback, arg, addr):
+ if self.is_valid_gc_object(addr.address[0]):
+ callback(addr, arg)
+ _trace_callback._annspecialcase_ = 'specialize:arg(1)'
+
def trace_partial(self, obj, start, stop, callback, arg):
"""Like trace(), but only walk the array part, for indices in
range(start, stop). Must only be called if has_gcptr_in_varsize().
diff --git a/rpython/memory/test/gc_test_base.py b/rpython/memory/test/gc_test_base.py
--- a/rpython/memory/test/gc_test_base.py
+++ b/rpython/memory/test/gc_test_base.py
@@ -245,8 +245,7 @@
T = lltype.GcStruct('T', ('z', lltype.Signed))
offset_of_x = llmemory.offsetof(S, 'x')
def customtrace(gc, obj, callback, arg):
- if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
- callback(obj + offset_of_x, arg)
+ gc._trace_callback(callback, arg, obj + offset_of_x)
lambda_customtrace = lambda: customtrace
#
for attrname in ['x', 'y']:
diff --git a/rpython/memory/test/test_transformed_gc.py b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -390,8 +390,7 @@
T = lltype.GcStruct('T', ('z', lltype.Signed))
offset_of_x = llmemory.offsetof(S, 'x')
def customtrace(gc, obj, callback, arg):
- if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
- callback(obj + offset_of_x, arg)
+ gc._trace_callback(callback, arg, obj + offset_of_x)
lambda_customtrace = lambda: customtrace
#
diff --git a/rpython/rlib/_stacklet_asmgcc.py b/rpython/rlib/_stacklet_asmgcc.py
--- a/rpython/rlib/_stacklet_asmgcc.py
+++ b/rpython/rlib/_stacklet_asmgcc.py
@@ -102,8 +102,7 @@
location)
# yield the translated addr of the next GCREF in the stack
addr = self.translateptr(addr)
- if gc.is_valid_gc_object(addr.address[0]):
- callback(addr, arg)
+ gc._trace_callback(callback, arg, addr)
caller = self.otherframe
reg = CALLEE_SAVED_REGS - 1
diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -446,8 +446,7 @@
S = lltype.GcStruct('S', ('x', llmemory.Address))
offset_of_x = llmemory.offsetof(S, 'x')
def customtrace(gc, obj, callback, arg):
- if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
- callback(obj + offset_of_x, arg)
+ gc._trace_callback(callback, arg, obj + offset_of_x)
lambda_customtrace = lambda: customtrace
#
def setup():
More information about the pypy-commit
mailing list