Primary constructor generation via FunctionCodegen Strategy, local variable table generation via JvmMethodSignature and FunctionDescriptor

This commit is contained in:
Mikhael Bogdanov
2013-04-26 13:06:18 +04:00
parent 5fe6e32882
commit 83d8930c02
8 changed files with 239 additions and 213 deletions
@@ -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) {
@@ -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);
@@ -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<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
List<ValueParameterDescriptor> paramDescrs = descriptor != null
? descriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
enter(parameter, explicitArgTypes.get(i));
}
}
public int getOuterThisIndex() {
@@ -1249,7 +1249,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<? extends ValueArgument> 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<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
@NotNull
@@ -2389,9 +2393,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> implem
return new ExpressionReceiver(receiverExpression, receiver.getType());
}
@Override
public boolean needsLocalVariableTable() {
return false;
}
}
);
@@ -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<String> localVariableNames,
@NotNull Map<Name, Label> labelsForSharedVars
@NotNull Map<Name, Label> labelsForSharedVars,
@NotNull OwnerKind ownerKind
) {
// TODO: specify signatures
Iterator<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator();
List<JvmMethodParameterSignature> 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<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator();
List<JvmMethodParameterSignature> 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<ValueParameterDescriptor> 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);
@@ -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<T extends CallableDescriptor> {
private final Collection<String> localVariableNames = new ArrayList<String>();
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<CallableDescriptor> {
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<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
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);
}
@@ -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<ConstructorDescriptor>(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<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
? constructorDescriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>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 &&
@@ -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();
}