Rename MemberMap and implement it via SlicedMap

This commit is contained in:
Alexander Udalov
2013-10-21 21:12:54 +04:00
parent 73b768a72c
commit 41e2300473
8 changed files with 146 additions and 169 deletions
@@ -27,7 +27,7 @@ public abstract class ClassBuilder {
private String thisName;
private final MemberMap members = new MemberMap();
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
public static class Concrete extends ClassBuilder {
private final ClassVisitor v;
@@ -76,8 +76,8 @@ public abstract class ClassBuilder {
}
@NotNull
public MemberMap getMemberMap() {
return members;
public JvmSerializationBindings getSerializationBindings() {
return serializationBindings;
}
@NotNull
@@ -48,6 +48,7 @@ import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.JvmSerializationBindings.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -111,10 +112,10 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
if (owner instanceof NamespaceFacadeContext) {
Type ownerType = ((NamespaceFacadeContext) owner).getDelegateToClassType();
v.getMemberMap().recordImplClassNameForCallable(functionDescriptor, shortNameByAsmType(ownerType));
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, functionDescriptor, shortNameByAsmType(ownerType));
}
else {
v.getMemberMap().recordMethodOfDescriptor(functionDescriptor, asmMethod);
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
}
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor);
@@ -152,7 +153,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
if (kind == JvmMethodParameterKind.VALUE) {
ValueParameterDescriptor parameter = iterator.next();
v.getMemberMap().recordIndexForValueParameter(parameter, i);
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter);
}
}
@@ -213,7 +213,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateKotlinAnnotation() {
DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getMemberMap()));
DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings()));
ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
@@ -31,11 +31,13 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Arrays;
public class JavaSerializerExtension extends SerializerExtension {
private final MemberMap memberMap;
import static org.jetbrains.jet.codegen.JvmSerializationBindings.*;
public JavaSerializerExtension(@NotNull MemberMap memberMap) {
this.memberMap = memberMap;
public class JavaSerializerExtension extends SerializerExtension {
private final JvmSerializationBindings bindings;
public JavaSerializerExtension(@NotNull JvmSerializationBindings bindings) {
this.bindings = bindings;
}
@Override
@@ -54,7 +56,7 @@ public class JavaSerializerExtension extends SerializerExtension {
@NotNull ProtoBuf.Callable.ValueParameter.Builder proto,
@NotNull NameTable nameTable
) {
Integer index = memberMap.getIndexForValueParameter(descriptor);
Integer index = bindings.get(INDEX_FOR_VALUE_PARAMETER, descriptor);
if (index != null) {
proto.setExtension(JavaProtoBuf.index, index);
}
@@ -66,7 +68,7 @@ public class JavaSerializerExtension extends SerializerExtension {
@NotNull NameTable nameTable
) {
if (callable instanceof FunctionDescriptor) {
Method method = memberMap.getMethodOfDescriptor((FunctionDescriptor) callable);
Method method = bindings.get(METHOD_FOR_FUNCTION, (FunctionDescriptor) callable);
if (method != null) {
proto.setExtension(JavaProtoBuf.methodSignature, new SignatureSerializer(nameTable).methodSignature(method));
}
@@ -76,10 +78,10 @@ public class JavaSerializerExtension extends SerializerExtension {
PropertyGetterDescriptor getter = property.getGetter();
PropertySetterDescriptor setter = property.getSetter();
Method getterMethod = getter == null ? null : memberMap.getMethodOfDescriptor(getter);
Method setterMethod = setter == null ? null : memberMap.getMethodOfDescriptor(setter);
Method getterMethod = getter == null ? null : bindings.get(METHOD_FOR_FUNCTION, getter);
Method setterMethod = setter == null ? null : bindings.get(METHOD_FOR_FUNCTION, setter);
Pair<Type, String> field = memberMap.getFieldOfProperty(property);
Pair<Type, String> field = bindings.get(FIELD_FOR_PROPERTY, property);
Type fieldType;
String fieldName;
boolean isStaticInOuter;
@@ -87,14 +89,14 @@ public class JavaSerializerExtension extends SerializerExtension {
if (field != null) {
fieldType = field.first;
fieldName = field.second;
isStaticInOuter = memberMap.isStaticFieldInOuterClass(property);
isStaticInOuter = bindings.get(STATIC_FIELD_IN_OUTER_CLASS, property);
syntheticMethod = null;
}
else {
fieldType = null;
fieldName = null;
isStaticInOuter = false;
syntheticMethod = memberMap.getSyntheticMethodOfProperty(property);
syntheticMethod = bindings.get(SYNTHETIC_METHOD_FOR_PROPERTY, property);
}
JavaProtoBuf.JavaPropertySignature signature = new SignatureSerializer(nameTable)
@@ -108,7 +110,7 @@ public class JavaSerializerExtension extends SerializerExtension {
@NotNull ProtoBuf.Callable.Builder proto,
@NotNull NameTable nameTable
) {
String name = memberMap.getImplClassNameOfCallable(callable);
String name = bindings.get(IMPL_CLASS_NAME_FOR_CALLABLE, callable);
if (name != null) {
proto.setExtension(JavaProtoBuf.implClassName, nameTable.getSimpleNameIndex(Name.identifier(name)));
}
@@ -0,0 +1,111 @@
/*
* 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.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.util.slicedmap.*;
import java.util.Collection;
import java.util.Map;
public final class JvmSerializationBindings {
public static final SerializationMappingSlice<FunctionDescriptor, Method> METHOD_FOR_FUNCTION =
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Pair<Type, String>> FIELD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Method> SYNTHETIC_METHOD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final SerializationMappingSlice<CallableMemberDescriptor, String> IMPL_CLASS_NAME_FOR_CALLABLE =
SerializationMappingSlice.create();
public static final SerializationMappingSetSlice<PropertyDescriptor> STATIC_FIELD_IN_OUTER_CLASS =
SerializationMappingSetSlice.create();
public static final SerializationMappingSlice<ValueParameterDescriptor, Integer> INDEX_FOR_VALUE_PARAMETER =
SerializationMappingSlice.create();
private static final class SerializationMappingSlice<K, V> extends BasicWritableSlice<K, V> {
public SerializationMappingSlice() {
super(Slices.ONLY_REWRITE_TO_EQUAL, false);
}
@NotNull
public static <K, V> SerializationMappingSlice<K, V> create() {
return new SerializationMappingSlice<K, V>();
}
}
private static final class SerializationMappingSetSlice<K> extends Slices.SetSlice<K> {
public SerializationMappingSetSlice() {
super(Slices.ONLY_REWRITE_TO_EQUAL, false);
}
@NotNull
public static <K> SerializationMappingSetSlice<K> create() {
return new SerializationMappingSetSlice<K>();
}
}
static {
BasicWritableSlice.initSliceDebugNames(JvmSerializationBindings.class);
}
private final MutableSlicedMap map;
private JvmSerializationBindings(@NotNull MutableSlicedMap map) {
this.map = map;
}
public JvmSerializationBindings() {
this(SlicedMapImpl.create());
}
@NotNull
public static JvmSerializationBindings union(@NotNull Collection<JvmSerializationBindings> bindings) {
MutableSlicedMap result = SlicedMapImpl.create();
for (JvmSerializationBindings binding : bindings) {
for (Map.Entry<SlicedMapKey<?, ?>, ?> entry : binding.map) {
SlicedMapKey<?, ?> key = entry.getKey();
result.put((WritableSlice) key.getSlice(), key.getKey(), entry.getValue());
}
}
return new JvmSerializationBindings(result);
}
public <K, V> void put(@NotNull SerializationMappingSlice<K, V> slice, @NotNull K key, @NotNull V value) {
map.put(slice, key, value);
}
public <K> void put(@NotNull SerializationMappingSetSlice<K> slice, @NotNull K key) {
map.put(slice, key, true);
}
@Nullable
public <K, V> V get(@NotNull SerializationMappingSlice<K, V> slice, @NotNull K key) {
return map.get(slice, key);
}
public <K> boolean get(@NotNull SerializationMappingSetSlice<K> slice, @NotNull K key) {
return Boolean.TRUE.equals(map.get(slice, key));
}
}
@@ -1,138 +0,0 @@
/*
* 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.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import java.util.*;
public final class MemberMap {
private final Map<FunctionDescriptor, Method> methodForFunction = new HashMap<FunctionDescriptor, Method>();
private final Map<PropertyDescriptor, Pair<Type, String>> fieldForProperty = new HashMap<PropertyDescriptor, Pair<Type, String>>();
private final Map<PropertyDescriptor, Method> syntheticMethodForProperty = new HashMap<PropertyDescriptor, Method>();
private final Map<CallableMemberDescriptor, String> implClassNameForCallable = new HashMap<CallableMemberDescriptor, String>();
private final Set<PropertyDescriptor> staticFieldInOuterClass = new HashSet<PropertyDescriptor>();
private final Map<ValueParameterDescriptor, Integer> indexForValueParameter = new HashMap<ValueParameterDescriptor, Integer>();
@NotNull
public static MemberMap union(@NotNull Collection<MemberMap> maps) {
MemberMap result = new MemberMap();
for (MemberMap map : maps) {
for (Map.Entry<FunctionDescriptor, Method> entry : map.methodForFunction.entrySet()) {
result.recordMethodOfDescriptor(entry.getKey(), entry.getValue());
}
for (Map.Entry<PropertyDescriptor, Pair<Type, String>> entry : map.fieldForProperty.entrySet()) {
result.recordFieldOfProperty(entry.getKey(), entry.getValue().first, entry.getValue().second);
}
for (Map.Entry<PropertyDescriptor, Method> entry : map.syntheticMethodForProperty.entrySet()) {
result.recordSyntheticMethodOfProperty(entry.getKey(), entry.getValue());
}
for (Map.Entry<CallableMemberDescriptor, String> entry : map.implClassNameForCallable.entrySet()) {
result.recordImplClassNameForCallable(entry.getKey(), entry.getValue());
}
for (PropertyDescriptor property : map.staticFieldInOuterClass) {
result.recordStaticFieldInOuterClass(property);
}
for (Map.Entry<ValueParameterDescriptor, Integer> entry : map.indexForValueParameter.entrySet()) {
result.recordIndexForValueParameter(entry.getKey(), entry.getValue());
}
}
return result;
}
public void recordMethodOfDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull Method method) {
Method old = methodForFunction.put(descriptor, method);
assert old == null : "Duplicate method for callable member: " + descriptor + "; " + old;
}
public void recordFieldOfProperty(@NotNull PropertyDescriptor descriptor, @NotNull Type type, @NotNull String fieldName) {
Pair<Type, String> old = fieldForProperty.put(descriptor, Pair.create(type, fieldName));
assert old == null : "Duplicate field for property: " + descriptor + "; " + old;
}
public void recordSyntheticMethodOfProperty(@NotNull PropertyDescriptor descriptor, @NotNull Method method) {
Method old = syntheticMethodForProperty.put(descriptor, method);
assert old == null : "Duplicate synthetic method for property: " + descriptor + "; " + old;
}
public void recordImplClassNameForCallable(@NotNull CallableMemberDescriptor descriptor, @NotNull String name) {
String old = implClassNameForCallable.put(descriptor, name);
assert old == null : "Duplicate src class name for callable: " + descriptor + "; " + old;
}
public void recordStaticFieldInOuterClass(@NotNull PropertyDescriptor property) {
boolean added = staticFieldInOuterClass.add(property);
assert added : "Duplicate static field in outer class: " + property;
}
public void recordIndexForValueParameter(@NotNull ValueParameterDescriptor descriptor, int index) {
Integer old = indexForValueParameter.put(descriptor, index);
assert old == null || old == index : "Duplicate index for value parameter: " + descriptor;
}
@Nullable
public Method getMethodOfDescriptor(@NotNull FunctionDescriptor descriptor) {
return methodForFunction.get(descriptor);
}
@Nullable
public Pair<Type, String> getFieldOfProperty(@NotNull PropertyDescriptor descriptor) {
return fieldForProperty.get(descriptor);
}
@Nullable
public Method getSyntheticMethodOfProperty(@NotNull PropertyDescriptor descriptor) {
return syntheticMethodForProperty.get(descriptor);
}
@Nullable
public String getImplClassNameOfCallable(@NotNull CallableMemberDescriptor descriptor) {
return implClassNameForCallable.get(descriptor);
}
public boolean isStaticFieldInOuterClass(@NotNull PropertyDescriptor property) {
return staticFieldInOuterClass.contains(property);
}
@Nullable
public Integer getIndexForValueParameter(@NotNull ValueParameterDescriptor descriptor) {
return indexForValueParameter.get(descriptor);
}
@Override
public String toString() {
return "Functions: " + methodForFunction.size() +
", fields: " + fieldForProperty.size() +
", synthetic methods: " + syntheticMethodForProperty.size() +
", impl class names: " + implClassNameForCallable.size() +
", value parameters: " + indexForValueParameter.size();
}
}
@@ -102,17 +102,17 @@ public class NamespaceCodegen extends MemberCodegen {
}
public void generate(@NotNull CompilationErrorHandler errorHandler) {
List<MemberMap> namespaceMembers = new ArrayList<MemberMap>(files.size() + 1);
List<JvmSerializationBindings> bindings = new ArrayList<JvmSerializationBindings>(files.size() + 1);
boolean shouldGeneratePackageClass = shouldGenerateNSClass(files);
if (shouldGeneratePackageClass) {
namespaceMembers.add(v.getClassBuilder().getMemberMap());
bindings.add(v.getClassBuilder().getSerializationBindings());
}
for (JetFile file : files) {
try {
ClassBuilder builder = generate(file);
if (builder != null) {
namespaceMembers.add(builder.getMemberMap());
bindings.add(builder.getSerializationBindings());
}
}
catch (ProcessCanceledException e) {
@@ -130,14 +130,14 @@ public class NamespaceCodegen extends MemberCodegen {
}
if (shouldGeneratePackageClass) {
writeKotlinPackageAnnotationIfNeeded(MemberMap.union(namespaceMembers));
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
}
assert v.isActivated() == shouldGeneratePackageClass :
"Different algorithms for generating namespace class and for heuristics for: " + name.asString();
}
private void writeKotlinPackageAnnotationIfNeeded(@NotNull MemberMap members) {
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
return;
}
@@ -146,7 +146,7 @@ public class NamespaceCodegen extends MemberCodegen {
if (file.isScript()) return;
}
DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(members));
DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(bindings));
ProtoBuf.Package packageProto = serializer.packageProto(descriptor).build();
if (packageProto.getMemberCount() == 0) return;
@@ -164,7 +164,6 @@ public class NamespaceCodegen extends MemberCodegen {
av.visitEnd();
}
@Nullable
private ClassBuilder generate(@NotNull JetFile file) {
boolean generateSrcClass = false;
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,6 +49,7 @@ import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.getParentBodyCodegen;
import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.codegen.JvmSerializationBindings.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -92,7 +94,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (context instanceof NamespaceFacadeContext) {
Type ownerType = ((NamespaceFacadeContext) context).getDelegateToClassType();
v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType));
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, propertyDescriptor, shortNameByAsmType(ownerType));
}
else if (!generateBackingField(p, propertyDescriptor)) {
generateSyntheticMethodIfNeeded(propertyDescriptor);
@@ -169,11 +171,11 @@ public class PropertyCodegen extends GenerationStateAware {
}
else {
Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) context.getContextDescriptor());
v.getMemberMap().recordImplClassNameForCallable(descriptor, shortNameByAsmType(tImplType));
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, shortNameByAsmType(tImplType));
}
if (kind != OwnerKind.TRAIT_IMPL) {
v.getMemberMap().recordSyntheticMethodOfProperty(descriptor, method);
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, method);
}
}
@@ -202,7 +204,7 @@ public class PropertyCodegen extends GenerationStateAware {
ImplementationBodyCodegen codegen = getParentBodyCodegen(classBodyCodegen);
builder = codegen.v;
backingFieldContext = codegen.context;
v.getMemberMap().recordStaticFieldInOuterClass(propertyDescriptor);
v.getSerializationBindings().put(STATIC_FIELD_IN_OUTER_CLASS, propertyDescriptor);
} else {
if (kind != OwnerKind.NAMESPACE || isDelegate) {
modifiers |= ACC_PRIVATE;
@@ -216,7 +218,7 @@ public class PropertyCodegen extends GenerationStateAware {
String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate);
v.getMemberMap().recordFieldOfProperty(propertyDescriptor, type, name);
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
return builder.newField(element, modifiers, name, type.getDescriptor(),
typeMapper.mapFieldSignature(jetType), defaultValue);