[pypy-svn] r73854 - in pypy/trunk/pypy: objspace/flow rpython translator
benjamin at codespeak.net
benjamin at codespeak.net
Sun Apr 18 01:15:46 CEST 2010
Author: benjamin
Date: Sun Apr 18 01:15:45 2010
New Revision: 73854
Modified:
pypy/trunk/pypy/objspace/flow/flowcontext.py
pypy/trunk/pypy/objspace/flow/model.py
pypy/trunk/pypy/objspace/flow/objspace.py
pypy/trunk/pypy/objspace/flow/operation.py
pypy/trunk/pypy/rpython/rint.py
pypy/trunk/pypy/translator/simplify.py
Log:
move things around in flowspace, to improve dependencies
It also locates more associated functionality in appropiate modules.
Modified: pypy/trunk/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/flowcontext.py (original)
+++ pypy/trunk/pypy/objspace/flow/flowcontext.py Sun Apr 18 01:15:45 2010
@@ -3,18 +3,13 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import pyframe
from pypy.interpreter.argument import ArgumentsForTranslation
+from pypy.objspace.flow import operation
from pypy.objspace.flow.model import *
from pypy.objspace.flow.framestate import FrameState
from pypy.rlib import jit
from pypy.tool.stdlib_opcode import host_bytecode_spec
import sys
-class OperationThatShouldNotBePropagatedError(OperationError):
- pass
-
-class ImplicitOperationError(OperationError):
- pass
-
class StopFlowing(Exception):
pass
@@ -271,13 +266,13 @@
self.crnt_frame = None
self.topframeref = old_frameref
- except OperationThatShouldNotBePropagatedError, e:
+ except operation.OperationThatShouldNotBePropagatedError, e:
raise Exception(
'found an operation that always raises %s: %s' % (
self.space.unwrap(e.w_type).__name__,
self.space.unwrap(e.get_w_value(self.space))))
- except ImplicitOperationError, e:
+ except operation.ImplicitOperationError, e:
if isinstance(e.w_type, Constant):
exc_cls = e.w_type.value
else:
@@ -380,7 +375,7 @@
def sys_exc_info(self):
operr = ExecutionContext.sys_exc_info(self)
- if isinstance(operr, ImplicitOperationError):
+ if isinstance(operr, operation.ImplicitOperationError):
# re-raising an implicit operation makes it an explicit one
w_value = operr.get_w_value(self.space)
operr = OperationError(operr.w_type, w_value)
@@ -491,7 +486,7 @@
def handle_operation_error(self, ec, operr, *args, **kwds):
# see test_propagate_attribute_error for why this is here
- if isinstance(operr, OperationThatShouldNotBePropagatedError):
+ if isinstance(operr, operation.OperationThatShouldNotBePropagatedError):
raise operr
return pyframe.PyFrame.handle_operation_error(self, ec, operr,
*args, **kwds)
Modified: pypy/trunk/pypy/objspace/flow/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/model.py (original)
+++ pypy/trunk/pypy/objspace/flow/model.py Sun Apr 18 01:15:45 2010
@@ -322,6 +322,14 @@
self.concretetype = concretetype
+class UnwrapException(Exception):
+ """Attempted to unwrap a Variable."""
+
+class WrapException(Exception):
+ """Attempted wrapping of a type that cannot sanely appear in flow graph or
+ during its construction"""
+
+
class SpaceOperation(object):
__slots__ = "opname args result offset".split()
Modified: pypy/trunk/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/objspace.py (original)
+++ pypy/trunk/pypy/objspace/flow/objspace.py Sun Apr 18 01:15:45 2010
@@ -6,18 +6,10 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import pyframe
from pypy.objspace.flow.model import *
-from pypy.objspace.flow import flowcontext
-from pypy.objspace.flow.operation import FunctionByName
+from pypy.objspace.flow import flowcontext, operation
from pypy.rlib.unroll import unrolling_iterable, _unroller
from pypy.rlib import rstackovf
-debug = 0
-
-class UnwrapException(Exception):
- "Attempted to unwrap a Variable."
-
-class WrapException(Exception):
- """Attempted wrapping of a type that cannot sanely appear in flow graph or during its construction"""
# method-wrappers have not enough introspection in CPython
if hasattr(complex.real.__get__, 'im_self'):
@@ -25,6 +17,22 @@
else:
type_with_bad_introspection = type(complex.real.__get__)
+# the following gives us easy access to declare more for applications:
+NOT_REALLY_CONST = {
+ Constant(sys): {
+ Constant('maxint'): True,
+ Constant('maxunicode'): True,
+ Constant('api_version'): True,
+ Constant('exit'): True,
+ Constant('exc_info'): True,
+ Constant('getrefcount'): True,
+ Constant('getdefaultencoding'): True,
+ # this is an incomplete list of true constants.
+ # if we add much more, a dedicated class
+ # might be considered for special objects.
+ }
+ }
+
# ______________________________________________________________________
class FlowObjSpace(ObjSpace):
"""NOT_RPYTHON.
@@ -32,7 +40,7 @@
the space operations that the interpreter generates when it interprets
(the bytecode of) some function.
"""
-
+
full_exceptions = False
do_imports_immediately = True
FrameClass = flowcontext.FlowSpaceFrame
@@ -41,7 +49,8 @@
import __builtin__
self.concrete_mode = 1
self.w_None = Constant(None)
- self.builtin = Module(self, Constant('__builtin__'), Constant(__builtin__.__dict__))
+ self.builtin = Module(self, Constant('__builtin__'),
+ Constant(__builtin__.__dict__))
def pick_builtin(w_globals):
return self.builtin
self.builtin.pick_builtin = pick_builtin
@@ -301,7 +310,7 @@
def do_operation_with_implicit_exceptions(self, name, *args_w):
w_result = self.do_operation(name, *args_w)
- self.handle_implicit_exceptions(implicit_exceptions.get(name))
+ self.handle_implicit_exceptions(operation.implicit_exceptions.get(name))
return w_result
def is_true(self, w_obj):
@@ -347,8 +356,8 @@
if outcome is StopIteration:
raise OperationError(self.w_StopIteration, w_exc_value)
elif outcome is RuntimeError:
- raise flowcontext.ImplicitOperationError(Constant(RuntimeError),
- w_exc_value)
+ raise operation.ImplicitOperationError(Constant(RuntimeError),
+ w_exc_value)
else:
return w_item
@@ -404,7 +413,7 @@
# raise SomeError(x)
#
# as shown by test_objspace.test_raise3.
-
+
exceptions = [Exception] # *any* exception by default
if isinstance(w_callable, Constant):
c = w_callable.value
@@ -414,7 +423,7 @@
types.ClassType,
types.TypeType)) and
c.__module__ in ['__builtin__', 'exceptions']):
- exceptions = implicit_exceptions.get(c, None)
+ exceptions = operation.implicit_exceptions.get(c, None)
self.handle_implicit_exceptions(exceptions)
return w_res
@@ -442,8 +451,7 @@
#if outcome is not Exception:
#w_exc_cls = Constant(outcome) Now done by guessexception itself
#pass
- raise flowcontext.ImplicitOperationError(w_exc_cls,
- w_exc_value)
+ raise operation.ImplicitOperationError(w_exc_cls, w_exc_value)
def w_KeyboardInterrupt(self):
# the reason to do this is: if you interrupt the flowing of a function
@@ -458,85 +466,8 @@
raise RuntimeError("the interpreter raises RuntimeError during "
"flow graph construction")
w_RuntimeError = prebuilt_recursion_error = property(w_RuntimeError)
+operation.add_operations(FlowObjSpace)
-# the following gives us easy access to declare more for applications:
-NOT_REALLY_CONST = {
- Constant(sys): {
- Constant('maxint'): True,
- Constant('maxunicode'): True,
- Constant('api_version'): True,
- Constant('exit'): True,
- Constant('exc_info'): True,
- Constant('getrefcount'): True,
- Constant('getdefaultencoding'): True,
- # this is an incomplete list of true constants.
- # if we add much more, a dedicated class
- # might be considered for special objects.
- }
- }
-
-# ______________________________________________________________________
-
-op_appendices = {
- OverflowError: 'ovf',
- IndexError: 'idx',
- KeyError: 'key',
- AttributeError: 'att',
- TypeError: 'typ',
- ZeroDivisionError: 'zer',
- ValueError: 'val',
- }
-
-implicit_exceptions = {
- int: [ValueError], # built-ins that can always raise exceptions
- float: [ValueError],
- chr: [ValueError],
- unichr: [ValueError],
- unicode: [UnicodeDecodeError],
- # specifying IndexError, and KeyError beyond Exception,
- # allows the annotator to be more precise, see test_reraiseAnything/KeyError in
- # the annotator tests
- 'getitem': [IndexError, KeyError, Exception],
- 'setitem': [IndexError, KeyError, Exception],
- 'delitem': [IndexError, KeyError, Exception],
- 'contains': [Exception], # from an r_dict
- }
-
-def _add_exceptions(names, exc):
- for name in names.split():
- lis = implicit_exceptions.setdefault(name, [])
- if exc in lis:
- raise ValueError, "your list is causing duplication!"
- lis.append(exc)
- assert exc in op_appendices
-
-def _add_except_ovf(names):
- # duplicate exceptions and add OverflowError
- for name in names.split():
- lis = implicit_exceptions.setdefault(name, [])[:]
- lis.append(OverflowError)
- implicit_exceptions[name+"_ovf"] = lis
-
-for _name in 'getattr', 'delattr':
- _add_exceptions(_name, AttributeError)
-for _name in 'iter', 'coerce':
- _add_exceptions(_name, TypeError)
-del _name
-
-_add_exceptions("""div mod divmod truediv floordiv pow
- inplace_div inplace_mod inplace_divmod inplace_truediv
- inplace_floordiv inplace_pow""", ZeroDivisionError)
-_add_exceptions("""pow inplace_pow lshift inplace_lshift rshift
- inplace_rshift""", ValueError)
-_add_exceptions("""truediv divmod
- inplace_add inplace_sub inplace_mul inplace_truediv
- inplace_floordiv inplace_div inplace_mod inplace_pow
- inplace_lshift""", OverflowError) # without a _ovf version
-_add_except_ovf("""neg abs add sub mul
- floordiv div mod pow lshift""") # with a _ovf version
-_add_exceptions("""pow""",
- OverflowError) # for the float case
-del _add_exceptions, _add_except_ovf
def extract_cell_content(c):
"""Get the value contained in a CPython 'cell', as read through
@@ -559,127 +490,5 @@
return x.other # crashes if the cell is actually empty
except AttributeError:
raise ValueError("empty cell")
-
-def make_op(name, symbol, arity, specialnames):
- if hasattr(FlowObjSpace, name):
- return # Shouldn't do it
-
- import __builtin__
-
- op = None
- skip = False
- arithmetic = False
-
- if name.startswith('del') or name.startswith('set') or name.startswith('inplace_'):
- # skip potential mutators
- if debug: print "Skip", name
- skip = True
- elif name in ['id', 'hash', 'iter', 'userdel']:
- # skip potential runtime context dependecies
- if debug: print "Skip", name
- skip = True
- elif name in ['repr', 'str']:
- rep = getattr(__builtin__, name)
- def op(obj):
- s = rep(obj)
- if s.find("at 0x") > -1:
- print >>sys.stderr, "Warning: captured address may be awkward"
- return s
- else:
- op = FunctionByName[name]
- arithmetic = (name + '_ovf') in FunctionByName
-
- if not op:
- if not skip:
- if debug: print >> sys.stderr, "XXX missing operator:", name
- else:
- if debug: print "Can constant-fold operation: %s" % name
-
- def generic_operator(self, *args_w):
- assert len(args_w) == arity, name+" got the wrong number of arguments"
- if op:
- args = []
- for w_arg in args_w:
- try:
- arg = self.unwrap_for_computation(w_arg)
- except UnwrapException:
- break
- else:
- args.append(arg)
- else:
- # All arguments are constants: call the operator now
- #print >> sys.stderr, 'Constant operation', op
- try:
- result = op(*args)
- except:
- etype, evalue, etb = sys.exc_info()
- msg = "generated by a constant operation: %s%r" % (
- name, tuple(args))
- raise flowcontext.OperationThatShouldNotBePropagatedError(
- self.wrap(etype), self.wrap(msg))
- else:
- # don't try to constant-fold operations giving a 'long'
- # result. The result is probably meant to be sent to
- # an intmask(), but the 'long' constant confuses the
- # annotator a lot.
- if arithmetic and type(result) is long:
- pass
- # don't constant-fold getslice on lists, either
- elif name == 'getslice' and type(result) is list:
- pass
- # otherwise, fine
- else:
- try:
- return self.wrap(result)
- except WrapException:
- # type cannot sanely appear in flow graph,
- # store operation with variable result instead
- pass
-
- #print >> sys.stderr, 'Variable operation', name, args_w
- w_result = self.do_operation_with_implicit_exceptions(name, *args_w)
- return w_result
-
- setattr(FlowObjSpace, name, generic_operator)
-
-for line in ObjSpace.MethodTable:
- make_op(*line)
-
-"""
-This is just a placeholder for some code I'm checking in elsewhere.
-It is provenly possible to determine constantness of certain expressions
-a little later. I introduced this a bit too early, together with tieing
-this to something being global, which was a bad idea.
-The concept is still valid, and it can be used to force something to
-be evaluated immediately because it is supposed to be a constant.
-One good possible use of this is loop unrolling.
-This will be found in an 'experimental' folder with some use cases.
-"""
-
-def override():
- def getattr(self, w_obj, w_name):
- # handling special things like sys
- # unfortunately this will never vanish with a unique import logic :-(
- if w_obj in self.not_really_const:
- const_w = self.not_really_const[w_obj]
- if w_name not in const_w:
- return self.do_operation_with_implicit_exceptions('getattr', w_obj, w_name)
- return self.regular_getattr(w_obj, w_name)
-
- FlowObjSpace.regular_getattr = FlowObjSpace.getattr
- FlowObjSpace.getattr = getattr
-
- # protect us from globals write access
- def setitem(self, w_obj, w_key, w_val):
- ec = self.getexecutioncontext()
- if not (ec and w_obj is ec.w_globals):
- return self.regular_setitem(w_obj, w_key, w_val)
- raise SyntaxError, "attempt to modify global attribute %r in %r" % (w_key, ec.graph.func)
-
- FlowObjSpace.regular_setitem = FlowObjSpace.setitem
- FlowObjSpace.setitem = setitem
-
-override()
-
# ______________________________________________________________________
# End of objspace.py
Modified: pypy/trunk/pypy/objspace/flow/operation.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/operation.py (original)
+++ pypy/trunk/pypy/objspace/flow/operation.py Sun Apr 18 01:15:45 2010
@@ -2,10 +2,25 @@
This module defines mappings between operation names and Python's
built-in functions (or type constructors) implementing them.
"""
+
+import __builtin__
+import __future__
+import operator
+import types
+import sys
from pypy.interpreter.baseobjspace import ObjSpace
-import operator, types, __future__
+from pypy.interpreter.error import OperationError
from pypy.tool.sourcetools import compile2
from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.objspace.flow import model
+
+
+class OperationThatShouldNotBePropagatedError(OperationError):
+ pass
+
+class ImplicitOperationError(OperationError):
+ pass
+
FunctionByName = {} # dict {"operation_name": <built-in function>}
OperationName = {} # dict {<built-in function>: "operation_name"}
@@ -216,8 +231,6 @@
]
def setup():
- if not hasattr(operator, 'is_'): # Python 2.2
- Table.append(('is_', lambda x, y: x is y))
# insert all operators
for line in ObjSpace.MethodTable:
name = line[0]
@@ -235,4 +248,184 @@
Arity[name] = line[2]
assert name in FunctionByName
setup()
-del Table # INTERNAL ONLY, use the dicts declared at the top of the file
+del Table, setup # INTERNAL ONLY, use the dicts declared at the top of the file
+
+op_appendices = {
+ OverflowError: 'ovf',
+ IndexError: 'idx',
+ KeyError: 'key',
+ AttributeError: 'att',
+ TypeError: 'typ',
+ ZeroDivisionError: 'zer',
+ ValueError: 'val',
+ }
+
+implicit_exceptions = {
+ int: [ValueError], # built-ins that can always raise exceptions
+ float: [ValueError],
+ chr: [ValueError],
+ unichr: [ValueError],
+ unicode: [UnicodeDecodeError],
+ # specifying IndexError, and KeyError beyond Exception,
+ # allows the annotator to be more precise, see test_reraiseAnything/KeyError in
+ # the annotator tests
+ 'getitem': [IndexError, KeyError, Exception],
+ 'setitem': [IndexError, KeyError, Exception],
+ 'delitem': [IndexError, KeyError, Exception],
+ 'contains': [Exception], # from an r_dict
+ }
+
+def _add_exceptions(names, exc):
+ for name in names.split():
+ lis = implicit_exceptions.setdefault(name, [])
+ if exc in lis:
+ raise ValueError, "your list is causing duplication!"
+ lis.append(exc)
+ assert exc in op_appendices
+
+def _add_except_ovf(names):
+ # duplicate exceptions and add OverflowError
+ for name in names.split():
+ lis = implicit_exceptions.setdefault(name, [])[:]
+ lis.append(OverflowError)
+ implicit_exceptions[name+"_ovf"] = lis
+
+for _name in 'getattr', 'delattr':
+ _add_exceptions(_name, AttributeError)
+for _name in 'iter', 'coerce':
+ _add_exceptions(_name, TypeError)
+del _name
+
+_add_exceptions("""div mod divmod truediv floordiv pow
+ inplace_div inplace_mod inplace_divmod inplace_truediv
+ inplace_floordiv inplace_pow""", ZeroDivisionError)
+_add_exceptions("""pow inplace_pow lshift inplace_lshift rshift
+ inplace_rshift""", ValueError)
+_add_exceptions("""truediv divmod
+ inplace_add inplace_sub inplace_mul inplace_truediv
+ inplace_floordiv inplace_div inplace_mod inplace_pow
+ inplace_lshift""", OverflowError) # without a _ovf version
+_add_except_ovf("""neg abs add sub mul
+ floordiv div mod pow lshift""") # with a _ovf version
+_add_exceptions("""pow""",
+ OverflowError) # for the float case
+del _add_exceptions, _add_except_ovf
+
+def make_op(fs, name, symbol, arity, specialnames):
+ if hasattr(fs, name):
+ return
+
+ op = None
+ skip = False
+ arithmetic = False
+
+ if (name.startswith('del') or
+ name.startswith('set') or
+ name.startswith('inplace_')):
+ # skip potential mutators
+ skip = True
+ elif name in ('id', 'hash', 'iter', 'userdel'):
+ # skip potential runtime context dependecies
+ skip = True
+ elif name in ('repr', 'str'):
+ rep = getattr(__builtin__, name)
+ def op(obj):
+ s = rep(obj)
+ if "at 0x" in s:
+ print >>sys.stderr, "Warning: captured address may be awkward"
+ return s
+ else:
+ op = FunctionByName[name]
+ arithmetic = (name + '_ovf') in FunctionByName
+
+ if not op and not skip:
+ raise ValueError("XXX missing operator: %s" % (name,))
+
+ def generic_operator(self, *args_w):
+ assert len(args_w) == arity, name + " got the wrong number of arguments"
+ if op:
+ args = []
+ for w_arg in args_w:
+ try:
+ arg = self.unwrap_for_computation(w_arg)
+ except model.UnwrapException:
+ break
+ else:
+ args.append(arg)
+ else:
+ # All arguments are constants: call the operator now
+ try:
+ result = op(*args)
+ except:
+ etype, evalue, etb = sys.exc_info()
+ msg = "generated by a constant operation: %s%r" % (
+ name, tuple(args))
+ raise OperationThatShouldNotBePropagatedError(
+ self.wrap(etype), self.wrap(msg))
+ else:
+ # don't try to constant-fold operations giving a 'long'
+ # result. The result is probably meant to be sent to
+ # an intmask(), but the 'long' constant confuses the
+ # annotator a lot.
+ if arithmetic and type(result) is long:
+ pass
+ # don't constant-fold getslice on lists, either
+ elif name == 'getslice' and type(result) is list:
+ pass
+ # otherwise, fine
+ else:
+ try:
+ return self.wrap(result)
+ except model.WrapException:
+ # type cannot sanely appear in flow graph,
+ # store operation with variable result instead
+ pass
+ w_result = self.do_operation_with_implicit_exceptions(name, *args_w)
+ return w_result
+
+ setattr(fs, name, generic_operator)
+
+
+"""
+This is just a placeholder for some code I'm checking in elsewhere.
+It is provenly possible to determine constantness of certain expressions
+a little later. I introduced this a bit too early, together with tieing
+this to something being global, which was a bad idea.
+The concept is still valid, and it can be used to force something to
+be evaluated immediately because it is supposed to be a constant.
+One good possible use of this is loop unrolling.
+This will be found in an 'experimental' folder with some use cases.
+"""
+
+def special_overrides(fs):
+ def getattr(self, w_obj, w_name):
+ # handling special things like sys
+ # unfortunately this will never vanish with a unique import logic :-(
+ if w_obj in self.not_really_const:
+ const_w = self.not_really_const[w_obj]
+ if w_name not in const_w:
+ return self.do_operation_with_implicit_exceptions('getattr',
+ w_obj, w_name)
+ return self.regular_getattr(w_obj, w_name)
+
+ fs.regular_getattr = fs.getattr
+ fs.getattr = getattr
+
+ # protect us from globals write access
+ def setitem(self, w_obj, w_key, w_val):
+ ec = self.getexecutioncontext()
+ if not (ec and w_obj is ec.w_globals):
+ return self.regular_setitem(w_obj, w_key, w_val)
+ raise SyntaxError("attempt to modify global attribute %r in %r"
+ % (w_key, ec.graph.func))
+
+ fs.regular_setitem = fs.setitem
+ fs.setitem = setitem
+
+
+def add_operations(fs):
+ """Add function operations to the flow space."""
+ for line in ObjSpace.MethodTable:
+ print line
+ make_op(fs, *line)
+ special_overrides(fs)
Modified: pypy/trunk/pypy/rpython/rint.py
==============================================================================
--- pypy/trunk/pypy/rpython/rint.py (original)
+++ pypy/trunk/pypy/rpython/rint.py Sun Apr 18 01:15:45 2010
@@ -1,7 +1,7 @@
import sys
from pypy.tool.pairtype import pairtype
from pypy.annotation import model as annmodel
-from pypy.objspace.flow.objspace import op_appendices
+from pypy.objspace.flow.operation import op_appendices
from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Bool, Float, \
Void, Char, UniChar, malloc, pyobjectptr, UnsignedLongLong, \
SignedLongLong, build_number, Number, cast_primitive, typeOf
Modified: pypy/trunk/pypy/translator/simplify.py
==============================================================================
--- pypy/trunk/pypy/translator/simplify.py (original)
+++ pypy/trunk/pypy/translator/simplify.py Sun Apr 18 01:15:45 2010
@@ -110,7 +110,7 @@
Instead, it will be replaced by an OP_LSHIFT_OVF operation.
"""
from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
- from pypy.objspace.flow.objspace import implicit_exceptions
+ from pypy.objspace.flow.operation import implicit_exceptions
covf = Constant(ovfcheck)
covfls = Constant(ovfcheck_lshift)
More information about the Pypy-commit
mailing list