Author: Armin Rigo <ar...@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(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit