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