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