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