Browse Source

Fix a couple of bugs in the bytecode parser

jonathanvdc 8 years ago
parent
commit
29f2a59977
2 changed files with 30 additions and 14 deletions
  1. 15 14
      kernel/modelverse_jit/bytecode_parser.py
  2. 15 0
      kernel/modelverse_jit/runtime.py

+ 15 - 14
kernel/modelverse_jit/bytecode_parser.py

@@ -12,7 +12,7 @@ class BytecodeParser(object):
     def parse_instruction(self, node_id):
     def parse_instruction(self, node_id):
         """Parses the instruction node with the given identifier."""
         """Parses the instruction node with the given identifier."""
         if node_id is None:
         if node_id is None:
-            return None
+            raise primitive_functions.PrimitiveFinished(None)
         elif node_id in self.parsed_nodes:
         elif node_id in self.parsed_nodes:
             # We've already parsed this node, so return it right away.
             # We've already parsed this node, so return it right away.
             raise primitive_functions.PrimitiveFinished(self.parsed_nodes[node_id])
             raise primitive_functions.PrimitiveFinished(self.parsed_nodes[node_id])
@@ -23,7 +23,7 @@ class BytecodeParser(object):
         instruction = self.create_instruction(instruction_type)
         instruction = self.create_instruction(instruction_type)
         self.parsed_nodes[node_id] = instruction
         self.parsed_nodes[node_id] = instruction
         # Initialize the instruction from the node's data.
         # Initialize the instruction from the node's data.
-        yield [("CALL_ARGS", [self.initialize_instruction, instruction, (node_id,)])]
+        yield [("CALL_ARGS", [self.initialize_instruction, (instruction, node_id)])]
         # Retrieve the debug information.
         # Retrieve the debug information.
         debug_info, = yield [("RD", [node_id, "__debug"])]
         debug_info, = yield [("RD", [node_id, "__debug"])]
         if debug_info is not None:
         if debug_info is not None:
@@ -40,29 +40,29 @@ class BytecodeParser(object):
 
 
     def parse_variable(self, node_id):
     def parse_variable(self, node_id):
         """Parses the given variable node."""
         """Parses the given variable node."""
-        var_id, = yield [("RD", [node_id, "var"])]
-        var_name, = yield [("RV", [var_id])]
-        return bytecode_ir.VariableNode(var_id, var_name)
+        var_name, = yield [("RV", [node_id])]
+        raise primitive_functions.PrimitiveFinished(
+            bytecode_ir.VariableNode(node_id, var_name))
 
 
     def __parse_node_unchecked(self, node_id, result_type):
     def __parse_node_unchecked(self, node_id, result_type):
         """Parses the given node as the specified type of object, without
         """Parses the given node as the specified type of object, without
            checking that the result actually conforms to said type."""
            checking that the result actually conforms to said type."""
-        if isinstance(result_type, bytecode_ir.VariableNode):
-            return self.parse_variable(node_id)
-        elif isinstance(result_type, int):
-            return node_id
+        if result_type is bytecode_ir.VariableNode:
+            yield [("TAIL_CALL_ARGS", [self.parse_variable, (node_id,)])]
+        elif result_type is int:
+            raise primitive_functions.PrimitiveFinished(node_id)
         else:
         else:
-            return self.parse_instruction(node_id)
+            yield [("TAIL_CALL_ARGS", [self.parse_instruction, (node_id,)])]
 
 
     def parse_node(self, node_id, result_type):
     def parse_node(self, node_id, result_type):
         """Parses the given node as the specified type of object."""
         """Parses the given node as the specified type of object."""
-        result = self.__parse_node_unchecked(node_id, result_type)
+        result, = yield [("CALL_ARGS", [self.__parse_node_unchecked, (node_id, result_type)])]
         if result is not None and not isinstance(result, result_type):
         if result is not None and not isinstance(result, result_type):
             raise jit_runtime.JitCompilationFailedException(
             raise jit_runtime.JitCompilationFailedException(
                 "Parsed a node as an instance of '%s', expected an instance of '%s'." % (
                 "Parsed a node as an instance of '%s', expected an instance of '%s'." % (
-                    type(result), result_type))
+                    type(result).__name__, result_type.__name__))
 
 
-        return result
+        raise primitive_functions.PrimitiveFinished(result)
 
 
     def parse_arguments(self, first_argument_id):
     def parse_arguments(self, first_argument_id):
         """Parses the parameter-to-argument mapping started by the specified first argument
         """Parses the parameter-to-argument mapping started by the specified first argument
@@ -83,7 +83,7 @@ class BytecodeParser(object):
     def create_instruction(self, instruction_type):
     def create_instruction(self, instruction_type):
         """Creates an instruction of the given type."""
         """Creates an instruction of the given type."""
         if instruction_type in bytecode_ir.INSTRUCTION_TYPE_MAPPING:
         if instruction_type in bytecode_ir.INSTRUCTION_TYPE_MAPPING:
-            return bytecode_ir.INSTRUCTION_TYPE_MAPPING[instruction_type].__new__()
+            return object.__new__(bytecode_ir.INSTRUCTION_TYPE_MAPPING[instruction_type])
         else:
         else:
             raise jit_runtime.JitCompilationFailedException(
             raise jit_runtime.JitCompilationFailedException(
                 "Unknown instruction type: '%s'" % instruction_type)
                 "Unknown instruction type: '%s'" % instruction_type)
@@ -101,6 +101,7 @@ class BytecodeParser(object):
     def initialize_instruction(self, instruction, node_id):
     def initialize_instruction(self, instruction, node_id):
         """Initializes the given instruction with data from the given node."""
         """Initializes the given instruction with data from the given node."""
         instr_type = type(instruction)
         instr_type = type(instruction)
+        # print("Initializing '%s' node" % instr_type)
         if instr_type is bytecode_ir.CallInstruction:
         if instr_type is bytecode_ir.CallInstruction:
             # Call instructions are complicated, so they get special treatment.
             # Call instructions are complicated, so they get special treatment.
             yield [("TAIL_CALL_ARGS", [self.initialize_call, (instruction, node_id)])]
             yield [("TAIL_CALL_ARGS", [self.initialize_call, (instruction, node_id)])]

+ 15 - 0
kernel/modelverse_jit/runtime.py

@@ -10,6 +10,21 @@ MUTABLE_FUNCTION_KEY = "mutable"
 FUNCTION_BODY_KEY = "body"
 FUNCTION_BODY_KEY = "body"
 """A dictionary key for function bodies."""
 """A dictionary key for function bodies."""
 
 
+KWARGS_PARAMETER_NAME = "kwargs"
+"""The name of the kwargs parameter in jitted functions."""
+
+CALL_FUNCTION_NAME = "__call_function"
+"""The name of the '__call_function' function, in the jitted function scope."""
+
+GET_INPUT_FUNCTION_NAME = "__get_input"
+"""The name of the '__get_input' function, in the jitted function scope."""
+
+LOCALS_NODE_NAME = "jit_locals"
+"""The name of the node that is connected to all JIT locals in a given function call."""
+
+LOCALS_EDGE_NAME = "jit_locals_edge"
+"""The name of the edge that connects the LOCALS_NODE_NAME node to a user root."""
+
 def call_function(function_id, named_arguments, **kwargs):
 def call_function(function_id, named_arguments, **kwargs):
     """Runs the function with the given id, passing it the specified argument dictionary."""
     """Runs the function with the given id, passing it the specified argument dictionary."""
     user_root = kwargs['user_root']
     user_root = kwargs['user_root']