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