[pypy-commit] pypy translation-cleanup: Remove FlowExecutionContext: merge it with FlowSpaceFrame.
rlamy
noreply at buildbot.pypy.org
Thu Sep 20 19:39:06 CEST 2012
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: translation-cleanup
Changeset: r57422:0298c7f450b5
Date: 2012-09-14 19:42 +0100
http://bitbucket.org/pypy/pypy/changeset/0298c7f450b5/
Log: Remove FlowExecutionContext: merge it with FlowSpaceFrame.
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
@@ -83,7 +83,7 @@
def bytecode_trace(self, frame):
pass
- def guessbool(self, ec, w_condition, **kwds):
+ def guessbool(self, frame, w_condition, **kwds):
raise AssertionError, "cannot guessbool(%s)" % (w_condition,)
@@ -120,13 +120,13 @@
# before.
self.last_join_point = frame.getstate()
- def guessbool(self, ec, w_condition):
+ def guessbool(self, frame, w_condition):
block = self.crnt_block
vars = block.getvariables()
links = []
for case in [False, True]:
egg = EggBlock(vars, block, case)
- ec.pendingblocks.append(egg)
+ frame.pendingblocks.append(egg)
link = Link(vars, egg, case)
links.append(link)
@@ -138,7 +138,7 @@
# block.exits[True] = ifLink.
raise StopFlowing
- def guessexception(self, ec, *cases):
+ def guessexception(self, frame, *cases):
block = self.crnt_block
bvars = vars = vars2 = block.getvariables()
links = []
@@ -155,7 +155,7 @@
vars.extend([last_exc, last_exc_value])
vars2.extend([Variable(), Variable()])
egg = EggBlock(vars2, block, case)
- ec.pendingblocks.append(egg)
+ frame.pendingblocks.append(egg)
link = Link(vars, egg, case)
if case is not None:
link.extravars(last_exception=last_exc, last_exc_value=last_exc_value)
@@ -186,14 +186,14 @@
[str(s) for s in self.listtoreplay[self.index:]]))
self.index += 1
- def guessbool(self, ec, w_condition, **kwds):
+ def guessbool(self, frame, w_condition, **kwds):
assert self.index == len(self.listtoreplay)
- ec.recorder = self.nextreplayer
+ frame.recorder = self.nextreplayer
return self.booloutcome
- def guessexception(self, ec, *classes):
+ def guessexception(self, frame, *classes):
assert self.index == len(self.listtoreplay)
- ec.recorder = self.nextreplayer
+ frame.recorder = self.nextreplayer
outcome = self.booloutcome
if outcome is None:
w_exc_cls, w_exc_value = None, None
@@ -206,10 +206,116 @@
# ____________________________________________________________
+class FlowSpaceFrame(pyframe.CPythonFrame):
-class FlowExecutionContext(object):
- def __init__(self, space):
+ def __init__(self, space, func, constargs=None):
+ code = HostCode._from_code(space, func.func_code)
+ self.pycode = code
self.space = space
+ self.w_globals = Constant(func.func_globals)
+ self.locals_stack_w = [None] * (code.co_nlocals + code.co_stacksize)
+ self.valuestackdepth = code.co_nlocals
+ self.lastblock = None
+
+ if func.func_closure is not None:
+ cl = [c.cell_contents for c in func.func_closure]
+ closure = [Cell(Constant(value)) for value in cl]
+ else:
+ closure = []
+ self.initialize_frame_scopes(closure, code)
+ self.f_lineno = code.co_firstlineno
+ 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)
+
+ self.w_locals = None # XXX: only for compatibility with PyFrame
+
+ self.joinpoints = {}
+ self._init_graph(func)
+ self.pendingblocks = collections.deque([self.graph.startblock])
+
+ def initialize_frame_scopes(self, closure, code):
+ if not (code.co_flags & CO_NEWLOCALS):
+ raise ValueError("The code object for a function should have "
+ "the flag CO_NEWLOCALS set.")
+ if len(closure) != len(code.co_freevars):
+ raise ValueError("code object received a closure with "
+ "an unexpected number of free variables")
+ self.cells = [Cell() for _ in code.co_cellvars] + closure
+
+ def _init_graph(self, func):
+ # 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, '_')
+
+ initialblock = SpamBlock(self.getstate())
+ if self.pycode.is_generator:
+ initialblock.operations.append(
+ SpaceOperation('generator_mark', [], Variable()))
+ 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.pycode.signature()
+ graph.defaults = func.func_defaults or ()
+ graph.is_generator = self.pycode.is_generator
+ self.graph = graph
+
+ 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
+ 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 = 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 guessbool(self, w_condition, **kwds):
return self.recorder.guessbool(self, w_condition, **kwds)
@@ -217,21 +323,15 @@
def guessexception(self, *classes):
return self.recorder.guessexception(self, *classes)
- def build_flow(self, func, constargs={}):
- space = self.space
- space.frame = frame = FlowSpaceFrame(self.space, func, constargs)
- self.joinpoints = {}
- self.graph = frame._init_graph(func)
- self.pendingblocks = collections.deque([self.graph.startblock])
-
+ def build_flow(self):
while self.pendingblocks:
block = self.pendingblocks.popleft()
try:
- self.recorder = frame.recording(block)
- frame.frame_finished_execution = False
- next_instr = frame.last_instr
+ self.recorder = self.recording(block)
+ self.frame_finished_execution = False
+ next_instr = self.last_instr
while True:
- next_instr = frame.handle_bytecode(next_instr)
+ next_instr = self.handle_bytecode(next_instr)
except ImplicitOperationError, e:
if isinstance(e.w_type, Constant):
@@ -259,7 +359,7 @@
self.mergeblock(e.block, e.currentstate)
except Return:
- w_result = frame.popvalue()
+ w_result = self.popvalue()
assert w_result is not None
link = Link([w_result], self.graph.returnblock)
self.recorder.crnt_block.closeblock(link)
@@ -311,114 +411,6 @@
operr = OperationError(operr.w_type, w_value)
return operr
-
-class FlowSpaceFrame(pyframe.CPythonFrame):
-
- def __init__(self, space, func, constargs=None):
- code = HostCode._from_code(space, func.func_code)
- self.pycode = code
- self.space = space
- self.w_globals = Constant(func.func_globals)
- self.locals_stack_w = [None] * (code.co_nlocals + code.co_stacksize)
- self.valuestackdepth = code.co_nlocals
- self.lastblock = None
-
- if func.func_closure is not None:
- cl = [c.cell_contents for c in func.func_closure]
- closure = [Cell(Constant(value)) for value in cl]
- else:
- closure = []
- self.initialize_frame_scopes(closure, code)
- self.f_lineno = code.co_firstlineno
- 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)
-
- self.w_locals = None # XXX: only for compatibility with PyFrame
-
- def initialize_frame_scopes(self, closure, code):
- if not (code.co_flags & CO_NEWLOCALS):
- raise ValueError("The code object for a function should have "
- "the flag CO_NEWLOCALS set.")
- if len(closure) != len(code.co_freevars):
- raise ValueError("code object received a closure with "
- "an unexpected number of free variables")
- self.cells = [Cell() for _ in code.co_cellvars] + closure
-
- def _init_graph(self, func):
- # 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, '_')
-
- initialblock = SpamBlock(self.getstate())
- if self.pycode.is_generator:
- initialblock.operations.append(
- SpaceOperation('generator_mark', [], Variable()))
- 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.pycode.signature()
- graph.defaults = func.func_defaults or ()
- graph.is_generator = self.pycode.is_generator
- return graph
-
- 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
- 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 = 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
-
# hack for unrolling iterables, don't use this
def replace_in_stack(self, oldvalue, newvalue):
w_new = Constant(newvalue)
@@ -472,7 +464,7 @@
def enter_bytecode(self, next_instr):
self.last_instr = next_instr
- self.space.executioncontext.recorder.bytecode_trace(self)
+ self.recorder.bytecode_trace(self)
def dispatch_bytecode(self, next_instr):
while True:
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
@@ -8,7 +8,8 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import pyframe, argument
from pypy.objspace.flow.model import *
-from pypy.objspace.flow import flowcontext, operation
+from pypy.objspace.flow import operation
+from pypy.objspace.flow.flowcontext import FlowSpaceFrame, fixeggblocks
from pypy.objspace.flow.specialcase import SPECIAL_CASES
from pypy.rlib.unroll import unrolling_iterable, _unroller
from pypy.rlib import rstackovf, rarithmetic
@@ -46,7 +47,7 @@
"""
full_exceptions = False
- FrameClass = flowcontext.FlowSpaceFrame
+ FrameClass = FlowSpaceFrame
def initialize(self):
self.w_None = Constant(None)
@@ -182,7 +183,7 @@
isinstance(w_obj.value, RequiredClass))
def getexecutioncontext(self):
- return getattr(self, 'executioncontext', None)
+ return self.frame
def exception_match(self, w_exc_type, w_check_class):
try:
@@ -220,21 +221,20 @@
"""
if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
raise Exception, "%r is tagged as NOT_RPYTHON" % (func,)
- ec = flowcontext.FlowExecutionContext(self)
- self.executioncontext = ec
+ frame = self.frame = FlowSpaceFrame(self, func, constargs)
try:
- ec.build_flow(func, constargs)
+ frame.build_flow()
except error.FlowingError, a:
# attach additional source info to AnnotatorError
_, _, tb = sys.exc_info()
- formated = error.format_global_error(ec.graph, self.frame.last_instr,
+ formated = error.format_global_error(frame.graph, self.frame.last_instr,
str(a))
e = error.FlowingError(formated)
raise error.FlowingError, e, tb
- graph = ec.graph
- flowcontext.fixeggblocks(graph)
+ graph = frame.graph
+ fixeggblocks(graph)
checkgraph(graph)
if graph.is_generator and tweak_for_generator:
from pypy.translator.generator import tweak_generator_graph
@@ -269,7 +269,7 @@
def do_operation(self, name, *args_w):
spaceop = SpaceOperation(name, args_w, Variable())
spaceop.offset = self.frame.last_instr
- self.executioncontext.recorder.append(spaceop)
+ self.frame.recorder.append(spaceop)
return spaceop.result
def do_operation_with_implicit_exceptions(self, name, *args_w):
@@ -285,8 +285,7 @@
else:
return bool(obj)
w_truthvalue = self.do_operation('is_true', w_obj)
- context = self.getexecutioncontext()
- return context.guessbool(w_truthvalue)
+ return self.frame.guessbool(w_truthvalue)
def iter(self, w_iterable):
try:
@@ -300,7 +299,7 @@
return w_iter
def next(self, w_iter):
- context = self.getexecutioncontext()
+ frame = self.frame
try:
it = self.unwrap(w_iter)
except UnwrapException:
@@ -312,10 +311,10 @@
except IndexError:
raise OperationError(self.w_StopIteration, self.w_None)
else:
- self.frame.replace_in_stack(it, next_unroller)
+ frame.replace_in_stack(it, next_unroller)
return self.wrap(v)
w_item = self.do_operation("next", w_iter)
- outcome, w_exc_cls, w_exc_value = context.guessexception(StopIteration,
+ outcome, w_exc_cls, w_exc_value = frame.guessexception(StopIteration,
RuntimeError)
if outcome is StopIteration:
raise OperationError(self.w_StopIteration, w_exc_value)
@@ -438,8 +437,7 @@
# exception-raising return block in the flow graph. Note that
# even if the interpreter re-raises the exception, it will not
# be the same ImplicitOperationError instance internally.
- context = self.getexecutioncontext()
- outcome, w_exc_cls, w_exc_value = context.guessexception(*exceptions)
+ outcome, w_exc_cls, w_exc_value = self.frame.guessexception(*exceptions)
if outcome is not None:
# we assume that the caught exc_cls will be exactly the
# one specified by 'outcome', and not a subclass of it,
More information about the pypy-commit
mailing list