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