|
@@ -45,6 +45,105 @@ class ModelverseJit(object):
|
|
|
|
|
|
def try_jit(self, body_id, parameter_list):
|
|
|
"""Tries to jit the function defined by the given entry point id and parameter list."""
|
|
|
+ gen = AnalysisState().analyze(body_id)
|
|
|
+ try:
|
|
|
+ inp = None
|
|
|
+ while True:
|
|
|
+ inp = yield gen.send(inp)
|
|
|
+ except primitive_functions.PrimitiveFinished as e:
|
|
|
+ pass
|
|
|
|
|
|
self.mark_no_jit(body_id)
|
|
|
- raise JitCompilationFailedException("Couln't JIT function body at " + str(body_id))
|
|
|
+ raise JitCompilationFailedException("Can't JIT function body at " + str(body_id))
|
|
|
+
|
|
|
+class AnalysisState(object):
|
|
|
+ """The state of a bytecode analysis call graph."""
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ self.analyzed_instructions = set()
|
|
|
+
|
|
|
+ def analyze(self, instruction_id):
|
|
|
+ """Tries to build an intermediate representation from the instruction with the
|
|
|
+ given id."""
|
|
|
+ instruction_val, = yield [("RV", [instruction_id])]
|
|
|
+ instruction_val = instruction_val["value"]
|
|
|
+ if instruction_val in self.instruction_analyzers:
|
|
|
+ gen = self.instruction_analyzers[instruction_val](self, instruction_id)
|
|
|
+ try:
|
|
|
+ inp = None
|
|
|
+ while True:
|
|
|
+ inp = yield gen.send(inp)
|
|
|
+ except StopIteration:
|
|
|
+ raise Exception(
|
|
|
+ "Instruction analyzer (for '%s') finished without returning a value!" %
|
|
|
+ (instruction_val))
|
|
|
+ else:
|
|
|
+ raise JitCompilationFailedException(
|
|
|
+ "Unknown instruction type: '%s'" % (instruction_val))
|
|
|
+
|
|
|
+ def analyze_all(self, instruction_ids):
|
|
|
+ """Tries to compile a list of IR trees from the given list of instruction ids."""
|
|
|
+ results = []
|
|
|
+ for inst in instruction_ids:
|
|
|
+ gen = self.analyze(inst)
|
|
|
+ try:
|
|
|
+ inp = None
|
|
|
+ while True:
|
|
|
+ inp = yield gen.send(inp)
|
|
|
+ except primitive_functions.PrimitiveFinished as e:
|
|
|
+ results.append(e.result)
|
|
|
+
|
|
|
+ raise primitive_functions.PrimitiveFinished(results)
|
|
|
+
|
|
|
+ def analyze_return(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'return' instruction."""
|
|
|
+ retval_id, = yield [("RD", [instruction_id, 'value'])]
|
|
|
+ if retval_id is None:
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.ReturnInstruction(
|
|
|
+ tree_ir.EmptyInstruction()))
|
|
|
+ else:
|
|
|
+ gen = self.analyze(retval_id)
|
|
|
+ try:
|
|
|
+ inp = None
|
|
|
+ while True:
|
|
|
+ inp = yield gen.send(inp)
|
|
|
+ except primitive_functions.PrimitiveFinished as e:
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.ReturnInstruction(e.result))
|
|
|
+
|
|
|
+ def analyze_if(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'if' instruction."""
|
|
|
+ cond, true, false, next_inst = yield [
|
|
|
+ ("RD", [instruction_id, "cond"]),
|
|
|
+ ("RD", [instruction_id, "then"]),
|
|
|
+ ("RD", [instruction_id, "else"]),
|
|
|
+ ("RD", [instruction_id, "next"])]
|
|
|
+
|
|
|
+ gen = self.analyze_all([cond, true, false, next_inst])
|
|
|
+ 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
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.CompoundInstruction(
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.ReadValueInstruction(cond_r),
|
|
|
+ true_r,
|
|
|
+ false_r),
|
|
|
+ next_r))
|
|
|
+
|
|
|
+ def analyze_constant(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'constant' (literal) instruction."""
|
|
|
+
|
|
|
+ node_id, = yield [("RD", [instruction_id, "node"])]
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.LiteralInstruction(node_id))
|
|
|
+
|
|
|
+ instruction_analyzers = {
|
|
|
+ 'if' : analyze_if,
|
|
|
+ 'return' : analyze_return,
|
|
|
+ 'constant' : analyze_constant
|
|
|
+ }
|