|
@@ -1,3 +1,4 @@
|
|
|
+import math
|
|
|
import keyword
|
|
|
from collections import defaultdict
|
|
|
import modelverse_kernel.primitives as primitive_functions
|
|
@@ -5,6 +6,7 @@ import modelverse_jit.bytecode_parser as bytecode_parser
|
|
|
import modelverse_jit.bytecode_to_tree as bytecode_to_tree
|
|
|
import modelverse_jit.bytecode_to_cfg as bytecode_to_cfg
|
|
|
import modelverse_jit.bytecode_ir as bytecode_ir
|
|
|
+import modelverse_jit.bytecode_interpreter as bytecode_interpreter
|
|
|
import modelverse_jit.cfg_optimization as cfg_optimization
|
|
|
import modelverse_jit.cfg_to_tree as cfg_to_tree
|
|
|
import modelverse_jit.cfg_ir as cfg_ir
|
|
@@ -60,7 +62,8 @@ def create_bare_function(function_name, parameter_list, function_body):
|
|
|
|
|
|
def create_function(
|
|
|
function_name, parameter_list, param_dict,
|
|
|
- body_param_dict, function_body, source_map_name=None):
|
|
|
+ body_param_dict, function_body, source_map_name=None,
|
|
|
+ compatible_temporary_protects=False):
|
|
|
"""Creates a function from the given function name, parameter list,
|
|
|
variable-to-parameter name map, variable-to-local name map and
|
|
|
function body. An optional source map can be included, too."""
|
|
@@ -99,7 +102,9 @@ def create_function(
|
|
|
|
|
|
# Shield temporaries from the GC.
|
|
|
constructed_body = tree_ir.protect_temporaries_from_gc(
|
|
|
- constructed_body, tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_NODE_NAME))
|
|
|
+ constructed_body,
|
|
|
+ tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_NODE_NAME),
|
|
|
+ compatible_temporary_protects)
|
|
|
|
|
|
return create_bare_function(function_name, parameter_list, constructed_body)
|
|
|
|
|
@@ -514,16 +519,14 @@ class ModelverseJit(object):
|
|
|
raise JitCompilationFailedException(
|
|
|
"Function was marked '%s'." % jit_runtime.MUTABLE_FUNCTION_KEY)
|
|
|
|
|
|
- constructed_function, = yield [
|
|
|
+ compiled_function, = yield [
|
|
|
("CALL_ARGS", [compile_function_body, (self, function_name, body_id, task_root)])]
|
|
|
|
|
|
yield [("END_TRY", [])]
|
|
|
del self.compilation_dependencies[body_id]
|
|
|
|
|
|
- # Convert the function definition to Python code, and compile it.
|
|
|
- compiled_function = self.jit_define_function(function_name, constructed_function)
|
|
|
-
|
|
|
if self.jit_success_log_function is not None:
|
|
|
+ assert self.jitted_entry_points[body_id] == function_name
|
|
|
self.jit_success_log_function(
|
|
|
"JIT compilation successful: (function '%s' at %d)" % (function_name, body_id))
|
|
|
|
|
@@ -546,7 +549,6 @@ class ModelverseJit(object):
|
|
|
and extracts the resulting function."""
|
|
|
# The comment below makes pylint shut up about our (hopefully benign) use of exec here.
|
|
|
# pylint: disable=I0011,W0122
|
|
|
-
|
|
|
if self.jit_code_log_function is not None:
|
|
|
self.jit_code_log_function(function_def)
|
|
|
|
|
@@ -570,10 +572,13 @@ class ModelverseJit(object):
|
|
|
if body_id is None:
|
|
|
raise ValueError('body_id cannot be None')
|
|
|
elif body_id in self.jitted_entry_points:
|
|
|
- # We have already compiled this function.
|
|
|
raise primitive_functions.PrimitiveFinished(
|
|
|
self.jit_globals[self.jitted_entry_points[body_id]])
|
|
|
|
|
|
+ compiled_func = self.lookup_compiled_body(body_id)
|
|
|
+ if compiled_func is not None:
|
|
|
+ raise primitive_functions.PrimitiveFinished(compiled_func)
|
|
|
+
|
|
|
# Generate a name for the function we're about to analyze, and 're-compile'
|
|
|
# it for the first time.
|
|
|
function_name = self.generate_function_name(body_id, suggested_name)
|
|
@@ -718,7 +723,34 @@ class ModelverseJit(object):
|
|
|
tree_ir.LiteralInstruction(jit_runtime.FUNCTION_BODY_KEY)),
|
|
|
global_name)
|
|
|
|
|
|
-def compile_function_body_baseline(jit, function_name, body_id, task_root, header=None):
|
|
|
+def compile_function_body_interpret(jit, function_name, body_id, task_root, header=None):
|
|
|
+ """Create a function that invokes the interpreter on the given function."""
|
|
|
+ (parameter_ids, parameter_list, _), = yield [
|
|
|
+ ("CALL_ARGS", [jit.jit_signature, (body_id,)])]
|
|
|
+ param_dict = dict(zip(parameter_ids, parameter_list))
|
|
|
+ body_bytecode, = yield [("CALL_ARGS", [jit.jit_parse_bytecode, (body_id,)])]
|
|
|
+ def __interpret_function(**kwargs):
|
|
|
+ if header is not None:
|
|
|
+ (done, result), = yield [("CALL_KWARGS", [header, kwargs])]
|
|
|
+ if done:
|
|
|
+ raise primitive_functions.PrimitiveFinished(result)
|
|
|
+
|
|
|
+ local_args = {}
|
|
|
+ inner_kwargs = dict(kwargs)
|
|
|
+ for param_id, name in param_dict.items():
|
|
|
+ local_args[param_id] = inner_kwargs[name]
|
|
|
+ del inner_kwargs[name]
|
|
|
+
|
|
|
+ yield [("TAIL_CALL_ARGS",
|
|
|
+ [bytecode_interpreter.interpret_bytecode_function,
|
|
|
+ (function_name, body_bytecode, local_args, inner_kwargs)])]
|
|
|
+
|
|
|
+ jit.jit_globals[function_name] = __interpret_function
|
|
|
+ raise primitive_functions.PrimitiveFinished(__interpret_function)
|
|
|
+
|
|
|
+def compile_function_body_baseline(
|
|
|
+ jit, function_name, body_id, task_root,
|
|
|
+ header=None, compatible_temporary_protects=False):
|
|
|
"""Have the baseline JIT compile the function with the given name and body id."""
|
|
|
(parameter_ids, parameter_list, _), = yield [
|
|
|
("CALL_ARGS", [jit.jit_signature, (body_id,)])]
|
|
@@ -737,10 +769,14 @@ def compile_function_body_baseline(jit, function_name, body_id, task_root, heade
|
|
|
constructed_body, = yield [("CALL_ARGS", [optimize_tree_ir, (constructed_body,)])]
|
|
|
|
|
|
# Wrap the tree IR in a function definition.
|
|
|
+ constructed_function = create_function(
|
|
|
+ function_name, parameter_list, param_dict,
|
|
|
+ body_param_dict, constructed_body, jit.get_source_map_name(function_name),
|
|
|
+ compatible_temporary_protects)
|
|
|
+
|
|
|
+ # Convert the function definition to Python code, and compile it.
|
|
|
raise primitive_functions.PrimitiveFinished(
|
|
|
- create_function(
|
|
|
- function_name, parameter_list, param_dict,
|
|
|
- body_param_dict, constructed_body, jit.get_source_map_name(function_name)))
|
|
|
+ jit.jit_define_function(function_name, constructed_function))
|
|
|
|
|
|
def compile_function_body_fast(jit, function_name, body_id, _):
|
|
|
"""Have the fast JIT compile the function with the given name and body id."""
|
|
@@ -763,10 +799,11 @@ def compile_function_body_fast(jit, function_name, body_id, _):
|
|
|
|
|
|
# Optimize the tree that was generated.
|
|
|
constructed_body, = yield [("CALL_ARGS", [optimize_tree_ir, (constructed_body,)])]
|
|
|
+ constructed_function = create_bare_function(function_name, parameter_list, constructed_body)
|
|
|
+
|
|
|
+ # Convert the function definition to Python code, and compile it.
|
|
|
raise primitive_functions.PrimitiveFinished(
|
|
|
- create_bare_function(
|
|
|
- function_name, parameter_list,
|
|
|
- constructed_body))
|
|
|
+ jit.jit_define_function(function_name, constructed_function))
|
|
|
|
|
|
def favor_large_functions(body_bytecode):
|
|
|
"""Computes the initial temperature of a function based on the size of
|
|
@@ -782,13 +819,7 @@ def favor_large_functions(body_bytecode):
|
|
|
# in a situation where said function runs for a long time before we
|
|
|
# realize that we really should have jitted it. And that's exactly what
|
|
|
# this heuristic tries to avoid.
|
|
|
- return (
|
|
|
- len(body_bytecode.get_reachable()),
|
|
|
- lambda old_value:
|
|
|
- tree_ir.BinaryInstruction(
|
|
|
- old_value,
|
|
|
- '+',
|
|
|
- tree_ir.LiteralInstruction(1)))
|
|
|
+ return len(body_bytecode.get_reachable()), 1
|
|
|
|
|
|
def favor_small_functions(body_bytecode):
|
|
|
"""Computes the initial temperature of a function based on the size of
|
|
@@ -799,18 +830,15 @@ def favor_small_functions(body_bytecode):
|
|
|
# of fast-jit's algorithms. So it might be cheaper to fast-jit small
|
|
|
# functions and get a performance boost from that than to fast-jit large
|
|
|
# functions.
|
|
|
- return (
|
|
|
- ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD - len(body_bytecode.get_reachable()),
|
|
|
- lambda old_value:
|
|
|
- tree_ir.BinaryInstruction(
|
|
|
- old_value,
|
|
|
- '+',
|
|
|
- tree_ir.LiteralInstruction(1)))
|
|
|
+ return ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD - len(body_bytecode.get_reachable()), 1
|
|
|
|
|
|
ADAPTIVE_JIT_LOOP_INSTRUCTION_MULTIPLIER = 4
|
|
|
|
|
|
-ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD = 200
|
|
|
-"""The threshold temperature at which fast-jit will be used."""
|
|
|
+ADAPTIVE_BASELINE_JIT_TEMPERATURE_THRESHOLD = 100
|
|
|
+"""The threshold temperature at which the adaptive JIT will use the baseline JIT."""
|
|
|
+
|
|
|
+ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD = 250
|
|
|
+"""The threshold temperature at which the adaptive JIT will use the fast JIT."""
|
|
|
|
|
|
def favor_loops(body_bytecode):
|
|
|
"""Computes the initial temperature of a function. Code within a loop makes
|
|
@@ -818,22 +846,139 @@ def favor_loops(body_bytecode):
|
|
|
temperature is incremented by one on every call."""
|
|
|
reachable_instructions = body_bytecode.get_reachable()
|
|
|
# First set the temperature to the negative number of instructions.
|
|
|
- temperature = ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD - len(reachable_instructions)
|
|
|
+ temperature = ADAPTIVE_BASELINE_JIT_TEMPERATURE_THRESHOLD - len(reachable_instructions)
|
|
|
for instruction in reachable_instructions:
|
|
|
if isinstance(instruction, bytecode_ir.WhileInstruction):
|
|
|
# Then increase the temperature by the number of instructions reachable
|
|
|
# from loop bodies. Note that the algorithm will count nested loops twice.
|
|
|
# This is actually by design.
|
|
|
- loop_body_instructions = instruction.body.get_reachable()
|
|
|
+ loop_body_instructions = instruction.body.get_reachable(
|
|
|
+ lambda x: not isinstance(
|
|
|
+ x, (bytecode_ir.BreakInstruction, bytecode_ir.ContinueInstruction)))
|
|
|
temperature += ADAPTIVE_JIT_LOOP_INSTRUCTION_MULTIPLIER * len(loop_body_instructions)
|
|
|
|
|
|
- return (
|
|
|
- temperature,
|
|
|
- lambda old_value:
|
|
|
- tree_ir.BinaryInstruction(
|
|
|
- old_value,
|
|
|
- '+',
|
|
|
- tree_ir.LiteralInstruction(1)))
|
|
|
+ return temperature, 1
|
|
|
+
|
|
|
+def favor_small_loops(body_bytecode):
|
|
|
+ """Computes the initial temperature of a function. Code within a loop makes
|
|
|
+ the function hotter; code outside loops makes the function colder. The
|
|
|
+ temperature is incremented by one on every call."""
|
|
|
+ reachable_instructions = body_bytecode.get_reachable()
|
|
|
+ # First set the temperature to the negative number of instructions.
|
|
|
+ temperature = ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD - 50 - len(reachable_instructions)
|
|
|
+ for instruction in reachable_instructions:
|
|
|
+ if isinstance(instruction, bytecode_ir.WhileInstruction):
|
|
|
+ # Then increase the temperature by the number of instructions reachable
|
|
|
+ # from loop bodies. Note that the algorithm will count nested loops twice.
|
|
|
+ # This is actually by design.
|
|
|
+ loop_body_instructions = instruction.body.get_reachable(
|
|
|
+ lambda x: not isinstance(
|
|
|
+ x, (bytecode_ir.BreakInstruction, bytecode_ir.ContinueInstruction)))
|
|
|
+ temperature += (
|
|
|
+ (ADAPTIVE_JIT_LOOP_INSTRUCTION_MULTIPLIER ** 2) *
|
|
|
+ int(math.sqrt(len(loop_body_instructions))))
|
|
|
+
|
|
|
+ return temperature, max(int(math.log(len(reachable_instructions), 2)), 1)
|
|
|
+
|
|
|
+class AdaptiveJitState(object):
|
|
|
+ """Shared state for adaptive JIT compilation."""
|
|
|
+ def __init__(
|
|
|
+ self, temperature_counter_name,
|
|
|
+ temperature_increment, can_rejit_name):
|
|
|
+ self.temperature_counter_name = temperature_counter_name
|
|
|
+ self.temperature_increment = temperature_increment
|
|
|
+ self.can_rejit_name = can_rejit_name
|
|
|
+
|
|
|
+ def compile_interpreter(
|
|
|
+ self, jit, function_name, body_id, task_root):
|
|
|
+ """Compiles the given function as a function that controls the temperature counter
|
|
|
+ and calls the interpreter."""
|
|
|
+ def __increment_temperature(**kwargs):
|
|
|
+ if jit.jit_globals[self.can_rejit_name]:
|
|
|
+ temperature_counter_val = jit.jit_globals[self.temperature_counter_name]
|
|
|
+ temperature_counter_val += self.temperature_increment
|
|
|
+ jit.jit_globals[self.temperature_counter_name] = temperature_counter_val
|
|
|
+ if temperature_counter_val >= ADAPTIVE_BASELINE_JIT_TEMPERATURE_THRESHOLD:
|
|
|
+ if temperature_counter_val >= ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD:
|
|
|
+ yield [
|
|
|
+ ("CALL_ARGS",
|
|
|
+ [jit.jit_rejit,
|
|
|
+ (task_root, body_id, function_name, compile_function_body_fast)])]
|
|
|
+ else:
|
|
|
+ yield [
|
|
|
+ ("CALL_ARGS",
|
|
|
+ [jit.jit_rejit,
|
|
|
+ (task_root, body_id, function_name, self.compile_baseline)])]
|
|
|
+ result, = yield [("CALL_KWARGS", [jit.jit_globals[function_name], kwargs])]
|
|
|
+ raise primitive_functions.PrimitiveFinished((True, result))
|
|
|
+
|
|
|
+ raise primitive_functions.PrimitiveFinished((False, None))
|
|
|
+
|
|
|
+ yield [
|
|
|
+ ("TAIL_CALL_ARGS",
|
|
|
+ [compile_function_body_interpret,
|
|
|
+ (jit, function_name, body_id, task_root, __increment_temperature)])]
|
|
|
+
|
|
|
+ def compile_baseline(
|
|
|
+ self, jit, function_name, body_id, task_root):
|
|
|
+ """Compiles the given function with the baseline JIT, and inserts logic that controls
|
|
|
+ the temperature counter."""
|
|
|
+ (_, parameter_list, _), = yield [
|
|
|
+ ("CALL_ARGS", [jit.jit_signature, (body_id,)])]
|
|
|
+
|
|
|
+ # This tree represents the following logic:
|
|
|
+ #
|
|
|
+ # if can_rejit:
|
|
|
+ # global temperature_counter
|
|
|
+ # temperature_counter = temperature_counter + temperature_increment
|
|
|
+ # if temperature_counter >= ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD:
|
|
|
+ # yield [("CALL_KWARGS", [jit_runtime.JIT_REJIT_FUNCTION_NAME, {...}])]
|
|
|
+ # yield [("TAIL_CALL_KWARGS", [function_name, {...}])]
|
|
|
+
|
|
|
+ header = tree_ir.SelectInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction(self.can_rejit_name),
|
|
|
+ tree_ir.create_block(
|
|
|
+ tree_ir.DeclareGlobalInstruction(self.temperature_counter_name),
|
|
|
+ tree_ir.IgnoreInstruction(
|
|
|
+ tree_ir.StoreGlobalInstruction(
|
|
|
+ self.temperature_counter_name,
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction(self.temperature_counter_name),
|
|
|
+ '+',
|
|
|
+ tree_ir.LiteralInstruction(self.temperature_increment)))),
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction(self.temperature_counter_name),
|
|
|
+ '>=',
|
|
|
+ tree_ir.LiteralInstruction(ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD)),
|
|
|
+ tree_ir.create_block(
|
|
|
+ tree_ir.RunGeneratorFunctionInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction(jit_runtime.JIT_REJIT_FUNCTION_NAME),
|
|
|
+ tree_ir.DictionaryLiteralInstruction([
|
|
|
+ (tree_ir.LiteralInstruction('task_root'),
|
|
|
+ bytecode_to_tree.load_task_root()),
|
|
|
+ (tree_ir.LiteralInstruction('body_id'),
|
|
|
+ tree_ir.LiteralInstruction(body_id)),
|
|
|
+ (tree_ir.LiteralInstruction('function_name'),
|
|
|
+ tree_ir.LiteralInstruction(function_name)),
|
|
|
+ (tree_ir.LiteralInstruction('compile_function_body'),
|
|
|
+ tree_ir.LoadGlobalInstruction(
|
|
|
+ jit_runtime.JIT_COMPILE_FUNCTION_BODY_FAST_FUNCTION_NAME))]),
|
|
|
+ result_type=tree_ir.NO_RESULT_TYPE),
|
|
|
+ bytecode_to_tree.create_return(
|
|
|
+ tree_ir.create_jit_call(
|
|
|
+ tree_ir.LoadGlobalInstruction(function_name),
|
|
|
+ [(name, tree_ir.LoadLocalInstruction(name))
|
|
|
+ for name in parameter_list],
|
|
|
+ tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME)))),
|
|
|
+ tree_ir.EmptyInstruction())),
|
|
|
+ tree_ir.EmptyInstruction())
|
|
|
+
|
|
|
+ # Compile with the baseline JIT, and insert the header.
|
|
|
+ yield [
|
|
|
+ ("TAIL_CALL_ARGS",
|
|
|
+ [compile_function_body_baseline,
|
|
|
+ (jit, function_name, body_id, task_root, header, True)])]
|
|
|
|
|
|
def compile_function_body_adaptive(
|
|
|
jit, function_name, body_id, task_root,
|
|
@@ -846,72 +991,43 @@ def compile_function_body_adaptive(
|
|
|
# and gets incremented every time the function is executed.
|
|
|
|
|
|
body_bytecode, = yield [("CALL_ARGS", [jit.jit_parse_bytecode, (body_id,)])]
|
|
|
- initial_temperature, increment_temperature = temperature_heuristic(body_bytecode)
|
|
|
- print('Initial temperature for %s: %d' % (function_name, initial_temperature))
|
|
|
+ initial_temperature, temperature_increment = temperature_heuristic(body_bytecode)
|
|
|
+ if jit.jit_success_log_function is not None:
|
|
|
+ jit.jit_success_log_function(
|
|
|
+ "Initial temperature for '%s': %d" % (function_name, initial_temperature))
|
|
|
|
|
|
if initial_temperature >= ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD:
|
|
|
# Initial temperature exceeds the fast-jit threshold.
|
|
|
# Compile this thing with fast-jit right away.
|
|
|
+ if jit.jit_success_log_function is not None:
|
|
|
+ jit.jit_success_log_function(
|
|
|
+ "Compiling '%s' with fast-jit." % function_name)
|
|
|
yield [
|
|
|
("TAIL_CALL_ARGS",
|
|
|
[compile_function_body_fast, (jit, function_name, body_id, task_root)])]
|
|
|
|
|
|
- (_, parameter_list, _), = yield [
|
|
|
- ("CALL_ARGS", [jit.jit_signature, (body_id,)])]
|
|
|
-
|
|
|
temperature_counter_name = jit.import_value(
|
|
|
initial_temperature, function_name + "_temperature_counter")
|
|
|
|
|
|
can_rejit_name = jit.get_can_rejit_name(function_name)
|
|
|
jit.jit_globals[can_rejit_name] = True
|
|
|
|
|
|
- # This tree represents the following logic:
|
|
|
- #
|
|
|
- # if can_rejit:
|
|
|
- # global temperature_counter
|
|
|
- # temperature_counter = increment_temperature(temperature_counter)
|
|
|
- # if temperature_counter >= ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD:
|
|
|
- # yield [("CALL_KWARGS", [jit_runtime.JIT_REJIT_FUNCTION_NAME, {...}])]
|
|
|
- # yield [("TAIL_CALL_KWARGS", [function_name, {...}])]
|
|
|
-
|
|
|
- header = tree_ir.SelectInstruction(
|
|
|
- tree_ir.LoadGlobalInstruction(can_rejit_name),
|
|
|
- tree_ir.create_block(
|
|
|
- tree_ir.DeclareGlobalInstruction(temperature_counter_name),
|
|
|
- tree_ir.IgnoreInstruction(
|
|
|
- tree_ir.StoreGlobalInstruction(
|
|
|
- temperature_counter_name,
|
|
|
- increment_temperature(
|
|
|
- tree_ir.LoadGlobalInstruction(temperature_counter_name)))),
|
|
|
- tree_ir.SelectInstruction(
|
|
|
- tree_ir.BinaryInstruction(
|
|
|
- tree_ir.LoadGlobalInstruction(temperature_counter_name),
|
|
|
- '>=',
|
|
|
- tree_ir.LiteralInstruction(ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD)),
|
|
|
- tree_ir.create_block(
|
|
|
- tree_ir.RunGeneratorFunctionInstruction(
|
|
|
- tree_ir.LoadGlobalInstruction(jit_runtime.JIT_REJIT_FUNCTION_NAME),
|
|
|
- tree_ir.DictionaryLiteralInstruction([
|
|
|
- (tree_ir.LiteralInstruction('task_root'),
|
|
|
- bytecode_to_tree.load_task_root()),
|
|
|
- (tree_ir.LiteralInstruction('body_id'),
|
|
|
- tree_ir.LiteralInstruction(body_id)),
|
|
|
- (tree_ir.LiteralInstruction('function_name'),
|
|
|
- tree_ir.LiteralInstruction(function_name)),
|
|
|
- (tree_ir.LiteralInstruction('compile_function_body'),
|
|
|
- tree_ir.LoadGlobalInstruction(
|
|
|
- jit_runtime.JIT_COMPILE_FUNCTION_BODY_FAST_FUNCTION_NAME))]),
|
|
|
- result_type=tree_ir.NO_RESULT_TYPE),
|
|
|
- tree_ir.create_jit_call(
|
|
|
- tree_ir.LoadGlobalInstruction(function_name),
|
|
|
- [(name, tree_ir.LoadLocalInstruction(name)) for name in parameter_list],
|
|
|
- tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME),
|
|
|
- tree_ir.RunTailGeneratorFunctionInstruction)),
|
|
|
- tree_ir.EmptyInstruction())),
|
|
|
- tree_ir.EmptyInstruction())
|
|
|
-
|
|
|
- # Compile with the baseline JIT, and insert the header.
|
|
|
- yield [
|
|
|
- ("TAIL_CALL_ARGS",
|
|
|
- [compile_function_body_baseline,
|
|
|
- (jit, function_name, body_id, task_root, header)])]
|
|
|
+ state = AdaptiveJitState(temperature_counter_name, temperature_increment, can_rejit_name)
|
|
|
+
|
|
|
+ if initial_temperature >= ADAPTIVE_BASELINE_JIT_TEMPERATURE_THRESHOLD:
|
|
|
+ # Initial temperature exceeds the baseline JIT threshold.
|
|
|
+ # Compile this thing with baseline JIT right away.
|
|
|
+ if jit.jit_success_log_function is not None:
|
|
|
+ jit.jit_success_log_function(
|
|
|
+ "Compiling '%s' with baseline-jit." % function_name)
|
|
|
+ yield [
|
|
|
+ ("TAIL_CALL_ARGS",
|
|
|
+ [state.compile_baseline, (jit, function_name, body_id, task_root)])]
|
|
|
+ else:
|
|
|
+ # Looks like we'll use the interpreter initially.
|
|
|
+ if jit.jit_success_log_function is not None:
|
|
|
+ jit.jit_success_log_function(
|
|
|
+ "Compiling '%s' with bytecode-interpreter." % function_name)
|
|
|
+ yield [
|
|
|
+ ("TAIL_CALL_ARGS",
|
|
|
+ [state.compile_interpreter, (jit, function_name, body_id, task_root)])]
|