[pypy-svn] r21761 - in pypy/dist/pypy: jit rpython translator translator/backendopt translator/backendopt/test translator/c translator/c/test translator/js translator/llvm/backendopt translator/locality

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Jan 6 22:05:19 CET 2006


Author: cfbolz
Date: Fri Jan  6 22:05:13 2006
New Revision: 21761

Modified:
   pypy/dist/pypy/jit/llabstractinterp.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/rptr.py
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/backendopt/propagate.py
   pypy/dist/pypy/translator/backendopt/removenoops.py
   pypy/dist/pypy/translator/backendopt/test/test_malloc.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/test/test_annotated.py
   pypy/dist/pypy/translator/js/opwriter.py
   pypy/dist/pypy/translator/llvm/backendopt/exception.py
   pypy/dist/pypy/translator/locality/calltree.py
   pypy/dist/pypy/translator/simplify.py
Log:
introduce a new ll operation: indirect_call. It is used if the function that is
being called is a Variable. This makes attaching of the possibly
called functions to the operation (which I will be doing next) much cleaner, as
I can abuse an argument for it.



Modified: pypy/dist/pypy/jit/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp.py	Fri Jan  6 22:05:13 2006
@@ -312,9 +312,9 @@
             for st in stlist:
                 op = st.origblock.operations[st.origposition]
                 if op.opname == 'direct_call':
+                    v = v.value
+                elif op.opname == 'indirect_call':
                     v = op.args[0]
-                    if isinstance(v, Constant):
-                        v = v.value
                 else:
                     v = '?'
                 print 'In %r:' % (v,)
@@ -673,6 +673,15 @@
             a_result = self.residualize(op, args_a)
         return a_result
 
+    def op_indirect_call(self, op, *args_a):
+        # XXX not really sure what the right thing to do is:
+        # right now there is no test that produces indirect_call
+        # the slight ugliness involved is, that it is necessary to
+        # change the operation from an indirect_call to a direct_call
+        # when the first argument of the indirect_call is discovered to be
+        # constant
+        assert 0, "XXX"
+
     def handle_call(self, op, a_func, *args_a):
         v_func = a_func.maybe_get_constant()
         if v_func is None:

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Fri Jan  6 22:05:13 2006
@@ -224,6 +224,11 @@
     def eval_operation(self, operation):
         log.operation("considering", operation)
         ophandler = self.getoperationhandler(operation.opname)
+        # XXX slighly unnice but an important safety check
+        if operation.opname == 'direct_call':
+            assert isinstance(operation.args[0], Constant)
+        elif operation.opname == 'indirect_call':
+            assert isinstance(operation.args[0], Variable)
         vals = [self.getval(x) for x in operation.args]
         # if these special cases pile up, do something better here
         if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast']:
@@ -314,6 +319,8 @@
         frame = self.__class__(graph, args, self.llinterpreter, self)
         return frame.eval()
 
+    op_indirect_call = op_direct_call  # XXX for now
+
     def op_malloc(self, obj):
         if self.llinterpreter.gc is not None:
             args = self.llinterpreter.gc.get_arg_malloc(obj)

Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Fri Jan  6 22:05:13 2006
@@ -312,7 +312,10 @@
         vlist += callparse.callparse(self.rtyper, anygraph, hop, opname)
         rresult = callparse.getrresult(self.rtyper, anygraph)
         hop.exception_is_here()
-        v = hop.genop('direct_call', vlist, resulttype = rresult)
+        if isinstance(vlist[0], Constant):
+            v = hop.genop('direct_call', vlist, resulttype = rresult)
+        else:
+            v = hop.genop('indirect_call', vlist, resulttype = rresult)
         return hop.llops.convertvar(v, rresult, hop.r_result)
 
 class __extend__(pairtype(FunctionsPBCRepr, FunctionsPBCRepr)):

Modified: pypy/dist/pypy/rpython/rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/rptr.py	(original)
+++ pypy/dist/pypy/rpython/rptr.py	Fri Jan  6 22:05:13 2006
@@ -62,8 +62,11 @@
         if isinstance(vlist[0], flowmodel.Constant):
             if hasattr(vlist[0].value, 'graph'):
                 hop.llops.record_extra_call(vlist[0].value.graph)
