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