Compare commits

...

10 Commits

Author SHA1 Message Date
Mikhail Bogdanov
c7d00dad52 Rename allowImplicitCast flag to allowNoUpcast 2020-08-04 20:29:44 +02:00
Mikhail Bogdanov
3f7433f7fe Don't checkcast ThisOrOuter if not necessary 2020-08-04 20:29:44 +02:00
Mikhail Bogdanov
a95569d7b4 Add tests for obsolete and closed issues in previous commits
#KT-13747 Obsolete
  #KT-16446 Fixed
  #KT-18939 Fixed
2020-08-04 20:29:44 +02:00
Mikhail Bogdanov
742f19604e Checkcast. Returns 2020-08-04 20:29:44 +02:00
Mikhail Bogdanov
af4e788abd Checkcast. Properly process generic properties 2020-08-04 20:29:44 +02:00
Mikhail Bogdanov
f437fa2d5f Don't cast lambda parameters 2020-08-04 20:29:43 +02:00
Mikhail Bogdanov
8dbe126e60 JVM. Avoid casts on function calls 2020-08-04 20:29:43 +02:00
Mikhail Bogdanov
68f66f559e JVM_IR. Avoid casts on function calls 2020-08-04 20:29:43 +02:00
Mikhail Bogdanov
c488f7ad09 Support ir 2020-08-04 20:29:43 +02:00
Mikhail Bogdanov
60792c2fcf Generate less checkcasts 2020-08-04 08:53:56 +02:00
58 changed files with 1223 additions and 128 deletions

View File

@@ -1038,7 +1038,12 @@ public class AsmUtil {
return new StackValue(stackValue.type, stackValue.kotlinType) {
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
Type innerType = stackValue.type;
KotlinType innerKotlinType = stackValue.kotlinType;
stackValue.put(innerType, innerKotlinType, v);

View File

@@ -48,7 +48,12 @@ abstract class SafeCallFusedWithPrimitiveEqualityBase(
v.mark(endLabel)
}
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
val falseLabel = Label()
val endLabel = Label()

View File

@@ -22,7 +22,12 @@ open class BranchedValue(
val opcode: Int
) : StackValue(Type.BOOLEAN_TYPE) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
val branchJumpLabel = Label()
condJump(branchJumpLabel, v, true)
val endLabel = Label()
@@ -66,7 +71,12 @@ open class BranchedValue(
}
}
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
v.iconst(1)
coerceTo(type, kotlinType, v)
}
@@ -89,7 +99,12 @@ open class BranchedValue(
}
}
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
v.iconst(0)
coerceTo(type, kotlinType, v)
}
@@ -172,7 +187,12 @@ class Invert(val condition: BranchedValue) : BranchedValue(condition, null, Type
class CondJump(val condition: BranchedValue, op: Int) : BranchedValue(condition, null, Type.BOOLEAN_TYPE, op) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
throw UnsupportedOperationException("Use condJump instead")
}

View File

