JVM: inline (!) some DescriptorAsmUtils methods into the inliner

Easier to work with it that way
This commit is contained in:
pyos
2022-04-28 14:40:33 +02:00
committed by Mikhael Bogdanov
parent 2f6c80f06f
commit 60c27affbb
2 changed files with 25 additions and 81 deletions
@@ -22,10 +22,8 @@ import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import java.util.*
@@ -44,7 +42,6 @@ class AnonymousObjectTransformer(
private var constructor: MethodNode? = null
private lateinit var sourceMap: SMAP
private lateinit var sourceMapper: SourceMapper
private val languageVersionSettings = inliningContext.state.languageVersionSettings
// TODO: use IrTypeMapper in the IR backend
private val typeMapper: KotlinTypeMapperBase = state.typeMapper
@@ -107,7 +104,7 @@ class AnonymousObjectTransformer(
return if (isCapturedFieldName(name)) {
null
} else {
classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value)
classBuilder.newField(NO_ORIGIN, access, name, desc, signature, value)
}
}
@@ -349,29 +346,9 @@ class AnonymousObjectTransformer(
parentRemapper: FieldRemapper,
constructorAdditionalFakeParams: List<CapturedParamInfo>
) {
val descTypes = ArrayList<Type>()
val constructorParams = constructorInlineBuilder.buildParameters()
val capturedIndexes = IntArray(constructorParams.parameters.size)
var index = 0
var size = 0
//complex processing cause it could have super constructor call params
for (info in constructorParams) {
if (!info.isSkipped) { //not inlined
if (info.isCaptured || info is CapturedParamInfo) {
capturedIndexes[index] = size
index++
}
if (size != 0) { //skip this
descTypes.add(info.type)
}
size += info.type.size
}
}
val constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *descTypes.toTypedArray())
val constructorParamTypes = constructorParams.filter { !it.isSkipped }.map { it.type }.drop(1)
val constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *constructorParamTypes.toTypedArray())
//TODO for inline method make public class
transformationInfo.newConstructorDescriptor = constructorDescriptor
val constructorVisitor = classBuilder.newMethod(
@@ -380,14 +357,28 @@ class AnonymousObjectTransformer(
val newBodyStartLabel = Label()
constructorVisitor.visitLabel(newBodyStartLabel)
//initialize captured fields
val newFieldsWithSkipped = getNewFieldsToGenerate(allCapturedBuilder.listCaptured())
val fieldInfoWithSkipped = transformToFieldInfo(Type.getObjectType(transformationInfo.newClassName), newFieldsWithSkipped)
val capturedFieldInitializer = InstructionAdapter(constructorVisitor)
fieldInfoWithSkipped.forEachIndexed { paramIndex, fieldInfo ->
if (!newFieldsWithSkipped[paramIndex].skip) {
DescriptorAsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer)
//initialize captured fields
val capturedIndexes = IntArray(constructorParams.parameters.size)
var index = 0
var size = 0
for (info in constructorParams) {
if (!info.isSkipped) { //not inlined
if (info.isCaptured || info is CapturedParamInfo) {
capturedIndexes[index] = size
index++
}
size += info.type.size
}
}
for ((paramIndex, info) in allCapturedBuilder.listCaptured().filter { it.functionalArgument !is LambdaInfo }.withIndex()) {
if (!info.isSkipInConstructor) {
val desc = info.type.descriptor
val access = AsmUtil.NO_FLAG_PACKAGE_PRIVATE or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_FINAL
classBuilder.newField(NO_ORIGIN, access, info.newFieldName, desc, null, null)
constructorVisitor.visitVarInsn(Opcodes.ALOAD, 0)
constructorVisitor.visitVarInsn(info.type.getOpcode(Opcodes.ILOAD), capturedIndexes[paramIndex])
constructorVisitor.visitFieldInsn(Opcodes.PUTFIELD, transformationInfo.newClassName, info.newFieldName, desc)
}
}
@@ -417,7 +408,7 @@ class AnonymousObjectTransformer(
val first = intermediateMethodNode.instructions.first
val oldStartLabel = (first as? LabelNode)?.label
intermediateMethodNode.accept(object : MethodBodyVisitor(capturedFieldInitializer) {
intermediateMethodNode.accept(object : MethodBodyVisitor(constructorVisitor) {
override fun visitLocalVariable(
name: String, desc: String, signature: String?, start: Label, end: Label, index: Int
) {
@@ -430,9 +421,6 @@ class AnonymousObjectTransformer(
}
})
constructorVisitor.visitEnd()
DescriptorAsmUtil.genClosureFields(
toNameTypePair(filterSkipped(newFieldsWithSkipped)), classBuilder
)
}
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
@@ -1,44 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.inline
import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.FieldInfo
import org.jetbrains.org.objectweb.asm.Type
class NewJavaField(val name: String, val type: Type, val skip: Boolean)
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
return params.filter {
//not inlined
it.functionalArgument !is LambdaInfo
}.map {
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
}
}
fun transformToFieldInfo(lambdaType: Type, newFields: List<NewJavaField>): List<FieldInfo> {
return newFields.map { field ->
FieldInfo.createForHiddenField(lambdaType, field.type, field.name)
}
}
fun filterSkipped(fields: List<NewJavaField>): List<NewJavaField> {
return fields.filter { !it.skip }
}
fun toNameTypePair(fields: List<NewJavaField>): List<Pair<String, Type>> = fields.map { Pair(it.name, it.type) }