瀏覽代碼

Fix a bug where jitted functions rely on non-jitted functions

jonathanvdc 8 年之前
父節點
當前提交
e1ff62bbaf
共有 1 個文件被更改,包括 22 次插入6 次删除
  1. 22 6
      kernel/modelverse_jit/jit.py

+ 22 - 6
kernel/modelverse_jit/jit.py

@@ -23,6 +23,7 @@ class ModelverseJit(object):
         self.max_instructions = 30 if max_instructions is None else max_instructions
         self.compiled_function_lookup = compiled_function_lookup
         self.jit_intrinsics = {}
+        self.compilation_dependencies = {}
         self.jit_enabled = True
 
     def set_jit_enabled(self, is_enabled=True):
@@ -141,7 +142,9 @@ class ModelverseJit(object):
         elif body_id in self.no_jit_entry_points:
             # We're not allowed to jit this function or have tried and failed before.
             raise JitCompilationFailedException(
-                'Cannot jit function at %d because it is marked non-jittable.' % body_id)
+                'Cannot jit function %s at %d because it is marked non-jittable.' % (
+                    '' if suggested_name is None else "'" + suggested_name + "'",
+                    body_id))
 
         # Generate a name for the function we're about to analyze, and pretend that
         # it already exists. (we need to do this for recursive functions)
@@ -159,19 +162,26 @@ class ModelverseJit(object):
 
         param_dict = dict(zip(parameter_ids, parameter_list))
         body_param_dict = dict(zip(parameter_ids, [p + "_ptr" for p in parameter_list]))
+        dependencies = set([body_id])
+        self.compilation_dependencies[body_id] = dependencies
         try:
             gen = AnalysisState(
-                self, user_root, body_param_dict, self.max_instructions).analyze(body_id)
+                self, body_id, user_root, body_param_dict,
+                self.max_instructions).analyze(body_id)
             inp = None
             while True:
                 inp = yield gen.send(inp)
         except primitive_functions.PrimitiveFinished as ex:
+            del self.compilation_dependencies[body_id]
             constructed_body = ex.result
         except JitCompilationFailedException as ex:
-            self.mark_no_jit(body_id)
-            del self.jitted_entry_points[body_id]
+            del self.compilation_dependencies[body_id]
+            for dep in dependencies:
+                self.mark_no_jit(dep)
+                if dep in self.jitted_entry_points:
+                    del self.jitted_entry_points[dep]
             raise JitCompilationFailedException(
-                '%s (function at %d)' % (ex.message, body_id))
+                "%s (function '%s' at %d)" % (ex.message, function_name, body_id))
 
         # Write a prologue and prepend it to the generated function body.
         prologue_statements = []
@@ -204,10 +214,11 @@ class ModelverseJit(object):
 
 class AnalysisState(object):
     """The state of a bytecode analysis call graph."""
-    def __init__(self, jit, user_root, local_mapping, max_instructions=None):
+    def __init__(self, jit, body_id, user_root, local_mapping, max_instructions=None):
         self.analyzed_instructions = set()
         self.function_vars = set()
         self.local_vars = set()
+        self.body_id = body_id
         self.max_instructions = max_instructions
         self.user_root = user_root
         self.jit = jit
@@ -692,6 +703,11 @@ class AnalysisState(object):
         self.register_function_var(callee_id)
 
         body_id, = yield [("RD", [callee_id, "body"])]
+
+        # Make this function dependent on the callee.
+        if body_id in self.jit.compilation_dependencies:
+            self.jit.compilation_dependencies[body_id].add(self.body_id)
+
         # Analyze the parameter list.
         try:
             gen = self.jit.jit_parameters(body_id)