Clean code after transformation

This commit is contained in:
Mikhael Bogdanov
2017-05-16 10:13:46 +02:00
parent eca359f176
commit 8a083a41d5
6 changed files with 32 additions and 33 deletions
@@ -428,7 +428,7 @@ class AnonymousObjectTransformer(
//lambda with non InlinedLambdaRemapper already have outer //lambda with non InlinedLambdaRemapper already have outer
val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?: val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?:
throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}") throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}")
val ownerType = Type.getObjectType(parent.lambdaInternalName) val ownerType = Type.getObjectType(parent.originalLambdaInternalName)
val desc = CapturedParamDesc(ownerType, InlineCodegenUtil.THIS, ownerType) val desc = CapturedParamDesc(ownerType, InlineCodegenUtil.THIS, ownerType)
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.`THIS$0`/*outer lambda/object*/, false) val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.`THIS$0`/*outer lambda/object*/, false)
val composed = StackValue.LOCAL_0 val composed = StackValue.LOCAL_0
@@ -24,16 +24,16 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
open class FieldRemapper( open class FieldRemapper(
val lambdaInternalName: String?, val originalLambdaInternalName: String?,
@JvmField val parent: FieldRemapper?, @JvmField val parent: FieldRemapper?,
private val params: Parameters protected val parameters: Parameters
) { ) {
val isRoot = parent == null val isRoot = parent == null
open val isInsideInliningLambda: Boolean = parent?.isInsideInliningLambda ?: false open val isInsideInliningLambda: Boolean = parent?.isInsideInliningLambda ?: false
protected open fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean): Boolean { protected open fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean): Boolean {
return fieldOwner == lambdaInternalName && return fieldOwner == originalLambdaInternalName &&
//don't process general field of anonymous objects //don't process general field of anonymous objects
InlineCodegenUtil.isCapturedFieldName(fieldName) InlineCodegenUtil.isCapturedFieldName(fieldName)
} }
@@ -72,7 +72,7 @@ open class FieldRemapper(
} }
@JvmOverloads @JvmOverloads
open fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo> = params.captured): CapturedParamInfo? { open fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo> = parameters.captured): CapturedParamInfo? {
for (valueDescriptor in captured) { for (valueDescriptor in captured) {
if (valueDescriptor.originalFieldName == fieldInsnNode.name && valueDescriptor.containingLambdaName == fieldInsnNode.owner) { if (valueDescriptor.originalFieldName == fieldInsnNode.name && valueDescriptor.containingLambdaName == fieldInsnNode.owner) {
return valueDescriptor return valueDescriptor
@@ -82,7 +82,7 @@ open class FieldRemapper(
} }
open val newLambdaInternalName: String open val newLambdaInternalName: String
get() = lambdaInternalName!! get() = originalLambdaInternalName!!
open fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? = open fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? =
MethodInliner.findCapturedField(node, this).remapValue MethodInliner.findCapturedField(node, this).remapValue
@@ -89,6 +89,7 @@ public class InlineCodegenUtil {
public static final String INLINE_FUN_VAR_SUFFIX = "$iv"; public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
public static final String DEFAULT_LAMBDA_FAKE_CALL = "$$$DEFAULT_LAMBDA_FAKE_CALL$$$"; public static final String DEFAULT_LAMBDA_FAKE_CALL = "$$$DEFAULT_LAMBDA_FAKE_CALL$$$";
public static final String CAPTURED_FIELD_FOLD_PREFIX = "$$$";
@Nullable @Nullable
public static SMAPAndMethodNode getMethodNode( public static SMAPAndMethodNode getMethodNode(
@@ -28,9 +28,8 @@ class InlinedLambdaRemapper(
public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) = public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) =
isFolding && super.canProcess(fieldOwner, fieldName, true) isFolding && super.canProcess(fieldOwner, fieldName, true)
override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>): CapturedParamInfo? { override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>) =
return parent!!.findField(fieldInsnNode, captured) parent!!.findField(fieldInsnNode, captured)
}
override val isInsideInliningLambda: Boolean = true override val isInsideInliningLambda: Boolean = true
@@ -709,7 +709,7 @@ class MethodInliner(
assert(node.name.startsWith("$$$")) { "Captured field template should start with $$$ prefix" } assert(node.name.startsWith("$$$")) { "Captured field template should start with $$$ prefix" }
val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc) val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc)
val field = fieldRemapper.findField(fin) ?: throw IllegalStateException( val field = fieldRemapper.findField(fin) ?: throw IllegalStateException(
"Couldn't find captured field " + node.owner + "." + node.name + " in " + fieldRemapper.lambdaInternalName "Couldn't find captured field ${node.owner}.${node.name} in ${fieldRemapper.originalLambdaInternalName}"
) )
return field return field
} }
@@ -17,18 +17,20 @@
package org.jetbrains.kotlin.codegen.inline package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.CAPTURED_FIELD_FOLD_PREFIX
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.THIS
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
class RegeneratedLambdaFieldRemapper( class RegeneratedLambdaFieldRemapper(
val oldOwnerType: String, originalLambdaInternalName: String,
override val newLambdaInternalName: String, override val newLambdaInternalName: String,
private val parameters: Parameters, parameters: Parameters,
private val recapturedLambdas: Map<String, LambdaInfo>, private val recapturedLambdas: Map<String, LambdaInfo>,
remapper: FieldRemapper, remapper: FieldRemapper,
private val isConstructor: Boolean private val isConstructor: Boolean
) : FieldRemapper(oldOwnerType, remapper, parameters) { ) : FieldRemapper(originalLambdaInternalName, remapper, parameters) {
public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) = public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) =
super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding) super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding)
@@ -41,38 +43,35 @@ class RegeneratedLambdaFieldRemapper(
if (searchInParent) { if (searchInParent) {
return parent!!.findField(fieldInsnNode) return parent!!.findField(fieldInsnNode)
} }
return findFieldInMyCaptured(fieldInsnNode) return findFieldInSuper(fieldInsnNode)
} }
override fun processNonAload0FieldAccessChains(isInlinedLambda: Boolean): Boolean { override fun processNonAload0FieldAccessChains(isInlinedLambda: Boolean): Boolean {
return isInlinedLambda && isConstructor return isInlinedLambda && isConstructor
} }
private fun findFieldInMyCaptured(fieldInsnNode: FieldInsnNode): CapturedParamInfo? { private fun findFieldInSuper(fieldInsnNode: FieldInsnNode): CapturedParamInfo? {
return super.findField(fieldInsnNode, parameters.captured) return super.findField(fieldInsnNode, parameters.captured)
} }
override fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? { override fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? {
assert(node.name.startsWith("$$$")) { "Captured field template should start with $$$ prefix" } val fieldName = node.name
if (node.name == "$$$" + InlineCodegenUtil.THIS) { assert(fieldName.startsWith(CAPTURED_FIELD_FOLD_PREFIX)) { "Captured field template should start with $CAPTURED_FIELD_FOLD_PREFIX prefix" }
assert(oldOwnerType == node.owner) { "Can't unfold '$$\$THIS' parameter" } if (fieldName == CAPTURED_FIELD_FOLD_PREFIX + THIS) {
assert(originalLambdaInternalName == node.owner) { "Can't unfold '$CAPTURED_FIELD_FOLD_PREFIX$THIS' parameter" }
return StackValue.LOCAL_0 return StackValue.LOCAL_0
} }
val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc) val fin = FieldInsnNode(node.opcode, node.owner, fieldName.substringAfter(CAPTURED_FIELD_FOLD_PREFIX), node.desc)
var field = findFieldInMyCaptured(fin) var fromParent = false
val field = findFieldInSuper(fin) ?:
//search in parent
findFieldInSuper(FieldInsnNode(
Opcodes.GETSTATIC, originalLambdaInternalName, InlineCodegenUtil.`THIS$0`,
Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor
))?.also { fromParent = true } ?:
throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName")
var searchInParent = false
if (field == null) {
field = findFieldInMyCaptured(FieldInsnNode(
Opcodes.GETSTATIC, oldOwnerType, InlineCodegenUtil.`THIS$0`,
Type.getObjectType(parent!!.lambdaInternalName!!).descriptor
))
searchInParent = true
if (field == null) {
throw IllegalStateException("Couldn't find captured this " + lambdaInternalName + " for " + node.name)
}
}
val result = StackValue.field( val result = StackValue.field(
if (field.isSkipped) if (field.isSkipped)
@@ -84,6 +83,6 @@ class RegeneratedLambdaFieldRemapper(
prefix ?: StackValue.LOCAL_0 prefix ?: StackValue.LOCAL_0
) )
return if (searchInParent) parent!!.getFieldForInline(node, result) else result return if (fromParent) parent!!.getFieldForInline(node, result) else result
} }
} }