Browse Source

Support 'next' edges on arbitrary nodes in the JIT

jonathanvdc 8 years ago
parent
commit
745a1b96cb
1 changed files with 27 additions and 11 deletions
  1. 27 11
      kernel/modelverse_jit/jit.py

+ 27 - 11
kernel/modelverse_jit/jit.py

@@ -65,6 +65,9 @@ class AnalysisState(object):
     def analyze(self, instruction_id):
         """Tries to build an intermediate representation from the instruction with the
         given id."""
+        # Add the instruction id to the analyzed_instructions set to avoid
+        # infinite loops.
+        self.analyzed_instructions.add(instruction_id)
         instruction_val, = yield [("RV", [instruction_id])]
         instruction_val = instruction_val["value"]
         if instruction_val in self.instruction_analyzers:
@@ -77,6 +80,22 @@ class AnalysisState(object):
                 raise Exception(
                     "Instruction analyzer (for '%s') finished without returning a value!" %
                     (instruction_val))
+            except primitive_functions.PrimitiveFinished as outer_e:
+                # Check if the instruction has a 'next' instruction.
+                next_instr, = yield [("RD", [instruction_id, "next"])]
+                if next_instr is None:
+                    raise outer_e
+                else:
+                    gen = self.analyze(next_instr)
+                    try:
+                        inp = None
+                        while True:
+                            inp = yield gen.send(inp)
+                    except primitive_functions.PrimitiveFinished as inner_e:
+                        raise primitive_functions.PrimitiveFinished(
+                            tree_ir.CompoundInstruction(
+                                outer_e.result,
+                                inner_e.result))
         else:
             raise JitCompilationFailedException(
                 "Unknown instruction type: '%s'" % (instruction_val))
@@ -114,26 +133,23 @@ class AnalysisState(object):
 
     def analyze_if(self, instruction_id):
         """Tries to analyze the given 'if' instruction."""
-        cond, true, false, next_inst = yield [
+        cond, true, false = yield [
             ("RD", [instruction_id, "cond"]),
             ("RD", [instruction_id, "then"]),
-            ("RD", [instruction_id, "else"]),
-            ("RD", [instruction_id, "next"])]
+            ("RD", [instruction_id, "else"])]
 
-        gen = self.analyze_all([cond, true, false, next_inst])
+        gen = self.analyze_all([cond, true, false])
         try:
             inp = None
             while True:
                 inp = yield gen.send(inp)
         except primitive_functions.PrimitiveFinished as e:
-            cond_r, true_r, false_r, next_r = e.result
+            cond_r, true_r, false_r = e.result
             raise primitive_functions.PrimitiveFinished(
-                tree_ir.CompoundInstruction(
-                    tree_ir.SelectInstruction(
-                        tree_ir.ReadValueInstruction(cond_r),
-                        true_r,
-                        false_r),
-                    next_r))
+                tree_ir.SelectInstruction(
+                    tree_ir.ReadValueInstruction(cond_r),
+                    true_r,
+                    false_r))
 
     def analyze_constant(self, instruction_id):
         """Tries to analyze the given 'constant' (literal) instruction."""