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