From bcc14effb58a73b823c0f917b09d974d186af076 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 10 Oct 2013 13:44:32 +0400 Subject: [PATCH] NamespaceCodegen refactoring --- .../jet/codegen/NamespaceCodegen.java | 92 ++---------- .../jet/codegen/NamespacePartCodegen.java | 141 ++++++++++++++++++ .../jet/codegen/context/CodegenContext.java | 4 +- .../context/NamespaceFacadeContext.java | 33 ++++ 4 files changed, 191 insertions(+), 79 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/NamespacePartCodegen.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/context/NamespaceFacadeContext.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index c3779d43ac5..46710577650 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.codegen; -import com.google.common.collect.Lists; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.io.FileUtil; @@ -26,7 +25,6 @@ import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.AnnotationVisitor; -import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext; @@ -35,9 +33,7 @@ import org.jetbrains.jet.descriptors.serialization.BitEncoding; import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer; import org.jetbrains.jet.descriptors.serialization.PackageData; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -49,7 +45,6 @@ import org.jetbrains.jet.lang.resolve.name.Name; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import static org.jetbrains.asm4.Opcodes.*; @@ -61,15 +56,19 @@ import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageCl public class NamespaceCodegen extends MemberCodegen { @NotNull private final ClassBuilderOnDemand v; - @NotNull private final FqName name; + + @NotNull + private final FqName name; + + @NotNull private final Collection files; private final NamespaceDescriptor descriptor; public NamespaceCodegen( @NotNull ClassBuilderOnDemand v, @NotNull final FqName fqName, - GenerationState state, - Collection namespaceFiles + @NotNull GenerationState state, + @NotNull Collection namespaceFiles ) { super(state, null); checkAllFilesHaveSameNamespace(namespaceFiles); @@ -165,9 +164,12 @@ public class NamespaceCodegen extends MemberCodegen { av.visitEnd(); } + @Nullable private ClassBuilder generate(@NotNull JetFile file) { boolean generateSrcClass = false; + FieldOwnerContext namespaceImpl = CodegenContext.STATIC.intoNamespace(descriptor); + for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { generateSrcClass = true; @@ -178,7 +180,7 @@ public class NamespaceCodegen extends MemberCodegen { } } else if (declaration instanceof JetScript) { - ScriptCodegen.createScriptCodegen((JetScript) declaration, state, CodegenContext.STATIC.intoNamespace(descriptor)).generate(); + ScriptCodegen.createScriptCodegen((JetScript) declaration, state, namespaceImpl).generate(); } } @@ -187,42 +189,20 @@ public class NamespaceCodegen extends MemberCodegen { Type namespacePartType = getNamespacePartType(getPackageClassFqName(name), file); ClassBuilder builder = state.getFactory().forNamespacePart(namespacePartType, file); - builder.defineClass(file, V1_6, - ACC_PUBLIC | ACC_FINAL, - namespacePartType.getInternalName(), - null, - //"jet/lang/Namespace", - "java/lang/Object", - new String[0] - ); - builder.visitSource(file.getName(), null); + NamespacePartCodegen namespacePartCodegen = new NamespacePartCodegen(builder, file, namespacePartType, namespaceImpl, state); + namespacePartCodegen.generate(); - writeKotlinPackageFragmentAnnotation(builder); - - FieldOwnerContext nameSpaceContext = CodegenContext.STATIC.intoNamespace(descriptor); - - FieldOwnerContext nameSpacePart = CodegenContext.STATIC.intoNamespacePart(namespacePartType, descriptor); + FieldOwnerContext nameSpacePart = CodegenContext.STATIC.intoNamespaceFacade(namespacePartType, descriptor); for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) { - genFunctionOrProperty(nameSpaceContext, (JetTypeParameterListOwner) declaration, builder); genFunctionOrProperty(nameSpacePart, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); } } - generateStaticInitializers(builder, file, nameSpaceContext); - - builder.done(); - return builder; } - private static void writeKotlinPackageFragmentAnnotation(@NotNull ClassBuilder builder) { - AnnotationVisitor av = builder.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), true); - av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); - av.visitEnd(); - } - public void generateClassOrObject(@NotNull JetClassOrObject classOrObject) { CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); genClassOrObject(context, classOrObject); @@ -263,48 +243,6 @@ public class NamespaceCodegen extends MemberCodegen { } } - private void generateStaticInitializers(@NotNull ClassBuilder builder, @NotNull JetFile file, @NotNull FieldOwnerContext context) { - List properties = collectPropertiesToInitialize(file); - if (properties.isEmpty()) return; - - MethodVisitor mv = builder.newMethod(file, ACC_STATIC, "", "()V", null, null); - if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { - mv.visitCode(); - - FrameMap frameMap = new FrameMap(); - - SimpleFunctionDescriptorImpl clInit = - new SimpleFunctionDescriptorImpl(descriptor, Collections.emptyList(), - Name.special(""), - CallableMemberDescriptor.Kind.SYNTHESIZED); - clInit.initialize(null, null, Collections.emptyList(), - Collections.emptyList(), null, null, Visibilities.PRIVATE, false); - - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context.intoFunction(clInit), state, this); - - for (JetDeclaration declaration : properties) { - ImplementationBodyCodegen. - initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration); - } - - mv.visitInsn(RETURN); - FunctionCodegen.endVisit(mv, "static initializer for namespace", file); - mv.visitEnd(); - } - } - - @NotNull - private List collectPropertiesToInitialize(@NotNull JetFile file) { - List result = Lists.newArrayList(); - for (JetDeclaration declaration : file.getDeclarations()) { - if (declaration instanceof JetProperty && - ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) { - result.add((JetProperty) declaration); - } - } - return result; - } - public void done() { v.done(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespacePartCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespacePartCodegen.java new file mode 100644 index 00000000000..50be7490075 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespacePartCodegen.java @@ -0,0 +1,141 @@ +/* + * 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 com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.asm4.AnnotationVisitor; +import org.jetbrains.asm4.MethodVisitor; +import org.jetbrains.asm4.Type; +import org.jetbrains.jet.codegen.context.FieldOwnerContext; +import org.jetbrains.jet.codegen.state.GenerationState; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; +import org.jetbrains.jet.lang.resolve.name.Name; + +import java.util.Collections; +import java.util.List; + +import static org.jetbrains.asm4.Opcodes.*; +import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; + +public class NamespacePartCodegen extends MemberCodegen { + + private final ClassBuilder v; + + private final NamespaceDescriptor descriptor; + + private final JetFile jetFile; + + private final Type namespacePartName; + + private final FieldOwnerContext context; + + public NamespacePartCodegen( + @NotNull ClassBuilder v, + @NotNull JetFile jetFile, + @NotNull Type namespacePartName, + @NotNull FieldOwnerContext context, + @NotNull GenerationState state + ) { + super(state, null); + this.v = v; + this.jetFile = jetFile; + this.namespacePartName = namespacePartName; + this.context = context; + descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, jetFile); + assert descriptor != null : "No namespace found for jetFile " + jetFile + " declared package: " + jetFile.getPackageName(); + } + + public void generate() { + v.defineClass(jetFile, V1_6, + ACC_PUBLIC | ACC_FINAL, + namespacePartName.getInternalName(), + null, + //"jet/lang/Namespace", + "java/lang/Object", + new String[0] + ); + v.visitSource(jetFile.getName(), null); + + writeKotlinPackageFragmentAnnotation(); + + for (JetDeclaration declaration : jetFile.getDeclarations()) { + if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) { + genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v); + } + } + + generateStaticInitializers(); + + v.done(); + } + + private void writeKotlinPackageFragmentAnnotation() { + AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), true); + av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); + av.visitEnd(); + } + + + private void generateStaticInitializers() { + List properties = collectPropertiesToInitialize(); + if (properties.isEmpty()) return; + + MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "", "()V", null, null); + if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { + mv.visitCode(); + + FrameMap frameMap = new FrameMap(); + + SimpleFunctionDescriptorImpl clInit = + new SimpleFunctionDescriptorImpl(this.descriptor, Collections.emptyList(), + Name.special(""), + CallableMemberDescriptor.Kind.SYNTHESIZED); + clInit.initialize(null, null, Collections.emptyList(), + Collections.emptyList(), null, null, Visibilities.PRIVATE, false); + + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, this.context.intoFunction(clInit), state, this); + + for (JetDeclaration declaration : properties) { + ImplementationBodyCodegen. + initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration); + } + + mv.visitInsn(RETURN); + FunctionCodegen.endVisit(mv, "static initializer for namespace", jetFile); + mv.visitEnd(); + } + } + + @NotNull + private List collectPropertiesToInitialize() { + List result = Lists.newArrayList(); + for (JetDeclaration declaration : jetFile.getDeclarations()) { + if (declaration instanceof JetProperty && + ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) { + result.add((JetProperty) declaration); + } + } + return result; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java index d1be0aee4da..6ec5e0d8bec 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java @@ -152,8 +152,8 @@ public abstract class CodegenContext { } @NotNull - public FieldOwnerContext intoNamespacePart(@NotNull Type delegateTo, @NotNull NamespaceDescriptor descriptor) { - return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo)); + public FieldOwnerContext intoNamespaceFacade(@NotNull Type delegateTo, @NotNull NamespaceDescriptor descriptor) { + return new NamespaceFacadeContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo)); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/NamespaceFacadeContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/NamespaceFacadeContext.java new file mode 100644 index 00000000000..878b8d75dd5 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/NamespaceFacadeContext.java @@ -0,0 +1,33 @@ +/* + * 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.context; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.OwnerKind; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; + +public class NamespaceFacadeContext extends NamespaceContext { + + public NamespaceFacadeContext( + @NotNull NamespaceDescriptor contextDescriptor, + @Nullable CodegenContext parent, + @NotNull OwnerKind kind + ) { + super(contextDescriptor, parent, kind); + } +}