[pypy-svn] r9655 - pypy/dist/pypy/objspace/flow
arigo at codespeak.net
arigo at codespeak.net
Sat Mar 5 13:51:33 CET 2005
Author: arigo
Date: Sat Mar 5 13:51:33 2005
New Revision: 9655
Modified:
pypy/dist/pypy/objspace/flow/flowcontext.py
pypy/dist/pypy/objspace/flow/objspace.py
pypy/dist/pypy/objspace/flow/specialcase.py
Log:
Partial clean-up of the flow object space. Instead of a set of 'crnt_*'
attributes, the FlowExecutionContext now has a 'recorder' attribute
pointing to a Recorder. The standard BlockRecorder records operations
into a block; the main alternate one is Replayer (which was
ReplayList).
Modified: pypy/dist/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/flowcontext.py (original)
+++ pypy/dist/pypy/objspace/flow/flowcontext.py Sat Mar 5 13:51:33 2005
@@ -16,12 +16,11 @@
Block.__init__(self, framestate.getvariables())
self.framestate = framestate
- def patchframe(self, frame, executioncontext):
+ def patchframe(self, frame):
if self.dead:
raise ExitFrame(None)
self.framestate.restoreframe(frame)
- executioncontext.crnt_block = self
- executioncontext.crnt_ops = self.operations
+ return BlockRecorder(self)
class EggBlock(Block):
@@ -31,30 +30,123 @@
self.prevblock = prevblock
self.booloutcome = booloutcome
- def patchframe(self, frame, executioncontext):
+ 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, executioncontext)
- replaylist = self.operations
+ block.patchframe(frame)
+ recorder = BlockRecorder(self)
prevblock = self
for block in parentblocks:
- replaylist = ReplayList(block.operations,
- prevblock, prevblock.booloutcome,
- replaylist)
+ recorder = Replayer(block, prevblock.booloutcome, recorder)
prevblock = block
- executioncontext.crnt_ops = replaylist
+ return recorder
-class ReplayList:
+# ____________________________________________________________
+
+class Recorder:
+
+ def append(self, operation):
+ raise NotImplementedError
+
+ def bytecode_trace(self, ec, frame):
+ pass
+
+ def guessbool(self, ec, w_condition, **kwds):
+ raise AssertionError, "cannot guessbool(%s)" % (w_condition,)
+
+
+class BlockRecorder(Recorder):
+ # Records all generated operations into a block.
+
+ def __init__(self, block):
+ self.crnt_block = block
+
+ def append(self, operation):
+ self.crnt_block.operations.append(operation)
+
+ def bytecode_trace(self, ec, frame):
+ assert frame is ec.crnt_frame, "seeing an unexpected frame!"
+ next_instr = frame.next_instr
+ ec.crnt_offset = next_instr # save offset for opcode
+ varnames = frame.code.getvarnames()
+ for name, w_value in zip(varnames, frame.getfastscope()):
+ if isinstance(w_value, Variable):
+ w_value.rename(name)
+ if next_instr in ec.joinpoints:
+ currentstate = FrameState(frame)
+ # can 'currentstate' be merged with one of the blocks that
+ # already exist for this bytecode position?
+ for block in ec.joinpoints[next_instr]:
+ newstate = block.framestate.union(currentstate)
+ if newstate is not None:
+ # yes
+ finished = newstate == block.framestate
+ break
+ else:
+ # no
+ newstate = currentstate.copy()
+ finished = False
+ block = None
+
+ if finished:
+ newblock = block
+ else:
+ newblock = SpamBlock(newstate)
+ # unconditionally link the current block to the newblock
+ outputargs = currentstate.getoutputargs(newstate)
+ self.crnt_block.closeblock(Link(outputargs, newblock))
+ # phew
+ if finished:
+ raise ExitFrame(None)
+ if block is not None and block.exits:
+ # to simplify the graph, we patch the old block to point
+ # directly at the new block which is its generalization
+ block.dead = True
+ block.operations = ()
+ block.exitswitch = None
+ outputargs = block.framestate.getoutputargs(newstate)
+ block.recloseblock(Link(outputargs, newblock))
+ ec.recorder = newblock.patchframe(frame)
+ ec.joinpoints[next_instr].insert(0, newblock)
+
+ def guessbool(self, ec, w_condition, cases=[False,True],
+ replace_last_variable_except_in_first_case = None):
+ block = self.crnt_block
+ vars = vars2 = block.getvariables()
+ links = []
+ for case in cases:
+ egg = EggBlock(vars2, block, case)
+ ec.pendingblocks.append(egg)
+ link = Link(vars, egg, case)
+ links.append(link)
+ if replace_last_variable_except_in_first_case is not None:
+ assert block.operations[-1].result is vars[-1]
+ vars = vars[:-1]
+ vars.extend(replace_last_variable_except_in_first_case)
+ vars2 = vars2[:-1]
+ while len(vars2) < len(vars):
+ vars2.append(Variable())
+ replace_last_variable_except_in_first_case = None
+ block.exitswitch = w_condition
+ block.closeblock(*links)
+ # forked the graph. Note that False comes before True by default
+ # in the exits tuple so that (just in case we need it) we
+ # actually have block.exits[False] = elseLink and
+ # block.exits[True] = ifLink.
+ raise ExitFrame(None)
+
+
+class Replayer(Recorder):
- def __init__(self, listtoreplay, nextblock, booloutcome, nextreplaylist):
- self.listtoreplay = listtoreplay
- self.nextblock = nextblock
+ def __init__(self, block, booloutcome, nextreplayer):
+ self.crnt_block = block
+ self.listtoreplay = block.operations
self.booloutcome = booloutcome
- self.nextreplaylist = nextreplaylist
+ self.nextreplayer = nextreplayer
self.index = 0
def append(self, operation):
@@ -67,16 +159,22 @@
[str(s) for s in self.listtoreplay[self.index:]]))
self.index += 1
- def finished(self):
- return self.index == len(self.listtoreplay)
+ def guessbool(self, ec, w_condition, **kwds):
+ assert self.index == len(self.listtoreplay)
+ ec.recorder = self.nextreplayer
+ return self.booloutcome
+
-class ConcreteNoOp:
+class ConcreteNoOp(Recorder):
# In "concrete mode", no SpaceOperations between Variables are allowed.
# Concrete mode is used to precompute lazily-initialized caches,
# when we don't want this precomputation to show up on the flow graph.
def append(self, operation):
raise AssertionError, "concrete mode: cannot perform %s" % operation
+# ____________________________________________________________
+
+
class FlowExecutionContext(ExecutionContext):
def __init__(self, space, code, globals, constargs={}, closure=None,
@@ -109,91 +207,15 @@
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.crnt_ops = []
+ self.recorder = []
return self.code.create_frame(self.space, self.w_globals,
self.closure)
def bytecode_trace(self, frame):
- if not isinstance(self.crnt_ops, list):
- return
- assert frame is self.crnt_frame, "seeing an unexpected frame!"
- next_instr = frame.next_instr
- self.crnt_offset = next_instr # save offset for opcode
- varnames = frame.code.getvarnames()
- for name, w_value in zip(varnames, frame.getfastscope()):
- if isinstance(w_value, Variable):
- w_value.rename(name)
- if next_instr in self.joinpoints:
- currentstate = FrameState(frame)
- # can 'currentstate' be merged with one of the blocks that
- # already exist for this bytecode position?
- for block in self.joinpoints[next_instr]:
- newstate = block.framestate.union(currentstate)
- if newstate is not None:
- # yes
- finished = newstate == block.framestate
- break
- else:
- # no
- newstate = currentstate.copy()
- finished = False
- block = None
-
- if finished:
- newblock = block
- else:
- newblock = SpamBlock(newstate)
- # unconditionally link the current block to the newblock
- outputargs = currentstate.getoutputargs(newstate)
- self.crnt_block.closeblock(Link(outputargs, newblock))
- # phew
- if finished:
- raise ExitFrame(None)
- if block is not None and block.exits:
- # to simplify the graph, we patch the old block to point
- # directly at the new block which is its generalization
- block.dead = True
- block.operations = ()
- block.exitswitch = None
- outputargs = block.framestate.getoutputargs(newstate)
- block.recloseblock(Link(outputargs, newblock))
- newblock.patchframe(frame, self)
- self.joinpoints[next_instr].insert(0, newblock)
+ self.recorder.bytecode_trace(self, frame)
- def guessbool(self, w_condition, cases=[False,True],
- replace_last_variable_except_in_first_case = None):
- if isinstance(self.crnt_ops, list):
- block = self.crnt_block
- vars = vars2 = block.getvariables()
- links = []
- for case in cases:
- egg = EggBlock(vars2, block, case)
- self.pendingblocks.append(egg)
- link = Link(vars, egg, case)
- links.append(link)
- if replace_last_variable_except_in_first_case is not None:
- assert block.operations[-1].result is vars[-1]
- vars = vars[:-1]
- vars.extend(replace_last_variable_except_in_first_case)
- vars2 = vars2[:-1]
- while len(vars2) < len(vars):
- vars2.append(Variable())
- replace_last_variable_except_in_first_case = None
- block.exitswitch = w_condition
- block.closeblock(*links)
- # forked the graph. Note that False comes before True by default
- # in the exits tuple so that (just in case we need it) we
- # actually have block.exits[False] = elseLink and
- # block.exits[True] = ifLink.
- raise ExitFrame(None)
- if isinstance(self.crnt_ops, ReplayList):
- replaylist = self.crnt_ops
- assert replaylist.finished()
- self.crnt_block = replaylist.nextblock
- self.crnt_ops = replaylist.nextreplaylist
- return replaylist.booloutcome
- raise AssertionError, "concrete mode: cannot guessbool(%s)" % (
- w_condition,)
+ def guessbool(self, w_condition, **kwds):
+ return self.recorder.guessbool(self, w_condition, **kwds)
def guessexception(self, *classes):
outcome = self.guessbool(Constant(last_exception, last_exception=True),
@@ -204,7 +226,7 @@
if outcome is None:
w_exc_cls, w_exc_value = None, None
else:
- w_exc_cls, w_exc_value = self.crnt_block.inputargs[-2:]
+ w_exc_cls, w_exc_value = self.recorder.crnt_block.inputargs[-2:]
return outcome, w_exc_cls, w_exc_value
def build_flow(self):
@@ -213,7 +235,7 @@
block = self.pendingblocks.pop(0)
frame = self.create_frame()
try:
- block.patchframe(frame, self)
+ self.recorder = block.patchframe(frame)
except ExitFrame:
continue # restarting a dead SpamBlock
try:
@@ -229,11 +251,12 @@
self.space.unwrap(e.w_value)))
except OperationError, e:
link = Link([e.w_type, e.w_value], self.graph.exceptblock)
- self.crnt_block.closeblock(link)
+ self.recorder.crnt_block.closeblock(link)
else:
if w_result is not None:
link = Link([w_result], self.graph.returnblock)
- self.crnt_block.closeblock(link)
+ self.recorder.crnt_block.closeblock(link)
+ del self.recorder
self.fixeggblocks()
def fixeggblocks(self):
Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py (original)
+++ pypy/dist/pypy/objspace/flow/objspace.py Sat Mar 5 13:51:33 2005
@@ -62,13 +62,13 @@
# "concrete mode". In this mode, only Constants are allowed
# and no SpaceOperation is recorded.
def my_builder(key, stuff):
- previous_ops = self.executioncontext.crnt_ops
- self.executioncontext.crnt_ops = flowcontext.ConcreteNoOp()
+ previous_recorder = self.executioncontext.recorder
+ self.executioncontext.recorder = flowcontext.ConcreteNoOp()
self.concrete_mode += 1
try:
return builder(key, stuff)
finally:
- self.executioncontext.crnt_ops = previous_ops
+ self.executioncontext.recorder = previous_recorder
self.concrete_mode -= 1
return super(FlowObjSpace, self).loadfromcache(key, my_builder, cache)
@@ -163,7 +163,7 @@
specialcase.setup(self)
def exception_match(self, w_exc_type, w_check_class):
- self.executioncontext.crnt_block.exc_handler = True
+ self.executioncontext.recorder.crnt_block.exc_handler = True
return ObjSpace.exception_match(self, w_exc_type, w_check_class)
@@ -243,7 +243,7 @@
spaceop = SpaceOperation(name, args_w, Variable())
if hasattr(self, 'executioncontext'): # not here during bootstrapping
spaceop.offset = self.executioncontext.crnt_offset
- self.executioncontext.crnt_ops.append(spaceop)
+ self.executioncontext.recorder.append(spaceop)
return spaceop.result
def is_true(self, w_obj):
Modified: pypy/dist/pypy/objspace/flow/specialcase.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/specialcase.py (original)
+++ pypy/dist/pypy/objspace/flow/specialcase.py Sat Mar 5 13:51:33 2005
@@ -55,8 +55,9 @@
# Normally, Instance should have been created by the previous operation
# which should be a simple_call(<Class>, ...).
# Fetch the <Class> out of there. (This doesn't work while replaying)
- if space.executioncontext.crnt_ops:
- spaceop = space.executioncontext.crnt_ops[-1]
+ operations = space.executioncontext.recorder.crnt_block.operations
+ if operations:
+ spaceop = operations[-1]
if (spaceop.opname == 'simple_call' and
spaceop.result is w_arg1):
w_type = spaceop.args[0]
More information about the Pypy-commit
mailing list