Minor. Reformat code

This commit is contained in:
Mikhael Bogdanov
2019-01-03 14:23:19 +01:00
parent cfc21ffa56
commit 90c787e102
31 changed files with 594 additions and 577 deletions
@@ -83,8 +83,7 @@ class AnonymousObjectTransformer(
throw RuntimeException("Lambda, SAM or anonymous object should have only one constructor") throw RuntimeException("Lambda, SAM or anonymous object should have only one constructor")
} }
constructor = node constructor = node
} } else {
else {
methodsToTransform.add(node) methodsToTransform.add(node)
} }
return node return node
@@ -94,8 +93,7 @@ class AnonymousObjectTransformer(
addUniqueField(name) addUniqueField(name)
return if (isCapturedFieldName(name)) { return if (isCapturedFieldName(name)) {
null null
} } else {
else {
classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value) classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value)
} }
} }
@@ -111,16 +109,14 @@ class AnonymousObjectTransformer(
if (!inliningContext.isInliningLambda) { if (!inliningContext.isInliningLambda) {
sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) { sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) {
SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!)) SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!))
} } else {
else {
//seems we can't do any clever mapping cause we don't know any about original class name //seems we can't do any clever mapping cause we don't know any about original class name
IdenticalSourceMapper IdenticalSourceMapper
} }
if (sourceInfo != null && !GENERATE_SMAP) { if (sourceInfo != null && !GENERATE_SMAP) {
classBuilder.visitSource(sourceInfo!!, debugInfo) classBuilder.visitSource(sourceInfo!!, debugInfo)
} }
} } else {
else {
if (sourceInfo != null) { if (sourceInfo != null) {
classBuilder.visitSource(sourceInfo!!, debugInfo) classBuilder.visitSource(sourceInfo!!, debugInfo)
} }
@@ -130,7 +126,7 @@ class AnonymousObjectTransformer(
val allCapturedParamBuilder = ParametersBuilder.newBuilder() val allCapturedParamBuilder = ParametersBuilder.newBuilder()
val constructorParamBuilder = ParametersBuilder.newBuilder() val constructorParamBuilder = ParametersBuilder.newBuilder()
val additionalFakeParams = extractParametersMappingAndPatchConstructor( val additionalFakeParams = extractParametersMappingAndPatchConstructor(
constructor!!, allCapturedParamBuilder, constructorParamBuilder,transformationInfo, parentRemapper constructor!!, allCapturedParamBuilder, constructorParamBuilder, transformationInfo, parentRemapper
) )
val deferringMethods = ArrayList<DeferredMethodVisitor>() val deferringMethods = ArrayList<DeferredMethodVisitor>()
@@ -172,8 +168,7 @@ class AnonymousObjectTransformer(
SourceMapper.flushToClassBuilder(sourceMapper, classBuilder) SourceMapper.flushToClassBuilder(sourceMapper, classBuilder)
val visitor = classBuilder.visitor val visitor = classBuilder.visitor
innerClassNodes.forEach { innerClassNodes.forEach { node ->
node ->
visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access) visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access)
} }
@@ -194,7 +189,7 @@ class AnonymousObjectTransformer(
} }
private fun writeTransformedMetadata(header: KotlinClassHeader, classBuilder: ClassBuilder) { private fun writeTransformedMetadata(header: KotlinClassHeader, classBuilder: ClassBuilder) {
writeKotlinMetadata(classBuilder, state, header.kind, header.extraInt) action@ { av -> writeKotlinMetadata(classBuilder, state, header.kind, header.extraInt) action@{ av ->
val (newProto, newStringTable) = transformMetadata(header) ?: run { val (newProto, newStringTable) = transformMetadata(header) ?: run {
val data = header.data val data = header.data
val strings = header.strings val strings = header.strings
@@ -258,7 +253,8 @@ class AnonymousObjectTransformer(
isConstructor: Boolean isConstructor: Boolean
): InlineResult { ): InlineResult {
val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode) val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
val parameters = if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode) val parameters =
if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
val remapper = RegeneratedLambdaFieldRemapper( val remapper = RegeneratedLambdaFieldRemapper(
oldObjectType.internalName, transformationInfo.newClassName, parameters, oldObjectType.internalName, transformationInfo.newClassName, parameters,
@@ -420,8 +416,7 @@ class AnonymousObjectTransformer(
//load captured parameters and patch instruction list //load captured parameters and patch instruction list
// NB: there is also could be object fields // NB: there is also could be object fields
val toDelete = arrayListOf<AbstractInsnNode>() val toDelete = arrayListOf<AbstractInsnNode>()
constructor.findCapturedFieldAssignmentInstructions(). constructor.findCapturedFieldAssignmentInstructions().forEach { fieldNode ->
forEach { fieldNode ->
val fieldName = fieldNode.name val fieldName = fieldNode.name
val parameterAload = fieldNode.previous as VarInsnNode val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var` val varIndex = parameterAload.`var`
@@ -456,8 +451,7 @@ class AnonymousObjectTransformer(
parameterInfo.lambda = info parameterInfo.lambda = info
if (capturedParams.contains(parameterInfo.index)) { if (capturedParams.contains(parameterInfo.index)) {
parameterInfo.isCaptured = true parameterInfo.isCaptured = true
} } else {
else {
//otherwise it's super constructor parameter //otherwise it's super constructor parameter
} }
} }
@@ -466,7 +460,8 @@ class AnonymousObjectTransformer(
//TODO: some of such parameters could be skipped - we should perform additional analysis //TODO: some of such parameters could be skipped - we should perform additional analysis
val capturedLambdasToInline = HashMap<String, LambdaInfo>() //captured var of inlined parameter val capturedLambdasToInline = HashMap<String, LambdaInfo>() //captured var of inlined parameter
val allRecapturedParameters = ArrayList<CapturedParamDesc>() val allRecapturedParameters = ArrayList<CapturedParamDesc>()
val addCapturedNotAddOuter = parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot val addCapturedNotAddOuter =
parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot
val alreadyAdded = HashMap<String, CapturedParamInfo>() val alreadyAdded = HashMap<String, CapturedParamInfo>()
for (info in capturedLambdas) { for (info in capturedLambdas) {
if (addCapturedNotAddOuter) { if (addCapturedNotAddOuter) {
@@ -501,8 +496,8 @@ class AnonymousObjectTransformer(
if (parentFieldRemapper is InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) { if (parentFieldRemapper is InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) {
//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.originalLambdaInternalName) val ownerType = Type.getObjectType(parent.originalLambdaInternalName)
val desc = CapturedParamDesc(ownerType, AsmUtil.THIS, ownerType) val desc = CapturedParamDesc(ownerType, AsmUtil.THIS, ownerType)
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, AsmUtil.CAPTURED_THIS_FIELD/*outer lambda/object*/, false) val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, AsmUtil.CAPTURED_THIS_FIELD/*outer lambda/object*/, false)
@@ -521,17 +516,15 @@ class AnonymousObjectTransformer(
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<LambdaInfo>): Boolean { private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<LambdaInfo>): Boolean {
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) { return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
values.any { it.capturedVars.any { isThis0(it.fieldName) }} values.any { it.capturedVars.any { isThis0(it.fieldName) } }
} } else false
else false
} }
private fun getNewFieldName(oldName: String, originalField: Boolean): String { private fun getNewFieldName(oldName: String, originalField: Boolean): String {
if (AsmUtil.CAPTURED_THIS_FIELD == oldName) { if (AsmUtil.CAPTURED_THIS_FIELD == oldName) {
return if (!originalField) { return if (!originalField) {
oldName oldName
} } else {
else {
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site //rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX) addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX)
} }
@@ -133,8 +133,7 @@ class IntervalMetaInfo<T : SplittableInterval<T>>(private val processor: Coverin
val split = interval.split(by, keepStart) val split = interval.split(by, keepStart)
if (!keepStart) { if (!keepStart) {
remapStartLabel(split.newPart.startLabel, split.patchedPart) remapStartLabel(split.newPart.startLabel, split.patchedPart)
} } else {
else {
remapEndLabel(split.newPart.endLabel, split.patchedPart) remapEndLabel(split.newPart.endLabel, split.patchedPart)
} }
addNewInterval(split.newPart) addNewInterval(split.newPart)
@@ -191,15 +190,16 @@ class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInt
val oldEnd = endLabel val oldEnd = endLabel
node.end = splitBy.startLabel node.end = splitBy.startLabel
Pair(splitBy.endLabel, oldEnd) Pair(splitBy.endLabel, oldEnd)
} } else {
else {
val oldStart = startLabel val oldStart = startLabel
node.start = splitBy.endLabel node.start = splitBy.endLabel
Pair(oldStart, splitBy.startLabel) Pair(oldStart, splitBy.startLabel)
} }
return SplitPair(this, LocalVarNodeWrapper( return SplitPair(
this, LocalVarNodeWrapper(
LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index) LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index)
)) )
)
} }
} }
@@ -29,8 +29,10 @@ internal class FictitiousArrayConstructor(arrayClass: ClassDescriptor) : SimpleF
fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor { fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor {
val arrayClass = arrayConstructor.constructedClass val arrayClass = arrayConstructor.constructedClass
return FictitiousArrayConstructor(arrayClass).apply { return FictitiousArrayConstructor(arrayClass).apply {
this.initialize(null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType, this.initialize(
Modality.FINAL, Visibilities.PUBLIC) null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType,
Modality.FINAL, Visibilities.PUBLIC
)
this.isInline = true this.isInline = true
} }
} }
@@ -33,8 +33,7 @@ inline fun <K, V> SLRUMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
val answer = defaultValue() val answer = defaultValue()
put(key, answer) put(key, answer)
answer answer
} } else {
else {
value value
} }
} }
@@ -55,7 +55,6 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
public boolean isEmpty() { public boolean isEmpty() {
if (!(startIns instanceof LabelNode)) { if (!(startIns instanceof LabelNode)) {
return false; return false;
} }
AbstractInsnNode end = endInsExclusive; AbstractInsnNode end = endInsExclusive;
while (end != startIns && end instanceof LabelNode) { while (end != startIns && end instanceof LabelNode) {
@@ -78,7 +77,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
} }
if (hasFinallyBlocks(inlineFunTryBlockInfo)) { if (hasFinallyBlocks(inlineFunTryBlockInfo)) {
new InternalFinallyBlockInliner(inlineFun, inlineFunTryBlockInfo, localVars, finallyParamOffset).processInlineFunFinallyBlocks(); new InternalFinallyBlockInliner(inlineFun, inlineFunTryBlockInfo, localVars, finallyParamOffset)
.processInlineFunFinallyBlocks();
} }
} }
@@ -88,10 +88,12 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
//lambdaTryCatchBlockNodes is number of TryCatchBlockNodes that was inlined with lambdas into function //lambdaTryCatchBlockNodes is number of TryCatchBlockNodes that was inlined with lambdas into function
//due to code generation specific they placed before function TryCatchBlockNodes //due to code generation specific they placed before function TryCatchBlockNodes
private InternalFinallyBlockInliner(@NotNull MethodNode inlineFun, private InternalFinallyBlockInliner(
@NotNull MethodNode inlineFun,
@NotNull List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo, @NotNull List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo,
@NotNull List<LocalVarNodeWrapper> localVariableInfo, @NotNull List<LocalVarNodeWrapper> localVariableInfo,
int finallyParamOffset) { int finallyParamOffset
) {
super(finallyParamOffset); super(finallyParamOffset);
this.inlineFun = inlineFun; this.inlineFun = inlineFun;
for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) { for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) {
@@ -166,7 +168,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
List<TryCatchBlockNodeInfo> clusterBlocks = clusterToFindFinally.getBlocks(); List<TryCatchBlockNodeInfo> clusterBlocks = clusterToFindFinally.getBlocks();
TryCatchBlockNodeInfo nodeWithDefaultHandlerIfExists = clusterBlocks.get(clusterBlocks.size() - 1); TryCatchBlockNodeInfo nodeWithDefaultHandlerIfExists = clusterBlocks.get(clusterBlocks.size() - 1);
FinallyBlockInfo finallyInfo = findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals()); FinallyBlockInfo finallyInfo =
findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals());
if (finallyInfo == null) continue; if (finallyInfo == null) continue;
if (nodeWithDefaultHandlerIfExists.getOnlyCopyNotProcess()) { if (nodeWithDefaultHandlerIfExists.getOnlyCopyNotProcess()) {
@@ -253,7 +256,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
if (isFinallyMarker(currentIns.getNext())) { if (isFinallyMarker(currentIns.getNext())) {
Integer constant = getConstant(currentIns); Integer constant = getConstant(currentIns);
finallyBlockCopy.visitLdcInsn(constant + depthShift); finallyBlockCopy.visitLdcInsn(constant + depthShift);
} else { }
else {
currentIns.accept(finallyBlockCopy); //VISIT currentIns.accept(finallyBlockCopy); //VISIT
} }
} }
@@ -286,7 +290,9 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
@NotNull @NotNull
private static Set<LabelNode> rememberOriginalLabelNodes(@NotNull FinallyBlockInfo finallyInfo) { private static Set<LabelNode> rememberOriginalLabelNodes(@NotNull FinallyBlockInfo finallyInfo) {
Set<LabelNode> labelsInsideFinally = new HashSet<>(); Set<LabelNode> labelsInsideFinally = new HashSet<>();
for (AbstractInsnNode currentIns = finallyInfo.startIns; currentIns != finallyInfo.endInsExclusive; currentIns = currentIns.getNext()) { for (AbstractInsnNode currentIns = finallyInfo.startIns;
currentIns != finallyInfo.endInsExclusive;
currentIns = currentIns.getNext()) {
if (currentIns instanceof LabelNode) { if (currentIns instanceof LabelNode) {
labelsInsideFinally.add((LabelNode) currentIns); labelsInsideFinally.add((LabelNode) currentIns);
} }
@@ -326,7 +332,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
tryCatchBlockNode.type); tryCatchBlockNode.type);
assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= inlineFun.instructions.indexOf(additionalTryCatchBlock.end); assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <=
inlineFun.instructions.indexOf(additionalTryCatchBlock.end);
tryBlocksMetaInfo.addNewInterval(new TryCatchBlockNodeInfo(additionalTryCatchBlock, true)); tryBlocksMetaInfo.addNewInterval(new TryCatchBlockNodeInfo(additionalTryCatchBlock, true));
} }
@@ -350,7 +357,10 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
TryCatchBlockNodeInfo startNode = startBlockPositions.next().getNodeInfo(); TryCatchBlockNodeInfo startNode = startBlockPositions.next().getNodeInfo();
TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo(); TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo();
assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " + startNode.getType() + " " + endNode.getType(); assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " +
startNode.getType() +
" " +
endNode.getType();
getTryBlocksMetaInfo() getTryBlocksMetaInfo()
.split(endNode, new SimpleInterval((LabelNode) endNode.getNode().end.getLabel().info, .split(endNode, new SimpleInterval((LabelNode) endNode.getNode().end.getLabel().info,
@@ -427,7 +437,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
} }
if (afterStartBlock) { if (afterStartBlock) {
if (block.getNode().type == null && (firstLabelInChain(tryCatchBlock.getNode().start) == firstLabelInChain(block.getNode().start) && if (block.getNode().type == null &&
(firstLabelInChain(tryCatchBlock.getNode().start) == firstLabelInChain(block.getNode().start) &&
firstLabelInChain(tryCatchBlock.getNode().end) == firstLabelInChain(block.getNode().end) firstLabelInChain(tryCatchBlock.getNode().end) == firstLabelInChain(block.getNode().end)
|| defaultHandler == firstLabelInChain(block.getNode().handler))) { || defaultHandler == firstLabelInChain(block.getNode().handler))) {
sameDefaultHandler.add(block); //first is tryCatchBlock if no catch clauses sameDefaultHandler.add(block); //first is tryCatchBlock if no catch clauses
@@ -545,5 +556,4 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
String text = getNodeText(inlineFun); String text = getNodeText(inlineFun);
System.out.println(text); System.out.println(text);
} }
} }
@@ -28,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks // before/after suspension point marks, so we detect those functions here and insert the corresponding marks
fun insertLegacySuspendInlineMarks(node: MethodNode) { fun insertLegacySuspendInlineMarks(node: MethodNode) {
with (node.instructions) { with(node.instructions) {
// look for return instruction before the end and insert "afterSuspendMarker" there // look for return instruction before the end and insert "afterSuspendMarker" there
insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions) insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions)
// insert "beforeSuspendMarker" at the beginning // insert "beforeSuspendMarker" at the beginning
@@ -36,8 +36,7 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi
if (!info.isSkippedOrRemapped) { if (!info.isSkippedOrRemapped) {
remapValues[shift] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE) remapValues[shift] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE)
realSize += info.getType().size realSize += info.getType().size
} } else {
else {
remapValues[shift] = if (info.isRemapped) info.remapValue else null remapValues[shift] = if (info.isRemapped) info.remapValue else null
if (CapturedParamInfo.isSynthetic(info)) { if (CapturedParamInfo.isSynthetic(info)) {
realSize += info.getType().size realSize += info.getType().size
@@ -59,12 +58,10 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi
} }
if (info.isRemapped) { if (info.isRemapped) {
return RemapInfo(info, remapped, REMAPPED) return RemapInfo(info, remapped, REMAPPED)
} } else {
else {
remappedIndex = (remapped as StackValue.Local).index remappedIndex = (remapped as StackValue.Local).index
} }
} } else {
else {
//captured params are not used directly in this inlined method, they are used in closure //captured params are not used directly in this inlined method, they are used in closure
//except captured ones for default lambdas, they are generated in default body //except captured ones for default lambdas, they are generated in default body
remappedIndex = actualParamsSize - params.argsSizeOnStack + index remappedIndex = actualParamsSize - params.argsSizeOnStack + index
@@ -115,8 +112,7 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi
if (remapInfo.parameterInfo != null && !isStore) { if (remapInfo.parameterInfo != null && !isStore) {
StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv) StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv)
} }
} } else {
else {
assert(remapInfo.parameterInfo != null) { "Non local value should have parameter info" } assert(remapInfo.parameterInfo != null) { "Non local value should have parameter info" }
value!!.put(remapInfo.parameterInfo!!.type, mv) value!!.put(remapInfo.parameterInfo!!.type, mv)
} }
@@ -86,5 +86,4 @@ public class MaxLocalsCalculator extends MethodVisitor {
maxLocals = nextFreeSlotNumber; maxLocals = nextFreeSlotNumber;
} }
} }
} }
@@ -61,6 +61,7 @@ import java.util.*;
*/ */
public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator { public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator {
private static final int[] FRAME_SIZE_CHANGE_BY_OPCODE; private static final int[] FRAME_SIZE_CHANGE_BY_OPCODE;
static { static {
// copy-pasted from org.jetbrains.org.objectweb.asm.Frame // copy-pasted from org.jetbrains.org.objectweb.asm.Frame
int i; int i;
@@ -418,6 +419,7 @@ public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator {
private int outputStackMax = 0; private int outputStackMax = 0;
private int inputStackSize = 0; private int inputStackSize = 0;
public LabelWrapper(Label label) { public LabelWrapper(Label label) {
this.label = label; this.label = label;
} }
@@ -120,8 +120,7 @@ class MethodInliner(
visitor visitor
} else MethodBodyVisitor(visitor) } else MethodBodyVisitor(visitor)
) )
} } catch (e: Throwable) {
catch (e: Throwable) {
throw wrapException(e, transformedNode, "couldn't inline method call") throw wrapException(e, transformedNode, "couldn't inline method call")
} }
@@ -203,8 +202,7 @@ class MethodInliner(
ReifiedTypeInliner.putNeedClassReificationMarker(mv) ReifiedTypeInliner.putNeedClassReificationMarker(mv)
result.reifiedTypeParametersUsages.mergeAll(transformResult.reifiedTypeParametersUsages) result.reifiedTypeParametersUsages.mergeAll(transformResult.reifiedTypeParametersUsages)
} }
} } else if (!transformationInfo!!.wasAlreadyRegenerated) {
else if (!transformationInfo!!.wasAlreadyRegenerated) {
result.addNotChangedClass(oldClassName) result.addNotChangedClass(oldClassName)
} }
} }
@@ -290,8 +288,7 @@ class MethodInliner(
NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
else if (info is DefaultLambda) { else if (info is DefaultLambda) {
NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
} } else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
val inliner = MethodInliner( val inliner = MethodInliner(
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
@@ -315,8 +312,7 @@ class MethodInliner(
addInlineMarker(this, false) addInlineMarker(this, false)
childSourceMapper.endMapping() childSourceMapper.endMapping()
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter) inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
} } else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
//TODO add proper message //TODO add proper message
assert(transformationInfo is AnonymousObjectTransformationInfo) { assert(transformationInfo is AnonymousObjectTransformationInfo) {
"<init> call doesn't correspond to object transformation info for '$owner.$name': $transformationInfo" "<init> call doesn't correspond to object transformation info for '$owner.$name': $transformationInfo"
@@ -366,16 +362,14 @@ class MethodInliner(
} }
transformationInfo = null transformationInfo = null
} } else {
else {
super.visitMethodInsn(opcode, owner, name, desc, itf) super.visitMethodInsn(opcode, owner, name, desc, itf)
} }
} } else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) &&
else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) && ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))
ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) { ) {
//we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas //we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas
} } else {
else {
super.visitMethodInsn(opcode, owner, name, desc, itf) super.visitMethodInsn(opcode, owner, name, desc, itf)
} }
} }
@@ -457,18 +451,19 @@ class MethodInliner(
if (DEFAULT_LAMBDA_FAKE_CALL == owner) { if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt() val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt()
val lambda = getLambdaIfExists(index) as DefaultLambda val lambda = getLambdaIfExists(index) as DefaultLambda
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) ->
(_, captured) ->
val originalBoundReceiverType = lambda.originalBoundReceiverType val originalBoundReceiverType = lambda.originalBoundReceiverType
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) { if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this)) StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this))
} }
super.visitFieldInsn( super.visitFieldInsn(
Opcodes.PUTSTATIC, captured.containingLambdaName, CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName, captured.type.descriptor Opcodes.PUTSTATIC,
captured.containingLambdaName,
CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName,
captured.type.descriptor
) )
} }
} } else {
else {
super.visitMethodInsn(opcode, owner, name, desc, itf) super.visitMethodInsn(opcode, owner, name, desc, itf)
} }
} }
@@ -532,23 +527,21 @@ class MethodInliner(
val sourceValue = frame.getStack(firstParameterIndex) val sourceValue = frame.getStack(firstParameterIndex)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete) val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep)) invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep))
} } else if (isSamWrapperConstructorCall(owner, name)) {
else if (isSamWrapperConstructorCall(owner, name)) {
recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner))) recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner)))
} } else if (isAnonymousConstructorCall(owner, name)) {
else if (isAnonymousConstructorCall(owner, name)) {
val lambdaMapping = HashMap<Int, LambdaInfo>() val lambdaMapping = HashMap<Int, LambdaInfo>()
var offset = 0 var offset = 0
var capturesAnonymousObjectThatMustBeRegenerated = false var capturesAnonymousObjectThatMustBeRegenerated = false
for (i in 0 until paramCount) { for (i in 0 until paramCount) {
val sourceValue = frame.getStack(firstParameterIndex + i) val sourceValue = frame.getStack(firstParameterIndex + i)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, false, instructions, sources, toDelete val lambdaInfo = getLambdaIfExistsAndMarkInstructions(
sourceValue, false, instructions, sources, toDelete
) )
if (lambdaInfo != null) { if (lambdaInfo != null) {
lambdaMapping.put(offset, lambdaInfo) lambdaMapping.put(offset, lambdaInfo)
} } else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
capturesAnonymousObjectThatMustBeRegenerated = true capturesAnonymousObjectThatMustBeRegenerated = true
} }
@@ -561,8 +554,7 @@ class MethodInliner(
) )
) )
awaitClassReification = false awaitClassReification = false
} } else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) {
else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) {
val reificationArgument = cur.reificationArgument val reificationArgument = cur.reificationArgument
val parameterName = reificationArgument!!.parameterName val parameterName = reificationArgument!!.parameterName
result.reifiedTypeParametersUsages.addUsedReifiedParameter(parameterName) result.reifiedTypeParametersUsages.addUsedReifiedParameter(parameterName)
@@ -580,8 +572,7 @@ class MethodInliner(
) )
) )
awaitClassReification = false awaitClassReification = false
} } else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
recordTransformation( recordTransformation(
WhenMappingTransformationInfo( WhenMappingTransformationInfo(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
@@ -590,7 +581,13 @@ class MethodInliner(
} }
} }
cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(frame.top()!!, true, instructions, sources, toDelete)?.let { cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(
frame.top()!!,
true,
instructions,
sources,
toDelete
)?.let {
toDelete.add(cur) toDelete.add(cur)
} }
@@ -605,9 +602,11 @@ class MethodInliner(
val fieldInsn = cur as FieldInsnNode val fieldInsn = cur as FieldInsnNode
if (isCapturedFieldName(fieldInsn.name) && if (isCapturedFieldName(fieldInsn.name) &&
nodeRemapper is InlinedLambdaRemapper && nodeRemapper is InlinedLambdaRemapper &&
nodeRemapper.originalLambdaInternalName == fieldInsn.owner) { nodeRemapper.originalLambdaInternalName == fieldInsn.owner
) {
val stackTransformations = mutableSetOf<AbstractInsnNode>() val stackTransformations = mutableSetOf<AbstractInsnNode>()
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations) val lambdaInfo =
getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) { if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) {
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) { assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}" "Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
@@ -619,16 +618,14 @@ class MethodInliner(
} }
} }
} }
} } else {
else {
//given frame is <tt>null</tt> if and only if the corresponding instruction cannot be reached (dead code). //given frame is <tt>null</tt> if and only if the corresponding instruction cannot be reached (dead code).
//clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems //clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems
if (cur.type == AbstractInsnNode.LABEL) { if (cur.type == AbstractInsnNode.LABEL) {
//NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression) //NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression)
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead, //it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
//but as result all this labels will be merged into one (see KT-5863) //but as result all this labels will be merged into one (see KT-5863)
} } else {
else {
toDelete.add(cur) toDelete.add(cur)
} }
} }
@@ -758,8 +755,7 @@ class MethodInliner(
private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) { private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) {
try { try {
FixStackWithLabelNormalizationMethodTransformer().transform("fake", node) FixStackWithLabelNormalizationMethodTransformer().transform("fake", node)
} } catch (e: Throwable) {
catch (e: Throwable) {
throw wrapException(e, node, "couldn't inline method call") throw wrapException(e, node, "couldn't inline method call")
} }
@@ -911,8 +907,7 @@ class MethodInliner(
private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException { private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException {
return if (originalException is InlineException) { return if (originalException is InlineException) {
InlineException("$errorPrefix: $errorSuffix", originalException) InlineException("$errorPrefix: $errorSuffix", originalException)
} } else {
else {
InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException) InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException)
} }
} }
@@ -971,8 +966,7 @@ class MethodInliner(
if (returnInsn.opcode != Opcodes.RETURN) { if (returnInsn.opcode != Opcodes.RETURN) {
returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) { returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
2 2
} } else {
else {
1 1
} }
} }
@@ -1028,8 +1022,7 @@ class MethodInliner(
try { try {
return analyzer.analyze("fake", node) return analyzer.analyze("fake", node)
} } catch (e: AnalyzerException) {
catch (e: AnalyzerException) {
throw RuntimeException(e) throw RuntimeException(e)
} }
@@ -1041,8 +1034,7 @@ class MethodInliner(
// INTRINSICS_CLASS_NAME.checkParameterIsNotNull(...) // INTRINSICS_CLASS_NAME.checkParameterIsNotNull(...)
private fun removeClosureAssertions(node: MethodNode) { private fun removeClosureAssertions(node: MethodNode) {
val toDelete = arrayListOf<AbstractInsnNode>() val toDelete = arrayListOf<AbstractInsnNode>()
InsnSequence(node.instructions).filterIsInstance<MethodInsnNode>().forEach { InsnSequence(node.instructions).filterIsInstance<MethodInsnNode>().forEach { methodInsnNode ->
methodInsnNode ->
if (methodInsnNode.name == "checkParameterIsNotNull" && methodInsnNode.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME) { if (methodInsnNode.name == "checkParameterIsNotNull" && methodInsnNode.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME) {
val prev = methodInsnNode.previous val prev = methodInsnNode.previous
assert(Opcodes.LDC == prev?.opcode) { "'checkParameterIsNotNull' should go after LDC but $prev" } assert(Opcodes.LDC == prev?.opcode) { "'checkParameterIsNotNull' should go after LDC but $prev" }
@@ -1077,8 +1069,7 @@ class MethodInliner(
private fun getCapturedFieldAccessChain(aload0: VarInsnNode): List<AbstractInsnNode> { private fun getCapturedFieldAccessChain(aload0: VarInsnNode): List<AbstractInsnNode> {
val lambdaAccessChain = mutableListOf<AbstractInsnNode>(aload0).apply { val lambdaAccessChain = mutableListOf<AbstractInsnNode>(aload0).apply {
addAll(InsnSequence(aload0.next, null).filter { it.isMeaningful }.takeWhile { addAll(InsnSequence(aload0.next, null).filter { it.isMeaningful }.takeWhile { insnNode ->
insnNode ->
insnNode is FieldInsnNode && "this$0" == insnNode.name insnNode is FieldInsnNode && "this$0" == insnNode.name
}.toList()) }.toList())
} }
@@ -1086,7 +1077,8 @@ class MethodInliner(
return lambdaAccessChain.apply { return lambdaAccessChain.apply {
last().getNextMeaningful().takeIf { insn -> insn is FieldInsnNode }?.also { last().getNextMeaningful().takeIf { insn -> insn is FieldInsnNode }?.also {
//captured field access //captured field access
insn -> add(insn) insn ->
add(insn)
} }
} }
} }
@@ -1170,9 +1162,11 @@ class MethodInliner(
//generate finally block before nonLocalReturn flag/return/goto //generate finally block before nonLocalReturn flag/return/goto
val label = LabelNode() val label = LabelNode()
instructions.insert(insnNode, label) instructions.insert(insnNode, label)
result.add(PointForExternalFinallyBlocks( result.add(
PointForExternalFinallyBlocks(
getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), getReturnType(insnNode.opcode), label getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), getReturnType(insnNode.opcode), label
)) )
)
} }
insnNode = insnNode.next insnNode = insnNode.next
} }
@@ -76,8 +76,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
return it return it
} }
} }
} } else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null
val dispatchReceiver = swapFrame.top()!! val dispatchReceiver = swapFrame.top()!!
getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let { getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let {
@@ -111,8 +110,7 @@ fun MethodNode.remove(instructions: Collection<AbstractInsnNode>) {
} }
fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence<FieldInsnNode> { fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence<FieldInsnNode> {
return InsnSequence(instructions).filterIsInstance<FieldInsnNode>(). return InsnSequence(instructions).filterIsInstance<FieldInsnNode>().filter { fieldNode ->
filter { fieldNode ->
//filter captured field assignment //filter captured field assignment
// aload 0 // aload 0
// aload x // aload x
@@ -28,10 +28,12 @@ class ParametersBuilder private constructor() {
} }
fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo { fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo {
return addParameter(ParameterInfo( return addParameter(
ParameterInfo(
type, skipped, nextParameterOffset, remapValue, type, skipped, nextParameterOffset, remapValue,
if (parameterIndex == -1) nextValueParameterIndex else parameterIndex + valueParamFirstIndex if (parameterIndex == -1) nextValueParameterIndex else parameterIndex + valueParamFirstIndex
)) )
)
} }
fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo { fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo {
@@ -65,7 +67,7 @@ class ParametersBuilder private constructor() {
return addParameter(info) return addParameter(info)
} }
private fun <T: ParameterInfo> addParameter(info: T): T { private fun <T : ParameterInfo> addParameter(info: T): T {
params.add(info) params.add(info)
nextParameterOffset += info.getType().size nextParameterOffset += info.getType().size
if (info !is CapturedParamInfo) { if (info !is CapturedParamInfo) {
@@ -94,8 +96,7 @@ class ParametersBuilder private constructor() {
return Parameters(params.map { param -> return Parameters(params.map { param ->
if (param is CapturedParamInfo) { if (param is CapturedParamInfo) {
param.cloneWithNewDeclarationIndex(nextDeclarationIndex++) param.cloneWithNewDeclarationIndex(nextDeclarationIndex++)
} } else {
else {
param param
} }
}) })
@@ -21,4 +21,5 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
class PropertyReferenceInfo( class PropertyReferenceInfo(
val target: VariableDescriptor, val target: VariableDescriptor,
val getFunction: FunctionDescriptor) val getFunction: FunctionDescriptor
)
@@ -66,11 +66,12 @@ class RegeneratedLambdaFieldRemapper(
var fromParent = false var fromParent = false
val field = findFieldInSuper(fin) ?: val field = findFieldInSuper(fin) ?:
//search in parent //search in parent
findFieldInSuper(FieldInsnNode( findFieldInSuper(
FieldInsnNode(
Opcodes.GETSTATIC, originalLambdaInternalName, AsmUtil.CAPTURED_THIS_FIELD, Opcodes.GETSTATIC, originalLambdaInternalName, AsmUtil.CAPTURED_THIS_FIELD,
Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor
))?.also { fromParent = true } ?: )
throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName") )?.also { fromParent = true } ?: throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName")
val result = StackValue.field( val result = StackValue.field(
@@ -43,7 +43,10 @@ class ReificationArgument(
) )
fun reify(replacementAsmType: Type, kotlinType: KotlinType) = fun reify(replacementAsmType: Type, kotlinType: KotlinType) =
Pair(Type.getType("[".repeat(arrayDepth) + replacementAsmType), TypeUtils.makeNullableIfNeeded(kotlinType.arrayOf(arrayDepth), nullable)) Pair(
Type.getType("[".repeat(arrayDepth) + replacementAsmType),
TypeUtils.makeNullableIfNeeded(kotlinType.arrayOf(arrayDepth), nullable)
)
private fun KotlinType.arrayOf(arrayDepth: Int): KotlinType { private fun KotlinType.arrayOf(arrayDepth: Int): KotlinType {
val builtins = this.builtIns val builtins = this.builtIns
@@ -140,15 +143,15 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?,
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType) OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType) OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType) OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
}) { }
) {
instructions.remove(insn.previous.previous!!) // PUSH operation ID instructions.remove(insn.previous.previous!!) // PUSH operation ID
instructions.remove(insn.previous!!) // PUSH type parameter instructions.remove(insn.previous!!) // PUSH type parameter
instructions.remove(insn) // INVOKESTATIC marker method instructions.remove(insn) // INVOKESTATIC marker method
} }
return null return null
} } else {
else {
val newReificationArgument = reificationArgument.combine(mapping.reificationArgument!!) val newReificationArgument = reificationArgument.combine(mapping.reificationArgument!!)
instructions.set(insn.previous!!, LdcInsnNode(newReificationArgument.asString())) instructions.set(insn.previous!!, LdcInsnNode(newReificationArgument.asString()))
return mapping.reificationArgument.parameterName return mapping.reificationArgument.parameterName
@@ -232,8 +235,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?,
next3.desc = getSpecialEnumFunDescriptor(parameter, true) next3.desc = getSpecialEnumFunDescriptor(parameter, true)
return true return true
} }
} } else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) {
else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) {
instructions.remove(next1) instructions.remove(next1)
instructions.remove(next2) instructions.remove(next2)
val desc = getSpecialEnumFunDescriptor(parameter, false) val desc = getSpecialEnumFunDescriptor(parameter, false)
@@ -261,7 +263,8 @@ val MethodInsnNode.reificationArgument: ReificationArgument?
return ReificationArgument(parameterName, nullable, arrayDepth) return ReificationArgument(parameterName, nullable, arrayDepth)
} }
val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() = val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind?
get() =
previous?.previous?.intConstant?.let { previous?.previous?.intConstant?.let {
ReifiedTypeInliner.OperationKind.values().getOrNull(it) ReifiedTypeInliner.OperationKind.values().getOrNull(it)
} }
@@ -275,7 +278,12 @@ class TypeParameterMappings() {
) )
} }
fun addParameterMappingForFurtherReification(name: String, type: KotlinType, reificationArgument: ReificationArgument, isReified: Boolean) { fun addParameterMappingForFurtherReification(
name: String,
type: KotlinType,
reificationArgument: ReificationArgument,
isReified: Boolean
) {
mappingsByName[name] = TypeParameterMapping( mappingsByName[name] = TypeParameterMapping(
name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified
) )
@@ -54,7 +54,8 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
@NotNull String superName, @NotNull String superName,
@NotNull String[] interfaces @NotNull String[] interfaces
) { ) {
super.defineClass(origin, version, access, remapper.mapType(name), remapper.mapSignature(signature, false), remapper.mapType(superName), remapper.mapTypes(interfaces)); super.defineClass(origin, version, access, remapper.mapType(name), remapper.mapSignature(signature, false),
remapper.mapType(superName), remapper.mapTypes(interfaces));
} }
@Override @Override
@@ -30,8 +30,7 @@ class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
private fun createLineNumberSequence(node: MethodNode, classSMAP: SMAP): Sequence<RangeMapping> { private fun createLineNumberSequence(node: MethodNode, classSMAP: SMAP): Sequence<RangeMapping> {
return InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map { lineNumber -> return InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map { lineNumber ->
val index = classSMAP.intervals.binarySearch(RangeMapping(lineNumber.line, lineNumber.line, 1), Comparator { val index = classSMAP.intervals.binarySearch(RangeMapping(lineNumber.line, lineNumber.line, 1), Comparator { value, key ->
value, key ->
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
}) })
if (index < 0) { if (index < 0) {
@@ -20,19 +20,23 @@ import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.ClassVisitor
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
class SamWrapperTransformationInfo(override val oldClassName: String, private val inliningContext: InliningContext, private val alreadyRegenerated: Boolean): TransformationInfo { class SamWrapperTransformationInfo(
override val oldClassName: String,
private val inliningContext: InliningContext,
private val alreadyRegenerated: Boolean
) : TransformationInfo {
override val nameGenerator: NameGenerator override val nameGenerator: NameGenerator
get() = object: NameGenerator("stub") { get() = object : NameGenerator("stub") {
override fun getGeneratorClass(): String { override fun getGeneratorClass(): String {
error ("Shouldn't be called on $oldClassName transformation") error("Shouldn't be called on $oldClassName transformation")
} }
override fun subGenerator(inliningMethod: String?): NameGenerator { override fun subGenerator(inliningMethod: String?): NameGenerator {
error ("Shouldn't be called on $oldClassName transformation") error("Shouldn't be called on $oldClassName transformation")
} }
override fun subGenerator(lambdaNoWhen: Boolean, nameSuffix: String?): NameGenerator { override fun subGenerator(lambdaNoWhen: Boolean, nameSuffix: String?): NameGenerator {
error ("Shouldn't be called on $oldClassName transformation") error("Shouldn't be called on $oldClassName transformation")
} }
} }
@@ -52,7 +52,11 @@ class WhenMappingTransformationInfo(
override fun canRemoveAfterTransformation(): Boolean = true override fun canRemoveAfterTransformation(): Boolean = true
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?): ObjectTransformer<*> = override fun createTransformer(
inliningContext: InliningContext,
sameModule: Boolean,
continuationClassName: String?
): ObjectTransformer<*> =
WhenMappingTransformer(this, inliningContext) WhenMappingTransformer(this, inliningContext)
companion object { companion object {
@@ -38,7 +38,7 @@ interface Interval {
fun isEmpty(): Boolean = startLabel == endLabel fun isEmpty(): Boolean = startLabel == endLabel
fun verify(processor: CoveringTryCatchNodeProcessor) { fun verify(processor: CoveringTryCatchNodeProcessor) {
assert (processor.instructionIndex(startLabel) <= processor.instructionIndex(endLabel)) { assert(processor.instructionIndex(startLabel) <= processor.instructionIndex(endLabel)) {
"Try block body starts after body end: ${processor.instructionIndex(startLabel)} > ${processor.instructionIndex(endLabel)}" "Try block body starts after body end: ${processor.instructionIndex(startLabel)} > ${processor.instructionIndex(endLabel)}"
} }
} }
@@ -71,8 +71,7 @@ class TryCatchBlockNodeInfo(
val oldEnd = endLabel val oldEnd = endLabel
node.end = splitBy.startLabel node.end = splitBy.startLabel
Pair(splitBy.endLabel, oldEnd) Pair(splitBy.endLabel, oldEnd)
} } else {
else {
val oldStart = startLabel val oldStart = startLabel
node.start = splitBy.endLabel node.start = splitBy.endLabel
Pair(oldStart, splitBy.startLabel) Pair(oldStart, splitBy.startLabel)
@@ -41,7 +41,10 @@ private data class Condition(
val varIndex = varInsNode?.`var` ?: 0 val varIndex = varInsNode?.`var` ?: 0
} }
fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, functionDescriptor: FunctionDescriptor): Map<Int, ValueParameterDescriptor> { fun extractDefaultLambdaOffsetAndDescriptor(
jvmSignature: JvmMethodSignature,
functionDescriptor: FunctionDescriptor
): Map<Int, ValueParameterDescriptor> {
val valueParameters = jvmSignature.valueParameters val valueParameters = jvmSignature.valueParameters
val containingDeclaration = functionDescriptor.containingDeclaration val containingDeclaration = functionDescriptor.containingDeclaration
val kind = val kind =
@@ -74,8 +77,7 @@ fun expandMaskConditionsAndUpdateVariableNodes(
if (isMaskIndex(it.`var`)) { if (isMaskIndex(it.`var`)) {
/*if slot for default mask is updated than we occurred in actual function body*/ /*if slot for default mask is updated than we occurred in actual function body*/
return@takeWhile it.opcode == Opcodes.ILOAD return@takeWhile it.opcode == Opcodes.ILOAD
} } else if (methodHandlerIndex == it.`var`) {
else if (methodHandlerIndex == it.`var`) {
return@takeWhile it.opcode == Opcodes.ALOAD return@takeWhile it.opcode == Opcodes.ALOAD
} }
} }
@@ -85,7 +87,8 @@ fun expandMaskConditionsAndUpdateVariableNodes(
val conditions = maskProcessingHeader.filterIsInstance<VarInsnNode>().mapNotNull { val conditions = maskProcessingHeader.filterIsInstance<VarInsnNode>().mapNotNull {
if (isMaskIndex(it.`var`) && if (isMaskIndex(it.`var`) &&
it.next?.next?.opcode == Opcodes.IAND && it.next?.next?.opcode == Opcodes.IAND &&
it.next.next.next?.opcode == Opcodes.IFEQ) { it.next.next.next?.opcode == Opcodes.IFEQ
) {
val jumpInstruction = it.next?.next?.next as JumpInsnNode val jumpInstruction = it.next?.next?.next as JumpInsnNode
Condition( Condition(
masks[it.`var` - maskStartIndex], masks[it.`var` - maskStartIndex],
@@ -94,15 +97,14 @@ fun expandMaskConditionsAndUpdateVariableNodes(
jumpInstruction, jumpInstruction,
jumpInstruction.label.previous as VarInsnNode jumpInstruction.label.previous as VarInsnNode
) )
} } else if (methodHandlerIndex == it.`var` &&
else if (methodHandlerIndex == it.`var` &&
it.next?.opcode == Opcodes.IFNULL && it.next?.opcode == Opcodes.IFNULL &&
it.next.next?.opcode == Opcodes.NEW) { it.next.next?.opcode == Opcodes.NEW
) {
//Always delete method handle for now //Always delete method handle for now
//This logic should be updated when method handles would be supported //This logic should be updated when method handles would be supported
Condition(0, 0, it, it.next as JumpInsnNode, null) Condition(0, 0, it, it.next as JumpInsnNode, null)
} } else null
else null
}.toList() }.toList()
val toDelete = linkedSetOf<AbstractInsnNode>() val toDelete = linkedSetOf<AbstractInsnNode>()
@@ -166,14 +168,16 @@ private fun extractDefaultLambdasInfo(
addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList()) addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
} }
val needReification = instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null val needReification =
instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
Triple(Type.getObjectType(instanceInstuction.owner), Type.getArgumentTypes(instanceInstuction.desc), needReification) Triple(Type.getObjectType(instanceInstuction.owner), Type.getArgumentTypes(instanceInstuction.desc), needReification)
} }
is FieldInsnNode -> { is FieldInsnNode -> {
toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList()) toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList())
val needReification = instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null val needReification =
instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null
Triple(Type.getObjectType(instanceInstuction.owner), emptyArray<Type>(), needReification) Triple(Type.getObjectType(instanceInstuction.owner), emptyArray<Type>(), needReification)
} }
@@ -469,8 +469,10 @@ internal fun isAfterSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn
internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT) internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT)
internal fun isFakeContinuationMarker(insn: AbstractInsnNode) = internal fun isFakeContinuationMarker(insn: AbstractInsnNode) =
insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL
internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) = internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL) isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
internal fun isAfterFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) = internal fun isAfterFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
isSuspendMarker(insn, INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL) isSuspendMarker(insn, INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL)