diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index b4238b68f19..c1f0cf909bf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -41,6 +41,8 @@ import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsPackage; import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; +import org.jetbrains.kotlin.codegen.intrinsics.CheckCast; +import org.jetbrains.kotlin.codegen.intrinsics.InstanceOf; import org.jetbrains.kotlin.codegen.when.SwitchCodegen; import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.descriptors.*; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/CheckCast.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/CheckCast.kt index 4f555aa1c60..8f969d7dd94 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/CheckCast.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/CheckCast.kt @@ -40,17 +40,6 @@ object CheckCast { "kotlin.MutableMap.MutableEntry" to "asMutableMapEntry" ) - private val SAFE_CHECKCAST_METHOD_NAME = hashMapOf( - "kotlin.MutableIterator" to "safeAsMutableIterator", - "kotlin.MutableIterable" to "safeAsMutableIterable", - "kotlin.MutableCollection" to "safeAsMutableCollection", - "kotlin.MutableList" to "safeAsMutableList", - "kotlin.MutableListIterator" to "safeAsMutableListIterator", - "kotlin.MutableSet" to "safeAsMutableSet", - "kotlin.MutableMap" to "safeAsMutableMap", - "kotlin.MutableMap.MutableEntry" to "safeAsMutableMapEntry" - ) - public @JvmStatic fun checkcast(v: InstructionAdapter, jetType: JetType, boxedAsmType: Type, safe: Boolean) { val intrinsicMethodName = getCheckcastIntrinsicMethodName(jetType, safe) if (intrinsicMethodName == null) { @@ -76,9 +65,10 @@ object CheckCast { } private fun getCheckcastIntrinsicMethodName(jetType: JetType, safe: Boolean): String? { + if (safe) return null val classDescriptor = TypeUtils.getClassDescriptor(jetType) ?: return null val classFqName = DescriptorUtils.getFqName(classDescriptor).asString() - return if (safe) SAFE_CHECKCAST_METHOD_NAME[classFqName] else CHECKCAST_METHOD_NAME[classFqName] + return CHECKCAST_METHOD_NAME[classFqName] } private fun getCheckcastIntrinsicMethodSignature(asmType: Type): String = diff --git a/compiler/testData/codegen/bytecodeText/inline/reifiedSafeAsWithMutable.kt b/compiler/testData/codegen/bytecodeText/inline/reifiedSafeAsWithMutable.kt new file mode 100644 index 00000000000..6e3c1429cb6 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inline/reifiedSafeAsWithMutable.kt @@ -0,0 +1,17 @@ +// For mutable collections and related types (e.g., MutableList, MutableListIterator) +// 'as?' should be generated as a single 'safeAs...' intrinsic call +// without instanceof or 'is...'. + +inline fun safeAs(x: Any) { + x as? T +} + +fun test() { + val x: Any = arrayListOf("abc", "def") + safeAs>(x) +} + +// 0 INSTANCEOF java/util/List +// 1 INVOKESTATIC kotlin/jvm/internal/TypeIntrinsics\.isMutableList +// 0 INVOKESTATIC kotlin/jvm/internal/TypeIntrinsics\.safeAsMutableList +// 1 CHECKCAST java/util/List \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/safeAsWithMutable.kt b/compiler/testData/codegen/bytecodeText/safeAsWithMutable.kt new file mode 100644 index 00000000000..38bcb02fc2d --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/safeAsWithMutable.kt @@ -0,0 +1,13 @@ +// For mutable collections and related types (e.g., MutableList, MutableListIterator) +// 'as?' should be generated as a single 'safeAs...' intrinsic call +// without instanceof or 'is...'. + +fun test() { + val x: Any = arrayListOf("abc", "def") + x as? MutableList<*> +} + +// 0 INSTANCEOF +// 1 INVOKESTATIC kotlin/jvm/internal/TypeIntrinsics\.isMutableList +// 0 INVOKESTATIC kotlin/jvm/internal/TypeIntrinsics\.asMutableList +// 1 CHECKCAST java/util/List \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index f2f19127ed1..563d45b9888 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -239,6 +239,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("safeAsWithMutable.kt") + public void testSafeAsWithMutable() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/safeAsWithMutable.kt"); + doTest(fileName); + } + @TestMetadata("topLevelFunWithDefaultArgs.kt") public void testTopLevelFunWithDefaultArgs() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/topLevelFunWithDefaultArgs.kt"); @@ -529,6 +535,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("reifiedSafeAsWithMutable.kt") + public void testReifiedSafeAsWithMutable() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/reifiedSafeAsWithMutable.kt"); + doTest(fileName); + } + @TestMetadata("removedFinallyMarkers.kt") public void testRemovedFinallyMarkers() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt"); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/TypeIntrinsics.java b/core/runtime.jvm/src/kotlin/jvm/internal/TypeIntrinsics.java index 76a8ef28a52..de0f2f9e505 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/TypeIntrinsics.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/TypeIntrinsics.java @@ -51,20 +51,6 @@ public class TypeIntrinsics { return result; } - public static Iterator safeAsMutableIterator(Object obj) { - Iterator result; - try { - result = (Iterator) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableIterator)) { - return null; - } - return result; - } - public static boolean isMutableListIterator(Object obj) { return (obj instanceof ListIterator) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableListIterator)); @@ -84,20 +70,6 @@ public class TypeIntrinsics { return result; } - public static ListIterator safeAsMutableListIterator(Object obj) { - ListIterator result; - try { - result = (ListIterator) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableListIterator)) { - return null; - } - return result; - } - public static boolean isMutableIterable(Object obj) { return (obj instanceof Iterable) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableIterable)); @@ -117,20 +89,6 @@ public class TypeIntrinsics { return result; } - public static Iterable safeAsMutableIterable(Object obj) { - Iterable result; - try { - result = (Iterable) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableIterable)) { - return null; - } - return result; - } - public static boolean isMutableCollection(Object obj) { return (obj instanceof Collection) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableCollection)); @@ -150,20 +108,6 @@ public class TypeIntrinsics { return result; } - public static Collection safeAsMutableCollection(Object obj) { - Collection result; - try { - result = (Collection) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableCollection)) { - return null; - } - return result; - } - public static boolean isMutableList(Object obj) { return (obj instanceof List) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableList)); @@ -183,20 +127,6 @@ public class TypeIntrinsics { return result; } - public static List safeAsMutableList(Object obj) { - List result; - try { - result = (List) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableList)) { - return null; - } - return result; - } - public static boolean isMutableSet(Object obj) { return (obj instanceof Set) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableSet)); @@ -216,20 +146,6 @@ public class TypeIntrinsics { return result; } - public static Set safeAsMutableSet(Object obj) { - Set result; - try { - result = (Set) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableSet)) { - return null; - } - return result; - } - public static boolean isMutableMap(Object obj) { return (obj instanceof Map) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableMap)); @@ -249,20 +165,6 @@ public class TypeIntrinsics { return result; } - public static Map safeAsMutableMap(Object obj) { - Map result; - try { - result = (Map) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableMap)) { - return null; - } - return result; - } - public static boolean isMutableMapEntry(Object obj) { return (obj instanceof Map.Entry) && (!(obj instanceof KMappedMarker) || (obj instanceof KMutableMap.Entry)); @@ -281,19 +183,4 @@ public class TypeIntrinsics { } return result; } - - public static Map.Entry safeAsMutableMapEntry(Object obj) { - Map.Entry result; - try { - result = (Map.Entry) obj; - } - catch (ClassCastException e) { - return null; - } - if ((obj instanceof KMappedMarker) && !(obj instanceof KMutableMap.Entry)) { - return null; - } - return result; - } - }