函数内联是 Kotlin 编译器中的一项关键优化技术,它通过在调用点将函数调用替换为函数的实际主体来实现。本文档提供了 Kotlin 编译器中函数内联实现的详细技术概述,重点关注 IR(中间表示)阶段。有关编译阶段的总体信息,请参阅 Kotlin 编译器与工具概述。
Kotlin 中的函数内联系统具有多种用途:
内联过程实现为一组作用于 IR 树的 IR 转换。它根据目标平台以多个阶段运行,并通过 Kotlin 源代码中的 inline 修饰符进行控制。
来源
函数内联实现包含几个协同工作的关键组件,以执行内联转换。
The FunctionInlining 类是内联过程的主要入口点。它扩展了 IrTransformer<IrDeclaration> 并实现了 BodyLoweringPass 接口,使其成为 IR 降低流水线的一部分。
The FunctionInlining 构造函数接受
context:提供对编译器服务的访问权限的 LoweringContextinlineFunctionResolver:负责确定应内联哪些函数的 InlineFunctionResolverThe main method is visitFunctionAccess,它在 IR 树中为每个函数调用调用。它确定函数是否应被内联并启动内联过程。
来源
The InlineFunctionResolver determines which functions should be inlined. It provides the following key methods
needsInlining(symbol: IrFunctionSymbol): Determines if a function should be inlinedneedsInlining(expression: IrFunctionAccessExpression): Determines if a function call should be inlinedgetFunctionDeclaration(symbol: IrFunctionSymbol): Retrieves the declaration of the function to be inlinedThe resolver operates in different modes (InlineMode)
PRIVATE_INLINE_FUNCTIONS: Only inline private functionsALL_INLINE_FUNCTIONS: Inline all functions marked with the inline modifierALL_FUNCTIONS: Inline all functions (rarely used, mainly for testing)Each target platform (JVM, JS, Native, Wasm) has its own implementation of the resolver to handle platform-specific concerns.
来源
The CallInlining inner class within FunctionInlining performs the actual inlining of a function. Its main methods include
inline(callSite: IrFunctionAccessExpression, parent: IrDeclarationParent): The entry point for inlining a function callinlineFunction(callSite: IrFunctionAccessExpression, callee: IrFunction, originalInlinedElement: IrElement): Creates an IR block representing the inlined functionevaluateArguments(...): Evaluates function arguments and substitutes parametersThis class handles the complex logic of
来源
The InlinePostprocessor inner class within CallInlining transforms the inlined function body. It
来源
The function inlining process consists of several steps, outlined below.
The process begins when FunctionInlining.visitFunctionAccess is called for a function call. It asks the InlineFunctionResolver if the function should be inlined
The resolver checks various conditions
inline modifier?For example, in the first phase of inlining, only private inline functions are inlined
来源
Before inlining, the function body is preprocessed to handle type substitution and other transformations
This processing substitutes type parameters in the function body with the actual type arguments from the call site.
来源
The evaluateArguments method in CallInlining handles
The substituteMap maps each parameter of the inlined function to the expression that should replace it in the inlined code.
来源
The InlinePostprocessor transforms return statements in the inlined function
This redirects the return to the returnable block that wraps the inlined function body, ensuring correct control flow.
来源
The InlinePostprocessor also transforms references to parameters
This replaces each reference to a parameter with the corresponding argument expression from the substituteMap.
来源
When an inline lambda is called within an inlined function, it's also inlined
This process is recursive - lambdas passed to inline functions are themselves inlined at their call sites, potentially multiple levels deep.
来源
Callable references (e.g., ::function) passed to inline functions require special handling. They are first transformed to lambda expressions by the InlineCallableReferenceToLambdaPhase
The transformation creates a lambda that delegates to the original function
来源
由于挂起函数会转换为 continuation-passing 风格(CPS)的转换,因此在内联时需要特殊处理。AddContinuationLowering 类负责处理此问题。
这确保了在内联挂起函数时,continuation 参数能够被正确处理。
来源
从内联函数访问的私有成员需要合成访问器。SyntheticAccessorLowering 创建这些访问器。
这些访问器确保私有成员可以从内联代码中访问。
来源
每个后端(JVM、Native、JS、Wasm)在函数内联方面都有自己的方法,但它们都使用通用的 FunctionInlining 基础设施。
JVM 后端通过 JvmIrInliner 和 JvmInlineFunctionResolver 实现内联。它处理 JVM 特定的问题,例如:
来源
Native 后端使用 NativeIrInliner 和 NativeInlineFunctionResolver。它处理:
来源
JS 后端通过 JsLoweringPhases.kt 中的阶段实现内联。它处理:
来源
Wasm 后端使用 WasmFunctionInlining,其关注点与 JS 后端类似,但针对 WebAssembly 进行了调整。
来源
函数内联被集成到 IR 降低管线中,作为一系列阶段。典型的顺序是:
确切的顺序因后端而异,并在特定平台的降低阶段文件中定义。
来源
内联系统包含对内联代码调试的支持。这包括:
例如,在 JVM 后端中
这使得调试器在单步执行内联代码时能够正确显示源代码和变量。
来源
函数内联是 Kotlin 编译器中一个复杂但至关重要的优化。它在 IR 级别进行操作,用函数体替换函数调用,同时处理许多特殊情况和特定于平台的要求。该系统设计得非常灵活,为各种目标平台提供了不同的阶段和解析器实现,确保了在所有支持的平台上进行高效且正确的内联。
对于任何从事 Kotlin 编译器工作或开发与内联代码交互的优化的人来说,理解这个系统至关重要。
刷新此 Wiki
最后索引时间2025 年 4 月 18 日(dc0dea)