Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QoL improvements to python_to_native and compiler_cache #444

Draft
wants to merge 1 commit into
base: will-inline-cached-functions
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 213 additions & 163 deletions typed_python/compiler/compiler_cache.py

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions typed_python/compiler/expression_conversion_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def allocateClassMethodDispatchSlot(self, clsType, methodName, retType, argTuple
# the first argument indicates whether this is an instance or type-level dispatch
assert argTupleType.ElementTypes[0].Value in ('type', 'instance')

identHash = self.converter.hashObjectToIdentity(
identHash = self.converter.hash_object_to_identity(
(clsType, methodName, retType, argTupleType, kwargTupleType)
)

Expand Down Expand Up @@ -1141,7 +1141,7 @@ def call_py_function(self, f, args, kwargs, returnTypeOverload=None):
funcGlobals[f.__code__.co_freevars[i]] = f.__closure__[i].cell_contents
globalsInCells.append(f.__code__.co_freevars[i])

call_target = self.functionContext.converter.convert(
call_target = self.functionContext.converter.convert_python_to_native(
f.__name__,
f.__code__,
funcGlobals,
Expand Down Expand Up @@ -1185,7 +1185,7 @@ def call_overload(self, overload, funcObj, args, kwargs, returnTypeOverload=None
else:
returnType = typeWrapper(overload.returnType) if overload.returnType is not None else None

call_target = self.functionContext.converter.convert(
call_target = self.functionContext.converter.convert_python_to_native(
overload.name,
overload.functionCode,
overload.realizedGlobals,
Expand Down Expand Up @@ -1474,7 +1474,7 @@ def namedVariableLookup(self, name):
return None

def expressionAsFunctionCall(self, name, args, generatingFunction, identity, outputType=None, alwaysRaises=False):
callTarget = self.converter.defineNonPythonFunction(
callTarget = self.converter.define_non_python_function(
name,
("expression", identity),
typed_python.compiler.function_conversion_context.ExpressionFunctionConversionContext(
Expand Down
6 changes: 3 additions & 3 deletions typed_python/compiler/function_conversion_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,17 +621,17 @@ def __iter__(self) -> generatorBaseclass:

returnSlot.convert_copy_initialize(output)

context.converter.triggerVirtualDestructor(generatorSubclass)
context.converter.trigger_virtual_destructor(generatorSubclass)

context.converter.triggerVirtualMethodInstantiation(
context.converter.trigger_virtual_method_instantiation(
generatorSubclass,
"__fastnext__",
PointerTo(T),
Tuple("instance"),
NamedTuple()
)

context.converter.triggerVirtualMethodInstantiation(
context.converter.trigger_virtual_method_instantiation(
generatorSubclass,
"__next__",
T,
Expand Down
2 changes: 1 addition & 1 deletion typed_python/compiler/llvm_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def buildSharedObject(self, functions):
serializedGlobalVariableDefinitions,
module.functionNameToType,
module.globalDependencies,
{name: self.converter.totalFunctionComplexity(name) for name in functions},
{name: self.converter.total_function_complexity(name) for name in functions},
{name: self.converter._functions_by_name[name] for name in functions},
{name: SerializationContext().serialize(self.converter._function_definitions[name]) for name in functions},
)
Expand Down
2 changes: 1 addition & 1 deletion typed_python/compiler/llvm_compiler_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def test_loaded_modules_persist():
" return f(x) * 100",
"g(1000)",
"def get_loaded_modules():",
" return len(Runtime.singleton().converter.loadedUncachedModules)"
" return len(Runtime.singleton().converter.loaded_uncached_modules)"
])
VERSION1 = {'x.py': xmodule}
assert evaluateExprInFreshProcess(VERSION1, 'x.get_loaded_modules()') == 1
24 changes: 12 additions & 12 deletions typed_python/compiler/native_ast_to_llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ def __init__(self,
# a list of the global LLVM names that the function depends on.
self.global_names = []
self.module = module
self.converter = converter
self.converter: Converter = converter
self.builder = builder
self.arg_assignments = arg_assignments
self.output_type = output_type
Expand Down Expand Up @@ -665,24 +665,24 @@ def namedCallTargetToLLVM(self, target: native_ast.NamedCallTarget) -> TypedLLVM
if func.module is not self.module:
# first, see if we'd like to inline this module
if (
self.converter.totalFunctionComplexity(target.name) < CROSS_MODULE_INLINE_COMPLEXITY
self.converter.total_function_complexity(target.name) < CROSS_MODULE_INLINE_COMPLEXITY
):
func = self.converter.repeatFunctionInModule(target.name, self.module)
func = self.converter.repeat_function_in_module(target.name, self.module)
else:
if target.name not in self.external_function_references:
self.external_function_references[target.name] = \
llvmlite.ir.Function(self.module, func.function_type, func.name)

func = self.external_function_references[target.name]
else:
assert self.compilerCache is not None and self.compilerCache.hasSymbol(target.name)
assert self.compilerCache is not None and self.compilerCache.has_symbol(target.name)
# this function is defined in a shared object that we've loaded from a prior
# invocation. Again, first make an inlining decision.
if (
self.compilerCache.complexityForSymbol(target.name) < CROSS_MODULE_INLINE_COMPLEXITY
self.compilerCache.complexity_for_symbol(target.name) < CROSS_MODULE_INLINE_COMPLEXITY
):
self.converter.generateDefinition(target.name)
func = self.converter.repeatFunctionInModule(target.name, self.module)
self.converter.generate_definition(target.name)
func = self.converter.repeat_function_in_module(target.name, self.module)
else:
if target.name not in self.external_function_references:
func_type = llvmlite.ir.FunctionType(
Expand Down Expand Up @@ -1518,7 +1518,7 @@ def __init__(self, compilerCache=None):

self.compilerCache = compilerCache

def totalFunctionComplexity(self, name):
def total_function_complexity(self, name):
"""Return the total number of instructions contained in a function.

The function must already have been defined in a prior pass. We use this
Expand All @@ -1535,19 +1535,19 @@ def totalFunctionComplexity(self, name):

return res

def generateDefinition(self, name: str) -> None:
def generate_definition(self, name: str) -> None:
"""Pull the TypedCallTarget matching `name` from the cache, and use to rebuild
the function definition. Add to _function_definitions and _functions_by_name.
"""
assert self.compilerCache is not None

definition = self.compilerCache.getDefinition(name)
llvm_func = self.compilerCache.getIR(name)
definition = self.compilerCache.get_definition(name)
llvm_func = self.compilerCache.get_IR(name)

self._functions_by_name[name] = llvm_func
self._function_definitions[name] = definition

def repeatFunctionInModule(self, name, module):
def repeat_function_in_module(self, name, module):
"""Request that the function given by 'name' be inlined into 'module'.

It must already have been defined in another module.
Expand Down
Loading