Recursive lambdas regeneration/copy
This commit is contained in:
@@ -199,7 +199,7 @@ public class InlineCodegen implements ParentCodegenAware, Inliner {
|
||||
InliningInfo info =
|
||||
new InliningInfo(expressionMap, null, null, null, state,
|
||||
codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()),
|
||||
codegen.getContext(), call);
|
||||
codegen.getContext(), call, Collections.<String, String>emptyMap());
|
||||
|
||||
MethodInliner inliner = new MethodInliner(node, parameters, info, null, new LambdaFieldRemapper(), isSameModule); //with captured
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -41,6 +43,8 @@ public class InliningInfo {
|
||||
|
||||
public final Call call;
|
||||
|
||||
public final Map<String, String> typeMapping;
|
||||
|
||||
public InliningInfo(
|
||||
Map<Integer, LambdaInfo> map,
|
||||
List<InlinableAccess> accesses,
|
||||
@@ -49,7 +53,8 @@ public class InliningInfo {
|
||||
GenerationState state,
|
||||
NameGenerator nameGenerator,
|
||||
CodegenContext startContext,
|
||||
Call call
|
||||
Call call,
|
||||
Map<String, String> typeMapping
|
||||
) {
|
||||
expresssionMap = map;
|
||||
inlinableAccesses = accesses;
|
||||
@@ -59,9 +64,17 @@ public class InliningInfo {
|
||||
this.nameGenerator = nameGenerator;
|
||||
this.startContext = startContext;
|
||||
this.call = call;
|
||||
this.typeMapping = typeMapping;
|
||||
}
|
||||
|
||||
public InliningInfo subInline(NameGenerator generator) {
|
||||
return new InliningInfo(expresssionMap, inlinableAccesses, constructorInvocation, remapper, state, generator, startContext, call);
|
||||
return subInline(generator, Collections.<String, String>emptyMap());
|
||||
}
|
||||
|
||||
public InliningInfo subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
|
||||
HashMap<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new InliningInfo(expresssionMap, inlinableAccesses, constructorInvocation, remapper, state, generator, startContext, call,
|
||||
newTypeMappings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,16 +27,16 @@ import org.jetbrains.asm4.tree.FieldInsnNode;
|
||||
import org.jetbrains.asm4.tree.MethodNode;
|
||||
import org.jetbrains.asm4.tree.VarInsnNode;
|
||||
import org.jetbrains.jet.OutputFile;
|
||||
import org.jetbrains.jet.codegen.AsmUtil;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.codegen.ClosureCodegen;
|
||||
import org.jetbrains.jet.codegen.FieldInfo;
|
||||
import org.jetbrains.jet.codegen.*;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.ASM4;
|
||||
import static org.jetbrains.asm4.Opcodes.V1_6;
|
||||
@@ -67,13 +67,13 @@ public class LambdaTransformer {
|
||||
private String[] interfaces;
|
||||
private boolean isSameModule;
|
||||
|
||||
public LambdaTransformer(String lambdaInternalName, InliningInfo info, boolean isSameModule) {
|
||||
public LambdaTransformer(String lambdaInternalName, InliningInfo info, boolean isSameModule, Type newLambdaType) {
|
||||
this.isSameModule = isSameModule;
|
||||
this.state = info.state;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.info = info;
|
||||
this.oldLambdaType = Type.getObjectType(lambdaInternalName);
|
||||
newLambdaType = Type.getObjectType(info.nameGenerator.genLambdaClassName());
|
||||
this.newLambdaType = newLambdaType;
|
||||
|
||||
//try to find just compiled classes then in dependencies
|
||||
ClassReader reader;
|
||||
@@ -173,7 +173,8 @@ public class LambdaTransformer {
|
||||
}
|
||||
|
||||
private ClassBuilder createClassBuilder() {
|
||||
return state.getFactory().forLambdaInlining(newLambdaType, info.call.getCalleeExpression().getContainingFile());
|
||||
return new RemappingClassBuilder(state.getFactory().forLambdaInlining(newLambdaType, info.call.getCalleeExpression().getContainingFile()),
|
||||
new TypeRemapper(info.typeMapping, isSameModule));
|
||||
}
|
||||
|
||||
private static MethodVisitor newMethod(ClassBuilder builder, MethodNode original) {
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.asm4.commons.Method;
|
||||
import org.jetbrains.asm4.commons.Remapper;
|
||||
import org.jetbrains.asm4.commons.RemappingMethodAdapter;
|
||||
import org.jetbrains.asm4.tree.*;
|
||||
import org.jetbrains.asm4.tree.analysis.*;
|
||||
import org.jetbrains.jet.codegen.ClosureCodegen;
|
||||
@@ -43,7 +45,7 @@ public class MethodInliner {
|
||||
//keeps order
|
||||
private final List<ConstructorInvocation> constructorInvocationList = new ArrayList<ConstructorInvocation>();
|
||||
//current state
|
||||
private final Map<String, ConstructorInvocation> constructorInvocation = new LinkedHashMap<String, ConstructorInvocation>();
|
||||
private final Map<String, String> currentTypeMapping = new HashMap<String, String>();
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -107,7 +109,10 @@ public class MethodInliner {
|
||||
|
||||
final Iterator<ConstructorInvocation> iterator = constructorInvocationList.iterator();
|
||||
|
||||
InlineAdapter inliner = new InlineAdapter(resultNode, parameters.totalSize()) {
|
||||
RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode,
|
||||
new TypeRemapper(currentTypeMapping, isSameModule));
|
||||
|
||||
InlineAdapter inliner = new InlineAdapter(remappingMethodAdapter, parameters.totalSize()) {
|
||||
|
||||
private ConstructorInvocation invocation;
|
||||
@Override
|
||||
@@ -116,24 +121,25 @@ public class MethodInliner {
|
||||
invocation = iterator.next();
|
||||
|
||||
if (invocation.isInlinable()) {
|
||||
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator),
|
||||
isSameModule);
|
||||
//TODO: need poping of type but what to do with local funs???
|
||||
Type newLambdaType = Type.getObjectType(parent.nameGenerator.genLambdaClassName());
|
||||
currentTypeMapping.put(invocation.getOwnerInternalName(), newLambdaType.getInternalName());
|
||||
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator, currentTypeMapping),
|
||||
isSameModule, newLambdaType);
|
||||
|
||||
transformer.doTransform(invocation);
|
||||
super.anew(transformer.getNewLambdaType());
|
||||
constructorInvocation.put(invocation.getOwnerInternalName(), invocation);
|
||||
} else {
|
||||
super.anew(type);
|
||||
}
|
||||
super.anew(type);
|
||||
} else {
|
||||
super.anew(type);
|
||||
}
|
||||
}
|
||||
|
||||
//for local function support
|
||||
@Override
|
||||
public void checkcast(Type type) {
|
||||
super.checkcast(changeOwnerIfLocalFun(type));
|
||||
}
|
||||
////for local function support
|
||||
//@Override
|
||||
//public void checkcast(Type type) {
|
||||
// super.checkcast(changeOwnerIfLocalFun(type));
|
||||
//}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||
@@ -191,7 +197,7 @@ public class MethodInliner {
|
||||
}
|
||||
}
|
||||
else {
|
||||
super.visitMethodInsn(opcode, changeOwnerIfLocalFun(owner), name, desc);
|
||||
super.visitMethodInsn(opcode, /*changeOwnerIfLocalFun(*/owner/*)*/, name, desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -525,26 +531,4 @@ public class MethodInliner {
|
||||
mv.visitVarInsn(next.getOpcode(Opcodes.ISTORE), shift);
|
||||
}
|
||||
}
|
||||
|
||||
private Type changeOwnerIfLocalFun(Type oldType) {
|
||||
if (isLambdaClass(oldType.getInternalName())) {
|
||||
ConstructorInvocation invocation1 = constructorInvocation.get(oldType.getInternalName());
|
||||
if (invocation1 != null && invocation1.isInlinable()) {
|
||||
return invocation1.getNewLambdaType();
|
||||
}
|
||||
}
|
||||
|
||||
return oldType;
|
||||
}
|
||||
|
||||
private String changeOwnerIfLocalFun(String oldType) {
|
||||
if (isLambdaClass(oldType)) {
|
||||
ConstructorInvocation invocation1 = constructorInvocation.get(oldType);
|
||||
if (invocation1 != null && invocation1.isInlinable()) {
|
||||
return invocation1.getNewLambdaType().getInternalName();
|
||||
}
|
||||
}
|
||||
|
||||
return oldType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.codegen.asm;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.commons.Remapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TypeRemapper extends Remapper {
|
||||
|
||||
@NotNull
|
||||
private final Map<String, String> typeMapping;
|
||||
|
||||
private final boolean isSameModule;
|
||||
|
||||
//typeMapping could be changed outside through method processing
|
||||
public TypeRemapper(@NotNull Map<String, String> typeMapping, boolean isSameModule) {
|
||||
this.typeMapping = typeMapping;
|
||||
this.isSameModule = isSameModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String map(String type) {
|
||||
String newType = typeMapping.get(type);
|
||||
if (newType != null) {
|
||||
return newType;
|
||||
}
|
||||
|
||||
/*if (!isSameModule) {
|
||||
int indexOfMinus = type.indexOf("-");
|
||||
if (indexOfMinus > 0) {
|
||||
//type.substring(0, indexOfMinus)
|
||||
}
|
||||
}*/
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.codegen.inline;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.AnnotationVisitor;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.FieldVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.commons.*;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.codegen.JvmSerializationBindings;
|
||||
|
||||
public class RemappingClassBuilder implements ClassBuilder {
|
||||
|
||||
private final ClassBuilder builder;
|
||||
private final Remapper remapper;
|
||||
|
||||
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
|
||||
this.builder = builder;
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FieldVisitor newField(
|
||||
@Nullable PsiElement origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
return new RemappingFieldAdapter(builder.newField(origin, access, name, remapper.mapDesc(desc), signature, value), remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public MethodVisitor newMethod(
|
||||
@Nullable PsiElement origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
return new RemappingMethodAdapter(access, desc, builder.newMethod(origin, access, name, remapper.mapMethodDesc(desc), signature, exceptions), remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
return builder.getSerializationBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
|
||||
return new RemappingAnnotationAdapter(builder.newAnnotation(remapper.mapDesc(desc), visible), remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
builder.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClassVisitor getVisitor() {
|
||||
return new RemappingClassAdapter(builder.getVisitor(), remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
builder.defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(@NotNull String name, @Nullable String debug) {
|
||||
builder.visitSource(name, debug);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
|
||||
builder.visitOuterClass(owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
|
||||
builder.visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getThisName() {
|
||||
return builder.getThisName();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user