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