|
@@ -39,6 +39,11 @@ class FlowGraphComponent(object):
|
|
|
result.blocks = result.get_entry_reachable_blocks()
|
|
|
return result
|
|
|
|
|
|
+def create_graph_component(entry_point):
|
|
|
+ """Creates a flow graph component from the given entry point."""
|
|
|
+ reachable = cfg_optimization.get_all_reachable_blocks(entry_point)
|
|
|
+ return FlowGraphComponent([entry_point], reachable[entry_point], reachable)
|
|
|
+
|
|
|
class SimpleBlock(object):
|
|
|
"""A 'simple' block in the relooper algorithm."""
|
|
|
def __init__(self, body, next_block):
|
|
@@ -51,6 +56,12 @@ class SimpleBlock(object):
|
|
|
state.lower_block(self.body),
|
|
|
self.next_block.lower(state))
|
|
|
|
|
|
+class EmptyBlock(object):
|
|
|
+ """An empty relooper block."""
|
|
|
+ def lower(self, _):
|
|
|
+ """Lowers this empty block to a tree."""
|
|
|
+ return tree_ir.EmptyInstruction()
|
|
|
+
|
|
|
class LoopBlock(object):
|
|
|
"""A 'loop' block in the relooper algorithm."""
|
|
|
def __init__(self, inner, next_block):
|
|
@@ -59,13 +70,10 @@ class LoopBlock(object):
|
|
|
|
|
|
def lower(self, state):
|
|
|
"""Lowers this 'loop' block to a tree."""
|
|
|
- old_loop = state.current_loop
|
|
|
- state.current_loop = self
|
|
|
inner = tree_ir.LoopInstruction(
|
|
|
tree_ir.create_block(
|
|
|
self.inner.lower(state),
|
|
|
tree_ir.BreakInstruction()))
|
|
|
- state.current_loop = old_loop
|
|
|
return tree_ir.create_block(
|
|
|
inner,
|
|
|
self.next_block.lower(state))
|
|
@@ -82,7 +90,7 @@ class MultipleBlock(object):
|
|
|
for entry, block in self.handled_blocks:
|
|
|
result = tree_ir.SelectInstruction(
|
|
|
tree_ir.BinaryInstruction(
|
|
|
- state.label_variable,
|
|
|
+ tree_ir.LoadLocalInstruction(state.label_variable),
|
|
|
'==',
|
|
|
tree_ir.LiteralInstruction(entry.index)),
|
|
|
block.lower(state),
|
|
@@ -102,13 +110,10 @@ class MultipleLoopBlock(MultipleBlock):
|
|
|
|
|
|
def lower(self, state):
|
|
|
"""Lowers this 'multiple' block to a tree."""
|
|
|
- old_loop = state.current_loop
|
|
|
- state.current_loop = self
|
|
|
inner = tree_ir.LoopInstruction(
|
|
|
tree_ir.create_block(
|
|
|
self.lower_handled_blocks(state),
|
|
|
tree_ir.BreakInstruction()))
|
|
|
- state.current_loop = old_loop
|
|
|
return tree_ir.create_block(
|
|
|
inner,
|
|
|
self.next_block.lower(state))
|
|
@@ -260,8 +265,11 @@ def to_relooper_multiple_or_loop(graph_component):
|
|
|
|
|
|
def reloop(graph_component):
|
|
|
"""Applies the relooper algorithm to the given graph component."""
|
|
|
- reachable_set = graph_component.get_entry_reachable_blocks()
|
|
|
entry_blocks = graph_component.entry_blocks
|
|
|
+ if len(entry_blocks) == 0:
|
|
|
+ return EmptyBlock()
|
|
|
+
|
|
|
+ reachable_set = graph_component.get_entry_reachable_blocks()
|
|
|
if len(entry_blocks) == 1 and entry_blocks[0] not in reachable_set:
|
|
|
graph_component.blocks.remove(entry_blocks[0])
|
|
|
return SimpleBlock(
|
|
@@ -276,6 +284,17 @@ def reloop(graph_component):
|
|
|
else:
|
|
|
return to_relooper_multiple_or_loop(graph_component)
|
|
|
|
|
|
+def reloop_trivial(graph_component):
|
|
|
+ """Converts the given control-flow graph to a 'multiple' block that contains only 'simple'
|
|
|
+ blocks."""
|
|
|
+ return MultipleLoopBlock(
|
|
|
+ [(block, SimpleBlock(block, EmptyBlock())) for block in graph_component.blocks],
|
|
|
+ EmptyBlock())
|
|
|
+
|
|
|
+def reloop_function_body(entry_point):
|
|
|
+ """Reloops the control-flow graph defined by the given entry point."""
|
|
|
+ return reloop_trivial(create_graph_component(entry_point))
|
|
|
+
|
|
|
class LoweringState(object):
|
|
|
"""Stores information related to the relooper->tree conversion."""
|
|
|
def __init__(self, jit):
|
|
@@ -326,7 +345,7 @@ class LoweringState(object):
|
|
|
for definition in block.definitions:
|
|
|
statements.append(self.lower_definition(definition))
|
|
|
statements.append(self.lower_flow(block.flow))
|
|
|
- return tree_ir.create_block(statements)
|
|
|
+ return tree_ir.create_block(*statements)
|
|
|
|
|
|
def lower_definition(self, definition):
|
|
|
"""Lowers the given definition to a tree."""
|
|
@@ -418,7 +437,8 @@ class LoweringState(object):
|
|
|
|
|
|
def lower_free_root_node(self, value):
|
|
|
"""Lowers a 'free-root-node' value."""
|
|
|
- return tree_ir.DeleteEdgeInstruction(self.__get_root_edge_name(value.root_node))
|
|
|
+ return tree_ir.DeleteEdgeInstruction(
|
|
|
+ tree_ir.LoadLocalInstruction(self.__get_root_edge_name(value.root_node)))
|
|
|
|
|
|
def lower_load_pointer(self, value):
|
|
|
"""Lowers a 'load' value."""
|
|
@@ -442,7 +462,7 @@ class LoweringState(object):
|
|
|
|
|
|
def lower_output(self, value):
|
|
|
"""Lowers an 'output' value."""
|
|
|
- return bytecode_to_tree.create_output(self.load_definition(value.output_value))
|
|
|
+ return bytecode_to_tree.create_output(self.load_definition(value.value))
|
|
|
|
|
|
def lower_direct_call(self, value):
|
|
|
"""Lowers a direct function call."""
|
|
@@ -522,7 +542,7 @@ class LoweringState(object):
|
|
|
|
|
|
def lower_throw(self, flow):
|
|
|
"""Lowers the given 'throw' flow instruction to a tree."""
|
|
|
- return tree_ir.RaiseInstruction(self.load_definition(flow.value))
|
|
|
+ return tree_ir.RaiseInstruction(self.load_definition(flow.exception))
|
|
|
|
|
|
def lower_unreachable(self, _):
|
|
|
"""Lowers the given 'unreachable' flow instruction to a tree."""
|