+            opname = 'direct_call'
+        else:
+            opname = 'indirect_call'
         hop.exception_is_here()
-        return hop.genop('direct_call', vlist,
+        return hop.genop(opname, vlist,
                          resulttype = self.lowleveltype.TO.RESULT)
 
 

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Fri Jan  6 22:05:13 2006
@@ -34,8 +34,7 @@
     def visit(block):
         if isinstance(block, Block):
             for i, op in enumerate(block.operations):
-                if not (op.opname == "direct_call" and
-                    isinstance(op.args[0], Constant)):
+                if not op.opname == "direct_call":
                     continue
                 funcobj = op.args[0].value._obj
                 graph = getattr(funcobj, 'graph', None)
@@ -335,8 +334,7 @@
     def build_call_graph(node):
         if isinstance(node, Block):
             for op in node.operations:
-                if (op.opname == "direct_call" and
-                    isinstance(op.args[0], Constant)):
+                if op.opname == "direct_call":
                     funcobj = op.args[0].value._obj
                     graph = getattr(funcobj, 'graph', None)
                     if graph is not None:

Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py	Fri Jan  6 22:05:13 2006
@@ -118,7 +118,8 @@
 _op = """getarrayitem setarrayitem malloc malloc_varsize flavored_malloc
          flavored_free getfield setfield getsubstruct getarraysubstruct
          getarraysize raw_malloc raw_free raw_memcopy raw_load
-         raw_store direct_call cast_pointer cast_ptr_to_int""".split()
+         raw_store direct_call indirect_call cast_pointer
+         cast_ptr_to_int""".split()
 from pypy.objspace.flow.operation import FunctionByName
 _op += FunctionByName.keys() #operations with PyObjects are dangerous
 cannot_constant_fold = {}

Modified: pypy/dist/pypy/translator/backendopt/removenoops.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/removenoops.py	(original)
+++ pypy/dist/pypy/translator/backendopt/removenoops.py	Fri Jan  6 22:05:13 2006
@@ -56,7 +56,7 @@
         graph.startblock.inputargs = args
         for block in graph.iterblocks():
             for op in block.operations:
-                if op.opname == 'direct_call':
+                if op.opname in ('direct_call', 'indirect_call'):
                     args = [arg for arg in op.args
                                 if arg.concretetype is not Void]
                     op.args = args

Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_malloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py	Fri Jan  6 22:05:13 2006
@@ -13,10 +13,10 @@
             for op in node.operations:
                 if op.opname == 'malloc':
                     count1 += 1
-                if op.opname == 'direct_call':
+                if op.opname in ('direct_call', 'indirect_call'):
                     count2 += 1
     assert count1 == 0   # number of mallocs left
-    assert count2 == 0   # number of direct_calls left
+    assert count2 == 0   # number of calls left
 
 def check(fn, signature, args, expected_result, must_be_removed=True):
     t = TranslationContext()

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Fri Jan  6 22:05:13 2006
@@ -434,6 +434,8 @@
         line = '%s\n%s' % (line, self.check_directcall_result(op, err))
         return line
 
+    OP_INDIRECT_CALL = OP_DIRECT_CALL # XXX for now
+
     def check_directcall_result(self, op, err):
         return 'if (RPyExceptionOccurred())\n\tFAIL(%s);' % err
 

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Fri Jan  6 22:05:13 2006
@@ -99,7 +99,7 @@
             return 'pypy_DecRf_%s(%s);' % (defnode.barename, expr)
 
     def push_alive_op_result(self, opname, expr, T):
-        if opname !='direct_call' and T != PyObjPtr:
+        if opname not in ('direct_call', 'indirect_call') and T != PyObjPtr:
             return self.push_alive(expr, T)
         return ''
 

Modified: pypy/dist/pypy/translator/c/test/test_annotated.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_annotated.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_annotated.py	Fri Jan  6 22:05:13 2006
@@ -266,4 +266,19 @@
         def f(i=r_longlong):
             return int(i)
         fn = self.getcompiled(f)
-        assert f(0) == 0
+        assert fn(0) == 0
+
+    def test_function_ptr(self):
+        def f1():
+            return 1
+        def f2():
+            return 2
+        def g(i=int):
+            if i:
+                f = f1
+            else:
+                f = f2
+            return f()
+        fn = self.getcompiled(g)
+        assert fn(0) == 2
+        assert fn(1) == 1

Modified: pypy/dist/pypy/translator/js/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/js/opwriter.py	(original)
+++ pypy/dist/pypy/translator/js/opwriter.py	Fri Jan  6 22:05:13 2006
@@ -228,6 +228,8 @@
         argrefs = self.db.repr_arg_multi(op_args[1:])
         self.codewriter.call(targetvar, functionref, argrefs)
 
+    indirect_call = direct_call  # XXX for now
+
     def invoke(self, op):
         op_args = [arg for arg in op.args
                    if arg.concretetype is not lltype.Void]

Modified: pypy/dist/pypy/translator/llvm/backendopt/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/backendopt/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/backendopt/exception.py	Fri Jan  6 22:05:13 2006
@@ -8,7 +8,8 @@
 n_calls = n_calls_patched = 0
 
 def create_exception_handling(translator, graph):
-    """After an exception in a direct_call, that is not catched by an explicit
+    """After an exception in a direct_call (or indirect_call), that is not caught
+    by an explicit
     except statement, we need to reraise the exception. So after this
     direct_call we need to test if an exception had occurred. If so, we return
     from the current graph with an unused value (false/0/0.0/null).
@@ -23,7 +24,7 @@
             last_operation -= 1
         for i in range(last_operation, -1, -1):
             op = block.operations[i]
-            if op.opname != 'direct_call':
+            if op.opname not in ('direct_call', 'indirect_call'):
                 continue
             n_calls += 1
             called_can_raise = True #XXX maybe we even want a list of possible exceptions

Modified: pypy/dist/pypy/translator/locality/calltree.py
==============================================================================
--- pypy/dist/pypy/translator/locality/calltree.py	(original)
+++ pypy/dist/pypy/translator/locality/calltree.py	Fri Jan  6 22:05:13 2006
@@ -68,21 +68,20 @@
             for op in block.operations:
                 if op.opname == 'direct_call':
                     fnarg = op.args[0]
-                    if isinstance(fnarg, Constant):
-                        fnptr = fnarg.value
-                        fn = fnptr._obj
-                        graph = fn.graph
-                        try:
-                            callednode = self.graphs2nodes[graph]
-                        except KeyError:
-                            s = "No node found for graph %s" % graph.name
-                            log.calltree.findCallees(s)
-                            continue
-                        else:
-                            res.append(callednode)
-                    else:
-                        s = "Node %s calls Variable %s" % (node.name, fnarg)
+                    fnptr = fnarg.value
+                    fn = fnptr._obj
+                    graph = fn.graph
+                    try:
+                        callednode = self.graphs2nodes[graph]
+                    except KeyError:
+                        s = "No node found for graph %s" % graph.name
                         log.calltree.findCallees(s)
+                        continue
+                    else:
+                        res.append(callednode)
+                elif op.opname == 'indirect_call':
+                    s = "Node %s calls Variable %s" % (node.name, op.args[0])
+                    log.calltree.findCallees(s)
         return res
 
     def simulate(self):

Modified: pypy/dist/pypy/translator/simplify.py
==============================================================================
--- pypy/dist/pypy/translator/simplify.py	(original)
+++ pypy/dist/pypy/translator/simplify.py	Fri Jan  6 22:05:13 2006
@@ -378,13 +378,13 @@
                 if op.opname in lloperations_with_side_effects:
                     raise HasSideEffects
                 if op.opname == "direct_call":
-                    if isinstance(op.args[0], Variable):
-                        raise HasSideEffects
                     g = get_graph(op.args[0], translator)
                     if g is None:
                         raise HasSideEffects
                     if not has_no_side_effects(translator, g, seen + [graph]):
                         raise HasSideEffects
+                elif op.opname == "indirect_call":
+                    raise HasSideEffects
         traverse(visit, graph)
     except HasSideEffects:
         return False



More information about the Pypy-commit mailing list