Don't generated redundant class files

This commit is contained in:
Mikhael Bogdanov
2014-03-05 14:00:22 +04:00
parent ea5788f86c
commit 00764d0ae1
6 changed files with 109 additions and 21 deletions
@@ -221,4 +221,10 @@ public final class ClassFileFactory extends GenerationStateAware implements Outp
this.sourceFiles = sourceFiles;
}
}
public void removeInlinedClasses(Set<String> classNamesToRemove) {
for (String classInternalName : classNamesToRemove) {
generators.remove(classInternalName + ".class");
}
}
}
@@ -126,7 +126,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
try {
node = createMethodNode(callableMethod);
inlineCall(node);
endCall(inlineCall(node));
}
catch (CompilationException e) {
throw e;
@@ -141,7 +141,13 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
text, e, call.getCallElement());
}
}
private void endCall(@NotNull InlineResult result) {
leaveTemps();
state.getFactory().removeInlinedClasses(result.getClassesToRemove());
}
@NotNull
@@ -191,7 +197,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
return node;
}
private void inlineCall(MethodNode node) {
private InlineResult inlineCall(MethodNode node) {
generateClosuresBodies();
List<ParameterInfo> realParams = new ArrayList<ParameterInfo>(actualParameters);
@@ -205,16 +211,15 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
InliningContext info =
new InliningContext(expressionMap, null, null, null, state,
codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()),
codegen.getContext(), call, Collections.<String, String>emptyMap());
codegen.getContext(), call, Collections.<String, String>emptyMap(), false);
MethodInliner inliner = new MethodInliner(node, parameters, info, null, new LambdaFieldRemapper(), isSameModule); //with captured
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(parameters, initialFrameSize);
inliner.doInline(codegen.v, remapper);
return inliner.doInline(codegen.v, remapper);
}
private void generateClosuresBodies() {
for (LambdaInfo info : expressionMap.values()) {
info.setNode(generateLambdaBody(info));
@@ -0,0 +1,51 @@
/*
* 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 org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class InlineResult {
private final Set<String> classesToRemove = new HashSet<String>();
private InlineResult() {
}
@NotNull
public static InlineResult create() {
return new InlineResult();
}
@NotNull
public InlineResult addAllClassesToRemove(@NotNull InlineResult child) {
classesToRemove.addAll(child.classesToRemove);
return this;
}
public void addClassToRemove(@NotNull String classInternalName) {
classesToRemove.add(classInternalName);
}
@NotNull
public Set<String> getClassesToRemove() {
return classesToRemove;
}
}
@@ -27,7 +27,7 @@ import java.util.Map;
public class InliningContext {
public final Map<Integer, LambdaInfo> expresssionMap;
public final Map<Integer, LambdaInfo> expressionMap;
public final List<InvokeCall> invokeCalls;
@@ -45,6 +45,8 @@ public class InliningContext {
public final Map<String, String> typeMapping;
public final boolean isInliningLambda;
public InliningContext(
Map<Integer, LambdaInfo> map,
List<InvokeCall> accesses,
@@ -54,9 +56,10 @@ public class InliningContext {
NameGenerator nameGenerator,
CodegenContext startContext,
Call call,
Map<String, String> typeMapping
Map<String, String> typeMapping,
boolean isInliningLambda
) {
expresssionMap = map;
expressionMap = map;
invokeCalls = accesses;
constructorInvocation = invocation;
this.remapper = remapper;
@@ -65,16 +68,26 @@ public class InliningContext {
this.startContext = startContext;
this.call = call;
this.typeMapping = typeMapping;
this.isInliningLambda = isInliningLambda;
}
public InliningContext subInline(NameGenerator generator) {
return subInline(generator, Collections.<String, String>emptyMap());
}
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
HashMap<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
newTypeMappings.putAll(additionalTypeMappings);
return new InliningContext(expresssionMap, invokeCalls, constructorInvocation, remapper, state, generator, startContext, call,
newTypeMappings);
public InliningContext subInlineLambda(NameGenerator generator) {
return subInline(generator, Collections.<String, String>emptyMap(), true);
}
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
return subInline(generator, additionalTypeMappings, isInliningLambda);
}
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) {
Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
newTypeMappings.putAll(additionalTypeMappings);
return new InliningContext(expressionMap, invokeCalls, constructorInvocation, remapper, state, generator, startContext, call,
newTypeMappings, isInliningLambda);
}
}
@@ -108,7 +108,7 @@ public class LambdaTransformer {
}
}
public void doTransform(ConstructorInvocation invocation) {
public InlineResult doTransform(ConstructorInvocation invocation) {
ClassBuilder classBuilder = createClassBuilder();
//TODO: public visibility for inline function
@@ -128,7 +128,7 @@ public class LambdaTransformer {
remapper = new RegeneratedLambdaFieldRemapper(oldLambdaType.getInternalName(), newLambdaType.getInternalName(), parameters, invocation.getCapturedLambdasToInline());
MethodInliner inliner = new MethodInliner(invoke, parameters, info.subInline(info.nameGenerator.subGenerator("lambda")), oldLambdaType,
remapper, isSameModule);
inliner.doInline(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), remapper, false);
InlineResult result = inliner.doInline(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), remapper, false);
invokeVisitor.visitMaxs(-1, -1);
generateConstructorAndFields(classBuilder, builder, invocation);
@@ -150,6 +150,7 @@ public class LambdaTransformer {
classBuilder.done();
invocation.setNewLambdaType(newLambdaType);
return result;
}
private void generateConstructorAndFields(@NotNull ClassBuilder classBuilder, @NotNull ParametersBuilder builder, @NotNull ConstructorInvocation invocation) {
@@ -46,6 +46,8 @@ public class MethodInliner {
//current state
private final Map<String, String> currentTypeMapping = new HashMap<String, String>();
private final InlineResult result;
/*
*
* @param node
@@ -68,14 +70,15 @@ public class MethodInliner {
this.lambdaFieldRemapper = lambdaFieldRemapper;
this.isSameModule = isSameModule;
this.typeMapper = parent.state.getTypeMapper();
this.result = InlineResult.create();
}
public void doInline(MethodVisitor adapter, VarRemapper.ParamRemapper remapper) {
doInline(adapter, remapper, new LambdaFieldRemapper(), true);
public InlineResult doInline(MethodVisitor adapter, VarRemapper.ParamRemapper remapper) {
return doInline(adapter, remapper, new LambdaFieldRemapper(), true);
}
public void doInline(
public InlineResult doInline(
MethodVisitor adapter,
VarRemapper.ParamRemapper remapper,
LambdaFieldRemapper capturedRemapper, boolean remapReturn
@@ -98,6 +101,7 @@ public class MethodInliner {
transformedNode.accept(visitor);
visitor.visitLabel(end);
return result;
}
private MethodNode doInline(MethodNode node, final LambdaFieldRemapper capturedRemapper) {
@@ -128,6 +132,11 @@ public class MethodInliner {
isSameModule, newLambdaType);
transformer.doTransform(invocation);
if (parent.isInliningLambda) {
//this class is transformed and original not used so we should remove original one after inlining
result.addClassToRemove(invocation.getOwnerInternalName());
}
}
}
@@ -154,11 +163,14 @@ public class MethodInliner {
Parameters lambdaParameters = info.addAllParameters(capturedRemapper);
setInlining(true);
MethodInliner inliner = new MethodInliner(info.getNode(), lambdaParameters, parent.subInline(parent.nameGenerator.subGenerator("lambda")), info.getLambdaClassType(),
capturedRemapper, true /*cause all calls in same module as lambda*/);
MethodInliner inliner = new MethodInliner(info.getNode(), lambdaParameters, parent.subInlineLambda(
parent.nameGenerator.subGenerator("lambda")), info.getLambdaClassType(),
capturedRemapper, true /*cause all calls in same module as lambda*/
);
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(lambdaParameters, valueParamShift);
inliner.doInline(this.mv, remapper); //TODO add skipped this and receiver
InlineResult lambdaResult = inliner.doInline(this.mv, remapper);//TODO add skipped this and receiver
result.addAllClassesToRemove(lambdaResult);
//return value boxing/unboxing
Method bridge = typeMapper.mapSignature(ClosureCodegen.getInvokeFunction(info.getFunctionDescriptor())).getAsmMethod();