[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