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
// with traitMember's modality
CallableMemberDescriptor copy =
inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
CallableMemberDescriptor.Kind.DECLARATION, true);
result.putAll(copyFunctions(inheritedMember, traitMember, inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
CallableMemberDescriptor.Kind.DECLARATION, true));
}
return result;
}
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);
}
@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) {
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) {
return isStaticKind(kind) ||
JetTypeMapper.isAccessor(functionDescriptor) ||
AnnotationsPackage.isPlatformStaticInObject(functionDescriptor);
AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor);
}
public static boolean isStaticKind(OwnerKind kind) {
@@ -2419,7 +2419,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (isSingleton) {
if (context.hasThisDescriptor() &&
context.getThisDescriptor().equals(calleeContainingClass) &&
!AnnotationsPackage.isPlatformStaticInObject(context.getContextDescriptor())) {
!AnnotationsPackage.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) {
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
}
else {
@@ -17,12 +17,18 @@
package org.jetbrains.jet.codegen
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.jet.codegen.state.GenerationState
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin
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(
val descriptor: FunctionDescriptor,
@@ -31,39 +37,54 @@ class PlatformStaticGenerator(
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
val typeMapper = state.getTypeMapper()
val asmMethod = typeMapper.mapSignature(descriptor).getAsmMethod()
val flags = Opcodes.ACC_STATIC or AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION)
val methodVisitor = classBuilder.newMethod(
Synthetic(declarationOrigin.element, descriptor),
flags,
asmMethod.getName()!!,
asmMethod.getDescriptor()!!,
typeMapper.mapSignature(descriptor).getGenericsSignature(),
FunctionCodegen.getThrownExceptions(descriptor, typeMapper))
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor
val copies = CodegenUtil.copyFunctions(
memberDescriptor,
memberDescriptor,
declarationOrigin.descriptor?.getContainingDeclaration()?.getContainingDeclaration(),
descriptor.getModality(),
descriptor.getVisibility(),
CallableMemberDescriptor.Kind.SYNTHESIZED,
false
)
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) {
methodVisitor.visitCode();
val iv = InstructionAdapter(methodVisitor)
val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)!!
singletonValue.put(singletonValue.type, iv);
var index = 0;
for (paramType in asmMethod.getArgumentTypes()) {
iv.load(index, paramType);
index += paramType.getSize();
}
codegen.functionCodegen.generateMethod(
Synthetic(declarationOrigin.element, staticFunctionDescriptor),
jvmMethodSignature,
staticFunctionDescriptor,
object: FunctionGenerationStrategy() {
override fun generateBody(
mv: MethodVisitor,
frameMap: FrameMap,
signature: JvmMethodSignature,
context: MethodContext,
parentCodegen: MemberCodegen<out JetElement>
) {
val typeMapper = parentCodegen.typeMapper
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
codegen.getContext().accessibleFunctionDescriptor(descriptor),
false,
codegen.getContext()
)
syntheticOrOriginalMethod.invokeWithoutAssertions(iv)
iv.areturn(asmMethod.getReturnType());
methodVisitor.visitEnd();
}
val iv = InstructionAdapter(mv)
val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
singletonValue.put(singletonValue.type, iv);
var index = 0;
val asmMethod = signature.getAsmMethod()
for (paramType in asmMethod.getArgumentTypes()) {
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) {
if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) {
if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) {
if (resultReceiver.canHaveSideEffects()) {
return coercion(resultReceiver, Type.VOID_TYPE);
}
@@ -1414,7 +1414,7 @@ public abstract class StackValue {
return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType());
}
else if (dispatchReceiver != null) {
if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) {
if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) {
return Type.VOID_TYPE;
}
else {
@@ -488,7 +488,7 @@ public class JetTypeMapper {
else {
if (isStaticDeclaration(functionDescriptor) ||
isAccessor(functionDescriptor) ||
AnnotationsPackage.isPlatformStaticInObject(functionDescriptor)) {
AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
invokeOpcode = INVOKESTATIC;
}
else if (isInterface) {
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve.annotations
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.descriptors.CallableDescriptor
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
}
public fun CallableDescriptor.isPlatformStaticInObject(): Boolean =
isPlatformStaticIn(ClassKind.OBJECT)
public fun CallableDescriptor.isPlatformStaticInObjectOrClass(): Boolean =
isPlatformStaticIn(ClassKind.OBJECT, ClassKind.CLASS)
public fun CallableDescriptor.isPlatformStaticInClassObject(): Boolean =
isPlatformStaticIn(ClassKind.CLASS_OBJECT)
private fun CallableDescriptor.isPlatformStaticIn(kind: ClassKind): Boolean =
private fun CallableDescriptor.isPlatformStaticIn(vararg kinds: ClassKind): Boolean =
when (this) {
is PropertyAccessorDescriptor -> {
val propertyDescriptor = getCorrespondingProperty()
DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), kind) &&
kinds.any { DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), it) } &&
(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;
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(),
getName(),
kind,
SourceElement.NO_SOURCE
getSource()
);
}