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