Code clean and simplification

This commit is contained in:
Mikhael Bogdanov
2014-02-27 18:27:21 +04:00
parent 55fbdbd302
commit 1a011c3f9b
12 changed files with 82 additions and 172 deletions
@@ -1,47 +0,0 @@
/*
* Copyright 2010-2013 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;
public class FieldAccess {
private final String name;
private final String type;
private final FieldAccess owner;
private final boolean isThisAccess;
public FieldAccess(String name, String type, FieldAccess owner) {
this.name = name;
this.type = type;
this.owner = owner;
isThisAccess = false;
}
public FieldAccess(String name, String type) {
this.name = "!this!" + name;
this.type = type;
isThisAccess = true;
owner = null;
}
public boolean isThisAccess() {
return isThisAccess;
}
}
@@ -196,10 +196,10 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
List<CapturedParamInfo> captured = getAllCaptured();
Parameters parameters = new Parameters(realParams, Parameters.addStubs(captured, realParams.size()));
Parameters parameters = new Parameters(realParams, Parameters.shiftAndAddStubs(captured, realParams.size()));
InliningInfo info =
new InliningInfo(expressionMap, null, null, null, state,
InliningContext info =
new InliningContext(expressionMap, null, null, null, state,
codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()),
codegen.getContext(), call, Collections.<String, String>emptyMap());
@@ -38,12 +38,14 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName;
@@ -78,25 +80,24 @@ public class InlineCodegenUtil {
@NotNull
public static VirtualFile getVirtualFileForCallable(DeserializedSimpleFunctionDescriptor deserializedDescriptor, GenerationState state) {
VirtualFile file = null;
DeclarationDescriptor parentDeclatation = deserializedDescriptor.getContainingDeclaration();
if (parentDeclatation instanceof PackageFragmentDescriptor) {
VirtualFile file;
DeclarationDescriptor parentDeclaration = deserializedDescriptor.getContainingDeclaration();
if (parentDeclaration instanceof PackageFragmentDescriptor) {
ProtoBuf.Callable proto = deserializedDescriptor.getFunctionProto();
if (proto.hasExtension(JavaProtoBuf.implClassName)) {
Name name = deserializedDescriptor.getNameResolver().getName(proto.getExtension(JavaProtoBuf.implClassName));
FqName namespaceFqName =
PackageClassUtils.getPackageClassFqName(((PackageFragmentDescriptor) parentDeclatation).getFqName()).parent().child(
name);
file = findVirtualFileWithHeader(state.getProject(), namespaceFqName);
} else {
assert false : "Function in namespace should have implClassName property in proto: " + deserializedDescriptor;
if (!proto.hasExtension(JavaProtoBuf.implClassName)) {
throw new IllegalStateException("Function in namespace should have implClassName property in proto: " + deserializedDescriptor);
}
Name name = deserializedDescriptor.getNameResolver().getName(proto.getExtension(JavaProtoBuf.implClassName));
FqName packagePartFqName =
PackageClassUtils.getPackageClassFqName(((PackageFragmentDescriptor) parentDeclaration).getFqName()).parent().child(
name);
file = findVirtualFileWithHeader(state.getProject(), packagePartFqName);
} else {
file = findVirtualFileContainingDescriptor(state.getProject(), deserializedDescriptor);
}
if (file == null) {
throw new RuntimeException("Couldn't find declaration file for " + deserializedDescriptor.getName());
throw new IllegalStateException("Couldn't find declaration file for " + deserializedDescriptor.getName());
}
return file;
@@ -123,11 +124,7 @@ public class InlineCodegenUtil {
return PackageClassUtils.getPackageClassFqName(getFqName(containerDescriptor).toSafe());
}
if (containerDescriptor instanceof ClassDescriptor) {
ClassKind classKind = ((ClassDescriptor) containerDescriptor).getKind();
if (classKind == ClassKind.CLASS_OBJECT || classKind == ClassKind.ENUM_ENTRY) {
return getContainerFqName(containerDescriptor.getContainingDeclaration());
}
return getFqName(containerDescriptor).toSafe();
return DeserializedResolverUtils.kotlinFqNameToJavaFqName(getFqName(containerDescriptor));
}
return null;
}
@@ -137,9 +134,8 @@ public class InlineCodegenUtil {
}
private static String getInlineName(@NotNull CodegenContext codegenContext, @NotNull DeclarationDescriptor currentDescriptor, @NotNull JetTypeMapper typeMapper) {
PsiFile file;
if (currentDescriptor instanceof PackageFragmentDescriptor) {
file = getContainingFile(codegenContext, typeMapper);
PsiFile file = getContainingFile(codegenContext, typeMapper);
Type packagePartType;
if (file == null) {
@@ -158,7 +154,7 @@ public class InlineCodegenUtil {
throw new RuntimeException("Couldn't find declaration for " + contextDescriptor.getContainingDeclaration().getName() + "." + contextDescriptor.getName() );
}
return packagePartType.getInternalName().replace('.', '/');
return packagePartType.getInternalName();
}
else if (currentDescriptor instanceof ClassifierDescriptor) {
Type type = typeMapper.mapType((ClassifierDescriptor) currentDescriptor);
@@ -172,6 +168,7 @@ public class InlineCodegenUtil {
}
}
//TODO: add suffix for special case
String suffix = currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString();
//noinspection ConstantConditions
@@ -192,15 +189,23 @@ public class InlineCodegenUtil {
public static boolean isInvokeOnLambda(String owner, String name) {
return INVOKE.equals(name) && /*TODO: check type*/owner.contains("Function");
}
public static boolean isLambdaConstructorCall(@NotNull String internalName, @NotNull String name) {
if (!"<init>".equals(name)) {
if (!INVOKE.equals(name)) {
return false;
}
return isLambdaClass(internalName);
for (String prefix : Arrays.asList("jet/Function", "jet/ExtensionFunction")) {
if (owner.startsWith(prefix)) {
String suffix = owner.substring(prefix.length());
if (isInteger(suffix)) {
return true;
}
}
}
return false;
}
public static boolean isLambdaConstructorCall(@NotNull String internalName, @NotNull String methodName) {
return "<init>".equals(methodName) && isLambdaClass(internalName);
}
public static boolean isLambdaClass(String internalName) {
@@ -212,10 +217,7 @@ public class InlineCodegenUtil {
}
String suffix = shortName.substring(index + 1);
for (char c : suffix.toCharArray()) {
if (!Character.isDigit(c)) return false;
}
return true;
return isInteger(suffix);
}
@NotNull
@@ -224,19 +226,10 @@ public class InlineCodegenUtil {
return index < 0 ? internalName : internalName.substring(index + 1);
}
public static boolean isInitCallOfFunction(String owner, String name) {
return "<init>".equals(name);
}
@Nullable
public static PsiFile getContainingFile(CodegenContext codegenContext, JetTypeMapper typeMapper) {
DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor();
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(typeMapper.getBindingContext(), contextDescriptor);
if (psiElement == null) {
//in case of synthetic
psiElement = BindingContextUtils.descriptorToDeclaration(typeMapper.getBindingContext(), contextDescriptor);
}
if (psiElement != null) {
return psiElement.getContainingFile();
}
@@ -247,4 +240,18 @@ public class InlineCodegenUtil {
public static MaxCalcNode wrapWithMaxLocalCalc(@NotNull MethodNode methodNode) {
return new MaxCalcNode(methodNode);
}
private static boolean isInteger(@NotNull String string) {
if (string.isEmpty()) {
return false;
}
for (int i = 0; i < string.length(); i++) {
if (!Character.isDigit(string.charAt(i))) {
return false;
}
}
return true;
}
}
@@ -25,7 +25,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class InliningInfo {
public class InliningContext {
public final Map<Integer, LambdaInfo> expresssionMap;
@@ -45,7 +45,7 @@ public class InliningInfo {
public final Map<String, String> typeMapping;
public InliningInfo(
public InliningContext(
Map<Integer, LambdaInfo> map,
List<InvokeCall> accesses,
List<ConstructorInvocation> invocation,
@@ -67,14 +67,14 @@ public class InliningInfo {
this.typeMapping = typeMapping;
}
public InliningInfo subInline(NameGenerator generator) {
public InliningContext subInline(NameGenerator generator) {
return subInline(generator, Collections.<String, String>emptyMap());
}
public InliningInfo subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
HashMap<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
newTypeMappings.putAll(additionalTypeMappings);
return new InliningInfo(expresssionMap, invokeCalls, constructorInvocation, remapper, state, generator, startContext, call,
return new InliningContext(expresssionMap, invokeCalls, constructorInvocation, remapper, state, generator, startContext, call,
newTypeMappings);
}
}
@@ -55,7 +55,7 @@ public class LambdaTransformer {
private final MethodNode bridge;
private final InliningInfo info;
private final InliningContext info;
private final Type oldLambdaType;
@@ -67,7 +67,7 @@ public class LambdaTransformer {
private String[] interfaces;
private final boolean isSameModule;
public LambdaTransformer(String lambdaInternalName, InliningInfo info, boolean isSameModule, Type newLambdaType) {
public LambdaTransformer(String lambdaInternalName, InliningContext info, boolean isSameModule, Type newLambdaType) {
this.isSameModule = isSameModule;
this.state = info.state;
this.typeMapper = state.getTypeMapper();
@@ -124,7 +124,8 @@ public class LambdaTransformer {
Parameters parameters = getLambdaParameters(builder, invocation);
MethodVisitor invokeVisitor = newMethod(classBuilder, invoke);
InlineFieldRemapper remapper = new InlineFieldRemapper(oldLambdaType.getInternalName(), newLambdaType.getInternalName(), parameters, invocation.getCapturedLambdasToInline());
RegeneratedLambdaFieldRemapper
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);
@@ -177,7 +178,7 @@ public class LambdaTransformer {
private ClassBuilder createClassBuilder() {
return new RemappingClassBuilder(state.getFactory().forLambdaInlining(newLambdaType, info.call.getCallElement().getContainingFile()),
new TypeRemapper(info.typeMapping, isSameModule));
new TypeRemapper(info.typeMapping));
}
private static MethodVisitor newMethod(ClassBuilder builder, MethodNode original) {
@@ -196,7 +197,7 @@ public class LambdaTransformer {
AbstractInsnNode cur = constructor.instructions.getFirst();
cur = cur.getNext(); //skip super call
List<LambdaInfo> additionalCaptured = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
List<LambdaInfo> capturedLambdas = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
while (cur != null) {
if (cur.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fieldNode = (FieldInsnNode) cur;
@@ -208,7 +209,7 @@ public class LambdaTransformer {
LambdaInfo lambdaInfo = indexToLambda.get(varIndex);
if (lambdaInfo != null) {
info.setLambda(lambdaInfo);
additionalCaptured.add(lambdaInfo);
capturedLambdas.add(lambdaInfo);
}
}
cur = cur.getNext();
@@ -218,7 +219,7 @@ public class LambdaTransformer {
//TODO: some of such parameters could be skipped - we should perform additional analysis
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> allRecapturedParameters = new ArrayList<CapturedParamInfo>();
for (LambdaInfo info : additionalCaptured) {
for (LambdaInfo info : capturedLambdas) {
for (CapturedParamInfo var : info.getCapturedVars()) {
CapturedParamInfo recapturedParamInfo = builder.addCapturedParam(getNewFieldName(var.getFieldName()), var.getType(), true, var);
recapturedParamInfo.setRecapturedFrom(info);
@@ -30,8 +30,7 @@ public class MaxCalcNode extends MethodVisitor {
private final MethodNode node;
public MaxCalcNode(MethodNode node)
{
public MaxCalcNode(MethodNode node) {
super(Opcodes.ASM4, node);
this.node = node;
int paramsSize = (node.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
@@ -28,7 +28,7 @@ public class MethodInliner {
private final Parameters parameters;
private final InliningInfo parent;
private final InliningContext parent;
@Nullable
private final Type lambdaType;
@@ -56,7 +56,7 @@ public class MethodInliner {
public MethodInliner(
@NotNull MethodNode node,
@NotNull Parameters parameters,
@NotNull InliningInfo parent,
@NotNull InliningContext parent,
@Nullable Type lambdaType,
LambdaFieldRemapper lambdaFieldRemapper,
boolean isSameModule
@@ -109,7 +109,7 @@ public class MethodInliner {
final Iterator<ConstructorInvocation> iterator = constructorInvocations.iterator();
RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode,
new TypeRemapper(currentTypeMapping, isSameModule));
new TypeRemapper(currentTypeMapping));
InlineAdapter inliner = new InlineAdapter(remappingMethodAdapter, parameters.totalSize()) {
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//All parameters with gaps
public class Parameters implements Iterable<ParameterInfo> {
private final List<ParameterInfo> real;
@@ -60,7 +61,7 @@ public class Parameters implements Iterable<ParameterInfo> {
return Iterables.concat(real, captured).iterator();
}
public static List<CapturedParamInfo> addStubs(List<CapturedParamInfo> capturedParams, int realSize) {
public static List<CapturedParamInfo> shiftAndAddStubs(List<CapturedParamInfo> capturedParams, int realSize) {
List<CapturedParamInfo> result = new ArrayList<CapturedParamInfo>();
for (CapturedParamInfo capturedParamInfo : capturedParams) {
CapturedParamInfo newInfo = capturedParamInfo.newIndex(result.size() + realSize);
@@ -51,13 +51,6 @@ public class ParametersBuilder {
original != null ? original.getIndex() : -1));
}
//public CapturedParamInfo addAdditionalCapturedParam(String fieldName, Type type, boolean skipped, @Nullable ParameterInfo original) {
// CapturedParamInfo capturedParamInfo =
// new CapturedParamInfo(fieldName, type, skipped, original != null ? original.getIndex() : -1, nextCaptured);
// additionalCapturedParams.add(capturedParamInfo);
// return capturedParamInfo;
//}
private void addParameter(ParameterInfo info) {
params.add(info);
nextIndex += info.getType().getSize();
@@ -82,7 +75,7 @@ public class ParametersBuilder {
}
public List<CapturedParamInfo> buildCapturedWithStubs() {
return Parameters.addStubs(buildCaptured(), nextIndex);
return Parameters.shiftAndAddStubs(buildCaptured(), nextIndex);
}
public Parameters buildParameters() {
@@ -27,7 +27,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
public class InlineFieldRemapper extends LambdaFieldRemapper {
public class RegeneratedLambdaFieldRemapper extends LambdaFieldRemapper {
private final String oldOwnerType;
@@ -37,7 +37,12 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
private final Map<String, LambdaInfo> recapturedLambdas;
public InlineFieldRemapper(String oldOwnerType, String newOwnerType, Parameters parameters, Map<String, LambdaInfo> recapturedLambdas) {
public RegeneratedLambdaFieldRemapper(
String oldOwnerType,
String newOwnerType,
Parameters parameters,
Map<String, LambdaInfo> recapturedLambdas
) {
this.oldOwnerType = oldOwnerType;
this.newOwnerType = newOwnerType;
this.parameters = parameters;
@@ -61,6 +66,7 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
String descriptor = Type.getObjectType(newOwnerType).getDescriptor();
//HACK: it would be reverted again to ALOAD 0 later
FieldInsnNode thisStub = new FieldInsnNode(opcode, newOwnerType, "$$$this", descriptor);
node.instructions.insertBefore(loadThis, thisStub);
@@ -96,15 +102,15 @@ public class InlineFieldRemapper extends LambdaFieldRemapper {
return recapturedLambdas.containsKey(owner);
}
@Nullable
@Override
public CapturedParamInfo findField(FieldInsnNode fieldInsnNode, Collection<CapturedParamInfo> captured) {
if (!isRecapturedLambdaType(fieldInsnNode.owner)) {
return super.findField(fieldInsnNode, captured);
} else {
if (isRecapturedLambdaType(fieldInsnNode.owner)) {
LambdaInfo info = recapturedLambdas.get(fieldInsnNode.owner);
return super.findField(fieldInsnNode, info.getCapturedVars());
}
else {
return super.findField(fieldInsnNode, captured);
}
}
}
@@ -1,40 +0,0 @@
/*
* Copyright 2010-2013 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.asm4.MethodVisitor;
import org.jetbrains.asm4.commons.InstructionAdapter;
public class ShiftAdapter extends InstructionAdapter {
private final int shift;
public ShiftAdapter(MethodVisitor mv, int shift) {
super(mv);
this.shift = shift;
}
@Override
public void visitIincInsn(int var, int increment) {
super.visitIincInsn(var + shift, increment);
}
@Override
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var + shift);
}
}
@@ -26,12 +26,9 @@ 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) {
public TypeRemapper(@NotNull Map<String, String> typeMapping) {
this.typeMapping = typeMapping;
this.isSameModule = isSameModule;
}
@Override
@@ -41,13 +38,6 @@ public class TypeRemapper extends Remapper {
return newType;
}
/*if (!isSameModule) {
int indexOfMinus = type.indexOf("-");
if (indexOfMinus > 0) {
//type.substring(0, indexOfMinus)
}
}*/
return type;
}
}