|
@@ -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)
|