Use our own primitive boxing methods in coroutines codegen

#KT-26490 Fixed
This commit is contained in:
Ilmir Usmanov
2018-09-12 15:35:07 +03:00
parent 273889d1a9
commit e9fc65c7ae
7 changed files with 105 additions and 1 deletions
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
object ChangeBoxingMethodTransformer : MethodTransformer() {
private val wrapperToInternalBoxing: Map<String, String>
init {
val map = hashMapOf<String, String>()
for (primitiveType in JvmPrimitiveType.values()) {
val name = primitiveType.wrapperFqName.topLevelClassInternalName()
map[name] = "box${primitiveType.javaKeywordName.capitalize()}"
}
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)
)
}
}
}
@@ -83,6 +83,9 @@ class CoroutineTransformerMethodVisitor(
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
RedundantLocalsEliminationMethodTransformer(languageVersionSettings).transform(containingClassInternalName, methodNode)
if (languageVersionSettings.isReleaseCoroutines()) {
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
}
updateMaxStack(methodNode)
val suspensionPoints = collectSuspensionPoints(methodNode)
@@ -56,7 +56,7 @@ const val DO_RESUME_METHOD_NAME = "doResume"
const val INVOKE_SUSPEND_METHOD_NAME = "invokeSuspend"
const val EXCEPTION_FIELD_NAME = "exception"
private val RELEASE_COROUTINES_VERSION_SETTINGS = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)
val RELEASE_COROUTINES_VERSION_SETTINGS = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)
fun LanguageVersionSettings.isResumeImplMethodName(name: String) =
if (isReleaseCoroutines())