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