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