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.intellij.psi.tree.IElementType; 020 import kotlin.Unit; 021 import kotlin.collections.ArraysKt; 022 import kotlin.collections.CollectionsKt; 023 import kotlin.jvm.functions.Function1; 024 import org.jetbrains.annotations.Contract; 025 import org.jetbrains.annotations.NotNull; 026 import org.jetbrains.annotations.Nullable; 027 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 028 import org.jetbrains.kotlin.builtins.PrimitiveType; 029 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; 030 import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty; 031 import org.jetbrains.kotlin.codegen.state.GenerationState; 032 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; 033 import org.jetbrains.kotlin.descriptors.*; 034 import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; 035 import org.jetbrains.kotlin.load.java.JvmAbi; 036 import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor; 037 import org.jetbrains.kotlin.psi.KtExpression; 038 import org.jetbrains.kotlin.resolve.DescriptorUtils; 039 import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor; 040 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 041 import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument; 042 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 043 import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; 044 import org.jetbrains.kotlin.resolve.constants.ConstantValue; 045 import org.jetbrains.kotlin.resolve.jvm.AsmTypes; 046 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; 047 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; 048 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; 049 import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor; 050 import org.jetbrains.kotlin.types.KotlinType; 051 import org.jetbrains.org.objectweb.asm.Label; 052 import org.jetbrains.org.objectweb.asm.Type; 053 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 054 055 import java.util.List; 056 057 import static org.jetbrains.kotlin.codegen.AsmUtil.*; 058 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 059 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 060 061 public abstract class StackValue { 062 063 private static final String NULLABLE_BYTE_TYPE_NAME = "java/lang/Byte"; 064 private static final String NULLABLE_SHORT_TYPE_NAME = "java/lang/Short"; 065 private static final String NULLABLE_LONG_TYPE_NAME = "java/lang/Long"; 066 067 public static final StackValue.Local LOCAL_0 = local(0, OBJECT_TYPE); 068 private static final StackValue UNIT = operation(UNIT_TYPE, new Function1<InstructionAdapter, Unit>() { 069 @Override 070 public Unit invoke(InstructionAdapter v) { 071 v.visitFieldInsn(GETSTATIC, UNIT_TYPE.getInternalName(), JvmAbi.INSTANCE_FIELD, UNIT_TYPE.getDescriptor()); 072 return null; 073 } 074 }); 075 076 @NotNull 077 public final Type type; 078 private final boolean canHaveSideEffects; 079 080 protected StackValue(@NotNull Type type) { 081 this(type, true); 082 } 083 084 protected StackValue(@NotNull Type type, boolean canHaveSideEffects) { 085 this.type = type; 086 this.canHaveSideEffects = canHaveSideEffects; 087 } 088 089 /** 090 * This method is called to put the value on the top of the JVM stack if <code>depth</code> other values have been put on the 091 * JVM stack after this value was generated. 092 * 093 * @param type the type as which the value should be put 094 * @param v the visitor used to genClassOrObject the instructions 095 * @param depth the number of new values put onto the stack 096 */ 097 public void moveToTopOfStack(@NotNull Type type, @NotNull InstructionAdapter v, int depth) { 098 put(type, v); 099 } 100 101 public void put(@NotNull Type type, @NotNull InstructionAdapter v) { 102 put(type, v, false); 103 } 104 105 public void put(@NotNull Type type, @NotNull InstructionAdapter v, boolean skipReceiver) { 106 if (!skipReceiver) { 107 putReceiver(v, true); 108 } 109 putSelector(type, v); 110 } 111 112 public abstract void putSelector(@NotNull Type type, @NotNull InstructionAdapter v); 113 114 public boolean isNonStaticAccess(boolean isRead) { 115 return false; 116 } 117 118 119 public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) { 120 //by default there is no receiver 121 //if you have it inherit StackValueWithSimpleReceiver 122 } 123 124 public void dup(@NotNull InstructionAdapter v, boolean withReceiver) { 125 if (!Type.VOID_TYPE.equals(type)) { 126 AsmUtil.dup(v, type); 127 } 128 } 129 130 public void store(@NotNull StackValue value, @NotNull InstructionAdapter v) { 131 store(value, v, false); 132 } 133 134 public boolean canHaveSideEffects() { 135 return canHaveSideEffects; 136 } 137 138 public void store(@NotNull StackValue value, @NotNull InstructionAdapter v, boolean skipReceiver) { 139 if (!skipReceiver) { 140 putReceiver(v, false); 141 } 142 value.put(value.type, v); 143 storeSelector(value.type, v); 144 } 145 146 protected void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 147 throw new UnsupportedOperationException("Cannot store to value " + this); 148 } 149 150 @NotNull 151 public static Local local(int index, @NotNull Type type) { 152 return new Local(index, type); 153 } 154 155 @NotNull 156 public static StackValue shared(int index, @NotNull Type type) { 157 return new Shared(index, type); 158 } 159 160 @NotNull 161 public static StackValue onStack(@NotNull Type type) { 162 return type == Type.VOID_TYPE ? none() : new OnStack(type); 163 } 164 165 @NotNull 166 public static StackValue constant(@Nullable Object value, @NotNull Type type) { 167 if (type == Type.BOOLEAN_TYPE) { 168 assert value instanceof Boolean : "Value for boolean constant should have boolean type: " + value; 169 return BranchedValue.Companion.booleanConstant((Boolean) value); 170 } 171 else { 172 return new Constant(value, type); 173 } 174 } 175 176 @NotNull 177 public static StackValue cmp(@NotNull IElementType opToken, @NotNull Type type, StackValue left, StackValue right) { 178 return BranchedValue.Companion.cmp(opToken, type, left, right); 179 } 180 181 @NotNull 182 public static StackValue not(@NotNull StackValue stackValue) { 183 return BranchedValue.Companion.createInvertValue(stackValue); 184 } 185 186 public static StackValue or(@NotNull StackValue left, @NotNull StackValue right) { 187 return new Or(left, right); 188 } 189 190 public static StackValue and(@NotNull StackValue left, @NotNull StackValue right) { 191 return new And(left, right); 192 } 193 194 public static StackValue compareIntWithZero(@NotNull StackValue argument, int operation) { 195 return new BranchedValue(argument, null, Type.INT_TYPE, operation); 196 } 197 198 public static StackValue compareWithNull(@NotNull StackValue argument, int operation) { 199 return new BranchedValue(argument, null, AsmTypes.OBJECT_TYPE, operation); 200 } 201 202 @NotNull 203 public static StackValue arrayElement(@NotNull Type type, StackValue array, StackValue index) { 204 return new ArrayElement(type, array, index); 205 } 206 207 @NotNull 208 public static StackValue collectionElement( 209 CollectionElementReceiver collectionElementReceiver, 210 Type type, 211 ResolvedCall<FunctionDescriptor> getter, 212 ResolvedCall<FunctionDescriptor> setter, 213 ExpressionCodegen codegen 214 ) { 215 return new CollectionElement(collectionElementReceiver, type, getter, setter, codegen); 216 } 217 218 @NotNull 219 public static Field field(@NotNull Type type, @NotNull Type owner, @NotNull String name, boolean isStatic, @NotNull StackValue receiver) { 220 return field(type, owner, name, isStatic, receiver, null); 221 } 222 223 @NotNull 224 public static Field field( 225 @NotNull Type type, 226 @NotNull Type owner, 227 @NotNull String name, 228 boolean isStatic, 229 @NotNull StackValue receiver, 230 @Nullable DeclarationDescriptor descriptor 231 ) { 232 return new Field(type, owner, name, isStatic, receiver, descriptor); 233 } 234 235 @NotNull 236 public static Field field(@NotNull StackValue.Field field, @NotNull StackValue newReceiver) { 237 return field(field.type, field.owner, field.name, field.isStaticPut, newReceiver, field.descriptor); 238 } 239 240 @NotNull 241 public static Field field(@NotNull FieldInfo info, @NotNull StackValue receiver) { 242 return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), info.isStatic(), receiver); 243 } 244 245 @NotNull 246 public static StackValue changeReceiverForFieldAndSharedVar(@NotNull StackValueWithSimpleReceiver stackValue, @Nullable StackValue newReceiver) { 247 //TODO static check 248 if (newReceiver != null) { 249 if (!stackValue.isStaticPut) { 250 if (stackValue instanceof Field) { 251 return field((Field) stackValue, newReceiver); 252 } 253 else if (stackValue instanceof FieldForSharedVar) { 254 return fieldForSharedVar((FieldForSharedVar) stackValue, newReceiver); 255 } 256 } 257 } 258 return stackValue; 259 } 260 261 @NotNull 262 public static Property property( 263 @NotNull PropertyDescriptor descriptor, 264 @Nullable Type backingFieldOwner, 265 @NotNull Type type, 266 boolean isStaticBackingField, 267 @Nullable String fieldName, 268 @Nullable CallableMethod getter, 269 @Nullable CallableMethod setter, 270 GenerationState state, 271 @NotNull StackValue receiver 272 ) { 273 return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, state, receiver); 274 } 275 276 @NotNull 277 public static StackValue expression(Type type, KtExpression expression, ExpressionCodegen generator) { 278 return new Expression(type, expression, generator); 279 } 280 281 private static void box(Type type, Type toType, InstructionAdapter v) { 282 if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) { 283 v.cast(type, Type.BYTE_TYPE); 284 v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";", false); 285 } 286 else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) { 287 v.cast(type, Type.SHORT_TYPE); 288 v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";", false); 289 } 290 else if (type == Type.LONG_TYPE || toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) { 291 v.cast(type, Type.LONG_TYPE); 292 v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME + ";", false); 293 } 294 else if (type == Type.INT_TYPE) { 295 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); 296 } 297 else if (type == Type.BOOLEAN_TYPE) { 298 v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); 299 } 300 else if (type == Type.CHAR_TYPE) { 301 v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); 302 } 303 else if (type == Type.FLOAT_TYPE) { 304 v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); 305 } 306 else if (type == Type.DOUBLE_TYPE) { 307 v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); 308 } 309 } 310 311 private static void unbox(Type type, InstructionAdapter v) { 312 if (type == Type.INT_TYPE) { 313 v.invokevirtual("java/lang/Number", "intValue", "()I", false); 314 } 315 else if (type == Type.BOOLEAN_TYPE) { 316 v.invokevirtual("java/lang/Boolean", "booleanValue", "()Z", false); 317 } 318 else if (type == Type.CHAR_TYPE) { 319 v.invokevirtual("java/lang/Character", "charValue", "()C", false); 320 } 321 else if (type == Type.SHORT_TYPE) { 322 v.invokevirtual("java/lang/Number", "shortValue", "()S", false); 323 } 324 else if (type == Type.LONG_TYPE) { 325 v.invokevirtual("java/lang/Number", "longValue", "()J", false); 326 } 327 else if (type == Type.BYTE_TYPE) { 328 v.invokevirtual("java/lang/Number", "byteValue", "()B", false); 329 } 330 else if (type == Type.FLOAT_TYPE) { 331 v.invokevirtual("java/lang/Number", "floatValue", "()F", false); 332 } 333 else if (type == Type.DOUBLE_TYPE) { 334 v.invokevirtual("java/lang/Number", "doubleValue", "()D", false); 335 } 336 } 337 338 protected void coerceTo(@NotNull Type toType, @NotNull InstructionAdapter v) { 339 coerce(this.type, toType, v); 340 } 341 342 protected void coerceFrom(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 343 coerce(topOfStackType, this.type, v); 344 } 345 346 public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v) { 347 if (toType.equals(fromType)) return; 348 349 if (toType.getSort() == Type.VOID) { 350 pop(v, fromType); 351 } 352 else if (fromType.getSort() == Type.VOID) { 353 if (toType.equals(UNIT_TYPE) || toType.equals(OBJECT_TYPE)) { 354 putUnitInstance(v); 355 } 356 else if (toType.getSort() == Type.OBJECT || toType.getSort() == Type.ARRAY) { 357 v.aconst(null); 358 } 359 else { 360 pushDefaultPrimitiveValueOnStack(toType, v); 361 } 362 } 363 else if (toType.equals(UNIT_TYPE)) { 364 if (fromType.equals(getType(Object.class))) { 365 v.checkcast(UNIT_TYPE); 366 } 367 else if (!fromType.equals(getType(Void.class))) { 368 pop(v, fromType); 369 putUnitInstance(v); 370 } 371 } 372 else if (toType.getSort() == Type.ARRAY) { 373 if (fromType.getSort() == Type.ARRAY && 374 fromType.getElementType().equals(AsmTypes.JAVA_CLASS_TYPE) && toType.equals(K_CLASS_ARRAY_TYPE)) { 375 wrapJavaClassesIntoKClasses(v); 376 } 377 else { 378 v.checkcast(toType); 379 } 380 } 381 else if (toType.getSort() == Type.OBJECT) { 382 if (fromType.getSort() == Type.OBJECT || fromType.getSort() == Type.ARRAY) { 383 if (!toType.equals(OBJECT_TYPE)) { 384 if (fromType.equals(AsmTypes.JAVA_CLASS_TYPE) && toType.equals(AsmTypes.K_CLASS_TYPE)) { 385 wrapJavaClassIntoKClass(v); 386 } 387 else { 388 v.checkcast(toType); 389 } 390 } 391 } 392 else { 393 box(fromType, toType, v); 394 } 395 } 396 else if (fromType.getSort() == Type.OBJECT) { 397 if (fromType.equals(getType(Boolean.class)) || fromType.equals(getType(Character.class))) { 398 unbox(unboxType(fromType), v); 399 coerce(unboxType(fromType), toType, v); 400 } 401 else { 402 if (toType.getSort() == Type.BOOLEAN || toType.getSort() == Type.CHAR) { 403 coerce(fromType, boxType(toType), v); 404 } 405 else { 406 coerce(fromType, getType(Number.class), v); 407 } 408 unbox(toType, v); 409 } 410 } 411 else { 412 v.cast(fromType, toType); 413 } 414 } 415 416 public static void putUnitInstance(@NotNull InstructionAdapter v) { 417 unit().put(UNIT_TYPE, v); 418 } 419 420 public static StackValue unit() { 421 return UNIT; 422 } 423 424 public static StackValue none() { 425 return None.INSTANCE; 426 } 427 428 public static Field receiverWithRefWrapper( 429 @NotNull Type localType, 430 @NotNull Type classType, 431 @NotNull String fieldName, 432 @NotNull StackValue receiver, 433 @Nullable DeclarationDescriptor descriptor 434 ) { 435 return field(sharedTypeForType(localType), classType, fieldName, false, receiver, descriptor); 436 } 437 438 public static FieldForSharedVar fieldForSharedVar( 439 @NotNull Type localType, 440 @NotNull Type classType, 441 @NotNull String fieldName, 442 @NotNull Field refWrapper 443 ) { 444 return new FieldForSharedVar(localType, classType, fieldName, refWrapper); 445 } 446 447 @NotNull 448 public static FieldForSharedVar fieldForSharedVar(@NotNull FieldForSharedVar field, @NotNull StackValue newReceiver) { 449 Field oldReceiver = (Field) field.receiver; 450 Field newSharedVarReceiver = field(oldReceiver, newReceiver); 451 return new FieldForSharedVar(field.type, field.owner, field.name, newSharedVarReceiver); 452 } 453 454 public static StackValue coercion(@NotNull StackValue value, @NotNull Type castType) { 455 if (value.type.equals(castType)) { 456 return value; 457 } 458 return new CoercionValue(value, castType); 459 } 460 461 @NotNull 462 public static StackValue thisOrOuter( 463 @NotNull ExpressionCodegen codegen, 464 @NotNull ClassDescriptor descriptor, 465 boolean isSuper, 466 boolean castReceiver 467 ) { 468 // Coerce 'this' for the case when it is smart cast. 469 // Do not coerce for other cases due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints). 470 boolean coerceType = descriptor.getKind() == ClassKind.INTERFACE || (castReceiver && !isSuper); 471 return new ThisOuter(codegen, descriptor, isSuper, coerceType); 472 } 473 474 public static StackValue postIncrement(int index, int increment) { 475 return new PostIncrement(index, increment); 476 } 477 478 public static StackValue preIncrementForLocalVar(int index, int increment) { 479 return new PreIncrementForLocalVar(index, increment); 480 } 481 482 public static StackValue preIncrement( 483 @NotNull Type type, 484 @NotNull StackValue stackValue, 485 int delta, 486 ResolvedCall resolvedCall, 487 @NotNull ExpressionCodegen codegen 488 ) { 489 if (stackValue instanceof StackValue.Local && Type.INT_TYPE == stackValue.type) { 490 return preIncrementForLocalVar(((StackValue.Local) stackValue).index, delta); 491 } 492 return new PrefixIncrement(type, stackValue, resolvedCall, codegen); 493 } 494 495 public static StackValue receiver( 496 ResolvedCall<?> resolvedCall, 497 StackValue receiver, 498 ExpressionCodegen codegen, 499 @Nullable Callable callableMethod 500 ) { 501 ReceiverValue callDispatchReceiver = resolvedCall.getDispatchReceiver(); 502 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 503 if (descriptor instanceof SyntheticFieldDescriptor) { 504 callDispatchReceiver = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverForBackend(); 505 } 506 507 ReceiverValue callExtensionReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver(); 508 if (callDispatchReceiver != null || callExtensionReceiver != null 509 || isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) { 510 ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter(); 511 ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); 512 513 if (descriptor.getOriginal() instanceof SamAdapterExtensionFunctionDescriptor) { 514 callDispatchReceiver = callExtensionReceiver; 515 callExtensionReceiver = null; 516 dispatchReceiverParameter = extensionReceiverParameter; 517 extensionReceiverParameter = null; 518 } 519 else if (descriptor instanceof SyntheticFieldDescriptor) { 520 dispatchReceiverParameter = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverParameterForBackend(); 521 } 522 523 boolean hasExtensionReceiver = callExtensionReceiver != null; 524 StackValue dispatchReceiver = platformStaticCallIfPresent( 525 genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, callDispatchReceiver, false), 526 descriptor 527 ); 528 StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, callExtensionReceiver, true); 529 Type type = CallReceiver.calcType(resolvedCall, dispatchReceiverParameter, extensionReceiverParameter, codegen.typeMapper, callableMethod, codegen.getState()); 530 assert type != null : "Could not map receiver type for " + resolvedCall; 531 return new CallReceiver(dispatchReceiver, extensionReceiver, type); 532 } 533 return receiver; 534 } 535 536 private static StackValue genReceiver( 537 @NotNull StackValue receiver, 538 @NotNull ExpressionCodegen codegen, 539 @NotNull ResolvedCall resolvedCall, 540 @Nullable Callable callableMethod, 541 @Nullable ReceiverValue receiverValue, 542 boolean isExtension 543 ) { 544 if (receiver == none()) { 545 if (receiverValue != null) { 546 return codegen.generateReceiverValue(receiverValue, false); 547 } 548 else if (isLocalFunCall(callableMethod) && !isExtension) { 549 StackValue value = codegen.findLocalOrCapturedValue(resolvedCall.getResultingDescriptor().getOriginal()); 550 assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall; 551 return value; 552 } 553 else if (isCallToMemberObjectImportedByName(resolvedCall)) { 554 return singleton(((ImportedFromObjectCallableDescriptor) resolvedCall.getResultingDescriptor()).getContainingObject(), codegen.typeMapper); 555 } 556 } 557 else if (receiverValue != null) { 558 return receiver; 559 } 560 return none(); 561 } 562 563 private static boolean isCallToMemberObjectImportedByName(@NotNull ResolvedCall resolvedCall) { 564 return resolvedCall.getResultingDescriptor() instanceof ImportedFromObjectCallableDescriptor; 565 } 566 567 private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) { 568 if (AnnotationUtilKt.isPlatformStaticInObjectOrClass(descriptor)) { 569 if (resultReceiver.canHaveSideEffects()) { 570 return coercion(resultReceiver, Type.VOID_TYPE); 571 } 572 else { 573 return none(); 574 } 575 } 576 return resultReceiver; 577 } 578 579 @Contract("null -> false") 580 private static boolean isLocalFunCall(@Nullable Callable callableMethod) { 581 return callableMethod != null && callableMethod.getGenerateCalleeType() != null; 582 } 583 584 public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) { 585 if (receiverWithParameter instanceof CallReceiver) { 586 CallReceiver callReceiver = (CallReceiver) receiverWithParameter; 587 return new CallReceiver(callReceiver.dispatchReceiver, none(), callReceiver.type); 588 } 589 return receiverWithParameter; 590 } 591 592 @NotNull 593 public static Field enumEntry(@NotNull ClassDescriptor descriptor, @NotNull KotlinTypeMapper typeMapper) { 594 DeclarationDescriptor enumClass = descriptor.getContainingDeclaration(); 595 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor; 596 Type type = typeMapper.mapType((ClassDescriptor) enumClass); 597 return field(type, type, descriptor.getName().asString(), true, none(), descriptor); 598 } 599 600 @NotNull 601 public static Field singleton(@NotNull ClassDescriptor classDescriptor, @NotNull KotlinTypeMapper typeMapper) { 602 return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none()); 603 } 604 605 public static Field singletonViaInstance(ClassDescriptor classDescriptor, KotlinTypeMapper typeMapper) { 606 return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper), none()); 607 } 608 609 public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) { 610 return new OperationStackValue(type, lambda); 611 } 612 613 public static StackValue functionCall(Type type, Function1<InstructionAdapter, Unit> lambda) { 614 return new FunctionCallStackValue(type, lambda); 615 } 616 617 public static boolean couldSkipReceiverOnStaticCall(StackValue value) { 618 return value instanceof Local || value instanceof Constant; 619 } 620 621 private static class None extends StackValue { 622 public static final None INSTANCE = new None(); 623 624 private None() { 625 super(Type.VOID_TYPE, false); 626 } 627 628 @Override 629 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 630 coerceTo(type, v); 631 } 632 } 633 634 public static class Local extends StackValue { 635 public final int index; 636 637 private Local(int index, Type type) { 638 super(type, false); 639 this.index = index; 640 641 if (index < 0) { 642 throw new IllegalStateException("local variable index must be non-negative"); 643 } 644 } 645 646 @Override 647 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 648 v.load(index, this.type); 649 coerceTo(type, v); 650 // TODO unbox 651 } 652 653 @Override 654 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 655 coerceFrom(topOfStackType, v); 656 v.store(index, this.type); 657 } 658 } 659 660 public static class OnStack extends StackValue { 661 public OnStack(Type type) { 662 super(type); 663 } 664 665 @Override 666 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 667 coerceTo(type, v); 668 } 669 670 @Override 671 public void moveToTopOfStack(@NotNull Type type, @NotNull InstructionAdapter v, int depth) { 672 if (depth == 0) { 673 put(type, v); 674 } 675 else if (depth == 1) { 676 int size = this.type.getSize(); 677 if (size == 1) { 678 v.swap(); 679 } 680 else if (size == 2) { 681 v.dupX2(); 682 v.pop(); 683 } 684 else { 685 throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack"); 686 } 687 688 coerceTo(type, v); 689 } 690 else if (depth == 2) { 691 int size = this.type.getSize(); 692 if (size == 1) { 693 v.dup2X1(); 694 v.pop2(); 695 } 696 else if (size == 2) { 697 v.dup2X2(); 698 v.pop2(); 699 } 700 else { 701 throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack"); 702 } 703 704 coerceTo(type, v); 705 } 706 else { 707 throw new UnsupportedOperationException("unsupported move-to-top depth " + depth); 708 } 709 } 710 } 711 712 public static class Constant extends StackValue { 713 @Nullable 714 private final Object value; 715 716 public Constant(@Nullable Object value, Type type) { 717 super(type, false); 718 this.value = value; 719 } 720 721 @Override 722 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 723 if (value instanceof Integer || value instanceof Byte || value instanceof Short) { 724 v.iconst(((Number) value).intValue()); 725 } 726 else if (value instanceof Long) { 727 v.lconst((Long) value); 728 } 729 else if (value instanceof Float) { 730 v.fconst((Float) value); 731 } 732 else if (value instanceof Double) { 733 v.dconst((Double) value); 734 } 735 else { 736 v.aconst(value); 737 } 738 739 coerceTo(type, v); 740 } 741 } 742 743 private static class ArrayElement extends StackValueWithSimpleReceiver { 744 private final Type type; 745 746 public ArrayElement(Type type, StackValue array, StackValue index) { 747 super(type, false, false, new Receiver(Type.LONG_TYPE, array, index), true); 748 this.type = type; 749 } 750 751 @Override 752 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 753 coerceFrom(topOfStackType, v); 754 v.astore(this.type); 755 } 756 757 @Override 758 public int receiverSize() { 759 return 2; 760 } 761 762 @Override 763 public void putSelector( 764 @NotNull Type type, @NotNull InstructionAdapter v 765 ) { 766 v.aload(this.type); // assumes array and index are on the stack 767 coerceTo(type, v); 768 } 769 } 770 771 public static class CollectionElementReceiver extends StackValue { 772 private final Callable callable; 773 private final boolean isGetter; 774 private final ExpressionCodegen codegen; 775 private final List<ResolvedValueArgument> valueArguments; 776 private final FrameMap frame; 777 private final StackValue receiver; 778 private final ResolvedCall<FunctionDescriptor> resolvedGetCall; 779 private final ResolvedCall<FunctionDescriptor> resolvedSetCall; 780 private DefaultCallArgs defaultArgs; 781 private CallGenerator callGenerator; 782 boolean isComplexOperationWithDup; 783 784 public CollectionElementReceiver( 785 @NotNull Callable callable, 786 @NotNull StackValue receiver, 787 ResolvedCall<FunctionDescriptor> resolvedGetCall, 788 ResolvedCall<FunctionDescriptor> resolvedSetCall, 789 boolean isGetter, 790 @NotNull ExpressionCodegen codegen, 791 List<ResolvedValueArgument> valueArguments 792 ) { 793 super(OBJECT_TYPE); 794 this.callable = callable; 795 796 this.isGetter = isGetter; 797 this.receiver = receiver; 798 this.resolvedGetCall = resolvedGetCall; 799 this.resolvedSetCall = resolvedSetCall; 800 this.valueArguments = valueArguments; 801 this.codegen = codegen; 802 this.frame = codegen.myFrameMap; 803 } 804 805 @Override 806 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 807 ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall; 808 StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable); 809 ArgumentGenerator generator = createArgumentGenerator(); 810 newReceiver.put(newReceiver.type, v); 811 callGenerator.putHiddenParams(); 812 813 defaultArgs = generator.generate(valueArguments, valueArguments); 814 } 815 816 private ArgumentGenerator createArgumentGenerator() { 817 assert callGenerator == null : 818 "'putSelector' and 'createArgumentGenerator' methods should be called once for CollectionElementReceiver: " + callable; 819 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 820 assert resolvedCall != null : "Resolved call should be non-null: " + callable; 821 callGenerator = 822 !isComplexOperationWithDup ? codegen.getOrCreateCallGenerator(resolvedCall) : codegen.defaultCallGenerator; 823 return new CallBasedArgumentGenerator( 824 codegen, 825 callGenerator, 826 resolvedCall.getResultingDescriptor().getValueParameters(), callable.getValueParameterTypes() 827 ); 828 } 829 830 @Override 831 public void dup(@NotNull InstructionAdapter v, boolean withReceiver) { 832 dupReceiver(v); 833 } 834 835 public void dupReceiver(@NotNull InstructionAdapter v) { 836 if (CollectionElement.isStandardStack(codegen.typeMapper, resolvedGetCall, 1) && 837 CollectionElement.isStandardStack(codegen.typeMapper, resolvedSetCall, 2)) { 838 v.dup2(); // collection and index 839 return; 840 } 841 842 FrameMap.Mark mark = frame.mark(); 843 844 // indexes 845 List<ValueParameterDescriptor> valueParameters = resolvedGetCall.getResultingDescriptor().getValueParameters(); 846 int firstParamIndex = -1; 847 for (int i = valueParameters.size() - 1; i >= 0; --i) { 848 Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType()); 849 firstParamIndex = frame.enterTemp(type); 850 v.store(firstParamIndex, type); 851 } 852 853 ReceiverValue receiverParameter = (ReceiverValue) resolvedGetCall.getExtensionReceiver(); 854 int receiverIndex = -1; 855 if (receiverParameter != null) { 856 Type type = codegen.typeMapper.mapType(receiverParameter.getType()); 857 receiverIndex = frame.enterTemp(type); 858 v.store(receiverIndex, type); 859 } 860 861 ReceiverValue dispatchReceiver = resolvedGetCall.getDispatchReceiver(); 862 int thisIndex = -1; 863 if (dispatchReceiver != null) { 864 thisIndex = frame.enterTemp(OBJECT_TYPE); 865 v.store(thisIndex, OBJECT_TYPE); 866 } 867 868 // for setter 869 870 int realReceiverIndex; 871 Type realReceiverType; 872 if (receiverIndex != -1) { 873 realReceiverType = codegen.typeMapper.mapType(receiverParameter.getType()); 874 realReceiverIndex = receiverIndex; 875 } 876 else if (thisIndex != -1) { 877 realReceiverType = OBJECT_TYPE; 878 realReceiverIndex = thisIndex; 879 } 880 else { 881 throw new UnsupportedOperationException(); 882 } 883 884 if (resolvedSetCall.getDispatchReceiver() != null) { 885 if (resolvedSetCall.getExtensionReceiver() != null) { 886 codegen.generateReceiverValue(resolvedSetCall.getDispatchReceiver(), false).put(OBJECT_TYPE, v); 887 } 888 v.load(realReceiverIndex, realReceiverType); 889 } 890 else { 891 if (resolvedSetCall.getExtensionReceiver() != null) { 892 v.load(realReceiverIndex, realReceiverType); 893 } 894 else { 895 throw new UnsupportedOperationException(); 896 } 897 } 898 899 int index = firstParamIndex; 900 for (ValueParameterDescriptor valueParameter : valueParameters) { 901 Type type = codegen.typeMapper.mapType(valueParameter.getType()); 902 v.load(index, type); 903 index -= type.getSize(); 904 } 905 906 // restoring original 907 if (thisIndex != -1) { 908 v.load(thisIndex, OBJECT_TYPE); 909 } 910 911 if (receiverIndex != -1) { 912 v.load(receiverIndex, realReceiverType); 913 } 914 915 index = firstParamIndex; 916 for (ValueParameterDescriptor valueParameter : valueParameters) { 917 Type type = codegen.typeMapper.mapType(valueParameter.getType()); 918 v.load(index, type); 919 index -= type.getSize(); 920 } 921 922 mark.dropTo(); 923 } 924 } 925 926 public static class CollectionElement extends StackValueWithSimpleReceiver { 927 private final Callable getter; 928 private final Callable setter; 929 private final ExpressionCodegen codegen; 930 private final ResolvedCall<FunctionDescriptor> resolvedGetCall; 931 private final ResolvedCall<FunctionDescriptor> resolvedSetCall; 932 933 public CollectionElement( 934 @NotNull CollectionElementReceiver collectionElementReceiver, 935 @NotNull Type type, 936 @Nullable ResolvedCall<FunctionDescriptor> resolvedGetCall, 937 @Nullable ResolvedCall<FunctionDescriptor> resolvedSetCall, 938 @NotNull ExpressionCodegen codegen 939 ) { 940 super(type, false, false, collectionElementReceiver, true); 941 this.resolvedGetCall = resolvedGetCall; 942 this.resolvedSetCall = resolvedSetCall; 943 this.setter = resolvedSetCall == null ? null : 944 codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(resolvedSetCall), false, resolvedSetCall); 945 this.getter = resolvedGetCall == null ? null : 946 codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(resolvedGetCall), false, resolvedGetCall); 947 this.codegen = codegen; 948 } 949 950 @Override 951 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 952 if (getter == null) { 953 throw new UnsupportedOperationException("no getter specified"); 954 } 955 CallGenerator callGenerator = getCallGenerator(); 956 callGenerator.genCall(getter, resolvedGetCall, genDefaultMaskIfPresent(callGenerator), codegen); 957 coerceTo(type, v); 958 } 959 960 private boolean genDefaultMaskIfPresent(CallGenerator callGenerator) { 961 DefaultCallArgs defaultArgs = ((CollectionElementReceiver) receiver).defaultArgs; 962 return defaultArgs.generateOnStackIfNeeded(callGenerator, true); 963 } 964 965 private CallGenerator getCallGenerator() { 966 CallGenerator generator = ((CollectionElementReceiver) receiver).callGenerator; 967 assert generator != null : 968 "CollectionElementReceiver should be putted on stack before CollectionElement:" + 969 " getCall = " + resolvedGetCall + ", setCall = " + resolvedSetCall; 970 return generator; 971 } 972 973 @Override 974 public int receiverSize() { 975 if (isStandardStack(codegen.typeMapper, resolvedGetCall, 1) && isStandardStack(codegen.typeMapper, resolvedSetCall, 2)) { 976 return 2; 977 } 978 else { 979 return -1; 980 } 981 } 982 983 public static boolean isStandardStack(@NotNull KotlinTypeMapper typeMapper, @Nullable ResolvedCall<?> call, int valueParamsSize) { 984 if (call == null) { 985 return true; 986 } 987 988 List<ValueParameterDescriptor> valueParameters = call.getResultingDescriptor().getValueParameters(); 989 if (valueParameters.size() != valueParamsSize) { 990 return false; 991 } 992 993 for (ValueParameterDescriptor valueParameter : valueParameters) { 994 if (typeMapper.mapType(valueParameter.getType()).getSize() != 1) { 995 return false; 996 } 997 } 998 999 if (call.getDispatchReceiver() != null) { 1000 if (call.getExtensionReceiver() != null) { 1001 return false; 1002 } 1003 } 1004 else { 1005 //noinspection ConstantConditions 1006 if (typeMapper.mapType(call.getResultingDescriptor().getExtensionReceiverParameter().getType()).getSize() != 1) { 1007 return false; 1008 } 1009 } 1010 1011 return true; 1012 } 1013 1014 @Override 1015 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 1016 if (setter == null) { 1017 throw new UnsupportedOperationException("no setter specified"); 1018 } 1019 1020 Type lastParameterType = ArraysKt.last(setter.getParameterTypes()); 1021 coerce(topOfStackType, lastParameterType, v); 1022 1023 getCallGenerator().afterParameterPut(lastParameterType, StackValue.onStack(lastParameterType), 1024 CollectionsKt.getLastIndex(setter.getValueParameterTypes())); 1025 1026 //Convention setter couldn't have default parameters, just getter can have it at last positions 1027 //We should remove default parameters of getter from stack*/ 1028 //Note that it works only for non-inline case 1029 CollectionElementReceiver collectionElementReceiver = (CollectionElementReceiver) receiver; 1030 if (collectionElementReceiver.isGetter) { 1031 List<ResolvedValueArgument> arguments = collectionElementReceiver.valueArguments; 1032 List<Type> types = getter.getValueParameterTypes(); 1033 for (int i = arguments.size() - 1; i >= 0; i--) { 1034 ResolvedValueArgument argument = arguments.get(i); 1035 if (argument instanceof DefaultValueArgument) { 1036 Type defaultType = types.get(i); 1037 AsmUtil.swap(v, lastParameterType, defaultType); 1038 AsmUtil.pop(v, defaultType); 1039 } 1040 } 1041 } 1042 1043 getCallGenerator().genCall(setter, resolvedSetCall, false, codegen); 1044 Type returnType = setter.getReturnType(); 1045 if (returnType != Type.VOID_TYPE) { 1046 pop(v, returnType); 1047 } 1048 } 1049 } 1050 1051 1052 public static class Field extends StackValueWithSimpleReceiver { 1053 public final Type owner; 1054 public final String name; 1055 public final DeclarationDescriptor descriptor; 1056 1057 public Field( 1058 @NotNull Type type, 1059 @NotNull Type owner, 1060 @NotNull String name, 1061 boolean isStatic, 1062 @NotNull StackValue receiver, 1063 @Nullable DeclarationDescriptor descriptor 1064 ) { 1065 super(type, isStatic, isStatic, receiver, receiver.canHaveSideEffects()); 1066 this.owner = owner; 1067 this.name = name; 1068 this.descriptor = descriptor; 1069 } 1070 1071 @Override 1072 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1073 v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor()); 1074 coerceTo(type, v); 1075 } 1076 1077 @Override 1078 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 1079 coerceFrom(topOfStackType, v); 1080 v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor()); 1081 } 1082 } 1083 1084 static class Property extends StackValueWithSimpleReceiver { 1085 private final CallableMethod getter; 1086 private final CallableMethod setter; 1087 private final Type backingFieldOwner; 1088 1089 private final PropertyDescriptor descriptor; 1090 private final GenerationState state; 1091 1092 private final String fieldName; 1093 1094 public Property( 1095 @NotNull PropertyDescriptor descriptor, @Nullable Type backingFieldOwner, 1096 @Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField, 1097 @Nullable String fieldName, @NotNull Type type, @NotNull GenerationState state, 1098 @NotNull StackValue receiver 1099 ) { 1100 super(type, isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver, true); 1101 this.backingFieldOwner = backingFieldOwner; 1102 this.getter = getter; 1103 this.setter = setter; 1104 this.descriptor = descriptor; 1105 this.state = state; 1106 this.fieldName = fieldName; 1107 } 1108 1109 @Override 1110 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1111 if (getter == null) { 1112 assert fieldName != null : "Property should have either a getter or a field name: " + descriptor; 1113 assert backingFieldOwner != null : "Property should have either a getter or a backingFieldOwner: " + descriptor; 1114 if (inlineJavaConstantIfNeeded(type, v)) return; 1115 1116 v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, 1117 backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor()); 1118 genNotNullAssertionForLateInitIfNeeded(v); 1119 coerceTo(type, v); 1120 } 1121 else { 1122 getter.genInvokeInstruction(v); 1123 coerce(getter.getReturnType(), type, v); 1124 1125 KotlinType returnType = descriptor.getReturnType(); 1126 if (returnType != null && KotlinBuiltIns.isNothing(returnType)) { 1127 v.aconst(null); 1128 v.athrow(); 1129 } 1130 } 1131 } 1132 1133 private boolean inlineJavaConstantIfNeeded(@NotNull Type type, @NotNull InstructionAdapter v) { 1134 if (!JvmCodegenUtil.isInlinedJavaConstProperty(descriptor)) return false; 1135 1136 assert AsmUtil.isPrimitive(this.type) || AsmTypes.JAVA_STRING_TYPE.equals(this.type) : 1137 "Java const property should have primitive or string type: " + descriptor; 1138 assert isStaticPut : "Java const property should be static" + descriptor; 1139 1140 JavaPropertyDescriptor javaPropertyDescriptor = (JavaPropertyDescriptor) descriptor; 1141 ConstantValue<?> constantValue = javaPropertyDescriptor.getCompileTimeInitializer(); 1142 if (constantValue == null) return false; 1143 1144 Object value = constantValue.getValue(); 1145 if (this.type == Type.FLOAT_TYPE && value instanceof Double) { 1146 value = ((Double) value).floatValue(); 1147 } 1148 1149 new Constant(value, this.type).putSelector(type, v); 1150 1151 return true; 1152 } 1153 1154 private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) { 1155 if (!descriptor.isLateInit()) return; 1156 1157 v.dup(); 1158 Label ok = new Label(); 1159 v.ifnonnull(ok); 1160 v.visitLdcInsn(descriptor.getName().asString()); 1161 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwUninitializedPropertyAccessException", "(Ljava/lang/String;)V", false); 1162 v.mark(ok); 1163 } 1164 1165 @Override 1166 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 1167 if (setter == null) { 1168 coerceFrom(topOfStackType, v); 1169 assert fieldName != null : "Property should have either a setter or a field name: " + descriptor; 1170 assert backingFieldOwner != null : "Property should have either a setter or a backingFieldOwner: " + descriptor; 1171 v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor()); 1172 } 1173 else { 1174 coerce(topOfStackType, ArraysKt.last(setter.getParameterTypes()), v); 1175 setter.genInvokeInstruction(v); 1176 1177 Type returnType = setter.getReturnType(); 1178 if (returnType != Type.VOID_TYPE) { 1179 pop(v, returnType); 1180 } 1181 } 1182 } 1183 1184 private static boolean isStatic(boolean isStaticBackingField, @Nullable CallableMethod callable) { 1185 if (isStaticBackingField && callable == null) { 1186 return true; 1187 } 1188 1189 if (callable != null && callable.isStaticCall()) { 1190 List<JvmMethodParameterSignature> parameters = callable.getValueParameters(); 1191 for (JvmMethodParameterSignature parameter : parameters) { 1192 JvmMethodParameterKind kind = parameter.getKind(); 1193 if (kind == JvmMethodParameterKind.VALUE) { 1194 break; 1195 } 1196 if (kind == JvmMethodParameterKind.RECEIVER || kind == JvmMethodParameterKind.THIS) { 1197 return false; 1198 } 1199 } 1200 return true; 1201 } 1202 1203 return false; 1204 } 1205 } 1206 1207 private static class Expression extends StackValue { 1208 private final KtExpression expression; 1209 private final ExpressionCodegen generator; 1210 1211 public Expression(Type type, KtExpression expression, ExpressionCodegen generator) { 1212 super(type); 1213 this.expression = expression; 1214 this.generator = generator; 1215 } 1216 1217 @Override 1218 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1219 generator.gen(expression, type); 1220 } 1221 } 1222 1223 public static class Shared extends StackValueWithSimpleReceiver { 1224 private final int index; 1225 1226 public Shared(int index, Type type) { 1227 super(type, false, false, local(index, OBJECT_TYPE), false); 1228 this.index = index; 1229 } 1230 1231 public int getIndex() { 1232 return index; 1233 } 1234 1235 @Override 1236 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1237 Type refType = refType(this.type); 1238 Type sharedType = sharedTypeForType(this.type); 1239 v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 1240 coerceFrom(refType, v); 1241 coerceTo(type, v); 1242 } 1243 1244 @Override 1245 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 1246 coerceFrom(topOfStackType, v); 1247 Type refType = refType(this.type); 1248 Type sharedType = sharedTypeForType(this.type); 1249 v.visitFieldInsn(PUTFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 1250 } 1251 } 1252 1253 @NotNull 1254 public static Type sharedTypeForType(@NotNull Type type) { 1255 switch (type.getSort()) { 1256 case Type.OBJECT: 1257 case Type.ARRAY: 1258 return OBJECT_REF_TYPE; 1259 default: 1260 PrimitiveType primitiveType = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(type); 1261 if (primitiveType == null) throw new UnsupportedOperationException(); 1262 1263 String typeName = primitiveType.getTypeName().getIdentifier(); 1264 return Type.getObjectType(REF_TYPE_PREFIX + typeName + "Ref"); 1265 } 1266 } 1267 1268 public static Type refType(Type type) { 1269 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 1270 return OBJECT_TYPE; 1271 } 1272 1273 return type; 1274 } 1275 1276 public static class FieldForSharedVar extends StackValueWithSimpleReceiver { 1277 final Type owner; 1278 final String name; 1279 1280 public FieldForSharedVar(Type type, Type owner, String name, StackValue.Field receiver) { 1281 super(type, false, false, receiver, receiver.canHaveSideEffects()); 1282 this.owner = owner; 1283 this.name = name; 1284 } 1285 1286 @Override 1287 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1288 Type sharedType = sharedTypeForType(this.type); 1289 Type refType = refType(this.type); 1290 v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 1291 coerceFrom(refType, v); 1292 coerceTo(type, v); 1293 } 1294 1295 @Override 1296 public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) { 1297 coerceFrom(topOfStackType, v); 1298 v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "element", refType(type).getDescriptor()); 1299 } 1300 } 1301 1302 private static class ThisOuter extends StackValue { 1303 private final ExpressionCodegen codegen; 1304 private final ClassDescriptor descriptor; 1305 private final boolean isSuper; 1306 private final boolean coerceType; 1307 1308 public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean coerceType) { 1309 super(OBJECT_TYPE, false); 1310 this.codegen = codegen; 1311 this.descriptor = descriptor; 1312 this.isSuper = isSuper; 1313 this.coerceType = coerceType; 1314 } 1315 1316 @Override 1317 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1318 StackValue stackValue = codegen.generateThisOrOuter(descriptor, isSuper); 1319 stackValue.put(coerceType ? type : stackValue.type, v); 1320 } 1321 } 1322 1323 private static class PostIncrement extends StackValue { 1324 private final int index; 1325 private final int increment; 1326 1327 public PostIncrement(int index, int increment) { 1328 super(Type.INT_TYPE); 1329 this.index = index; 1330 this.increment = increment; 1331 } 1332 1333 @Override 1334 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1335 if (!type.equals(Type.VOID_TYPE)) { 1336 v.load(index, Type.INT_TYPE); 1337 coerceTo(type, v); 1338 } 1339 v.iinc(index, increment); 1340 } 1341 } 1342 1343 private static class PreIncrementForLocalVar extends StackValue { 1344 private final int index; 1345 private final int increment; 1346 1347 public PreIncrementForLocalVar(int index, int increment) { 1348 super(Type.INT_TYPE); 1349 this.index = index; 1350 this.increment = increment; 1351 } 1352 1353 @Override 1354 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1355 v.iinc(index, increment); 1356 if (!type.equals(Type.VOID_TYPE)) { 1357 v.load(index, Type.INT_TYPE); 1358 coerceTo(type, v); 1359 } 1360 } 1361 } 1362 1363 private static class PrefixIncrement extends StackValue { 1364 private final ResolvedCall resolvedCall; 1365 private final ExpressionCodegen codegen; 1366 private StackValue value; 1367 1368 public PrefixIncrement( 1369 @NotNull Type type, 1370 @NotNull StackValue value, 1371 ResolvedCall resolvedCall, 1372 @NotNull ExpressionCodegen codegen 1373 ) { 1374 super(type); 1375 this.value = value; 1376 this.resolvedCall = resolvedCall; 1377 this.codegen = codegen; 1378 } 1379 1380 @Override 1381 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1382 value = StackValue.complexReceiver(value, true, false, true); 1383 value.put(this.type, v); 1384 1385 value.store(codegen.invokeFunction(resolvedCall, StackValue.onStack(this.type)), v, true); 1386 1387 value.put(this.type, v, true); 1388 coerceTo(type, v); 1389 } 1390 } 1391 1392 public static class CallReceiver extends StackValue { 1393 private final StackValue dispatchReceiver; 1394 private final StackValue extensionReceiver; 1395 1396 public CallReceiver( 1397 @NotNull StackValue dispatchReceiver, 1398 @NotNull StackValue extensionReceiver, 1399 @NotNull Type type 1400 ) { 1401 super(type, dispatchReceiver.canHaveSideEffects() || extensionReceiver.canHaveSideEffects()); 1402 this.dispatchReceiver = dispatchReceiver; 1403 this.extensionReceiver = extensionReceiver; 1404 } 1405 1406 @Nullable 1407 public static Type calcType( 1408 @NotNull ResolvedCall<?> resolvedCall, 1409 @Nullable ReceiverParameterDescriptor dispatchReceiver, 1410 @Nullable ReceiverParameterDescriptor extensionReceiver, 1411 @NotNull KotlinTypeMapper typeMapper, 1412 @Nullable Callable callableMethod, 1413 @NotNull GenerationState state 1414 ) { 1415 if (extensionReceiver != null) { 1416 CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor(); 1417 1418 if (descriptor instanceof PropertyDescriptor && 1419 // hackaround: boxing changes behaviour of T.javaClass intrinsic 1420 !(state.getIntrinsics().getIntrinsic((PropertyDescriptor) descriptor) instanceof JavaClassProperty) 1421 ) { 1422 ReceiverParameterDescriptor receiverCandidate = descriptor.getExtensionReceiverParameter(); 1423 assert receiverCandidate != null; 1424 return typeMapper.mapType(receiverCandidate.getType()); 1425 } 1426 1427 return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType()); 1428 } 1429 else if (dispatchReceiver != null) { 1430 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 1431 1432 if (AnnotationUtilKt.isPlatformStaticInObjectOrClass(descriptor)) { 1433 return Type.VOID_TYPE; 1434 } 1435 1436 if (callableMethod != null) { 1437 return callableMethod.getDispatchReceiverType(); 1438 } 1439 1440 // Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have 1441 // all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver. 1442 DeclarationDescriptor container = descriptor.getContainingDeclaration(); 1443 if (container instanceof ClassDescriptor) { 1444 return typeMapper.mapClass((ClassDescriptor) container); 1445 } 1446 1447 return typeMapper.mapType(dispatchReceiver); 1448 } 1449 else if (isLocalFunCall(callableMethod)) { 1450 return callableMethod.getGenerateCalleeType(); 1451 } 1452 1453 return Type.VOID_TYPE; 1454 } 1455 1456 @Override 1457 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1458 StackValue currentExtensionReceiver = extensionReceiver; 1459 boolean hasExtensionReceiver = extensionReceiver != none(); 1460 if (extensionReceiver instanceof StackValue.SafeCall) { 1461 currentExtensionReceiver.put(currentExtensionReceiver.type, v); 1462 currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type); 1463 } 1464 1465 dispatchReceiver.put(hasExtensionReceiver ? dispatchReceiver.type : type, v); 1466 1467 currentExtensionReceiver 1468 .moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiver.type.getSize()); 1469 } 1470 1471 @Override 1472 public void dup(@NotNull InstructionAdapter v, boolean withReceiver) { 1473 AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type); 1474 } 1475 } 1476 1477 public abstract static class StackValueWithSimpleReceiver extends StackValue { 1478 1479 public final boolean isStaticPut; 1480 1481 public final boolean isStaticStore; 1482 @NotNull 1483 public final StackValue receiver; 1484 1485 public StackValueWithSimpleReceiver( 1486 @NotNull Type type, 1487 boolean isStaticPut, 1488 boolean isStaticStore, 1489 @NotNull StackValue receiver, 1490 boolean canHaveSideEffects 1491 ) { 1492 super(type, canHaveSideEffects); 1493 this.receiver = receiver; 1494 this.isStaticPut = isStaticPut; 1495 this.isStaticStore = isStaticStore; 1496 } 1497 1498 @Override 1499 public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) { 1500 boolean hasReceiver = isNonStaticAccess(isRead); 1501 if (hasReceiver || receiver.canHaveSideEffects()) { 1502 receiver.put(hasReceiver ? receiver.type : Type.VOID_TYPE, v); 1503 } 1504 } 1505 1506 @Override 1507 public boolean isNonStaticAccess(boolean isRead) { 1508 return isRead ? !isStaticPut : !isStaticStore; 1509 } 1510 1511 public int receiverSize() { 1512 return receiver.type.getSize(); 1513 } 1514 1515 @Override 1516 public void dup(@NotNull InstructionAdapter v, boolean withWriteReceiver) { 1517 if (!withWriteReceiver) { 1518 super.dup(v, false); 1519 } 1520 else { 1521 int receiverSize = isNonStaticAccess(false) ? receiverSize() : 0; 1522 switch (receiverSize) { 1523 case 0: 1524 AsmUtil.dup(v, type); 1525 break; 1526 1527 case 1: 1528 if (type.getSize() == 2) { 1529 v.dup2X1(); 1530 } 1531 else { 1532 v.dupX1(); 1533 } 1534 break; 1535 1536 case 2: 1537 if (type.getSize() == 2) { 1538 v.dup2X2(); 1539 } 1540 else { 1541 v.dupX2(); 1542 } 1543 break; 1544 1545 case -1: 1546 throw new UnsupportedOperationException(); 1547 } 1548 } 1549 } 1550 1551 @Override 1552 public void store( 1553 @NotNull StackValue rightSide, @NotNull InstructionAdapter v, boolean skipReceiver 1554 ) { 1555 if (!skipReceiver) { 1556 putReceiver(v, false); 1557 } 1558 rightSide.put(rightSide.type, v); 1559 storeSelector(rightSide.type, v); 1560 } 1561 } 1562 1563 private static class ComplexReceiver extends StackValue { 1564 1565 private final StackValueWithSimpleReceiver originalValueWithReceiver; 1566 private final boolean[] isReadOperations; 1567 1568 public ComplexReceiver(StackValueWithSimpleReceiver value, boolean[] isReadOperations) { 1569 super(value.type, value.receiver.canHaveSideEffects()); 1570 this.originalValueWithReceiver = value; 1571 this.isReadOperations = isReadOperations; 1572 if (value instanceof CollectionElement) { 1573 if (value.receiver instanceof CollectionElementReceiver) { 1574 ((CollectionElementReceiver) value.receiver).isComplexOperationWithDup = true; 1575 } 1576 } 1577 } 1578 1579 @Override 1580 public void putSelector( 1581 @NotNull Type type, @NotNull InstructionAdapter v 1582 ) { 1583 boolean wasPut = false; 1584 StackValue receiver = originalValueWithReceiver.receiver; 1585 for (boolean operation : isReadOperations) { 1586 if (originalValueWithReceiver.isNonStaticAccess(operation)) { 1587 if (!wasPut) { 1588 receiver.put(receiver.type, v); 1589 wasPut = true; 1590 } 1591 else { 1592 receiver.dup(v, false); 1593 } 1594 } 1595 } 1596 1597 if (!wasPut && receiver.canHaveSideEffects()) { 1598 receiver.put(Type.VOID_TYPE, v); 1599 } 1600 } 1601 } 1602 1603 public static class Receiver extends StackValue { 1604 1605 private final StackValue[] instructions; 1606 1607 protected Receiver(@NotNull Type type, StackValue... receiverInstructions) { 1608 super(type); 1609 instructions = receiverInstructions; 1610 } 1611 1612 @Override 1613 public void putSelector( 1614 @NotNull Type type, @NotNull InstructionAdapter v 1615 ) { 1616 for (StackValue instruction : instructions) { 1617 instruction.put(instruction.type, v); 1618 } 1619 } 1620 } 1621 1622 public static class DelegatedForComplexReceiver extends StackValueWithSimpleReceiver { 1623 1624 public final StackValueWithSimpleReceiver originalValue; 1625 1626 public DelegatedForComplexReceiver( 1627 @NotNull Type type, 1628 @NotNull StackValueWithSimpleReceiver originalValue, 1629 @NotNull ComplexReceiver receiver 1630 ) { 1631 super(type, bothReceiverStatic(originalValue), bothReceiverStatic(originalValue), receiver, originalValue.canHaveSideEffects()); 1632 this.originalValue = originalValue; 1633 } 1634 1635 private static boolean bothReceiverStatic(StackValueWithSimpleReceiver originalValue) { 1636 return !(originalValue.isNonStaticAccess(true) || originalValue.isNonStaticAccess(false)); 1637 } 1638 1639 @Override 1640 public void putSelector( 1641 @NotNull Type type, @NotNull InstructionAdapter v 1642 ) { 1643 originalValue.putSelector(type, v); 1644 } 1645 1646 @Override 1647 public void storeSelector( 1648 @NotNull Type topOfStackType, @NotNull InstructionAdapter v 1649 ) { 1650 originalValue.storeSelector(topOfStackType, v); 1651 } 1652 1653 @Override 1654 public void dup(@NotNull InstructionAdapter v, boolean withWriteReceiver) { 1655 originalValue.dup(v, withWriteReceiver); 1656 } 1657 } 1658 1659 public static StackValue complexWriteReadReceiver(StackValue stackValue) { 1660 return complexReceiver(stackValue, false, true); 1661 } 1662 1663 private static StackValue complexReceiver(StackValue stackValue, boolean... isReadOperations) { 1664 if (stackValue instanceof StackValueWithSimpleReceiver) { 1665 return new DelegatedForComplexReceiver(stackValue.type, (StackValueWithSimpleReceiver) stackValue, 1666 new ComplexReceiver((StackValueWithSimpleReceiver) stackValue, isReadOperations)); 1667 } 1668 else { 1669 return stackValue; 1670 } 1671 } 1672 1673 static class SafeCall extends StackValue { 1674 1675 @NotNull private final Type type; 1676 private final StackValue receiver; 1677 @Nullable private final Label ifNull; 1678 1679 public SafeCall(@NotNull Type type, @NotNull StackValue value, @Nullable Label ifNull) { 1680 super(type); 1681 this.type = type; 1682 this.receiver = value; 1683 this.ifNull = ifNull; 1684 } 1685 1686 @Override 1687 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1688 receiver.put(this.type, v); 1689 if (ifNull != null) { 1690 //not a primitive 1691 v.dup(); 1692 v.ifnull(ifNull); 1693 } 1694 coerceTo(type, v); 1695 } 1696 } 1697 1698 static class SafeFallback extends StackValueWithSimpleReceiver { 1699 1700 @Nullable private final Label ifNull; 1701 1702 public SafeFallback(@NotNull Type type, @Nullable Label ifNull, StackValue receiver) { 1703 super(type, false, false, receiver, true); 1704 this.ifNull = ifNull; 1705 } 1706 1707 @Override 1708 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 1709 Label end = new Label(); 1710 1711 v.goTo(end); 1712 v.mark(ifNull); 1713 v.pop(); 1714 if (!this.type.equals(Type.VOID_TYPE)) { 1715 v.aconst(null); 1716 } 1717 v.mark(end); 1718 1719 coerceTo(type, v); 1720 } 1721 1722 @Override 1723 public void store( 1724 @NotNull StackValue rightSide, @NotNull InstructionAdapter v, boolean skipReceiver 1725 ) { 1726 receiver.store(rightSide, v, skipReceiver); 1727 1728 Label end = new Label(); 1729 v.goTo(end); 1730 v.mark(ifNull); 1731 v.pop(); 1732 v.mark(end); 1733 } 1734 } 1735 } 1736