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