[pypy-commit] pypy framestate: Remove all CONTINUE_LOOP/BREAK_LOOP instrs before FlowContext.build_flow() phase
rlamy
noreply at buildbot.pypy.org
Fri Feb 13 14:27:27 CET 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: framestate
Changeset: r75852:26a661c1f513
Date: 2015-02-13 06:44 +0000
http://bitbucket.org/pypy/pypy/changeset/26a661c1f513/
Log: Remove all CONTINUE_LOOP/BREAK_LOOP instrs before
FlowContext.build_flow() phase
diff --git a/rpython/flowspace/bytecode.py b/rpython/flowspace/bytecode.py
--- a/rpython/flowspace/bytecode.py
+++ b/rpython/flowspace/bytecode.py
@@ -202,25 +202,54 @@
def build_flow(self, code):
self.pending_blocks = {}
self.handlerstack = []
- self.blocks = [SimpleBlock([])]
- self.curr_block = self.blocks[0]
+ self.all_handlers = []
+ start_block = self.new_block()
+ self.blocks = [start_block]
+ self.curr_block = start_block
self.needs_new_block = False
- self.graph = graph = BytecodeGraph(self.blocks[0])
+ self.graph = graph = BytecodeGraph(start_block)
for instr in self._iter_instr(code):
instr.bc_flow(self)
+ self.analyze_contexts(graph)
self.analyze_signals(graph)
self.check_graph()
return graph
+ def analyze_contexts(self, graph):
+ start = graph.entry._exits[0]
+ self.pending = [start]
+ start.set_blockstack([])
+ done = set()
+ while self.pending:
+ block = self.pending.pop(0)
+ if block in done:
+ continue
+ self.blockstack = block.blockstack[:]
+ for instr in block:
+ instr.context_effect(self)
+ for child in block._exits:
+ child.set_blockstack(self.blockstack)
+ self.pending.append(child)
+ done.add(block)
+
def analyze_signals(self, graph):
for block in graph.iterblocks():
self.curr_block = block
- block.init_blockstack()
self.blockstack = block.blockstack[:]
for instr in block:
instr.do_signals(self)
- for exit in block._exits:
- exit.set_blockstack(self.blockstack)
+
+ def splice_finally_handler(self, block, context):
+ def copy_block(handler):
+ b = handler.copy()
+ if handler is context.handler_end:
+ instr = b.operations.pop()
+ assert isinstance(instr, END_FINALLY)
+ else:
+ b.set_exits([copy_block(child) for child in handler._exits])
+ self.blocks.append(b)
+ return b
+ block.set_exits([copy_block(context.handler)])
def check_graph(self):
for b in self.blocks:
@@ -315,7 +344,7 @@
def set_blockstack(self, blockstack):
if self.blockstack is None:
- self.blockstack = blockstack
+ self.blockstack = blockstack[:]
else:
assert self.blockstack == blockstack
@@ -342,6 +371,13 @@
if exit:
self.set_exits([exit])
+ def copy(self):
+ block = SimpleBlock(self.operations[:])
+ block.set_exits(self._exits)
+ if self.blockstack is not None:
+ block.blockstack = self.blockstack[:]
+ return block
+
OPNAMES = host_bytecode_spec.method_names
NO_ARG = -1
@@ -361,6 +397,9 @@
reader.end_block()
reader.get_block_at(self.arg)
+ def context_effect(self, reader):
+ pass
+
def do_signals(self, reader):
pass
@@ -538,23 +577,18 @@
from rpython.flowspace.flowcontext import ExceptBlock, FinallyBlock
while reader.blockstack:
context = reader.blockstack.pop()
+ block.operations.append(POP_BLOCK(-1, self.offset))
if isinstance(context, ExceptBlock):
- block.operations.append(POP_BLOCK(-1, self.offset))
+ pass
elif isinstance(context, FinallyBlock):
- block.operations.append(self)
- block.set_exits([context.handler])
- return
+ reader.splice_finally_handler(block, context)
+ block = context.handler_end
else: # LoopBlock
- block.operations.append(POP_BLOCK(-1, self.offset))
block.set_exits([context.handler])
return
raise BytecodeCorruption(
"A break statement should not escape from the function")
- def eval(self, ctx):
- from rpython.flowspace.flowcontext import Break
- return ctx.unroll(Break())
-
@bc_reader.register_opcode
class CONTINUE_LOOP(BCInstruction):
def bc_flow(self, reader):
@@ -572,26 +606,23 @@
if isinstance(context, ExceptBlock):
block.operations.append(POP_BLOCK(-1, self.offset))
elif isinstance(context, FinallyBlock):
- block.operations.append(self)
- block.set_exits([context.handler])
- return
+ block.operations.append(POP_BLOCK(-1, self.offset))
+ reader.splice_finally_handler(block, context)
+ block = context.handler_end
else: # LoopBlock
- block.operations.append(POP_BLOCK(-1, self.offset))
+ reader.blockstack.append(context)
block.set_exits([self.target])
return
raise BytecodeCorruption(
"A continue statement should not escape from the function")
- def eval(self, ctx):
- from rpython.flowspace.flowcontext import Continue
- return ctx.unroll(Continue(self.target))
-
@bc_reader.register_opcode
class END_FINALLY(BCInstruction):
def bc_flow(self, reader):
reader.curr_block.operations.append(self)
signal = reader.handlerstack.pop()
signal.handler_end = reader.curr_block
+ reader.end_block()
def eval(self, ctx):
# unlike CPython, there are two statically distinct cases: the
@@ -629,7 +660,9 @@
self.block.handler = self.target
reader.end_block()
- def do_signals(self, reader):
+ def context_effect(self, reader):
+ self.target.set_blockstack(reader.blockstack)
+ reader.pending.append(self.target)
reader.blockstack.append(self.block)
def eval(self, ctx):
@@ -642,6 +675,7 @@
def bc_flow(self, reader):
SetupInstruction.bc_flow(self, reader)
reader.handlerstack.append(self.block)
+ reader.all_handlers.append(self.block)
def make_block(self, stackdepth):
from rpython.flowspace.flowcontext import ExceptBlock
@@ -658,6 +692,7 @@
def bc_flow(self, reader):
SetupInstruction.bc_flow(self, reader)
reader.handlerstack.append(self.block)
+ reader.all_handlers.append(self.block)
def make_block(self, stackdepth):
from rpython.flowspace.flowcontext import FinallyBlock
@@ -668,6 +703,7 @@
def bc_flow(self, reader):
SetupInstruction.bc_flow(self, reader)
reader.handlerstack.append(self.block)
+ reader.all_handlers.append(self.block)
def make_block(self, stackdepth):
from rpython.flowspace.flowcontext import FinallyBlock
@@ -692,7 +728,7 @@
reader.curr_block.operations.append(self)
reader.end_block()
- def do_signals(self, reader):
+ def context_effect(self, reader):
reader.blockstack.pop()
def eval(self, ctx):
More information about the pypy-commit
mailing list