[pypy-commit] pypy default: Merged in rlamy/pypy/translation-cleanup (pull request #82)
arigo
noreply at buildbot.pypy.org
Fri Aug 10 10:03:35 CEST 2012
Author: arigo <armin.rigo at gmail.com>
Branch:
Changeset: r56681:1ed8b5b0ecb6
Date: 2012-08-10 10:02 +0200
http://bitbucket.org/pypy/pypy/changeset/1ed8b5b0ecb6/
Log: Merged in rlamy/pypy/translation-cleanup (pull request #82)
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -4,10 +4,12 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import pyframe, nestedscope
from pypy.interpreter.argument import ArgumentsForTranslation
+from pypy.interpreter.astcompiler.consts import CO_GENERATOR
+from pypy.interpreter.pycode import PyCode, cpython_code_signature
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.objspace.flow.framestate import (FrameState, recursively_unflatten,
+ recursively_flatten)
from pypy.tool.stdlib_opcode import host_bytecode_spec
class StopFlowing(Exception):
@@ -28,13 +30,6 @@
self.framestate = framestate
self.dead = False
- def patchframe(self, frame):
- if self.dead:
- raise StopFlowing
- self.framestate.restoreframe(frame)
- return BlockRecorder(self)
-
-
class EggBlock(Block):
# make slots optional, for debugging
if hasattr(Block, '__slots__'):
@@ -45,21 +40,6 @@
self.prevblock = prevblock
self.booloutcome = booloutcome
- def patchframe(self, frame):
- parentblocks = []
- block = self
- while isinstance(block, EggBlock):
- block = block.prevblock
- parentblocks.append(block)
- # parentblocks = [Egg, Egg, ..., Egg, Spam] not including self
- block.patchframe(frame)
- recorder = BlockRecorder(self)
- prevblock = self
- for block in parentblocks:
- recorder = Replayer(block, prevblock.booloutcome, recorder)
- prevblock = block
- return recorder
-
def extravars(self, last_exception=None, last_exc_value=None):
self.last_exception = last_exception
@@ -93,7 +73,6 @@
self.crnt_block.operations.append(operation)
def bytecode_trace(self, ec, frame):
- assert frame is ec.crnt_frame, "seeing an unexpected frame!"
ec.crnt_offset = frame.last_instr # save offset for opcode
if self.enterspamblock:
# If we have a SpamBlock, the first call to bytecode_trace()
@@ -110,7 +89,7 @@
# the same block. We will continue, to figure out where the next
# such operation *would* appear, and we make a join point just
# before.
- self.last_join_point = FrameState(frame)
+ self.last_join_point = frame.getstate()
def guessbool(self, ec, w_condition, cases=[False,True],
replace_last_variable_except_in_first_case = None):
@@ -184,43 +163,24 @@
class FlowExecutionContext(ExecutionContext):
- def __init__(self, space, code, globals, constargs={}, outer_func=None,
- name=None, is_generator=False):
- ExecutionContext.__init__(self, space)
- self.code = code
-
- self.w_globals = w_globals = space.wrap(globals)
-
- self.crnt_offset = -1
- self.crnt_frame = None
- if outer_func and outer_func.closure:
- self.closure = [nestedscope.Cell(Constant(value))
- for value in outer_func.closure]
- else:
- self.closure = None
- frame = self.create_frame()
- formalargcount = code.getformalargcount()
- arg_list = [Variable() for i in range(formalargcount)]
- for position, value in constargs.items():
- arg_list[position] = Constant(value)
- frame.setfastscope(arg_list)
- self.joinpoints = {}
- initialblock = SpamBlock(FrameState(frame).copy())
- self.pendingblocks = collections.deque([initialblock])
- self.graph = FunctionGraph(name or code.co_name, initialblock)
- self.is_generator = is_generator
+ def _init_graph(self, func, initialblock):
+ # CallableFactory.pycall may add class_ to functions that are methods
+ name = func.func_name
+ class_ = getattr(func, 'class_', None)
+ if class_ is not None:
+ name = '%s.%s' % (class_.__name__, name)
+ for c in "<>&!":
+ name = name.replace(c, '_')
+ self.graph = graph = FunctionGraph(name, initialblock)
+ graph.func = func
+ # attach a signature and defaults to the graph
+ # so that it becomes even more interchangeable with the function
+ # itself
+ graph.signature = self.code.signature()
+ graph.defaults = func.func_defaults or ()
make_link = Link # overridable for transition tracking
- def create_frame(self):
- # create an empty frame suitable for the code object
- # while ignoring any operation like the creation of the locals dict
- self.recorder = []
- frame = FlowSpaceFrame(self.space, self.code,
- self.w_globals, self)
- frame.last_instr = 0
- return frame
-
def bytecode_trace(self, frame):
self.recorder.bytecode_trace(self, frame)
@@ -247,33 +207,40 @@
w_exc_cls = egg.last_exception
return outcome, w_exc_cls, w_exc_value
- def build_flow(self):
+ def build_flow(self, func, constargs={}):
+ space = self.space
+ code = PyCode._from_code(space, func.func_code)
+ self.is_generator = bool(code.co_flags & CO_GENERATOR)
+ self.code = code
+
+ self.crnt_offset = -1
+ self.frame = frame = FlowSpaceFrame(self.space, code,
+ func, constargs)
+ self.joinpoints = {}
+ initialblock = SpamBlock(frame.getstate())
+ self.pendingblocks = collections.deque([initialblock])
+ self._init_graph(func, initialblock)
+
if self.is_generator:
- self.produce_generator_mark()
+ initialblock.operations.append(
+ SpaceOperation('generator_mark', [], Variable()))
+
while self.pendingblocks:
block = self.pendingblocks.popleft()
- frame = self.create_frame()
try:
- self.recorder = block.patchframe(frame)
+ self.recorder = frame.recording(block)
except StopFlowing:
continue # restarting a dead SpamBlock
try:
- old_frameref = self.topframeref
- self.topframeref = jit.non_virtual_ref(frame)
- self.crnt_frame = frame
- try:
- frame.frame_finished_execution = False
- while True:
- w_result = frame.dispatch(frame.pycode,
- frame.last_instr,
- self)
- if frame.frame_finished_execution:
- break
- else:
- self.generate_yield(frame, w_result)
- finally:
- self.crnt_frame = None
- self.topframeref = old_frameref
+ frame.frame_finished_execution = False
+ while True:
+ w_result = frame.dispatch(frame.pycode,
+ frame.last_instr,
+ self)
+ if frame.frame_finished_execution:
+ break
+ else:
+ self.generate_yield(frame, w_result)
except operation.OperationThatShouldNotBePropagatedError, e:
raise Exception(
@@ -316,11 +283,6 @@
del self.recorder
self.fixeggblocks()
- def produce_generator_mark(self):
- [initialblock] = self.pendingblocks
- initialblock.operations.append(
- SpaceOperation('generator_mark', [], Variable()))
-
def generate_yield(self, frame, w_result):
assert self.is_generator
self.recorder.crnt_block.operations.append(
@@ -408,7 +370,7 @@
# hack for unrolling iterables, don't use this
def replace_in_stack(self, oldvalue, newvalue):
w_new = Constant(newvalue)
- f = self.crnt_frame
+ f = self.frame
stack_items_w = f.locals_stack_w
for i in range(f.valuestackdepth-1, f.pycode.co_nlocals-1, -1):
w_v = stack_items_w[i]
@@ -421,6 +383,71 @@
class FlowSpaceFrame(pyframe.CPythonFrame):
+ def __init__(self, space, code, func, constargs=None):
+ w_globals = Constant(func.func_globals)
+ class outerfunc: pass # hack
+ if func.func_closure is not None:
+ cl = [c.cell_contents for c in func.func_closure]
+ outerfunc.closure = [nestedscope.Cell(Constant(value)) for value in cl]
+ else:
+ outerfunc.closure = None
+ super(FlowSpaceFrame, self).__init__(space, code, w_globals, outerfunc)
+ self.last_instr = 0
+
+ if constargs is None:
+ constargs = {}
+ formalargcount = code.getformalargcount()
+ arg_list = [Variable() for i in range(formalargcount)]
+ for position, value in constargs.items():
+ arg_list[position] = Constant(value)
+ self.setfastscope(arg_list)
+
+ def getstate(self):
+ # getfastscope() can return real None, for undefined locals
+ data = self.save_locals_stack()
+ if self.last_exception is None:
+ data.append(Constant(None))
+ data.append(Constant(None))
+ else:
+ data.append(self.last_exception.w_type)
+ data.append(self.last_exception.get_w_value(self.space))
+ recursively_flatten(self.space, data)
+ nonmergeable = (self.get_blocklist(),
+ self.last_instr, # == next_instr when between bytecodes
+ self.w_locals,)
+ return FrameState(data, nonmergeable)
+
+ def setstate(self, state):
+ """ Reset the frame to the given state. """
+ data = state.mergeable[:]
+ recursively_unflatten(self.space, data)
+ self.restore_locals_stack(data[:-2]) # Nones == undefined locals
+ if data[-2] == Constant(None):
+ assert data[-1] == Constant(None)
+ self.last_exception = None
+ else:
+ self.last_exception = OperationError(data[-2], data[-1])
+ blocklist, self.last_instr, self.w_locals = state.nonmergeable
+ self.set_blocklist(blocklist)
+
+ def recording(self, block):
+ """ Setup recording of the block and return the recorder. """
+ parentblocks = []
+ parent = block
+ while isinstance(parent, EggBlock):
+ parent = parent.prevblock
+ parentblocks.append(parent)
+ # parentblocks = [Egg, Egg, ..., Egg, Spam] not including block
+ if parent.dead:
+ raise StopFlowing
+ self.setstate(parent.framestate)
+ recorder = BlockRecorder(block)
+ prevblock = block
+ for parent in parentblocks:
+ recorder = Replayer(parent, prevblock.booloutcome, recorder)
+ prevblock = parent
+ return recorder
+
def SETUP_WITH(self, offsettoend, next_instr):
# A simpler version than the 'real' 2.7 one:
# directly call manager.__enter__(), don't use special lookup functions
diff --git a/pypy/objspace/flow/framestate.py b/pypy/objspace/flow/framestate.py
--- a/pypy/objspace/flow/framestate.py
+++ b/pypy/objspace/flow/framestate.py
@@ -1,59 +1,16 @@
-from pypy.interpreter.pyframe import PyFrame
from pypy.interpreter.pyopcode import SuspendedUnroller
-from pypy.interpreter.error import OperationError
from pypy.rlib.unroll import SpecTag
from pypy.objspace.flow.model import *
class FrameState:
- # XXX this class depends on the internal state of PyFrame objects
-
- def __init__(self, state):
- if isinstance(state, PyFrame):
- # getfastscope() can return real None, for undefined locals
- data = state.save_locals_stack()
- if state.last_exception is None:
- data.append(Constant(None))
- data.append(Constant(None))
- else:
- data.append(state.last_exception.w_type)
- data.append(state.last_exception.get_w_value(state.space))
- recursively_flatten(state.space, data)
- self.mergeable = data
- self.nonmergeable = (
- state.get_blocklist(),
- state.last_instr, # == next_instr when between bytecodes
- state.w_locals,
- )
- elif isinstance(state, tuple):
- self.mergeable, self.nonmergeable = state
- else:
- raise TypeError("can't get framestate for %r" %
- state.__class__.__name__)
+ def __init__(self, mergeable, nonmergeable):
+ self.mergeable = mergeable
+ self.nonmergeable = nonmergeable
self.next_instr = self.nonmergeable[1]
for w1 in self.mergeable:
assert isinstance(w1, (Variable, Constant)) or w1 is None, (
'%r found in frame state' % w1)
- def restoreframe(self, frame):
- if isinstance(frame, PyFrame):
- data = self.mergeable[:]
- recursively_unflatten(frame.space, data)
- frame.restore_locals_stack(data[:-2]) # Nones == undefined locals
- if data[-2] == Constant(None):
- assert data[-1] == Constant(None)
- frame.last_exception = None
- else:
- frame.last_exception = OperationError(data[-2], data[-1])
- (
- blocklist,
- frame.last_instr,
- frame.w_locals,
- ) = self.nonmergeable
- frame.set_blocklist(blocklist)
- else:
- raise TypeError("can't set framestate for %r" %
- frame.__class__.__name__)
-
def copy(self):
"Make a copy of this state in which all Variables are fresh."
newstate = []
@@ -61,7 +18,7 @@
if isinstance(w, Variable):
w = Variable()
newstate.append(w)
- return FrameState((newstate, self.nonmergeable))
+ return FrameState(newstate, self.nonmergeable)
def getvariables(self):
return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -94,7 +51,7 @@
newstate.append(union(w1, w2))
except UnionError:
return None
- return FrameState((newstate, self.nonmergeable))
+ return FrameState(newstate, self.nonmergeable)
def getoutputargs(self, targetstate):
"Return the output arguments needed to link self to targetstate."
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -5,13 +5,12 @@
import types
from pypy.tool import error
from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
-from pypy.interpreter.pycode import PyCode, cpython_code_signature
from pypy.interpreter.module import Module
from pypy.interpreter.error import OperationError
-from pypy.interpreter.astcompiler.consts import CO_GENERATOR
from pypy.interpreter import pyframe, argument
from pypy.objspace.flow.model import *
-from pypy.objspace.flow import flowcontext, operation, specialcase
+from pypy.objspace.flow import flowcontext, operation
+from pypy.objspace.flow.specialcase import SPECIAL_CASES
from pypy.rlib.unroll import unrolling_iterable, _unroller
from pypy.rlib import rstackovf, rarithmetic
from pypy.rlib.rarithmetic import is_valid_int
@@ -76,7 +75,7 @@
for exc in [NameError, UnboundLocalError]:
clsname = exc.__name__
setattr(self, 'w_'+clsname, None)
- self.specialcases = {}
+ self.specialcases = SPECIAL_CASES.copy()
#self.make_builtins()
#self.make_sys()
# w_str is needed because cmp_exc_match of frames checks against it,
@@ -162,7 +161,7 @@
if type(val) is not str:
raise TypeError("expected string: " + repr(w_obj))
return val
- return self.unwrap(w_obj)
+ return self.unwrap(w_obj)
def float_w(self, w_obj):
if isinstance(w_obj, Constant):
@@ -220,10 +219,6 @@
# because it is done each time a FlowExecutionContext is built
return None
- def setup_executioncontext(self, ec):
- self.executioncontext = ec
- specialcase.setup(self)
-
def exception_match(self, w_exc_type, w_check_class):
try:
check_class = self.unwrap(w_check_class)
@@ -260,36 +255,11 @@
"""
if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
raise Exception, "%r is tagged as NOT_RPYTHON" % (func,)
- code = func.func_code
- is_generator = bool(code.co_flags & CO_GENERATOR)
- code = PyCode._from_code(self, code)
- if func.func_closure is None:
- cl = None
- else:
- cl = [extract_cell_content(c) for c in func.func_closure]
- # CallableFactory.pycall may add class_ to functions that are methods
- name = func.func_name
- class_ = getattr(func, 'class_', None)
- if class_ is not None:
- name = '%s.%s' % (class_.__name__, name)
- for c in "<>&!":
- name = name.replace(c, '_')
- class outerfunc: # hack
- closure = cl
- ec = flowcontext.FlowExecutionContext(self, code, func.func_globals,
- constargs, outerfunc, name,
- is_generator)
- graph = ec.graph
- graph.func = func
- # attach a signature and defaults to the graph
- # so that it becomes even more interchangeable with the function
- # itself
- graph.signature = cpython_code_signature(code)
- graph.defaults = func.func_defaults or ()
- self.setup_executioncontext(ec)
+ ec = flowcontext.FlowExecutionContext(self)
+ self.executioncontext = ec
try:
- ec.build_flow()
+ ec.build_flow(func, constargs)
except error.FlowingError, a:
# attach additional source info to AnnotatorError
_, _, tb = sys.exc_info()
@@ -297,12 +267,12 @@
str(a))
e = error.FlowingError(formated)
raise error.FlowingError, e, tb
+
+ graph = ec.graph
checkgraph(graph)
- #
- if is_generator and tweak_for_generator:
+ if ec.is_generator and tweak_for_generator:
from pypy.translator.generator import tweak_generator_graph
tweak_generator_graph(graph)
- #
return graph
def fixedview(self, w_tuple, expected_length=None):
@@ -325,7 +295,7 @@
e = OperationError(self.w_ValueError, self.w_None)
e.normalize_exception(self)
raise e
- return [self.do_operation('getitem', w_iterable, self.wrap(i))
+ return [self.do_operation('getitem', w_iterable, self.wrap(i))
for i in range(expected_length)]
return ObjSpace.unpackiterable(self, w_iterable, expected_length)
@@ -391,6 +361,11 @@
return w_item
def setitem(self, w_obj, w_key, w_val):
+ # protect us from globals write access
+ ec = self.getexecutioncontext()
+ if ec and w_obj is ec.frame.w_globals:
+ raise SyntaxError("attempt to modify global attribute %r in %r"
+ % (w_key, ec.graph.func))
if self.concrete_mode:
try:
obj = self.unwrap_for_computation(w_obj)
@@ -400,9 +375,38 @@
return self.w_None
except UnwrapException:
pass
- return self.do_operation_with_implicit_exceptions('setitem', w_obj,
+ return self.do_operation_with_implicit_exceptions('setitem', w_obj,
w_key, w_val)
+ 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)
+ try:
+ obj = self.unwrap_for_computation(w_obj)
+ name = self.unwrap_for_computation(w_name)
+ except UnwrapException:
+ pass
+ else:
+ try:
+ result = getattr(obj, name)
+ except Exception, e:
+ etype = e.__class__
+ msg = "generated by a constant operation:\n\t%s%r" % (
+ 'getattr', (obj, name))
+ raise operation.OperationThatShouldNotBePropagatedError(
+ self.wrap(etype), self.wrap(msg))
+ try:
+ return self.wrap(result)
+ except WrapException:
+ pass
+ return self.do_operation_with_implicit_exceptions('getattr',
+ w_obj, w_name)
+
def call_function(self, w_func, *args_w):
nargs = len(args_w)
args = argument.ArgumentsForTranslation(self, list(args_w))
@@ -487,28 +491,3 @@
"flow graph construction")
w_RuntimeError = prebuilt_recursion_error = property(w_RuntimeError)
operation.add_operations(FlowObjSpace)
-
-
-def extract_cell_content(c):
- """Get the value contained in a CPython 'cell', as read through
- the func_closure of a function object."""
- try:
- # This is simple on 2.5
- return getattr(c, "cell_contents")
- except AttributeError:
- class X(object):
- def __cmp__(self, other):
- self.other = other
- return 0
- def __eq__(self, other):
- self.other = other
- return True
- x = X()
- x_cell, = (lambda: x).func_closure
- x_cell == c
- try:
- return x.other # crashes if the cell is actually empty
- except AttributeError:
- raise ValueError("empty cell")
-# ______________________________________________________________________
-# End of objspace.py
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -378,45 +378,7 @@
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:
make_op(fs, *line)
- special_overrides(fs)
diff --git a/pypy/objspace/flow/specialcase.py b/pypy/objspace/flow/specialcase.py
--- a/pypy/objspace/flow/specialcase.py
+++ b/pypy/objspace/flow/specialcase.py
@@ -19,7 +19,7 @@
if len(args_w) > 2:
w_loc = args_w[2]
if len(args_w) > 3:
- w_frm = args_w[3]
+ w_frm = args_w[3]
if not isinstance(w_loc, Constant):
# import * in a function gives us the locals as Variable
# we always forbid it as a SyntaxError
@@ -89,6 +89,9 @@
# _________________________________________________________________________
def sc_r_uint(space, r_uint, args):
+ # special case to constant-fold r_uint(32-bit-constant)
+ # (normally, the 32-bit constant is a long, and is not allowed to
+ # show up in the flow graphs at all)
args_w, kwds_w = args.unpack()
assert not kwds_w
[w_value] = args_w
@@ -99,20 +102,8 @@
def sc_we_are_translated(space, we_are_translated, args):
return Constant(True)
-def setup(space):
- # fn = pyframe.normalize_exception.get_function(space)
- # this is now routed through the objspace, directly.
- # space.specialcases[fn] = sc_normalize_exception
- space.specialcases[__import__] = sc_import
- # redirect ApplevelClass for print et al.
- space.specialcases[ApplevelClass] = sc_applevel
- # turn calls to built-in functions to the corresponding operation,
- # if possible
- for fn in OperationName:
- space.specialcases[fn] = sc_operator
- # special case to constant-fold r_uint(32-bit-constant)
- # (normally, the 32-bit constant is a long, and is not allowed to
- # show up in the flow graphs at all)
- space.specialcases[r_uint] = sc_r_uint
- # special case we_are_translated() to return True
- space.specialcases[we_are_translated] = sc_we_are_translated
+SPECIAL_CASES = {__import__: sc_import, ApplevelClass: sc_applevel,
+ r_uint: sc_r_uint, we_are_translated: sc_we_are_translated}
+for fn in OperationName:
+ SPECIAL_CASES[fn] = sc_operator
+
diff --git a/pypy/objspace/flow/test/test_framestate.py b/pypy/objspace/flow/test/test_framestate.py
--- a/pypy/objspace/flow/test/test_framestate.py
+++ b/pypy/objspace/flow/test/test_framestate.py
@@ -1,14 +1,13 @@
-
-
from py.test import raises
from pypy.objspace.flow.model import *
-from pypy.objspace.flow.framestate import *
from pypy.interpreter.pycode import PyCode
+from pypy.rlib.unroll import SpecTag
from pypy.objspace.flow.objspace import FlowObjSpace
+from pypy.objspace.flow.flowcontext import FlowSpaceFrame
class TestFrameState:
def setup_class(cls):
- cls.space = FlowObjSpace()
+ cls.space = FlowObjSpace()
def getframe(self, func):
space = self.space
@@ -18,15 +17,9 @@
pass
code = func.func_code
code = PyCode._from_code(self.space, code)
- w_globals = Constant({}) # space.newdict()
- frame = self.space.createframe(code, w_globals)
-
- formalargcount = code.getformalargcount()
- dummy = Constant(None)
- #dummy.dummy = True
- arg_list = ([Variable() for i in range(formalargcount)] +
- [dummy] * (frame.pycode.co_nlocals - formalargcount))
- frame.setfastscope(arg_list)
+ frame = FlowSpaceFrame(space, code, func)
+ # hack the frame
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(None)
return frame
def func_simple(x):
@@ -35,55 +28,55 @@
def test_eq_framestate(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
- fs2 = FrameState(frame)
+ fs1 = frame.getstate()
+ fs2 = frame.getstate()
assert fs1 == fs2
def test_neq_hacked_framestate(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1 != fs2
def test_union_on_equal_framestates(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
- fs2 = FrameState(frame)
+ fs1 = frame.getstate()
+ fs2 = frame.getstate()
assert fs1.union(fs2) == fs1
def test_union_on_hacked_framestates(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1.union(fs2) == fs2 # fs2 is more general
assert fs2.union(fs1) == fs2 # fs2 is more general
def test_restore_frame(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs1.restoreframe(frame)
- assert fs1 == FrameState(frame)
+ frame.setstate(fs1)
+ assert fs1 == frame.getstate()
def test_copy(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
fs2 = fs1.copy()
assert fs1 == fs2
def test_getvariables(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
vars = fs1.getvariables()
- assert len(vars) == 1
+ assert len(vars) == 1
def test_getoutputargs(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
outputargs = fs1.getoutputargs(fs2)
# 'x' -> 'x' is a Variable
# locals_w[n-1] -> locals_w[n-1] is Constant(None)
@@ -91,17 +84,17 @@
def test_union_different_constants(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(42)
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
fs3 = fs1.union(fs2)
- fs3.restoreframe(frame)
+ frame.setstate(fs3)
assert isinstance(frame.locals_stack_w[frame.pycode.co_nlocals-1],
Variable) # generalized
def test_union_spectag(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(SpecTag())
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1.union(fs2) is None # UnionError
diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -32,8 +32,8 @@
if conftest.option.view:
graph.show()
- def setup_class(cls):
- cls.space = FlowObjSpace()
+ def setup_class(cls):
+ cls.space = FlowObjSpace()
def all_operations(self, graph):
result = {}
@@ -77,7 +77,7 @@
if i < 0:
i = j
return user_defined_function(i) + 1
-
+
def test_ifthenelse(self):
x = self.codetest(self.ifthenelse)
@@ -96,7 +96,7 @@
#__________________________________________________________
def print_(i):
print i
-
+
def test_print(self):
x = self.codetest(self.print_)
@@ -124,7 +124,7 @@
if i:
i = 5
return i
-
+
def test_union_hard(self):
x = self.codetest(self.union_hard)
@@ -135,7 +135,7 @@
total += i
i = i - 1
return total
-
+
def test_while_union(self):
x = self.codetest(self.while_union)
@@ -145,7 +145,7 @@
for i in lst:
total += i
return total
-
+
def test_simple_for(self):
x = self.codetest(self.simple_for)
@@ -311,7 +311,7 @@
else:
found[link.exitcase] = None
assert found == {IndexError: True, KeyError: True, Exception: None}
-
+
def reraiseAnything(x):
try:
pow(x, 5)
@@ -354,7 +354,7 @@
#__________________________________________________________
def raise1(msg):
raise IndexError
-
+
def test_raise1(self):
x = self.codetest(self.raise1)
simplify_graph(x)
@@ -371,7 +371,7 @@
#__________________________________________________________
def raise2(msg):
raise IndexError, msg
-
+
def test_raise2(self):
x = self.codetest(self.raise2)
# XXX can't check the shape of the graph, too complicated...
@@ -379,7 +379,7 @@
#__________________________________________________________
def raise3(msg):
raise IndexError(msg)
-
+
def test_raise3(self):
x = self.codetest(self.raise3)
# XXX can't check the shape of the graph, too complicated...
@@ -387,7 +387,7 @@
#__________________________________________________________
def raise4(stuff):
raise stuff
-
+
def test_raise4(self):
x = self.codetest(self.raise4)
@@ -405,7 +405,7 @@
except IndexError:
return -1
return 0
-
+
def test_raise_and_catch_1(self):
x = self.codetest(self.raise_and_catch_1)
@@ -416,7 +416,7 @@
except IndexError:
return -1
return 0
-
+
def test_catch_simple_call(self):
x = self.codetest(self.catch_simple_call)
@@ -427,7 +427,7 @@
except (IndexError, OSError):
return -1
return 0
-
+
def test_multiple_catch_simple_call(self):
graph = self.codetest(self.multiple_catch_simple_call)
simplify_graph(graph)
@@ -447,7 +447,7 @@
del x
for i in range(10):
pass
-
+
def test_dellocal(self):
x = self.codetest(self.dellocal)
@@ -456,7 +456,7 @@
x = DATA['x']
z = DATA[name]
return x, z
-
+
def test_globalconstdict(self):
x = self.codetest(self.globalconstdict)
@@ -464,12 +464,12 @@
def dictliteral(name):
x = {'x': 1}
return x
-
+
def test_dictliteral(self):
x = self.codetest(self.dictliteral)
#__________________________________________________________
-
+
def specialcases(x):
operator.lt(x,3)
operator.le(x,3)
@@ -488,7 +488,7 @@
# the following ones are constant-folded
operator.eq(2,3)
operator.__gt__(2,3)
-
+
def test_specialcases(self):
x = self.codetest(self.specialcases)
from pypy.translator.simplify import join_blocks
@@ -765,7 +765,7 @@
raise
graph = self.codetest(f)
simplify_graph(graph)
- assert self.all_operations(graph) == {'getitem_idx': 1}
+ assert self.all_operations(graph) == {'getitem_idx': 1}
def f(c, x):
try:
@@ -775,7 +775,7 @@
graph = self.codetest(f)
simplify_graph(graph)
assert self.all_operations(graph) == {'getitem_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -794,7 +794,7 @@
simplify_graph(graph)
self.show(graph)
assert self.all_operations(graph) == {'getitem_idx_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -812,7 +812,7 @@
graph = self.codetest(f)
simplify_graph(graph)
assert self.all_operations(graph) == {'getitem_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -1004,14 +1004,3 @@
def user_defined_function():
pass
-
-
-def test_extract_cell_content():
- class Strange(object):
- def __cmp__(self, other):
- assert False, "should not be called"
- strange = Strange()
- def f():
- return strange
- res = objspace.extract_cell_content(f.func_closure[0])
- assert res is strange
More information about the pypy-commit
mailing list