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.isConstOrHasJvmFieldAnnotation; 065 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; 066 import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS; 067 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; 068 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 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 (descriptor.getVisibility() == Visibilities.PUBLIC || 261 // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes 262 descriptor.getVisibility() == Visibilities.LOCAL || 263 descriptor.getVisibility() == Visibilities.INTERNAL) { 264 return ACC_PUBLIC; 265 } 266 return NO_FLAG_PACKAGE_PRIVATE; 267 } 268 269 public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { 270 return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; 271 } 272 273 public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { 274 int visibility = (innerClass.getVisibility() == Visibilities.LOCAL) ? ACC_PUBLIC : getVisibilityAccessFlag(innerClass); 275 return visibility | 276 innerAccessFlagsForModalityAndKind(innerClass) | 277 (innerClass.isInner() ? 0 : ACC_STATIC); 278 } 279 280 private static int innerAccessFlagsForModalityAndKind(@NotNull ClassDescriptor innerClass) { 281 switch (innerClass.getKind()) { 282 case INTERFACE: 283 return ACC_ABSTRACT | ACC_INTERFACE; 284 case ENUM_CLASS: 285 return ACC_FINAL | ACC_ENUM; 286 case ANNOTATION_CLASS: 287 return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE; 288 default: 289 if (innerClass.getModality() == Modality.FINAL) { 290 return ACC_FINAL; 291 } 292 else if (innerClass.getModality() == Modality.ABSTRACT) { 293 return ACC_ABSTRACT; 294 } 295 } 296 return 0; 297 } 298 299 public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { 300 if (descriptor instanceof PropertyAccessorDescriptor) { 301 return KotlinBuiltIns.isDeprecated(descriptor) 302 ? ACC_DEPRECATED 303 : getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); 304 } 305 else if (KotlinBuiltIns.isDeprecated(descriptor)) { 306 return ACC_DEPRECATED; 307 } 308 return 0; 309 } 310 311 private static int getVarargsFlag(FunctionDescriptor functionDescriptor) { 312 if (!functionDescriptor.getValueParameters().isEmpty() 313 && functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1) 314 .getVarargElementType() != null) { 315 return ACC_VARARGS; 316 } 317 return 0; 318 } 319 320 @Nullable 321 private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) { 322 DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); 323 Visibility memberVisibility = memberDescriptor.getVisibility(); 324 325 if (AnnotationUtilKt.isInlineOnly(memberDescriptor)) return ACC_PRIVATE; 326 327 if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) { 328 return ACC_PUBLIC; 329 } 330 331 if (isEnumEntry(memberDescriptor)) { 332 return NO_FLAG_PACKAGE_PRIVATE; 333 } 334 335 if (memberDescriptor instanceof ConstructorDescriptor && isAnonymousObject(memberDescriptor.getContainingDeclaration())) { 336 return getVisibilityAccessFlagForAnonymous((ClassDescriptor) memberDescriptor.getContainingDeclaration()); 337 } 338 339 if (memberDescriptor instanceof SyntheticJavaPropertyDescriptor) { 340 return getVisibilityAccessFlag(((SyntheticJavaPropertyDescriptor) memberDescriptor).getGetMethod()); 341 } 342 if (memberDescriptor instanceof PropertyAccessorDescriptor) { 343 PropertyDescriptor property = ((PropertyAccessorDescriptor) memberDescriptor).getCorrespondingProperty(); 344 if (property instanceof SyntheticJavaPropertyDescriptor) { 345 FunctionDescriptor method = memberDescriptor == property.getGetter() 346 ? ((SyntheticJavaPropertyDescriptor) property).getGetMethod() 347 : ((SyntheticJavaPropertyDescriptor) property).getSetMethod(); 348 assert method != null : "No get/set method in SyntheticJavaPropertyDescriptor: " + property; 349 return getVisibilityAccessFlag(method); 350 } 351 } 352 353 if (memberDescriptor instanceof CallableDescriptor && memberVisibility == Visibilities.PROTECTED) { 354 for (CallableDescriptor overridden : DescriptorUtils.getAllOverriddenDescriptors((CallableDescriptor) memberDescriptor)) { 355 if (isJvmInterface(overridden.getContainingDeclaration())) { 356 return ACC_PUBLIC; 357 } 358 } 359 } 360 361 if (!Visibilities.isPrivate(memberVisibility)) { 362 return null; 363 } 364 365 // the following code is only for PRIVATE visibility of member 366 if (memberDescriptor instanceof ConstructorDescriptor) { 367 if (isEnumEntry(containingDeclaration)) { 368 return NO_FLAG_PACKAGE_PRIVATE; 369 } 370 if (isEnumClass(containingDeclaration)) { 371 //TODO: should be ACC_PRIVATE 372 // see http://youtrack.jetbrains.com/issue/KT-2680 373 return ACC_PROTECTED; 374 } 375 } 376 377 return null; 378 } 379 380 public static Type stringValueOfType(Type type) { 381 int sort = type.getSort(); 382 return sort == Type.OBJECT || sort == Type.ARRAY 383 ? OBJECT_TYPE 384 : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type; 385 } 386 387 private static Type stringBuilderAppendType(Type type) { 388 switch (type.getSort()) { 389 case Type.OBJECT: 390 return STRING_BUILDER_OBJECT_APPEND_ARG_TYPES.contains(type) ? type : OBJECT_TYPE; 391 case Type.ARRAY: 392 return OBJECT_TYPE; 393 case Type.BYTE: 394 case Type.SHORT: 395 return Type.INT_TYPE; 396 default: 397 return type; 398 } 399 } 400 401 public static void genThrow(@NotNull InstructionAdapter v, @NotNull String exception, @Nullable String message) { 402 v.anew(Type.getObjectType(exception)); 403 v.dup(); 404 if (message != null) { 405 v.aconst(message); 406 v.invokespecial(exception, "<init>", "(Ljava/lang/String;)V", false); 407 } 408 else { 409 v.invokespecial(exception, "<init>", "()V", false); 410 } 411 v.athrow(); 412 } 413 414 public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) { 415 List<Pair<String, Type>> allFields = new ArrayList<Pair<String, Type>>(); 416 417 ClassifierDescriptor captureThis = closure.getCaptureThis(); 418 if (captureThis != null) { 419 allFields.add(Pair.create(CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis))); 420 } 421 422 KotlinType captureReceiverType = closure.getCaptureReceiverType(); 423 if (captureReceiverType != null) { 424 allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType))); 425 } 426 427 allFields.addAll(closure.getRecordedFields()); 428 genClosureFields(allFields, v); 429 } 430 431 public static void genClosureFields(List<Pair<String, Type>> allFields, ClassBuilder builder) { 432 //noinspection PointlessBitwiseExpression 433 int access = NO_FLAG_PACKAGE_PRIVATE | ACC_SYNTHETIC | ACC_FINAL; 434 for (Pair<String, Type> field : allFields) { 435 builder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, field.first, field.second.getDescriptor(), null, null); 436 } 437 } 438 439 public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { 440 assert !info.isStatic(); 441 Type fieldType = info.getFieldType(); 442 iv.load(0, info.getOwnerType());//this 443 iv.load(index, fieldType); //param 444 iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); 445 index += fieldType.getSize(); 446 return index; 447 } 448 449 public static void genStringBuilderConstructor(InstructionAdapter v) { 450 v.visitTypeInsn(NEW, "java/lang/StringBuilder"); 451 v.dup(); 452 v.invokespecial("java/lang/StringBuilder", "<init>", "()V", false); 453 } 454 455 public static void genInvokeAppendMethod(InstructionAdapter v, Type type) { 456 type = stringBuilderAppendType(type); 457 v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;", false); 458 } 459 460 public static StackValue genToString(final StackValue receiver, final Type receiverType) { 461 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 462 @Override 463 public Unit invoke(InstructionAdapter v) { 464 Type type = stringValueOfType(receiverType); 465 receiver.put(type, v); 466 v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false); 467 return null; 468 } 469 }); 470 } 471 472 static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) { 473 if (type.getSort() == Type.ARRAY) { 474 Type elementType = correctElementType(type); 475 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 476 iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I", false); 477 } 478 else { 479 iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I", false); 480 } 481 } 482 else if (type.getSort() == Type.OBJECT) { 483 iv.invokevirtual("java/lang/Object", "hashCode", "()I", false); 484 } 485 else if (type.getSort() == Type.LONG) { 486 genLongHashCode(mv, iv); 487 } 488 else if (type.getSort() == Type.DOUBLE) { 489 iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false); 490 genLongHashCode(mv, iv); 491 } 492 else if (type.getSort() == Type.FLOAT) { 493 iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false); 494 } 495 else if (type.getSort() == Type.BOOLEAN) { 496 Label end = new Label(); 497 iv.dup(); 498 iv.ifeq(end); 499 iv.pop(); 500 iv.iconst(1); 501 iv.mark(end); 502 } 503 else { // byte short char int 504 // do nothing 505 } 506 } 507 508 private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) { 509 iv.dup2(); 510 iv.iconst(32); 511 iv.ushr(Type.LONG_TYPE); 512 iv.xor(Type.LONG_TYPE); 513 mv.visitInsn(L2I); 514 } 515 516 static void genInvertBoolean(InstructionAdapter v) { 517 v.iconst(1); 518 v.xor(Type.INT_TYPE); 519 } 520 521 @NotNull 522 public static StackValue genEqualsForExpressionsOnStack( 523 final @NotNull IElementType opToken, 524 final @NotNull StackValue left, 525 final @NotNull StackValue right 526 ) { 527 final Type leftType = left.type; 528 final Type rightType = right.type; 529 if (isPrimitive(leftType) && leftType == rightType) { 530 return StackValue.cmp(opToken, leftType, left, right); 531 } 532 533 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 534 @Override 535 public Unit invoke(InstructionAdapter v) { 536 left.put(leftType, v); 537 right.put(rightType, v); 538 genAreEqualCall(v); 539 540 if (opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ) { 541 genInvertBoolean(v); 542 } 543 return Unit.INSTANCE; 544 } 545 }); 546 } 547 548 public static void genAreEqualCall(InstructionAdapter v) { 549 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); 550 } 551 552 public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) { 553 if (expectedType == Type.LONG_TYPE) { 554 v.lconst(myDelta); 555 } 556 else if (expectedType == Type.FLOAT_TYPE) { 557 v.fconst(myDelta); 558 } 559 else if (expectedType == Type.DOUBLE_TYPE) { 560 v.dconst(myDelta); 561 } 562 else { 563 v.iconst(myDelta); 564 v.add(Type.INT_TYPE); 565 StackValue.coerce(Type.INT_TYPE, expectedType, v); 566 return; 567 } 568 v.add(expectedType); 569 } 570 571 public static void swap(InstructionAdapter v, Type stackTop, Type afterTop) { 572 if (stackTop.getSize() == 1) { 573 if (afterTop.getSize() == 1) { 574 v.swap(); 575 } 576 else { 577 v.dupX2(); 578 v.pop(); 579 } 580 } 581 else { 582 if (afterTop.getSize() == 1) { 583 v.dup2X1(); 584 } 585 else { 586 v.dup2X2(); 587 } 588 v.pop2(); 589 } 590 } 591 592 public static void genNotNullAssertionsForParameters( 593 @NotNull InstructionAdapter v, 594 @NotNull GenerationState state, 595 @NotNull FunctionDescriptor descriptor, 596 @NotNull FrameMap frameMap 597 ) { 598 if (!state.isParamAssertionsEnabled()) return; 599 600 // Private method is not accessible from other classes, no assertions needed 601 if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return; 602 603 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 604 if (receiverParameter != null) { 605 genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver"); 606 } 607 608 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) { 609 genParamAssertion(v, state.getTypeMapper(), frameMap, parameter, parameter.getName().asString()); 610 } 611 } 612 613 private static void genParamAssertion( 614 @NotNull InstructionAdapter v, 615 @NotNull JetTypeMapper typeMapper, 616 @NotNull FrameMap frameMap, 617 @NotNull CallableDescriptor parameter, 618 @NotNull String name 619 ) { 620 KotlinType type = parameter.getReturnType(); 621 if (type == null || isNullableType(type)) return; 622 623 int index = frameMap.getIndex(parameter); 624 Type asmType = typeMapper.mapType(type); 625 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 626 v.load(index, asmType); 627 v.visitLdcInsn(name); 628 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull", 629 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 630 } 631 } 632 633 @NotNull 634 public static StackValue genNotNullAssertions( 635 @NotNull GenerationState state, 636 @NotNull final StackValue stackValue, 637 @Nullable final RuntimeAssertionInfo runtimeAssertionInfo 638 ) { 639 if (!state.isCallAssertionsEnabled()) return stackValue; 640 if (runtimeAssertionInfo == null || !runtimeAssertionInfo.getNeedNotNullAssertion()) return stackValue; 641 642 return new StackValue(stackValue.type) { 643 644 @Override 645 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 646 stackValue.put(type, v); 647 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 648 v.dup(); 649 v.visitLdcInsn(runtimeAssertionInfo.getMessage()); 650 v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull", 651 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 652 } 653 } 654 }; 655 } 656 657 public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 658 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 659 v.aconst(null); 660 } 661 else { 662 pushDefaultPrimitiveValueOnStack(type, v); 663 } 664 } 665 666 public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 667 if (type.getSort() == Type.FLOAT) { 668 v.fconst(0); 669 } 670 else if (type.getSort() == Type.DOUBLE) { 671 v.dconst(0); 672 } 673 else if (type.getSort() == Type.LONG) { 674 v.lconst(0); 675 } 676 else { 677 v.iconst(0); 678 } 679 } 680 681 public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) { 682 return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && 683 isObject(propertyDescriptor.getContainingDeclaration()); 684 } 685 686 public static int getVisibilityForBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) { 687 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 688 if (isDelegate || isExtensionProperty) { 689 return ACC_PRIVATE; 690 } 691 else { 692 return propertyDescriptor.isLateInit() || isConstOrHasJvmFieldAnnotation(propertyDescriptor) 693 ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) 694 : ACC_PRIVATE; 695 } 696 } 697 698 private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) { 699 if (!propertyDescriptor.isVar()) { 700 return propertyDescriptor; 701 } 702 else { 703 return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor; 704 } 705 } 706 707 public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 708 DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration(); 709 return propertyDescriptor.isConst() 710 && isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration()) 711 && getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC; 712 } 713 714 public static Type comparisonOperandType(Type left, Type right) { 715 if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE; 716 if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE; 717 if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE; 718 return Type.INT_TYPE; 719 } 720 721 @NotNull 722 public static Type numberFunctionOperandType(@NotNull Type expectedType) { 723 if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE || expectedType == Type.CHAR_TYPE) { 724 return Type.INT_TYPE; 725 } 726 return expectedType; 727 } 728 729 public static void pop(@NotNull MethodVisitor v, @NotNull Type type) { 730 if (type.getSize() == 2) { 731 v.visitInsn(Opcodes.POP2); 732 } 733 else { 734 v.visitInsn(Opcodes.POP); 735 } 736 } 737 738 public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) { 739 dup(v, type.getSize()); 740 } 741 742 private static void dup(@NotNull InstructionAdapter v, int size) { 743 if (size == 2) { 744 v.dup2(); 745 } 746 else if (size == 1) { 747 v.dup(); 748 } 749 else { 750 throw new UnsupportedOperationException(); 751 } 752 } 753 754 public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) { 755 if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) { 756 return; 757 } 758 759 if (topOfStack.getSize() == 0) { 760 dup(v, afterTop); 761 } 762 else if (afterTop.getSize() == 0) { 763 dup(v, topOfStack); 764 } 765 else if (afterTop.getSize() == 1) { 766 if (topOfStack.getSize() == 1) { 767 dup(v, 2); 768 } 769 else { 770 v.dup2X1(); 771 v.pop2(); 772 v.dupX2(); 773 v.dupX2(); 774 v.pop(); 775 v.dup2X1(); 776 } 777 } 778 else { 779 //Note: it's possible to write dup3 and dup4 780 throw new UnsupportedOperationException("Don't know how generate dup3/dup4 for: " + topOfStack + " and " + afterTop); 781 } 782 } 783 784 public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull GenerationState state) { 785 AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), true); 786 JvmCodegenUtil.writeAbiVersion(av); 787 av.visitEnd(); 788 } 789 790 public static void writeAnnotationData( 791 @NotNull AnnotationVisitor av, 792 @NotNull DescriptorSerializer serializer, 793 @NotNull MessageLite message, 794 boolean old 795 ) { 796 byte[] bytes = serializer.serialize(message); 797 798 AnnotationVisitor data = av.visitArray(old ? JvmAnnotationNames.DATA_FIELD_NAME : JvmAnnotationNames.METADATA_DATA_FIELD_NAME); 799 for (String string : BitEncoding.encodeBytes(bytes)) { 800 data.visit(null, string); 801 } 802 data.visitEnd(); 803 AnnotationVisitor strings = av.visitArray( 804 old ? JvmAnnotationNames.STRINGS_FIELD_NAME : JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME 805 ); 806 for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) { 807 strings.visit(null, string); 808 } 809 strings.visitEnd(); 810 } 811 812 @NotNull 813 public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 814 return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor(); 815 } 816 817 @NotNull 818 public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 819 return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName)); 820 } 821 822 @NotNull 823 public static String internalNameByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 824 return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName(); 825 } 826 827 @NotNull 828 public static String getSimpleInternalName(@NotNull String internalName) { 829 int lastSlash = internalName.lastIndexOf('/'); 830 if (lastSlash >= 0) { 831 return internalName.substring(lastSlash + 1); 832 } 833 else { 834 return internalName; 835 } 836 } 837 838 public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) { 839 if (isPrimitive(type)) { 840 v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;"); 841 } 842 else { 843 v.aconst(type); 844 } 845 } 846 847 public static void wrapJavaClassIntoKClass(@NotNull InstructionAdapter v) { 848 v.invokestatic(REFLECTION, "getOrCreateKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false); 849 } 850 851 public static void wrapJavaClassesIntoKClasses(@NotNull InstructionAdapter v) { 852 v.invokestatic(REFLECTION, "getOrCreateKotlinClasses", Type.getMethodDescriptor(K_CLASS_ARRAY_TYPE, getType(Class[].class)), false); 853 } 854 855 public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) { 856 OwnerKind kind = context.getContextKind(); 857 //Trait always should have this descriptor 858 return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1; 859 } 860 }