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