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