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