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,10 +143,24 @@ 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;
}
@NotNull
public static Map<FunctionDescriptor, FunctionDescriptor> copyFunctions(
@NotNull CallableMemberDescriptor inheritedMember,
@NotNull CallableMemberDescriptor traitMember,
DeclarationDescriptor newOwner,
Modality modality,
Visibility visibility,
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) { if (traitMember instanceof SimpleFunctionDescriptor) {
result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy);
} }
@@ -159,7 +173,6 @@ public class CodegenUtil {
} }
} }
} }
}
return result; return result;
} }
@@ -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,26 +37,40 @@ 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,
staticFunctionDescriptor,
object: FunctionGenerationStrategy() {
override fun generateBody(
mv: MethodVisitor,
frameMap: FrameMap,
signature: JvmMethodSignature,
context: MethodContext,
parentCodegen: MemberCodegen<out JetElement>
) {
val typeMapper = parentCodegen.typeMapper
val iv = InstructionAdapter(mv)
val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)!! val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
singletonValue.put(singletonValue.type, iv); singletonValue.put(singletonValue.type, iv);
var index = 0; var index = 0;
val asmMethod = signature.getAsmMethod()
for (paramType in asmMethod.getArgumentTypes()) { for (paramType in asmMethod.getArgumentTypes()) {
iv.load(index, paramType); iv.load(index, paramType);
index += paramType.getSize(); index += paramType.getSize();
@@ -63,7 +83,8 @@ class PlatformStaticGenerator(
) )
syntheticOrOriginalMethod.invokeWithoutAssertions(iv) syntheticOrOriginalMethod.invokeWithoutAssertions(iv)
iv.areturn(asmMethod.getReturnType()); iv.areturn(asmMethod.getReturnType());
methodVisitor.visitEnd();
} }
} }
)
}
} }
@@ -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()
); );
} }