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.state;
018
019 import com.intellij.psi.PsiElement;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.codegen.*;
023 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
024 import org.jetbrains.jet.codegen.binding.CodegenBinding;
025 import org.jetbrains.jet.codegen.context.CodegenContext;
026 import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
027 import org.jetbrains.jet.config.IncrementalCompilation;
028 import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
031 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
032 import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
033 import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
034 import org.jetbrains.jet.lang.psi.JetFile;
035 import org.jetbrains.jet.lang.resolve.BindingContext;
036 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
037 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
038 import org.jetbrains.jet.lang.resolve.OverrideResolver;
039 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
040 import org.jetbrains.jet.lang.resolve.constants.StringValue;
041 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
042 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
043 import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
044 import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassStaticsPackageFragmentDescriptor;
045 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
046 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
047 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
048 import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
049 import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
050 import org.jetbrains.jet.lang.resolve.name.FqName;
051 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
052 import org.jetbrains.jet.lang.types.*;
053 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
054 import org.jetbrains.org.objectweb.asm.Type;
055 import org.jetbrains.org.objectweb.asm.commons.Method;
056
057 import java.util.ArrayList;
058 import java.util.List;
059 import java.util.Map;
060
061 import static org.jetbrains.jet.codegen.AsmUtil.*;
062 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
063 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
064 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
065 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
066 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
067
068 public class JetTypeMapper {
069 private final BindingContext bindingContext;
070 private final ClassBuilderMode classBuilderMode;
071
072 public JetTypeMapper(@NotNull BindingContext bindingContext, @NotNull ClassBuilderMode classBuilderMode) {
073 this.bindingContext = bindingContext;
074 this.classBuilderMode = classBuilderMode;
075 }
076
077 @NotNull
078 public BindingContext getBindingContext() {
079 return bindingContext;
080 }
081
082 private enum JetTypeMapperMode {
083 /**
084 * foo.Bar is mapped to Lfoo/Bar;
085 */
086 IMPL,
087 /**
088 * kotlin.Int is mapped to I
089 */
090 VALUE,
091 /**
092 * kotlin.Int is mapped to Ljava/lang/Integer;
093 */
094 TYPE_PARAMETER,
095 /**
096 * kotlin.Int is mapped to Ljava/lang/Integer;
097 * No projections allowed in immediate arguments
098 */
099 SUPER_TYPE
100 }
101
102 @NotNull
103 public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean isInsideModule) {
104 if (isLocalNamedFun(descriptor)) {
105 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
106 }
107
108 DeclarationDescriptor container = descriptor.getContainingDeclaration();
109 if (container instanceof JavaClassStaticsPackageFragmentDescriptor) {
110 return mapClass(((JavaClassStaticsPackageFragmentDescriptor) container).getCorrespondingClass());
111 }
112 else if (container instanceof PackageFragmentDescriptor) {
113 return Type.getObjectType(internalNameForPackage((PackageFragmentDescriptor) container, descriptor, isInsideModule));
114 }
115 else if (container instanceof ClassDescriptor) {
116 return mapClass((ClassDescriptor) container);
117 }
118 else if (container instanceof ScriptDescriptor) {
119 return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
120 }
121 else {
122 throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
123 }
124 }
125
126 @NotNull
127 private String internalNameForPackage(
128 @NotNull PackageFragmentDescriptor packageFragment,
129 @NotNull DeclarationDescriptor descriptor,
130 boolean insideModule
131 ) {
132 if (insideModule) {
133 JetFile file = BindingContextUtils.getContainingFile(bindingContext, descriptor);
134 if (file != null) {
135 return PackagePartClassUtils.getPackagePartInternalName(file);
136 }
137
138 if (descriptor instanceof DeserializedCallableMemberDescriptor && IncrementalCompilation.ENABLED) {
139 //
140 // TODO calls from other modules/libraries should use facade: KT-4590
141 FqName packagePartFqName = PackagePartClassUtils.getPackagePartFqName((DeserializedCallableMemberDescriptor) descriptor);
142 return AsmUtil.internalNameByFqNameWithoutInnerClasses(packagePartFqName);
143 }
144 }
145
146 return PackageClassUtils.getPackageClassInternalName(packageFragment.getFqName());
147 }
148
149 @NotNull
150 public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
151 return mapReturnType(descriptor, null);
152 }
153
154 @NotNull
155 private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
156 JetType returnType = descriptor.getReturnType();
157 assert returnType != null : "Function has no return type: " + descriptor;
158 if (returnType.equals(KotlinBuiltIns.getInstance().getUnitType()) && !(descriptor instanceof PropertyGetterDescriptor)) {
159 if (sw != null) {
160 sw.writeAsmType(Type.VOID_TYPE);
161 }
162 return Type.VOID_TYPE;
163 }
164 else {
165 return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE, false);
166 }
167 }
168
169 @NotNull
170 private Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode mode) {
171 return mapType(jetType, null, mode);
172 }
173
174 @NotNull
175 public Type mapSupertype(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
176 return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
177 }
178
179 @NotNull
180 public Type mapClass(@NotNull ClassifierDescriptor classifier) {
181 return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
182 }
183
184 @NotNull
185 public Type mapType(@NotNull JetType jetType) {
186 return mapType(jetType, null, JetTypeMapperMode.VALUE);
187 }
188
189 @NotNull
190 public Type mapType(@NotNull CallableDescriptor descriptor) {
191 //noinspection ConstantConditions
192 return mapType(descriptor.getReturnType());
193 }
194
195 @NotNull
196 public Type mapType(@NotNull ClassifierDescriptor descriptor) {
197 return mapType(descriptor.getDefaultType());
198 }
199
200 @NotNull
201 private Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
202 return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT, false);
203 }
204
205 @NotNull
206 private Type mapType(
207 @NotNull JetType jetType,
208 @Nullable BothSignatureWriter signatureVisitor,
209 @NotNull JetTypeMapperMode kind,
210 @NotNull Variance howThisTypeIsUsed,
211 boolean arrayParameter
212 ) {
213 Type known = null;
214 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
215
216 if (descriptor instanceof ClassDescriptor) {
217 FqNameUnsafe className = DescriptorUtils.getFqName(descriptor);
218 if (className.isSafe()) {
219 known = KotlinToJavaTypesMap.getInstance().getJavaAnalog(className.toSafe(), jetType.isNullable());
220 }
221 }
222
223 boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
224 if (known != null) {
225 if (kind == JetTypeMapperMode.VALUE) {
226 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
227 }
228 else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE) {
229 return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter, projectionsAllowed);
230 }
231 else if (kind == JetTypeMapperMode.IMPL) {
232 // TODO: enable and fix tests
233 //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
234 return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
235 }
236 else {
237 throw new IllegalStateException("unknown kind: " + kind);
238 }
239 }
240
241 TypeConstructor constructor = jetType.getConstructor();
242 if (constructor instanceof IntersectionTypeConstructor) {
243 jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
244 }
245
246 if (descriptor == null) {
247 throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
248 }
249
250 if (ErrorUtils.isError(descriptor)) {
251 if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
252 throw new IllegalStateException(generateErrorMessageForErrorType(jetType, descriptor));
253 }
254 Type asmType = Type.getObjectType("error/NonExistentClass");
255 if (signatureVisitor != null) {
256 signatureVisitor.writeAsmType(asmType);
257 }
258 return asmType;
259 }
260
261 if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.getInstance().isArray(jetType)) {
262 if (jetType.getArguments().size() != 1) {
263 throw new UnsupportedOperationException("arrays must have one type argument");
264 }
265 TypeProjection memberProjection = jetType.getArguments().get(0);
266 JetType memberType = memberProjection.getType();
267
268 if (signatureVisitor != null) {
269 signatureVisitor.writeArrayType();
270 mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER, memberProjection.getProjectionKind(), true);
271 signatureVisitor.writeArrayEnd();
272 }
273
274 return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
275 }
276
277 if (descriptor instanceof ClassDescriptor) {
278 Type asmType = getAsmType(bindingContext, (ClassDescriptor) descriptor);
279 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
280 return asmType;
281 }
282
283 if (descriptor instanceof TypeParameterDescriptor) {
284 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
285 Type type = mapType(typeParameterDescriptor.getUpperBounds().iterator().next(), kind);
286 if (signatureVisitor != null) {
287 signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
288 }
289 return type;
290 }
291
292 throw new UnsupportedOperationException("Unknown type " + jetType);
293 }
294
295 @NotNull
296 public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
297 return Type.getObjectType(getAsmType(bindingContext, descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
298 }
299
300 @NotNull
301 private String generateErrorMessageForErrorType(@NotNull JetType type, @NotNull DeclarationDescriptor descriptor) {
302 PsiElement declarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
303 PsiElement parentDeclarationElement = null;
304 if (declarationElement != null) {
305 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
306 if (containingDeclaration != null) {
307 parentDeclarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, containingDeclaration);
308 }
309 }
310
311 return String.format("Error types are not allowed when classBuilderMode = %s. " +
312 "Type: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
313 classBuilderMode,
314 type,
315 type.getClass().getSimpleName(),
316 descriptor,
317 declarationElement,
318 declarationElement != null ? declarationElement.getText() : "null",
319 parentDeclarationElement,
320 parentDeclarationElement != null ? parentDeclarationElement.getText() : "null");
321 }
322
323 private void writeGenericType(
324 BothSignatureWriter signatureVisitor,
325 Type asmType,
326 JetType jetType,
327 Variance howThisTypeIsUsed,
328 boolean projectionsAllowed
329 ) {
330 if (signatureVisitor != null) {
331 signatureVisitor.writeClassBegin(asmType);
332
333 List<TypeProjection> arguments = jetType.getArguments();
334 for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
335 TypeProjection argument = arguments.get(parameter.getIndex());
336
337 Variance projectionKind = projectionsAllowed
338 ? getEffectiveVariance(
339 parameter.getVariance(),
340 argument.getProjectionKind(),
341 howThisTypeIsUsed
342 )
343 : Variance.INVARIANT;
344 signatureVisitor.writeTypeArgument(projectionKind);
345
346 mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
347 signatureVisitor.writeTypeArgumentEnd();
348 }
349 signatureVisitor.writeClassEnd();
350 }
351 }
352
353 private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
354 // Return type must not contain wildcards
355 if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
356
357 if (parameterVariance == Variance.INVARIANT) {
358 return projectionKind;
359 }
360 if (projectionKind == Variance.INVARIANT) {
361 return parameterVariance;
362 }
363 if (parameterVariance == projectionKind) {
364 return parameterVariance;
365 }
366
367 // In<out X> = In<*>
368 // Out<in X> = Out<*>
369 return Variance.OUT_VARIANCE;
370 }
371
372 private Type mapKnownAsmType(
373 JetType jetType,
374 Type asmType,
375 @Nullable BothSignatureWriter signatureVisitor,
376 @NotNull Variance howThisTypeIsUsed
377 ) {
378 return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false, true);
379 }
380
381 private Type mapKnownAsmType(
382 JetType jetType,
383 Type asmType,
384 @Nullable BothSignatureWriter signatureVisitor,
385 @NotNull Variance howThisTypeIsUsed,
386 boolean arrayParameter,
387 boolean allowProjections
388 ) {
389 if (signatureVisitor != null) {
390 if (jetType.getArguments().isEmpty()) {
391 if (arrayParameter && howThisTypeIsUsed == Variance.IN_VARIANCE) {
392 asmType = AsmTypeConstants.OBJECT_TYPE;
393 }
394 signatureVisitor.writeAsmType(asmType);
395 }
396 else {
397 writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
398 }
399 }
400 return asmType;
401 }
402
403 @NotNull
404 public CallableMethod mapToCallableMethod(
405 @NotNull FunctionDescriptor descriptor,
406 boolean superCall,
407 @NotNull CodegenContext<?> context
408 ) {
409 DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
410
411 FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
412
413 JvmMethodSignature signature;
414 Type owner;
415 Type ownerForDefaultImpl;
416 Type ownerForDefaultParam;
417 int invokeOpcode;
418 Type thisClass;
419
420 if (functionParent instanceof ClassDescriptor) {
421 FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
422
423 ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
424 ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
425
426 boolean originalIsInterface = isInterface(declarationOwner);
427 boolean currentIsInterface = isInterface(currentOwner);
428
429 boolean isInterface = currentIsInterface && originalIsInterface;
430
431 ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
432 ownerForDefaultParam = mapClass(ownerForDefault);
433 ownerForDefaultImpl = isInterface(ownerForDefault) ? mapTraitImpl(ownerForDefault) : ownerForDefaultParam;
434
435 if (isInterface && superCall) {
436 invokeOpcode = INVOKESTATIC;
437 signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
438 owner = mapTraitImpl(currentOwner);
439 thisClass = mapClass(currentOwner);
440 }
441 else {
442 if (isAccessor(functionDescriptor)) {
443 invokeOpcode = INVOKESTATIC;
444 }
445 else if (isInterface) {
446 invokeOpcode = INVOKEINTERFACE;
447 }
448 else {
449 boolean isPrivateFunInvocation = functionDescriptor.getVisibility() == Visibilities.PRIVATE;
450 invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
451 }
452
453 signature = mapSignature(functionDescriptor.getOriginal());
454
455 ClassDescriptor receiver = currentIsInterface && !originalIsInterface ? declarationOwner : currentOwner;
456 owner = mapClass(receiver);
457 thisClass = owner;
458 }
459 }
460 else {
461 signature = mapSignature(functionDescriptor.getOriginal());
462 owner = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context));
463 ownerForDefaultParam = owner;
464 ownerForDefaultImpl = owner;
465 if (functionParent instanceof PackageFragmentDescriptor) {
466 invokeOpcode = INVOKESTATIC;
467 thisClass = null;
468 }
469 else if (functionDescriptor instanceof ConstructorDescriptor) {
470 invokeOpcode = INVOKESPECIAL;
471 thisClass = null;
472 }
473 else {
474 invokeOpcode = INVOKEVIRTUAL;
475 thisClass = owner;
476 }
477 }
478
479 Type calleeType = isLocalNamedFun(functionDescriptor) ? owner : null;
480
481 Type receiverParameterType;
482 ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getReceiverParameter();
483 if (receiverParameter != null) {
484 receiverParameterType = mapType(receiverParameter.getType());
485 }
486 else {
487 receiverParameterType = null;
488 }
489 return new CallableMethod(
490 owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
491 thisClass, receiverParameterType, calleeType);
492 }
493
494 public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
495 return descriptor instanceof AccessorForFunctionDescriptor ||
496 descriptor instanceof AccessorForPropertyDescriptor ||
497 descriptor instanceof AccessorForPropertyDescriptor.Getter ||
498 descriptor instanceof AccessorForPropertyDescriptor.Setter;
499 }
500
501 @NotNull
502 private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
503 if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
504 return function;
505 }
506 return findBaseDeclaration(function);
507 }
508
509 @NotNull
510 private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
511 if (function.getOverriddenDescriptors().isEmpty()) {
512 return function;
513 }
514 else {
515 // TODO: prefer class to interface
516 return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
517 }
518 }
519
520 @NotNull
521 private static String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
522 String platformName = getPlatformName(descriptor);
523 if (platformName != null) return platformName;
524
525 if (descriptor instanceof PropertyAccessorDescriptor) {
526 PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
527 if (isAnnotationClass(property.getContainingDeclaration())) {
528 return property.getName().asString();
529 }
530
531 if (descriptor instanceof PropertyGetterDescriptor) {
532 return PropertyCodegen.getterName(property.getName());
533 }
534 else {
535 return PropertyCodegen.setterName(property.getName());
536 }
537 }
538 else if (isLocalNamedFun(descriptor) || descriptor instanceof AnonymousFunctionDescriptor) {
539 return "invoke";
540 }
541 else {
542 return descriptor.getName().asString();
543 }
544 }
545
546 @Nullable
547 private static String getPlatformName(@NotNull Annotated descriptor) {
548 AnnotationDescriptor platformNameAnnotation = descriptor.getAnnotations().findAnnotation(new FqName("kotlin.platform.platformName"));
549 if (platformNameAnnotation == null) return null;
550
551 Map<ValueParameterDescriptor, CompileTimeConstant<?>> arguments = platformNameAnnotation.getAllValueArguments();
552 if (arguments.isEmpty()) return null;
553
554 CompileTimeConstant<?> name = arguments.values().iterator().next();
555 if (!(name instanceof StringValue)) return null;
556
557 return ((StringValue) name).getValue();
558 }
559
560 @NotNull
561 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor descriptor) {
562 return mapSignature(descriptor, OwnerKind.IMPLEMENTATION);
563 }
564
565 @NotNull
566 public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
567 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
568
569 if (f instanceof ConstructorDescriptor) {
570 sw.writeParametersStart();
571 writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
572
573 for (ValueParameterDescriptor parameter : f.getOriginal().getValueParameters()) {
574 writeParameter(sw, parameter.getType());
575 }
576
577 writeVoidReturn(sw);
578 }
579 else {
580 if (f instanceof PropertyAccessorDescriptor) {
581 writeFormalTypeParameters(((PropertyAccessorDescriptor) f).getCorrespondingProperty().getTypeParameters(), sw);
582 }
583 else {
584 writeFormalTypeParameters(f.getTypeParameters(), sw);
585 }
586
587 sw.writeParametersStart();
588 writeThisIfNeeded(f, kind, sw);
589 writeReceiverIfNeeded(f.getReceiverParameter(), sw);
590
591 for (ValueParameterDescriptor parameter : f.getValueParameters()) {
592 writeParameter(sw, parameter.getType());
593 }
594
595 sw.writeReturnType();
596 if (forceBoxedReturnType(f)) {
597 // TYPE_PARAMETER is a hack to automatically box the return type
598 //noinspection ConstantConditions
599 mapType(f.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
600 }
601 else {
602 mapReturnType(f, sw);
603 }
604 sw.writeReturnTypeEnd();
605 }
606
607 return sw.makeJvmMethodSignature(mapFunctionName(f));
608 }
609
610 @NotNull
611 public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind, @NotNull CodegenContext<?> context) {
612 Method jvmSignature = mapSignature(functionDescriptor, kind).getAsmMethod();
613 Type ownerType = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context));
614 String descriptor = jvmSignature.getDescriptor().replace(")", "I)");
615 boolean isConstructor = "<init>".equals(jvmSignature.getName());
616 if (!isStatic(kind) && !isConstructor) {
617 descriptor = descriptor.replace("(", "(" + ownerType.getDescriptor());
618 }
619
620 return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
621 }
622
623 /**
624 * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
625 * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
626 * with a non-primitive return type. In that case the generated method's return type should be boxed: otherwise it's not possible to use
627 * this class from Java since javac issues errors when loading the class (incompatible return types)
628 */
629 private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
630 //noinspection ConstantConditions
631 if (!KotlinBuiltIns.getInstance().isPrimitiveType(descriptor.getReturnType())) return false;
632
633 for (FunctionDescriptor overridden : OverrideResolver.getAllOverriddenDescriptors(descriptor)) {
634 //noinspection ConstantConditions
635 if (!KotlinBuiltIns.getInstance().isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
636 }
637
638 return false;
639 }
640
641 private static void writeVoidReturn(@NotNull BothSignatureWriter sw) {
642 sw.writeReturnType();
643 sw.writeAsmType(Type.VOID_TYPE);
644 sw.writeReturnTypeEnd();
645 }
646
647 @Nullable
648 public String mapFieldSignature(@NotNull JetType backingFieldType) {
649 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
650 mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
651 return sw.makeJavaGenericSignature();
652 }
653
654 private void writeThisIfNeeded(
655 @NotNull CallableMemberDescriptor descriptor,
656 @NotNull OwnerKind kind,
657 @NotNull BothSignatureWriter sw
658 ) {
659 if (kind == OwnerKind.TRAIT_IMPL) {
660 ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
661 Type type = getTraitImplThisParameterType(containingDeclaration, this);
662
663 sw.writeParameterType(JvmMethodParameterKind.THIS);
664 sw.writeAsmType(type);
665 sw.writeParameterTypeEnd();
666 }
667 else if (isAccessor(descriptor) && descriptor.getExpectedThisObject() != null) {
668 sw.writeParameterType(JvmMethodParameterKind.THIS);
669 mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), sw, JetTypeMapperMode.VALUE);
670 sw.writeParameterTypeEnd();
671 }
672 }
673
674
675 public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull BothSignatureWriter sw) {
676 for (TypeParameterDescriptor typeParameter : typeParameters) {
677 writeFormalTypeParameter(typeParameter, sw);
678 }
679 }
680
681 private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull BothSignatureWriter sw) {
682 if (classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && typeParameterDescriptor.getName().isSpecial()) {
683 // If a type parameter has no name, the code below fails, but it should recover in case of light classes
684 return;
685 }
686
687 sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
688
689 classBound:
690 {
691 sw.writeClassBound();
692
693 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
694 if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
695 if (!isInterface(jetType)) {
696 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
697 break classBound;
698 }
699 }
700 }
701
702 // "extends Object" is optional according to ClassFileFormat-Java5.pdf
703 // but javac complaints to signature:
704 // <P:>Ljava/lang/Object;
705 // TODO: avoid writing java/lang/Object if interface list is not empty
706 }
707 sw.writeClassBoundEnd();
708
709 for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
710 ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
711 if (classifier instanceof ClassDescriptor) {
712 if (isInterface(jetType)) {
713 sw.writeInterfaceBound();
714 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
715 sw.writeInterfaceBoundEnd();
716 }
717 }
718 else if (classifier instanceof TypeParameterDescriptor) {
719 sw.writeInterfaceBound();
720 mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
721 sw.writeInterfaceBoundEnd();
722 }
723 else {
724 throw new UnsupportedOperationException("Unknown classifier: " + classifier);
725 }
726 }
727 }
728
729 private void writeReceiverIfNeeded(@Nullable ReceiverParameterDescriptor receiver, @NotNull BothSignatureWriter sw) {
730 if (receiver != null) {
731 sw.writeParameterType(JvmMethodParameterKind.RECEIVER);
732 mapType(receiver.getType(), sw, JetTypeMapperMode.VALUE);
733 sw.writeParameterTypeEnd();
734 }
735 }
736
737 private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JetType type) {
738 sw.writeParameterType(JvmMethodParameterKind.VALUE);
739 mapType(type, sw, JetTypeMapperMode.VALUE);
740 sw.writeParameterTypeEnd();
741 }
742
743 private void writeAdditionalConstructorParameters(
744 @NotNull ConstructorDescriptor descriptor,
745 @NotNull BothSignatureWriter signatureWriter
746 ) {
747 CalculatedClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
748
749 ClassDescriptor captureThis = getExpectedThisObjectForConstructorCall(descriptor, closure);
750 if (captureThis != null) {
751 signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
752 mapType(captureThis.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
753 signatureWriter.writeParameterTypeEnd();
754 }
755
756 JetType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
757 if (captureReceiverType != null) {
758 signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
759 mapType(captureReceiverType, signatureWriter, JetTypeMapperMode.VALUE);
760 signatureWriter.writeParameterTypeEnd();
761 }
762
763 ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
764 if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
765 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
766 mapType(KotlinBuiltIns.getInstance().getStringType(), signatureWriter, JetTypeMapperMode.VALUE);
767 signatureWriter.writeParameterTypeEnd();
768 signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL);
769 mapType(KotlinBuiltIns.getInstance().getIntType(), signatureWriter, JetTypeMapperMode.VALUE);
770 signatureWriter.writeParameterTypeEnd();
771 }
772
773 if (closure == null) return;
774
775 for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
776 Type type;
777 if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
778 Type sharedVarType = getSharedVarType(variableDescriptor);
779 if (sharedVarType == null) {
780 sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
781 }
782 type = sharedVarType;
783 }
784 else if (isLocalNamedFun(variableDescriptor)) {
785 type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
786 }
787 else {
788 type = null;
789 }
790
791 if (type != null) {
792 signatureWriter.writeParameterType(JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE);
793 signatureWriter.writeAsmType(type);
794 signatureWriter.writeParameterTypeEnd();
795 }
796 }
797
798 JetDelegatorToSuperCall superCall = closure.getSuperCall();
799 if (superCall != null) {
800 DeclarationDescriptor superDescriptor = bindingContext
801 .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
802
803 if (superDescriptor instanceof ConstructorDescriptor && isAnonymousObject(descriptor.getContainingDeclaration())) {
804 for (JvmMethodParameterSignature parameter : mapSignature((ConstructorDescriptor) superDescriptor).getValueParameters()) {
805 signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM);
806 signatureWriter.writeAsmType(parameter.getAsmType());
807 signatureWriter.writeParameterTypeEnd();
808 }
809 }
810 }
811 }
812
813 @NotNull
814 public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
815 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
816
817 sw.writeParametersStart();
818
819 for (ScriptDescriptor importedScript : importedScripts) {
820 sw.writeParameterType(JvmMethodParameterKind.VALUE);
821 ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
822 assert descriptor != null;
823 mapType(descriptor.getDefaultType(), sw, JetTypeMapperMode.VALUE);
824 sw.writeParameterTypeEnd();
825 }
826
827 for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
828 writeParameter(sw, valueParameter.getType());
829 }
830
831 writeVoidReturn(sw);
832
833 return sw.makeJvmMethodSignature("<init>");
834 }
835
836 @NotNull
837 public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
838 JvmMethodSignature method = mapSignature(descriptor);
839 ClassDescriptor container = descriptor.getContainingDeclaration();
840 Type owner = mapClass(container);
841 if (owner.getSort() != Type.OBJECT) {
842 throw new IllegalStateException("type must have been mapped to object: " + container.getDefaultType() + ", actual: " + owner);
843 }
844 return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
845 }
846
847 public Type getSharedVarType(DeclarationDescriptor descriptor) {
848 if (descriptor instanceof PropertyDescriptor) {
849 return StackValue.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType()));
850 }
851 else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
852 return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
853 }
854 else if (descriptor instanceof FunctionDescriptor) {
855 return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
856 }
857 else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
858 JetType outType = ((VariableDescriptor) descriptor).getType();
859 return StackValue.sharedTypeForType(mapType(outType));
860 }
861 return null;
862 }
863 }