[JS IR] Correct pureness of expressions for arrayLiteral

This commit is contained in:
Ilya Goncharov
2021-03-09 15:23:08 +03:00
parent f890156dde
commit 47d050c420
3 changed files with 30 additions and 27 deletions
@@ -200,8 +200,8 @@ fun IrTypeParametersContainer.copyTypeParameters(
// Therefore, we first copy the parameters themselves, then set up their supertypes. // Therefore, we first copy the parameters themselves, then set up their supertypes.
val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter -> val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter ->
sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin).also { sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin).also {
oldToNewParameterMap[sourceParameter] = it oldToNewParameterMap[sourceParameter] = it
} }
} }
typeParameters += newTypeParameters typeParameters += newTypeParameters
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) -> srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
@@ -323,8 +323,7 @@ fun IrType.remapTypeParameters(
when { when {
classifier is IrTypeParameter -> { classifier is IrTypeParameter -> {
val newClassifier = val newClassifier =
srcToDstParameterMap?.get(classifier) ?: srcToDstParameterMap?.get(classifier) ?: if (classifier.parent == source)
if (classifier.parent == source)
target.typeParameters[classifier.index] target.typeParameters[classifier.index]
else else
classifier classifier
@@ -485,16 +484,16 @@ fun IrClass.addFakeOverrides(irBuiltIns: IrBuiltIns, implementedMembers: List<Ir
} }
fun IrFactory.createStaticFunctionWithReceivers( fun IrFactory.createStaticFunctionWithReceivers(
irParent: IrDeclarationParent, irParent: IrDeclarationParent,
name: Name, name: Name,
oldFunction: IrFunction, oldFunction: IrFunction,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type, dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin, origin: IrDeclarationOrigin = oldFunction.origin,
modality: Modality = Modality.FINAL, modality: Modality = Modality.FINAL,
visibility: DescriptorVisibility = oldFunction.visibility, visibility: DescriptorVisibility = oldFunction.visibility,
isFakeOverride: Boolean = oldFunction.isFakeOverride, isFakeOverride: Boolean = oldFunction.isFakeOverride,
copyMetadata: Boolean = true, copyMetadata: Boolean = true,
typeParametersFromContext: List<IrTypeParameter> = listOf() typeParametersFromContext: List<IrTypeParameter> = listOf()
): IrSimpleFunction { ): IrSimpleFunction {
return createFunction( return createFunction(
oldFunction.startOffset, oldFunction.endOffset, oldFunction.startOffset, oldFunction.endOffset,
@@ -548,13 +547,13 @@ fun IrFactory.createStaticFunctionWithReceivers(
remapTypeMap = typeParameterMap remapTypeMap = typeParameterMap
) )
valueParameters = listOfNotNull(dispatchReceiver, extensionReceiver) + valueParameters = listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map { oldFunction.valueParameters.map {
it.copyTo( it.copyTo(
this, this,
index = it.index + offset, index = it.index + offset,
remapTypeMap = typeParameterMap remapTypeMap = typeParameterMap
) )
} }
if (copyMetadata) metadata = oldFunction.metadata if (copyMetadata) metadata = oldFunction.metadata
@@ -662,7 +661,13 @@ fun IrExpression?.isPure(
if (valueDeclaration is IrVariable) !valueDeclaration.isVar if (valueDeclaration is IrVariable) !valueDeclaration.isVar
else true else true
} }
is IrCall -> context?.isSideEffectFree(this) ?: false is IrCall -> if (context?.isSideEffectFree(this) == true) {
for (i in 0 until valueArgumentsCount) {
val valueArgument = getValueArgument(i)
if (!valueArgument.isPure(anyVariable, checkFields, context)) return false
}
true
} else false
is IrGetObjectValue -> type.isUnit() is IrGetObjectValue -> type.isUnit()
is IrVararg -> elements.all { (it as? IrExpression)?.isPure(anyVariable, checkFields, context) == true } is IrVararg -> elements.all { (it as? IrExpression)?.isPure(anyVariable, checkFields, context) == true }
else -> false else -> false
@@ -525,7 +525,6 @@ class FunctionInlining(
val arguments = buildParameterToArgument(callSite, callee) val arguments = buildParameterToArgument(callSite, callee)
val evaluationStatements = mutableListOf<IrStatement>() val evaluationStatements = mutableListOf<IrStatement>()
val substitutor = ParameterSubstitutor() val substitutor = ParameterSubstitutor()
var argumentExtracted = false
arguments.forEach { argument -> arguments.forEach { argument ->
/* /*
* We need to create temporary variable for each argument except inlinable lambda arguments. * We need to create temporary variable for each argument except inlinable lambda arguments.
@@ -533,14 +532,12 @@ class FunctionInlining(
* not only for those referring to inlinable lambdas. * not only for those referring to inlinable lambdas.
*/ */
if (argument.isInlinableLambdaArgument) { if (argument.isInlinableLambdaArgument) {
argumentExtracted = true
substituteMap[argument.parameter] = argument.argumentExpression substituteMap[argument.parameter] = argument.argumentExpression
(argument.argumentExpression as? IrFunctionReference)?.let { evaluationStatements += evaluateArguments(it) } (argument.argumentExpression as? IrFunctionReference)?.let { evaluationStatements += evaluateArguments(it) }
return@forEach return@forEach
} }
if (argument.isImmutableVariableLoad) { if (argument.isImmutableVariableLoad) {
argumentExtracted = true
substituteMap[argument.parameter] = substituteMap[argument.parameter] =
argument.argumentExpression.transform( // Arguments may reference the previous ones - substitute them. argument.argumentExpression.transform( // Arguments may reference the previous ones - substitute them.
substitutor, substitutor,
@@ -549,7 +546,7 @@ class FunctionInlining(
return@forEach return@forEach
} }
argumentExtracted = argumentExtracted || !argument.argumentExpression.isPure(false) val argumentExtracted = !argument.argumentExpression.isPure(false)
// Arguments may reference the previous ones - substitute them. // Arguments may reference the previous ones - substitute them.
val variableInitializer = argument.argumentExpression.transform(substitutor, data = null) val variableInitializer = argument.argumentExpression.transform(substitutor, data = null)
@@ -60,7 +60,8 @@ class JsIrBackendContext(
override var inVerbosePhase: Boolean = false override var inVerbosePhase: Boolean = false
override fun isSideEffectFree(call: IrCall): Boolean = override fun isSideEffectFree(call: IrCall): Boolean =
call.symbol in intrinsics.primitiveToLiteralConstructor.values call.symbol in intrinsics.primitiveToLiteralConstructor.values ||
call.symbol == intrinsics.arrayLiteral
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
val errorPolicy = configuration[JSConfigurationKeys.ERROR_TOLERANCE_POLICY] ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration[JSConfigurationKeys.ERROR_TOLERANCE_POLICY] ?: ErrorTolerancePolicy.DEFAULT