Write enclosing method info for transformed objects

This commit is contained in:
Michael Bogdanov
2016-01-08 12:51:42 +03:00
parent 8ab1190082
commit 657b9ff808
20 changed files with 348 additions and 51 deletions
@@ -97,21 +97,6 @@ public class AnonymousObjectTransformer {
innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
}
@Override
public void visitOuterClass(@NotNull String owner, String name, String desc) {
InliningContext parent = inliningContext.getParent();
assert parent != null : "Context for transformer should have parent one: " + inliningContext;
//we don't write owner info for lamdbas and SAMs just only for objects
if (parent.isRoot() || parent.isInliningLambdaRootContext()) {
//TODO: think about writing method info - there is some problem with new constructor desc calculation
super.visitOuterClass(inliningContext.getParent().getClassNameToInline(), null, null);
return;
}
super.visitOuterClass(owner, name, desc);
}
@Override
public MethodVisitor visitMethod(
int access, @NotNull String name, @NotNull String desc, String signature, String[] exceptions
@@ -202,16 +187,24 @@ public class AnonymousObjectTransformer {
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
ClassVisitor visitor = classBuilder.getVisitor();
for (InnerClassNode node : innerClassNodes) {
classBuilder.getVisitor().visitInnerClass(node.name, node.outerName, node.innerName, node.access);
visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access);
}
writeOuterInfo(visitor);
classBuilder.done();
anonymousObjectGen.setNewLambdaType(newLambdaType);
return transformationResult;
}
private void writeOuterInfo(@NotNull ClassVisitor visitor) {
InlineCallSiteInfo info = inliningContext.getCallSiteInfo();
visitor.visitOuterClass(info.getOwnerClassName(), info.getFunctionName(), info.getFunctionDesc());
}
@NotNull
private InlineResult inlineMethodAndUpdateGlobalResult(
@NotNull AnonymousObjectGeneration anonymousObjectGen,
@@ -244,9 +237,20 @@ public class AnonymousObjectTransformer {
parameters, anonymousObjectGen.getCapturedLambdasToInline(),
parentRemapper, isConstructor);
MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(),
sourceMapper);
MethodInliner inliner =
new MethodInliner(
sourceNode,
parameters,
inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
remapper,
isSameModule,
"Transformer for " + anonymousObjectGen.getOwnerInternalName(),
sourceMapper,
new InlineCallSiteInfo(
anonymousObjectGen.getOwnerInternalName(),
sourceNode.name,
isConstructor ? anonymousObjectGen.getNewConstructorDescriptor() : sourceNode.desc)
);
InlineResult result = inliner.doInline(deferringVisitor, new LocalVarRemapper(parameters, 0), false, LabelOwner.NOT_APPLICABLE);
result.getReifiedTypeParametersUsages().mergeAll(typeParametersToReify);
@@ -285,6 +289,8 @@ public class AnonymousObjectTransformer {
}
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
//TODO for inline method make public class
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
"<init>", constructorDescriptor,
@@ -325,8 +331,6 @@ public class AnonymousObjectTransformer {
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
constructorVisitor.visitEnd();
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
//TODO for inline method make public class
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
}
@NotNull
@@ -0,0 +1,19 @@
/*
* 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
class InlineCallSiteInfo(val ownerClassName: String, val functionName: String?, val functionDesc: String?)
@@ -269,12 +269,12 @@ public class InlineCodegen extends CallGenerator {
.subGenerator(functionDescriptor.getName().asString()),
codegen.getContext(),
callElement,
codegen.getParentCodegen().getClassName(), reifiedTypeInliner,
getInlineCallSiteInfo(), reifiedTypeInliner,
typeParameterMappings);
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + callElement.getText(),
createNestedSourceMapper(nodeAndSmap)); //with captured
createNestedSourceMapper(nodeAndSmap), info.getCallSiteInfo()); //with captured
LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
@@ -306,6 +306,13 @@ public class InlineCodegen extends CallGenerator {
return result;
}
private InlineCallSiteInfo getInlineCallSiteInfo() {
MemberCodegen<?> parentCodegen = codegen.getParentCodegen();
MethodContext context = codegen.getContext();
JvmMethodSignature signature = typeMapper.mapSignature(context.getFunctionDescriptor(), context.getContextKind());
return new InlineCallSiteInfo(parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor());
}
private void generateClosuresBodies() {
for (LambdaInfo info : expressionMap.values()) {
info.setNode(generateLambdaBody(info));
@@ -73,17 +73,18 @@ public class InliningContext {
return subInline(nameGenerator.subGenerator("lambda"), map, true);
}
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
private InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
return subInline(generator, additionalTypeMappings, isInliningLambda);
}
public InliningContext subInlineWithClassRegeneration(@NotNull NameGenerator generator,
@NotNull Map<String, String> newTypeMappings,
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
@NotNull AnonymousObjectGeneration anonymousObjectGeneration,
@NotNull InlineCallSiteInfo callSiteInfo
) {
return new RegeneratedClassContext(this, expressionMap, state, generator,
TypeRemapper.createFrom(typeRemapper, newTypeMappings),
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration, callSiteInfo);
}
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) {
@@ -131,8 +132,8 @@ public class InliningContext {
return isInliningLambda && !getParent().isInliningLambda;
}
public String getClassNameToInline() {
public InlineCallSiteInfo getCallSiteInfo() {
assert parent != null : "At least root context should return proper value";
return parent.getClassNameToInline();
return parent.getCallSiteInfo();
}
}
@@ -55,6 +55,8 @@ public class MethodInliner {
private final SourceMapper sourceMapper;
private final InlineCallSiteInfo inlineCallSiteInfo;
private final JetTypeMapper typeMapper;
private final List<InvokeCall> invokeCalls = new ArrayList<InvokeCall>();
@@ -82,7 +84,8 @@ public class MethodInliner {
@NotNull FieldRemapper nodeRemapper,
boolean isSameModule,
@NotNull String errorPrefix,
@NotNull SourceMapper sourceMapper
@NotNull SourceMapper sourceMapper,
@NotNull InlineCallSiteInfo inlineCallSiteInfo
) {
this.node = node;
this.parameters = parameters;
@@ -91,6 +94,7 @@ public class MethodInliner {
this.isSameModule = isSameModule;
this.errorPrefix = errorPrefix;
this.sourceMapper = sourceMapper;
this.inlineCallSiteInfo = inlineCallSiteInfo;
this.typeMapper = inliningContext.state.getTypeMapper();
this.result = InlineResult.create();
}
@@ -145,7 +149,7 @@ public class MethodInliner {
return result;
}
private MethodNode doInline(MethodNode node) {
private MethodNode doInline(final MethodNode node) {
final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
@@ -179,7 +183,8 @@ public class MethodInliner {
.subInlineWithClassRegeneration(
inliningContext.nameGenerator,
currentTypeMapping,
anonymousObjectGen),
anonymousObjectGen,
inlineCallSiteInfo),
isSameModule, Type.getObjectType(newClassName)
);
@@ -243,7 +248,7 @@ public class MethodInliner {
inliningContext.subInlineLambda(info),
newCapturedRemapper, true /*cause all calls in same module as lambda*/,
"Lambda inlining " + info.getLambdaClassType().getInternalName(),
mapper);
mapper, inlineCallSiteInfo);
LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift);
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);//TODO add skipped this and receiver
@@ -639,7 +644,7 @@ public class MethodInliner {
}
}
private void transformFinallyDeepIndex(@NotNull MethodNode node, int finallyDeepShift) {
private static void transformFinallyDeepIndex(@NotNull MethodNode node, int finallyDeepShift) {
if (finallyDeepShift == 0) {
return;
}
@@ -24,6 +24,7 @@ import java.util.Map;
public class RegeneratedClassContext extends InliningContext {
private final AnonymousObjectGeneration anonymousObjectGeneration;
private InlineCallSiteInfo callSiteInfo;
public RegeneratedClassContext(
@Nullable InliningContext parent,
@@ -33,14 +34,15 @@ public class RegeneratedClassContext extends InliningContext {
@NotNull TypeRemapper typeRemapper,
@NotNull ReifiedTypeInliner reifiedTypeInliner,
boolean isInliningLambda,
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
@NotNull AnonymousObjectGeneration anonymousObjectGeneration,
@NotNull InlineCallSiteInfo callSiteInfo
) {
super(parent, map, state, nameGenerator, typeRemapper, reifiedTypeInliner, isInliningLambda, true);
this.anonymousObjectGeneration = anonymousObjectGeneration;
this.callSiteInfo = callSiteInfo;
}
@Override
public String getClassNameToInline() {
return anonymousObjectGeneration.getOwnerInternalName();
public InlineCallSiteInfo getCallSiteInfo() {
return callSiteInfo;
}
}
@@ -26,7 +26,7 @@ import java.util.Map;
public class RootInliningContext extends InliningContext {
public final CodegenContext startContext;
private final String classNameToInline;
private final InlineCallSiteInfo inlineCallSiteInfo;
public final TypeParameterMappings typeParameterMappings;
public final KtElement callElement;
@@ -36,20 +36,19 @@ public class RootInliningContext extends InliningContext {
@NotNull NameGenerator nameGenerator,
@NotNull CodegenContext startContext,
@NotNull KtElement callElement,
@NotNull String classNameToInline,
@NotNull InlineCallSiteInfo classNameToInline,
@NotNull ReifiedTypeInliner inliner,
@Nullable TypeParameterMappings typeParameterMappings
) {
super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false);
this.callElement = callElement;
this.startContext = startContext;
this.classNameToInline = classNameToInline;
this.inlineCallSiteInfo = classNameToInline;
this.typeParameterMappings = typeParameterMappings;
}
@Override
@NotNull
public String getClassNameToInline() {
return classNameToInline;
public InlineCallSiteInfo getCallSiteInfo() {
return inlineCallSiteInfo;
}
}