Optimize PropertyMetadataImpl instance creation

Create all property metadatas in <clinit> and save them to a static array
$propertyMetadata. Getter/setter of each delegated property will then just
obtain the corresponding instance from that array

 #KT-4232 Fixed
This commit is contained in:
Alexander Udalov
2014-04-22 22:59:48 +04:00
parent 925b27238c
commit 61675de305
10 changed files with 183 additions and 30 deletions
@@ -93,7 +93,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
private final Type returnType; private final Type returnType;
private final BindingContext bindingContext; private final BindingContext bindingContext;
final MethodContext context; private final MethodContext context;
private final CodegenStatementVisitor statementVisitor; private final CodegenStatementVisitor statementVisitor;
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
@@ -105,8 +105,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
* When we create a temporary variable to hold some value not to compute it many times * When we create a temporary variable to hold some value not to compute it many times
* we put it into this map to emit access to that variable instead of evaluating the whole expression * we put it into this map to emit access to that variable instead of evaluating the whole expression
*/ */
private final Map<JetElement, StackValue.Local> tempVariables = Maps.newHashMap(); final Map<JetElement, StackValue> tempVariables = Maps.newHashMap();
@NotNull
private final TailRecursionCodegen tailRecursionCodegen; private final TailRecursionCodegen tailRecursionCodegen;
public final CallGenerator defaultCallGenerator; public final CallGenerator defaultCallGenerator;
@@ -442,6 +442,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateSyntheticParts() { protected void generateSyntheticParts() {
generateDelegatedPropertyMetadataArray();
generateFieldForSingleton(); generateFieldForSingleton();
generateClassObjectBackingFieldCopies(); generateClassObjectBackingFieldCopies();
@@ -474,6 +476,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
genClosureFields(context.closure, v, state.getTypeMapper()); genClosureFields(context.closure, v, state.getTypeMapper());
} }
private void generateDelegatedPropertyMetadataArray() {
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generatePropertyMetadataArrayFieldIfNeeded(classAsmType, myClass);
}
}
private boolean isGenericToArrayPresent() { private boolean isGenericToArrayPresent() {
Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray")); Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray"));
for (FunctionDescriptor function : functions) { for (FunctionDescriptor function : functions) {
@@ -31,7 +31,9 @@ import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames; import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
@@ -40,15 +42,18 @@ import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.NotNullLazyValue; import org.jetbrains.jet.storage.NotNullLazyValue;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.boxType; import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive; import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED; import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public abstract class MemberCodegen extends ParentCodegenAwareImpl { public abstract class MemberCodegen extends ParentCodegenAwareImpl {
protected final FieldOwnerContext context; protected final FieldOwnerContext context;
@@ -193,7 +198,7 @@ public abstract class MemberCodegen extends ParentCodegenAwareImpl {
} }
protected void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull JetProperty property) { protected void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull JetProperty property) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property); PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
assert propertyDescriptor != null; assert propertyDescriptor != null;
JetExpression initializer = property.getDelegateExpressionOrInitializer(); JetExpression initializer = property.getDelegateExpressionOrInitializer();
@@ -220,7 +225,7 @@ public abstract class MemberCodegen extends ParentCodegenAwareImpl {
JetExpression initializer = property.getDelegateExpressionOrInitializer(); JetExpression initializer = property.getDelegateExpressionOrInitializer();
if (initializer == null) return false; if (initializer == null) return false;
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property); PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
assert propertyDescriptor != null; assert propertyDescriptor != null;
CompileTimeConstant<?> compileTimeValue = propertyDescriptor.getCompileTimeInitializer(); CompileTimeConstant<?> compileTimeValue = propertyDescriptor.getCompileTimeInitializer();
@@ -281,4 +286,38 @@ public abstract class MemberCodegen extends ParentCodegenAwareImpl {
} }
return false; return false;
} }
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType, @NotNull JetDeclarationContainer container) {
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
for (JetDeclaration declaration : container.getDeclarations()) {
if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
if (property.getDelegate() != null) {
delegatedProperties.add(property);
}
}
}
if (delegatedProperties.isEmpty()) return;
v.newField(null, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
"[" + PROPERTY_METADATA_TYPE, null, null);
InstructionAdapter iv = createOrGetClInitCodegen().v;
iv.iconst(delegatedProperties.size());
iv.newarray(PROPERTY_METADATA_TYPE);
for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
VariableDescriptor property = BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
iv.dup();
iv.iconst(i);
iv.anew(PROPERTY_METADATA_IMPL_TYPE);
iv.dup();
iv.visitLdcInsn(property.getName().asString());
iv.invokespecial(PROPERTY_METADATA_IMPL_TYPE.getInternalName(), "<init>", "(Ljava/lang/String;)V");
iv.astore(PROPERTY_METADATA_IMPL_TYPE);
}
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
}
} }
@@ -74,6 +74,8 @@ public class PackagePartCodegen extends MemberCodegen {
} }
}); });
generatePropertyMetadataArrayFieldIfNeeded(packagePartType, jetFile);
if (clInit != null) { if (clInit != null) {
clInit.v.visitInsn(RETURN); clInit.v.visitInsn(RETURN);
FunctionCodegen.endVisit(clInit.v, "static initializer for package", jetFile); FunctionCodegen.endVisit(clInit.v, "static initializer for package", jetFile);
@@ -18,10 +18,10 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.*;
import org.jetbrains.jet.codegen.context.PackageFacadeContext;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.GenerationStateAware;
@@ -49,6 +49,7 @@ import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.codegen.JvmSerializationBindings.*; import static org.jetbrains.jet.codegen.JvmSerializationBindings.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.PROPERTY_METADATA_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PropertyCodegen extends GenerationStateAware { public class PropertyCodegen extends GenerationStateAware {
@@ -291,8 +292,8 @@ public class PropertyCodegen extends GenerationStateAware {
FunctionGenerationStrategy strategy; FunctionGenerationStrategy strategy;
if (isDefaultAccessor) { if (isDefaultAccessor) {
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) { if (p instanceof JetProperty && ((JetProperty) p).getDelegate() != null) {
strategy = new DefaultPropertyWithDelegateAccessorStrategy(state, accessorDescriptor); strategy = new DelegatedPropertyAccessorStrategy(state, accessorDescriptor, indexOfDelegatedProperty((JetProperty) p));
} }
else { else {
strategy = new DefaultPropertyAccessorStrategy(state, accessorDescriptor); strategy = new DefaultPropertyAccessorStrategy(state, accessorDescriptor);
@@ -306,6 +307,32 @@ public class PropertyCodegen extends GenerationStateAware {
functionCodegen.generateMethod(accessor != null ? accessor : p, signature, accessorDescriptor, strategy); functionCodegen.generateMethod(accessor != null ? accessor : p, signature, accessorDescriptor, strategy);
} }
private static int indexOfDelegatedProperty(@NotNull JetProperty property) {
PsiElement parent = property.getParent();
JetDeclarationContainer container;
if (parent instanceof JetClassBody) {
container = ((JetClassOrObject) parent.getParent());
}
else if (parent instanceof JetFile) {
container = (JetFile) parent;
}
else {
throw new UnsupportedOperationException("Unknown delegated property container: " + parent);
}
int index = 0;
for (JetDeclaration declaration : container.getDeclarations()) {
if (declaration instanceof JetProperty && ((JetProperty) declaration).getDelegate() != null) {
if (declaration == property) {
return index;
}
index++;
}
}
throw new IllegalStateException("Delegated property not found in its parent: " + JetPsiUtil.getElementTextWithContext(property));
}
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) { public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
@@ -318,7 +345,7 @@ public class PropertyCodegen extends GenerationStateAware {
PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty(); PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty();
int paramCode = 0; int paramCode = 0;
if (codegen.context.getContextKind() != OwnerKind.PACKAGE) { if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
v.load(0, OBJECT_TYPE); v.load(0, OBJECT_TYPE);
paramCode = 1; paramCode = 1;
} }
@@ -345,9 +372,12 @@ public class PropertyCodegen extends GenerationStateAware {
} }
} }
private static class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) { private final int index;
public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor, int index) {
super(state, descriptor); super(state, descriptor);
this.index = index;
} }
@Override @Override
@@ -361,13 +391,35 @@ public class PropertyCodegen extends GenerationStateAware {
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, callableDescriptor); Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, callableDescriptor);
assert call != null : "Call should be recorded for delegate call " + signature.toString(); assert call != null : "Call should be recorded for delegate call " + signature.toString();
if (codegen.context.getContextKind() != OwnerKind.PACKAGE) { if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
v.load(0, OBJECT_TYPE); v.load(0, OBJECT_TYPE);
} }
PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty(); CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext();
final Type owner;
if (ownerContext instanceof ClassContext) {
owner = state.getTypeMapper().mapClass(((ClassContext) ownerContext).getContextDescriptor());
}
else if (ownerContext instanceof PackageContext) {
owner = ((PackageContext) ownerContext).getPackagePartType();
}
else {
throw new UnsupportedOperationException("Unknown context: " + ownerContext);
}
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null); codegen.tempVariables.put(
call.getValueArguments().get(1).asElement(),
new StackValue(PROPERTY_METADATA_TYPE) {
@Override
public void put(Type type, InstructionAdapter v) {
v.getstatic(owner.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
v.iconst(index);
StackValue.arrayElement(PROPERTY_METADATA_TYPE).put(type, v);
}
}
);
StackValue delegatedProperty = codegen.intermediateValueForProperty(callableDescriptor.getCorrespondingProperty(), true, null);
StackValue lastValue = codegen.invokeFunction(call, delegatedProperty, resolvedCall); StackValue lastValue = codegen.invokeFunction(call, delegatedProperty, resolvedCall);
Type asmType = signature.getReturnType(); Type asmType = signature.getReturnType();
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.context;
import kotlin.Function0; import kotlin.Function0;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.binding.MutableClosure; import org.jetbrains.jet.codegen.binding.MutableClosure;
@@ -33,17 +32,18 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.storage.LockBasedStorageManager; import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.NullableLazyValue; import org.jetbrains.jet.storage.NullableLazyValue;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_THIS_FIELD; import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_THIS_FIELD;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag; import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
public abstract class CodegenContext<T extends DeclarationDescriptor> { public abstract class CodegenContext<T extends DeclarationDescriptor> {
@@ -103,17 +103,15 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
} }
@NotNull @NotNull
public ClassOrPackageFragmentDescriptor getClassOrPackageDescriptor() { @SuppressWarnings("unchecked")
CodegenContext c = this; public CodegenContext<? extends ClassOrPackageFragmentDescriptor> getClassOrPackageParentContext() {
CodegenContext<?> context = this;
while (true) { while (true) {
assert c != null; if (context.getContextDescriptor() instanceof ClassOrPackageFragmentDescriptor) {
DeclarationDescriptor contextDescriptor = c.getContextDescriptor(); return (CodegenContext) context;
if (contextDescriptor instanceof ClassOrPackageFragmentDescriptor) {
return (ClassOrPackageFragmentDescriptor) contextDescriptor;
}
else {
c = c.getParentContext();
} }
context = context.getParentContext();
assert context != null : "Context which is not top-level has no parent: " + this;
} }
} }
@@ -413,7 +411,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
} }
CodegenContext descriptorContext = null; CodegenContext descriptorContext = null;
if (!fromOutsideContext || getClassOrPackageDescriptor() != descriptor.getContainingDeclaration()) { if (!fromOutsideContext || getClassOrPackageParentContext().getContextDescriptor() != descriptor.getContainingDeclaration()) {
DeclarationDescriptor enclosed = descriptor.getContainingDeclaration(); DeclarationDescriptor enclosed = descriptor.getContainingDeclaration();
boolean isClassObjectMember = DescriptorUtils.isClassObject(enclosed); boolean isClassObjectMember = DescriptorUtils.isClassObject(enclosed);
//go upper //go upper
@@ -35,6 +35,8 @@ public class AsmTypeConstants {
public static final Type FUNCTION0_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function0"); public static final Type FUNCTION0_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function0");
public static final Type FUNCTION1_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function1"); public static final Type FUNCTION1_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function1");
public static final Type INT_RANGE_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/IntRange"); public static final Type INT_RANGE_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/IntRange");
public static final Type PROPERTY_METADATA_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadata");
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadataImpl");
public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef"); public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef");
@@ -0,0 +1,46 @@
import java.util.IdentityHashMap
class A {
var foo: Int by IntHandler
class object {
var bar: Any? by AnyHandler
}
}
val baz: String by StringHandler
val metadatas = IdentityHashMap<PropertyMetadata, Unit>()
fun record(p: PropertyMetadata) = metadatas.put(p, Unit.VALUE)
object IntHandler {
fun get(t: Any?, p: PropertyMetadata): Int { record(p); return 42 }
fun set(t: Any?, p: PropertyMetadata, value: Int) { record(p) }
}
object AnyHandler {
fun get(t: Any?, p: PropertyMetadata): Any? { record(p); return 3.14 }
fun set(t: Any?, p: PropertyMetadata, value: Any?) { record(p) }
}
object StringHandler {
fun get(t: Any?, p: PropertyMetadata): String { record(p); return p.name }
fun set(t: Any?, p: PropertyMetadata, value: String) { record(p) }
}
fun box(): String {
val a = A()
a.foo = 42
a.foo = a.foo + baz.length
a.foo = 239
A.bar = baz + a.foo
baz + A.bar
if (metadatas.keySet().size() != 3)
return "Fail: only three instances of PropertyMetadata should have been created\n${metadatas.keySet()}"
return "OK"
}
@@ -2299,6 +2299,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/delegatedProperty/privateVar.kt"); doTest("compiler/testData/codegen/box/delegatedProperty/privateVar.kt");
} }
@TestMetadata("propertyMetadataShouldBeCached.kt")
public void testPropertyMetadataShouldBeCached() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/propertyMetadataShouldBeCached.kt");
}
@TestMetadata("setAsExtensionFun.kt") @TestMetadata("setAsExtensionFun.kt")
public void testSetAsExtensionFun() throws Exception { public void testSetAsExtensionFun() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/setAsExtensionFun.kt"); doTest("compiler/testData/codegen/box/delegatedProperty/setAsExtensionFun.kt");
@@ -38,6 +38,7 @@ public final class JvmAbi {
public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME; public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME;
public static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate"; public static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate";
public static final String PROPERTY_METADATA_ARRAY_NAME = "$propertyMetadata";
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = "$annotations"; public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = "$annotations";
public static final String INSTANCE_FIELD = "instance$"; public static final String INSTANCE_FIELD = "instance$";