Browse Source

Generate DEBUG_INFO requests during baseline JIT codegen

jonathanvdc 8 years ago
parent
commit
0888c0133d
2 changed files with 50 additions and 9 deletions
  1. 31 9
      kernel/modelverse_jit/jit.py
  2. 19 0
      kernel/modelverse_jit/tree_ir.py

+ 31 - 9
kernel/modelverse_jit/jit.py

@@ -58,14 +58,22 @@ def create_bare_function(function_name, parameter_list, function_body):
 
 def create_function(
         function_name, parameter_list, param_dict,
-        body_param_dict, function_body):
+        body_param_dict, function_body, source_map_name=None):
     """Creates a function from the given function name, parameter list,
        variable-to-parameter name map, variable-to-local name map and
-       function body."""
+       function body. An optional source map can be included, too."""
     # Write a prologue and prepend it to the generated function body.
-    prologue_statements = []
+    prolog_statements = []
+    # If the source map is not None, then we should generate a "DEBUG_INFO"
+    # request.
+    if source_map_name is not None:
+        prolog_statements.append(
+            tree_ir.RegisterDebugInfoInstruction(
+                tree_ir.LiteralInstruction(function_name),
+                tree_ir.LoadGlobalInstruction(source_map_name)))
+
     # Create a LOCALS_NODE_NAME node, and connect it to the user root.
-    prologue_statements.append(
+    prolog_statements.append(
         tree_ir.create_new_local_node(
             jit_runtime.LOCALS_NODE_NAME,
             tree_ir.LoadIndexInstruction(
@@ -76,15 +84,15 @@ def create_function(
         arg_ptr = tree_ir.create_new_local_node(
             body_param_dict[key],
             tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_NODE_NAME))
-        prologue_statements.append(arg_ptr)
-        prologue_statements.append(
+        prolog_statements.append(arg_ptr)
+        prolog_statements.append(
             tree_ir.CreateDictionaryEdgeInstruction(
                 tree_ir.LoadLocalInstruction(body_param_dict[key]),
                 tree_ir.LiteralInstruction('value'),
                 tree_ir.LoadLocalInstruction(val)))
 
     constructed_body = tree_ir.create_block(
-        *(prologue_statements + [function_body]))
+        *(prolog_statements + [function_body]))
 
     # Shield temporaries from the GC.
     constructed_body = tree_ir.protect_temporaries_from_gc(
@@ -517,6 +525,14 @@ class ModelverseJit(object):
 
         raise primitive_functions.PrimitiveFinished(compiled_function)
 
+    def get_source_map_name(self, function_name):
+        """Gets the name of the given jitted function's source map. None is returned if source maps
+           are disabled."""
+        if self.source_maps_enabled:
+            return function_name + "_source_map"
+        else:
+            return None
+
     def jit_define_function(self, function_name, function_def):
         """Converts the given tree-IR function definition to Python code, defines it,
            and extracts the resulting function."""
@@ -527,7 +543,12 @@ class ModelverseJit(object):
             self.jit_code_log_function(function_def)
 
         # Convert the function definition to Python code, and compile it.
-        exec(str(function_def), self.jit_globals)
+        code_generator = tree_ir.PythonGenerator()
+        function_def.generate_python_def(code_generator)
+        source_map_name = self.get_source_map_name(function_name)
+        if source_map_name is not None:
+            self.jit_globals[source_map_name] = code_generator.source_map_builder.source_map
+        exec(str(code_generator), self.jit_globals)
 
         # Extract the compiled function from the JIT global state.
         return self.jit_globals[function_name]
@@ -678,7 +699,8 @@ def compile_function_body_baseline(jit, function_name, body_id, task_root):
     # Wrap the tree IR in a function definition.
     raise primitive_functions.PrimitiveFinished(
         create_function(
-            function_name, parameter_list, param_dict, body_param_dict, constructed_body))
+            function_name, parameter_list, param_dict,
+            body_param_dict, constructed_body, jit.get_source_map_name(function_name)))
 
 def compile_function_body_fast(jit, function_name, body_id, _):
     """Have the fast JIT compile the function with the given name and body id."""

+ 19 - 0
kernel/modelverse_jit/tree_ir.py

@@ -998,6 +998,25 @@ class RunTailGeneratorFunctionInstruction(StateInstruction):
         """Gets this state instruction's argument list."""
         return [self.function, self.argument_dict]
 
+class RegisterDebugInfoInstruction(StateInstruction):
+    """An instruction that sends a DEBUG_INFO request to the request handler."""
+    def __init__(self, function_name, function_source_map):
+        StateInstruction.__init__(self)
+        self.function_name = function_name
+        self.function_source_map = function_source_map
+
+    def get_result_type_impl(self):
+        """Gets the type of value produced by this instruction."""
+        return NO_RESULT_TYPE
+
+    def get_opcode(self):
+        """Gets the opcode for this state instruction."""
+        return "DEBUG_INFO"
+
+    def get_arguments(self):
+        """Gets this state instruction's argument list."""
+        return [self.function_name, self.function_source_map]
+
 class VariableName(object):
     """A data structure that unifies names across instructions that access the
        same variable."""