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