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