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