Remove unsafe cast function usages from JVM backend modules

This commit is contained in:
Alexander Udalov
2022-11-01 13:56:02 +01:00
committed by Space Team
parent 2cd16f055a
commit 1418423423
34 changed files with 93 additions and 129 deletions
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -159,13 +158,13 @@ fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, cl
}
fun rewriteAssertionsDisabledFieldInitialization(methodNode: MethodNode, className: String) {
InsnSequence(methodNode.instructions).firstOrNull {
val node = InsnSequence(methodNode.instructions).firstOrNull {
it is FieldInsnNode && it.opcode == Opcodes.PUTSTATIC && it.name == ASSERTIONS_DISABLED_FIELD_NAME
}?.findPreviousOrNull {
it is MethodInsnNode && it.opcode == Opcodes.INVOKEVIRTUAL
&& it.owner == "java/lang/Class" && it.name == "desiredAssertionStatus" && it.desc == "()Z"
}?.previous?.safeAs<LdcInsnNode>()?.cst =
Type.getObjectType(className)
}?.previous
(node as? LdcInsnNode)?.cst = Type.getObjectType(className)
}
private fun <D : FunctionDescriptor> ResolvedCall<D>.replaceAssertWithAssertInner(): ResolvedCall<D> {
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
@@ -73,8 +72,9 @@ private class UnitSourceInterpreter(private val localVariables: Set<Int>) : Basi
// Map from unit values to ASTORE/POP use-sites.
val unitUsageInformation = mutableMapOf<AbstractInsnNode, MutableSet<AbstractInsnNode>>()
private fun markUnspillable(value: BasicValue?) =
value?.safeAs<UnitValue>()?.let { unspillableUnitValues += it.insns }
private fun markUnspillable(value: BasicValue?) {
(value as? UnitValue)?.let { unspillableUnitValues += it.insns }
}
private fun collectUnitUsage(use: AbstractInsnNode, value: UnitValue) {
for (def in value.insns) {
@@ -90,7 +90,9 @@ private class UnitSourceInterpreter(private val localVariables: Set<Int>) : Basi
for ((insn, frame) in methodNode.instructions.asSequence().zip(frames.asSequence())) {
if (frame != null && insn.opcode == Opcodes.POP) {
val value = frame.top()
value.safeAs<UnitValue>()?.let { collectUnitUsage(insn, it) }
if (value is UnitValue) {
collectUnitUsage(insn, value)
}
}
}
return frames
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -109,8 +108,8 @@ class SuspendFunctionGenerationStrategy(
return bfs(this)
}
private fun containingClassInternalNameOrNull() =
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
private fun containingClassInternalNameOrNull(): String? =
(originalSuspendDescriptor.containingDeclaration as? ClassDescriptor)?.let(state.typeMapper::mapClass)?.internalName
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
this.codegen = codegen
@@ -39,12 +39,11 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.error.ErrorTypeKind
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -187,9 +186,9 @@ fun ResolvedCall<*>.isSuspensionPoint(codegen: ExpressionCodegen): SuspensionPoi
if (functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return SuspensionPointKind.ALWAYS
if (functionDescriptor.isInline) return SuspensionPointKind.NEVER
val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>()
?.variableCall?.resultingDescriptor?.safeAs<ValueParameterDescriptor>()
?.let { it.isCrossinline || (!it.isNoinline && codegen.context.functionDescriptor.isInline) } == true
val parameter = (this as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor as? ValueParameterDescriptor
val isInlineLambda = parameter != null &&
(parameter.isCrossinline || (!parameter.isNoinline && codegen.context.functionDescriptor.isInline))
return if (isInlineLambda) SuspensionPointKind.NOT_INLINE else SuspensionPointKind.ALWAYS
}
@@ -225,7 +224,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
annotations = Annotations.EMPTY,
name = CONTINUATION_PARAMETER_NAME,
// Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1
outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.isBuiltinFunctionalClassDescriptor == true)
outType = if ((function.containingDeclaration as? ClassDescriptor)?.isBuiltinFunctionalClassDescriptor == true)
function.builtIns.nullableAnyType
else
function.getContinuationParameterTypeOfSuspendFunction(),
@@ -363,8 +362,7 @@ private fun InstructionAdapter.invokeGetContext() {
@Suppress("UNCHECKED_CAST")
fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
(this as? SimpleFunctionDescriptor)?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor =
if (isSuspend)
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -697,7 +696,7 @@ class MethodInliner(
if (lambdaInfo !is PsiExpressionLambda || !lambdaInfo.invokeMethodDescriptor.isSuspend) return
val sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode))
val cfg = ControlFlowGraph.build(processingNode)
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs<VarInsnNode>()?.`var` == 0 }
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && (it as? VarInsnNode)?.`var` == 0 }
val visited = hashSetOf<AbstractInsnNode>()
fun findMeaningfulSuccs(insn: AbstractInsnNode): Collection<AbstractInsnNode> {
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.codegen.ASSERTIONS_DISABLED_FIELD_NAME
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil
@@ -25,6 +24,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.intConstant
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
@@ -577,7 +576,7 @@ private fun addAfterUnboxInlineClassMarker(v: InstructionAdapter) {
}
internal fun addReturnsUnitMarkerIfNecessary(v: InstructionAdapter, resolvedCall: ResolvedCall<*>) {
val wrapperDescriptor = resolvedCall.candidateDescriptor.safeAs<FunctionDescriptor>() ?: return
val wrapperDescriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
val unsubstitutedDescriptor = wrapperDescriptor.unwrapInitialDescriptorForSuspendFunction()
val typeSubstitutor = TypeSubstitutor.create(
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
@@ -143,8 +142,8 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
}
}
private fun BasicValue.getCapturedVarOrNull() =
safeAs<ProperTrackedReferenceValue>()?.descriptor?.safeAs<CapturedVarDescriptor>()
private fun BasicValue.getCapturedVarOrNull(): CapturedVarDescriptor? =
(this as? ProperTrackedReferenceValue)?.descriptor as? CapturedVarDescriptor
private fun assignLocalVars(frames: Array<out Frame<BasicValue>?>) {
for (localVar in methodNode.localVariables) {
@@ -23,8 +23,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
@@ -96,7 +94,7 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
}
private fun tryRewriteComparisonWithZero(insn: JumpInsnNode, frame: Frame<BasicValue>, actions: ArrayList<() -> Unit>) {
val top = frame.top()!!.safeAs<IConstValue>() ?: return
val top = frame.top()!! as? IConstValue ?: return
val constCondition = when (insn.opcode) {
Opcodes.IFEQ -> top.value == 0
@@ -199,9 +197,9 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
in Opcodes.ICONST_M1..Opcodes.ICONST_5 ->
IConstValue.of(insn.opcode - Opcodes.ICONST_0)
Opcodes.BIPUSH, Opcodes.SIPUSH ->
IConstValue.of(insn.cast<IntInsnNode>().operand)
IConstValue.of((insn as IntInsnNode).operand)
Opcodes.LDC -> {
val operand = insn.cast<LdcInsnNode>().cst
val operand = (insn as LdcInsnNode).cst
if (operand is Int)
IConstValue.of(operand)
else
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.codegen.inline.MaxStackFrameSizeAndLocalsCalculator
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.kotlin.codegen.optimization.removeNodeGetNext
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
@@ -244,7 +243,7 @@ internal inline fun <reified T : AbstractInsnNode> AbstractInsnNode.isInsn(opcod
takeInsnIf(opcode, condition) != null
internal inline fun <reified T : AbstractInsnNode> AbstractInsnNode.takeInsnIf(opcode: Int, condition: T.() -> Boolean): T? =
takeIf { it.opcode == opcode }?.safeAs<T>()?.takeIf { it.condition() }
(takeIf { it.opcode == opcode } as? T)?.takeIf { it.condition() }
fun InsnList.removeAll(nodes: Collection<AbstractInsnNode>) {
for (node in nodes) remove(node)
@@ -34,9 +34,8 @@ import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.types.*
import org.jetbrains.org.objectweb.asm.Type
abstract class PrimitiveNumberRangeIntrinsicRangeValue(
rangeCall: ResolvedCall<out CallableDescriptor>
@@ -100,7 +99,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
step: Int,
isStartInclusive: Boolean = true
): ForLoopGenerator? {
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
val endConstValue = codegen.getCompileTimeConstant(endExpression) as? IntegerValueConstant<*> ?: return null
return when (endConstValue) {
is ByteValue -> {
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
@@ -25,11 +24,10 @@ import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGene
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.getFirstArgumentExpression
import org.jetbrains.kotlin.resolve.calls.util.getReceiverExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.constants.IntegerValueConstant
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Type
class PrimitiveNumberRangeLiteralRangeValue(
@@ -109,8 +107,8 @@ private fun ExpressionCodegen.isArraySizeMinusOne(expression: KtExpression): Boo
isConstantOne(expression.right!!)
private fun ExpressionCodegen.isConstantOne(expression: KtExpression): Boolean {
val constantValue = getCompileTimeConstant(expression).safeAs<IntegerValueConstant<*>>() ?: return false
return constantValue.value == 1
val constantValue = getCompileTimeConstant(expression)
return constantValue is IntegerValueConstant<*> && constantValue.value == 1
}
private fun ExpressionCodegen.isArraySizeAccess(expression: KtExpression): Boolean {