@@ -68,7 +68,7 @@ interface CallGenerator {
}
val value = codegen.gen(argumentExpression)
value.put(parameterType.type, parameterType.kotlinType, v)
value.put(parameterType.type, parameterType.kotlinType, v, false, true)
if (isVarargInvoke) {
v.astore(OBJECT_TYPE)

View File

@@ -152,7 +152,7 @@ public class CallReceiver extends StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, boolean allowNoUpcast) {
StackValue currentExtensionReceiver = extensionReceiver;
boolean hasExtensionReceiver = extensionReceiver != none();
if (extensionReceiver instanceof SafeCall) {
@@ -172,7 +172,8 @@ public class CallReceiver extends StackValue {
hasExtensionReceiver ? type : currentExtensionReceiver.type,
hasExtensionReceiver ? kotlinType : currentExtensionReceiver.kotlinType,
v,
dispatchReceiverType.getSize()
dispatchReceiverType.getSize(),
allowNoUpcast
);
}

View File

@@ -293,6 +293,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
public StackValue putInstanceOnStack(@NotNull ExpressionCodegen codegen, @Nullable StackValue functionReferenceReceiver) {
return StackValue.operation(
functionReferenceTarget != null ? K_FUNCTION : asmType,
classDescriptor.getDefaultType(),
v -> {
if (isConst(closure)) {
v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());

View File

@@ -346,7 +346,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
stackValue = new StackValue(stackValue.type, stackValue.kotlinType) {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
stackValueToWrap.put(functionTypeForWrapper, null, v);
invokeCoroutineMigrationMethod(
@@ -371,10 +372,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public void gen(KtElement expr, Type type, KotlinType kotlinType) {
StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr);
putStackValue(expr, type, kotlinType, value);
putStackValue(expr, type, kotlinType, value, false);
}
private void putStackValue(@Nullable KtElement expr, @NotNull Type type, @Nullable KotlinType kotlinType, @NotNull StackValue value) {
private void putStackValue(
@Nullable KtElement expr,
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull StackValue value,
boolean allowNoUpcast
) {
// for repl store the result of the last line into special field
if (value.type != Type.VOID_TYPE) {
ScriptContext context = getScriptContext();
@@ -390,7 +397,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
value.put(type, kotlinType, v);
value.put(type, kotlinType, v, false, allowNoUpcast);
}
@Nullable
@@ -1663,7 +1670,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
putStackValue(returnedExpression, returnType, returnKotlinType, valueToReturn);
putStackValue(returnedExpression, returnType, returnKotlinType, valueToReturn, true);
Label afterReturnLabel = new Label();
generateFinallyBlocksIfNeeded(returnType, returnKotlinType, afterReturnLabel);
@@ -2474,7 +2481,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
coroutineInstanceValue = new StackValue(CoroutineCodegenUtilKt.EXPERIMENTAL_CONTINUATION_ASM_TYPE) {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
releaseContinuation.put(CoroutineCodegenUtilKt.RELEASE_CONTINUATION_ASM_TYPE, v);
invokeCoroutineMigrationMethod(
@@ -2690,7 +2698,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!isConstructor) { // otherwise already
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
receiver.put(receiver.type, receiver.kotlinType, v);
receiver.put(receiver.type, receiver.kotlinType, v, false, true);
// In regular cases we add an inline marker just before receiver is loaded (to spill the stack before a suspension)
// But in case of safe call things we get the following bytecode:
@@ -4596,7 +4604,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
arguments.get(1).asElement(),
new StackValue(K_PROPERTY_TYPE) {
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
metadataValue.put(type, kotlinType, v);
}
}

View File

@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
@@ -352,7 +353,7 @@ class PropertyReferenceCodegen(
codegen.frameMap.getIndex(
codegen.context.functionDescriptor.valueParameters.last()
),
OBJECT_TYPE, targetKotlinType
OBJECT_TYPE, if (targetKotlinType.isInlineClassType()) targetKotlinType else null
),
v
)

View File

@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
@@ -101,30 +102,50 @@ public abstract class StackValue {
* @param v the visitor used to genClassOrObject the instructions
* @param depth the number of new values put onto the stack
*/
public void moveToTopOfStack(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, int depth) {
put(type, kotlinType, v);
public void moveToTopOfStack(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, int depth, boolean allowNoUpcast) {
put(type, kotlinType, v, false, allowNoUpcast);
}
public void put(@NotNull InstructionAdapter v) {
put(type, null, v, false);
public final void put(@NotNull InstructionAdapter v) {
put(type, null, v, false, false);
}
public void put(@NotNull Type type, @NotNull InstructionAdapter v) {
put(type, null, v, false);
public final void put(@NotNull Type type, @NotNull InstructionAdapter v) {
put(type, null, v, false, false);
}
public void put(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
put(type, kotlinType, v, false);
public final void put(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
put(type, kotlinType, v, false, false);
}
public void put(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, boolean skipReceiver) {
public final void put(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean skipReceiver
) {
put(type, kotlinType, v, skipReceiver, false);
}
public final void put(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean skipReceiver,
boolean allowNoUpcast
) {
if (!skipReceiver) {
putReceiver(v, true);
}
putSelector(type, kotlinType, v);
putSelector(type, kotlinType, v, allowNoUpcast);
}
public abstract void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v);
public abstract void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
);
public boolean isNonStaticAccess(boolean isRead) {
return false;
@@ -525,8 +546,17 @@ public abstract class StackValue {
coerce(this.type, this.kotlinType, toType, toKotlinType, v);
}
protected void coerceFrom(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerce(topOfStackType, topOfStackKotlinType, this.type, this.kotlinType, v);
protected void coerceTo(@NotNull Type toType, @Nullable KotlinType toKotlinType, @NotNull InstructionAdapter v, boolean allowNoUpcast) {
coerce(this.type, this.kotlinType, toType, toKotlinType, v, allowNoUpcast);
}
protected void coerceFrom(
@NotNull Type topOfStackType,
@Nullable KotlinType topOfStackKotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
coerce(topOfStackType, topOfStackKotlinType, this.type, this.kotlinType, v, allowNoUpcast);
}
public static void coerce(
@@ -535,8 +565,27 @@ public abstract class StackValue {
@NotNull Type toType,
@Nullable KotlinType toKotlinType,
@NotNull InstructionAdapter v
) {
coerce(fromType, fromKotlinType, toType, toKotlinType, v, false);
}
public static void coerce(
@NotNull Type fromType,
@Nullable KotlinType fromKotlinType,
@NotNull Type toType,
@Nullable KotlinType toKotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (coerceInlineClasses(fromType, fromKotlinType, toType, toKotlinType, v)) return;
if (allowNoUpcast &&
fromKotlinType != null &&
toKotlinType != null &&
fromType.getSort() == Type.OBJECT &&
toType.getSort() == Type.OBJECT &&
!fromType.equals(OBJECT_TYPE) && //TODO: investigate a bunch of failed coroutines tests
!KotlinBuiltIns.isNothingOrNullableNothing(fromKotlinType)) {
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(fromKotlinType, toKotlinType)) return; //use implicit cast
}
coerce(fromType, toType, v);
}
@@ -994,7 +1043,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
coerceTo(type, kotlinType, v);
}
}
@@ -1017,14 +1071,19 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
v.load(index, this.type);
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, false/*need more investigation*/);
v.store(index, this.type);
}
}
@@ -1049,15 +1108,20 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
v.load(index, this.type);
StackValue.genNonNullAssertForLateinit(v, name.asString());
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, false);
v.store(index, this.type);
PseudoInsnsKt.storeNotNull(v);
}
@@ -1098,7 +1162,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCall(true);
List<? extends ValueArgument> arguments = resolvedCall.getCall().getValueArguments();
assert arguments.size() == 2 : "Resolved call for 'getValue' should have 2 arguments, but was " +
@@ -1142,14 +1211,19 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
coerceTo(type, kotlinType, v);
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void moveToTopOfStack(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, int depth) {
public void moveToTopOfStack(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v, int depth, boolean allowNoUpcast) {
if (depth == 0) {
put(type, kotlinType, v);
put(type, kotlinType, v, allowNoUpcast);
}
else if (depth == 1) {
int size = this.type.getSize();
@@ -1164,7 +1238,7 @@ public abstract class StackValue {
throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack");
}
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
else if (depth == 2) {
int size = this.type.getSize();
@@ -1180,7 +1254,7 @@ public abstract class StackValue {
throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack");
}
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
else {
throw new UnsupportedOperationException("unsupported move-to-top depth " + depth);
@@ -1199,7 +1273,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (value instanceof Integer || value instanceof Byte || value instanceof Short) {
v.iconst(((Number) value).intValue());
}
@@ -1220,7 +1299,7 @@ public abstract class StackValue {
}
if (value != null || AsmUtil.isPrimitive(type)) {
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
}
}
@@ -1235,7 +1314,7 @@ public abstract class StackValue {
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, true);
v.astore(this.type);
}
@@ -1246,10 +1325,11 @@ public abstract class StackValue {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
v.aload(this.type); // assumes array and index are on the stack
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
}
@@ -1265,7 +1345,8 @@ public abstract class StackValue {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
coerceTo(type, kotlinType, v);
}
@@ -1306,7 +1387,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
ArgumentGenerator generator = createArgumentGenerator();
@@ -1452,13 +1538,18 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (getter == null) {
throw new UnsupportedOperationException("no getter specified");
}
CallGenerator callGenerator = getCallGenerator();
callGenerator.genCall(getter, resolvedGetCall, genDefaultMaskIfPresent(callGenerator), codegen);
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
private boolean genDefaultMaskIfPresent(CallGenerator callGenerator) {
@@ -1622,14 +1713,19 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor());
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, true);
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor());
}
@@ -1656,7 +1752,7 @@ public abstract class StackValue {
@NotNull StackValue receiver, @NotNull ExpressionCodegen codegen, @Nullable ResolvedCall resolvedCall,
boolean skipLateinitAssertion, @Nullable KotlinType delegateKotlinType
) {
super(type, descriptor.getType(), isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver, true);
super(type, descriptor.getOriginal().getType(), isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver, true);
this.backingFieldOwner = backingFieldOwner;
this.getter = getter;
this.setter = setter;
@@ -1706,11 +1802,16 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (getter == null) {
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
assert backingFieldOwner != null : "Property should have either a getter or a backingFieldOwner: " + descriptor;
if (inlineConstantIfNeeded(type, kotlinType, v)) return;
if (inlineConstantIfNeeded(type, kotlinType, v, allowNoUpcast)) return;
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
@@ -1723,7 +1824,7 @@ public abstract class StackValue {
genNonNullAssertForLateinit(v, this.descriptor.getName().asString());
}
}
coerceTo(type, kotlinType, v);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
else {
PropertyGetterDescriptor getterDescriptor = descriptor.getGetter();
@@ -1738,7 +1839,7 @@ public abstract class StackValue {
}
Type typeOfValueOnStack = getter.getReturnType();
KotlinType kotlinTypeOfValueOnStack = getterDescriptor.getReturnType();
KotlinType kotlinTypeOfValueOnStack = getterDescriptor.getOriginal().getReturnType();
if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
if (this.type.equals(K_CLASS_TYPE)) {
wrapJavaClassIntoKClass(v);
@@ -1752,7 +1853,7 @@ public abstract class StackValue {
}
}
coerce(typeOfValueOnStack, kotlinTypeOfValueOnStack, type, kotlinType, v);
coerce(typeOfValueOnStack, kotlinTypeOfValueOnStack, type, kotlinType, v, allowNoUpcast);
// For non-private lateinit properties in companion object, the assertion is generated in the public getFoo method
// in the companion and _not_ in the synthetic accessor access$getFoo$cp in the outer class. The reason is that this way,
@@ -1775,19 +1876,29 @@ public abstract class StackValue {
}
}
private boolean inlineConstantIfNeeded(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
private boolean inlineConstantIfNeeded(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (JvmCodegenUtil.isInlinedJavaConstProperty(descriptor)) {
return inlineConstant(type, kotlinType, v);
return inlineConstant(type, kotlinType, v, allowNoUpcast);
}
if (descriptor.isConst() && codegen.getState().getShouldInlineConstVals()) {
return inlineConstant(type, kotlinType, v);
return inlineConstant(type, kotlinType, v, allowNoUpcast);
}
return false;
}
private boolean inlineConstant(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
private boolean inlineConstant(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
assert AsmUtil.isPrimitive(this.type) || AsmTypes.JAVA_STRING_TYPE.equals(this.type) :
"Const property should have primitive or string type: " + descriptor;
assert isStaticPut : "Const property should be static" + descriptor;
@@ -1800,7 +1911,7 @@ public abstract class StackValue {
value = ((Double) value).floatValue();
}
StackValue.constant(value, this.type, this.kotlinType).putSelector(type, kotlinType, v);
StackValue.constant(value, this.type, this.kotlinType).putSelector(type, kotlinType, v, allowNoUpcast);
return true;
}
@@ -1830,7 +1941,7 @@ public abstract class StackValue {
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
if (setter == null) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, true);
assert fieldName != null : "Property should have either a setter or a field name: " + descriptor;
assert backingFieldOwner != null : "Property should have either a setter or a backingFieldOwner: " + descriptor;
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
@@ -1893,7 +2004,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
generator.gen(expression, type, kotlinType);
}
}
@@ -1924,20 +2040,25 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
if (isLateinit) {
StackValue.genNonNullAssertForLateinit(v, name.asString());
}
coerceFrom(refType, null, v);
coerceTo(type, kotlinType, v);
coerceFrom(refType, null, v, true);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, true);
Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(PUTFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
@@ -1989,20 +2110,25 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
Type sharedType = sharedTypeForType(this.type);
Type refType = refType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
if (isLateinit) {
StackValue.genNonNullAssertForLateinit(v, variableName.asString());
}
coerceFrom(refType, null, v);
coerceTo(type, kotlinType, v);
coerceFrom(refType, null, v, false);
coerceTo(type, kotlinType, v, allowNoUpcast);
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
coerceFrom(topOfStackType, topOfStackKotlinType, v);
coerceFrom(topOfStackType, topOfStackKotlinType, v, true);
v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "element", refType(type).getDescriptor());
}
@@ -2027,12 +2153,17 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
StackValue stackValue = codegen.generateThisOrOuter(descriptor, isSuper);
stackValue.put(
coerceType ? type : stackValue.type,
coerceType ? kotlinType : stackValue.kotlinType,
v
v, false, allowNoUpcast
);
}
}
@@ -2048,7 +2179,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
if (!type.equals(Type.VOID_TYPE)) {
v.load(index, Type.INT_TYPE);
coerceTo(type, kotlinType, v);
@@ -2068,7 +2204,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
v.iinc(index, increment);
if (!type.equals(Type.VOID_TYPE)) {
v.load(index, Type.INT_TYPE);
@@ -2095,13 +2236,18 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
value = StackValue.complexReceiver(value, true, false, true);
value.put(this.type, this.kotlinType, v);
value.store(codegen.invokeFunction(resolvedCall, StackValue.onStack(this.type, this.kotlinType)), v, true);
value.put(this.type, this.kotlinType, v, true);
value.put(this.type, this.kotlinType, v, true, false);
coerceTo(type, kotlinType, v);
}
}
@@ -2219,7 +2365,8 @@ public abstract class StackValue {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
boolean wasPut = false;
StackValue receiver = originalValueWithReceiver.receiver;
@@ -2252,10 +2399,11 @@ public abstract class StackValue {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
for (StackValue instruction : instructions) {
instruction.put(instruction.type, instruction.kotlinType, v);
instruction.put(instruction.type, instruction.kotlinType, v, false, allowNoUpcast);
}
}
}
@@ -2279,9 +2427,10 @@ public abstract class StackValue {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
originalValue.putSelector(type, kotlinType, v);
originalValue.putSelector(type, kotlinType, v, allowNoUpcast);
}
@Override
@@ -2338,7 +2487,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
receiver.put(this.type, this.kotlinType, v);
if (ifNull != null) {
//not a primitive
@@ -2359,7 +2513,12 @@ public abstract class StackValue {
}
@Override
public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
public void putSelector(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull InstructionAdapter v,
boolean allowNoUpcast
) {
Label end = new Label();
v.goTo(end);

View File

@@ -27,8 +27,13 @@ class CoercionValue(
private val underlyingKotlinType: KotlinType? // type of the underlying parameter for inline class
) : StackValue(castType, castKotlinType, value.canHaveSideEffects()) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
value.putSelector(value.type, value.kotlinType, v)
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
value.putSelector(value.type, value.kotlinType, v, allowNoUpcast)
// consider the following example:
@@ -63,8 +68,13 @@ class StackValueWithLeaveTask(
stackValue.putReceiver(v, isRead)
}
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
stackValue.putSelector(type, kotlinType, v)
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
stackValue.putSelector(type, kotlinType, v, allowNoUpcast)
leaveTasks(stackValue)
}
}
@@ -75,9 +85,14 @@ open class OperationStackValue(
val lambda: (v: InstructionAdapter) -> Unit
) : StackValue(resultType, resultKotlinType) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
lambda(v)
coerceTo(type, kotlinType, v)
coerceTo(type, kotlinType, v, allowNoUpcast)
}
}

View File

@@ -30,7 +30,12 @@ class CallBasedInExpressionGenerator(
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowNoUpcast: Boolean
) {
invokeFunction(v)
coerceTo(type, kotlinType, v)
}

View File

@@ -3410,6 +3410,41 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/generic.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -167,11 +167,11 @@ class ExpressionCodegen(
fun markLineNumber(element: IrElement) = element.markLineNumber(true)
// TODO remove
fun gen(expression: IrExpression, type: Type, irType: IrType, data: BlockInfo): StackValue {
fun gen(expression: IrExpression, type: Type, irType: IrType, data: BlockInfo, allowImplicitCast: Boolean = false): StackValue {
if (expression.attributeOwnerId === context.fakeContinuation) {
addFakeContinuationMarker(mv)
} else {
expression.accept(this, data).materializeAt(type, irType)
expression.accept(this, data).materializeAt(type, irType, allowImplicitCast)
}
return StackValue.onStack(type, irType.toKotlinType())
}
@@ -424,7 +424,8 @@ class ExpressionCodegen(
expression.dispatchReceiver?.let { receiver ->
val type = if ((expression as? IrCall)?.superQualifierSymbol != null) receiver.asmType else callable.owner
callGenerator.genValueAndPut(callee.dispatchReceiverParameter!!, receiver, type, this, data)
// Type mapper could use more specific type for invoke instruction and it will cause inconsistency between irType and asmType below (see kt10822.kt)
callGenerator.genValueAndPut(callee.dispatchReceiverParameter!!, receiver, type, this, data, false)
}
expression.extensionReceiver?.let { receiver ->
@@ -484,7 +485,7 @@ class ExpressionCodegen(
MaterialValue(this, AsmTypes.K_CLASS_ARRAY_TYPE, expression.type)
}
else ->
MaterialValue(this, callable.asmMethod.returnType, callee.returnType)
MaterialValue(this, callable.asmMethod.returnType, callable.actualReturnType)
}
}
@@ -560,15 +561,7 @@ class ExpressionCodegen(
return if (expression is IrSetField) {
val value = expression.value.accept(this, data)
// We only initialize enum entries with a subtype of `fieldType` and can avoid the CHECKCAST.
// This is important for some tools which analyze bytecode for enum classes by looking at the
// initializer of the $VALUES field.
if (callee.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
value.materialize()
} else {
value.materializeAt(fieldType, callee.type)
}
value.materializeAt(fieldType, callee.type, true)
expression.markLineNumber(startOffset = true)
when {
@@ -750,7 +743,7 @@ class ExpressionCodegen(
val returnType = if (owner == irFunction) signature.returnType else methodSignatureMapper.mapReturnType(owner)
val afterReturnLabel = Label()
expression.value.accept(this, data).materializeAt(returnType, owner.returnType)
expression.value.accept(this, data).materializeAt(returnType, owner.returnType, true)
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
expression.markLineNumber(startOffset = true)
if (isNonLocalReturn) {
@@ -1007,11 +1000,11 @@ class ExpressionCodegen(
mv.mark(tryCatchBlockEnd)
// TODO: generate a common `finally` for try & catch blocks here? Right now this breaks the inliner.
return object : PromisedValue(this, tryAsmType, aTry.type) {
override fun materializeAt(target: Type, irTarget: IrType) {
override fun materializeAt(target: Type, irTarget: IrType, allowNoUpcast: Boolean) {
if (savedValue != null) {
mv.load(savedValue, tryAsmType)
frameMap.leaveTemp(tryAsmType)
super.materializeAt(target, irTarget)
super.materializeAt(target, irTarget, allowNoUpcast)
} else {
unitValue.materializeAt(target, irTarget)
}

View File

@@ -37,9 +37,10 @@ interface IrCallGenerator {
argumentExpression: IrExpression,
parameterType: Type,
codegen: ExpressionCodegen,
blockInfo: BlockInfo
blockInfo: BlockInfo,
allowImplicitCast: Boolean = true
) {
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo, allowImplicitCast)
}
object DefaultCallGenerator : IrCallGenerator

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
@@ -15,7 +16,8 @@ class IrCallableMethod(
val owner: Type,
val invokeOpcode: Int,
val signature: JvmMethodSignature,
val isInterfaceMethod: Boolean
val isInterfaceMethod: Boolean,
val actualReturnType: IrType
) {
val asmMethod: Method = signature.asmMethod

View File

@@ -68,14 +68,15 @@ class IrInlineCodegen(
argumentExpression: IrExpression,
parameterType: Type,
codegen: ExpressionCodegen,
blockInfo: BlockInfo
blockInfo: BlockInfo,
allowImplicitCast: Boolean
) {
if (codegen.irFunction.isInvokeSuspendOfContinuation()) {
// In order to support java interop of inline suspend functions, we generate continuations for these inline suspend functions.
// These functions should behave as ordinary suspend functions, i.e. we should not inline the content of the inline function
// into continuation.
// Thus, we should put its arguments to stack.
super.genValueAndPut(irValueParameter, argumentExpression, parameterType, codegen, blockInfo)
super.genValueAndPut(irValueParameter, argumentExpression, parameterType, codegen, blockInfo, allowImplicitCast)
}
val isInlineParameter = irValueParameter.isInlineParameter()

View File

@@ -308,7 +308,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
if (callee !is IrSimpleFunction) {
check(callee is IrConstructor) { "Function must be a simple function or a constructor: ${callee.render()}" }
return IrCallableMethod(owner, Opcodes.INVOKESPECIAL, mapSignatureSkipGeneric(callee), false)
return IrCallableMethod(owner, Opcodes.INVOKESPECIAL, mapSignatureSkipGeneric(callee), false, callee.returnType)
}
val isInterface = calleeParent.isJvmInterface
@@ -326,7 +326,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
val signature = mapOverriddenSpecialBuiltinIfNeeded(caller, declaration, isSuperCall)
?: mapSignatureSkipGeneric(declaration)
return IrCallableMethod(owner, invokeOpcode, signature, isInterface)
return IrCallableMethod(owner, invokeOpcode, signature, isInterface, declaration.returnType)
}
// TODO: get rid of this (probably via some special lowering)

View File

@@ -11,8 +11,10 @@ import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
@@ -21,9 +23,10 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
// A value that may not have been fully constructed yet. The ability to "roll back" code generation
// is useful for certain optimizations.
abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val irType: IrType) {
// If this value is immaterial, construct an object on the top of the stack. This
// must always be done before generating other values or emitting raw bytecode.
open fun materializeAt(target: Type, irTarget: IrType) {
open fun materializeAt(target: Type, irTarget: IrType, allowNoUpcast: Boolean = false) {
val erasedSourceType = irType.eraseTypeParameters()
val erasedTargetType = irTarget.eraseTypeParameters()
val isFromTypeInlineClass = erasedSourceType.classOrNull!!.owner.isInline
@@ -54,6 +57,15 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
}
if (type != target) {
if (allowNoUpcast && type.sort == Type.OBJECT && target.sort == Type.OBJECT &&
type != AsmTypes.VOID_WRAPPER_TYPE &&
type != AsmTypes.OBJECT_TYPE &&
//TODO: Missed type parameters in coroutines types
irType.classifierOrNull?.let { (it.owner as? IrClass)?.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA } != true &&
irType.isSubtypeOf(irTarget, codegen.context.irBuiltIns)
) {
return
}
StackValue.coerce(type, target, mv)
}
}
@@ -85,7 +97,7 @@ abstract class BooleanValue(codegen: ExpressionCodegen) :
abstract fun jumpIfFalse(target: Label)
abstract fun jumpIfTrue(target: Label)
override fun materializeAt(target: Type, irTarget: IrType) {
override fun materializeAt(target: Type, irTarget: IrType, allowNoUpcast: Boolean) {
val const0 = Label()
val end = Label()
jumpIfFalse(const0)
@@ -103,7 +115,7 @@ abstract class BooleanValue(codegen: ExpressionCodegen) :
class BooleanConstant(codegen: ExpressionCodegen, val value: Boolean) : BooleanValue(codegen) {
override fun jumpIfFalse(target: Label) = if (value) Unit else mv.goTo(target)
override fun jumpIfTrue(target: Label) = if (value) mv.goTo(target) else Unit
override fun materializeAt(target: Type, irTarget: IrType) {
override fun materializeAt(target: Type, irTarget: IrType, allowNoUpcast: Boolean) {
mv.iconst(if (value) 1 else 0)
if (Type.BOOLEAN_TYPE != target) {
StackValue.coerce(Type.BOOLEAN_TYPE, target, mv)

View File

@@ -29,7 +29,7 @@ object ArraySet : IntrinsicMethod() {
val elementType = AsmUtil.correctElementType(receiver.type)
val elementIrType = receiver.irType.getArrayElementType(codegen.context.irBuiltIns)
expression.getValueArgument(0)!!.accept(codegen, data).materializeAt(Type.INT_TYPE, codegen.context.irBuiltIns.intType)
expression.getValueArgument(1)!!.accept(codegen, data).materializeAt(elementType, elementIrType)
expression.getValueArgument(1)!!.accept(codegen, data).materializeAt(elementType, elementIrType, true)
codegen.mv.astore(elementType)
return codegen.unitValue
}

View File

@@ -29,9 +29,9 @@ object UnsafeCoerce : IntrinsicMethod() {
val arg = expression.getValueArgument(0)!!
val result = arg.accept(codegen, data)
return object : PromisedValue(codegen, toType, to) {
override fun materializeAt(target: Type, irTarget: IrType) {
override fun materializeAt(target: Type, irTarget: IrType, allowNoUpcast: Boolean) {
result.materializeAt(fromType, from)
super.materializeAt(target, irTarget)
super.materializeAt(target, irTarget, allowNoUpcast)
}
override fun discard() {

View File

@@ -0,0 +1,28 @@
fun cond() = true
var result = ""
open class Base
open class Derived : Base() {
fun test(base: Base, base2: Base) {
result += "O"
}
}
open class Child1 : Derived()
open class Child2 : Derived()
fun Derived.test2(base: Base, base2: Base) {
result += "K"
}
fun test(child1: Child1?,child2: Child2) {
(child1 ?: child2).test(child1 ?: child2, child1 ?: child2)
(child1 ?: child2).test2(child1 ?: child2, child1 ?: child2)
}
fun box(): String {
test(Child1(), Child2())
return result
}

View File

@@ -0,0 +1,26 @@
fun cond() = true
var result = ""
open class Base
open class Derived : Base() {
fun test(base: Base, base2: Base) {
result += "O"
}
}
open class Child1 : Derived()
open class Child2 : Derived()
fun Derived.test2(base: Base, base2: Base) {
result += "K"
}
fun box(): String {
(if (cond()) Child1() else Child2()).test(if (cond()) Child1() else Child2(), if (cond()) Child1() else Child2())
(if (cond()) Child1() else Child2()).test2(if (cond()) Child1() else Child2(), if (cond()) Child1() else Child2())
return result
}

View File

@@ -0,0 +1,26 @@
fun cond() = true
var result = ""
open class Base
open class Derived : Base() {
fun test(base: Base, base2: Base) {
result += "O"
}
}
open class Child1 : Derived()
open class Child2 : Derived()
fun Derived.test2(base: Base, base2: Base) {
result += "K"
}
fun box(): String {
(if (cond()) Child1() else return "fail 0").test(if (cond()) Child1() else return "fail 1", if (cond()) Child1() else return "fail 2")
(if (cond()) Child1() else return "fail 00").test2(if (cond()) Child1() else return "fail 3", if (cond()) Child1() else return "fail 4")
return result
}

View File

@@ -0,0 +1,24 @@
var result = ""
open class Base
open class Derived : Base() {
fun test(base: Base, base2: Base) {
result += "O"
}
}
open class Child1 : Derived()
open class Child2 : Derived()
fun Derived.testExt(base: Base, base2: Base) {
result += "K"
}
fun box(): String {
Child2().test(try { Child1() } finally { Child2()} , try { Child1() } finally { Child2() } )
Child2().testExt(try { Child1() } finally { Child2() } , try { Child1() } finally { Child2() } )
return result
}

View File

@@ -0,0 +1,16 @@
open class A {
fun foo(): String {
return "OK"
}
}
open class B : A()
fun<T : A> test(init: () -> T): T = init()
fun call(b: B ) = b
fun box(): String {
return call(test { B() }).foo()
}

View File

@@ -0,0 +1,20 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
open class TransformationInfo
class MyTransformationInfo(val value: String) : TransformationInfo()
abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val transformationInfo: T)
class MyTransformer(info: MyTransformationInfo): ObjectTransformer<MyTransformationInfo>(info) {
fun test(): String {
return test(transformationInfo)
}
fun test(info: MyTransformationInfo): String {
return info.value
}
}
fun box(): String {
return MyTransformer(MyTransformationInfo("OK")).test()
}

View File

@@ -0,0 +1,27 @@
interface FirDeclaration
interface FirSymbolOwner<E> where E : FirSymbolOwner<E>, E : FirDeclaration
abstract class AbstractFirBasedSymbol<E> : FirSymbolOwner<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
lateinit var fir: E
}
open class FirClassSymbol<E : FirClass<E>>: AbstractFirBasedSymbol<E>()
open class FirClass<F : FirClass<F>> : FirSymbolOwner<F>, FirDeclaration
open class FirRegularClass : FirClass<FirRegularClass>()
open class ClassFirBasedSymbol : AbstractFirBasedSymbol<FirRegularClass>()
fun test(symbol: ClassFirBasedSymbol) {
test(symbol.fir)
}
fun test(p: FirRegularClass) {
}
fun box(): String {
val classFirBasedSymbol = ClassFirBasedSymbol()
classFirBasedSymbol.fir = FirRegularClass()
test(classFirBasedSymbol)
return "OK"
}

View File

@@ -0,0 +1,30 @@
// FILE: 1.kt
package test
open class Base
open class Derived : Base()
open class Derived2 : Base()
inline fun test(s: () -> Base): Base {
return s()
}
fun cond() = true
// FILE: 2.kt
import test.*
fun base(base: Base) {
}
fun box(): String {
val value = if (cond())
test { Derived() }
else test { Derived2() }
base(value)
return "OK"
}

View File

@@ -0,0 +1,33 @@
open class SuperBase
open class Base : SuperBase() {
fun test(base: Base) {
testSuper(base)
}
fun testSuper(base: SuperBase) {
}
}
open class Derived : Base()
fun Base.testExt(base: Base) {
testExtSuper(base)
}
fun SuperBase.testExtSuper(base: SuperBase) {
}
fun test() {
Derived().test(Derived())
Derived().testExt(Derived())
}
// JVM_TEMPLATES:
// 0 CHECKCAST
// JVM_IR_TEMPLATES:
// 0 CHECKCAST

View File

@@ -0,0 +1,23 @@
fun cond() = true
open class Base
open class Derived : Base() {
fun test(base: Base, base2: Base) {
}
}
open class Child1 : Derived()
open class Child2 : Derived()
fun Derived.test2(base: Base, base2: Base) {
}
fun test() {
(if (cond()) Child1() else Child2()).test(if (cond()) Child1() else Child2(), if (cond()) Child1() else Child2())
(if (cond()) Child1() else Child2()).test2(if (cond()) Child1() else Child2(), if (cond()) Child1() else Child2())
}
// 12 CHECKCAST
// 12 CHECKCAST Derived

View File

@@ -0,0 +1,35 @@
open class SuperBase
open class Base : SuperBase()
open class Derived : Base()
open class BaseGeneric<T: SuperBase> {
fun test(p: T) : T = p
}
open class DerivedGeneric : BaseGeneric<Derived>()
@JvmField
var property: Base = Base()
fun test(array: Array<Base>) {
val factory = DerivedGeneric();
property = factory.test(Derived())
array[0] = factory.test(Derived())
var captured = Base();
{
captured = factory.test(Derived())
}()
}
// 0 CHECKCAST SuperBase
// JVM_TEMPLATES:
// 4 CHECKCAST
// 1 CHECKCAST kotlin/jvm/functions/Function0
// 3 CHECKCAST Base
// JVM_IR_TEMPLATES:
// 2 CHECKCAST
// 2 CHECKCAST Base

View File

@@ -0,0 +1,3 @@
val test : Collection<String> = ArrayList()
// 0 CHECKCAST

View File

@@ -0,0 +1,8 @@
private fun test(list: List<String>) {}
fun main(args: Array<String>) {
val arrayList = ArrayList<String>()
test(arrayList)
}
// 0 CHECKCAST

View File

@@ -0,0 +1,11 @@
fun foo(y: Y) {}
open class Y
class Z : Y() {
fun bar() {
foo(this)
}
}
// 0 CHECKCAST

View File

@@ -0,0 +1,17 @@
fun test(s: () -> Unit) {
}
fun test() {
test { } //static
var captured: Any = "123"
test {
captured
} //non-static
}
// JVM_TEMPLATES:
// 0 CHECKCAST
// there is a problem with subtype cheking for lambda class against FunctionX<...>
// JVM_IR_TEMPLATES:
// 2 CHECKCAST

View File

@@ -0,0 +1,8 @@
open class Base
open class Derived : Base()
fun test() : Base {
return Derived()
}
// 0 CHECKCAST

View File

@@ -0,0 +1,22 @@
open class Base
open class Derived : Base()
@JvmField
var property: Base = Base()
fun test(array: Array<Base>) {
property = Derived()
array[0] = Derived()
var captured = Base();
{
captured = Derived()
}()
}
// JVM_TEMPLATES:
// 1 CHECKCAST
// 1 CHECKCAST kotlin/jvm/functions/Function0
// JVM_IR_TEMPLATES:
// 0 CHECKCAST

View File

@@ -0,0 +1,28 @@
open class Base
open class Derived : Base()
@JvmField
var property: Base = Base()
fun test(array: Array<Base>) {
property = Derived() as Derived
property = Derived() as Base
array[0] = Derived() as Derived
array[0] = Derived() as Base
var captured = Base() as Base;
{
captured = Derived() as Derived
captured = Derived() as Base
}()
}
// JVM_TEMPLATES:
// 4 CHECKCAST
// 1 CHECKCAST kotlin/jvm/functions/Function0
// This checkcast should not be generated
// 3 CHECKCAST Base
// JVM_IR_TEMPLATES:
// 0 CHECKCAST

View File

@@ -0,0 +1,29 @@
interface A
open class Base
open class Derived : Base()
open class Derived2 : Base()
fun cond(): Boolean = true
@JvmField
var property: Base = Base()
fun test(array: Array<Base>) {
property = if (cond()) Derived() else Derived2()
array[0] = if (cond()) Derived() else Derived2()
var captured = Base();
{
captured = if (cond()) Derived() else Derived2()
}()
}
// JVM_TEMPLATES:
// 7 CHECKCAST
// 1 CHECKCAST kotlin/jvm/functions/Function0
// 6 CHECKCAST Base
// JVM_IR_TEMPLATES:
// 6 CHECKCAST
// 6 CHECKCAST Base

View File

@@ -0,0 +1,5 @@
fun foo(): Array<String> {
return emptyArray()
}
// 0 CHECKCAST

View File

@@ -3430,6 +3430,41 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/generic.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -2698,6 +2698,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -865,6 +865,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/checkcast"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("kt13747.kt")
public void testKt13747() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt13747.kt");
}
@TestMetadata("kt14811.kt")
public void testKt14811() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt14811.kt");
@@ -884,6 +889,74 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
public void testKt22714() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt22714.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/checkcast/implicit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Implicit extends AbstractBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInImplicit() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/checkcast/implicit"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/functionCall.kt");
}
@TestMetadata("functionCallWithExplicitCastOnMerge.kt")
public void testFunctionCallWithExplicitCastOnMerge() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/functionCallWithExplicitCastOnMerge.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/generic.kt");
}
@TestMetadata("kt16446.kt")
public void testKt16446() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt16446.kt");
}
@TestMetadata("kt18939.kt")
public void testKt18939() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt18939.kt");
}
@TestMetadata("kt21473.kt")
public void testKt21473() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt21473.kt");
}
@TestMetadata("lambdaAsParameter.kt")
public void testLambdaAsParameter() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/lambdaAsParameter.kt");
}
@TestMetadata("return.kt")
public void testReturn() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/return.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simple.kt");
}
@TestMetadata("simpleExplicitCast.kt")
public void testSimpleExplicitCast() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simpleExplicitCast.kt");
}
@TestMetadata("simpleWithExplicitCastOnMerge.kt")
public void testSimpleWithExplicitCastOnMerge() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simpleWithExplicitCastOnMerge.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/coercionToUnitOptimization")

View File

@@ -2698,6 +2698,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -539,6 +539,19 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
public void testNewSchemeWithJvmDefault() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt");
}
@TestMetadata("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/.idea")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class _idea extends AbstractCompileKotlinAgainstKotlinTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentIn_idea() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/.idea"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
}
}
}

View File

@@ -3430,6 +3430,41 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/generic.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -3410,6 +3410,41 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/generic.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -2698,6 +2698,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -865,6 +865,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/checkcast"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("kt13747.kt")
public void testKt13747() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt13747.kt");
}
@TestMetadata("kt14811.kt")
public void testKt14811() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt14811.kt");
@@ -884,6 +889,74 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
public void testKt22714() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/kt22714.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/checkcast/implicit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Implicit extends AbstractIrBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInImplicit() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/checkcast/implicit"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/functionCall.kt");
}
@TestMetadata("functionCallWithExplicitCastOnMerge.kt")
public void testFunctionCallWithExplicitCastOnMerge() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/functionCallWithExplicitCastOnMerge.kt");
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/generic.kt");
}
@TestMetadata("kt16446.kt")
public void testKt16446() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt16446.kt");
}
@TestMetadata("kt18939.kt")
public void testKt18939() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt18939.kt");
}
@TestMetadata("kt21473.kt")
public void testKt21473() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/kt21473.kt");
}
@TestMetadata("lambdaAsParameter.kt")
public void testLambdaAsParameter() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/lambdaAsParameter.kt");
}
@TestMetadata("return.kt")
public void testReturn() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/return.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simple.kt");
}
@TestMetadata("simpleExplicitCast.kt")
public void testSimpleExplicitCast() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simpleExplicitCast.kt");
}
@TestMetadata("simpleWithExplicitCastOnMerge.kt")
public void testSimpleWithExplicitCastOnMerge() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/checkcast/implicit/simpleWithExplicitCastOnMerge.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/coercionToUnitOptimization")

