Browse Source

Support automatic nop insertion in fast-jit

jonathanvdc 8 years ago
parent
commit
033de36915

+ 6 - 0
kernel/modelverse_jit/bytecode_to_cfg.py

@@ -145,6 +145,8 @@ class AnalysisState(object):
         #
         #
         # !loop_body():
         # !loop_body():
         #     $result = <body>
         #     $result = <body>
+        #     static if jit.nop_insertion_enabled:
+        #         $_ = direct-call ('macro-io', void) nop()
         #     jump !loop_condition()
         #     jump !loop_condition()
         #
         #
         # !loop_exit():
         # !loop_exit():
@@ -165,6 +167,8 @@ class AnalysisState(object):
 
 
         self.current_block = loop_body_block
         self.current_block = loop_body_block
         self.analyze(instruction.body)
         self.analyze(instruction.body)
+        if self.jit.nop_insertion_enabled:
+            self.current_block.append_definition(cfg_ir.create_nop())
         self.current_block.flow = cfg_ir.create_jump(loop_condition_block)
         self.current_block.flow = cfg_ir.create_jump(loop_condition_block)
 
 
         self.current_block = loop_exit_block
         self.current_block = loop_exit_block
@@ -296,6 +300,8 @@ class AnalysisState(object):
             raise jit_runtime.JitCompilationFailedException(
             raise jit_runtime.JitCompilationFailedException(
                 "'continue' instruction targets a 'while' loop that has not been defined yet.")
                 "'continue' instruction targets a 'while' loop that has not been defined yet.")
 
 
+        if self.jit.nop_insertion_enabled:
+            self.current_block.append_definition(cfg_ir.create_nop())
         cond_block, _ = self.loop_instructions[instruction.loop]
         cond_block, _ = self.loop_instructions[instruction.loop]
         self.current_block.flow = cfg_ir.create_jump(cond_block)
         self.current_block.flow = cfg_ir.create_jump(cond_block)
         self.current_block = cfg_ir.BasicBlock(self.counter)
         self.current_block = cfg_ir.BasicBlock(self.counter)

+ 10 - 0
kernel/modelverse_jit/cfg_ir.py

@@ -491,6 +491,9 @@ INPUT_MACRO_NAME = 'input'
 OUTPUT_MACRO_NAME = 'output'
 OUTPUT_MACRO_NAME = 'output'
 """The name of the macro that pushes an output onto the output queue."""
 """The name of the macro that pushes an output onto the output queue."""
 
 
+NOP_MACRO_NAME = 'nop'
+"""The name of the macro that performs a nop."""
+
 READ_DICT_KEYS_MACRO_NAME = 'read_dict_keys'
 READ_DICT_KEYS_MACRO_NAME = 'read_dict_keys'
 """The name of the macro that reads all keys from a dictionary."""
 """The name of the macro that reads all keys from a dictionary."""
 
 
@@ -893,6 +896,13 @@ def create_input():
         INPUT_MACRO_NAME, [],
         INPUT_MACRO_NAME, [],
         calling_convention=MACRO_IO_CALLING_CONVENTION)
         calling_convention=MACRO_IO_CALLING_CONVENTION)
 
 
+def create_nop():
+    """Creates a value that performs a nop."""
+    return DirectFunctionCall(
+        NOP_MACRO_NAME, [],
+        calling_convention=MACRO_IO_CALLING_CONVENTION,
+        has_value=False)
+
 def create_gc_protect(protected_value, root):
 def create_gc_protect(protected_value, root):
     """Creates a value that protects the first from the GC by drawing an
     """Creates a value that protects the first from the GC by drawing an
        edge between it and the given root."""
        edge between it and the given root."""

+ 3 - 1
kernel/modelverse_jit/cfg_to_tree.py

@@ -873,7 +873,9 @@ class LoweringState(object):
     def lower_io_call(self, value):
     def lower_io_call(self, value):
         """Expands an IO call."""
         """Expands an IO call."""
         arg_list = [self.use_definition(arg) for _, arg in value.argument_list]
         arg_list = [self.use_definition(arg) for _, arg in value.argument_list]
-        if value.target_name == cfg_ir.INPUT_MACRO_NAME:
+        if value.target_name == cfg_ir.NOP_MACRO_NAME:
+            return tree_ir.NopInstruction()
+        elif value.target_name == cfg_ir.INPUT_MACRO_NAME:
             return bytecode_to_tree.create_input(self.jit.use_input_function)
             return bytecode_to_tree.create_input(self.jit.use_input_function)
         elif value.target_name == cfg_ir.OUTPUT_MACRO_NAME:
         elif value.target_name == cfg_ir.OUTPUT_MACRO_NAME:
             return bytecode_to_tree.create_output(*arg_list)
             return bytecode_to_tree.create_output(*arg_list)