001 /*
002 * Copyright 2010-2014 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.progress.ProcessCanceledException;
021 import com.intellij.util.ArrayUtil;
022 import kotlin.Function0;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.backend.common.DataClassMethodGenerator;
026 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
027 import org.jetbrains.jet.codegen.binding.CodegenBinding;
028 import org.jetbrains.jet.codegen.binding.MutableClosure;
029 import org.jetbrains.jet.codegen.bridges.BridgesPackage;
030 import org.jetbrains.jet.codegen.context.ClassContext;
031 import org.jetbrains.jet.codegen.context.ConstructorContext;
032 import org.jetbrains.jet.codegen.context.MethodContext;
033 import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
034 import org.jetbrains.jet.codegen.state.GenerationState;
035 import org.jetbrains.jet.codegen.state.JetTypeMapper;
036 import org.jetbrains.jet.descriptors.serialization.BitEncoding;
037 import org.jetbrains.jet.descriptors.serialization.ClassData;
038 import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer;
039 import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
040 import org.jetbrains.jet.lang.descriptors.*;
041 import org.jetbrains.jet.lang.psi.*;
042 import org.jetbrains.jet.lang.resolve.BindingContext;
043 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
044 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
045 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
046 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
047 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
048 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
049 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
050 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature;
051 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
052 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
053 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
054 import org.jetbrains.jet.lang.resolve.name.Name;
055 import org.jetbrains.jet.lang.types.*;
056 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
057 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
058 import org.jetbrains.jet.lexer.JetTokens;
059 import org.jetbrains.org.objectweb.asm.*;
060 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
061 import org.jetbrains.org.objectweb.asm.commons.Method;
062
063 import java.util.*;
064
065 import static org.jetbrains.jet.codegen.AsmUtil.*;
066 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
067 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
068 import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
069 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
070 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
071 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
072 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
073 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
074 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
075
076 public class ImplementationBodyCodegen extends ClassBodyCodegen {
077 private static final String VALUES = "$VALUES";
078 private JetDelegationSpecifier superCall;
079 private Type superClassAsmType;
080 @Nullable // null means java/lang/Object
081 private JetType superClassType;
082 private final Type classAsmType;
083
084 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy;
085
086 public ImplementationBodyCodegen(
087 @NotNull JetClassOrObject aClass,
088 @NotNull ClassContext context,
089 @NotNull ClassBuilder v,
090 @NotNull GenerationState state,
091 @Nullable MemberCodegen<?> parentCodegen
092 ) {
093 super(aClass, context, v, state, parentCodegen);
094 this.classAsmType = typeMapper.mapClass(descriptor);
095 }
096
097 @Override
098 protected void generateDeclaration() {
099 getSuperClass();
100
101 JvmClassSignature signature = signature();
102
103 boolean isAbstract = false;
104 boolean isInterface = false;
105 boolean isFinal = false;
106 boolean isStatic;
107 boolean isAnnotation = false;
108 boolean isEnum = false;
109
110 if (myClass instanceof JetClass) {
111 JetClass jetClass = (JetClass) myClass;
112 if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) {
113 isAbstract = true;
114 }
115 if (jetClass.isTrait()) {
116 isAbstract = true;
117 isInterface = true;
118 }
119 else if (jetClass.isAnnotation()) {
120 isAbstract = true;
121 isInterface = true;
122 isAnnotation = true;
123 signature.getInterfaces().add("java/lang/annotation/Annotation");
124 }
125 else if (jetClass.isEnum()) {
126 isAbstract = hasAbstractMembers(descriptor);
127 isEnum = true;
128 }
129
130 if (descriptor.getKind() == ClassKind.OBJECT || descriptor.getKind() == ClassKind.CLASS_OBJECT) {
131 isFinal = true;
132 }
133
134 if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) {
135 isFinal = true;
136 }
137 isStatic = !jetClass.isInner();
138 }
139 else {
140 isStatic = myClass.getParent() instanceof JetClassObject;
141 isFinal = true;
142 }
143
144 int access = 0;
145
146 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
147 // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class
148 // Light class generation is implemented so that Cls-classes only read bare code of classes,
149 // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY)
150 // Thus we must write full accessibility flags on inner classes in this mode
151 access |= getVisibilityAccessFlag(descriptor);
152 // Same for STATIC
153 if (isStatic) {
154 access |= ACC_STATIC;
155 }
156 }
157 else {
158 access |= getVisibilityAccessFlagForClass(descriptor);
159 }
160 if (isAbstract) {
161 access |= ACC_ABSTRACT;
162 }
163 if (isInterface) {
164 access |= ACC_INTERFACE; // ACC_SUPER
165 }
166 else {
167 access |= ACC_SUPER;
168 }
169 if (isFinal) {
170 access |= ACC_FINAL;
171 }
172 if (isAnnotation) {
173 access |= ACC_ANNOTATION;
174 }
175 if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) {
176 access |= ACC_DEPRECATED;
177 }
178 if (isEnum) {
179 for (JetDeclaration declaration : myClass.getDeclarations()) {
180 if (declaration instanceof JetEnumEntry) {
181 if (enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) {
182 access &= ~ACC_FINAL;
183 }
184 }
185 }
186 access |= ACC_ENUM;
187 }
188 List<String> interfaces = signature.getInterfaces();
189 v.defineClass(myClass, V1_6,
190 access,
191 signature.getName(),
192 signature.getJavaGenericSignature(),
193 signature.getSuperclassName(),
194 ArrayUtil.toStringArray(interfaces)
195 );
196 v.visitSource(myClass.getContainingFile().getName(), null);
197
198 writeEnclosingMethod();
199
200 writeOuterClasses();
201
202 writeInnerClasses();
203
204 AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
205 }
206
207 @Override
208 protected void generateKotlinAnnotation() {
209 if (isAnonymousObject(descriptor)) {
210 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.ANONYMOUS_OBJECT);
211 return;
212 }
213
214 if (!isTopLevelOrInnerClass(descriptor)) {
215 // LOCAL_CLASS is also written to inner classes of local classes
216 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.LOCAL_CLASS);
217 return;
218 }
219
220 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
221
222 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings()));
223
224 ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
225
226 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto);
227
228 AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
229 //noinspection ConstantConditions
230 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
231 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
232 for (String string : BitEncoding.encodeBytes(data.toBytes())) {
233 array.visit(null, string);
234 }
235 array.visitEnd();
236 av.visitEnd();
237 }
238
239 private void writeEnclosingMethod() {
240 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
241 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
242
243 boolean isObjectLiteral = DescriptorUtils.isAnonymousObject(descriptor);
244
245 boolean isLocalOrAnonymousClass = isObjectLiteral ||
246 !(parentDescriptor instanceof PackageFragmentDescriptor || parentDescriptor instanceof ClassDescriptor);
247 // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level
248 if (isLocalOrAnonymousClass && state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
249 writeOuterClassAndEnclosingMethod(descriptor, descriptor, typeMapper, v);
250 }
251 }
252
253 private void writeInnerClasses() {
254 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor);
255 if (result != null) {
256 for (ClassDescriptor innerClass : result) {
257 writeInnerClass(innerClass);
258 }
259 }
260 }
261
262 private void writeOuterClasses() {
263 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
264 // for each enclosing class and for each immediate member
265 DeclarationDescriptor inner = descriptor;
266 while (true) {
267 if (inner == null || isTopLevelDeclaration(inner)) {
268 break;
269 }
270 if (inner instanceof ClassDescriptor) {
271 writeInnerClass((ClassDescriptor) inner);
272 }
273 inner = inner.getContainingDeclaration();
274 }
275 }
276
277 private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
278 // TODO: proper access
279 int innerClassAccess = getVisibilityAccessFlag(innerClass);
280 if (innerClass.getModality() == Modality.FINAL) {
281 innerClassAccess |= ACC_FINAL;
282 }
283 else if (innerClass.getModality() == Modality.ABSTRACT) {
284 innerClassAccess |= ACC_ABSTRACT;
285 }
286
287 if (innerClass.getKind() == ClassKind.TRAIT) {
288 innerClassAccess |= ACC_INTERFACE;
289 }
290 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) {
291 innerClassAccess |= ACC_ENUM;
292 }
293
294 if (!innerClass.isInner()) {
295 innerClassAccess |= ACC_STATIC;
296 }
297
298 // TODO: cache internal names
299 DeclarationDescriptor containing = innerClass.getContainingDeclaration();
300 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null;
301
302 String innerClassInternalName;
303 String innerName;
304
305 if (isClassObject(innerClass)) {
306 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME;
307 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
308 }
309 else {
310 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
311 innerClassInternalName = getInternalNameForImpl(innerClass);
312 }
313
314 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess);
315 }
316
317 @NotNull
318 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) {
319 return typeMapper.mapClass(descriptor).getInternalName();
320 }
321
322 @NotNull
323 private JvmClassSignature signature() {
324 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
325
326 typeMapper.writeFormalTypeParameters(descriptor.getTypeConstructor().getParameters(), sw);
327
328 sw.writeSuperclass();
329 if (superClassType == null) {
330 sw.writeClassBegin(superClassAsmType);
331 sw.writeClassEnd();
332 }
333 else {
334 typeMapper.mapSupertype(superClassType, sw);
335 }
336 sw.writeSuperclassEnd();
337
338 List<JetType> interfaceSupertypes = Lists.newArrayList();
339 boolean explicitKObject = false;
340
341 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
342 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
343 assert superType != null : "No supertype for class: " + myClass.getText();
344 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
345 if (isInterface(superClassDescriptor)) {
346 interfaceSupertypes.add(superType);
347
348 assert superClassDescriptor != null : "should be already checked by isInterface()";
349 if (JvmAbi.K_OBJECT.equalsTo(DescriptorUtils.getFqName(superClassDescriptor))) {
350 explicitKObject = true;
351 }
352 }
353 }
354
355 LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>();
356 if (!explicitKObject) {
357 Type kObject = asmTypeByFqNameWithoutInnerClasses(JvmAbi.K_OBJECT);
358 sw.writeInterface();
359 sw.writeClassBegin(kObject);
360 sw.writeClassEnd();
361 sw.writeInterfaceEnd();
362 superInterfaces.add(kObject.getInternalName());
363 }
364
365 for (JetType supertype : interfaceSupertypes) {
366 sw.writeInterface();
367 Type jvmName = typeMapper.mapSupertype(supertype, sw);
368 sw.writeInterfaceEnd();
369 superInterfaces.add(jvmName.getInternalName());
370 }
371
372 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(),
373 new ArrayList<String>(superInterfaces),
374 sw.makeJavaGenericSignature());
375 }
376
377 protected void getSuperClass() {
378 superClassAsmType = AsmTypeConstants.OBJECT_TYPE;
379 superClassType = null;
380
381 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
382
383 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
384 return;
385 }
386
387 if (kind != OwnerKind.IMPLEMENTATION) {
388 throw new IllegalStateException("must be impl to reach this code: " + kind);
389 }
390
391 for (JetDelegationSpecifier specifier : delegationSpecifiers) {
392 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
393 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
394 assert superType != null :
395 String.format("No type recorded for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier));
396
397 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
398 assert superClassDescriptor != null;
399 if (!isInterface(superClassDescriptor)) {
400 superClassType = superType;
401 superClassAsmType = typeMapper.mapClass(superClassDescriptor);
402 superCall = specifier;
403 }
404 }
405 }
406
407 if (superClassType == null) {
408 if (descriptor.getKind() == ClassKind.ENUM_CLASS) {
409 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType());
410 superClassAsmType = typeMapper.mapType(superClassType);
411 }
412 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
413 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next();
414 superClassAsmType = typeMapper.mapType(superClassType);
415 }
416 }
417 }
418
419 @Override
420 protected void generateSyntheticParts() {
421 generateDelegatedPropertyMetadataArray();
422
423 generateFieldForSingleton();
424
425 generateClassObjectBackingFieldCopies();
426
427 try {
428 generatePrimaryConstructor();
429 }
430 catch (CompilationException e) {
431 throw e;
432 }
433 catch (ProcessCanceledException e) {
434 throw e;
435 }
436 catch (RuntimeException e) {
437 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
438 }
439
440 generateTraitMethods();
441
442 generateSyntheticAccessors();
443
444 generateEnumMethodsAndConstInitializers();
445
446 generateFunctionsForDataClasses();
447
448 generateBuiltinMethodStubs();
449
450 generateToArray();
451
452 genClosureFields(context.closure, v, state.getTypeMapper());
453 }
454
455 private void generateDelegatedPropertyMetadataArray() {
456 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
457 generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
458 }
459 }
460
461 private boolean isGenericToArrayPresent() {
462 Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray"));
463 for (FunctionDescriptor function : functions) {
464 if (CallResolverUtil.isOrOverridesSynthesized(function)) {
465 continue;
466 }
467
468 if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
469 continue;
470 }
471
472 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(function.getTypeParameters().get(0).getDefaultType());
473 JetType returnType = function.getReturnType();
474 assert returnType != null : function.toString();
475 JetType paramType = function.getValueParameters().get(0).getType();
476 if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) {
477 return true;
478 }
479 }
480 return false;
481
482 }
483
484 private void generateToArray() {
485 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
486 if (!isSubclass(descriptor, builtIns.getCollection())) return;
487
488 int access = descriptor.getKind() == ClassKind.TRAIT ?
489 ACC_PUBLIC | ACC_ABSTRACT :
490 ACC_PUBLIC;
491 if (JvmCodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) {
492 MethodVisitor mv = v.getVisitor().visitMethod(access, "toArray", "()[Ljava/lang/Object;", null, null);
493
494 if (descriptor.getKind() != ClassKind.TRAIT) {
495 InstructionAdapter iv = new InstructionAdapter(mv);
496 mv.visitCode();
497
498 iv.load(0, classAsmType);
499 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;");
500 iv.areturn(Type.getObjectType("[Ljava/lang/Object;"));
501
502 FunctionCodegen.endVisit(mv, "toArray", myClass);
503 }
504 }
505
506 if (!isGenericToArrayPresent()) {
507 MethodVisitor mv = v.getVisitor().visitMethod(access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null);
508
509 if (descriptor.getKind() != ClassKind.TRAIT) {
510 InstructionAdapter iv = new InstructionAdapter(mv);
511 mv.visitCode();
512
513 iv.load(0, classAsmType);
514 iv.load(1, Type.getObjectType("[Ljava/lang/Object;"));
515
516 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;");
517 iv.areturn(Type.getObjectType("[Ljava/lang/Object;"));
518
519 FunctionCodegen.endVisit(mv, "toArray", myClass);
520 }
521 }
522 }
523
524 private void generateMethodStub(
525 @NotNull String name,
526 @NotNull String desc,
527 @NotNull ClassifierDescriptor returnedClassifier,
528 @NotNull ClassifierDescriptor... valueParameterClassifiers
529 ) {
530 if (JvmCodegenUtil.getDeclaredFunctionByRawSignature(
531 descriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers) == null) {
532 int access = descriptor.getKind() == ClassKind.TRAIT ?
533 ACC_PUBLIC | ACC_ABSTRACT :
534 ACC_PUBLIC;
535 MethodVisitor mv = v.getVisitor().visitMethod(access, name, desc, null, null);
536 if (descriptor.getKind() != ClassKind.TRAIT) {
537 mv.visitCode();
538 genThrow(mv, "java/lang/UnsupportedOperationException", "Mutating immutable collection");
539 FunctionCodegen.endVisit(mv, "built-in stub for " + name + desc, null);
540 }
541 }
542 }
543
544 private void generateBuiltinMethodStubs() {
545 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
546 if (isSubclass(descriptor, builtIns.getCollection())) {
547 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getCollection(), 0);
548
549 generateMethodStub("add", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), classifier);
550 generateMethodStub("remove", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), builtIns.getAny());
551 generateMethodStub("addAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
552 generateMethodStub("removeAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
553 generateMethodStub("retainAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
554 generateMethodStub("clear", "()V", builtIns.getUnit());
555 }
556
557 if (isSubclass(descriptor, builtIns.getList())) {
558 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getList(), 0);
559
560 generateMethodStub("set", "(ILjava/lang/Object;)Ljava/lang/Object;", classifier, builtIns.getInt(), classifier);
561 generateMethodStub("add", "(ILjava/lang/Object;)V", builtIns.getUnit(), builtIns.getInt(), classifier);
562 generateMethodStub("remove", "(I)Ljava/lang/Object;", classifier, builtIns.getInt());
563 }
564
565 if (isSubclass(descriptor, builtIns.getMap())) {
566 ClassifierDescriptor keyClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 0);
567 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 1);
568
569 generateMethodStub("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, keyClassifier,
570 valueClassifier);
571 generateMethodStub("remove", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, builtIns.getAny());
572 generateMethodStub("putAll", "(Ljava/util/Map;)V", builtIns.getUnit(), builtIns.getMap());
573 generateMethodStub("clear", "()V", builtIns.getUnit());
574 }
575
576 if (isSubclass(descriptor, builtIns.getMapEntry())) {
577 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMapEntry(), 1);
578
579 generateMethodStub("setValue", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, valueClassifier);
580 }
581
582 if (isSubclass(descriptor, builtIns.getIterator())) {
583 generateMethodStub("remove", "()V", builtIns.getUnit());
584 }
585 }
586
587 @NotNull
588 private ClassifierDescriptor getSubstituteForTypeParameterOf(@NotNull ClassDescriptor trait, int index) {
589 TypeParameterDescriptor listTypeParameter = trait.getTypeConstructor().getParameters().get(index);
590 TypeSubstitutor deepSubstitutor = SubstitutionUtils.buildDeepSubstitutor(descriptor.getDefaultType());
591 TypeProjection substitute = deepSubstitutor.substitute(new TypeProjectionImpl(listTypeParameter.getDefaultType()));
592 assert substitute != null : "Couldn't substitute: " + descriptor;
593 ClassifierDescriptor classifier = substitute.getType().getConstructor().getDeclarationDescriptor();
594 assert classifier != null : "No classifier: " + substitute.getType();
595 return classifier;
596 }
597
598 private void generateFunctionsForDataClasses() {
599 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return;
600
601 new DataClassMethodGeneratorImpl(myClass, bindingContext).generate();
602 }
603
604 private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator {
605 DataClassMethodGeneratorImpl(
606 JetClassOrObject klass,
607 BindingContext bindingContext
608 ) {
609 super(klass, bindingContext);
610 }
611
612 @Override
613 public void generateEqualsMethod(@NotNull List<PropertyDescriptor> properties) {
614 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
615 InstructionAdapter iv = new InstructionAdapter(mv);
616
617 mv.visitCode();
618 Label eq = new Label();
619 Label ne = new Label();
620
621 iv.load(0, OBJECT_TYPE);
622 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
623 iv.ifacmpeq(eq);
624
625 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
626 iv.instanceOf(classAsmType);
627 iv.ifeq(ne);
628
629 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
630 iv.checkcast(classAsmType);
631 iv.store(2, AsmTypeConstants.OBJECT_TYPE);
632
633 for (PropertyDescriptor propertyDescriptor : properties) {
634 Type asmType = typeMapper.mapType(propertyDescriptor);
635
636 genPropertyOnStack(iv, propertyDescriptor, 0);
637 genPropertyOnStack(iv, propertyDescriptor, 2);
638
639 if (asmType.getSort() == Type.ARRAY) {
640 Type elementType = correctElementType(asmType);
641 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
642 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
643 }
644 else {
645 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z");
646 }
647 }
648 else {
649 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType);
650 value.put(Type.BOOLEAN_TYPE, iv);
651 }
652
653 iv.ifeq(ne);
654 }
655
656 iv.mark(eq);
657 iv.iconst(1);
658 iv.areturn(Type.INT_TYPE);
659
660 iv.mark(ne);
661 iv.iconst(0);
662 iv.areturn(Type.INT_TYPE);
663
664 FunctionCodegen.endVisit(mv, "equals", myClass);
665 }
666
667 @Override
668 public void generateHashCodeMethod(@NotNull List<PropertyDescriptor> properties) {
669 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
670 InstructionAdapter iv = new InstructionAdapter(mv);
671
672 mv.visitCode();
673 boolean first = true;
674 for (PropertyDescriptor propertyDescriptor : properties) {
675 if (!first) {
676 iv.iconst(31);
677 iv.mul(Type.INT_TYPE);
678 }
679
680 genPropertyOnStack(iv, propertyDescriptor, 0);
681
682 Label ifNull = null;
683 Type asmType = typeMapper.mapType(propertyDescriptor);
684 if (!isPrimitive(asmType)) {
685 ifNull = new Label();
686 iv.dup();
687 iv.ifnull(ifNull);
688 }
689
690 genHashCode(mv, iv, asmType);
691
692 if (ifNull != null) {
693 Label end = new Label();
694 iv.goTo(end);
695 iv.mark(ifNull);
696 iv.pop();
697 iv.iconst(0);
698 iv.mark(end);
699 }
700
701 if (first) {
702 first = false;
703 }
704 else {
705 iv.add(Type.INT_TYPE);
706 }
707 }
708
709 mv.visitInsn(IRETURN);
710
711 FunctionCodegen.endVisit(mv, "hashCode", myClass);
712 }
713
714 @Override
715 public void generateToStringMethod(@NotNull List<PropertyDescriptor> properties) {
716 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
717 InstructionAdapter iv = new InstructionAdapter(mv);
718
719 mv.visitCode();
720 genStringBuilderConstructor(iv);
721
722 boolean first = true;
723 for (PropertyDescriptor propertyDescriptor : properties) {
724 if (first) {
725 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"=");
726 first = false;
727 }
728 else {
729 iv.aconst(", " + propertyDescriptor.getName().asString()+"=");
730 }
731 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
732
733 Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
734
735 if (type.getSort() == Type.ARRAY) {
736 Type elementType = correctElementType(type);
737 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
738 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;");
739 type = JAVA_STRING_TYPE;
740 }
741 else {
742 if (elementType.getSort() != Type.CHAR) {
743 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;");
744 type = JAVA_STRING_TYPE;
745 }
746 }
747 }
748 genInvokeAppendMethod(iv, type);
749 }
750
751 iv.aconst(")");
752 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
753
754 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
755 iv.areturn(JAVA_STRING_TYPE);
756
757 FunctionCodegen.endVisit(mv, "toString", myClass);
758 }
759
760 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) {
761 iv.load(index, classAsmType);
762 //noinspection ConstantConditions
763 Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod();
764
765 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor());
766 return method.getReturnType();
767 }
768
769 @Override
770 public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
771 functionCodegen.generateMethod(myClass, typeMapper.mapSignature(function), function, new FunctionGenerationStrategy() {
772 @Override
773 public void generateBody(
774 @NotNull MethodVisitor mv,
775 @NotNull JvmMethodSignature signature,
776 @NotNull MethodContext context,
777 @NotNull MemberCodegen<?> parentCodegen
778 ) {
779 Type componentType = signature.getReturnType();
780 InstructionAdapter iv = new InstructionAdapter(mv);
781 if (!componentType.equals(Type.VOID_TYPE)) {
782 iv.load(0, classAsmType);
783 String desc = "()" + componentType.getDescriptor();
784 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc);
785 }
786 iv.areturn(componentType);
787 }
788 });
789 }
790
791 @Override
792 public void generateCopyFunction(@NotNull final FunctionDescriptor function, @NotNull List<JetParameter> constructorParameters) {
793 JvmMethodSignature methodSignature = typeMapper.mapSignature(function);
794
795 final Type thisDescriptorType = typeMapper.mapType(descriptor);
796
797 functionCodegen.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() {
798 @Override
799 public void generateBody(
800 @NotNull MethodVisitor mv,
801 @NotNull JvmMethodSignature signature,
802 @NotNull MethodContext context,
803 @NotNull MemberCodegen<?> parentCodegen
804 ) {
805 InstructionAdapter iv = new InstructionAdapter(mv);
806
807 iv.anew(thisDescriptorType);
808 iv.dup();
809
810 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor);
811 assert function.getValueParameters().size() == constructor.getValueParameters().size() :
812 "Number of parameters of copy function and constructor are different. " +
813 "Copy: " + function.getValueParameters().size() + ", " +
814 "constructor: " + constructor.getValueParameters().size();
815
816 MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
817 if (closure != null && closure.getCaptureThis() != null) {
818 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor));
819 iv.load(0, classAsmType);
820 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
821 }
822
823 int parameterIndex = 1; // localVariable 0 = this
824 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
825 Type type = typeMapper.mapType(parameterDescriptor.getType());
826 iv.load(parameterIndex, type);
827 parameterIndex += type.getSize();
828 }
829
830 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getAsmMethod().getDescriptor();
831 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor);
832
833 iv.areturn(thisDescriptorType);
834 }
835 });
836
837 functionCodegen.generateDefaultIfNeeded(
838 context.intoFunction(function), methodSignature, function, OwnerKind.IMPLEMENTATION,
839 new DefaultParameterValueLoader() {
840 @Override
841 public void putValueOnStack(ValueParameterDescriptor valueParameter, ExpressionCodegen codegen) {
842 assert KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration())
843 : "Function container should be annotated with [data]: " + function;
844 PropertyDescriptor property = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter);
845 assert property != null : "Copy function doesn't correspond to any property: " + function;
846 codegen.v.load(0, thisDescriptorType);
847 Type propertyType = typeMapper.mapType(property);
848 codegen.intermediateValueForProperty(property, false, null).put(propertyType, codegen.v);
849 }
850 },
851 null
852 );
853 }
854 }
855
856 private void generateEnumMethodsAndConstInitializers() {
857 if (isEnumClass(descriptor)) {
858 generateEnumValuesMethod();
859 generateEnumValueOfMethod();
860 initializeEnumConstants();
861 }
862 }
863
864 private void generateEnumValuesMethod() {
865 Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
866
867 MethodVisitor mv = v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null);
868 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
869
870 mv.visitCode();
871 mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), VALUES, type.getDescriptor());
872 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false);
873 mv.visitTypeInsn(CHECKCAST, type.getInternalName());
874 mv.visitInsn(ARETURN);
875 FunctionCodegen.endVisit(mv, "values()", myClass);
876 }
877
878 private void generateEnumValueOfMethod() {
879 MethodVisitor mv =
880 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
881 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
882
883 mv.visitCode();
884 mv.visitLdcInsn(classAsmType);
885 mv.visitVarInsn(ALOAD, 0);
886 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
887 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName());
888 mv.visitInsn(ARETURN);
889 FunctionCodegen.endVisit(mv, "valueOf()", myClass);
890 }
891
892 protected void generateSyntheticAccessors() {
893 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors();
894 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
895 generateSyntheticAccessor(entry);
896 }
897 }
898
899 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
900 if (entry.getValue() instanceof FunctionDescriptor) {
901 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
902 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
903 functionCodegen.generateMethod(
904 null, typeMapper.mapSignature(bridge), bridge,
905 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) {
906 @Override
907 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
908 generateMethodCallTo(original, codegen.v);
909 codegen.v.areturn(signature.getReturnType());
910 }
911 }
912 );
913 }
914 else if (entry.getValue() instanceof PropertyDescriptor) {
915 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
916 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
917
918 PropertyGetterDescriptor getter = bridge.getGetter();
919 assert getter != null;
920 functionCodegen.generateMethod(null, typeMapper.mapSignature(getter), getter,
921 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
922 @Override
923 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
924 InstructionAdapter iv = codegen.v;
925 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
926 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
927
928 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
929 for (int i = 0, reg = 0; i < argTypes.length; i++) {
930 Type argType = argTypes[i];
931 iv.load(reg, argType);
932 //noinspection AssignmentToForLoopParameter
933 reg += argType.getSize();
934 }
935
936 property.put(property.type, iv);
937 iv.areturn(signature.getReturnType());
938 }
939 });
940
941
942 if (bridge.isVar()) {
943 PropertySetterDescriptor setter = bridge.getSetter();
944 assert setter != null;
945
946 functionCodegen.generateMethod(null, typeMapper.mapSignature(setter), setter,
947 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
948 @Override
949 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
950 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
951 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
952 InstructionAdapter iv = codegen.v;
953
954 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
955 for (int i = 0, reg = 0; i < argTypes.length; i++) {
956 Type argType = argTypes[i];
957 iv.load(reg, argType);
958 //noinspection AssignmentToForLoopParameter
959 reg += argType.getSize();
960 }
961 property.store(property.type, iv);
962
963 iv.areturn(signature.getReturnType());
964 }
965 });
966 }
967 }
968 else {
969 throw new UnsupportedOperationException();
970 }
971 }
972
973 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) {
974 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
975 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor);
976 CallableMethod callableMethod = isConstructor ?
977 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
978 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context);
979
980 int reg = 1;
981 if (isConstructor) {
982 iv.anew(callableMethod.getOwner());
983 iv.dup();
984 reg = 0;
985 }
986 else if (callFromAccessor) {
987 iv.load(0, OBJECT_TYPE);
988 }
989
990 for (Type argType : callableMethod.getAsmMethod().getArgumentTypes()) {
991 iv.load(reg, argType);
992 reg += argType.getSize();
993 }
994 callableMethod.invokeWithoutAssertions(iv);
995 }
996
997 private void generateFieldForSingleton() {
998 if (isEnumClass(descriptor) || isEnumEntry(descriptor)) return;
999
1000 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
1001 ClassDescriptor fieldTypeDescriptor;
1002 JetClassOrObject original;
1003 if (isObject(descriptor)) {
1004 original = myClass;
1005 fieldTypeDescriptor = descriptor;
1006 }
1007 else if (classObjectDescriptor != null) {
1008 JetClassObject classObject = ((JetClass) myClass).getClassObject();
1009 assert classObject != null : "Class object not found: " + myClass.getText();
1010 original = classObject.getObjectDeclaration();
1011 fieldTypeDescriptor = classObjectDescriptor;
1012 }
1013 else {
1014 return;
1015 }
1016
1017 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
1018
1019 v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
1020
1021 if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
1022 genInitSingleton(fieldTypeDescriptor, field);
1023 }
1024 }
1025
1026 private void generateClassObjectBackingFieldCopies() {
1027 if (classObjectPropertiesToCopy == null) return;
1028
1029 for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) {
1030 PropertyDescriptor property = info.descriptor;
1031
1032 FieldVisitor fv = v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false),
1033 typeMapper.mapType(property).getDescriptor(), null, info.defaultValue);
1034
1035 AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property);
1036
1037 //This field are always static and final so if it has constant initializer don't do anything in clinit,
1038 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
1039 // TODO: test this code
1040 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && info.defaultValue == null) {
1041 ExpressionCodegen codegen = createOrGetClInitCodegen();
1042 int classObjectIndex = putClassObjectInLocalVar(codegen);
1043 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
1044 copyFieldFromClassObject(property);
1045 }
1046 }
1047 }
1048
1049 private int putClassObjectInLocalVar(ExpressionCodegen codegen) {
1050 FrameMap frameMap = codegen.myFrameMap;
1051 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
1052 int classObjectIndex = frameMap.getIndex(classObjectDescriptor);
1053 if (classObjectIndex == -1) {
1054 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
1055 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
1056 classObject.put(classObject.type, codegen.v);
1057 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
1058 }
1059 return classObjectIndex;
1060 }
1061
1062 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
1063 ExpressionCodegen codegen = createOrGetClInitCodegen();
1064 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
1065 property.put(property.type, codegen.v);
1066 StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true);
1067 field.store(field.type, codegen.v);
1068 }
1069
1070 protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
1071 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1072 ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
1073 ExpressionCodegen codegen = createOrGetClInitCodegen();
1074 FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor);
1075 generateMethodCallTo(fd, codegen.v);
1076 field.store(field.type, codegen.v);
1077 }
1078 }
1079
1080 protected void generatePrimaryConstructor() {
1081 if (ignoreIfTraitOrAnnotation()) return;
1082
1083 if (kind != OwnerKind.IMPLEMENTATION) {
1084 throw new IllegalStateException("incorrect kind for primary constructor: " + kind);
1085 }
1086
1087 final MutableClosure closure = context.closure;
1088 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
1089
1090 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, closure);
1091
1092 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1093 lookupConstructorExpressionsInClosureIfPresent(constructorContext);
1094 }
1095
1096 assert constructorDescriptor != null : "Constructor not found for class: " + descriptor;
1097 final JvmMethodSignature constructorSignature = typeMapper.mapSignature(constructorDescriptor);
1098
1099 functionCodegen.generateMethod(myClass, constructorSignature, constructorDescriptor, constructorContext,
1100 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
1101 @NotNull
1102 @Override
1103 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
1104 return new ConstructorFrameMap(constructorSignature);
1105 }
1106
1107 @Override
1108 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1109 generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
1110 }
1111 }
1112 );
1113
1114 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorSignature, constructorDescriptor,
1115 OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT, null);
1116
1117 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor);
1118 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
1119
1120 if (isClassObject(descriptor)) {
1121 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
1122 }
1123 }
1124
1125 private void generatePrimaryConstructorImpl(
1126 @Nullable ConstructorDescriptor constructorDescriptor,
1127 @NotNull final ExpressionCodegen codegen,
1128 @Nullable MutableClosure closure
1129 ) {
1130 List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
1131 ? constructorDescriptor.getValueParameters()
1132 : Collections.<ValueParameterDescriptor>emptyList();
1133
1134 InstructionAdapter iv = codegen.v;
1135
1136 if (closure != null) {
1137 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
1138 int k = 1;
1139 for (FieldInfo info : argsFromClosure) {
1140 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
1141 }
1142 }
1143
1144 if (superCall == null) {
1145 genSimpleSuperCall(iv);
1146 }
1147 else if (superCall instanceof JetDelegatorToSuperClass) {
1148 genSuperCallToDelegatorToSuperClass(iv);
1149 }
1150 else {
1151 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
1152 }
1153
1154 int n = 0;
1155 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1156 if (specifier == superCall) {
1157 continue;
1158 }
1159
1160 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1161 genCallToDelegatorByExpressionSpecifier(iv, codegen, n++, specifier);
1162 }
1163 }
1164
1165 int curParam = 0;
1166 List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
1167 for (JetParameter parameter : constructorParameters) {
1168 if (parameter.hasValOrVarNode()) {
1169 VariableDescriptor descriptor = paramDescrs.get(curParam);
1170 Type type = typeMapper.mapType(descriptor);
1171 iv.load(0, classAsmType);
1172 iv.load(codegen.myFrameMap.getIndex(descriptor), type);
1173 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
1174 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
1175 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor, false), type.getDescriptor());
1176 }
1177 curParam++;
1178 }
1179
1180 boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor);
1181 if (generateInitializerInOuter) {
1182 final ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this);
1183 //generate object$
1184 parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper));
1185 generateInitializers(new Function0<ExpressionCodegen>() {
1186 @Override
1187 public ExpressionCodegen invoke() {
1188 return parentCodegen.createOrGetClInitCodegen();
1189 }
1190 });
1191 } else {
1192 generateInitializers(new Function0<ExpressionCodegen>() {
1193 @Override
1194 public ExpressionCodegen invoke() {
1195 return codegen;
1196 }
1197 });
1198 }
1199
1200 iv.visitInsn(RETURN);
1201 }
1202
1203 private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) {
1204 iv.load(0, superClassAsmType);
1205 JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
1206 List<Type> parameterTypes = new ArrayList<Type>();
1207 assert superType != null;
1208 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1209 if (CodegenBinding.hasThis0(bindingContext, superClassDescriptor)) {
1210 iv.load(1, OBJECT_TYPE);
1211 parameterTypes.add(typeMapper.mapType(
1212 enclosingClassDescriptor(bindingContext, descriptor)));
1213 }
1214 Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
1215 //noinspection ConstantConditions
1216 iv.invokespecial(typeMapper.mapType(superClassDescriptor).getInternalName(), "<init>",
1217 superCallMethod.getDescriptor());
1218 }
1219
1220 private void genSimpleSuperCall(InstructionAdapter iv) {
1221 iv.load(0, superClassAsmType);
1222 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
1223 iv.load(1, JAVA_STRING_TYPE);
1224 iv.load(2, Type.INT_TYPE);
1225 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V");
1226 }
1227 else {
1228 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V");
1229 }
1230 }
1231
1232 private void genCallToDelegatorByExpressionSpecifier(
1233 InstructionAdapter iv,
1234 ExpressionCodegen codegen,
1235 int n,
1236 JetDelegationSpecifier specifier
1237 ) {
1238 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1239 PropertyDescriptor propertyDescriptor = null;
1240 if (expression instanceof JetSimpleNameExpression) {
1241 ResolvedCall<?> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression);
1242 if (call != null) {
1243 CallableDescriptor callResultingDescriptor = call.getResultingDescriptor();
1244 if (callResultingDescriptor instanceof ValueParameterDescriptor) {
1245 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor;
1246 // constructor parameter
1247 if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
1248 // constructor of my class
1249 if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == descriptor) {
1250 propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor);
1251 }
1252 }
1253 }
1254
1255 // todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier
1256 }
1257 }
1258
1259 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
1260 assert superType != null;
1261
1262 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1263 assert superClassDescriptor != null;
1264
1265 StackValue field;
1266 if (propertyDescriptor != null &&
1267 !propertyDescriptor.isVar() &&
1268 Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) {
1269 // final property with backing field
1270 field = StackValue.field(typeMapper.mapType(propertyDescriptor), classAsmType, propertyDescriptor.getName().asString(), false);
1271 }
1272 else {
1273 iv.load(0, classAsmType);
1274 codegen.genToJVMStack(expression);
1275
1276 String delegateField = "$delegate_" + n;
1277 Type fieldType = typeMapper.mapType(superClassDescriptor);
1278 String fieldDesc = fieldType.getDescriptor();
1279
1280 v.newField(specifier, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, delegateField, fieldDesc, /*TODO*/null, null);
1281
1282 field = StackValue.field(fieldType, classAsmType, delegateField, false);
1283 field.store(fieldType, iv);
1284 }
1285
1286 generateDelegates(superClassDescriptor, field);
1287 }
1288
1289 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) {
1290 JetVisitorVoid visitor = new JetVisitorVoid() {
1291 @Override
1292 public void visitJetElement(@NotNull JetElement e) {
1293 e.acceptChildren(this);
1294 }
1295
1296 @Override
1297 public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expr) {
1298 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
1299
1300 DeclarationDescriptor toLookup;
1301 if (isLocalNamedFun(descriptor)) {
1302 toLookup = descriptor;
1303 }
1304 else if (descriptor instanceof CallableMemberDescriptor) {
1305 toLookup = descriptor.getContainingDeclaration();
1306 }
1307 else if (descriptor instanceof VariableDescriptor) {
1308 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor();
1309 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
1310 if (descriptor.equals(parameterDescriptor)) return;
1311 }
1312 toLookup = descriptor;
1313 }
1314 else return;
1315
1316 constructorContext.lookupInContext(toLookup, null, state, true);
1317 }
1318
1319 @Override
1320 public void visitThisExpression(@NotNull JetThisExpression expression) {
1321 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
1322 assert descriptor instanceof CallableDescriptor ||
1323 descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor;
1324 if (context.getCallableDescriptorWithReceiver() != descriptor) {
1325 context.lookupInContext(descriptor, null, state, true);
1326 }
1327 }
1328 };
1329
1330 for (JetDeclaration declaration : myClass.getDeclarations()) {
1331 if (declaration instanceof JetProperty) {
1332 JetProperty property = (JetProperty) declaration;
1333 JetExpression initializer = property.getInitializer();
1334 if (initializer != null) {
1335 initializer.accept(visitor);
1336 }
1337 }
1338 else if (declaration instanceof JetClassInitializer) {
1339 JetClassInitializer initializer = (JetClassInitializer) declaration;
1340 initializer.accept(visitor);
1341 }
1342 }
1343
1344 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1345 if (specifier != superCall) {
1346 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1347 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1348 assert delegateExpression != null;
1349 delegateExpression.accept(visitor);
1350 }
1351 }
1352 else {
1353 if (superCall instanceof JetDelegatorToSuperCall) {
1354 JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList();
1355 if (argumentList != null) {
1356 argumentList.accept(visitor);
1357 }
1358 }
1359 }
1360 }
1361 }
1362
1363 private boolean ignoreIfTraitOrAnnotation() {
1364 if (myClass instanceof JetClass) {
1365 JetClass aClass = (JetClass) myClass;
1366 if (aClass.isTrait()) {
1367 return true;
1368 }
1369 if (aClass.isAnnotation()) {
1370 return true;
1371 }
1372 }
1373 return false;
1374 }
1375
1376 private void generateTraitMethods() {
1377 if (JetPsiUtil.isTrait(myClass)) return;
1378
1379 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1380 if (!(declaration instanceof CallableMemberDescriptor)) continue;
1381
1382 CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
1383 CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember);
1384 if (traitMember == null) continue;
1385
1386 assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
1387
1388 // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
1389 // with traitMember's modality
1390 CallableMemberDescriptor copy =
1391 inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
1392 CallableMemberDescriptor.Kind.DECLARATION, true);
1393
1394 if (traitMember instanceof SimpleFunctionDescriptor) {
1395 generateDelegationToTraitImpl((FunctionDescriptor) traitMember, (FunctionDescriptor) copy);
1396 }
1397 else if (traitMember instanceof PropertyDescriptor) {
1398 for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) {
1399 for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) {
1400 if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind
1401 generateDelegationToTraitImpl(traitAccessor, inheritedAccessor);
1402 }
1403 }
1404 }
1405 }
1406 }
1407 }
1408
1409 private void generateDelegationToTraitImpl(@NotNull final FunctionDescriptor traitFun, @NotNull FunctionDescriptor inheritedFun) {
1410 functionCodegen.generateMethod(
1411 descriptorToDeclaration(bindingContext, traitFun),
1412 typeMapper.mapSignature(inheritedFun),
1413 inheritedFun,
1414 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, inheritedFun) {
1415 @Override
1416 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1417 DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration();
1418 if (!(containingDeclaration instanceof ClassDescriptor)) return;
1419 ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration;
1420 if (containingTrait.getKind() != ClassKind.TRAIT) return;
1421
1422 Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal()).getAsmMethod();
1423
1424 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
1425 Type[] originalArgTypes = traitMethod.getArgumentTypes();
1426
1427 InstructionAdapter iv = codegen.v;
1428 iv.load(0, OBJECT_TYPE);
1429 for (int i = 0, reg = 1; i < argTypes.length; i++) {
1430 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
1431 //noinspection AssignmentToForLoopParameter
1432 reg += argTypes[i].getSize();
1433 }
1434
1435 Type type = getTraitImplThisParameterType(containingTrait, typeMapper);
1436 String desc = traitMethod.getDescriptor().replace("(", "(" + type.getDescriptor());
1437
1438 iv.invokestatic(typeMapper.mapTraitImpl(containingTrait).getInternalName(), traitMethod.getName(), desc);
1439
1440 Type returnType = signature.getReturnType();
1441 StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv);
1442 iv.areturn(returnType);
1443 }
1444 }
1445 );
1446 }
1447
1448 private void generateDelegatorToConstructorCall(
1449 InstructionAdapter iv, ExpressionCodegen codegen,
1450 ConstructorDescriptor constructorDescriptor
1451 ) {
1452 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
1453
1454 iv.load(0, OBJECT_TYPE);
1455
1456 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
1457 iv.load(1, OBJECT_TYPE);
1458 iv.load(2, Type.INT_TYPE);
1459 }
1460
1461 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor);
1462
1463 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression());
1464 assert resolvedCall != null;
1465 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
1466
1467 //noinspection SuspiciousMethodCalls
1468 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration());
1469 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) {
1470 iv.load(((ConstructorFrameMap) codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE);
1471 }
1472
1473 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
1474
1475 if (isAnonymousObject(descriptor) && superCall instanceof JetDelegatorToSuperCall) {
1476 int nextVar = findFirstSuperArgument(method);
1477 for (Type t : superCallable.getAsmMethod().getArgumentTypes()) {
1478 iv.load(nextVar, t);
1479 nextVar += t.getSize();
1480 }
1481 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall);
1482 }
1483 else {
1484 codegen.invokeMethodWithArguments(null, superCallable, resolvedCall, StackValue.none());
1485 }
1486 }
1487
1488 private static int findFirstSuperArgument(@NotNull CallableMethod method) {
1489 int i = 0;
1490 for (JvmMethodParameterSignature type : method.getValueParameters()) {
1491 if (type.getKind() == JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM) {
1492 return i + 1; // because of this
1493 }
1494 i += type.getAsmType().getSize();
1495 }
1496 return -1;
1497 }
1498
1499 @Override
1500 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
1501 if (declaration instanceof JetEnumEntry) {
1502 String name = declaration.getName();
1503 assert name != null : "Enum entry has no name: " + declaration.getText();
1504 String desc = "L" + classAsmType.getInternalName() + ";";
1505 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
1506 myEnumConstants.add((JetEnumEntry) declaration);
1507 }
1508
1509 super.generateDeclaration(propertyCodegen, declaration);
1510 }
1511
1512 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
1513
1514 private void initializeEnumConstants() {
1515 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
1516
1517 ExpressionCodegen codegen = createOrGetClInitCodegen();
1518 InstructionAdapter iv = codegen.v;
1519
1520 Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
1521 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, VALUES, arrayAsmType.getDescriptor(), null, null);
1522
1523 iv.iconst(myEnumConstants.size());
1524 iv.newarray(classAsmType);
1525
1526 if (!myEnumConstants.isEmpty()) {
1527 iv.dup();
1528 for (int ordinal = 0, size = myEnumConstants.size(); ordinal < size; ordinal++) {
1529 initializeEnumConstant(codegen, ordinal);
1530 }
1531 }
1532
1533 iv.putstatic(classAsmType.getInternalName(), VALUES, arrayAsmType.getDescriptor());
1534 }
1535
1536 private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) {
1537 InstructionAdapter iv = codegen.v;
1538 JetEnumEntry enumConstant = myEnumConstants.get(ordinal);
1539
1540 iv.dup();
1541 iv.iconst(ordinal);
1542
1543 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant);
1544 assert classDescriptor != null;
1545 Type implClass = typeMapper.mapClass(classDescriptor);
1546
1547 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
1548 if (delegationSpecifiers.size() > 1) {
1549 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
1550 }
1551
1552 iv.anew(implClass);
1553 iv.dup();
1554
1555 iv.aconst(enumConstant.getName());
1556 iv.iconst(ordinal);
1557
1558 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) {
1559 JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
1560 if (!(specifier instanceof JetDelegatorToSuperCall)) {
1561 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
1562 }
1563
1564 ResolvedCall<?> resolvedCall =
1565 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression());
1566 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText();
1567
1568 CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor());
1569
1570 codegen.invokeMethodWithArguments(null, method, resolvedCall, StackValue.none());
1571 }
1572 else {
1573 iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V");
1574 }
1575
1576 iv.dup();
1577 iv.putstatic(classAsmType.getInternalName(), enumConstant.getName(), classAsmType.getDescriptor());
1578 iv.astore(OBJECT_TYPE);
1579 }
1580
1581 protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
1582 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1583 if (declaration instanceof CallableMemberDescriptor) {
1584 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
1585 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
1586 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
1587 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
1588 if (overriddenDescriptor.getContainingDeclaration() == toClass) {
1589 if (declaration instanceof PropertyDescriptor) {
1590 propertyCodegen
1591 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
1592 }
1593 else if (declaration instanceof FunctionDescriptor) {
1594 functionCodegen
1595 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field);
1596 }
1597 }
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) {
1605 if (classObjectPropertiesToCopy == null) {
1606 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>();
1607 }
1608 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue));
1609 }
1610
1611 private static class PropertyAndDefaultValue {
1612 public final PropertyDescriptor descriptor;
1613 public final Object defaultValue;
1614
1615 public PropertyAndDefaultValue(PropertyDescriptor descriptor, Object defaultValue) {
1616 this.descriptor = descriptor;
1617 this.defaultValue = defaultValue;
1618 }
1619 }
1620 }