Introduced base class for AnonymousObjectGeneration

This commit is contained in:
Michael Bogdanov
2016-03-10 15:22:34 +03:00
parent c6007c91f7
commit 8c9d8778eb
5 changed files with 165 additions and 61 deletions
@@ -24,7 +24,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class AnonymousObjectGeneration { public class AnonymousObjectRegenerationInfo extends RegenerationInfo {
private final String ownerInternalName; private final String ownerInternalName;
@@ -45,7 +45,7 @@ public class AnonymousObjectGeneration {
private final boolean alreadyRegenerated; private final boolean alreadyRegenerated;
private final boolean isStaticOrigin; private final boolean isStaticOrigin;
AnonymousObjectGeneration( AnonymousObjectRegenerationInfo(
@NotNull String ownerInternalName, @NotNull String ownerInternalName,
boolean needReification, boolean needReification,
@NotNull Map<Integer, LambdaInfo> lambdasToInline, @NotNull Map<Integer, LambdaInfo> lambdasToInline,
@@ -63,7 +63,7 @@ public class AnonymousObjectGeneration {
this.isStaticOrigin = isStaticOrigin; this.isStaticOrigin = isStaticOrigin;
} }
public AnonymousObjectGeneration( public AnonymousObjectRegenerationInfo(
@NotNull String ownerInternalName, boolean needReification, @NotNull String ownerInternalName, boolean needReification,
boolean alreadyRegenerated, boolean alreadyRegenerated,
boolean isStaticOrigin boolean isStaticOrigin
@@ -74,10 +74,13 @@ public class AnonymousObjectGeneration {
); );
} }
@NotNull
@Override
public String getOldClassName() { public String getOldClassName() {
return ownerInternalName; return ownerInternalName;
} }
@Override
public boolean shouldRegenerate(boolean isSameModule) { public boolean shouldRegenerate(boolean isSameModule) {
return !alreadyRegenerated && ( return !alreadyRegenerated && (
!lambdasToInline.isEmpty() || !isSameModule || capturedOuterRegenerated || needReification !lambdasToInline.isEmpty() || !isSameModule || capturedOuterRegenerated || needReification
@@ -88,8 +91,10 @@ public class AnonymousObjectGeneration {
return lambdasToInline; return lambdasToInline;
} }
public Type getNewLambdaType() { @NotNull
return newLambdaType; @Override
public String getNewClassName() {
return newLambdaType.getInternalName();
} }
public void setNewLambdaType(Type newLambdaType) { public void setNewLambdaType(Type newLambdaType) {
@@ -34,14 +34,12 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
public class AnonymousObjectTransformer { public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjectRegenerationInfo> {
protected final GenerationState state; protected final GenerationState state;
protected final KotlinTypeMapper typeMapper; protected final KotlinTypeMapper typeMapper;
private final InlineResult transformationResult;
private MethodNode constructor; private MethodNode constructor;
private String sourceInfo; private String sourceInfo;
@@ -56,36 +54,33 @@ public class AnonymousObjectTransformer {
private final Type newLambdaType; private final Type newLambdaType;
private final ClassReader reader;
private final boolean isSameModule; private final boolean isSameModule;
private final Map<String, List<String>> fieldNames = new HashMap<String, List<String>>(); private final Map<String, List<String>> fieldNames = new HashMap<String, List<String>>();
public AnonymousObjectTransformer( public AnonymousObjectTransformer(
@NotNull String objectInternalName, @NotNull AnonymousObjectRegenerationInfo regenerationInfo,
@NotNull InliningContext inliningContext, @NotNull InliningContext inliningContext,
boolean isSameModule, boolean isSameModule,
@NotNull Type newLambdaType @NotNull Type newLambdaType
) { ) {
super(regenerationInfo, inliningContext.state);
this.isSameModule = isSameModule; this.isSameModule = isSameModule;
this.state = inliningContext.state; this.state = inliningContext.state;
this.typeMapper = state.getTypeMapper(); this.typeMapper = state.getTypeMapper();
this.inliningContext = inliningContext; this.inliningContext = inliningContext;
this.oldObjectType = Type.getObjectType(objectInternalName); this.oldObjectType = Type.getObjectType(regenerationInfo.getOldClassName());
this.newLambdaType = newLambdaType; this.newLambdaType = newLambdaType;
reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName);
transformationResult = InlineResult.create();
} }
@Override
@NotNull @NotNull
public InlineResult doTransform(@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) { public InlineResult doTransform(@NotNull AnonymousObjectRegenerationInfo regenerationInfo, @NotNull FieldRemapper parentRemapper) {
final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>(); final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
ClassBuilder classBuilder = createClassBuilder(); ClassBuilder classBuilder = createRemappingClassBuilderViaFactory(inliningContext);
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>(); final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
reader.accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) { createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
@Override @Override
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name); InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name);
@@ -160,13 +155,13 @@ public class AnonymousObjectTransformer {
ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder(); ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
List<CapturedParamInfo> additionalFakeParams = List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder, extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
anonymousObjectGen, parentRemapper); regenerationInfo, parentRemapper);
List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>(); List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();
for (MethodNode next : methodsToTransform) { for (MethodNode next : methodsToTransform) {
MethodVisitor deferringVisitor = newMethod(classBuilder, next); MethodVisitor deferringVisitor = newMethod(classBuilder, next);
InlineResult funResult = InlineResult funResult =
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false); inlineMethodAndUpdateGlobalResult(regenerationInfo, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false);
Type returnType = Type.getReturnType(next.desc); Type returnType = Type.getReturnType(next.desc);
if (!AsmUtil.isPrimitive(returnType)) { if (!AsmUtil.isPrimitive(returnType)) {
@@ -183,7 +178,7 @@ public class AnonymousObjectTransformer {
method.visitEnd(); method.visitEnd();
} }
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams); generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, regenerationInfo, parentRemapper, additionalFakeParams);
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder); SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
@@ -196,7 +191,7 @@ public class AnonymousObjectTransformer {
classBuilder.done(); classBuilder.done();
anonymousObjectGen.setNewLambdaType(newLambdaType); regenerationInfo.setNewLambdaType(newLambdaType);
return transformationResult; return transformationResult;
} }
@@ -207,14 +202,14 @@ public class AnonymousObjectTransformer {
@NotNull @NotNull
private InlineResult inlineMethodAndUpdateGlobalResult( private InlineResult inlineMethodAndUpdateGlobalResult(
@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull AnonymousObjectRegenerationInfo regenerationInfo,
@NotNull FieldRemapper parentRemapper, @NotNull FieldRemapper parentRemapper,
@NotNull MethodVisitor deferringVisitor, @NotNull MethodVisitor deferringVisitor,
@NotNull MethodNode next, @NotNull MethodNode next,
@NotNull ParametersBuilder allCapturedParamBuilder, @NotNull ParametersBuilder allCapturedParamBuilder,
boolean isConstructor boolean isConstructor
) { ) {
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, isConstructor); InlineResult funResult = inlineMethod(regenerationInfo, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, isConstructor);
transformationResult.addAllClassesToRemove(funResult); transformationResult.addAllClassesToRemove(funResult);
transformationResult.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages()); transformationResult.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages());
return funResult; return funResult;
@@ -222,7 +217,7 @@ public class AnonymousObjectTransformer {
@NotNull @NotNull
private InlineResult inlineMethod( private InlineResult inlineMethod(
@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull AnonymousObjectRegenerationInfo regenerationInfo,
@NotNull FieldRemapper parentRemapper, @NotNull FieldRemapper parentRemapper,
@NotNull MethodVisitor deferringVisitor, @NotNull MethodVisitor deferringVisitor,
@NotNull MethodNode sourceNode, @NotNull MethodNode sourceNode,
@@ -234,7 +229,7 @@ public class AnonymousObjectTransformer {
RegeneratedLambdaFieldRemapper remapper = RegeneratedLambdaFieldRemapper remapper =
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(), new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
parameters, anonymousObjectGen.getCapturedLambdasToInline(), parameters, regenerationInfo.getCapturedLambdasToInline(),
parentRemapper, isConstructor); parentRemapper, isConstructor);
MethodInliner inliner = MethodInliner inliner =
@@ -244,12 +239,12 @@ public class AnonymousObjectTransformer {
inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")), inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
remapper, remapper,
isSameModule, isSameModule,
"Transformer for " + anonymousObjectGen.getOldClassName(), "Transformer for " + regenerationInfo.getOldClassName(),
sourceMapper, sourceMapper,
new InlineCallSiteInfo( new InlineCallSiteInfo(
anonymousObjectGen.getOldClassName(), regenerationInfo.getOldClassName(),
sourceNode.name, sourceNode.name,
isConstructor ? anonymousObjectGen.getNewConstructorDescriptor() : sourceNode.desc), isConstructor ? regenerationInfo.getNewConstructorDescriptor() : sourceNode.desc),
null null
); );
@@ -263,7 +258,7 @@ public class AnonymousObjectTransformer {
@NotNull ClassBuilder classBuilder, @NotNull ClassBuilder classBuilder,
@NotNull ParametersBuilder allCapturedBuilder, @NotNull ParametersBuilder allCapturedBuilder,
@NotNull ParametersBuilder constructorInlineBuilder, @NotNull ParametersBuilder constructorInlineBuilder,
@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull AnonymousObjectRegenerationInfo regenerationInfo,
@NotNull FieldRemapper parentRemapper, @NotNull FieldRemapper parentRemapper,
@NotNull List<CapturedParamInfo> constructorAdditionalFakeParams @NotNull List<CapturedParamInfo> constructorAdditionalFakeParams
) { ) {
@@ -291,7 +286,7 @@ public class AnonymousObjectTransformer {
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()])); String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
//TODO for inline method make public class //TODO for inline method make public class
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor); regenerationInfo.setNewConstructorDescriptor(constructorDescriptor);
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN, MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
AsmUtil.NO_FLAG_PACKAGE_PRIVATE, AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
"<init>", constructorDescriptor, "<init>", constructorDescriptor,
@@ -329,7 +324,7 @@ public class AnonymousObjectTransformer {
} }
} }
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true); inlineMethodAndUpdateGlobalResult(regenerationInfo, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
constructorVisitor.visitEnd(); constructorVisitor.visitEnd();
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder); AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
} }
@@ -346,16 +341,6 @@ public class AnonymousObjectTransformer {
return builder.buildParameters(); return builder.buildParameters();
} }
@NotNull
private ClassBuilder createClassBuilder() {
ClassBuilder classBuilder = state.getFactory().newVisitor(NO_ORIGIN, newLambdaType, inliningContext.getRoot().callElement.getContainingFile());
return new RemappingClassBuilder(
classBuilder,
new AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.getRoot().typeParameterMappings == null, transformationResult)
);
}
@NotNull @NotNull
private static DeferredMethodVisitor newMethod(@NotNull final ClassBuilder builder, @NotNull final MethodNode original) { private static DeferredMethodVisitor newMethod(@NotNull final ClassBuilder builder, @NotNull final MethodNode original) {
return new DeferredMethodVisitor( return new DeferredMethodVisitor(
@@ -383,20 +368,20 @@ public class AnonymousObjectTransformer {
@NotNull MethodNode constructor, @NotNull MethodNode constructor,
@NotNull ParametersBuilder capturedParamBuilder, @NotNull ParametersBuilder capturedParamBuilder,
@NotNull ParametersBuilder constructorParamBuilder, @NotNull ParametersBuilder constructorParamBuilder,
@NotNull final AnonymousObjectGeneration anonymousObjectGen, @NotNull final AnonymousObjectRegenerationInfo regenerationInfo,
@NotNull FieldRemapper parentFieldRemapper @NotNull FieldRemapper parentFieldRemapper
) { ) {
CapturedParamOwner owner = new CapturedParamOwner() { CapturedParamOwner owner = new CapturedParamOwner() {
@Override @Override
public Type getType() { public Type getType() {
return Type.getObjectType(anonymousObjectGen.getOldClassName()); return Type.getObjectType(regenerationInfo.getOldClassName());
} }
}; };
Set<LambdaInfo> capturedLambdas = new LinkedHashSet<LambdaInfo>(); //captured var of inlined parameter Set<LambdaInfo> capturedLambdas = new LinkedHashSet<LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>(); List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
Map<Integer, LambdaInfo> indexToLambda = anonymousObjectGen.getLambdasToInline(); Map<Integer, LambdaInfo> indexToLambda = regenerationInfo.getLambdasToInline();
Set<Integer> capturedParams = new HashSet<Integer>(); Set<Integer> capturedParams = new HashSet<Integer>();
//load captured parameters and patch instruction list (NB: there is also could be object fields) //load captured parameters and patch instruction list (NB: there is also could be object fields)
@@ -439,7 +424,7 @@ public class AnonymousObjectTransformer {
} }
constructorParamBuilder.addThis(oldObjectType, false); constructorParamBuilder.addThis(oldObjectType, false);
String constructorDesc = anonymousObjectGen.getConstructorDesc(); String constructorDesc = regenerationInfo.getConstructorDesc();
if (constructorDesc == null) { if (constructorDesc == null) {
// in case of anonymous object with empty closure // in case of anonymous object with empty closure
@@ -514,8 +499,8 @@ public class AnonymousObjectTransformer {
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed); constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
} }
anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters); regenerationInfo.setAllRecapturedParameters(allRecapturedParameters);
anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline); regenerationInfo.setCapturedLambdasToInline(capturedLambdasToInline);
return constructorAdditionalFakeParams; return constructorAdditionalFakeParams;
} }
@@ -63,7 +63,7 @@ public class MethodInliner {
private final List<InvokeCall> invokeCalls = new ArrayList<InvokeCall>(); private final List<InvokeCall> invokeCalls = new ArrayList<InvokeCall>();
//keeps order //keeps order
private final List<AnonymousObjectGeneration> anonymousObjectGenerations = new ArrayList<AnonymousObjectGeneration>(); private final List<AnonymousObjectRegenerationInfo> anonymousObjectRegenerations = new ArrayList<AnonymousObjectRegenerationInfo>();
//current state //current state
private final Map<String, String> currentTypeMapping = new HashMap<String, String>(); private final Map<String, String> currentTypeMapping = new HashMap<String, String>();
@@ -160,7 +160,7 @@ public class MethodInliner {
final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null); final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
final Iterator<AnonymousObjectGeneration> iterator = anonymousObjectGenerations.iterator(); final Iterator<AnonymousObjectRegenerationInfo> iterator = anonymousObjectRegenerations.iterator();
final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping); final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping);
final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter( final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(
@@ -173,8 +173,8 @@ public class MethodInliner {
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node); final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) { InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) {
private AnonymousObjectGeneration anonymousObjectGen; private AnonymousObjectRegenerationInfo anonymousObjectGen;
private void handleAnonymousObjectGeneration() { private void handleAnonymousObjectRegeneration() {
anonymousObjectGen = iterator.next(); anonymousObjectGen = iterator.next();
if (anonymousObjectGen.shouldRegenerate(isSameModule)) { if (anonymousObjectGen.shouldRegenerate(isSameModule)) {
@@ -183,7 +183,7 @@ public class MethodInliner {
String newClassName = inliningContext.nameGenerator.genLambdaClassName(); String newClassName = inliningContext.nameGenerator.genLambdaClassName();
remapper.addMapping(oldClassName, newClassName); remapper.addMapping(oldClassName, newClassName);
AnonymousObjectTransformer transformer = AnonymousObjectTransformer transformer =
new AnonymousObjectTransformer(oldClassName, new AnonymousObjectTransformer((AnonymousObjectRegenerationInfo) anonymousObjectGen,
inliningContext inliningContext
.subInlineWithClassRegeneration( .subInlineWithClassRegeneration(
inliningContext.nameGenerator, inliningContext.nameGenerator,
@@ -213,7 +213,7 @@ public class MethodInliner {
@Override @Override
public void anew(@NotNull Type type) { public void anew(@NotNull Type type) {
if (isAnonymousConstructorCall(type.getInternalName(), "<init>")) { if (isAnonymousConstructorCall(type.getInternalName(), "<init>")) {
handleAnonymousObjectGeneration(); handleAnonymousObjectRegeneration();
} }
//in case of regenerated anonymousObjectGen type would be remapped to new one via remappingMethodAdapter //in case of regenerated anonymousObjectGen type would be remapped to new one via remappingMethodAdapter
@@ -278,7 +278,7 @@ public class MethodInliner {
visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(),
"$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor()); "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
} }
String newInternalName = anonymousObjectGen.getNewLambdaType().getInternalName(); String newInternalName = anonymousObjectGen.getNewClassName();
super.visitMethodInsn(opcode, newInternalName, name, anonymousObjectGen.getNewConstructorDescriptor(), itf); super.visitMethodInsn(opcode, newInternalName, name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
//TODO: add new inner class also for other contexts //TODO: add new inner class also for other contexts
@@ -302,7 +302,7 @@ public class MethodInliner {
@Override @Override
public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) { public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) {
if (opcode == Opcodes.GETSTATIC && isAnonymousSingletonLoad(owner, name)) { if (opcode == Opcodes.GETSTATIC && isAnonymousSingletonLoad(owner, name)) {
handleAnonymousObjectGeneration(); handleAnonymousObjectRegeneration();
} }
super.visitFieldInsn(opcode, owner, name, desc); super.visitFieldInsn(opcode, owner, name, desc);
} }
@@ -488,7 +488,7 @@ public class MethodInliner {
offset += i == 0 ? 1 : argTypes[i - 1].getSize(); offset += i == 0 ? 1 : argTypes[i - 1].getSize();
} }
anonymousObjectGenerations.add( anonymousObjectRegenerations.add(
buildConstructorInvocation( buildConstructorInvocation(
owner, desc, lambdaMapping, awaitClassReification owner, desc, lambdaMapping, awaitClassReification
) )
@@ -500,8 +500,8 @@ public class MethodInliner {
FieldInsnNode fieldInsnNode = (FieldInsnNode) cur; FieldInsnNode fieldInsnNode = (FieldInsnNode) cur;
String owner = fieldInsnNode.owner; String owner = fieldInsnNode.owner;
if (isAnonymousSingletonLoad(owner, fieldInsnNode.name)) { if (isAnonymousSingletonLoad(owner, fieldInsnNode.name)) {
anonymousObjectGenerations.add( anonymousObjectRegenerations.add(
new AnonymousObjectGeneration( new AnonymousObjectRegenerationInfo(
owner, awaitClassReification, isAlreadyRegenerated(owner), true owner, awaitClassReification, isAlreadyRegenerated(owner), true
) )
); );
@@ -551,13 +551,13 @@ public class MethodInliner {
} }
@NotNull @NotNull
private AnonymousObjectGeneration buildConstructorInvocation( private AnonymousObjectRegenerationInfo buildConstructorInvocation(
@NotNull String anonymousType, @NotNull String anonymousType,
@NotNull String desc, @NotNull String desc,
@NotNull Map<Integer, LambdaInfo> lambdaMapping, @NotNull Map<Integer, LambdaInfo> lambdaMapping,
boolean needReification boolean needReification
) { ) {
return new AnonymousObjectGeneration( return new AnonymousObjectRegenerationInfo(
anonymousType, needReification, lambdaMapping, anonymousType, needReification, lambdaMapping,
inliningContext.classRegeneration, inliningContext.classRegeneration,
isAlreadyRegenerated(anonymousType), isAlreadyRegenerated(anonymousType),
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2016 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 org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor
import org.jetbrains.org.objectweb.asm.Type
abstract class ObjectTransformer<T : RegenerationInfo>(val regenerationInfo: T, val state: GenerationState) {
abstract fun doTransform(info: T, parentRemapper: FieldRemapper): InlineResult
@JvmField
val transformationResult = InlineResult.create()
protected fun createRemappingClassBuilderViaFactory(inliningContext: InliningContext): ClassBuilder {
val classBuilder = state.factory.newVisitor(
JvmDeclarationOrigin.NO_ORIGIN,
Type.getObjectType(regenerationInfo.getNewClassName()),
inliningContext.root.callElement.containingFile
)
return RemappingClassBuilder(
classBuilder,
AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.root.typeParameterMappings == null, transformationResult))
}
fun createClassReader(): ClassReader {
return InlineCodegenUtil.buildClassReaderByInternalName(state, regenerationInfo.getOldClassName())
}
}
class WhenMappingTransformer(
whenObjectRegenerationInfo: WhenMappingRegenerationInfo,
state: GenerationState,
val inliningContext: InliningContext
) : ObjectTransformer<WhenMappingRegenerationInfo>(whenObjectRegenerationInfo, state) {
override fun doTransform(info: WhenMappingRegenerationInfo, parentRemapper: FieldRemapper): InlineResult {
val classReader = createClassReader()
//TODO add additional check that it's when mapping
val classBuilder = createRemappingClassBuilderViaFactory(inliningContext)
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String, superName: String, interfaces: Array<String>) {
InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name)
super.visit(version, access, name, signature, superName, interfaces)
}
}, ClassReader.SKIP_FRAMES)
return transformationResult
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2016 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
abstract class RegenerationInfo() {
abstract fun getOldClassName(): String
abstract fun getNewClassName(): String
abstract fun shouldRegenerate(sameModule: Boolean): Boolean
}
class WhenMappingRegenerationInfo(val oldName: String, val nameGenerator: NameGenerator) : RegenerationInfo() {
override fun shouldRegenerate(sameModule: Boolean): Boolean {
throw UnsupportedOperationException()
}
override fun getOldClassName(): String {
return oldName
}
override fun getNewClassName(): String {
return nameGenerator.genLambdaClassName() + oldName
}
}