Convert FieldRemapper to Kotlin

This commit is contained in:
Mikhael Bogdanov
2017-05-15 20:53:32 +02:00
parent f795f2777c
commit 5b947ac27e
4 changed files with 59 additions and 89 deletions
@@ -391,7 +391,7 @@ class AnonymousObjectTransformer(
//TODO: some of such parameters could be skipped - we should perform additional analysis
val capturedLambdasToInline = HashMap<String, LambdaInfo>() //captured var of inlined parameter
val allRecapturedParameters = ArrayList<CapturedParamDesc>()
val addCapturedNotAddOuter = parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot
val addCapturedNotAddOuter = parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot
val alreadyAdded = HashMap<String, CapturedParamInfo>()
for (info in capturedLambdas) {
if (addCapturedNotAddOuter) {
@@ -426,8 +426,8 @@ class AnonymousObjectTransformer(
if (parentFieldRemapper is InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) {
//lambda with non InlinedLambdaRemapper already have outer
val parent = parentFieldRemapper.getParent()
assert(parent is RegeneratedLambdaFieldRemapper)
val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?:
throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}")
val ownerType = Type.getObjectType(parent.lambdaInternalName)
val desc = CapturedParamDesc(ownerType, InlineCodegenUtil.THIS, ownerType)
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.`THIS$0`/*outer lambda/object*/, false)
@@ -14,122 +14,91 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.inline;
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.Collection;
import java.util.List;
open class FieldRemapper(val lambdaInternalName: String?, @JvmField val parent: FieldRemapper?, private val params: Parameters) {
public class FieldRemapper {
protected FieldRemapper parent;
private final String lambdaInternalName;
private final Parameters params;
public FieldRemapper(@Nullable String lambdaInternalName, @Nullable FieldRemapper parent, @NotNull Parameters methodParams) {
this.lambdaInternalName = lambdaInternalName;
this.parent = parent;
this.params = methodParams;
}
protected boolean canProcess(@NotNull String fieldOwner, @NotNull String fieldName, boolean isFolding) {
return fieldOwner.equals(getLambdaInternalName()) &&
protected open fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean): Boolean {
return fieldOwner == lambdaInternalName &&
//don't process general field of anonymous objects
InlineCodegenUtil.isCapturedFieldName(fieldName);
InlineCodegenUtil.isCapturedFieldName(fieldName)
}
@Nullable
public AbstractInsnNode foldFieldAccessChainIfNeeded(@NotNull List<AbstractInsnNode> capturedFieldAccess, @NotNull MethodNode node) {
if (capturedFieldAccess.size() == 1) {
fun foldFieldAccessChainIfNeeded(capturedFieldAccess: List<AbstractInsnNode>, node: MethodNode): AbstractInsnNode? {
if (capturedFieldAccess.size == 1) {
//just aload
return null;
return null
}
return foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node);
return foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node)
}
//TODO: seems that this method is redundant but it added from safety purposes before new milestone
public boolean processNonAload0FieldAccessChains(boolean isInlinedLambda) {
return false;
open fun processNonAload0FieldAccessChains(isInlinedLambda: Boolean): Boolean {
return false
}
@Nullable
private AbstractInsnNode foldFieldAccessChainIfNeeded(
@NotNull List<AbstractInsnNode> capturedFieldAccess,
int currentInstruction,
@NotNull MethodNode node
) {
boolean checkParent = !isRoot() && currentInstruction < capturedFieldAccess.size() - 1;
private fun foldFieldAccessChainIfNeeded(
capturedFieldAccess: List<AbstractInsnNode>,
currentInstruction: Int,
node: MethodNode
): AbstractInsnNode? {
val checkParent = !isRoot && currentInstruction < capturedFieldAccess.size - 1
if (checkParent) {
AbstractInsnNode transformed = parent.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node);
val transformed = parent!!.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node)
if (transformed != null) {
return transformed;
return transformed
}
}
FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction);
val insnNode = capturedFieldAccess[currentInstruction] as FieldInsnNode
if (canProcess(insnNode.owner, insnNode.name, true)) {
insnNode.name = "$$$" + insnNode.name;
insnNode.setOpcode(Opcodes.GETSTATIC);
insnNode.name = "$$$" + insnNode.name
insnNode.opcode = Opcodes.GETSTATIC
AbstractInsnNode next = capturedFieldAccess.get(0);
while (next != insnNode) {
AbstractInsnNode toDelete = next;
next = next.getNext();
node.instructions.remove(toDelete);
var next = capturedFieldAccess[0]
while (next !== insnNode) {
val toDelete = next
next = next.next
node.instructions.remove(toDelete)
}
return capturedFieldAccess.get(capturedFieldAccess.size() - 1);
return capturedFieldAccess[capturedFieldAccess.size - 1]
}
return null;
return null
}
@Nullable
public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode) {
return findField(fieldInsnNode, params.getCaptured());
fun findField(fieldInsnNode: FieldInsnNode): CapturedParamInfo? {
return findField(fieldInsnNode, params.captured)
}
@Nullable
protected CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<CapturedParamInfo> captured) {
for (CapturedParamInfo valueDescriptor : captured) {
if (valueDescriptor.getOriginalFieldName().equals(fieldInsnNode.name) &&
valueDescriptor.getContainingLambdaName().equals(fieldInsnNode.owner)) {
return valueDescriptor;
open fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>): CapturedParamInfo? {
for (valueDescriptor in captured) {
if (valueDescriptor.originalFieldName == fieldInsnNode.name && valueDescriptor.containingLambdaName == fieldInsnNode.owner) {
return valueDescriptor
}
}
return null;
return null
}
@NotNull
public FieldRemapper getParent() {
return parent;
open fun getNewLambdaInternalName(): String {
return lambdaInternalName!!
}
public String getLambdaInternalName() {
return lambdaInternalName;
val isRoot: Boolean
get() = parent == null
open fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? {
return MethodInliner.findCapturedField(node, this).remapValue
}
public String getNewLambdaInternalName() {
return lambdaInternalName;
}
public boolean isRoot() {
return parent == null;
}
@Nullable
public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) {
return MethodInliner.findCapturedField(node, this).getRemapValue();
}
public boolean isInsideInliningLambda() {
return !isRoot() && parent.isInsideInliningLambda();
}
open val isInsideInliningLambda: Boolean
get() = !isRoot && parent!!.isInsideInliningLambda
}
@@ -28,13 +28,14 @@ class InlinedLambdaRemapper(
public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) =
isFolding && super.canProcess(fieldOwner, fieldName, true)
public override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>) =
parent.findField(fieldInsnNode, captured)
override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection<CapturedParamInfo>): CapturedParamInfo? {
return parent!!.findField(fieldInsnNode, captured)
}
override fun isInsideInliningLambda() = true
override val isInsideInliningLambda: Boolean = true
override fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?) =
if (parent.isRoot)
if (parent!!.isRoot)
super.getFieldForInline(node, prefix)
else
parent.getFieldForInline(node, prefix)
@@ -60,7 +60,7 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
@Nullable
@Override
public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<CapturedParamInfo> captured) {
public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<? extends CapturedParamInfo> captured) {
boolean searchInParent = !canProcess(fieldInsnNode.owner, fieldInsnNode.name, false);
if (searchInParent) {
return parent.findField(fieldInsnNode);