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