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