diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index f2c7a67ec65..2601e3608ba 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -147,7 +147,7 @@ public class AsmUtil { int flags = getCommonCallableFlags(functionDescriptor); - if (functionDescriptor.getModality() == Modality.FINAL) { + if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) { DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); if (!(containingDeclaration instanceof ClassDescriptor) || ((ClassDescriptor) containingDeclaration).getKind() != ClassKind.TRAIT) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index abb55139874..d53c617333b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -122,7 +122,7 @@ public class ClosureCodegen extends GenerationStateAware { JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(interfaceFunction.getName(), funDescriptor); FunctionCodegen fc = new FunctionCodegen(context, cv, state); - fc.generateMethod(fun, jvmMethodSignature, false, null, funDescriptor, strategy); + fc.generateMethod(fun, jvmMethodSignature, false, funDescriptor, strategy); this.constructor = generateConstructor(cv); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java index f9392728983..1a28ba69649 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java @@ -17,13 +17,10 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.Nullable; -import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind; import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; -import java.util.Collections; import java.util.List; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; @@ -48,15 +45,6 @@ public class ConstructorFrameMap extends FrameMap { } } } - - List explicitArgTypes = callableMethod.getValueParameterTypes(); - List paramDescrs = descriptor != null - ? descriptor.getValueParameters() - : Collections.emptyList(); - for (int i = 0; i < paramDescrs.size(); i++) { - ValueParameterDescriptor parameter = paramDescrs.get(i); - enter(parameter, explicitArgTypes.get(i)); - } } public int getOuterThisIndex() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 1e5a8a383b8..9ef874313eb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1249,7 +1249,7 @@ public class ExpressionCodegen extends JetVisitor implem JvmClassName closureSuperClass = samInterfaceClass == null ? getFunctionImplClassName(descriptor) : JvmClassName.byType(OBJECT_TYPE); ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context, - this, new FunctionGenerationStrategy.Default(state, declaration)); + this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration)); closureCodegen.gen(); @@ -2335,14 +2335,23 @@ public class ExpressionCodegen extends JetVisitor implem JvmClassName closureSuperClass = JvmClassName.byType(typeMapper.mapType(kFunctionImpl)); ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context, this, - new FunctionGenerationStrategy() { + new FunctionGenerationStrategy.CodegenBased(state, functionDescriptor) { + @Override - public void generateBody( - @NotNull MethodVisitor mv, - @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + public ExpressionCodegen initializeExpressionCodegen( + JvmMethodSignature signature, MethodContext context, MethodVisitor mv, + Type returnType ) { + FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); + JetType returnJetType = referencedFunction.getReturnType(); + assert returnJetType != null : "Return type can't be null: " + referencedFunction; + + return super.initializeExpressionCodegen(signature, context, + mv, typeMapper.mapReturnType(returnJetType)); + } + + @Override + public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) { /* Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invokation of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of @@ -2352,17 +2361,12 @@ public class ExpressionCodegen extends JetVisitor implem */ FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); - JetType returnJetType = referencedFunction.getReturnType(); - assert returnJetType != null : "Return type can't be null: " + referencedFunction; - Type returnType = typeMapper.mapReturnType(returnJetType); JetCallExpression fakeExpression = constructFakeFunctionCall(referencedFunction); final List fakeArguments = fakeExpression.getValueArguments(); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context, state); - final ReceiverValue receiverValue = computeAndSaveReceiver(signature, codegen); - computeAndSaveArguments(frameMap, fakeArguments, codegen); + computeAndSaveArguments(codegen.myFrameMap, fakeArguments, codegen); ResolvedCall fakeResolvedCall = new DelegatingResolvedCall(resolvedCall) { @NotNull @@ -2389,9 +2393,10 @@ public class ExpressionCodegen extends JetVisitor implem }; StackValue result; + Type returnType = codegen.returnType; if (referencedFunction instanceof ConstructorDescriptor) { if (returnType.getSort() == Type.ARRAY) { - codegen.generateNewArray(fakeExpression, returnJetType); + codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType()); result = StackValue.onStack(returnType); } else { @@ -2403,7 +2408,7 @@ public class ExpressionCodegen extends JetVisitor implem result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall); } - InstructionAdapter v = new InstructionAdapter(mv); + InstructionAdapter v = codegen.v; result.put(returnType, v); v.areturn(returnType); } @@ -2463,11 +2468,6 @@ public class ExpressionCodegen extends JetVisitor implem return new ExpressionReceiver(receiverExpression, receiver.getType()); } - - @Override - public boolean needsLocalVariableTable() { - return false; - } } ); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 5831bc5c106..280533b870f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -20,6 +20,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.asm4.AnnotationVisitor; import org.jetbrains.asm4.Label; import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; @@ -28,8 +29,10 @@ import org.jetbrains.asm4.commons.Method; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.MethodContext; +import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind; import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; +import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature; import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter; import org.jetbrains.jet.codegen.state.GenerationState; @@ -81,8 +84,8 @@ public class FunctionCodegen extends GenerationStateAware { if (kind != OwnerKind.TRAIT_IMPL || function.getBodyExpression() != null) { boolean needJetAnnotations = kind != OwnerKind.TRAIT_IMPL; - generateMethod(function, method, needJetAnnotations, null, functionDescriptor, - new FunctionGenerationStrategy.Default(state, function)); + generateMethod(function, method, needJetAnnotations, functionDescriptor, + new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function)); } generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), state, v, method.getAsmMethod(), functionDescriptor, kind, @@ -93,16 +96,25 @@ public class FunctionCodegen extends GenerationStateAware { @Nullable PsiElement origin, @NotNull JvmMethodSignature jvmSignature, boolean needJetAnnotations, - @Nullable String propertyTypeSignature, @NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionGenerationStrategy strategy ) { - MethodContext context = owner.intoFunction(functionDescriptor); + generateMethod(origin, jvmSignature, needJetAnnotations, functionDescriptor, owner.intoFunction(functionDescriptor), strategy); + } + + public void generateMethod( + @Nullable PsiElement origin, + @NotNull JvmMethodSignature jvmSignature, + boolean needJetAnnotations, + @NotNull FunctionDescriptor functionDescriptor, + @NotNull MethodContext methodContext, + @NotNull FunctionGenerationStrategy strategy + ) { Method asmMethod = jvmSignature.getAsmMethod(); MethodVisitor mv = v.newMethod(origin, - getMethodAsmFlags(functionDescriptor, context.getContextKind()), + getMethodAsmFlags(functionDescriptor, methodContext.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), jvmSignature.getGenericsSignature(), @@ -112,17 +124,17 @@ public class FunctionCodegen extends GenerationStateAware { if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) return; if (needJetAnnotations) { - genJetAnnotations(mv, functionDescriptor, propertyTypeSignature); + genJetAnnotations(mv, functionDescriptor, jvmSignature); } - if (isAbstract(functionDescriptor, context.getContextKind())) return; + if (isAbstract(functionDescriptor, methodContext.getContextKind())) return; if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { genStubCode(mv); return; } - generateMethodBody(mv, functionDescriptor, context, jvmSignature, strategy); + generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy); endVisit(mv, null, origin); @@ -132,7 +144,10 @@ public class FunctionCodegen extends GenerationStateAware { @Nullable private Type getThisTypeForFunction(@NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext context) { ReceiverParameterDescriptor expectedThisObject = functionDescriptor.getExpectedThisObject(); - if (expectedThisObject != null) { + if (functionDescriptor instanceof ConstructorDescriptor) { + return typeMapper.mapType(functionDescriptor.getReturnType()); + } + else if (expectedThisObject != null) { return typeMapper.mapType(expectedThisObject.getType()); } else if (isFunctionLiteral(functionDescriptor) || isLocalNamedFun(functionDescriptor)) { @@ -164,7 +179,7 @@ public class FunctionCodegen extends GenerationStateAware { generateStaticDelegateMethodBody(mv, signature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind); } else { - FrameMap frameMap = context.prepareFrame(typeMapper); + FrameMap frameMap = strategy.getFrameMap(typeMapper, context); for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) { frameMap.enter(parameter, typeMapper.mapType(parameter)); @@ -174,7 +189,7 @@ public class FunctionCodegen extends GenerationStateAware { genNotNullAssertionsForParameters(new InstructionAdapter(mv), state, functionDescriptor, frameMap); - strategy.generateBody(mv, signature, context, frameMap); + strategy.generateBody(mv, signature, context); localVariableNames.addAll(strategy.getLocalVariableNames()); } @@ -182,10 +197,9 @@ public class FunctionCodegen extends GenerationStateAware { Label methodEnd = new Label(); mv.visitLabel(methodEnd); - if (strategy.needsLocalVariableTable()) { - Type thisType = getThisTypeForFunction(functionDescriptor, context); - generateLocalVariableTable(mv, functionDescriptor, thisType, methodBegin, methodEnd, localVariableNames, labelsForSharedVars); - } + + Type thisType = getThisTypeForFunction(functionDescriptor, context); + generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, localVariableNames, labelsForSharedVars, kind); } @NotNull @@ -200,47 +214,59 @@ public class FunctionCodegen extends GenerationStateAware { private void generateLocalVariableTable( @NotNull MethodVisitor mv, + @NotNull JvmMethodSignature jvmMethodSignature, @NotNull FunctionDescriptor functionDescriptor, @Nullable Type thisType, @NotNull Label methodBegin, @NotNull Label methodEnd, @NotNull Collection localVariableNames, - @NotNull Map labelsForSharedVars + @NotNull Map labelsForSharedVars, + @NotNull OwnerKind ownerKind ) { - // TODO: specify signatures + Iterator valueParameters = functionDescriptor.getValueParameters().iterator(); + List params = jvmMethodSignature.getKotlinParameterTypes(); + int shift = 0; - int k = 0; - - if (thisType != null) { - mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, k++); + boolean isStatic = isStatic(ownerKind) || ownerKind == OwnerKind.TRAIT_IMPL; + if (!isStatic) { + //add this + if (thisType != null) { + mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift); + } else { + //sometimes there is no thisType for callable reference + } + shift++; } - ReceiverParameterDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); - if (receiverParameter != null) { - Type type = typeMapper.mapType(receiverParameter.getType()); - mv.visitLocalVariable(JvmAbi.RECEIVER_PARAMETER, type.getDescriptor(), null, methodBegin, methodEnd, k); - k += type.getSize(); - } + for (int i = 0; i < params.size(); i++) { + JvmMethodParameterSignature param = params.get(i); + JvmMethodParameterKind kind = param.getKind(); + String parameterName = "$" + param.getKind().name().toLowerCase(); - for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) { - Type type = typeMapper.mapType(parameter); - - Label divideLabel = labelsForSharedVars.get(parameter.getName()); - String parameterName = parameter.getName().getName(); - if (divideLabel != null) { - mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k); - - String nameForSharedVar = createTmpVariableName(localVariableNames); - localVariableNames.add(nameForSharedVar); - - Type sharedVarType = typeMapper.getSharedVarType(parameter); - mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k); - k += Math.max(type.getSize(), sharedVarType.getSize()); + if (needIndexForVar(kind)) { + parameterName = parameterName + "$" + i; } - else { - mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, k); - k += type.getSize(); + + Type type = param.getAsmType(); + if (kind == JvmMethodParameterKind.VALUE) { + ValueParameterDescriptor parameter = valueParameters.next(); + Label divideLabel = labelsForSharedVars.get(parameter.getName()); + parameterName = parameter.getName().getName(); + if (divideLabel != null) { + mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, shift); + + String nameForSharedVar = createTmpVariableName(localVariableNames); + localVariableNames.add(nameForSharedVar); + + Type sharedVarType = typeMapper.getSharedVarType(parameter); + mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, shift); + shift += Math.max(type.getSize(), sharedVarType.getSize()); + continue; + } } + + mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift); + shift += type.getSize(); } } @@ -304,18 +330,16 @@ public class FunctionCodegen extends GenerationStateAware { private void genJetAnnotations( @NotNull MethodVisitor mv, @NotNull FunctionDescriptor functionDescriptor, - @Nullable String propertyTypeSignature + @NotNull JvmMethodSignature jvmSignature ) { - JvmMethodSignature jvmSignature = - typeMapper.mapToCallableMethod(functionDescriptor, false, false, false, OwnerKind.IMPLEMENTATION).getSignature(); if (functionDescriptor instanceof PropertyAccessorDescriptor) { - assert propertyTypeSignature != null; - PropertyCodegen.generateJetPropertyAnnotation(mv, propertyTypeSignature, jvmSignature.getKotlinTypeParameter(), + assert jvmSignature instanceof JvmPropertyAccessorSignature; + PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature, ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility()); } else if (functionDescriptor instanceof SimpleFunctionDescriptor) { - if (propertyTypeSignature != null) { + if (jvmSignature instanceof JvmPropertyAccessorSignature) { throw new IllegalStateException(); } Modality modality = functionDescriptor.getModality(); @@ -334,36 +358,57 @@ public class FunctionCodegen extends GenerationStateAware { aw.writeReturnType(jvmSignature.getKotlinReturnType()); aw.visitEnd(); } + else if (functionDescriptor instanceof ConstructorDescriptor) { + AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true); + + int flagsValue = getFlagsForVisibility(functionDescriptor.getVisibility()); + if (JvmStdlibNames.FLAGS_DEFAULT_VALUE != flagsValue) { + jetConstructorVisitor.visit(JvmStdlibNames.JET_FLAGS_FIELD, flagsValue); + } + + jetConstructorVisitor.visitEnd(); + } else { throw new IllegalStateException(); } + Iterator valueParameters = functionDescriptor.getValueParameters().iterator(); List kotlinParameterTypes = jvmSignature.getKotlinParameterTypes(); + assert kotlinParameterTypes != null; - int start = 0; - ReceiverParameterDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); - if (receiverParameter != null) { - JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, start++); - av.writeName(JvmAbi.RECEIVER_PARAMETER); - av.writeReceiver(); - av.writeType(kotlinParameterTypes.get(0).getKotlinSignature()); - av.visitEnd(); - } + for (int i = 0; i < kotlinParameterTypes.size(); i++) { + JvmMethodParameterSignature param = kotlinParameterTypes.get(i); + JvmMethodParameterKind kind = param.getKind(); + String parameterName = "$" + param.getKind().name().toLowerCase(); + + ValueParameterDescriptor parameterDescriptor = null; + if (kind == JvmMethodParameterKind.VALUE) { + parameterDescriptor = valueParameters.next(); + parameterName = parameterDescriptor.getName().getName(); + } else if (needIndexForVar(kind)) { + parameterName = parameterName + "$" + i; + } - List valueParameters = functionDescriptor.getValueParameters(); - for (int i = 0; i != valueParameters.size(); ++i) { - ValueParameterDescriptor parameterDescriptor = valueParameters.get(i); AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameterDescriptor); - JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start); - av.writeName(parameterDescriptor.getName().getName()); - av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue()); - av.writeVararg(parameterDescriptor.getVarargElementType() != null); - av.writeType(kotlinParameterTypes.get(i + start).getKotlinSignature()); + JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i); + av.writeName(parameterName); + if (kind == JvmMethodParameterKind.RECEIVER) { + av.writeReceiver(); + } + if (parameterDescriptor != null) { + av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue()); + av.writeVararg(parameterDescriptor.getVarargElementType() != null); + } + av.writeType(param.getKotlinSignature()); av.visitEnd(); } } + private boolean needIndexForVar(JvmMethodParameterKind kind) { + return kind == JvmMethodParameterKind.SHARED_VAR || kind == JvmMethodParameterKind.SUPER_CALL_PARAM; + } + public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) { try { mv.visitMaxs(-1, -1); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java index 67a4aed792f..985c7084d1d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java @@ -18,22 +18,28 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.asm4.MethodVisitor; +import org.jetbrains.asm4.Type; +import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.state.GenerationState; +import org.jetbrains.jet.codegen.state.JetTypeMapper; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import java.util.ArrayList; import java.util.Collection; -public abstract class FunctionGenerationStrategy { +public abstract class FunctionGenerationStrategy { + private final Collection localVariableNames = new ArrayList(); + private FrameMap frameMap; + public abstract void generateBody( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + @NotNull MethodContext context ); protected void addLocalVariableName(@NotNull String name) { @@ -45,31 +51,72 @@ public abstract class FunctionGenerationStrategy { return localVariableNames; } - public boolean needsLocalVariableTable() { - return true; + @NotNull + protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context) { + return context.prepareFrame(typeMapper); } + @NotNull + public FrameMap getFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context) { + if (frameMap == null) { + frameMap = createFrameMap(typeMapper, context); + } + return frameMap; + } + + public static class FunctionDefault extends CodegenBased { - public static class Default extends FunctionGenerationStrategy { - private final GenerationState state; private final JetDeclarationWithBody declaration; - public Default(@NotNull GenerationState state, @NotNull JetDeclarationWithBody declaration) { - this.state = state; + public FunctionDefault( + @NotNull GenerationState state, + @NotNull CallableDescriptor descriptor, + @NotNull JetDeclarationWithBody declaration + ) { + super(state, descriptor); this.declaration = declaration; } + @Override + public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) { + codegen.returnExpression(declaration.getBodyExpression()); + } + } + + public abstract static class CodegenBased extends FunctionGenerationStrategy { + + private final GenerationState state; + protected final T callableDescriptor; + + public CodegenBased(@NotNull GenerationState state, T callableDescriptor) { + this.state = state; + this.callableDescriptor = callableDescriptor; + } + @Override public void generateBody( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + @NotNull MethodContext context ) { - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getAsmMethod().getReturnType(), context, state); + ExpressionCodegen codegen = initializeExpressionCodegen(signature, context, mv, signature.getAsmMethod().getReturnType()); + doGenerateBody(codegen, signature); + generateLocalVarNames(codegen); + } - codegen.returnExpression(declaration.getBodyExpression()); + abstract public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature); + @NotNull + public ExpressionCodegen initializeExpressionCodegen( + JvmMethodSignature signature, + MethodContext context, + MethodVisitor mv, + Type returnType + ) { + return new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context), returnType, context, state); + } + + public void generateLocalVarNames(@NotNull ExpressionCodegen codegen) { for (String name : codegen.getLocalVariableNamesForExpression()) { addLocalVariableName(name); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index d124b0865f0..396e94d4a25 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -681,13 +681,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JvmMethodSignature signature = typeMapper.mapSignature(function); FunctionCodegen fc = new FunctionCodegen(context, v, state); - fc.generateMethod(myClass, signature, true, null, function, new FunctionGenerationStrategy() { + fc.generateMethod(myClass, signature, true, function, new FunctionGenerationStrategy() { @Override public void generateBody( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + @NotNull MethodContext context ) { InstructionAdapter iv = new InstructionAdapter(mv); if (!componentType.equals(Type.VOID_TYPE)) { @@ -706,13 +705,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); FunctionCodegen fc = new FunctionCodegen(context, v, state); - fc.generateMethod(myClass, methodSignature, true, null, function, new FunctionGenerationStrategy() { + fc.generateMethod(myClass, methodSignature, true, function, new FunctionGenerationStrategy() { @Override public void generateBody( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + @NotNull MethodContext context ) { InstructionAdapter iv = new InstructionAdapter(mv); @@ -860,10 +858,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, method.getName(), method.getDescriptor(), null, null); - PropertyGetterDescriptor getter = ((PropertyDescriptor) entry.getValue()).getGetter(); + PropertyGetterDescriptor getter = bridge.getGetter(); assert getter != null; - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), - originalSignature.getJvmMethodSignature().getKotlinTypeParameter(), + PropertyCodegen.generateJetPropertyAnnotation(mv, + originalSignature, original, getter.getVisibility()); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { @@ -897,10 +895,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_STATIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - PropertySetterDescriptor setter = ((PropertyDescriptor) entry.getValue()).getSetter(); + PropertySetterDescriptor setter = bridge.getSetter(); assert setter != null; - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), - originalSignature2.getJvmMethodSignature().getKotlinTypeParameter(), + PropertyCodegen.generateJetPropertyAnnotation(mv, + originalSignature2, original, setter.getVisibility()); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { @@ -967,6 +965,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { throw new IllegalStateException("incorrect kind for primary constructor: " + kind); } + final MutableClosure closure = context.closure; ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); @@ -975,60 +974,49 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { lookupConstructorExpressionsInClosureIfPresent(constructorContext); } - MutableClosure closure = context.closure; - boolean hasCapturedThis = closure != null && closure.getCaptureThis() != null; - - CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure); + final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure); JvmMethodSignature constructorMethod = callableMethod.getSignature(); assert constructorDescriptor != null; - int flags = getConstructorAsmFlags(constructorDescriptor); - MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), - constructorMethod.getGenericsSignature(), null); - if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { - AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true); + FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); - int flagsValue = getFlagsForVisibility(constructorDescriptor.getVisibility()); - if (JvmStdlibNames.FLAGS_DEFAULT_VALUE != flagsValue) { - jetConstructorVisitor.visit(JvmStdlibNames.JET_FLAGS_FIELD, flagsValue); - } + functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext, + new FunctionGenerationStrategy.CodegenBased(state, constructorDescriptor) { - jetConstructorVisitor.visitEnd(); + @NotNull + @Override + protected FrameMap createFrameMap( + @NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context + ) { + return new ConstructorFrameMap(callableMethod, callableDescriptor); + } - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(constructorDescriptor); + @Override + public void doGenerateBody( + ExpressionCodegen codegen, JvmMethodSignature signature + ) { + generatePrimaryConstructorImpl(callableDescriptor, codegen, closure); + } + }); - writeParameterAnnotations(constructorDescriptor, constructorMethod, hasCapturedThis, mv); + FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor, + OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); - if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { - genStubCode(mv); - return; - } - - generatePrimaryConstructorImpl(constructorDescriptor, constructorContext, constructorMethod, callableMethod, closure, mv); - } FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v); } private void generatePrimaryConstructorImpl( ConstructorDescriptor constructorDescriptor, - ConstructorContext constructorContext, - JvmMethodSignature constructorMethod, - CallableMethod callableMethod, - MutableClosure closure, - MethodVisitor mv + ExpressionCodegen codegen, + MutableClosure closure ) { - mv.visitCode(); - List paramDescrs = constructorDescriptor != null ? constructorDescriptor.getValueParameters() : Collections.emptyList(); - ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor); - - InstructionAdapter iv = new InstructionAdapter(mv); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state); + InstructionAdapter iv = codegen.v; JvmClassName classname = JvmClassName.byType(classAsmType); @@ -1039,7 +1027,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { genSuperCallToDelegatorToSuperClass(iv); } else { - generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, frameMap); + generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor); } if (closure != null) { @@ -1068,7 +1056,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { VariableDescriptor descriptor = paramDescrs.get(curParam); Type type = typeMapper.mapType(descriptor); iv.load(0, classAsmType); - iv.load(frameMap.getIndex(descriptor), type); + iv.load(codegen.myFrameMap.getIndex(descriptor), type); iv.putfield(classAsmType.getInternalName(), descriptor.getName().getName(), type.getDescriptor()); } curParam++; @@ -1076,12 +1064,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateInitializers(codegen, iv, myClass.getDeclarations(), bindingContext, state); - mv.visitInsn(RETURN); - FunctionCodegen.endVisit(mv, "constructor", myClass); - - assert constructorDescriptor != null; - FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor, - OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); + iv.visitInsn(RETURN); } private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) { @@ -1113,37 +1096,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private void writeParameterAnnotations( - ConstructorDescriptor constructorDescriptor, - JvmMethodSignature constructorMethod, - boolean hasThis0, - MethodVisitor mv - ) { - if (constructorDescriptor != null) { - int i = 0; - - if (hasThis0) { - i++; - } - - if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) { - i += 2; - } - - for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) { - AnnotationCodegen.forParameter(i, mv, state.getTypeMapper()).genAnnotations(valueParameter); - JetValueParameterAnnotationWriter jetValueParameterAnnotation = - JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i); - jetValueParameterAnnotation.writeName(valueParameter.getName().getName()); - jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue()); - jetValueParameterAnnotation.writeVararg(valueParameter.getVarargElementType() != null); - jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i)); - jetValueParameterAnnotation.visitEnd(); - ++i; - } - } - } - private void genCallToDelegatorByExpressionSpecifier( InstructionAdapter iv, ExpressionCodegen codegen, @@ -1450,8 +1402,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateDelegatorToConstructorCall( InstructionAdapter iv, ExpressionCodegen codegen, - ConstructorDescriptor constructorDescriptor, - ConstructorFrameMap frameMap + ConstructorDescriptor constructorDescriptor ) { ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); @@ -1474,7 +1425,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper); if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { - iv.load(frameMap.getOuterThisIndex(), OBJECT_TYPE); + iv.load(((ConstructorFrameMap)codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE); } if (myClass instanceof JetObjectDeclaration && diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index b4ebeeb434a..1f7acd55558 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -41,8 +41,6 @@ import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; -import java.util.Collection; - import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.codegen.AsmUtil.getDeprecatedAccessFlag; import static org.jetbrains.jet.codegen.CodegenUtil.*; @@ -135,11 +133,10 @@ public class PropertyCodegen extends GenerationStateAware { FunctionGenerationStrategy strategy = defaultGetter ? new DefaultPropertyAccessorStrategy(getterDescriptor) - : new FunctionGenerationStrategy.Default(state, getter); + : new FunctionGenerationStrategy.FunctionDefault(state, getterDescriptor, getter); functionCodegen.generateMethod(getter != null ? getter : p, signature.getJvmMethodSignature(), true, - signature.getPropertyTypeKotlinSignature(), getterDescriptor, strategy); } @@ -159,11 +156,10 @@ public class PropertyCodegen extends GenerationStateAware { FunctionGenerationStrategy strategy = defaultSetter ? new DefaultPropertyAccessorStrategy(setterDescriptor) - : new FunctionGenerationStrategy.Default(state, setter); + : new FunctionGenerationStrategy.FunctionDefault(state, setterDescriptor, setter); functionCodegen.generateMethod(setter != null ? setter : p, signature.getJvmMethodSignature(), true, - signature.getPropertyTypeKotlinSignature(), setterDescriptor, strategy); } @@ -182,8 +178,7 @@ public class PropertyCodegen extends GenerationStateAware { public void generateBody( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature signature, - @NotNull MethodContext context, - @NotNull FrameMap frameMap + @NotNull MethodContext context ) { generateDefaultAccessor(descriptor, new InstructionAdapter(mv), typeMapper, context); } @@ -233,7 +228,7 @@ public class PropertyCodegen extends GenerationStateAware { } public static void generateJetPropertyAnnotation( - MethodVisitor mv, @NotNull String kotlinType, @NotNull String typeParameters, + MethodVisitor mv, @NotNull JvmPropertyAccessorSignature propertyAccessorSignature, @NotNull PropertyDescriptor propertyDescriptor, @NotNull Visibility visibility ) { JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); @@ -245,8 +240,8 @@ public class PropertyCodegen extends GenerationStateAware { : JvmStdlibNames.FLAG_FORCE_OPEN_BIT; } aw.writeFlags(flags | DescriptorKindUtils.kindToFlags(propertyDescriptor.getKind())); - aw.writeTypeParameters(typeParameters); - aw.writePropertyType(kotlinType); + aw.writeTypeParameters(propertyAccessorSignature.getKotlinTypeParameter()); + aw.writePropertyType(propertyAccessorSignature.getPropertyTypeKotlinSignature()); aw.visitEnd(); }