View File

@@ -2698,6 +2698,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -534,6 +534,19 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
public void testNewSchemeWithJvmDefault() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/newSchemeWithJvmDefault.kt");
}
@TestMetadata("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/.idea")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class _idea extends AbstractIrCompileKotlinAgainstKotlinTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentIn_idea() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/compileKotlinAgainstKotlin/jvm8/defaults/interop/.idea"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
}
}
}

View File

@@ -2735,6 +2735,36 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -2448,6 +2448,11 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -2735,6 +2735,36 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -2448,6 +2448,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -2735,6 +2735,36 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/checkcastOptimization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("functionCallWithElvis.kt")
public void testFunctionCallWithElvis() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithElvis.kt");
}
@TestMetadata("functionCallWithIf.kt")
public void testFunctionCallWithIf() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithIf.kt");
}
@TestMetadata("functionCallWithReturn.kt")
public void testFunctionCallWithReturn() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithReturn.kt");
}
@TestMetadata("functionCallWithTry.kt")
public void testFunctionCallWithTry() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/functionCallWithTry.kt");
}
@TestMetadata("genereicParamDowncast.kt")
public void testGenereicParamDowncast() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genereicParamDowncast.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/genericProperty.kt");
}
@TestMetadata("kt19128.kt")
public void testKt19128() throws Exception {
runTest("compiler/testData/codegen/box/checkcastOptimization/kt19128.kt");

View File

@@ -2448,6 +2448,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/optimizations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/checkcast.kt");
}
@TestMetadata("kt20844.kt")
public void testKt20844() throws Exception {
runTest("compiler/testData/codegen/boxInline/optimizations/kt20844.kt");

View File

@@ -36,7 +36,12 @@ class ResourcePropertyStackValue(
assert(containerOptions.containerType != AndroidContainerType.UNKNOWN)
}
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
override fun putSelector(
type: Type,
kotlinType: KotlinType?,
v: InstructionAdapter,
allowImplicitCast: Boolean
) {
val returnTypeString = typeMapper.mapType(resource.type.lowerIfFlexible()).className
if (AndroidConst.FRAGMENT_FQNAME == returnTypeString || AndroidConst.SUPPORT_FRAGMENT_FQNAME == returnTypeString || AndroidConst.ANDROIDX_SUPPORT_FRAGMENT_FQNAME == returnTypeString) {
return putSelectorForFragment(v)