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