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