001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Sets; 021 import com.intellij.openapi.progress.ProcessCanceledException; 022 import com.intellij.openapi.util.Pair; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.util.ArrayUtil; 025 import org.jetbrains.annotations.NotNull; 026 import org.jetbrains.annotations.Nullable; 027 import org.jetbrains.asm4.AnnotationVisitor; 028 import org.jetbrains.asm4.Label; 029 import org.jetbrains.asm4.MethodVisitor; 030 import org.jetbrains.asm4.Type; 031 import org.jetbrains.asm4.commons.InstructionAdapter; 032 import org.jetbrains.asm4.commons.Method; 033 import org.jetbrains.jet.codegen.binding.CalculatedClosure; 034 import org.jetbrains.jet.codegen.binding.CodegenBinding; 035 import org.jetbrains.jet.codegen.binding.MutableClosure; 036 import org.jetbrains.jet.codegen.context.ClassContext; 037 import org.jetbrains.jet.codegen.context.ConstructorContext; 038 import org.jetbrains.jet.codegen.context.MethodContext; 039 import org.jetbrains.jet.codegen.signature.*; 040 import org.jetbrains.jet.codegen.state.GenerationState; 041 import org.jetbrains.jet.codegen.state.JetTypeMapper; 042 import org.jetbrains.jet.descriptors.serialization.BitEncoding; 043 import org.jetbrains.jet.descriptors.serialization.ClassData; 044 import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer; 045 import org.jetbrains.jet.descriptors.serialization.ProtoBuf; 046 import org.jetbrains.jet.lang.descriptors.*; 047 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 048 import org.jetbrains.jet.lang.psi.*; 049 import org.jetbrains.jet.lang.resolve.BindingContext; 050 import org.jetbrains.jet.lang.resolve.BindingContextUtils; 051 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 052 import org.jetbrains.jet.lang.resolve.OverridingUtil; 053 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; 054 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 055 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 056 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; 057 import org.jetbrains.jet.lang.resolve.java.JvmAbi; 058 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; 059 import org.jetbrains.jet.lang.resolve.name.Name; 060 import org.jetbrains.jet.lang.types.*; 061 import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 062 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 063 import org.jetbrains.jet.lexer.JetTokens; 064 065 import java.util.*; 066 067 import static org.jetbrains.asm4.Opcodes.*; 068 import static org.jetbrains.jet.codegen.AsmUtil.*; 069 import static org.jetbrains.jet.codegen.CodegenUtil.*; 070 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; 071 import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; 072 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; 073 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; 074 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 075 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; 076 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; 077 078 public class ImplementationBodyCodegen extends ClassBodyCodegen { 079 private static final String VALUES = "$VALUES"; 080 private JetDelegationSpecifier superCall; 081 private Type superClassAsmType; 082 @Nullable // null means java/lang/Object 083 private JetType superClassType; 084 private final Type classAsmType; 085 086 private final FunctionCodegen functionCodegen; 087 private final PropertyCodegen propertyCodegen; 088 089 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy; 090 091 public ImplementationBodyCodegen( 092 @NotNull JetClassOrObject aClass, 093 @NotNull ClassContext context, 094 @NotNull ClassBuilder v, 095 @NotNull GenerationState state, 096 @Nullable MemberCodegen parentCodegen 097 ) { 098 super(aClass, context, v, state, parentCodegen); 099 this.classAsmType = typeMapper.mapClass(descriptor); 100 this.functionCodegen = new FunctionCodegen(context, v, state, this); 101 this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this); 102 } 103 104 @Override 105 protected void generateDeclaration() { 106 getSuperClass(); 107 108 JvmClassSignature signature = signature(); 109 110 boolean isAbstract = false; 111 boolean isInterface = false; 112 boolean isFinal = false; 113 boolean isStatic; 114 boolean isAnnotation = false; 115 boolean isEnum = false; 116 117 if (myClass instanceof JetClass) { 118 JetClass jetClass = (JetClass) myClass; 119 if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { 120 isAbstract = true; 121 } 122 if (jetClass.isTrait()) { 123 isAbstract = true; 124 isInterface = true; 125 } 126 else if (jetClass.isAnnotation()) { 127 isAbstract = true; 128 isInterface = true; 129 isAnnotation = true; 130 signature.getInterfaces().add("java/lang/annotation/Annotation"); 131 } 132 else if (jetClass.isEnum()) { 133 isAbstract = hasAbstractMembers(descriptor); 134 isEnum = true; 135 } 136 137 if (descriptor.getKind() == ClassKind.OBJECT || descriptor.getKind() == ClassKind.CLASS_OBJECT) { 138 isFinal = true; 139 } 140 141 if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) { 142 isFinal = true; 143 } 144 isStatic = !jetClass.isInner(); 145 } 146 else { 147 isStatic = myClass.getParent() instanceof JetClassObject; 148 isFinal = true; 149 } 150 151 int access = 0; 152 153 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) { 154 // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class 155 // Light class generation is implemented so that Cls-classes only read bare code of classes, 156 // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY) 157 // Thus we must write full accessibility flags on inner classes in this mode 158 access |= getVisibilityAccessFlag(descriptor); 159 // Same for STATIC 160 if (isStatic) { 161 access |= ACC_STATIC; 162 } 163 } 164 else { 165 access |= getVisibilityAccessFlagForClass(descriptor); 166 } 167 if (isAbstract) { 168 access |= ACC_ABSTRACT; 169 } 170 if (isInterface) { 171 access |= ACC_INTERFACE; // ACC_SUPER 172 } 173 else { 174 access |= ACC_SUPER; 175 } 176 if (isFinal) { 177 access |= ACC_FINAL; 178 } 179 if (isAnnotation) { 180 access |= ACC_ANNOTATION; 181 } 182 if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) { 183 access |= ACC_DEPRECATED; 184 } 185 if (isEnum) { 186 for (JetDeclaration declaration : myClass.getDeclarations()) { 187 if (declaration instanceof JetEnumEntry) { 188 if (enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) { 189 access &= ~ACC_FINAL; 190 } 191 } 192 } 193 access |= ACC_ENUM; 194 } 195 List<String> interfaces = signature.getInterfaces(); 196 v.defineClass(myClass, V1_6, 197 access, 198 signature.getName(), 199 signature.getJavaGenericSignature(), 200 signature.getSuperclassName(), 201 ArrayUtil.toStringArray(interfaces) 202 ); 203 v.visitSource(myClass.getContainingFile().getName(), null); 204 205 writeEnclosingMethod(); 206 207 writeOuterClasses(); 208 209 writeInnerClasses(); 210 211 AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor); 212 } 213 214 @Override 215 protected void generateKotlinAnnotation() { 216 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings())); 217 218 ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); 219 220 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto); 221 222 AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true); 223 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); 224 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); 225 for (String string : BitEncoding.encodeBytes(data.toBytes())) { 226 array.visit(null, string); 227 } 228 array.visitEnd(); 229 av.visitEnd(); 230 } 231 232 private void writeEnclosingMethod() { 233 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class. 234 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); 235 236 boolean isObjectLiteral = DescriptorUtils.isAnonymous(descriptor); 237 238 boolean isLocalOrAnonymousClass = isObjectLiteral || 239 !(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor); 240 if (isLocalOrAnonymousClass) { 241 String outerClassName = getOuterClassName(descriptor, typeMapper); 242 FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class); 243 244 if (function != null) { 245 Method method = typeMapper.mapSignature(function).getAsmMethod(); 246 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor()); 247 } 248 else { 249 assert isObjectLiteral 250 : "Function descriptor could be null only for object literal in package namespace: " + descriptor.getName(); 251 v.visitOuterClass(outerClassName, null, null); 252 } 253 } 254 } 255 256 @NotNull 257 private static String getOuterClassName(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) { 258 ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class); 259 if (container != null) { 260 return typeMapper.mapClass(container).getInternalName(); 261 } 262 263 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), classDescriptor); 264 assert containingFile != null : "Containing file should be present for " + classDescriptor; 265 return NamespaceCodegen.getNamespacePartInternalName(containingFile); 266 } 267 268 private void writeInnerClasses() { 269 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor); 270 if (result != null) { 271 for (ClassDescriptor innerClass : result) { 272 writeInnerClass(innerClass); 273 } 274 } 275 } 276 277 private void writeOuterClasses() { 278 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information 279 // for each enclosing class and for each immediate member 280 DeclarationDescriptor inner = descriptor; 281 while (true) { 282 if (inner == null || isTopLevelDeclaration(inner)) { 283 break; 284 } 285 if (inner instanceof ClassDescriptor && !isEnumClassObject(inner)) { 286 writeInnerClass((ClassDescriptor) inner); 287 } 288 inner = inner.getContainingDeclaration(); 289 } 290 } 291 292 private void writeInnerClass(@NotNull ClassDescriptor innerClass) { 293 // TODO: proper access 294 int innerClassAccess = getVisibilityAccessFlag(innerClass); 295 if (innerClass.getModality() == Modality.FINAL) { 296 innerClassAccess |= ACC_FINAL; 297 } 298 else if (innerClass.getModality() == Modality.ABSTRACT) { 299 innerClassAccess |= ACC_ABSTRACT; 300 } 301 302 if (innerClass.getKind() == ClassKind.TRAIT) { 303 innerClassAccess |= ACC_INTERFACE; 304 } 305 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) { 306 innerClassAccess |= ACC_ENUM; 307 } 308 309 if (!innerClass.isInner()) { 310 innerClassAccess |= ACC_STATIC; 311 } 312 313 // TODO: cache internal names 314 DeclarationDescriptor containing = innerClass.getContainingDeclaration(); 315 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null; 316 317 String innerClassInternalName; 318 String innerName; 319 320 if (isClassObject(innerClass)) { 321 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME; 322 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX; 323 } 324 else { 325 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); 326 innerClassInternalName = getInternalNameForImpl(innerClass); 327 } 328 329 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess); 330 } 331 332 @NotNull 333 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) { 334 return typeMapper.mapClass(descriptor).getInternalName(); 335 } 336 337 private JvmClassSignature signature() { 338 List<String> superInterfaces; 339 340 LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>(); 341 342 // TODO: generics signature is not always needed 343 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true); 344 345 346 { // type parameters 347 List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters(); 348 typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor); 349 } 350 351 { // superclass 352 signatureVisitor.writeSuperclass(); 353 if (superClassType == null) { 354 signatureVisitor.writeClassBegin(superClassAsmType); 355 signatureVisitor.writeClassEnd(); 356 } 357 else { 358 typeMapper.mapSupertype(superClassType, signatureVisitor); 359 } 360 signatureVisitor.writeSuperclassEnd(); 361 } 362 363 364 { // superinterfaces 365 superInterfacesLinkedHashSet.add(JvmAbi.JET_OBJECT.getInternalName()); 366 367 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 368 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 369 assert superType != null; 370 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 371 if (isInterface(superClassDescriptor)) { 372 signatureVisitor.writeInterface(); 373 Type jvmName = typeMapper.mapSupertype(superType, signatureVisitor); 374 signatureVisitor.writeInterfaceEnd(); 375 superInterfacesLinkedHashSet.add(jvmName.getInternalName()); 376 } 377 } 378 379 superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet); 380 } 381 382 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(), superInterfaces, 383 signatureVisitor.makeJavaGenericSignature()); 384 } 385 386 protected void getSuperClass() { 387 superClassAsmType = AsmTypeConstants.OBJECT_TYPE; 388 superClassType = null; 389 390 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); 391 392 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) { 393 return; 394 } 395 396 if (kind != OwnerKind.IMPLEMENTATION) { 397 throw new IllegalStateException("must be impl to reach this code: " + kind); 398 } 399 400 for (JetDelegationSpecifier specifier : delegationSpecifiers) { 401 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) { 402 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 403 assert superType != null; 404 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 405 assert superClassDescriptor != null; 406 if (!isInterface(superClassDescriptor)) { 407 superClassType = superType; 408 superClassAsmType = typeMapper.mapClass(superClassDescriptor); 409 superCall = specifier; 410 } 411 } 412 } 413 414 if (superClassType == null) { 415 if (descriptor.getKind() == ClassKind.ENUM_CLASS) { 416 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType()); 417 superClassAsmType = typeMapper.mapType(superClassType); 418 } 419 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) { 420 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next(); 421 superClassAsmType = typeMapper.mapType(superClassType); 422 } 423 } 424 } 425 426 @Override 427 protected void generateSyntheticParts() { 428 generateFieldForSingleton(); 429 430 generateClassObjectBackingFieldCopies(); 431 432 try { 433 generatePrimaryConstructor(); 434 } 435 catch (CompilationException e) { 436 throw e; 437 } 438 catch (ProcessCanceledException e) { 439 throw e; 440 } 441 catch (RuntimeException e) { 442 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e); 443 } 444 445 generateTraitMethods(); 446 447 generateSyntheticAccessors(); 448 449 generateEnumMethodsAndConstInitializers(); 450 451 generateFunctionsForDataClasses(); 452 453 generateBuiltinMethodStubs(); 454 455 generateToArray(); 456 457 genClosureFields(context.closure, v, state.getTypeMapper()); 458 } 459 460 private boolean isGenericToArrayPresent() { 461 Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray")); 462 for (FunctionDescriptor function : functions) { 463 if (CallResolverUtil.isOrOverridesSynthesized(function)) { 464 continue; 465 } 466 467 if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { 468 continue; 469 } 470 471 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(function.getTypeParameters().get(0).getDefaultType()); 472 JetType returnType = function.getReturnType(); 473 assert returnType != null : function.toString(); 474 JetType paramType = function.getValueParameters().get(0).getType(); 475 if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) { 476 return true; 477 } 478 } 479 return false; 480 481 } 482 483 private void generateToArray() { 484 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 485 if (isSubclass(descriptor, builtIns.getCollection())) { 486 if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) { 487 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null); 488 InstructionAdapter iv = new InstructionAdapter(mv); 489 490 mv.visitCode(); 491 492 iv.load(0, classAsmType); 493 iv.invokestatic("jet/runtime/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;"); 494 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 495 496 FunctionCodegen.endVisit(mv, "toArray", myClass); 497 } 498 499 if (!isGenericToArrayPresent()) { 500 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); 501 InstructionAdapter iv = new InstructionAdapter(mv); 502 503 mv.visitCode(); 504 505 iv.load(0, classAsmType); 506 iv.load(1, Type.getObjectType("[Ljava/lang/Object;")); 507 508 iv.invokestatic("jet/runtime/CollectionToArray", "toArray", "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;"); 509 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 510 511 FunctionCodegen.endVisit(mv, "toArray", myClass); 512 } 513 } 514 } 515 516 private void generateMethodStub( 517 @NotNull String name, 518 @NotNull String desc, 519 @NotNull ClassifierDescriptor returnedClassifier, 520 @NotNull ClassifierDescriptor... valueParameterClassifiers 521 ) { 522 if (CodegenUtil.getDeclaredFunctionByRawSignature( 523 descriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers) == null) { 524 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, name, desc, null, null); 525 AsmUtil.genMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating immutable collection"); 526 } 527 } 528 529 private void generateBuiltinMethodStubs() { 530 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 531 if (isSubclass(descriptor, builtIns.getCollection())) { 532 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getCollection(), 0); 533 534 generateMethodStub("add", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), classifier); 535 generateMethodStub("remove", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), builtIns.getAny()); 536 generateMethodStub("addAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 537 generateMethodStub("removeAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 538 generateMethodStub("retainAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 539 generateMethodStub("clear", "()V", builtIns.getUnit()); 540 } 541 542 if (isSubclass(descriptor, builtIns.getList())) { 543 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getList(), 0); 544 545 generateMethodStub("set", "(ILjava/lang/Object;)Ljava/lang/Object;", classifier, builtIns.getInt(), classifier); 546 generateMethodStub("add", "(ILjava/lang/Object;)V", builtIns.getUnit(), builtIns.getInt(), classifier); 547 generateMethodStub("remove", "(I)Ljava/lang/Object;", classifier, builtIns.getInt()); 548 } 549 550 if (isSubclass(descriptor, builtIns.getMap())) { 551 ClassifierDescriptor keyClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 0); 552 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 1); 553 554 generateMethodStub("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, keyClassifier, 555 valueClassifier); 556 generateMethodStub("remove", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, builtIns.getAny()); 557 generateMethodStub("putAll", "(Ljava/util/Map;)V", builtIns.getUnit(), builtIns.getMap()); 558 generateMethodStub("clear", "()V", builtIns.getUnit()); 559 } 560 561 if (isSubclass(descriptor, builtIns.getMapEntry())) { 562 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMapEntry(), 1); 563 564 generateMethodStub("setValue", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, valueClassifier); 565 } 566 567 if (isSubclass(descriptor, builtIns.getIterator())) { 568 generateMethodStub("remove", "()V", builtIns.getUnit()); 569 } 570 } 571 572 @NotNull 573 private ClassifierDescriptor getSubstituteForTypeParameterOf(@NotNull ClassDescriptor trait, int index) { 574 TypeParameterDescriptor listTypeParameter = trait.getTypeConstructor().getParameters().get(index); 575 TypeSubstitutor deepSubstitutor = SubstitutionUtils.buildDeepSubstitutor(descriptor.getDefaultType()); 576 TypeProjection substitute = deepSubstitutor.substitute(new TypeProjectionImpl(listTypeParameter.getDefaultType())); 577 assert substitute != null : "Couldn't substitute: " + descriptor; 578 ClassifierDescriptor classifier = substitute.getType().getConstructor().getDeclarationDescriptor(); 579 assert classifier != null : "No classifier: " + substitute.getType(); 580 return classifier; 581 } 582 583 private List<PropertyDescriptor> getDataProperties() { 584 ArrayList<PropertyDescriptor> result = Lists.newArrayList(); 585 for (JetParameter parameter : getPrimaryConstructorParameters()) { 586 if (parameter.getValOrVarNode() != null) { 587 result.add(bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)); 588 } 589 } 590 return result; 591 } 592 593 private void generateFunctionsForDataClasses() { 594 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return; 595 596 generateComponentFunctionsForDataClasses(); 597 generateCopyFunctionForDataClasses(); 598 599 List<PropertyDescriptor> properties = getDataProperties(); 600 if (!properties.isEmpty()) { 601 generateDataClassToStringIfNeeded(properties); 602 generateDataClassHashCodeIfNeeded(properties); 603 generateDataClassEqualsIfNeeded(properties); 604 } 605 } 606 607 private void generateCopyFunctionForDataClasses() { 608 FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, descriptor); 609 if (copyFunction != null) { 610 generateCopyFunction(copyFunction); 611 } 612 } 613 614 private void generateDataClassToStringIfNeeded(List<PropertyDescriptor> properties) { 615 ClassDescriptor stringClass = KotlinBuiltIns.getInstance().getString(); 616 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toString"), stringClass) == null) { 617 generateDataClassToStringMethod(properties); 618 } 619 } 620 621 private void generateDataClassHashCodeIfNeeded(List<PropertyDescriptor> properties) { 622 ClassDescriptor intClass = KotlinBuiltIns.getInstance().getInt(); 623 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("hashCode"), intClass) == null) { 624 generateDataClassHashCodeMethod(properties); 625 } 626 } 627 628 private void generateDataClassEqualsIfNeeded(List<PropertyDescriptor> properties) { 629 ClassDescriptor booleanClass = KotlinBuiltIns.getInstance().getBoolean(); 630 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny(); 631 FunctionDescriptor equalsFunction = getDeclaredFunctionByRawSignature(descriptor, Name.identifier("equals"), booleanClass, anyClass); 632 if (equalsFunction == null) { 633 generateDataClassEqualsMethod(properties); 634 } 635 } 636 637 private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) { 638 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); 639 InstructionAdapter iv = new InstructionAdapter(mv); 640 641 mv.visitCode(); 642 Label eq = new Label(); 643 Label ne = new Label(); 644 645 iv.load(0, OBJECT_TYPE); 646 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 647 iv.ifacmpeq(eq); 648 649 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 650 iv.instanceOf(classAsmType); 651 iv.ifeq(ne); 652 653 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 654 iv.checkcast(classAsmType); 655 iv.store(2, AsmTypeConstants.OBJECT_TYPE); 656 657 for (PropertyDescriptor propertyDescriptor : properties) { 658 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 659 660 genPropertyOnStack(iv, propertyDescriptor, 0); 661 genPropertyOnStack(iv, propertyDescriptor, 2); 662 663 if (asmType.getSort() == Type.ARRAY) { 664 Type elementType = correctElementType(asmType); 665 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 666 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z"); 667 } 668 else { 669 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z"); 670 } 671 } 672 else { 673 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType); 674 value.put(Type.BOOLEAN_TYPE, iv); 675 } 676 677 iv.ifeq(ne); 678 } 679 680 iv.mark(eq); 681 iv.iconst(1); 682 iv.areturn(Type.INT_TYPE); 683 684 iv.mark(ne); 685 iv.iconst(0); 686 iv.areturn(Type.INT_TYPE); 687 688 FunctionCodegen.endVisit(mv, "equals", myClass); 689 } 690 691 private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) { 692 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null); 693 InstructionAdapter iv = new InstructionAdapter(mv); 694 695 mv.visitCode(); 696 boolean first = true; 697 for (PropertyDescriptor propertyDescriptor : properties) { 698 if (!first) { 699 iv.iconst(31); 700 iv.mul(Type.INT_TYPE); 701 } 702 703 genPropertyOnStack(iv, propertyDescriptor, 0); 704 705 Label ifNull = null; 706 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 707 if (!isPrimitive(asmType)) { 708 ifNull = new Label(); 709 iv.dup(); 710 iv.ifnull(ifNull); 711 } 712 713 genHashCode(mv, iv, asmType); 714 715 if (ifNull != null) { 716 Label end = new Label(); 717 iv.goTo(end); 718 iv.mark(ifNull); 719 iv.pop(); 720 iv.iconst(0); 721 iv.mark(end); 722 } 723 724 if (first) { 725 first = false; 726 } 727 else { 728 iv.add(Type.INT_TYPE); 729 } 730 } 731 732 mv.visitInsn(IRETURN); 733 734 FunctionCodegen.endVisit(mv, "hashCode", myClass); 735 } 736 737 private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) { 738 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); 739 InstructionAdapter iv = new InstructionAdapter(mv); 740 741 mv.visitCode(); 742 genStringBuilderConstructor(iv); 743 744 boolean first = true; 745 for (PropertyDescriptor propertyDescriptor : properties) { 746 if (first) { 747 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"="); 748 first = false; 749 } 750 else { 751 iv.aconst(", " + propertyDescriptor.getName().asString()+"="); 752 } 753 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 754 755 Type type = genPropertyOnStack(iv, propertyDescriptor, 0); 756 757 if (type.getSort() == Type.ARRAY) { 758 Type elementType = correctElementType(type); 759 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 760 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;"); 761 type = JAVA_STRING_TYPE; 762 } 763 else { 764 if (elementType.getSort() != Type.CHAR) { 765 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;"); 766 type = JAVA_STRING_TYPE; 767 } 768 } 769 } 770 genInvokeAppendMethod(iv, type); 771 } 772 773 iv.aconst(")"); 774 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 775 776 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); 777 iv.areturn(JAVA_STRING_TYPE); 778 779 FunctionCodegen.endVisit(mv, "toString", myClass); 780 } 781 782 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) { 783 iv.load(index, classAsmType); 784 Method 785 method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod(); 786 787 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor()); 788 return method.getReturnType(); 789 } 790 791 private void generateComponentFunctionsForDataClasses() { 792 if (!myClass.hasPrimaryConstructor() || !KotlinBuiltIns.getInstance().isData(descriptor)) return; 793 794 ConstructorDescriptor constructor = descriptor.getConstructors().iterator().next(); 795 796 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) { 797 FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter); 798 if (function != null) { 799 generateComponentFunction(function, parameter); 800 } 801 } 802 } 803 804 private void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) { 805 JetType returnType = function.getReturnType(); 806 assert returnType != null : "Return type of component function should not be null: " + function; 807 final Type componentType = typeMapper.mapReturnType(returnType); 808 809 JvmMethodSignature signature = typeMapper.mapSignature(function); 810 811 functionCodegen.generateMethod(myClass, signature, function, new FunctionGenerationStrategy() { 812 @Override 813 public void generateBody( 814 @NotNull MethodVisitor mv, 815 @NotNull JvmMethodSignature signature, 816 @NotNull MethodContext context, 817 @Nullable MemberCodegen parentCodegen 818 ) { 819 InstructionAdapter iv = new InstructionAdapter(mv); 820 if (!componentType.equals(Type.VOID_TYPE)) { 821 iv.load(0, classAsmType); 822 String desc = "()" + componentType.getDescriptor(); 823 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc); 824 } 825 iv.areturn(componentType); 826 } 827 }); 828 } 829 830 private void generateCopyFunction(@NotNull final FunctionDescriptor function) { 831 JvmMethodSignature methodSignature = typeMapper.mapSignature(function); 832 833 final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); 834 835 functionCodegen.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() { 836 @Override 837 public void generateBody( 838 @NotNull MethodVisitor mv, 839 @NotNull JvmMethodSignature signature, 840 @NotNull MethodContext context, 841 @Nullable MemberCodegen parentCodegen 842 ) { 843 InstructionAdapter iv = new InstructionAdapter(mv); 844 845 iv.anew(thisDescriptorType); 846 iv.dup(); 847 848 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor); 849 assert function.getValueParameters().size() == constructor.getValueParameters().size() : 850 "Number of parameters of copy function and constructor are different. " + 851 "Copy: " + function.getValueParameters().size() + ", " + 852 "constructor: " + constructor.getValueParameters().size(); 853 854 MutableClosure closure = ImplementationBodyCodegen.this.context.closure; 855 if (closure != null && closure.getCaptureThis() != null) { 856 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor)); 857 iv.load(0, classAsmType); 858 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); 859 } 860 861 int parameterIndex = 1; // localVariable 0 = this 862 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) { 863 Type type = typeMapper.mapType(parameterDescriptor.getType()); 864 iv.load(parameterIndex, type); 865 parameterIndex += type.getSize(); 866 } 867 868 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor(); 869 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor); 870 871 iv.areturn(thisDescriptorType); 872 } 873 }); 874 875 MethodContext functionContext = context.intoFunction(function); 876 877 functionCodegen.generateDefaultIfNeeded(functionContext, methodSignature, function, OwnerKind.IMPLEMENTATION, 878 new DefaultParameterValueLoader() { 879 @Override 880 public void putValueOnStack( 881 ValueParameterDescriptor descriptor, 882 ExpressionCodegen codegen 883 ) { 884 assert (KotlinBuiltIns.getInstance() 885 .isData((ClassDescriptor) function.getContainingDeclaration())) 886 : "Trying to create function with default arguments for function that isn't presented in code for class without data annotation"; 887 PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get( 888 BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor); 889 assert propertyDescriptor != null 890 : "Trying to generate default value for parameter of copy function that doesn't correspond to any property"; 891 codegen.v.load(0, thisDescriptorType); 892 Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType()); 893 codegen.intermediateValueForProperty(propertyDescriptor, false, null) 894 .put(propertyType, codegen.v); 895 } 896 }); 897 898 } 899 900 private void generateEnumMethodsAndConstInitializers() { 901 if (isEnumClass(descriptor)) { 902 generateEnumValuesMethod(); 903 generateEnumValueOfMethod(); 904 initializeEnumConstants(); 905 } 906 } 907 908 private void generateEnumValuesMethod() { 909 Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); 910 911 MethodVisitor mv = v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null); 912 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 913 914 mv.visitCode(); 915 mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), VALUES, type.getDescriptor()); 916 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;"); 917 mv.visitTypeInsn(CHECKCAST, type.getInternalName()); 918 mv.visitInsn(ARETURN); 919 FunctionCodegen.endVisit(mv, "values()", myClass); 920 } 921 922 private void generateEnumValueOfMethod() { 923 MethodVisitor mv = 924 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null); 925 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 926 927 mv.visitCode(); 928 mv.visitLdcInsn(classAsmType); 929 mv.visitVarInsn(ALOAD, 0); 930 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;"); 931 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName()); 932 mv.visitInsn(ARETURN); 933 FunctionCodegen.endVisit(mv, "valueOf()", myClass); 934 } 935 936 protected void generateSyntheticAccessors() { 937 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors(); 938 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) { 939 generateSyntheticAccessor(entry); 940 } 941 } 942 943 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) { 944 if (entry.getValue() instanceof FunctionDescriptor) { 945 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); 946 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); 947 functionCodegen.generateMethod(null, typeMapper.mapSignature(bridge), bridge, 948 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) { 949 @Override 950 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 951 generateMethodCallTo(original, codegen.v); 952 953 codegen.v.areturn(signature.getAsmMethod().getReturnType()); 954 } 955 }); 956 } 957 else if (entry.getValue() instanceof PropertyDescriptor) { 958 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); 959 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); 960 961 962 PropertyGetterDescriptor getter = bridge.getGetter(); 963 assert getter != null; 964 functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), getter, 965 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) { 966 @Override 967 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 968 InstructionAdapter iv = codegen.v; 969 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 970 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 971 if (!forceField) { 972 iv.load(0, OBJECT_TYPE); 973 } 974 property.put(property.type, iv); 975 iv.areturn(signature.getAsmMethod().getReturnType()); 976 } 977 }); 978 979 980 if (bridge.isVar()) { 981 PropertySetterDescriptor setter = bridge.getSetter(); 982 assert setter != null; 983 984 functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), setter, 985 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) { 986 @Override 987 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 988 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 989 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 990 InstructionAdapter iv = codegen.v; 991 992 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 993 for (int i = 0, reg = 0; i < argTypes.length; i++) { 994 Type argType = argTypes[i]; 995 iv.load(reg, argType); 996 //noinspection AssignmentToForLoopParameter 997 reg += argType.getSize(); 998 } 999 property.store(property.type, iv); 1000 1001 iv.areturn(signature.getAsmMethod().getReturnType()); 1002 } 1003 }); 1004 } 1005 } 1006 else { 1007 throw new UnsupportedOperationException(); 1008 } 1009 } 1010 1011 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) { 1012 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor; 1013 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor); 1014 CallableMethod callableMethod = isConstructor ? 1015 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) : 1016 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, 1017 isCallInsideSameClassAsDeclared(functionDescriptor, context), 1018 isCallInsideSameModuleAsDeclared(functionDescriptor, context), 1019 context.getContextKind()); 1020 1021 Method method = callableMethod.getSignature().getAsmMethod(); 1022 Type[] argTypes = method.getArgumentTypes(); 1023 1024 int reg = 1; 1025 if (isConstructor) { 1026 iv.anew(callableMethod.getOwner()); 1027 iv.dup(); 1028 reg = 0; 1029 } 1030 else if (callFromAccessor) { 1031 iv.load(0, OBJECT_TYPE); 1032 } 1033 1034 for (int paramIndex = 0; paramIndex < argTypes.length; paramIndex++) { 1035 Type argType = argTypes[paramIndex]; 1036 iv.load(reg, argType); 1037 //noinspection AssignmentToForLoopParameter 1038 reg += argType.getSize(); 1039 } 1040 callableMethod.invokeWithoutAssertions(iv); 1041 } 1042 1043 private void generateFieldForSingleton() { 1044 boolean hasClassObject = descriptor.getClassObjectDescriptor() != null; 1045 boolean isEnumClass = DescriptorUtils.isEnumClass(descriptor); 1046 boolean isObjectDeclaration = descriptor.getKind() == ClassKind.OBJECT && isNonLiteralObject(myClass) ; 1047 1048 if (!isObjectDeclaration && !hasClassObject || isEnumClass) return; 1049 1050 ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor; 1051 assert fieldTypeDescriptor != null; 1052 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper); 1053 JetClassOrObject original; 1054 if (hasClassObject) { 1055 JetClassObject classObject = ((JetClass) myClass).getClassObject(); 1056 assert classObject != null : myClass.getText(); 1057 original = classObject.getObjectDeclaration(); 1058 } 1059 else { 1060 original = myClass; 1061 } 1062 1063 v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); 1064 1065 if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) { 1066 genInitSingleton(fieldTypeDescriptor, field); 1067 } 1068 } 1069 1070 private void generateClassObjectBackingFieldCopies() { 1071 if (classObjectPropertiesToCopy != null) { 1072 for (PropertyAndDefaultValue propertyInfo : classObjectPropertiesToCopy) { 1073 PropertyDescriptor propertyDescriptor = propertyInfo.propertyDescriptor; 1074 1075 v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(propertyDescriptor), 1076 typeMapper.mapType(propertyDescriptor).getDescriptor(), null, propertyInfo.defaultValue); 1077 1078 //This field are always static and final so if it has constant initializer don't do anything in clinit, 1079 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 1080 // TODO: test this code 1081 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && propertyInfo.defaultValue == null) { 1082 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1083 int classObjectIndex = putClassObjectInLocalVar(codegen); 1084 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v); 1085 copyFieldFromClassObject(propertyDescriptor); 1086 } 1087 } 1088 } 1089 } 1090 1091 private int putClassObjectInLocalVar(ExpressionCodegen codegen) { 1092 FrameMap frameMap = codegen.myFrameMap; 1093 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor(); 1094 int classObjectIndex = frameMap.getIndex(classObjectDescriptor); 1095 if (classObjectIndex == -1) { 1096 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE); 1097 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper); 1098 classObject.put(classObject.type, codegen.v); 1099 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v); 1100 } 1101 return classObjectIndex; 1102 } 1103 1104 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) { 1105 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1106 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null); 1107 property.put(property.type, codegen.v); 1108 StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true); 1109 field.store(field.type, codegen.v); 1110 } 1111 1112 protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) { 1113 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1114 ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor); 1115 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1116 FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor); 1117 generateMethodCallTo(fd, codegen.v); 1118 field.store(field.type, codegen.v); 1119 } 1120 } 1121 1122 protected void generatePrimaryConstructor() { 1123 if (ignoreIfTraitOrAnnotation()) return; 1124 1125 if (kind != OwnerKind.IMPLEMENTATION) { 1126 throw new IllegalStateException("incorrect kind for primary constructor: " + kind); 1127 } 1128 1129 final MutableClosure closure = context.closure; 1130 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); 1131 1132 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, closure); 1133 1134 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1135 lookupConstructorExpressionsInClosureIfPresent(constructorContext); 1136 } 1137 1138 assert constructorDescriptor != null; 1139 final JvmMethodSignature constructorSignature = typeMapper.mapConstructorSignature(constructorDescriptor, closure); 1140 1141 functionCodegen.generateMethod(null, constructorSignature, constructorDescriptor, constructorContext, 1142 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) { 1143 1144 @NotNull 1145 @Override 1146 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) { 1147 return new ConstructorFrameMap(constructorSignature); 1148 } 1149 1150 @Override 1151 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 1152 generatePrimaryConstructorImpl(callableDescriptor, codegen, closure); 1153 } 1154 } 1155 ); 1156 1157 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorSignature, constructorDescriptor, 1158 OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); 1159 1160 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, closure); 1161 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v); 1162 1163 if (isClassObject(descriptor)) { 1164 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, typeMapper); 1165 } 1166 } 1167 1168 private void generatePrimaryConstructorImpl( 1169 @Nullable ConstructorDescriptor constructorDescriptor, 1170 @NotNull ExpressionCodegen codegen, 1171 @Nullable MutableClosure closure 1172 ) { 1173 List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null 1174 ? constructorDescriptor.getValueParameters() 1175 : Collections.<ValueParameterDescriptor>emptyList(); 1176 1177 InstructionAdapter iv = codegen.v; 1178 1179 if (superCall == null) { 1180 genSimpleSuperCall(iv); 1181 } 1182 else if (superCall instanceof JetDelegatorToSuperClass) { 1183 genSuperCallToDelegatorToSuperClass(iv); 1184 } 1185 else { 1186 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor); 1187 } 1188 1189 if (closure != null) { 1190 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType); 1191 int k = 1; 1192 for (FieldInfo info : argsFromClosure) { 1193 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv); 1194 } 1195 } 1196 1197 int n = 0; 1198 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1199 if (specifier == superCall) { 1200 continue; 1201 } 1202 1203 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1204 genCallToDelegatorByExpressionSpecifier(iv, codegen, n++, specifier); 1205 } 1206 } 1207 1208 int curParam = 0; 1209 List<JetParameter> constructorParameters = getPrimaryConstructorParameters(); 1210 for (JetParameter parameter : constructorParameters) { 1211 if (parameter.getValOrVarNode() != null) { 1212 VariableDescriptor descriptor = paramDescrs.get(curParam); 1213 Type type = typeMapper.mapType(descriptor); 1214 iv.load(0, classAsmType); 1215 iv.load(codegen.myFrameMap.getIndex(descriptor), type); 1216 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 1217 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter; 1218 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor), type.getDescriptor()); 1219 } 1220 curParam++; 1221 } 1222 1223 boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor); 1224 if (generateInitializerInOuter) { 1225 ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this); 1226 //generate object$ 1227 parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper)); 1228 parentCodegen.generateInitializers(parentCodegen.createOrGetClInitCodegen(), 1229 myClass.getDeclarations(), bindingContext, state); 1230 } else { 1231 generateInitializers(codegen, myClass.getDeclarations(), bindingContext, state); 1232 } 1233 1234 1235 iv.visitInsn(RETURN); 1236 } 1237 1238 private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) { 1239 iv.load(0, superClassAsmType); 1240 JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference()); 1241 List<Type> parameterTypes = new ArrayList<Type>(); 1242 assert superType != null; 1243 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 1244 if (CodegenBinding.hasThis0(bindingContext, superClassDescriptor)) { 1245 iv.load(1, OBJECT_TYPE); 1246 parameterTypes.add(typeMapper.mapType( 1247 enclosingClassDescriptor(bindingContext, descriptor))); 1248 } 1249 Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); 1250 //noinspection ConstantConditions 1251 iv.invokespecial(typeMapper.mapType(superClassDescriptor).getInternalName(), "<init>", 1252 superCallMethod.getDescriptor()); 1253 } 1254 1255 private void genSimpleSuperCall(InstructionAdapter iv) { 1256 iv.load(0, superClassAsmType); 1257 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) { 1258 iv.load(1, JAVA_STRING_TYPE); 1259 iv.load(2, Type.INT_TYPE); 1260 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V"); 1261 } 1262 else { 1263 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V"); 1264 } 1265 } 1266 1267 private void genCallToDelegatorByExpressionSpecifier( 1268 InstructionAdapter iv, 1269 ExpressionCodegen codegen, 1270 int n, 1271 JetDelegationSpecifier specifier 1272 ) { 1273 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1274 PropertyDescriptor propertyDescriptor = null; 1275 if (expression instanceof JetSimpleNameExpression) { 1276 ResolvedCall<? extends CallableDescriptor> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression); 1277 if (call != null) { 1278 CallableDescriptor callResultingDescriptor = call.getResultingDescriptor(); 1279 if (callResultingDescriptor instanceof ValueParameterDescriptor) { 1280 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor; 1281 // constructor parameter 1282 if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) { 1283 // constructor of my class 1284 if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == descriptor) { 1285 propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor); 1286 } 1287 } 1288 } 1289 1290 // todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier 1291 } 1292 } 1293 1294 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 1295 assert superType != null; 1296 1297 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 1298 assert superClassDescriptor != null; 1299 1300 StackValue field; 1301 if (propertyDescriptor != null && 1302 !propertyDescriptor.isVar() && 1303 Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) { 1304 // final property with backing field 1305 field = StackValue.field(typeMapper.mapType(propertyDescriptor.getType()), classAsmType, 1306 propertyDescriptor.getName().asString(), false); 1307 } 1308 else { 1309 iv.load(0, classAsmType); 1310 codegen.genToJVMStack(expression); 1311 1312 String delegateField = "$delegate_" + n; 1313 Type fieldType = typeMapper.mapType(superClassDescriptor); 1314 String fieldDesc = fieldType.getDescriptor(); 1315 1316 v.newField(specifier, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, delegateField, fieldDesc, /*TODO*/null, null); 1317 1318 field = StackValue.field(fieldType, classAsmType, delegateField, false); 1319 field.store(fieldType, iv); 1320 } 1321 1322 generateDelegates(superClassDescriptor, field); 1323 } 1324 1325 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) { 1326 JetVisitorVoid visitor = new JetVisitorVoid() { 1327 @Override 1328 public void visitJetElement(JetElement e) { 1329 e.acceptChildren(this); 1330 } 1331 1332 @Override 1333 public void visitSimpleNameExpression(JetSimpleNameExpression expr) { 1334 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr); 1335 if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) { 1336 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor(); 1337 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) { 1338 //noinspection ConstantConditions 1339 if (descriptor.equals(parameterDescriptor)) { 1340 return; 1341 } 1342 } 1343 constructorContext.lookupInContext(descriptor, null, state, true); 1344 } else if (isLocalNamedFun(descriptor)) { 1345 assert descriptor != null; 1346 MutableClassDescriptor classDescriptor = 1347 (MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor(); 1348 1349 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getAllCallableMembers()) { 1350 if (descriptor.equals(memberDescriptor)) { 1351 return; 1352 } 1353 } 1354 constructorContext.lookupInContext(descriptor, null, state, true); 1355 } 1356 } 1357 1358 @Override 1359 public void visitThisExpression(JetThisExpression expression) { 1360 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 1361 assert descriptor instanceof CallableDescriptor || 1362 descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor; 1363 if (context.getCallableDescriptorWithReceiver() != descriptor) { 1364 context.lookupInContext(descriptor, null, state, true); 1365 } 1366 } 1367 }; 1368 1369 for (JetDeclaration declaration : myClass.getDeclarations()) { 1370 if (declaration instanceof JetProperty) { 1371 JetProperty property = (JetProperty) declaration; 1372 JetExpression initializer = property.getInitializer(); 1373 if (initializer != null) { 1374 initializer.accept(visitor); 1375 } 1376 } 1377 else if (declaration instanceof JetClassInitializer) { 1378 JetClassInitializer initializer = (JetClassInitializer) declaration; 1379 initializer.accept(visitor); 1380 } 1381 } 1382 1383 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1384 if (specifier != superCall) { 1385 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1386 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1387 assert delegateExpression != null; 1388 delegateExpression.accept(visitor); 1389 } 1390 } 1391 else { 1392 if (superCall instanceof JetDelegatorToSuperCall) { 1393 JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList(); 1394 if (argumentList != null) { 1395 argumentList.accept(visitor); 1396 } 1397 } 1398 } 1399 } 1400 } 1401 1402 private boolean ignoreIfTraitOrAnnotation() { 1403 if (myClass instanceof JetClass) { 1404 JetClass aClass = (JetClass) myClass; 1405 if (aClass.isTrait()) { 1406 return true; 1407 } 1408 if (aClass.isAnnotation()) { 1409 return true; 1410 } 1411 } 1412 return false; 1413 } 1414 1415 private void generateTraitMethods() { 1416 if (JetPsiUtil.isTrait(myClass)) { 1417 return; 1418 } 1419 1420 for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) { 1421 if (needDelegates.second instanceof SimpleFunctionDescriptor) { 1422 generateDelegationToTraitImpl((FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first); 1423 } 1424 else if (needDelegates.second instanceof PropertyDescriptor) { 1425 PropertyDescriptor property = (PropertyDescriptor) needDelegates.second; 1426 List<PropertyAccessorDescriptor> inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors(); 1427 for (PropertyAccessorDescriptor accessor : property.getAccessors()) { 1428 for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) { 1429 if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind 1430 generateDelegationToTraitImpl(accessor, inheritedAccessor); 1431 } 1432 } 1433 } 1434 } 1435 } 1436 } 1437 1438 1439 private void generateDelegationToTraitImpl(final @NotNull FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) { 1440 DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); 1441 if (!(containingDeclaration instanceof ClassDescriptor)) { 1442 return; 1443 } 1444 1445 ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration; 1446 if (containingClass.getKind() != ClassKind.TRAIT) { 1447 return; 1448 } 1449 1450 int flags = ACC_PUBLIC; // TODO. 1451 1452 TraitImplDelegateInfo delegateInfo = getTraitImplDelegateInfo(fun); 1453 Method methodToGenerate = delegateInfo.methodToGenerate; 1454 Method methodInTrait = delegateInfo.methodInTrait; 1455 1456 PsiElement origin = descriptorToDeclaration(bindingContext, fun); 1457 MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null, null); 1458 AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(fun); 1459 1460 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1461 Type returnType = methodToGenerate.getReturnType(); 1462 1463 mv.visitCode(); 1464 FrameMap frameMap = context.prepareFrame(typeMapper); 1465 ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state, this); 1466 codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it? 1467 1468 Type[] argTypes = methodToGenerate.getArgumentTypes(); 1469 Type[] originalArgTypes = methodInTrait.getArgumentTypes(); 1470 1471 InstructionAdapter iv = new InstructionAdapter(mv); 1472 iv.load(0, OBJECT_TYPE); 1473 for (int i = 0, reg = 1; i < argTypes.length; i++) { 1474 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); 1475 //noinspection AssignmentToForLoopParameter 1476 reg += argTypes[i].getSize(); 1477 } 1478 1479 Type type = getTraitImplThisParameterType(containingClass, typeMapper); 1480 String functionDescriptor = methodInTrait.getDescriptor().replace("(", "(" + type.getDescriptor()); 1481 1482 iv.invokestatic(typeMapper.mapTraitImpl(containingClass).getInternalName(), methodToGenerate.getName(), functionDescriptor); 1483 StackValue.onStack(methodInTrait.getReturnType()).put(returnType, iv); 1484 iv.areturn(returnType); 1485 1486 FunctionCodegen.endVisit(iv, "trait method", callableDescriptorToDeclaration(bindingContext, fun)); 1487 } 1488 1489 FunctionCodegen.generateBridgeIfNeeded(context, state, v, methodToGenerate, fun); 1490 } 1491 1492 private static class TraitImplDelegateInfo { 1493 private final Method methodToGenerate; 1494 private final Method methodInTrait; 1495 1496 private TraitImplDelegateInfo(@NotNull Method methodToGenerate, @NotNull Method methodInTrait) { 1497 this.methodToGenerate = methodToGenerate; 1498 this.methodInTrait = methodInTrait; 1499 } 1500 } 1501 1502 @NotNull 1503 private TraitImplDelegateInfo getTraitImplDelegateInfo(@NotNull FunctionDescriptor fun) { 1504 if (fun instanceof PropertyAccessorDescriptor) { 1505 PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty(); 1506 PropertyDescriptor original = property.getOriginal(); 1507 if (fun instanceof PropertyGetterDescriptor) { 1508 JvmMethodSignature toGenerate = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION); 1509 JvmMethodSignature inTrait = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); 1510 return new TraitImplDelegateInfo( 1511 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1512 } 1513 else if (fun instanceof PropertySetterDescriptor) { 1514 JvmMethodSignature toGenerate = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION); 1515 JvmMethodSignature inTrait = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); 1516 return new TraitImplDelegateInfo( 1517 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1518 } 1519 else { 1520 throw new IllegalStateException("Accessor is neither getter, nor setter, what is it? " + fun); 1521 } 1522 } 1523 else { 1524 Method function = typeMapper.mapSignature(fun).getAsmMethod(); 1525 Method functionOriginal = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod(); 1526 return new TraitImplDelegateInfo(function, functionOriginal); 1527 } 1528 } 1529 1530 private void generateDelegatorToConstructorCall( 1531 InstructionAdapter iv, ExpressionCodegen codegen, 1532 ConstructorDescriptor constructorDescriptor 1533 ) { 1534 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); 1535 1536 iv.load(0, OBJECT_TYPE); 1537 1538 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) { 1539 iv.load(1, OBJECT_TYPE); 1540 iv.load(2, Type.INT_TYPE); 1541 } 1542 1543 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure); 1544 1545 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1546 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression()); 1547 assert resolvedCall != null; 1548 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1549 1550 //noinspection SuspiciousMethodCalls 1551 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration()); 1552 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper); 1553 1554 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { 1555 iv.load(((ConstructorFrameMap)codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE); 1556 } 1557 1558 if (myClass instanceof JetObjectDeclaration && 1559 superCall instanceof JetDelegatorToSuperCall && 1560 ((JetObjectDeclaration) myClass).isObjectLiteral()) { 1561 int nextVar = findFirstSuperArgument(method); 1562 for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { 1563 iv.load(nextVar, t); 1564 nextVar += t.getSize(); 1565 } 1566 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall); 1567 } 1568 else { 1569 codegen.invokeMethodWithArguments(superCallable, resolvedCall, null, StackValue.none()); 1570 } 1571 } 1572 1573 private static int findFirstSuperArgument(CallableMethod method) { 1574 List<JvmMethodParameterSignature> types = method.getSignature().getKotlinParameterTypes(); 1575 int i = 0; 1576 for (JvmMethodParameterSignature type : types) { 1577 if (type.getKind() == JvmMethodParameterKind.SUPER_CALL_PARAM) { 1578 return i + 1; // because of this 1579 } 1580 i += type.getAsmType().getSize(); 1581 } 1582 return -1; 1583 } 1584 1585 @Override 1586 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) { 1587 if (declaration instanceof JetEnumEntry) { 1588 String name = declaration.getName(); 1589 assert name != null : "Enum entry has no name: " + declaration.getText(); 1590 String desc = "L" + classAsmType.getInternalName() + ";"; 1591 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null); 1592 myEnumConstants.add((JetEnumEntry) declaration); 1593 } 1594 1595 super.generateDeclaration(propertyCodegen, declaration); 1596 } 1597 1598 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>(); 1599 1600 private void initializeEnumConstants() { 1601 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 1602 1603 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1604 InstructionAdapter iv = codegen.v; 1605 1606 Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); 1607 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, VALUES, arrayAsmType.getDescriptor(), null, null); 1608 1609 iv.iconst(myEnumConstants.size()); 1610 iv.newarray(classAsmType); 1611 1612 if (!myEnumConstants.isEmpty()) { 1613 iv.dup(); 1614 for (int ordinal = 0, size = myEnumConstants.size(); ordinal < size; ordinal++) { 1615 initializeEnumConstant(codegen, ordinal); 1616 } 1617 } 1618 1619 iv.putstatic(classAsmType.getInternalName(), VALUES, arrayAsmType.getDescriptor()); 1620 } 1621 1622 private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) { 1623 InstructionAdapter iv = codegen.v; 1624 JetEnumEntry enumConstant = myEnumConstants.get(ordinal); 1625 1626 iv.dup(); 1627 iv.iconst(ordinal); 1628 1629 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant); 1630 assert classDescriptor != null; 1631 Type implClass = typeMapper.mapClass(classDescriptor); 1632 1633 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers(); 1634 if (delegationSpecifiers.size() > 1) { 1635 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported"); 1636 } 1637 1638 iv.anew(implClass); 1639 iv.dup(); 1640 1641 iv.aconst(enumConstant.getName()); 1642 iv.iconst(ordinal); 1643 1644 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { 1645 JetDelegationSpecifier specifier = delegationSpecifiers.get(0); 1646 if (!(specifier instanceof JetDelegatorToSuperCall)) { 1647 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); 1648 } 1649 1650 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1651 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression()); 1652 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText(); 1653 1654 CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor()); 1655 1656 codegen.invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 1657 } 1658 else { 1659 iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V"); 1660 } 1661 1662 iv.dup(); 1663 iv.putstatic(classAsmType.getInternalName(), enumConstant.getName(), classAsmType.getDescriptor()); 1664 iv.astore(OBJECT_TYPE); 1665 } 1666 1667 public static void generateInitializers( 1668 @NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations, 1669 @NotNull BindingContext bindingContext, @NotNull GenerationState state 1670 ) { 1671 JetTypeMapper typeMapper = state.getTypeMapper(); 1672 for (JetDeclaration declaration : declarations) { 1673 if (declaration instanceof JetProperty) { 1674 if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) { 1675 initializeProperty(codegen, bindingContext, (JetProperty) declaration); 1676 } 1677 } 1678 else if (declaration instanceof JetClassInitializer) { 1679 codegen.gen(((JetClassInitializer) declaration).getBody(), Type.VOID_TYPE); 1680 } 1681 } 1682 } 1683 1684 1685 public static void initializeProperty( 1686 @NotNull ExpressionCodegen codegen, 1687 @NotNull BindingContext bindingContext, 1688 @NotNull JetProperty property 1689 ) { 1690 1691 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property); 1692 assert propertyDescriptor != null; 1693 1694 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1695 assert initializer != null : "shouldInitializeProperty must return false if initializer is null"; 1696 1697 JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor); 1698 1699 StackValue.StackValueWithSimpleReceiver propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER); 1700 1701 if (!propValue.isStatic) { 1702 codegen.v.load(0, OBJECT_TYPE); 1703 } 1704 1705 Type type = codegen.expressionType(initializer); 1706 if (jetType.isNullable()) { 1707 type = boxType(type); 1708 } 1709 codegen.gen(initializer, type); 1710 1711 propValue.store(type, codegen.v); 1712 } 1713 1714 public static boolean shouldWriteFieldInitializer(PropertyDescriptor descriptor, JetTypeMapper mapper) { 1715 //final field of primitive or String type 1716 if (!descriptor.isVar()) { 1717 Type type = mapper.mapType(descriptor.getType()); 1718 return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName()); 1719 } 1720 return false; 1721 } 1722 1723 public static boolean shouldInitializeProperty( 1724 @NotNull JetProperty property, 1725 @NotNull JetTypeMapper typeMapper 1726 ) { 1727 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1728 if (initializer == null) return false; 1729 1730 CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); 1731 if (compileTimeValue == null) return true; 1732 1733 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) typeMapper.getBindingContext().get(BindingContext.VARIABLE, property); 1734 assert propertyDescriptor != null; 1735 1736 //TODO: OPTIMIZATION: don't initialize static final fields 1737 1738 Object value = compileTimeValue.getValue(); 1739 JetType jetType = getPropertyOrDelegateType(typeMapper.getBindingContext(), property, propertyDescriptor); 1740 Type type = typeMapper.mapType(jetType); 1741 return !skipDefaultValue(propertyDescriptor, value, type); 1742 } 1743 1744 @NotNull 1745 private static JetType getPropertyOrDelegateType(@NotNull BindingContext bindingContext, @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { 1746 JetExpression delegateExpression = property.getDelegateExpression(); 1747 if (delegateExpression != null) { 1748 JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression); 1749 assert delegateType != null : "Type of delegate expression should be recorded"; 1750 return delegateType; 1751 } 1752 return descriptor.getType(); 1753 } 1754 1755 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) { 1756 if (isPrimitive(type)) { 1757 if (!propertyDescriptor.getType().isNullable() && value instanceof Number) { 1758 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) { 1759 return true; 1760 } 1761 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) { 1762 return true; 1763 } 1764 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) { 1765 return true; 1766 } 1767 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) { 1768 return true; 1769 } 1770 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) { 1771 return true; 1772 } 1773 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) { 1774 return true; 1775 } 1776 } 1777 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) { 1778 return true; 1779 } 1780 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) { 1781 return true; 1782 } 1783 } 1784 else { 1785 if (value == null) { 1786 return true; 1787 } 1788 } 1789 return false; 1790 } 1791 1792 protected void generateDelegates(ClassDescriptor toClass, StackValue field) { 1793 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1794 if (declaration instanceof CallableMemberDescriptor) { 1795 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; 1796 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) { 1797 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors(); 1798 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) { 1799 if (overriddenDescriptor.getContainingDeclaration() == toClass) { 1800 if (declaration instanceof PropertyDescriptor) { 1801 propertyCodegen 1802 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field); 1803 } 1804 else if (declaration instanceof FunctionDescriptor) { 1805 functionCodegen 1806 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field); 1807 } 1808 } 1809 } 1810 } 1811 } 1812 } 1813 } 1814 1815 1816 /** 1817 * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, 1818 * second is member of trait that contain implementation. 1819 */ 1820 private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { 1821 List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList(); 1822 1823 for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1824 if (!(decl instanceof CallableMemberDescriptor)) { 1825 continue; 1826 } 1827 1828 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl; 1829 if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 1830 continue; 1831 } 1832 1833 Collection<CallableMemberDescriptor> overriddenDeclarations = 1834 OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor); 1835 1836 Collection<CallableMemberDescriptor> filteredOverriddenDeclarations = 1837 OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations)); 1838 1839 int count = 0; 1840 CallableMemberDescriptor candidate = null; 1841 1842 for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { 1843 if (isTrait(overriddenDeclaration.getContainingDeclaration()) && 1844 overriddenDeclaration.getModality() != Modality.ABSTRACT) { 1845 candidate = overriddenDeclaration; 1846 count++; 1847 } 1848 } 1849 if (candidate == null) { 1850 continue; 1851 } 1852 1853 assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName(); 1854 1855 1856 Collection<JetType> superTypesOfSuperClass = 1857 superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>emptySet(); 1858 ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject(); 1859 assert expectedThisObject != null; 1860 JetType candidateType = expectedThisObject.getType(); 1861 boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType); 1862 1863 if (!implementedInSuperClass) { 1864 r.add(Pair.create(callableMemberDescriptor, candidate)); 1865 } 1866 } 1867 return r; 1868 } 1869 1870 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { 1871 if (classObjectPropertiesToCopy == null) { 1872 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>(); 1873 } 1874 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue)); 1875 } 1876 1877 static class PropertyAndDefaultValue { 1878 1879 PropertyAndDefaultValue(PropertyDescriptor propertyDescriptor, Object defaultValue) { 1880 this.propertyDescriptor = propertyDescriptor; 1881 this.defaultValue = defaultValue; 1882 } 1883 1884 private PropertyDescriptor propertyDescriptor; 1885 1886 private Object defaultValue; 1887 1888 1889 } 1890 }