[pypy-svn] r47497 - in pypy/dist/pypy/rpython/memory/gctransform: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Tue Oct 16 14:50:34 CEST 2007
Author: cfbolz
Date: Tue Oct 16 14:50:33 2007
New Revision: 47497
Modified:
pypy/dist/pypy/rpython/memory/gctransform/framework.py
pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
pypy/dist/pypy/rpython/memory/gctransform/transform.py
Log:
significantly reduce the number of pushing and popping
the framework GCs do: variables are only saved across a
call if the variable is needed afterwards.
Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Tue Oct 16 14:50:33 2007
@@ -416,9 +416,9 @@
def gct_direct_call(self, hop):
if self.collect_analyzer.analyze(hop.spaceop):
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
self.default(hop)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
else:
self.default(hop)
@@ -462,20 +462,20 @@
args = [self.c_const_gc, c_type_id, v_length, c_size,
c_varitemsize, c_ofstolength, c_can_collect,
c_has_finalizer]
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
v_result = hop.genop("direct_call", [malloc_ptr] + args,
resulttype=llmemory.GCREF)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
return v_result
gct_fv_gc_malloc_varsize = gct_fv_gc_malloc
def gct_gc__collect(self, hop):
op = hop.spaceop
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
hop.genop("direct_call", [self.collect_ptr, self.c_const_gc],
resultvar=op.result)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
def gct_gc_x_swap_pool(self, hop):
op = hop.spaceop
@@ -502,11 +502,11 @@
def gct_gc_x_become(self, hop):
op = hop.spaceop
[v_target, v_source] = op.args
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
hop.genop("direct_call",
[self.x_become_ptr, self.c_const_gc, v_target, v_source],
resultvar=op.result)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
def gct_zero_gc_pointers_inside(self, hop):
v_ob = hop.spaceop.args[0]
@@ -530,12 +530,12 @@
v_instance, = op.args
v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
resulttype=llmemory.Address)
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
v_result = hop.genop("direct_call", [malloc_ptr] + args,
resulttype=llmemory.GCREF)
v_result = hop.genop("cast_opaque_ptr", [v_result],
resulttype=WEAKREFPTR)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
hop.genop("bare_setfield",
[v_result, rmodel.inputconst(lltype.Void, "weakptr"), v_addr])
v_weakref = hop.genop("cast_ptr_to_weakrefptr", [v_result],
@@ -551,13 +551,13 @@
def gct_gc_id(self, hop):
if self.id_ptr is not None:
- self.push_roots(hop)
+ livevars = self.push_roots(hop)
[v_ptr] = hop.spaceop.args
v_ptr = hop.genop("cast_opaque_ptr", [v_ptr],
resulttype=llmemory.GCREF)
hop.genop("direct_call", [self.id_ptr, self.c_const_gc, v_ptr],
resultvar=hop.spaceop.result)
- self.pop_roots(hop)
+ self.pop_roots(hop, livevars)
else:
hop.rename('cast_ptr_to_int') # works nicely for non-moving GCs
@@ -570,10 +570,17 @@
def push_roots(self, hop):
if self.incr_stack_ptr is None:
return
- livevars = [var for var in self.livevars if not var_ispyobj(var)]
+ if self.gcdata.gc.moving_gc:
+ # moving GCs don't borrow, so the caller does not need to keep
+ # the arguments alive
+ livevars = [var for var in self.livevars_after_op
+ if not var_ispyobj(var)]
+ else:
+ livevars = self.livevars_after_op + self.current_op_keeps_alive
+ livevars = [var for var in livevars if not var_ispyobj(var)]
self.num_pushs += len(livevars)
if not livevars:
- return
+ return []
c_len = rmodel.inputconst(lltype.Signed, len(livevars) )
base_addr = hop.genop("direct_call", [self.incr_stack_ptr, c_len ],
resulttype=llmemory.Address)
@@ -588,11 +595,11 @@
resulttype=WEAKREFPTR)
v_adr = gen_cast(hop.llops, llmemory.Address, var)
hop.genop("raw_store", [base_addr, c_type, c_k, v_adr])
+ return livevars
- def pop_roots(self, hop):
+ def pop_roots(self, hop, livevars):
if self.decr_stack_ptr is None:
return
- livevars = [var for var in self.livevars if not var_ispyobj(var)]
if not livevars:
return
c_len = rmodel.inputconst(lltype.Signed, len(livevars) )
Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py Tue Oct 16 14:50:33 2007
@@ -79,7 +79,7 @@
[varoftype(PTR_TYPE), Constant('x', lltype.Void)],
varoftype(lltype.Void))
transformer = WriteBarrierTransformer(t)
- hop = GcHighLevelOp(transformer, spaceop, llops)
+ hop = GcHighLevelOp(transformer, spaceop, 0, llops)
hop.dispatch()
found = False
for op in llops:
Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/transform.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/transform.py Tue Oct 16 14:50:33 2007
@@ -33,10 +33,17 @@
PyObjPtr = lltype.Ptr(lltype.PyObject)
class GcHighLevelOp(object):
- def __init__(self, gctransformer, op, llops):
- self.gctransformer = gctransformer
+ def __init__(self, gct, op, index, llops):
+ self.gctransformer = gct
self.spaceop = op
+ self.index = index
self.llops = llops
+ gct.livevars_after_op = [
+ var for var in gct.livevars
+ if gct.var_last_needed_in[var] > self.index]
+ gct.current_op_keeps_alive = [
+ var for var in self.spaceop.args
+ if gct.var_last_needed_in.get(var) == self.index]
def dispatch(self):
gct = self.gctransformer
@@ -56,6 +63,8 @@
gct.push_alive(v_result)
elif opname not in ('direct_call', 'indirect_call'):
gct.push_alive(v_result)
+
+
def rename(self, newopname):
self.llops.append(
@@ -152,8 +161,21 @@
#self.curr_block = block
self.livevars = [var for var in block.inputargs
if var_needsgc(var) and not is_borrowed(var)]
- for op in block.operations:
- hop = GcHighLevelOp(self, op, self.llops)
+ allvars = [var for var in block.getvariables() if var_needsgc(var)]
+ self.var_last_needed_in = dict.fromkeys(allvars, 0)
+ for i, op in enumerate(block.operations):
+ for var in op.args:
+ if not var_needsgc(var):
+ continue
+ self.var_last_needed_in[var] = i
+ for link in block.exits:
+ for var in link.args:
+ if not var_needsgc(var):
+ continue
+ self.var_last_needed_in[var] = len(block.operations) + 1
+
+ for i, op in enumerate(block.operations):
+ hop = GcHighLevelOp(self, op, i, self.llops)
hop.dispatch()
if len(block.exits) != 0: # i.e not the return block
@@ -182,6 +204,7 @@
block.operations[:] = self.llops
self.llops = None
self.livevars = None
+ self.var_last_needed_in = None
def transform_graph(self, graph):
if graph in self.minimal_transform:
More information about the Pypy-commit
mailing list