diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 41681950920..0c2e8326a60 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -35,7 +35,9 @@ import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapperMode; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.java.JvmAbi; @@ -49,7 +51,8 @@ import java.util.List; import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.codegen.AsmUtil.*; -import static org.jetbrains.jet.codegen.CodegenUtil.*; +import static org.jetbrains.jet.codegen.CodegenUtil.getInternalClassName; +import static org.jetbrains.jet.codegen.CodegenUtil.isConst; import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; @@ -156,7 +159,7 @@ public class ClosureCodegen extends GenerationStateAware { CodegenContext closureContext = context.intoClosure(funDescriptor, expressionCodegen); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(interfaceFunctionName, funDescriptor); - fc.generateMethod(body, jvmMethodSignature, false, null, funDescriptor); + fc.generateMethod(body, jvmMethodSignature, false, null, funDescriptor, new FunctionGenerationStrategy.Default(state, body)); assert closureContext.closure != null; return closureContext.closure.getCaptureThis(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 21e9db03e59..619c450dc9b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -37,7 +37,7 @@ import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapperMode; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.JvmAbi; @@ -67,8 +67,8 @@ public class FunctionCodegen extends GenerationStateAware { this.v = v; } - public void gen(JetNamedFunction f) { - SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f); + public void gen(@NotNull JetNamedFunction function) { + SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, function); assert functionDescriptor != null; OwnerKind kind = owner.getContextKind(); @@ -80,46 +80,29 @@ public class FunctionCodegen extends GenerationStateAware { isCallInsideSameModuleAsDeclared(functionDescriptor, owner), kind).getSignature(); - if (kind != OwnerKind.TRAIT_IMPL || hasBodyExpression(f)) { + if (kind != OwnerKind.TRAIT_IMPL || function.getBodyExpression() != null) { boolean needJetAnnotations = kind != OwnerKind.TRAIT_IMPL; - generateMethod(f, method, needJetAnnotations, null, functionDescriptor); + generateMethod(function, method, needJetAnnotations, null, functionDescriptor, + new FunctionGenerationStrategy.Default(state, function)); } generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), state, v, method.getAsmMethod(), functionDescriptor, kind, DefaultParameterValueLoader.DEFAULT); } - public void generateMethod( - @NotNull JetDeclaration declaration, + @Nullable PsiElement origin, @NotNull JvmMethodSignature jvmSignature, boolean needJetAnnotations, @Nullable String propertyTypeSignature, - @NotNull FunctionDescriptor functionDescriptor - ) { - assert declaration instanceof JetDeclarationWithBody || declaration instanceof JetProperty || declaration instanceof JetParameter; - - checkMustGenerateCode(functionDescriptor); - - generateMethodHeaderAndBody(declaration, jvmSignature, needJetAnnotations, propertyTypeSignature, functionDescriptor); - - if (state.getClassBuilderMode() == ClassBuilderMode.FULL && !isAbstract(functionDescriptor, owner.getContextKind())) { - generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor); - } - } - - private void generateMethodHeaderAndBody( - @NotNull JetDeclaration declaration, - @NotNull JvmMethodSignature jvmSignature, - boolean needJetAnnotations, - @Nullable String propertyTypeSignature, - @NotNull FunctionDescriptor functionDescriptor + @NotNull FunctionDescriptor functionDescriptor, + @NotNull FunctionGenerationStrategy strategy ) { MethodContext context = owner.intoFunction(functionDescriptor); Method asmMethod = jvmSignature.getAsmMethod(); - MethodVisitor mv = v.newMethod(declaration, + MethodVisitor mv = v.newMethod(origin, getMethodAsmFlags(functionDescriptor, context.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), @@ -140,14 +123,16 @@ public class FunctionCodegen extends GenerationStateAware { return; } - MethodInfo info = generateMethodBody(mv, declaration, functionDescriptor, context, asmMethod); + MethodInfo info = generateMethodBody(mv, functionDescriptor, context, jvmSignature, strategy); info.localVariableNames.addAll(getParameterNamesAsStrings(functionDescriptor)); Type thisType = getThisTypeForFunction(functionDescriptor, context); generateLocalVariableTable(typeMapper, mv, functionDescriptor, thisType, info); - endVisit(mv, null, declaration); + endVisit(mv, null, origin); + + generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor); } @Nullable @@ -167,10 +152,10 @@ public class FunctionCodegen extends GenerationStateAware { @NotNull private MethodInfo generateMethodBody( @NotNull MethodVisitor mv, - @NotNull JetDeclaration funOrProperty, @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext context, - @NotNull Method asmMethod + @NotNull JvmMethodSignature signature, + @NotNull FunctionGenerationStrategy strategy ) { Collection localVariableNames = new ArrayList(); Map labelsForSharedVars = new HashMap(); @@ -182,7 +167,7 @@ public class FunctionCodegen extends GenerationStateAware { OwnerKind kind = context.getContextKind(); if (kind instanceof OwnerKind.StaticDelegateKind) { - generateStaticDelegateMethodBody(mv, asmMethod, (OwnerKind.StaticDelegateKind) kind); + generateStaticDelegateMethodBody(mv, signature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind); } else { FrameMap frameMap = context.prepareFrame(typeMapper); @@ -195,23 +180,7 @@ public class FunctionCodegen extends GenerationStateAware { genNotNullAssertionsForParameters(new InstructionAdapter(mv), state, functionDescriptor, frameMap); - boolean hasBodyExpression = hasBodyExpression(funOrProperty); - if (hasBodyExpression) { - JetDeclarationWithBody fun = (JetDeclarationWithBody) funOrProperty; - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, asmMethod.getReturnType(), context, state); - codegen.returnExpression(fun.getBodyExpression()); - - localVariableNames.addAll(codegen.getLocalVariableNamesForExpression()); - } else { - ///generate default accessor - assert functionDescriptor instanceof PropertyAccessorDescriptor; - PropertyCodegen.generateDefaultAccessor( - (PropertyAccessorDescriptor) functionDescriptor, - new InstructionAdapter(mv), - kind, - typeMapper, - context); - } + strategy.generateBody(mv, signature, context, localVariableNames, frameMap); } Label methodEnd = new Label(); @@ -220,12 +189,6 @@ public class FunctionCodegen extends GenerationStateAware { return new MethodInfo(methodBegin, methodEnd, localVariableNames, labelsForSharedVars); } - private static boolean hasBodyExpression(JetDeclaration funOrProperty) { - return (funOrProperty instanceof JetDeclarationWithBody - && ((JetDeclarationWithBody) funOrProperty).getBodyExpression() != null); - } - - public static class MethodInfo { public final Label beginLabel; public final Label endLabel; @@ -398,7 +361,9 @@ public class FunctionCodegen extends GenerationStateAware { kotlinFlags |= DescriptorKindUtils.kindToFlags(functionDescriptor.getKind()); //noinspection ConstantConditions aw.writeFlags(kotlinFlags); - aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); + if (jvmSignature.getKotlinTypeParameter() != null) { + aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); + } aw.writeReturnType(jvmSignature.getKotlinReturnType()); aw.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java new file mode 100644 index 00000000000..df5d8910d60 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionGenerationStrategy.java @@ -0,0 +1,63 @@ +/* + * 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; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.asm4.MethodVisitor; +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.lang.psi.JetDeclarationWithBody; + +import java.util.Collection; + +public abstract class FunctionGenerationStrategy { + + public abstract void generateBody( + @NotNull MethodVisitor mv, + @NotNull JvmMethodSignature signature, + @NotNull MethodContext context, + @NotNull Collection localVariableNames, + @NotNull FrameMap frameMap + ); + + + 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; + this.declaration = declaration; + } + + @Override + public void generateBody( + @NotNull MethodVisitor mv, + @NotNull JvmMethodSignature signature, + @NotNull MethodContext context, + @NotNull Collection localVariableNames, + @NotNull FrameMap frameMap + ) { + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getAsmMethod().getReturnType(), context, state); + + codegen.returnExpression(declaration.getBodyExpression()); + + localVariableNames.addAll(codegen.getLocalVariableNamesForExpression()); + } + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 9590ceae1b2..a64e5503c37 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -24,6 +24,8 @@ import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; 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.signature.JvmPropertyAccessorSignature; import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.state.GenerationStateAware; @@ -39,6 +41,8 @@ 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.*; @@ -128,11 +132,16 @@ public class PropertyCodegen extends GenerationStateAware { getterDescriptor = getterDescriptor != null ? getterDescriptor : DescriptorResolver.createDefaultGetter(propertyDescriptor); if (kind != OwnerKind.TRAIT_IMPL || !defaultGetter) { + FunctionGenerationStrategy strategy = + defaultGetter + ? new DefaultPropertyAccessorStrategy(getterDescriptor) + : new FunctionGenerationStrategy.Default(state, getter); functionCodegen.generateMethod(getter != null ? getter : p, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), - getterDescriptor); + getterDescriptor, + strategy); } //} } @@ -147,22 +156,47 @@ public class PropertyCodegen extends GenerationStateAware { setterDescriptor = setterDescriptor != null ? setterDescriptor : DescriptorResolver.createDefaultSetter(propertyDescriptor); if (kind != OwnerKind.TRAIT_IMPL || !defaultSetter) { + FunctionGenerationStrategy strategy = + defaultSetter + ? new DefaultPropertyAccessorStrategy(setterDescriptor) + : new FunctionGenerationStrategy.Default(state, setter); functionCodegen.generateMethod(setter != null ? setter : p, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), - setterDescriptor); + setterDescriptor, + strategy); } } } - public static void generateDefaultAccessor( + private class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy { + private final PropertyAccessorDescriptor descriptor; + + public DefaultPropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) { + this.descriptor = descriptor; + } + + @Override + public void generateBody( + @NotNull MethodVisitor mv, + @NotNull JvmMethodSignature signature, + @NotNull MethodContext context, + @NotNull Collection localVariableNames, + @NotNull FrameMap frameMap + ) { + generateDefaultAccessor(descriptor, new InstructionAdapter(mv), typeMapper, context); + } + } + + private static void generateDefaultAccessor( @NotNull PropertyAccessorDescriptor accessorDescriptor, @NotNull InstructionAdapter iv, - @NotNull OwnerKind kind, @NotNull JetTypeMapper typeMapper, - @NotNull CodegenContext context) { + @NotNull CodegenContext context + ) { + OwnerKind kind = context.getContextKind(); PropertyDescriptor propertyDescriptor = accessorDescriptor.getCorrespondingProperty(); Type type = typeMapper.mapType(propertyDescriptor);