JVM: inline (!) some DescriptorAsmUtils methods into the inliner
Easier to work with it that way
This commit is contained in:
+25
-37
@@ -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.deserialization.JvmProtoBufUtil
|
||||||
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
|
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
|
||||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
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.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
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.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -44,7 +42,6 @@ class AnonymousObjectTransformer(
|
|||||||
private var constructor: MethodNode? = null
|
private var constructor: MethodNode? = null
|
||||||
private lateinit var sourceMap: SMAP
|
private lateinit var sourceMap: SMAP
|
||||||
private lateinit var sourceMapper: SourceMapper
|
private lateinit var sourceMapper: SourceMapper
|
||||||
private val languageVersionSettings = inliningContext.state.languageVersionSettings
|
|
||||||
|
|
||||||
// TODO: use IrTypeMapper in the IR backend
|
// TODO: use IrTypeMapper in the IR backend
|
||||||
private val typeMapper: KotlinTypeMapperBase = state.typeMapper
|
private val typeMapper: KotlinTypeMapperBase = state.typeMapper
|
||||||
@@ -107,7 +104,7 @@ class AnonymousObjectTransformer(
|
|||||||
return if (isCapturedFieldName(name)) {
|
return if (isCapturedFieldName(name)) {
|
||||||
null
|
null
|
||||||
} else {
|
} 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,
|
parentRemapper: FieldRemapper,
|
||||||
constructorAdditionalFakeParams: List<CapturedParamInfo>
|
constructorAdditionalFakeParams: List<CapturedParamInfo>
|
||||||
) {
|
) {
|
||||||
val descTypes = ArrayList<Type>()
|
|
||||||
|
|
||||||
val constructorParams = constructorInlineBuilder.buildParameters()
|
val constructorParams = constructorInlineBuilder.buildParameters()
|
||||||
val capturedIndexes = IntArray(constructorParams.parameters.size)
|
val constructorParamTypes = constructorParams.filter { !it.isSkipped }.map { it.type }.drop(1)
|
||||||
var index = 0
|
val constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *constructorParamTypes.toTypedArray())
|
||||||
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())
|
|
||||||
//TODO for inline method make public class
|
//TODO for inline method make public class
|
||||||
transformationInfo.newConstructorDescriptor = constructorDescriptor
|
transformationInfo.newConstructorDescriptor = constructorDescriptor
|
||||||
val constructorVisitor = classBuilder.newMethod(
|
val constructorVisitor = classBuilder.newMethod(
|
||||||
@@ -380,14 +357,28 @@ class AnonymousObjectTransformer(
|
|||||||
|
|
||||||
val newBodyStartLabel = Label()
|
val newBodyStartLabel = Label()
|
||||||
constructorVisitor.visitLabel(newBodyStartLabel)
|
constructorVisitor.visitLabel(newBodyStartLabel)
|
||||||
//initialize captured fields
|
|
||||||
val newFieldsWithSkipped = getNewFieldsToGenerate(allCapturedBuilder.listCaptured())
|
|
||||||
val fieldInfoWithSkipped = transformToFieldInfo(Type.getObjectType(transformationInfo.newClassName), newFieldsWithSkipped)
|
|
||||||
|
|
||||||
val capturedFieldInitializer = InstructionAdapter(constructorVisitor)
|
//initialize captured fields
|
||||||
fieldInfoWithSkipped.forEachIndexed { paramIndex, fieldInfo ->
|
val capturedIndexes = IntArray(constructorParams.parameters.size)
|
||||||
if (!newFieldsWithSkipped[paramIndex].skip) {
|
var index = 0
|
||||||
DescriptorAsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer)
|
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 first = intermediateMethodNode.instructions.first
|
||||||
val oldStartLabel = (first as? LabelNode)?.label
|
val oldStartLabel = (first as? LabelNode)?.label
|
||||||
intermediateMethodNode.accept(object : MethodBodyVisitor(capturedFieldInitializer) {
|
intermediateMethodNode.accept(object : MethodBodyVisitor(constructorVisitor) {
|
||||||
override fun visitLocalVariable(
|
override fun visitLocalVariable(
|
||||||
name: String, desc: String, signature: String?, start: Label, end: Label, index: Int
|
name: String, desc: String, signature: String?, start: Label, end: Label, index: Int
|
||||||
) {
|
) {
|
||||||
@@ -430,9 +421,6 @@ class AnonymousObjectTransformer(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
constructorVisitor.visitEnd()
|
constructorVisitor.visitEnd()
|
||||||
DescriptorAsmUtil.genClosureFields(
|
|
||||||
toNameTypePair(filterSkipped(newFieldsWithSkipped)), classBuilder
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
|
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) }
|
|
||||||
Reference in New Issue
Block a user