PlatformStaticGenerator reworked to use FunctionCodegen.generateMethod()

This commit is contained in:
Andrey Breslav
2014-12-11 19:16:05 +03:00
parent 6916c0f5cc
commit f9fea88749
9 changed files with 95 additions and 57 deletions
@@ -143,19 +143,32 @@ public class CodegenUtil {
// inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
// with traitMember's modality // with traitMember's modality
CallableMemberDescriptor copy = result.putAll(copyFunctions(inheritedMember, traitMember, inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, CallableMemberDescriptor.Kind.DECLARATION, true));
CallableMemberDescriptor.Kind.DECLARATION, true); }
return result;
}
if (traitMember instanceof SimpleFunctionDescriptor) { @NotNull
result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); public static Map<FunctionDescriptor, FunctionDescriptor> copyFunctions(
} @NotNull CallableMemberDescriptor inheritedMember,
else if (traitMember instanceof PropertyDescriptor) { @NotNull CallableMemberDescriptor traitMember,
for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { DeclarationDescriptor newOwner,
for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { Modality modality,
if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind Visibility visibility,
result.put(traitAccessor, inheritedAccessor); CallableMemberDescriptor.Kind kind,
} boolean copyOverrides
) {
CallableMemberDescriptor copy = inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides);
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>(0);
if (traitMember instanceof SimpleFunctionDescriptor) {
result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy);
}
else if (traitMember instanceof PropertyDescriptor) {
for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) {
for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) {
if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind
result.put(traitAccessor, inheritedAccessor);
} }
} }
} }
@@ -173,7 +173,7 @@ public class AsmUtil {
public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) { public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) {
return isStaticKind(kind) || return isStaticKind(kind) ||
JetTypeMapper.isAccessor(functionDescriptor) || JetTypeMapper.isAccessor(functionDescriptor) ||
AnnotationsPackage.isPlatformStaticInObject(functionDescriptor); AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor);
} }
public static boolean isStaticKind(OwnerKind kind) { public static boolean isStaticKind(OwnerKind kind) {
@@ -2419,7 +2419,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (isSingleton) { if (isSingleton) {
if (context.hasThisDescriptor() && if (context.hasThisDescriptor() &&
context.getThisDescriptor().equals(calleeContainingClass) && context.getThisDescriptor().equals(calleeContainingClass) &&
!AnnotationsPackage.isPlatformStaticInObject(context.getContextDescriptor())) { !AnnotationsPackage.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) {
return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
} }
else { else {
@@ -17,12 +17,18 @@
package org.jetbrains.jet.codegen package org.jetbrains.jet.codegen
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.jet.codegen.state.GenerationState import org.jetbrains.jet.codegen.state.GenerationState
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.jet.lang.descriptors.ClassDescriptor import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin
import org.jetbrains.jet.lang.resolve.java.diagnostics.Synthetic import org.jetbrains.jet.lang.resolve.java.diagnostics.Synthetic
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature
import org.jetbrains.jet.codegen.context.MethodContext
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.backend.common.CodegenUtil
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor
class PlatformStaticGenerator( class PlatformStaticGenerator(
val descriptor: FunctionDescriptor, val descriptor: FunctionDescriptor,
@@ -31,39 +37,54 @@ class PlatformStaticGenerator(
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> { ) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) { override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
val typeMapper = state.getTypeMapper() val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor
val asmMethod = typeMapper.mapSignature(descriptor).getAsmMethod() val copies = CodegenUtil.copyFunctions(
val flags = Opcodes.ACC_STATIC or AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION) memberDescriptor,
val methodVisitor = classBuilder.newMethod( memberDescriptor,
Synthetic(declarationOrigin.element, descriptor), declarationOrigin.descriptor?.getContainingDeclaration()?.getContainingDeclaration(),
flags, descriptor.getModality(),
asmMethod.getName()!!, descriptor.getVisibility(),
asmMethod.getDescriptor()!!, CallableMemberDescriptor.Kind.SYNTHESIZED,
typeMapper.mapSignature(descriptor).getGenericsSignature(), false
FunctionCodegen.getThrownExceptions(descriptor, typeMapper)) )
val staticFunctionDescriptor = copies[descriptor]!!
AnnotationCodegen.forMethod(methodVisitor, typeMapper)!!.genAnnotations(descriptor, asmMethod.getReturnType()) val jvmMethodSignature = state.getTypeMapper().mapSignature(staticFunctionDescriptor)
if (state.getClassBuilderMode() == ClassBuilderMode.FULL && flags and Opcodes.ACC_NATIVE == 0) { codegen.functionCodegen.generateMethod(
methodVisitor.visitCode(); Synthetic(declarationOrigin.element, staticFunctionDescriptor),
val iv = InstructionAdapter(methodVisitor) jvmMethodSignature,
val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor staticFunctionDescriptor,
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)!! object: FunctionGenerationStrategy() {
singletonValue.put(singletonValue.type, iv); override fun generateBody(
var index = 0; mv: MethodVisitor,
for (paramType in asmMethod.getArgumentTypes()) { frameMap: FrameMap,
iv.load(index, paramType); signature: JvmMethodSignature,
index += paramType.getSize(); context: MethodContext,
} parentCodegen: MemberCodegen<out JetElement>
) {
val typeMapper = parentCodegen.typeMapper
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod( val iv = InstructionAdapter(mv)
codegen.getContext().accessibleFunctionDescriptor(descriptor), val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor
false, val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
codegen.getContext() singletonValue.put(singletonValue.type, iv);
) var index = 0;
syntheticOrOriginalMethod.invokeWithoutAssertions(iv) val asmMethod = signature.getAsmMethod()
iv.areturn(asmMethod.getReturnType()); for (paramType in asmMethod.getArgumentTypes()) {
methodVisitor.visitEnd(); iv.load(index, paramType);
} index += paramType.getSize();
}
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
codegen.getContext().accessibleFunctionDescriptor(descriptor),
false,
codegen.getContext()
)
syntheticOrOriginalMethod.invokeWithoutAssertions(iv)
iv.areturn(asmMethod.getReturnType());
}
}
)
} }
} }
@@ -480,7 +480,7 @@ public abstract class StackValue {
} }
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) { private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) { if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) {
if (resultReceiver.canHaveSideEffects()) { if (resultReceiver.canHaveSideEffects()) {
return coercion(resultReceiver, Type.VOID_TYPE); return coercion(resultReceiver, Type.VOID_TYPE);
} }
@@ -1414,7 +1414,7 @@ public abstract class StackValue {
return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType()); return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType());
} }
else if (dispatchReceiver != null) { else if (dispatchReceiver != null) {
if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) { if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) {
return Type.VOID_TYPE; return Type.VOID_TYPE;
} }
else { else {
@@ -488,7 +488,7 @@ public class JetTypeMapper {
else { else {
if (isStaticDeclaration(functionDescriptor) || if (isStaticDeclaration(functionDescriptor) ||
isAccessor(functionDescriptor) || isAccessor(functionDescriptor) ||
AnnotationsPackage.isPlatformStaticInObject(functionDescriptor)) { AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
invokeOpcode = INVOKESTATIC; invokeOpcode = INVOKESTATIC;
} }
else if (isInterface) { else if (isInterface) {
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve.annotations package org.jetbrains.jet.lang.resolve.annotations
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.CallableDescriptor import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.DescriptorUtils
@@ -36,18 +35,18 @@ public fun DeclarationDescriptor.hasIntrinsicAnnotation(): Boolean {
return getAnnotations().findAnnotation(FqName("kotlin.jvm.internal.Intrinsic")) != null return getAnnotations().findAnnotation(FqName("kotlin.jvm.internal.Intrinsic")) != null
} }
public fun CallableDescriptor.isPlatformStaticInObject(): Boolean = public fun CallableDescriptor.isPlatformStaticInObjectOrClass(): Boolean =
isPlatformStaticIn(ClassKind.OBJECT) isPlatformStaticIn(ClassKind.OBJECT, ClassKind.CLASS)
public fun CallableDescriptor.isPlatformStaticInClassObject(): Boolean = public fun CallableDescriptor.isPlatformStaticInClassObject(): Boolean =
isPlatformStaticIn(ClassKind.CLASS_OBJECT) isPlatformStaticIn(ClassKind.CLASS_OBJECT)
private fun CallableDescriptor.isPlatformStaticIn(kind: ClassKind): Boolean = private fun CallableDescriptor.isPlatformStaticIn(vararg kinds: ClassKind): Boolean =
when (this) { when (this) {
is PropertyAccessorDescriptor -> { is PropertyAccessorDescriptor -> {
val propertyDescriptor = getCorrespondingProperty() val propertyDescriptor = getCorrespondingProperty()
DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), kind) && kinds.any { DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), it) } &&
(hasPlatformStaticAnnotation() || propertyDescriptor.hasPlatformStaticAnnotation()) (hasPlatformStaticAnnotation() || propertyDescriptor.hasPlatformStaticAnnotation())
} }
else -> DescriptorUtils.isKindOf(getContainingDeclaration(), kind) && hasPlatformStaticAnnotation() else -> kinds.any { DescriptorUtils.isKindOf(getContainingDeclaration(), it) } && hasPlatformStaticAnnotation()
} }
@@ -17,5 +17,10 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
public interface SourceElement { public interface SourceElement {
SourceElement NO_SOURCE = new SourceElement() { }; SourceElement NO_SOURCE = new SourceElement() {
@Override
public String toString() {
return "NO_SOURCE";
}
};
} }
@@ -92,7 +92,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme
getAnnotations(), getAnnotations(),
getName(), getName(),
kind, kind,
SourceElement.NO_SOURCE getSource()
); );
} }