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