Author: Armin Rigo <[email protected]>
Branch:
Changeset: r89896:4a7ae8e412f5
Date: 2017-02-01 21:56 +0100
http://bitbucket.org/pypy/pypy/changeset/4a7ae8e412f5/
Log: Change the time at which we modify a graph with "hint_close_stack".
Previously, it was at the time where we find a direct_call to it.
Now it is when we're about to gctransform the graph itself.
If we first find a function pointer to this function, then this
change is important: without it, funcgen.py will hold the unmodified
graph and enumerate dependencies from there, instead of the real
dependencies of the modified graph. As pycket found, there are cases
where it occurs.
diff --git a/rpython/memory/gctransform/asmgcroot.py
b/rpython/memory/gctransform/asmgcroot.py
--- a/rpython/memory/gctransform/asmgcroot.py
+++ b/rpython/memory/gctransform/asmgcroot.py
@@ -26,7 +26,6 @@
class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer):
_asmgcc_save_restore_arguments = None
- _seen_gctransformer_hint_close_stack = None
def push_roots(self, hop, keep_current_args=False):
livevars = self.get_livevars_for_roots(hop, keep_current_args)
@@ -50,29 +49,28 @@
hop.genop("direct_call", [c_asm_nocollect, name])
def gct_direct_call(self, hop):
+ # just a sanity check: if we find a fnptr with the hint on the
+ # _callable, then we'd also find the hint by looking only at the
+ # graph. We'll actually change this graph only later, in
+ # start_transforming_graph().
fnptr = hop.spaceop.args[0].value
try:
close_stack = fnptr._obj._callable._gctransformer_hint_close_stack_
except AttributeError:
+ pass
+ else:
+ assert fnptr._obj.graph.func is fnptr._obj._callable
+ BaseFrameworkGCTransformer.gct_direct_call(self, hop)
+
+ def start_transforming_graph(self, graph):
+ try:
+ close_stack = graph.func._gctransformer_hint_close_stack_
+ except AttributeError:
close_stack = False
if close_stack:
- self.handle_call_with_close_stack(hop)
- else:
- BaseFrameworkGCTransformer.gct_direct_call(self, hop)
+ self._transform_hint_close_stack(graph)
- def handle_call_with_close_stack(self, hop):
- fnptr = hop.spaceop.args[0].value
- if self._seen_gctransformer_hint_close_stack is None:
- self._seen_gctransformer_hint_close_stack = {}
- if fnptr._obj.graph not in self._seen_gctransformer_hint_close_stack:
- self._transform_hint_close_stack(fnptr)
- self._seen_gctransformer_hint_close_stack[fnptr._obj.graph] = True
- #
- livevars = self.push_roots(hop)
- self.default(hop)
- self.pop_roots(hop, livevars)
-
- def _transform_hint_close_stack(self, fnptr):
+ def _transform_hint_close_stack(self, graph):
# We cannot easily pass variable amount of arguments of the call
# across the call to the pypy_asm_stackwalk helper. So we store
# them away and restore them. More precisely, we need to
@@ -83,8 +81,8 @@
sradict = self._asmgcc_save_restore_arguments
sra = [] # list of pointers to raw-malloced containers for args
seen = {}
- FUNC1 = lltype.typeOf(fnptr).TO
- for TYPE in FUNC1.ARGS:
+ ARGS = [v.concretetype for v in graph.getargs()]
+ for TYPE in ARGS:
if isinstance(TYPE, lltype.Ptr):
TYPE = llmemory.Address
num = seen.get(TYPE, 0)
@@ -98,8 +96,10 @@
sra.append(sradict[key])
#
# make a copy of the graph that will reload the values
- graph = fnptr._obj.graph
graph2 = copygraph(graph)
+ del graph2.func # otherwise, start_transforming_graph() will
+ # again transform graph2, and we get an
+ # infinite loop
#
# edit the original graph to only store the value of the arguments
block = Block(graph.startblock.inputargs)
@@ -116,17 +116,18 @@
SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void))
#
# call asm_stackwalk(graph2)
- FUNC2 = lltype.FuncType([], FUNC1.RESULT)
+ RESULT = graph.getreturnvar().concretetype
+ FUNC2 = lltype.FuncType([], RESULT)
fnptr2 = lltype.functionptr(FUNC2,
- fnptr._obj._name + '_reload',
+ graph.name + '_reload',
graph=graph2)
c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2))
HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2),
- ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT)
+ ASM_FRAMEDATA_HEAD_PTR], RESULT)
v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk")
block.operations.append(
SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk))
- v_result = varoftype(FUNC1.RESULT)
+ v_result = varoftype(RESULT)
block.operations.append(
SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2,
c_gcrootanchor,
diff --git a/rpython/memory/gctransform/transform.py
b/rpython/memory/gctransform/transform.py
--- a/rpython/memory/gctransform/transform.py
+++ b/rpython/memory/gctransform/transform.py
@@ -201,6 +201,9 @@
self.var_last_needed_in = None
self.curr_block = None
+ def start_transforming_graph(self, graph):
+ pass # for asmgcc.py
+
def transform_graph(self, graph):
if graph in self.minimal_transform:
if self.minimalgctransformer:
@@ -210,6 +213,7 @@
if graph in self.seen_graphs:
return
self.seen_graphs.add(graph)
+ self.start_transforming_graph(graph)
self.links_to_split = {} # link -> vars to pop_alive across the link
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit