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