All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.codegen.inline.InliningContext.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.codegen.inline

import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState

class RootInliningContext(
    state: GenerationState,
    nameGenerator: NameGenerator,
    val sourceCompilerForInline: SourceCompilerForInline,
    override val callSiteInfo: InlineCallSiteInfo,
    val inlineMethodReifier: ReifiedTypeInliner<*>,
    typeParameterMappings: TypeParameterMappings<*>
) : InliningContext(
    null, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false
)

class RegeneratedClassContext(
    parent: InliningContext,
    state: GenerationState,
    nameGenerator: NameGenerator,
    typeRemapper: TypeRemapper,
    lambdaInfo: LambdaInfo?,
    override val callSiteInfo: InlineCallSiteInfo,
    override val transformationInfo: TransformationInfo
) : InliningContext(
    parent, state, nameGenerator, typeRemapper, lambdaInfo, true
) {
    val continuationBuilders: MutableMap = hashMapOf()
}

open class InliningContext(
    val parent: InliningContext?,
    val state: GenerationState,
    val nameGenerator: NameGenerator,
    val typeRemapper: TypeRemapper,
    val lambdaInfo: LambdaInfo?,
    val classRegeneration: Boolean
) {
    val isInliningLambda
        get() = lambdaInfo != null

    // Consider this arrangement:
    //     inline fun  f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
    //     inline fun  g() = f<...> { /* uses `V` in a local class */ }
    // When inlining `f` into `g`, we need to reify the contents of the default for `x` (if it was used), but not the
    // contents of the lambda passed as the argument in `g` as all reified type parameters used by the latter are not from `f`.
    val shouldReifyTypeParametersInObjects: Boolean
        get() = lambdaInfo == null || lambdaInfo is DefaultLambda

    var generateAssertField = false

    open val transformationInfo: TransformationInfo?
        get() = null

    var isContinuation: Boolean = false

    val isRoot: Boolean
        get() = parent == null

    val root: RootInliningContext
        get() = if (isRoot) this as RootInliningContext else parent!!.root

    private val regeneratedAnonymousObjects = hashSetOf()

    fun isRegeneratedAnonymousObject(internalName: String): Boolean =
        internalName in regeneratedAnonymousObjects || (parent != null && parent.isRegeneratedAnonymousObject(internalName))

    fun recordRegeneratedAnonymousObject(internalName: String) {
        regeneratedAnonymousObjects.add(internalName)
    }

    fun subInlineLambda(lambdaInfo: LambdaInfo): InliningContext =
        subInline(
            nameGenerator.subGenerator("lambda"),
            //mark lambda inlined
            hashMapOf(lambdaInfo.lambdaClassType.internalName to null),
            lambdaInfo,
            // TODO we also want this for the old backend (KT-28064), but this changes EnclosingMethod of objects
            //      in inline lambdas, so use a language version flag.
            if (state.isIrBackend)
                false // Do not regenerate objects in lambdas inlined into regenerated objects unless needed for some other reason.
            else
                classRegeneration
        )

    fun subInlineWithClassRegeneration(
        generator: NameGenerator,
        newTypeMappings: MutableMap,
        callSiteInfo: InlineCallSiteInfo,
        transformationInfo: TransformationInfo
    ): RegeneratedClassContext = RegeneratedClassContext(
        this, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings),
        lambdaInfo, callSiteInfo, transformationInfo
    )

    @JvmOverloads
    fun subInline(
        generator: NameGenerator,
        additionalTypeMappings: Map = emptyMap(),
        lambdaInfo: LambdaInfo? = this.lambdaInfo,
        classRegeneration: Boolean = this.classRegeneration
    ): InliningContext {
        val isInliningLambda = lambdaInfo != null
        return InliningContext(
            this, state, generator,
            TypeRemapper.createFrom(
                typeRemapper,
                additionalTypeMappings,
                //root inline lambda
                isInliningLambda && !this.isInliningLambda
            ),
            lambdaInfo, classRegeneration
        )
    }

    open val callSiteInfo: InlineCallSiteInfo
        get() {
            return parent!!.callSiteInfo
        }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy