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

org.jetbrains.kotlin.codegen.coroutines.ChangeBoxingMethodTransformer.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
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.coroutines

import org.jetbrains.kotlin.codegen.optimization.boxing.isPrimitiveBoxing
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.codegen.topLevelClassInternalName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*

private val BOXING_CLASS_INTERNAL_NAME =
    RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()

@OptIn(ExperimentalStdlibApi::class)
object ChangeBoxingMethodTransformer : MethodTransformer() {
    private val wrapperToInternalBoxing: Map

    init {
        val map = hashMapOf()
        for (primitiveType in JvmPrimitiveType.values()) {
            val name = primitiveType.wrapperFqName.topLevelClassInternalName()
            map[name] = "box${primitiveType.javaKeywordName.capitalize(Locale.US)}"
        }
        wrapperToInternalBoxing = map
    }

    override fun transform(internalClassName: String, methodNode: MethodNode) {
        for (boxing in methodNode.instructions.asSequence().filter { it.isPrimitiveBoxing() }) {
            assert(boxing.opcode == Opcodes.INVOKESTATIC) {
                "boxing shall be INVOKESTATIC wrapper.valueOf"
            }
            boxing as MethodInsnNode
            val methodName = wrapperToInternalBoxing[boxing.owner].sure {
                "expected primitive wrapper, but got ${boxing.owner}"
            }
            methodNode.instructions.set(
                boxing,
                MethodInsnNode(boxing.opcode, BOXING_CLASS_INTERNAL_NAME, methodName, boxing.desc, false)
            )
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy