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 org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.asm4.Label; 023 import org.jetbrains.asm4.Type; 024 import org.jetbrains.asm4.commons.InstructionAdapter; 025 import org.jetbrains.asm4.commons.Method; 026 import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; 027 import org.jetbrains.jet.codegen.state.GenerationState; 028 import org.jetbrains.jet.codegen.state.JetTypeMapper; 029 import org.jetbrains.jet.lang.descriptors.*; 030 import org.jetbrains.jet.lang.psi.JetExpression; 031 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 032 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 033 import org.jetbrains.jet.lexer.JetTokens; 034 035 import java.util.List; 036 037 import static org.jetbrains.asm4.Opcodes.*; 038 import static org.jetbrains.jet.codegen.AsmUtil.*; 039 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; 040 041 public abstract class StackValue { 042 043 private static final String NULLABLE_BYTE_TYPE_NAME = "java/lang/Byte"; 044 private static final String NULLABLE_SHORT_TYPE_NAME = "java/lang/Short"; 045 private static final String NULLABLE_LONG_TYPE_NAME = "java/lang/Long"; 046 047 @NotNull 048 public final Type type; 049 050 protected StackValue(@NotNull Type type) { 051 this.type = type; 052 } 053 054 /** 055 * Put this value to the top of the stack. 056 */ 057 public abstract void put(Type type, InstructionAdapter v); 058 059 /** 060 * 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 061 * JVM stack after this value was generated. 062 * 063 * @param type the type as which the value should be put 064 * @param v the visitor used to genClassOrObject the instructions 065 * @param depth the number of new values put onto the stack 066 */ 067 protected void moveToTopOfStack(Type type, InstructionAdapter v, int depth) { 068 put(type, v); 069 } 070 071 /** 072 * Set this value from the top of the stack. 073 */ 074 public void store(Type topOfStackType, InstructionAdapter v) { 075 throw new UnsupportedOperationException("cannot store to value " + this); 076 } 077 078 public void dupReceiver(InstructionAdapter v) { 079 } 080 081 public int receiverSize() { 082 return 0; 083 } 084 085 public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { 086 put(this.type, v); 087 coerceTo(Type.BOOLEAN_TYPE, v); 088 if (jumpIfFalse) { 089 v.ifeq(label); 090 } 091 else { 092 v.ifne(label); 093 } 094 } 095 096 public static Local local(int index, Type type) { 097 return new Local(index, type); 098 } 099 100 public static StackValue shared(int index, Type type) { 101 return new Shared(index, type); 102 } 103 104 public static StackValue onStack(Type type) { 105 return type == Type.VOID_TYPE ? none() : new OnStack(type); 106 } 107 108 public static StackValue constant(@Nullable Object value, Type type) { 109 return new Constant(value, type); 110 } 111 112 public static StackValue cmp(IElementType opToken, Type type) { 113 return type.getSort() == Type.OBJECT ? new ObjectCompare(opToken, type) : new NumberCompare(opToken, type); 114 } 115 116 public static StackValue not(StackValue stackValue) { 117 return new Invert(stackValue); 118 } 119 120 @NotNull 121 public static StackValue arrayElement(Type type, boolean unbox) { 122 return new ArrayElement(type, unbox); 123 } 124 125 @NotNull 126 public static StackValue collectionElement( 127 Type type, 128 ResolvedCall<FunctionDescriptor> getter, 129 ResolvedCall<FunctionDescriptor> setter, 130 ExpressionCodegen codegen, 131 GenerationState state 132 ) { 133 return new CollectionElement(type, getter, setter, codegen, state); 134 } 135 136 @NotNull 137 public static Field field(@NotNull Type type, @NotNull Type owner, @NotNull String name, boolean isStatic) { 138 return new Field(type, owner, name, isStatic); 139 } 140 141 @NotNull 142 public static Property property( 143 @NotNull PropertyDescriptor descriptor, 144 @NotNull Type methodOwner, 145 @NotNull Type type, 146 boolean isStatic, 147 @NotNull String name, 148 @Nullable CallableMethod getter, 149 @Nullable CallableMethod setter, 150 GenerationState state 151 ) { 152 return new Property(descriptor, methodOwner, getter, setter, isStatic, name, type, state); 153 } 154 155 @NotNull 156 public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) { 157 return new Expression(type, expression, generator); 158 } 159 160 private static void box(Type type, Type toType, InstructionAdapter v) { 161 if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) { 162 v.cast(type, Type.BYTE_TYPE); 163 v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";"); 164 } 165 else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) { 166 v.cast(type, Type.SHORT_TYPE); 167 v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";"); 168 } 169 else if (type == Type.LONG_TYPE || toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) { 170 v.cast(type, Type.LONG_TYPE); 171 v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME +";"); 172 } 173 else if (type == Type.INT_TYPE) { 174 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 175 } 176 else if (type == Type.BOOLEAN_TYPE) { 177 v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); 178 } 179 else if (type == Type.CHAR_TYPE) { 180 v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); 181 } 182 else if (type == Type.FLOAT_TYPE) { 183 v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); 184 } 185 else if (type == Type.DOUBLE_TYPE) { 186 v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); 187 } 188 } 189 190 private static void unbox(Type type, InstructionAdapter v) { 191 if (type == Type.INT_TYPE) { 192 v.invokevirtual("java/lang/Number", "intValue", "()I"); 193 } 194 else if (type == Type.BOOLEAN_TYPE) { 195 v.invokevirtual("java/lang/Boolean", "booleanValue", "()Z"); 196 } 197 else if (type == Type.CHAR_TYPE) { 198 v.invokevirtual("java/lang/Character", "charValue", "()C"); 199 } 200 else if (type == Type.SHORT_TYPE) { 201 v.invokevirtual("java/lang/Number", "shortValue", "()S"); 202 } 203 else if (type == Type.LONG_TYPE) { 204 v.invokevirtual("java/lang/Number", "longValue", "()J"); 205 } 206 else if (type == Type.BYTE_TYPE) { 207 v.invokevirtual("java/lang/Number", "byteValue", "()B"); 208 } 209 else if (type == Type.FLOAT_TYPE) { 210 v.invokevirtual("java/lang/Number", "floatValue", "()F"); 211 } 212 else if (type == Type.DOUBLE_TYPE) { 213 v.invokevirtual("java/lang/Number", "doubleValue", "()D"); 214 } 215 } 216 217 protected void coerceTo(Type toType, InstructionAdapter v) { 218 coerce(this.type, toType, v); 219 } 220 221 protected void coerceFrom(Type topOfStackType, InstructionAdapter v) { 222 coerce(topOfStackType, this.type, v); 223 } 224 225 public static void coerce(Type fromType, Type toType, InstructionAdapter v) { 226 if (toType.equals(fromType)) return; 227 228 if (toType.getSort() == Type.VOID) { 229 pop(v, fromType); 230 } 231 else if (fromType.getSort() == Type.VOID) { 232 if (toType.equals(UNIT_TYPE) || toType.equals(OBJECT_TYPE)) { 233 putUnitInstance(v); 234 } 235 else if (toType.getSort() == Type.OBJECT || toType.getSort() == Type.ARRAY) { 236 v.aconst(null); 237 } 238 else { 239 pushDefaultPrimitiveValueOnStack(toType, v); 240 } 241 } 242 else if (toType.equals(UNIT_TYPE)) { 243 if (fromType.equals(getType(Object.class))) { 244 v.checkcast(UNIT_TYPE); 245 } 246 else if (!fromType.equals(getType(Void.class))) { 247 pop(v, fromType); 248 putUnitInstance(v); 249 } 250 } 251 else if (toType.getSort() == Type.ARRAY) { 252 v.checkcast(toType); 253 } 254 else if (toType.getSort() == Type.OBJECT) { 255 if (fromType.getSort() == Type.OBJECT || fromType.getSort() == Type.ARRAY) { 256 if (!toType.equals(OBJECT_TYPE)) { 257 v.checkcast(toType); 258 } 259 } 260 else { 261 box(fromType, toType, v); 262 } 263 } 264 else if (fromType.getSort() == Type.OBJECT) { 265 if (fromType.equals(getType(Boolean.class)) || fromType.equals(getType(Character.class))) { 266 unbox(unboxType(fromType), v); 267 coerce(unboxType(fromType), toType, v); 268 } 269 else { 270 if (toType.getSort() == Type.BOOLEAN || toType.getSort() == Type.CHAR) { 271 coerce(fromType, boxType(toType), v); 272 } 273 else { 274 coerce(fromType, getType(Number.class), v); 275 } 276 unbox(toType, v); 277 } 278 } 279 else { 280 v.cast(fromType, toType); 281 } 282 } 283 284 public static void putUnitInstance(InstructionAdapter v) { 285 v.visitFieldInsn(GETSTATIC, UNIT_TYPE.getInternalName(), "VALUE", UNIT_TYPE.getDescriptor()); 286 } 287 288 protected void putAsBoolean(InstructionAdapter v) { 289 Label ifTrue = new Label(); 290 Label end = new Label(); 291 condJump(ifTrue, false, v); 292 v.iconst(0); 293 v.goTo(end); 294 v.mark(ifTrue); 295 v.iconst(1); 296 v.mark(end); 297 } 298 299 public static StackValue none() { 300 return None.INSTANCE; 301 } 302 303 public static StackValue fieldForSharedVar(Type localType, Type classType, String fieldName) { 304 return new FieldForSharedVar(localType, classType, fieldName); 305 } 306 307 public static StackValue composed(StackValue prefix, StackValue suffix) { 308 return new Composed(prefix, suffix); 309 } 310 311 public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean isExplicit) { 312 // Coerce this/super for traits to support traits with required classes. 313 // Coerce explicit 'this' for the case when it is smartcasted. 314 // Do not coerce for other classes due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints). 315 boolean coerceType = descriptor.getKind() == ClassKind.TRAIT || (isExplicit && !isSuper); 316 return new ThisOuter(codegen, descriptor, isSuper, coerceType); 317 } 318 319 public static StackValue postIncrement(int index, int increment) { 320 return new PostIncrement(index, increment); 321 } 322 323 public static StackValue preIncrement(int index, int increment) { 324 return new PreIncrement(index, increment); 325 } 326 327 public static StackValue receiver( 328 ResolvedCall<?> resolvedCall, 329 StackValue receiver, 330 ExpressionCodegen codegen, 331 @Nullable CallableMethod callableMethod 332 ) { 333 if (resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()) { 334 return new CallReceiver(resolvedCall, receiver, codegen, callableMethod, true); 335 } 336 return receiver; 337 } 338 339 public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) { 340 if (receiverWithParameter instanceof CallReceiver) { 341 CallReceiver callReceiver = (CallReceiver) receiverWithParameter; 342 return new CallReceiver(callReceiver.resolvedCall, callReceiver.receiver, 343 callReceiver.codegen, callReceiver.callableMethod, false); 344 } 345 return receiverWithParameter; 346 } 347 348 public static Field singleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) { 349 FieldInfo info = FieldInfo.createForSingleton(classDescriptor, typeMapper); 350 return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true); 351 } 352 353 private static class None extends StackValue { 354 public static final None INSTANCE = new None(); 355 356 private None() { 357 super(Type.VOID_TYPE); 358 } 359 360 @Override 361 public void put(Type type, InstructionAdapter v) { 362 coerceTo(type, v); 363 } 364 } 365 366 public static class Local extends StackValue { 367 public final int index; 368 369 private Local(int index, Type type) { 370 super(type); 371 this.index = index; 372 373 if (index < 0) { 374 throw new IllegalStateException("local variable index must be non-negative"); 375 } 376 } 377 378 @Override 379 public void put(Type type, InstructionAdapter v) { 380 v.load(index, this.type); 381 coerceTo(type, v); 382 // TODO unbox 383 } 384 385 @Override 386 public void store(Type topOfStackType, InstructionAdapter v) { 387 coerceFrom(topOfStackType, v); 388 v.store(index, this.type); 389 } 390 } 391 392 public static class OnStack extends StackValue { 393 public OnStack(Type type) { 394 super(type); 395 } 396 397 @Override 398 public void put(Type type, InstructionAdapter v) { 399 coerceTo(type, v); 400 } 401 402 @Override 403 public void moveToTopOfStack(Type type, InstructionAdapter v, int depth) { 404 if (depth == 0) { 405 put(type, v); 406 } 407 else if (depth == 1) { 408 if (type.getSize() != 1) { 409 throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack"); 410 } 411 v.swap(); 412 } 413 else { 414 throw new UnsupportedOperationException("unsupported move-to-top depth " + depth); 415 } 416 } 417 } 418 419 public static class Constant extends StackValue { 420 @Nullable 421 private final Object value; 422 423 public Constant(@Nullable Object value, Type type) { 424 super(type); 425 this.value = value; 426 } 427 428 @Override 429 public void put(Type type, InstructionAdapter v) { 430 if (value instanceof Integer) { 431 v.iconst((Integer) value); 432 } 433 else if (value instanceof Long) { 434 v.lconst((Long) value); 435 } 436 else if (value instanceof Float) { 437 v.fconst((Float) value); 438 } 439 else if (value instanceof Double) { 440 v.dconst((Double) value); 441 } 442 else { 443 v.aconst(value); 444 } 445 446 coerceTo(type, v); 447 } 448 449 @Override 450 public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { 451 if (value instanceof Boolean) { 452 boolean boolValue = (Boolean) value; 453 if (boolValue ^ jumpIfFalse) { 454 v.goTo(label); 455 } 456 } 457 else { 458 throw new UnsupportedOperationException("don't know how to generate this condjump"); 459 } 460 } 461 } 462 463 private static class NumberCompare extends StackValue { 464 protected final IElementType opToken; 465 private final Type operandType; 466 467 public NumberCompare(IElementType opToken, Type operandType) { 468 super(Type.BOOLEAN_TYPE); 469 this.opToken = opToken; 470 this.operandType = operandType; 471 } 472 473 @Override 474 public void put(Type type, InstructionAdapter v) { 475 putAsBoolean(v); 476 coerceTo(type, v); 477 } 478 479 @Override 480 public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { 481 int opcode; 482 if (opToken == JetTokens.EQEQ) { 483 opcode = jumpIfFalse ? IFNE : IFEQ; 484 } 485 else if (opToken == JetTokens.EXCLEQ) { 486 opcode = jumpIfFalse ? IFEQ : IFNE; 487 } 488 else if (opToken == JetTokens.GT) { 489 opcode = jumpIfFalse ? IFLE : IFGT; 490 } 491 else if (opToken == JetTokens.GTEQ) { 492 opcode = jumpIfFalse ? IFLT : IFGE; 493 } 494 else if (opToken == JetTokens.LT) { 495 opcode = jumpIfFalse ? IFGE : IFLT; 496 } 497 else if (opToken == JetTokens.LTEQ) { 498 opcode = jumpIfFalse ? IFGT : IFLE; 499 } 500 else { 501 throw new UnsupportedOperationException("don't know how to generate this condjump"); 502 } 503 if (operandType == Type.FLOAT_TYPE || operandType == Type.DOUBLE_TYPE) { 504 if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 505 v.cmpl(operandType); 506 } 507 else { 508 v.cmpg(operandType); 509 } 510 } 511 else if (operandType == Type.LONG_TYPE) { 512 v.lcmp(); 513 } 514 else { 515 opcode += (IF_ICMPEQ - IFEQ); 516 } 517 v.visitJumpInsn(opcode, label); 518 } 519 } 520 521 private static class ObjectCompare extends NumberCompare { 522 public ObjectCompare(IElementType opToken, Type operandType) { 523 super(opToken, operandType); 524 } 525 526 @Override 527 public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { 528 int opcode; 529 if (opToken == JetTokens.EQEQEQ) { 530 opcode = jumpIfFalse ? IF_ACMPNE : IF_ACMPEQ; 531 } 532 else if (opToken == JetTokens.EXCLEQEQEQ) { 533 opcode = jumpIfFalse ? IF_ACMPEQ : IF_ACMPNE; 534 } 535 else { 536 throw new UnsupportedOperationException("don't know how to generate this condjump"); 537 } 538 v.visitJumpInsn(opcode, label); 539 } 540 } 541 542 private static class Invert extends StackValue { 543 private final StackValue myOperand; 544 545 private Invert(StackValue operand) { 546 super(Type.BOOLEAN_TYPE); 547 myOperand = operand; 548 if (myOperand.type != Type.BOOLEAN_TYPE) { 549 throw new UnsupportedOperationException("operand of ! must be boolean"); 550 } 551 } 552 553 @Override 554 public void put(Type type, InstructionAdapter v) { 555 putAsBoolean(v); 556 coerceTo(type, v); 557 } 558 559 @Override 560 public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { 561 myOperand.condJump(label, !jumpIfFalse, v); 562 } 563 } 564 565 private static class ArrayElement extends StackValue { 566 private final Type boxed; 567 568 public ArrayElement(Type type, boolean unbox) { 569 super(type); 570 this.boxed = unbox ? boxType(type) : type; 571 } 572 573 @Override 574 public void put(Type type, InstructionAdapter v) { 575 v.aload(boxed); // assumes array and index are on the stack 576 coerce(boxed, type, v); 577 } 578 579 @Override 580 public void store(Type topOfStackType, InstructionAdapter v) { 581 coerce(topOfStackType, boxed, v); 582 v.astore(boxed); 583 } 584 585 @Override 586 public void dupReceiver(InstructionAdapter v) { 587 v.dup2(); // array and index 588 } 589 590 @Override 591 public int receiverSize() { 592 return 2; 593 } 594 } 595 596 private static class CollectionElement extends StackValue { 597 private final Callable getter; 598 private final Callable setter; 599 private final ExpressionCodegen codegen; 600 private final GenerationState state; 601 private final FrameMap frame; 602 private final ResolvedCall<FunctionDescriptor> resolvedGetCall; 603 private final ResolvedCall<FunctionDescriptor> resolvedSetCall; 604 private final FunctionDescriptor setterDescriptor; 605 private final FunctionDescriptor getterDescriptor; 606 607 public CollectionElement( 608 Type type, 609 ResolvedCall<FunctionDescriptor> resolvedGetCall, 610 ResolvedCall<FunctionDescriptor> resolvedSetCall, 611 ExpressionCodegen codegen, 612 GenerationState state 613 ) { 614 super(type); 615 this.resolvedGetCall = resolvedGetCall; 616 this.resolvedSetCall = resolvedSetCall; 617 this.state = state; 618 this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor(); 619 this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor(); 620 this.setter = resolvedSetCall == null ? null : codegen.resolveToCallable(setterDescriptor, false); 621 this.getter = resolvedGetCall == null ? null : codegen.resolveToCallable(getterDescriptor, false); 622 this.codegen = codegen; 623 this.frame = codegen.myFrameMap; 624 } 625 626 @Override 627 public void put(Type type, InstructionAdapter v) { 628 if (getter == null) { 629 throw new UnsupportedOperationException("no getter specified"); 630 } 631 if (getter instanceof CallableMethod) { 632 ((CallableMethod) getter).invokeWithNotNullAssertion(v, state, resolvedGetCall); 633 } 634 else { 635 ((IntrinsicMethod) getter).generate(codegen, v, this.type, null, null, null); 636 } 637 coerceTo(type, v); 638 } 639 640 @Override 641 public void store(Type topOfStackType, InstructionAdapter v) { 642 if (setter == null) { 643 throw new UnsupportedOperationException("no setter specified"); 644 } 645 if (setter instanceof CallableMethod) { 646 CallableMethod method = (CallableMethod) setter; 647 Method asmMethod = method.getAsmMethod(); 648 Type[] argumentTypes = asmMethod.getArgumentTypes(); 649 coerce(topOfStackType, argumentTypes[argumentTypes.length - 1], v); 650 method.invokeWithNotNullAssertion(v, state, resolvedSetCall); 651 Type returnType = asmMethod.getReturnType(); 652 if (returnType != Type.VOID_TYPE) { 653 pop(v, returnType); 654 } 655 } 656 else { 657 //noinspection ConstantConditions 658 ((IntrinsicMethod) setter).generate(codegen, v, null, null, null, null); 659 } 660 } 661 662 @Override 663 public int receiverSize() { 664 if (isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) { 665 return 2; 666 } 667 else { 668 return -1; 669 } 670 } 671 672 @Override 673 public void dupReceiver(InstructionAdapter v) { 674 if (isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) { 675 v.dup2(); // collection and index 676 return; 677 } 678 679 int size = 0; 680 // ugly hack: getting the last variable index 681 int lastIndex = frame.enterTemp(Type.INT_TYPE); 682 frame.leaveTemp(Type.INT_TYPE); 683 684 // indexes 685 List<ValueParameterDescriptor> valueParameters = resolvedGetCall.getResultingDescriptor().getValueParameters(); 686 int firstParamIndex = -1; 687 for (int i = valueParameters.size() - 1; i >= 0; --i) { 688 Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType()); 689 int sz = type.getSize(); 690 frame.enterTemp(type); 691 lastIndex += sz; 692 size += sz; 693 v.store((firstParamIndex = lastIndex) - sz, type); 694 } 695 696 ReceiverValue receiverParameter = resolvedGetCall.getReceiverArgument(); 697 int receiverIndex = -1; 698 if (receiverParameter.exists()) { 699 Type type = codegen.typeMapper.mapType(receiverParameter.getType()); 700 int sz = type.getSize(); 701 frame.enterTemp(type); 702 lastIndex += sz; 703 size += sz; 704 v.store((receiverIndex = lastIndex) - sz, type); 705 } 706 707 ReceiverValue thisObject = resolvedGetCall.getThisObject(); 708 int thisIndex = -1; 709 if (thisObject.exists()) { 710 frame.enterTemp(OBJECT_TYPE); 711 lastIndex++; 712 size++; 713 v.store((thisIndex = lastIndex) - 1, OBJECT_TYPE); 714 } 715 716 // for setter 717 718 int realReceiverIndex; 719 Type realReceiverType; 720 if (receiverIndex != -1) { 721 realReceiverType = codegen.typeMapper.mapType(receiverParameter.getType()); 722 realReceiverIndex = receiverIndex; 723 } 724 else if (thisIndex != -1) { 725 realReceiverType = OBJECT_TYPE; 726 realReceiverIndex = thisIndex; 727 } 728 else { 729 throw new UnsupportedOperationException(); 730 } 731 732 if (resolvedSetCall.getThisObject().exists()) { 733 if (resolvedSetCall.getReceiverArgument().exists()) { 734 codegen.generateFromResolvedCall(resolvedSetCall.getThisObject(), OBJECT_TYPE); 735 } 736 v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType); 737 } 738 else { 739 if (resolvedSetCall.getReceiverArgument().exists()) { 740 v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType); 741 } 742 else { 743 throw new UnsupportedOperationException(); 744 } 745 } 746 747 int index = firstParamIndex; 748 for (ValueParameterDescriptor valueParameter : valueParameters) { 749 Type type = codegen.typeMapper.mapType(valueParameter.getType()); 750 int sz = type.getSize(); 751 v.load(index - sz, type); 752 index -= sz; 753 } 754 755 // restoring original 756 if (thisIndex != -1) { 757 v.load(thisIndex - 1, OBJECT_TYPE); 758 } 759 760 if (receiverIndex != -1) { 761 v.load(receiverIndex - realReceiverType.getSize(), realReceiverType); 762 } 763 764 index = firstParamIndex; 765 for (ValueParameterDescriptor valueParameter : valueParameters) { 766 Type type = codegen.typeMapper.mapType(valueParameter.getType()); 767 int sz = type.getSize(); 768 v.load(index - sz, type); 769 index -= sz; 770 } 771 772 for (int i = 0; i < size; i++) { 773 frame.leaveTemp(OBJECT_TYPE); 774 } 775 } 776 777 private boolean isStandardStack(ResolvedCall<?> call, int valueParamsSize) { 778 if (call == null) { 779 return true; 780 } 781 782 List<ValueParameterDescriptor> valueParameters = call.getResultingDescriptor().getValueParameters(); 783 if (valueParameters.size() != valueParamsSize) { 784 return false; 785 } 786 787 for (ValueParameterDescriptor valueParameter : valueParameters) { 788 if (codegen.typeMapper.mapType(valueParameter.getType()).getSize() != 1) { 789 return false; 790 } 791 } 792 793 if (call.getThisObject().exists()) { 794 if (call.getReceiverArgument().exists()) { 795 return false; 796 } 797 } 798 else { 799 if (codegen.typeMapper.mapType(call.getResultingDescriptor().getReceiverParameter().getType()) 800 .getSize() != 1) { 801 return false; 802 } 803 } 804 805 return true; 806 } 807 } 808 809 810 public static class Field extends StackValueWithSimpleReceiver { 811 public final Type owner; 812 public final String name; 813 814 public Field(Type type, Type owner, String name, boolean isStatic) { 815 super(type, isStatic); 816 this.owner = owner; 817 this.name = name; 818 } 819 820 @Override 821 public void put(Type type, InstructionAdapter v) { 822 v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor()); 823 coerceTo(type, v); 824 } 825 826 @Override 827 public void store(Type topOfStackType, InstructionAdapter v) { 828 coerceFrom(topOfStackType, v); 829 v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor()); 830 } 831 } 832 833 static class Property extends StackValueWithSimpleReceiver { 834 @Nullable 835 private final CallableMethod getter; 836 @Nullable 837 private final CallableMethod setter; 838 @NotNull 839 public final Type methodOwner; 840 841 @NotNull 842 private final PropertyDescriptor descriptor; 843 @NotNull 844 private final GenerationState state; 845 846 private final String name; 847 848 public Property( 849 @NotNull PropertyDescriptor descriptor, @NotNull Type methodOwner, 850 @Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStatic, 851 @NotNull String name, @NotNull Type type, @NotNull GenerationState state 852 ) { 853 super(type, isStatic); 854 this.methodOwner = methodOwner; 855 this.getter = getter; 856 this.setter = setter; 857 this.descriptor = descriptor; 858 this.state = state; 859 this.name = name; 860 } 861 862 @Override 863 public void put(Type type, InstructionAdapter v) { 864 if (getter == null) { 865 v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), getPropertyName(), 866 this.type.getDescriptor()); 867 genNotNullAssertionForField(v, state, descriptor); 868 coerceTo(type, v); 869 } 870 else { 871 Method method = getter.getAsmMethod(); 872 v.visitMethodInsn(getter.getInvokeOpcode(), getter.getOwner().getInternalName(), method.getName(), method.getDescriptor()); 873 coerce(method.getReturnType(), type, v); 874 } 875 } 876 877 @Override 878 public void store(Type topOfStackType, InstructionAdapter v) { 879 coerceFrom(topOfStackType, v); 880 if (setter == null) { 881 v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), getPropertyName(), 882 this.type.getDescriptor()); } 883 else { 884 Method method = setter.getAsmMethod(); 885 v.visitMethodInsn(setter.getInvokeOpcode(), setter.getOwner().getInternalName(), method.getName(), method.getDescriptor()); 886 } 887 } 888 889 private String getPropertyName() { 890 return name; 891 } 892 893 public boolean isPropertyWithBackingFieldInOuterClass() { 894 return descriptor instanceof AccessorForPropertyBackingFieldInOuterClass; 895 } 896 } 897 898 private static class Expression extends StackValue { 899 private final JetExpression expression; 900 private final ExpressionCodegen generator; 901 902 public Expression(Type type, JetExpression expression, ExpressionCodegen generator) { 903 super(type); 904 this.expression = expression; 905 this.generator = generator; 906 } 907 908 @Override 909 public void put(Type type, InstructionAdapter v) { 910 generator.gen(expression, type); 911 } 912 } 913 914 public static class Shared extends StackValue { 915 private final int index; 916 private boolean isReleaseOnPut = false; 917 918 public Shared(int index, Type type) { 919 super(type); 920 this.index = index; 921 } 922 923 public void releaseOnPut() { 924 isReleaseOnPut = true; 925 } 926 927 public int getIndex() { 928 return index; 929 } 930 931 @Override 932 public void put(Type type, InstructionAdapter v) { 933 v.load(index, OBJECT_TYPE); 934 Type refType = refType(this.type); 935 Type sharedType = sharedTypeForType(this.type); 936 v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 937 coerceFrom(refType, v); 938 coerceTo(type, v); 939 if (isReleaseOnPut) { 940 v.aconst(null); 941 v.store(index, OBJECT_TYPE); 942 } 943 } 944 945 @Override 946 public void store(Type topOfStackType, InstructionAdapter v) { 947 coerceFrom(topOfStackType, v); 948 v.load(index, OBJECT_TYPE); 949 AsmUtil.swap(v, sharedTypeForType(this.type), topOfStackType); 950 Type refType = refType(this.type); 951 Type sharedType = sharedTypeForType(this.type); 952 v.visitFieldInsn(PUTFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 953 } 954 } 955 956 public static Type sharedTypeForType(Type type) { 957 switch (type.getSort()) { 958 case Type.OBJECT: 959 case Type.ARRAY: 960 return OBJECT_REF_TYPE; 961 case Type.BYTE: 962 return Type.getObjectType("kotlin/jvm/internal/Ref$ByteRef"); 963 case Type.SHORT: 964 return Type.getObjectType("kotlin/jvm/internal/Ref$ShortRef"); 965 case Type.CHAR: 966 return Type.getObjectType("kotlin/jvm/internal/Ref$CharRef"); 967 case Type.INT: 968 return Type.getObjectType("kotlin/jvm/internal/Ref$IntRef"); 969 case Type.LONG: 970 return Type.getObjectType("kotlin/jvm/internal/Ref$LongRef"); 971 case Type.BOOLEAN: 972 return Type.getObjectType("kotlin/jvm/internal/Ref$BooleanRef"); 973 case Type.FLOAT: 974 return Type.getObjectType("kotlin/jvm/internal/Ref$FloatRef"); 975 case Type.DOUBLE: 976 return Type.getObjectType("kotlin/jvm/internal/Ref$DoubleRef"); 977 default: 978 throw new UnsupportedOperationException(); 979 } 980 } 981 982 public static Type refType(Type type) { 983 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 984 return OBJECT_TYPE; 985 } 986 987 return type; 988 } 989 990 static class FieldForSharedVar extends StackValueWithSimpleReceiver { 991 final Type owner; 992 final String name; 993 994 public FieldForSharedVar(Type type, Type owner, String name) { 995 super(type, false); 996 this.owner = owner; 997 this.name = name; 998 } 999 1000 @Override 1001 public void put(Type type, InstructionAdapter v) { 1002 Type sharedType = sharedTypeForType(this.type); 1003 Type refType = refType(this.type); 1004 v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); 1005 coerceFrom(refType, v); 1006 coerceTo(type, v); 1007 } 1008 1009 @Override 1010 public void store(Type topOfStackType, InstructionAdapter v) { 1011 coerceFrom(topOfStackType, v); 1012 v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "element", refType(type).getDescriptor()); 1013 } 1014 } 1015 1016 public static class Composed extends StackValue { 1017 public final StackValue prefix; 1018 public final StackValue suffix; 1019 1020 public Composed(StackValue prefix, StackValue suffix) { 1021 super(suffix.type); 1022 this.prefix = prefix; 1023 this.suffix = suffix; 1024 } 1025 1026 @Override 1027 public void put(Type type, InstructionAdapter v) { 1028 prefix.put(prefix.type, v); 1029 suffix.put(type, v); 1030 } 1031 1032 @Override 1033 public void store(Type topOfStackType, InstructionAdapter v) { 1034 prefix.put(OBJECT_TYPE, v); 1035 suffix.store(topOfStackType, v); 1036 } 1037 } 1038 1039 private static class ThisOuter extends StackValue { 1040 private final ExpressionCodegen codegen; 1041 private final ClassDescriptor descriptor; 1042 private final boolean isSuper; 1043 private final boolean coerceType; 1044 1045 public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean coerceType) { 1046 super(OBJECT_TYPE); 1047 this.codegen = codegen; 1048 this.descriptor = descriptor; 1049 this.isSuper = isSuper; 1050 this.coerceType = coerceType; 1051 } 1052 1053 @Override 1054 public void put(Type type, InstructionAdapter v) { 1055 StackValue stackValue = codegen.generateThisOrOuter(descriptor, isSuper); 1056 stackValue.put(coerceType ? type : stackValue.type, v); 1057 } 1058 } 1059 1060 private static class PostIncrement extends StackValue { 1061 private final int index; 1062 private final int increment; 1063 1064 public PostIncrement(int index, int increment) { 1065 super(Type.INT_TYPE); 1066 this.index = index; 1067 this.increment = increment; 1068 } 1069 1070 @Override 1071 public void put(Type type, InstructionAdapter v) { 1072 if (!type.equals(Type.VOID_TYPE)) { 1073 v.load(index, Type.INT_TYPE); 1074 coerceTo(type, v); 1075 } 1076 v.iinc(index, increment); 1077 } 1078 } 1079 1080 private static class PreIncrement extends StackValue { 1081 private final int index; 1082 private final int increment; 1083 1084 public PreIncrement(int index, int increment) { 1085 super(Type.INT_TYPE); 1086 this.index = index; 1087 this.increment = increment; 1088 } 1089 1090 @Override 1091 public void put(Type type, InstructionAdapter v) { 1092 v.iinc(index, increment); 1093 if (!type.equals(Type.VOID_TYPE)) { 1094 v.load(index, Type.INT_TYPE); 1095 coerceTo(type, v); 1096 } 1097 } 1098 } 1099 1100 public static class CallReceiver extends StackValue { 1101 private final ResolvedCall<?> resolvedCall; 1102 final StackValue receiver; 1103 private final ExpressionCodegen codegen; 1104 private final CallableMethod callableMethod; 1105 private final boolean putReceiverArgumentOnStack; 1106 1107 public CallReceiver( 1108 ResolvedCall<?> resolvedCall, 1109 StackValue receiver, 1110 ExpressionCodegen codegen, 1111 CallableMethod callableMethod, 1112 boolean putReceiverArgumentOnStack 1113 ) { 1114 super(calcType(resolvedCall, codegen, callableMethod)); 1115 this.resolvedCall = resolvedCall; 1116 this.receiver = receiver; 1117 this.codegen = codegen; 1118 this.callableMethod = callableMethod; 1119 this.putReceiverArgumentOnStack = putReceiverArgumentOnStack; 1120 } 1121 1122 private static Type calcType(ResolvedCall<?> resolvedCall, ExpressionCodegen codegen, CallableMethod callableMethod) { 1123 ReceiverValue thisObject = resolvedCall.getThisObject(); 1124 ReceiverValue receiverArgument = resolvedCall.getReceiverArgument(); 1125 1126 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 1127 1128 if (thisObject.exists()) { 1129 if (callableMethod != null) { 1130 if (receiverArgument.exists()) { 1131 return callableMethod.getReceiverClass(); 1132 } 1133 else { 1134 //noinspection ConstantConditions 1135 return callableMethod.getThisType(); 1136 } 1137 } 1138 else { 1139 if (receiverArgument.exists()) { 1140 return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType()); 1141 } 1142 else { 1143 return codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType()); 1144 } 1145 } 1146 } 1147 else { 1148 if (receiverArgument.exists()) { 1149 if (callableMethod != null) { 1150 return callableMethod.getReceiverClass(); 1151 } 1152 else { 1153 return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType()); 1154 } 1155 } 1156 else { 1157 return Type.VOID_TYPE; 1158 } 1159 } 1160 } 1161 1162 @Override 1163 public void put(Type type, InstructionAdapter v) { 1164 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 1165 1166 ReceiverValue thisObject = resolvedCall.getThisObject(); 1167 ReceiverValue receiverArgument = resolvedCall.getReceiverArgument(); 1168 if (thisObject.exists()) { 1169 if (receiverArgument.exists()) { 1170 if (callableMethod != null) { 1171 codegen.generateFromResolvedCall(thisObject, callableMethod.getOwner()); 1172 } 1173 else { 1174 codegen.generateFromResolvedCall(thisObject, codegen.typeMapper 1175 .mapType(descriptor.getExpectedThisObject().getType())); 1176 } 1177 if (putReceiverArgumentOnStack) { 1178 genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 1); 1179 } 1180 } 1181 else { 1182 genReceiver(v, thisObject, type, null, 0); 1183 } 1184 } 1185 else { 1186 if (putReceiverArgumentOnStack && receiverArgument.exists()) { 1187 genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 0); 1188 } 1189 } 1190 } 1191 1192 private void genReceiver( 1193 InstructionAdapter v, ReceiverValue receiverArgument, Type type, 1194 @Nullable ReceiverParameterDescriptor receiverParameter, int depth 1195 ) { 1196 if (receiver == StackValue.none()) { 1197 if (receiverParameter != null) { 1198 Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType()); 1199 codegen.generateFromResolvedCall(receiverArgument, receiverType); 1200 StackValue.onStack(receiverType).put(type, v); 1201 } 1202 else { 1203 codegen.generateFromResolvedCall(receiverArgument, type); 1204 } 1205 } 1206 else { 1207 receiver.moveToTopOfStack(type, v, depth); 1208 } 1209 } 1210 } 1211 1212 public abstract static class StackValueWithSimpleReceiver extends StackValue { 1213 1214 protected final boolean isStatic; 1215 1216 public StackValueWithSimpleReceiver(@NotNull Type type, boolean isStatic) { 1217 super(type); 1218 this.isStatic = isStatic; 1219 } 1220 1221 @Override 1222 public void dupReceiver(InstructionAdapter v) { 1223 if (!isStatic) { 1224 v.dup(); 1225 } 1226 } 1227 1228 @Override 1229 public int receiverSize() { 1230 return isStatic ? 0 : 1; 1231 } 1232 } 1233 }