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.ImmutableMap; 020 import com.google.common.collect.Sets; 021 import com.intellij.openapi.util.Pair; 022 import com.intellij.psi.tree.IElementType; 023 import org.jetbrains.annotations.NotNull; 024 import org.jetbrains.annotations.Nullable; 025 import org.jetbrains.jet.codegen.binding.CalculatedClosure; 026 import org.jetbrains.jet.codegen.binding.CodegenBinding; 027 import org.jetbrains.jet.codegen.state.GenerationState; 028 import org.jetbrains.jet.codegen.state.JetTypeMapper; 029 import org.jetbrains.jet.lang.descriptors.*; 030 import org.jetbrains.jet.lang.psi.JetFile; 031 import org.jetbrains.jet.lang.resolve.BindingContextUtils; 032 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 033 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 034 import org.jetbrains.jet.lang.resolve.java.*; 035 import org.jetbrains.jet.lang.resolve.java.descriptor.JavaCallableMemberDescriptor; 036 import org.jetbrains.jet.lang.resolve.name.FqName; 037 import org.jetbrains.jet.lang.types.JetType; 038 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 039 import org.jetbrains.jet.lexer.JetTokens; 040 import org.jetbrains.org.objectweb.asm.AnnotationVisitor; 041 import org.jetbrains.org.objectweb.asm.Label; 042 import org.jetbrains.org.objectweb.asm.MethodVisitor; 043 import org.jetbrains.org.objectweb.asm.Type; 044 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 045 import org.jetbrains.org.objectweb.asm.commons.Method; 046 047 import java.util.ArrayList; 048 import java.util.List; 049 import java.util.Map; 050 import java.util.Set; 051 052 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*; 053 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 054 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; 055 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME; 056 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; 057 import static org.jetbrains.jet.lang.resolve.java.mapping.PrimitiveTypesUtil.asmTypeForPrimitive; 058 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 059 060 public class AsmUtil { 061 private static final Set<ClassDescriptor> PRIMITIVE_NUMBER_CLASSES = Sets.newHashSet( 062 KotlinBuiltIns.getInstance().getByte(), 063 KotlinBuiltIns.getInstance().getShort(), 064 KotlinBuiltIns.getInstance().getInt(), 065 KotlinBuiltIns.getInstance().getLong(), 066 KotlinBuiltIns.getInstance().getFloat(), 067 KotlinBuiltIns.getInstance().getDouble(), 068 KotlinBuiltIns.getInstance().getChar() 069 ); 070 071 private static final int NO_FLAG_LOCAL = 0; 072 public static final int NO_FLAG_PACKAGE_PRIVATE = 0; 073 074 @NotNull 075 private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder() 076 .put(Visibilities.PRIVATE, ACC_PRIVATE) 077 .put(Visibilities.PROTECTED, ACC_PROTECTED) 078 .put(JavaVisibilities.PROTECTED_STATIC_VISIBILITY, ACC_PROTECTED) 079 .put(JavaVisibilities.PROTECTED_AND_PACKAGE, ACC_PROTECTED) 080 .put(Visibilities.PUBLIC, ACC_PUBLIC) 081 .put(Visibilities.INTERNAL, ACC_PUBLIC) 082 .put(Visibilities.LOCAL, NO_FLAG_LOCAL) 083 .put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE) 084 .build(); 085 086 public static final String CAPTURED_RECEIVER_FIELD = "receiver$0"; 087 public static final String CAPTURED_THIS_FIELD = "this$0"; 088 089 private static final ImmutableMap<Integer, JvmPrimitiveType> primitiveTypeByAsmSort; 090 private static final ImmutableMap<Type, Type> primitiveTypeByBoxedType; 091 092 static { 093 ImmutableMap.Builder<Integer, JvmPrimitiveType> typeBySortBuilder = ImmutableMap.builder(); 094 ImmutableMap.Builder<Type, Type> typeByWrapperBuilder = ImmutableMap.builder(); 095 for (JvmPrimitiveType primitiveType : JvmPrimitiveType.values()) { 096 Type asmType = asmTypeForPrimitive(primitiveType); 097 typeBySortBuilder.put(asmType.getSort(), primitiveType); 098 typeByWrapperBuilder.put(asmTypeByFqNameWithoutInnerClasses(primitiveType.getWrapperFqName()), asmType); 099 } 100 primitiveTypeByAsmSort = typeBySortBuilder.build(); 101 primitiveTypeByBoxedType = typeByWrapperBuilder.build(); 102 } 103 104 private AsmUtil() { 105 } 106 107 @NotNull 108 public static Type boxType(@NotNull Type type) { 109 JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort()); 110 return jvmPrimitiveType != null ? asmTypeByFqNameWithoutInnerClasses(jvmPrimitiveType.getWrapperFqName()) : type; 111 } 112 113 @NotNull 114 public static Type unboxType(@NotNull Type boxedType) { 115 Type primitiveType = primitiveTypeByBoxedType.get(boxedType); 116 if (primitiveType == null) { 117 throw new UnsupportedOperationException("Unboxing: " + boxedType); 118 } 119 return primitiveType; 120 } 121 122 public static boolean isIntPrimitive(Type type) { 123 return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; 124 } 125 126 public static boolean isNumberPrimitive(Type type) { 127 return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE; 128 } 129 130 public static boolean isPrimitive(Type type) { 131 return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY; 132 } 133 134 public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) { 135 if (!(descriptor instanceof ClassDescriptor)) { 136 return false; 137 } 138 return PRIMITIVE_NUMBER_CLASSES.contains(descriptor); 139 } 140 141 public static Type correctElementType(Type type) { 142 String internalName = type.getInternalName(); 143 assert internalName.charAt(0) == '['; 144 return Type.getType(internalName.substring(1)); 145 } 146 147 public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { 148 return (functionDescriptor.getModality() == Modality.ABSTRACT 149 || isInterface(functionDescriptor.getContainingDeclaration())) 150 && !isStaticMethod(kind, functionDescriptor); 151 } 152 153 public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) { 154 return isStatic(kind) || JetTypeMapper.isAccessor(functionDescriptor); 155 } 156 157 public static boolean isStatic(OwnerKind kind) { 158 return kind == OwnerKind.PACKAGE || kind == OwnerKind.TRAIT_IMPL; 159 } 160 161 public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) { 162 int flags = getCommonCallableFlags(functionDescriptor); 163 164 if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) { 165 DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); 166 if (!(containingDeclaration instanceof ClassDescriptor) || 167 ((ClassDescriptor) containingDeclaration).getKind() != ClassKind.TRAIT) { 168 flags |= ACC_FINAL; 169 } 170 } 171 172 if (isStaticMethod(kind, functionDescriptor)) { 173 flags |= ACC_STATIC; 174 } 175 176 if (isAbstractMethod(functionDescriptor, kind)) { 177 flags |= ACC_ABSTRACT; 178 } 179 180 if (JetTypeMapper.isAccessor(functionDescriptor)) { 181 flags |= ACC_SYNTHETIC; 182 } 183 184 return flags; 185 } 186 187 private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) { 188 int flags = getVisibilityAccessFlag(functionDescriptor); 189 flags |= getVarargsFlag(functionDescriptor); 190 flags |= getDeprecatedAccessFlag(functionDescriptor); 191 return flags; 192 } 193 194 //TODO: move mapping logic to front-end java 195 public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) { 196 Integer specialCase = specialCaseVisibility(descriptor); 197 if (specialCase != null) { 198 return specialCase; 199 } 200 Integer defaultMapping = visibilityToAccessFlag.get(descriptor.getVisibility()); 201 if (defaultMapping == null) { 202 throw new IllegalStateException(descriptor.getVisibility() + " is not a valid visibility in backend. Descriptor: " + descriptor); 203 } 204 return defaultMapping; 205 } 206 207 /* 208 Use this method to get visibility flag for class to define it in byte code (v.defineClass method). 209 For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor) 210 Classes in byte code should be public or package private 211 */ 212 public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) { 213 if (DescriptorUtils.isTopLevelDeclaration(descriptor) || 214 descriptor.getVisibility() == Visibilities.PUBLIC || 215 descriptor.getVisibility() == Visibilities.INTERNAL) { 216 return ACC_PUBLIC; 217 } 218 return NO_FLAG_PACKAGE_PRIVATE; 219 } 220 221 222 public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { 223 if (isDeclarationInsideInlineFunction(descriptor)) { 224 return ACC_PUBLIC; 225 } 226 return NO_FLAG_PACKAGE_PRIVATE; 227 } 228 229 public static boolean isDeclarationInsideInlineFunction(@NotNull ClassDescriptor descriptor) { 230 //NB: constructor context couldn't be inline 231 DeclarationDescriptor parentDeclaration = descriptor.getContainingDeclaration(); 232 if (parentDeclaration instanceof SimpleFunctionDescriptor && 233 ((SimpleFunctionDescriptor) parentDeclaration).getInlineStrategy().isInline()) { 234 return true; 235 } 236 return false; 237 } 238 239 public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { 240 if (descriptor instanceof PropertyAccessorDescriptor) { 241 return KotlinBuiltIns.getInstance().isDeprecated(descriptor) 242 ? ACC_DEPRECATED 243 : getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); 244 } 245 else if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) { 246 return ACC_DEPRECATED; 247 } 248 return 0; 249 } 250 251 private static int getVarargsFlag(FunctionDescriptor functionDescriptor) { 252 if (!functionDescriptor.getValueParameters().isEmpty() 253 && functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1) 254 .getVarargElementType() != null) { 255 return ACC_VARARGS; 256 } 257 return 0; 258 } 259 260 @Nullable 261 private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) { 262 DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); 263 if (isInterface(containingDeclaration)) { 264 return ACC_PUBLIC; 265 } 266 Visibility memberVisibility = memberDescriptor.getVisibility(); 267 if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) { 268 return ACC_PUBLIC; 269 } 270 if (isEnumEntry(memberDescriptor)) { 271 return NO_FLAG_PACKAGE_PRIVATE; 272 } 273 if (memberVisibility != Visibilities.PRIVATE) { 274 return null; 275 } 276 // the following code is only for PRIVATE visibility of member 277 if (memberDescriptor instanceof ConstructorDescriptor) { 278 if (isAnonymousObject(containingDeclaration)) { 279 return NO_FLAG_PACKAGE_PRIVATE; 280 } 281 282 ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind(); 283 if (kind == ClassKind.OBJECT) { 284 return NO_FLAG_PACKAGE_PRIVATE; 285 } 286 else if (kind == ClassKind.ENUM_ENTRY) { 287 return NO_FLAG_PACKAGE_PRIVATE; 288 } 289 else if (kind == ClassKind.ENUM_CLASS) { 290 //TODO: should be ACC_PRIVATE 291 // see http://youtrack.jetbrains.com/issue/KT-2680 292 return ACC_PROTECTED; 293 } 294 } 295 if (containingDeclaration instanceof PackageFragmentDescriptor) { 296 return ACC_PUBLIC; 297 } 298 return null; 299 } 300 301 @NotNull 302 public static Type getTraitImplThisParameterType(@NotNull ClassDescriptor traitDescriptor, @NotNull JetTypeMapper typeMapper) { 303 JetType jetType = getSuperClass(traitDescriptor); 304 Type type = typeMapper.mapType(jetType); 305 if (type.getInternalName().equals("java/lang/Object")) { 306 return typeMapper.mapType(traitDescriptor.getDefaultType()); 307 } 308 return type; 309 } 310 311 private static Type stringValueOfOrStringBuilderAppendType(Type type) { 312 int sort = type.getSort(); 313 return sort == Type.OBJECT || sort == Type.ARRAY 314 ? AsmTypeConstants.OBJECT_TYPE 315 : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type; 316 } 317 318 public static void genThrow(@NotNull MethodVisitor mv, @NotNull String exception, @NotNull String message) { 319 InstructionAdapter iv = new InstructionAdapter(mv); 320 iv.anew(Type.getObjectType(exception)); 321 iv.dup(); 322 iv.aconst(message); 323 iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V"); 324 iv.athrow(); 325 } 326 327 public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) { 328 List<Pair<String, Type>> allFields = new ArrayList<Pair<String, Type>>(); 329 330 ClassifierDescriptor captureThis = closure.getCaptureThis(); 331 if (captureThis != null) { 332 allFields.add(Pair.create(CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis))); 333 } 334 335 JetType captureReceiverType = closure.getCaptureReceiverType(); 336 if (captureReceiverType != null) { 337 allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType))); 338 } 339 340 allFields.addAll(closure.getRecordedFields()); 341 genClosureFields(allFields, v); 342 } 343 344 public static void genClosureFields(List<Pair<String, Type>> allFields, ClassBuilder builder) { 345 //noinspection PointlessBitwiseExpression 346 int access = NO_FLAG_PACKAGE_PRIVATE | ACC_SYNTHETIC | ACC_FINAL; 347 for (Pair<String, Type> field : allFields) { 348 builder.newField(null, access, field.first, field.second.getDescriptor(), null, null); 349 } 350 } 351 352 public static List<FieldInfo> transformCapturedParams(List<Pair<String, Type>> allFields, Type owner) { 353 List<FieldInfo> result = new ArrayList<FieldInfo>(); 354 for (Pair<String, Type> field : allFields) { 355 result.add(FieldInfo.createForHiddenField(owner, field.second, field.first)); 356 } 357 return result; 358 } 359 360 public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { 361 assert !info.isStatic(); 362 Type fieldType = info.getFieldType(); 363 iv.load(0, info.getOwnerType());//this 364 iv.load(index, fieldType); //param 365 iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); 366 index += fieldType.getSize(); 367 return index; 368 } 369 370 public static void genStringBuilderConstructor(InstructionAdapter v) { 371 v.visitTypeInsn(NEW, "java/lang/StringBuilder"); 372 v.dup(); 373 v.invokespecial("java/lang/StringBuilder", "<init>", "()V"); 374 } 375 376 public static void genInvokeAppendMethod(InstructionAdapter v, Type type) { 377 type = stringValueOfOrStringBuilderAppendType(type); 378 v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;"); 379 } 380 381 public static StackValue genToString(InstructionAdapter v, StackValue receiver, Type receiverType) { 382 Type type = stringValueOfOrStringBuilderAppendType(receiverType); 383 receiver.put(type, v); 384 v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;"); 385 return StackValue.onStack(JAVA_STRING_TYPE); 386 } 387 388 static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) { 389 if (type.getSort() == Type.ARRAY) { 390 Type elementType = correctElementType(type); 391 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 392 iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I"); 393 } 394 else { 395 iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I"); 396 } 397 } 398 else if (type.getSort() == Type.OBJECT) { 399 iv.invokevirtual("java/lang/Object", "hashCode", "()I"); 400 } 401 else if (type.getSort() == Type.LONG) { 402 genLongHashCode(mv, iv); 403 } 404 else if (type.getSort() == Type.DOUBLE) { 405 iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J"); 406 genLongHashCode(mv, iv); 407 } 408 else if (type.getSort() == Type.FLOAT) { 409 iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I"); 410 } 411 else if (type.getSort() == Type.BOOLEAN) { 412 Label end = new Label(); 413 iv.dup(); 414 iv.ifeq(end); 415 iv.pop(); 416 iv.iconst(1); 417 iv.mark(end); 418 } 419 else { // byte short char int 420 // do nothing 421 } 422 } 423 424 private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) { 425 iv.dup2(); 426 iv.iconst(32); 427 iv.ushr(Type.LONG_TYPE); 428 iv.xor(Type.LONG_TYPE); 429 mv.visitInsn(L2I); 430 } 431 432 static void genInvertBoolean(InstructionAdapter v) { 433 v.iconst(1); 434 v.xor(Type.INT_TYPE); 435 } 436 437 public static StackValue genEqualsForExpressionsOnStack( 438 InstructionAdapter v, 439 IElementType opToken, 440 Type leftType, 441 Type rightType 442 ) { 443 if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) { 444 return StackValue.cmp(opToken, leftType); 445 } 446 else { 447 if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 448 return StackValue.cmp(opToken, leftType); 449 } 450 else { 451 v.invokestatic("kotlin/jvm/internal/Intrinsics", "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z"); 452 453 if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) { 454 genInvertBoolean(v); 455 } 456 457 return StackValue.onStack(Type.BOOLEAN_TYPE); 458 } 459 } 460 } 461 462 public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) { 463 if (expectedType == Type.LONG_TYPE) { 464 v.lconst(myDelta); 465 } 466 else if (expectedType == Type.FLOAT_TYPE) { 467 v.fconst(myDelta); 468 } 469 else if (expectedType == Type.DOUBLE_TYPE) { 470 v.dconst(myDelta); 471 } 472 else { 473 v.iconst(myDelta); 474 v.add(Type.INT_TYPE); 475 StackValue.coerce(Type.INT_TYPE, expectedType, v); 476 return; 477 } 478 v.add(expectedType); 479 } 480 481 public static Type genNegate(Type expectedType, InstructionAdapter v) { 482 if (expectedType == Type.BYTE_TYPE || expectedType == Type.SHORT_TYPE || expectedType == Type.CHAR_TYPE) { 483 expectedType = Type.INT_TYPE; 484 } 485 v.neg(expectedType); 486 return expectedType; 487 } 488 489 public static void swap(InstructionAdapter v, Type stackTop, Type afterTop) { 490 if (stackTop.getSize() == 1) { 491 if (afterTop.getSize() == 1) { 492 v.swap(); 493 } else { 494 v.dupX2(); 495 v.pop(); 496 } 497 } else { 498 if (afterTop.getSize() == 1) { 499 v.dup2X1(); 500 } else { 501 v.dup2X2(); 502 } 503 v.pop2(); 504 } 505 } 506 507 public static void genNotNullAssertionsForParameters( 508 @NotNull InstructionAdapter v, 509 @NotNull GenerationState state, 510 @NotNull FunctionDescriptor descriptor, 511 @NotNull FrameMap frameMap 512 ) { 513 if (!state.isGenerateNotNullParamAssertions()) return; 514 515 // Private method is not accessible from other classes, no assertions needed 516 if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return; 517 518 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) { 519 JetType type = parameter.getReturnType(); 520 if (type == null || isNullableType(type)) continue; 521 522 int index = frameMap.getIndex(parameter); 523 Type asmType = state.getTypeMapper().mapType(type); 524 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 525 v.load(index, asmType); 526 v.visitLdcInsn(parameter.getName().asString()); 527 v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkParameterIsNotNull", "(Ljava/lang/Object;Ljava/lang/String;)V"); 528 } 529 } 530 } 531 532 public static void genNotNullAssertionForField( 533 @NotNull InstructionAdapter v, 534 @NotNull GenerationState state, 535 @NotNull PropertyDescriptor descriptor 536 ) { 537 genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull"); 538 } 539 540 public static void genNotNullAssertionForMethod( 541 @NotNull InstructionAdapter v, 542 @NotNull GenerationState state, 543 @NotNull ResolvedCall resolvedCall 544 ) { 545 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 546 if (descriptor instanceof ConstructorDescriptor) return; 547 548 genNotNullAssertion(v, state, descriptor, "checkReturnedValueIsNotNull"); 549 } 550 551 private static void genNotNullAssertion( 552 @NotNull InstructionAdapter v, 553 @NotNull GenerationState state, 554 @NotNull CallableDescriptor descriptor, 555 @NotNull String assertMethodToCall 556 ) { 557 if (!state.isGenerateNotNullAssertions()) return; 558 559 if (!isDeclaredInJava(descriptor)) return; 560 561 JetType type = descriptor.getReturnType(); 562 if (type == null || isNullableType(type)) return; 563 564 Type asmType = state.getTypeMapper().mapReturnType(descriptor); 565 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 566 v.dup(); 567 v.visitLdcInsn(descriptor.getContainingDeclaration().getName().asString()); 568 v.visitLdcInsn(descriptor.getName().asString()); 569 v.invokestatic("kotlin/jvm/internal/Intrinsics", assertMethodToCall, "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V"); 570 } 571 } 572 573 private static boolean isDeclaredInJava(@NotNull CallableDescriptor callableDescriptor) { 574 CallableDescriptor descriptor = callableDescriptor; 575 while (true) { 576 if (descriptor instanceof JavaCallableMemberDescriptor) { 577 return true; 578 } 579 CallableDescriptor original = descriptor.getOriginal(); 580 if (descriptor == original) break; 581 descriptor = original; 582 } 583 return false; 584 } 585 586 public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 587 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 588 v.aconst(null); 589 } 590 else { 591 pushDefaultPrimitiveValueOnStack(type, v); 592 } 593 } 594 595 public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 596 if (type.getSort() == Type.FLOAT) { 597 v.fconst(0); 598 } 599 else if (type.getSort() == Type.DOUBLE) { 600 v.dconst(0); 601 } 602 else if (type.getSort() == Type.LONG) { 603 v.lconst(0); 604 } 605 else { 606 v.iconst(0); 607 } 608 } 609 610 public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 611 return isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.CLASS); 612 } 613 614 public static int getVisibilityForSpecialPropertyBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) { 615 boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null; 616 if (isDelegate || isExtensionProperty) { 617 return ACC_PRIVATE; 618 } else { 619 return areBothAccessorDefault(propertyDescriptor) ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) : ACC_PRIVATE; 620 } 621 } 622 623 private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) { 624 if (!propertyDescriptor.isVar() ) { 625 return propertyDescriptor; 626 } else { 627 return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor; 628 } 629 } 630 631 public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 632 boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null; 633 return !propertyDescriptor.isVar() && !isExtensionProperty 634 && isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.TRAIT) 635 && areBothAccessorDefault(propertyDescriptor) 636 && getVisibilityForSpecialPropertyBackingField(propertyDescriptor, false) == ACC_PUBLIC; 637 } 638 639 public static boolean isClassObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor classObject) { 640 return isPropertyWithSpecialBackingField(classObject, ClassKind.CLASS); 641 } 642 643 private static boolean areBothAccessorDefault(@NotNull PropertyDescriptor propertyDescriptor) { 644 return isAccessorWithEmptyBody(propertyDescriptor.getGetter()) 645 && (!propertyDescriptor.isVar() || isAccessorWithEmptyBody(propertyDescriptor.getSetter())); 646 } 647 648 private static boolean isAccessorWithEmptyBody(@Nullable PropertyAccessorDescriptor accessorDescriptor) { 649 return accessorDescriptor == null || !accessorDescriptor.hasBody(); 650 } 651 652 private static boolean isPropertyWithSpecialBackingField(@NotNull DeclarationDescriptor classObject, ClassKind kind) { 653 return isClassObject(classObject) && isKindOf(classObject.getContainingDeclaration(), kind); 654 } 655 656 public static Type comparisonOperandType(Type left, Type right) { 657 if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE; 658 if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE; 659 if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE; 660 return Type.INT_TYPE; 661 } 662 663 @NotNull 664 public static Type numberFunctionOperandType(@NotNull Type expectedType) { 665 if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE) { 666 return Type.INT_TYPE; 667 } 668 return expectedType; 669 } 670 671 public static void pop(@NotNull InstructionAdapter v, @NotNull Type type) { 672 if (type.getSize() == 2) { 673 v.pop2(); 674 } 675 else { 676 v.pop(); 677 } 678 } 679 680 public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) { 681 if (type.getSize() == 2) { 682 v.dup2(); 683 } 684 else { 685 v.dup(); 686 } 687 } 688 689 public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull KotlinSyntheticClass.Kind kind) { 690 AnnotationVisitor av = v.newAnnotation(Type.getObjectType(KotlinSyntheticClass.CLASS_NAME.getInternalName()).getDescriptor(), true); 691 av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); 692 av.visitEnum(KotlinSyntheticClass.KIND_FIELD_NAME.asString(), 693 Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(), 694 kind.toString()); 695 av.visitEnd(); 696 } 697 698 @NotNull 699 public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 700 return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor(); 701 } 702 703 @NotNull 704 public static String shortNameByAsmType(@NotNull Type type) { 705 String internalName = type.getInternalName(); 706 int lastSlash = internalName.lastIndexOf('/'); 707 return lastSlash < 0 ? internalName : internalName.substring(lastSlash + 1); 708 } 709 710 @NotNull 711 public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 712 return Type.getObjectType(JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName()); 713 } 714 715 public static void writeOuterClassAndEnclosingMethod( 716 @NotNull ClassDescriptor descriptor, 717 @NotNull DeclarationDescriptor originalDescriptor, 718 @NotNull JetTypeMapper typeMapper, 719 @NotNull ClassBuilder v 720 ) { 721 String outerClassName = getOuterClassName(descriptor, originalDescriptor, typeMapper); 722 FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class); 723 724 if (function != null) { 725 Method method = typeMapper.mapSignature(function).getAsmMethod(); 726 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor()); 727 } 728 else { 729 v.visitOuterClass(outerClassName, null, null); 730 } 731 } 732 733 @NotNull 734 private static String getOuterClassName(@NotNull ClassDescriptor classDescriptor, @NotNull DeclarationDescriptor originalDescriptor, @NotNull JetTypeMapper typeMapper) { 735 DeclarationDescriptor container = classDescriptor.getContainingDeclaration(); 736 while (container != null) { 737 if (container instanceof ClassDescriptor) { 738 return typeMapper.mapClass((ClassDescriptor)container).getInternalName(); 739 } else if (CodegenBinding.isLocalFunOrLambda(container)) { 740 ClassDescriptor descriptor = 741 CodegenBinding.anonymousClassForFunction(typeMapper.getBindingContext(), (FunctionDescriptor) container); 742 return typeMapper.mapClass(descriptor).getInternalName(); 743 } 744 745 container = container.getContainingDeclaration(); 746 } 747 748 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), originalDescriptor); 749 assert containingFile != null : "Containing file should be present for " + classDescriptor; 750 return PackageCodegen.getPackagePartInternalName(containingFile); 751 } 752 753 }