[K/JS] Rework IR deserialization and lowering phases to consume less memory

This commit is contained in:
Artem Kobzar
2023-04-19 13:10:19 +00:00
committed by Space Team
parent 1ee2d0814c
commit 33c5068b79
134 changed files with 964 additions and 616 deletions
@@ -347,7 +347,7 @@ internal class AdapterGenerator(
return adapterFunction.valueParameters[parameterIndex + parameterShift].toIrGetValue(startOffset, endOffset) return adapterFunction.valueParameters[parameterIndex + parameterShift].toIrGetValue(startOffset, endOffset)
} }
adapteeFunction.valueParameters.zip(firAdaptee.valueParameters).mapIndexed { index, (valueParameter, firParameter) -> adapteeFunction.valueParameters.zip(firAdaptee.valueParameters).forEachIndexed { index, (valueParameter, firParameter) ->
when (val mappedArgument = mappedArguments?.get(firParameter)) { when (val mappedArgument = mappedArguments?.get(firParameter)) {
is ResolvedCallArgument.VarargArgument -> { is ResolvedCallArgument.VarargArgument -> {
val valueArgument = if (mappedArgument.arguments.isEmpty()) { val valueArgument = if (mappedArgument.arguments.isEmpty()) {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -141,8 +142,8 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
}.apply { }.apply {
parent = irFunction.parent parent = irFunction.parent
createParameterDeclarations() createParameterDeclarations()
typeParameters = irFunction.typeParameters.map { typeParam -> typeParameters = irFunction.typeParameters.memoryOptimizedMap { typeParam ->
typeParam.copyToWithoutSuperTypes(this).apply { superTypes += typeParam.superTypes } typeParam.copyToWithoutSuperTypes(this).apply { superTypes = superTypes memoryOptimizedPlus typeParam.superTypes }
} }
} }
@@ -186,11 +187,11 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
coroutineClass.declarations += this coroutineClass.declarations += this
coroutineConstructors += this coroutineConstructors += this
valueParameters = functionParameters.mapIndexed { index, parameter -> valueParameters = functionParameters.memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index) parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
} }
val continuationParameter = coroutineBaseClassConstructor.valueParameters[0] val continuationParameter = coroutineBaseClassConstructor.valueParameters[0]
valueParameters += continuationParameter.copyTo( valueParameters = valueParameters memoryOptimizedPlus continuationParameter.copyTo(
this, DECLARATION_ORIGIN_COROUTINE_IMPL, this, DECLARATION_ORIGIN_COROUTINE_IMPL,
index = valueParameters.size, type = continuationType index = valueParameters.size, type = continuationType
) )
@@ -235,18 +236,18 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
parent = coroutineClass parent = coroutineClass
coroutineClass.declarations += this coroutineClass.declarations += this
typeParameters = stateMachineFunction.typeParameters.map { parameter -> typeParameters = stateMachineFunction.typeParameters.memoryOptimizedMap { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL) parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes } .apply { superTypes = superTypes memoryOptimizedPlus parameter.superTypes }
} }
valueParameters = stateMachineFunction.valueParameters.mapIndexed { index, parameter -> valueParameters = stateMachineFunction.valueParameters.memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index) parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
} }
this.createDispatchReceiverParameter() this.createDispatchReceiverParameter()
overriddenSymbols += stateMachineFunction.symbol overriddenSymbols = overriddenSymbols memoryOptimizedPlus stateMachineFunction.symbol
} }
buildStateMachine(function, irFunction, argumentToPropertiesMap) buildStateMachine(function, irFunction, argumentToPropertiesMap)
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
val ANNOTATION_IMPLEMENTATION = object : IrDeclarationOriginImpl("ANNOTATION_IMPLEMENTATION", isSynthetic = true) {} val ANNOTATION_IMPLEMENTATION = object : IrDeclarationOriginImpl("ANNOTATION_IMPLEMENTATION", isSynthetic = true) {}
@@ -156,7 +157,8 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext,
// (although annotations imported from Java do have) // (although annotations imported from Java do have)
val props = declarations.filterIsInstance<IrProperty>() val props = declarations.filterIsInstance<IrProperty>()
if (props.isNotEmpty()) return props if (props.isNotEmpty()) return props
return declarations.filterIsInstance<IrSimpleFunction>().filter { it.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR } return declarations
.filterIsInstanceAnd<IrSimpleFunction> { it.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR }
.mapNotNull { it.correspondingPropertySymbol?.owner } .mapNotNull { it.correspondingPropertySymbol?.owner }
} }
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendContext) { abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendContext) {
@@ -40,7 +41,7 @@ abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendCon
} }
protected fun IrFunction.copyValueParametersFrom(original: IrFunction, wrapWithNullable: Boolean = true) { protected fun IrFunction.copyValueParametersFrom(original: IrFunction, wrapWithNullable: Boolean = true) {
valueParameters = original.valueParameters.map { valueParameters = original.valueParameters.memoryOptimizedMap {
val newType = it.type.remapTypeParameters(original.classIfConstructor, classIfConstructor) val newType = it.type.remapTypeParameters(original.classIfConstructor, classIfConstructor)
val makeNullable = wrapWithNullable && it.defaultValue != null && val makeNullable = wrapWithNullable && it.defaultValue != null &&
(context.ir.unfoldInlineClassType(it.type) ?: it.type) !in context.irBuiltIns.primitiveIrTypes (context.ir.unfoldInlineClassType(it.type) ?: it.type) !in context.irBuiltIns.primitiveIrTypes
@@ -121,17 +122,18 @@ abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendCon
context.mapping.defaultArgumentsOriginalFunction[defaultsFunction] = declaration context.mapping.defaultArgumentsOriginalFunction[defaultsFunction] = declaration
if (forceSetOverrideSymbols) { if (forceSetOverrideSymbols) {
(defaultsFunction as IrSimpleFunction).overriddenSymbols += declaration.overriddenSymbols.mapNotNull { (defaultsFunction as IrSimpleFunction).overriddenSymbols =
generateDefaultsFunction( defaultsFunction.overriddenSymbols memoryOptimizedPlus declaration.overriddenSymbols.mapNotNull {
it.owner, generateDefaultsFunction(
skipInlineMethods, it.owner,
skipExternalMethods, skipInlineMethods,
forceSetOverrideSymbols, skipExternalMethods,
visibility, forceSetOverrideSymbols,
useConstructorMarker, visibility,
it.owner.copyAnnotations(), useConstructorMarker,
)?.symbol as IrSimpleFunctionSymbol? it.owner.copyAnnotations(),
} )?.symbol as IrSimpleFunctionSymbol?
}
} }
} }
} }
@@ -200,7 +202,7 @@ abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendCon
parent = declaration.parent parent = declaration.parent
generateDefaultArgumentStubFrom(declaration, useConstructorMarker) generateDefaultArgumentStubFrom(declaration, useConstructorMarker)
// TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant. // TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant.
annotations += copiedAnnotations annotations = annotations memoryOptimizedPlus copiedAnnotations
} }
} }
} }
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
// TODO: fix expect/actual default parameters // TODO: fix expect/actual default parameters
@@ -488,7 +489,7 @@ class DefaultParameterPatchOverridenSymbolsLowering(
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? { override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (declaration is IrSimpleFunction) { if (declaration is IrSimpleFunction) {
(context.mapping.defaultArgumentsOriginalFunction[declaration] as? IrSimpleFunction)?.run { (context.mapping.defaultArgumentsOriginalFunction[declaration] as? IrSimpleFunction)?.run {
declaration.overriddenSymbols += overriddenSymbols.mapNotNull { declaration.overriddenSymbols = declaration.overriddenSymbols memoryOptimizedPlus overriddenSymbols.mapNotNull {
(context.mapping.defaultArgumentsDispatchFunction[it.owner] as? IrSimpleFunction)?.symbol (context.mapping.defaultArgumentsDispatchFunction[it.owner] as? IrSimpleFunction)?.symbol
} }
} }
@@ -35,6 +35,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
interface VisibilityPolicy { interface VisibilityPolicy {
fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility = fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
@@ -708,7 +710,7 @@ class LocalDeclarationsLowering(
) )
// Type parameters of oldDeclaration may depend on captured type parameters, so deal with that after copying. // Type parameters of oldDeclaration may depend on captured type parameters, so deal with that after copying.
newDeclaration.typeParameters.drop(newTypeParameters.size).forEach { tp -> newDeclaration.typeParameters.drop(newTypeParameters.size).forEach { tp ->
tp.superTypes = tp.superTypes.map { localFunctionContext.remapType(it) } tp.superTypes = tp.superTypes.memoryOptimizedMap { localFunctionContext.remapType(it) }
} }
newDeclaration.parent = ownerParent newDeclaration.parent = ownerParent
@@ -721,7 +723,7 @@ class LocalDeclarationsLowering(
} }
newDeclaration.copyAttributes(oldDeclaration) newDeclaration.copyAttributes(oldDeclaration)
newDeclaration.valueParameters += createTransformedValueParameters( newDeclaration.valueParameters = newDeclaration.valueParameters memoryOptimizedPlus createTransformedValueParameters(
capturedValues, localFunctionContext, oldDeclaration, newDeclaration, capturedValues, localFunctionContext, oldDeclaration, newDeclaration,
isExplicitLocalFunction = oldDeclaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION isExplicitLocalFunction = oldDeclaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION
) )
@@ -831,7 +833,7 @@ class LocalDeclarationsLowering(
throw AssertionError("Local class constructor can't have extension receiver: ${ir2string(oldDeclaration)}") throw AssertionError("Local class constructor can't have extension receiver: ${ir2string(oldDeclaration)}")
} }
newDeclaration.valueParameters += createTransformedValueParameters( newDeclaration.valueParameters = newDeclaration.valueParameters memoryOptimizedPlus createTransformedValueParameters(
capturedValues, localClassContext, oldDeclaration, newDeclaration capturedValues, localClassContext, oldDeclaration, newDeclaration
) )
newDeclaration.recordTransformedValueParameters(constructorContext) newDeclaration.recordTransformedValueParameters(constructorContext)
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isArray import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) { class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) {
private fun IrClass.addSyntheticFunction(name: String, returnType: IrType) = private fun IrClass.addSyntheticFunction(name: String, returnType: IrType) =
@@ -43,7 +44,7 @@ class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irCla
companion object { companion object {
fun IrClass.collectOverridenSymbols(predicate: (IrFunction) -> Boolean): List<IrSimpleFunctionSymbol> = fun IrClass.collectOverridenSymbols(predicate: (IrFunction) -> Boolean): List<IrSimpleFunctionSymbol> =
superTypes.mapNotNull { it.getClass()?.functions?.singleOrNull(predicate)?.symbol } superTypes.memoryOptimizedMapNotNull { it.getClass()?.functions?.singleOrNull(predicate)?.symbol }
} }
} }
@@ -29,6 +29,9 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.findIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() { abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
// SAM wrappers are cached, either in the file class (if it exists), or in a top-level enclosing class. // SAM wrappers are cached, either in the file class (if it exists), or in a top-level enclosing class.
@@ -79,8 +82,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
cachedImplementations.clear() cachedImplementations.clear()
inlineCachedImplementations.clear() inlineCachedImplementations.clear()
enclosingContainer = irFile.declarations.filterIsInstance<IrClass>().find { it.isFileClass } enclosingContainer = irFile.declarations.findIsInstanceAnd<IrClass> { it.isFileClass } ?: irFile
?: irFile
irFile.transformChildrenVoid() irFile.transformChildrenVoid()
for (wrapper in cachedImplementations.values + inlineCachedImplementations.values) { for (wrapper in cachedImplementations.values + inlineCachedImplementations.values) {
@@ -177,7 +179,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
setSourceRange(createFor) setSourceRange(createFor)
}.apply { }.apply {
createImplicitParameterDeclarationWithWrappedDescriptor() createImplicitParameterDeclarationWithWrappedDescriptor()
superTypes = listOf(superType) + getAdditionalSupertypes(superType) superTypes = listOf(superType) memoryOptimizedPlus getAdditionalSupertypes(superType)
parent = enclosingContainer!! parent = enclosingContainer!!
} }
@@ -221,7 +223,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
overriddenSymbols = listOf(originalSuperMethod.symbol) overriddenSymbols = listOf(originalSuperMethod.symbol)
dispatchReceiverParameter = subclass.thisReceiver!!.copyTo(this) dispatchReceiverParameter = subclass.thisReceiver!!.copyTo(this)
extensionReceiverParameter = originalSuperMethod.extensionReceiverParameter?.copyTo(this) extensionReceiverParameter = originalSuperMethod.extensionReceiverParameter?.copyTo(this)
valueParameters = originalSuperMethod.valueParameters.map { it.copyTo(this) } valueParameters = originalSuperMethod.valueParameters.memoryOptimizedMap { it.copyTo(this) }
body = context.createIrBuilder(symbol).irBlockBody { body = context.createIrBuilder(symbol).irBlockBody {
+irReturn( +irReturn(
irCall( irCall(
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
/** /**
* Replaces suspend functions with regular non-suspend functions with additional * Replaces suspend functions with regular non-suspend functions with additional
@@ -120,12 +122,12 @@ private fun IrSimpleFunction.createSuspendFunctionStub(context: CommonBackendCon
val substitutionMap = makeTypeParameterSubstitutionMap(this, function) val substitutionMap = makeTypeParameterSubstitutionMap(this, function)
function.copyReceiverParametersFrom(this, substitutionMap) function.copyReceiverParametersFrom(this, substitutionMap)
function.overriddenSymbols += overriddenSymbols.map { function.overriddenSymbols = function.overriddenSymbols memoryOptimizedPlus overriddenSymbols.map {
factory.stageController.restrictTo(it.owner) { factory.stageController.restrictTo(it.owner) {
it.owner.getOrCreateFunctionWithContinuationStub(context).symbol it.owner.getOrCreateFunctionWithContinuationStub(context).symbol
} }
} }
function.valueParameters = valueParameters.map { it.copyTo(function) } function.valueParameters = valueParameters.memoryOptimizedMap { it.copyTo(function) }
val mapping = mutableMapOf<IrValueSymbol, IrValueSymbol>() val mapping = mutableMapOf<IrValueSymbol, IrValueSymbol>()
valueParameters.forEach { mapping[it.symbol] = function.valueParameters[it.index].symbol } valueParameters.forEach { mapping[it.symbol] = function.valueParameters[it.index].symbol }
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.declarations.copyAttributes import org.jetbrains.kotlin.ir.declarations.copyAttributes
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -21,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.utils.memoryOptimizedMap
internal class DeepCopyIrTreeWithSymbolsForInliner( internal class DeepCopyIrTreeWithSymbolsForInliner(
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?, val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
@@ -54,7 +54,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
arguments: List<IrTypeArgument>, arguments: List<IrTypeArgument>,
erasedParameters: MutableSet<IrTypeParameterSymbol>? erasedParameters: MutableSet<IrTypeParameterSymbol>?
) = ) =
arguments.map { argument -> arguments.memoryOptimizedMap { argument ->
(argument as? IrTypeProjection)?.let { proj -> (argument as? IrTypeProjection)?.let { proj ->
remapTypeAndOptionallyErase(proj.type, erasedParameters)?.let { newType -> remapTypeAndOptionallyErase(proj.type, erasedParameters)?.let { newType ->
makeTypeProjection(newType, proj.variance) makeTypeProjection(newType, proj.variance)
@@ -112,7 +112,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
kotlinType = null kotlinType = null
this.classifier = symbolRemapper.getReferencedClassifier(classifier) this.classifier = symbolRemapper.getReferencedClassifier(classifier)
arguments = remapTypeArguments(type.arguments, erasedParameters) arguments = remapTypeArguments(type.arguments, erasedParameters)
annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall } annotations = type.annotations.memoryOptimizedMap { it.transform(copier, null) as IrConstructorCall }
} }
} }
} }
@@ -52,7 +52,7 @@ interface JsCommonBackendContext : CommonBackendContext {
} }
// TODO: investigate if it could be removed // TODO: investigate if it could be removed
internal fun <T> BackendContext.lazy2(fn: () -> T) = lazy { irFactory.stageController.withInitialIr(fn) } internal fun <T> BackendContext.lazy2(fn: () -> T) = lazy(LazyThreadSafetyMode.NONE) { irFactory.stageController.withInitialIr(fn) }
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
class JsCommonCoroutineSymbols( class JsCommonCoroutineSymbols(
@@ -66,14 +66,14 @@ class JsCommonCoroutineSymbols(
val coroutineImpl = val coroutineImpl =
symbolTable.referenceClass(findClass(coroutinePackage.memberScope, COROUTINE_IMPL_NAME)) symbolTable.referenceClass(findClass(coroutinePackage.memberScope, COROUTINE_IMPL_NAME))
val coroutineImplLabelPropertyGetter by lazy { coroutineImpl.getPropertyGetter("state")!!.owner } val coroutineImplLabelPropertyGetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertyGetter("state")!!.owner }
val coroutineImplLabelPropertySetter by lazy { coroutineImpl.getPropertySetter("state")!!.owner } val coroutineImplLabelPropertySetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertySetter("state")!!.owner }
val coroutineImplResultSymbolGetter by lazy { coroutineImpl.getPropertyGetter("result")!!.owner } val coroutineImplResultSymbolGetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertyGetter("result")!!.owner }
val coroutineImplResultSymbolSetter by lazy { coroutineImpl.getPropertySetter("result")!!.owner } val coroutineImplResultSymbolSetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertySetter("result")!!.owner }
val coroutineImplExceptionPropertyGetter by lazy { coroutineImpl.getPropertyGetter("exception")!!.owner } val coroutineImplExceptionPropertyGetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertyGetter("exception")!!.owner }
val coroutineImplExceptionPropertySetter by lazy { coroutineImpl.getPropertySetter("exception")!!.owner } val coroutineImplExceptionPropertySetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertySetter("exception")!!.owner }
val coroutineImplExceptionStatePropertyGetter by lazy { coroutineImpl.getPropertyGetter("exceptionState")!!.owner } val coroutineImplExceptionStatePropertyGetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertyGetter("exceptionState")!!.owner }
val coroutineImplExceptionStatePropertySetter by lazy { coroutineImpl.getPropertySetter("exceptionState")!!.owner } val coroutineImplExceptionStatePropertySetter by lazy(LazyThreadSafetyMode.NONE) { coroutineImpl.getPropertySetter("exceptionState")!!.owner }
val continuationClass = symbolTable.referenceClass( val continuationClass = symbolTable.referenceClass(
coroutinePackage.memberScope.getContributedClassifier( coroutinePackage.memberScope.getContributedClassifier(
@@ -185,7 +185,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val jsNumberRangeToLong = getInternalFunction("numberRangeToLong") val jsNumberRangeToLong = getInternalFunction("numberRangeToLong")
private val _rangeUntilFunctions = irBuiltIns.findFunctions(Name.identifier("until"), "kotlin", "ranges") private val _rangeUntilFunctions = irBuiltIns.findFunctions(Name.identifier("until"), "kotlin", "ranges")
val rangeUntilFunctions by lazy { val rangeUntilFunctions by lazy(LazyThreadSafetyMode.NONE) {
_rangeUntilFunctions _rangeUntilFunctions
.filter { it.owner.extensionReceiverParameter != null && it.owner.valueParameters.size == 1 } .filter { it.owner.extensionReceiverParameter != null && it.owner.valueParameters.size == 1 }
.associateBy { it.owner.extensionReceiverParameter!!.type to it.owner.valueParameters[0].type } .associateBy { it.owner.extensionReceiverParameter!!.type to it.owner.valueParameters[0].type }
@@ -324,11 +324,11 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun")) val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
val jsNameAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsName")) val jsNameAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsName"))
val jsExportAnnotationSymbol by lazy { val jsExportAnnotationSymbol by lazy(LazyThreadSafetyMode.NONE) {
context.symbolTable.referenceClass(context.getJsInternalClass("JsExport")) context.symbolTable.referenceClass(context.getJsInternalClass("JsExport"))
} }
val jsExportIgnoreAnnotationSymbol by lazy { val jsExportIgnoreAnnotationSymbol by lazy(LazyThreadSafetyMode.NONE) {
jsExportAnnotationSymbol.owner jsExportAnnotationSymbol.owner
.findDeclaration<IrClass> { it.fqNameWhenAvailable == FqName("kotlin.js.JsExport.Ignore") } .findDeclaration<IrClass> { it.fqNameWhenAvailable == FqName("kotlin.js.JsExport.Ignore") }
?.symbol ?: error("can't find kotlin.js.JsExport.Ignore annotation") ?.symbol ?: error("can't find kotlin.js.JsExport.Ignore annotation")
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.linkage.partial.createPartialLinkageSupportForLowerings import org.jetbrains.kotlin.backend.common.linkage.partial.createPartialLinkageSupportForLowerings
import org.jetbrains.kotlin.backend.common.serialization.IrInterningService
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -48,9 +49,9 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.isNullable import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceMapNotNull
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.filterIsInstanceMapNotNull
import java.util.WeakHashMap import java.util.WeakHashMap
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -73,6 +74,7 @@ class JsIrBackendContext(
val polyfills = JsPolyfills() val polyfills = JsPolyfills()
val fieldToInitializer = WeakHashMap<IrField, IrExpression>() val fieldToInitializer = WeakHashMap<IrField, IrExpression>()
val globalInternationService = IrInterningService()
val localClassNames = WeakHashMap<IrClass, String>() val localClassNames = WeakHashMap<IrClass, String>()
@@ -102,17 +104,17 @@ class JsIrBackendContext(
val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>() val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
val additionalExportedDeclarations = mutableSetOf<IrDeclaration>() val additionalExportedDeclarations = hashSetOf<IrDeclaration>()
val bodilessBuiltInsPackageFragment: IrPackageFragment = IrExternalPackageFragmentImpl( val bodilessBuiltInsPackageFragment: IrPackageFragment = IrExternalPackageFragmentImpl(
DescriptorlessExternalPackageFragmentSymbol(), DescriptorlessExternalPackageFragmentSymbol(),
FqName("kotlin") FqName("kotlin")
) )
val packageLevelJsModules = mutableSetOf<IrFile>() val packageLevelJsModules = hashSetOf<IrFile>()
val declarationLevelJsModules = mutableListOf<IrDeclarationWithName>() val declarationLevelJsModules = mutableListOf<IrDeclarationWithName>()
val testFunsPerFile = mutableMapOf<IrFile, IrSimpleFunction>() val testFunsPerFile = hashMapOf<IrFile, IrSimpleFunction>()
override fun createTestContainerFun(irFile: IrFile): IrSimpleFunction { override fun createTestContainerFun(irFile: IrFile): IrSimpleFunction {
return testFunsPerFile.getOrPut(irFile) { return testFunsPerFile.getOrPut(irFile) {
@@ -263,13 +265,13 @@ class JsIrBackendContext(
private val getProgressionLastElementSymbols = private val getProgressionLastElementSymbols =
irBuiltIns.findFunctions(Name.identifier("getProgressionLastElement"), "kotlin", "internal") irBuiltIns.findFunctions(Name.identifier("getProgressionLastElement"), "kotlin", "internal")
override val getProgressionLastElementByReturnType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy { override val getProgressionLastElementByReturnType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy(LazyThreadSafetyMode.NONE) {
getProgressionLastElementSymbols.associateBy { it.owner.returnType.classifierOrFail } getProgressionLastElementSymbols.associateBy { it.owner.returnType.classifierOrFail }
} }
private val toUIntSymbols = irBuiltIns.findFunctions(Name.identifier("toUInt"), "kotlin") private val toUIntSymbols = irBuiltIns.findFunctions(Name.identifier("toUInt"), "kotlin")
override val toUIntByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy { override val toUIntByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy(LazyThreadSafetyMode.NONE) {
toUIntSymbols.associateBy { toUIntSymbols.associateBy {
it.owner.extensionReceiverParameter?.type?.classifierOrFail it.owner.extensionReceiverParameter?.type?.classifierOrFail
?: error("Expected extension receiver for ${it.owner.render()}") ?: error("Expected extension receiver for ${it.owner.render()}")
@@ -278,7 +280,7 @@ class JsIrBackendContext(
private val toULongSymbols = irBuiltIns.findFunctions(Name.identifier("toULong"), "kotlin") private val toULongSymbols = irBuiltIns.findFunctions(Name.identifier("toULong"), "kotlin")
override val toULongByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy { override val toULongByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> by lazy(LazyThreadSafetyMode.NONE) {
toULongSymbols.associateBy { toULongSymbols.associateBy {
it.owner.extensionReceiverParameter?.type?.classifierOrFail it.owner.extensionReceiverParameter?.type?.classifierOrFail
?: error("Expected extension receiver for ${it.owner.render()}") ?: error("Expected extension receiver for ${it.owner.render()}")
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
class PropertyLazyInitialization(val enabled: Boolean, eagerInitialization: IrClassSymbol) { class PropertyLazyInitialization(val enabled: Boolean, eagerInitialization: IrClassSymbol) {
val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = mutableMapOf() val fileToInitializationFuns: MutableMap<IrFile, IrSimpleFunction?> = hashMapOf()
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf() val fileToInitializerPureness: MutableMap<IrFile, Boolean> = hashMapOf()
val eagerInitialization: IrClassSymbol = eagerInitialization val eagerInitialization: IrClassSymbol = eagerInitialization
} }
@@ -122,6 +122,7 @@ fun compileIr(
irLinker.postProcess(inOrAfterLinkageStep = true) irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process") irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
irLinker.clear()
allModules.forEach { module -> allModules.forEach { module ->
if (shouldGeneratePolyfills) { if (shouldGeneratePolyfills) {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.backend.js.lower.isEs6ConstructorReplacement
import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
@@ -27,7 +27,7 @@ abstract class UsefulDeclarationProcessor(
protected fun getMethodOfAny(name: String): IrDeclaration = protected fun getMethodOfAny(name: String): IrDeclaration =
context.irBuiltIns.anyClass.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == name } context.irBuiltIns.anyClass.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == name }
protected val toStringMethod: IrDeclaration by lazy { getMethodOfAny("toString") } protected val toStringMethod: IrDeclaration by lazy(LazyThreadSafetyMode.NONE) { getMethodOfAny("toString") }
protected abstract fun isExported(declaration: IrDeclaration): Boolean protected abstract fun isExported(declaration: IrDeclaration): Boolean
protected abstract val bodyVisitor: BodyVisitorBase protected abstract val bodyVisitor: BodyVisitorBase
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.isAny
@@ -22,6 +21,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
import org.jetbrains.kotlin.utils.memoryOptimizedFilter
import org.jetbrains.kotlin.utils.memoryOptimizedMap
class UselessDeclarationsRemover( class UselessDeclarationsRemover(
private val removeUnusedAssociatedObjects: Boolean, private val removeUnusedAssociatedObjects: Boolean,
@@ -52,13 +53,13 @@ class UselessDeclarationsRemover(
// Otherwise `JsClassGenerator.generateAssociatedKeyProperties` will try to reference the object factory (which is removed). // Otherwise `JsClassGenerator.generateAssociatedKeyProperties` will try to reference the object factory (which is removed).
// That will result in an error from the Namer. It cannot generate a name for an absent declaration. // That will result in an error from the Namer. It cannot generate a name for an absent declaration.
if (removeUnusedAssociatedObjects && declaration.annotations.any { !it.shouldKeepAnnotation() }) { if (removeUnusedAssociatedObjects && declaration.annotations.any { !it.shouldKeepAnnotation() }) {
declaration.annotations = declaration.annotations.filter { it.shouldKeepAnnotation() } declaration.annotations = declaration.annotations.memoryOptimizedFilter { it.shouldKeepAnnotation() }
} }
declaration.superTypes = declaration.superTypes declaration.superTypes = declaration.superTypes
.flatMap { it.classOrNull?.collectUsedSuperTypes() ?: emptyList() } .flatMap { it.classOrNull?.collectUsedSuperTypes() ?: emptyList() }
.distinct() .distinct()
.map { it.defaultType } .memoryOptimizedMap { it.defaultType }
} }
private fun IrClassSymbol.collectUsedSuperTypes(): Set<IrClassSymbol> { private fun IrClassSymbol.collectUsedSuperTypes(): Set<IrClassSymbol> {
@@ -68,7 +69,7 @@ class UselessDeclarationsRemover(
} else { } else {
owner.superTypes owner.superTypes
.flatMap { it.takeIf { !it.isAny() }?.classOrNull?.collectUsedSuperTypes() ?: emptyList() } .flatMap { it.takeIf { !it.isAny() }?.classOrNull?.collectUsedSuperTypes() ?: emptyList() }
.toSet() .toHashSet()
} }
} }
} }
@@ -23,9 +23,8 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.keysToMap
private const val magicPropertyName = "__doNotUseOrImplementIt" private const val magicPropertyName = "__doNotUseOrImplementIt"
@@ -34,7 +33,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
fun generateExport(file: IrPackageFragment): List<ExportedDeclaration> { fun generateExport(file: IrPackageFragment): List<ExportedDeclaration> {
val namespaceFqName = file.fqName val namespaceFqName = file.fqName
val exports = file.declarations.flatMap { declaration -> listOfNotNull(exportDeclaration(declaration)) } val exports = file.declarations.memoryOptimizedFlatMap { declaration -> listOfNotNull(exportDeclaration(declaration)) }
return when { return when {
exports.isEmpty() -> emptyList() exports.isEmpty() -> emptyList()
!generateNamespacesForPackages || namespaceFqName.isRoot -> exports !generateNamespacesForPackages || namespaceFqName.isRoot -> exports
@@ -46,7 +45,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
ExportedModule( ExportedModule(
context.configuration[CommonConfigurationKeys.MODULE_NAME]!!, context.configuration[CommonConfigurationKeys.MODULE_NAME]!!,
moduleKind, moduleKind,
(context.externalPackageFragment.values + modules.flatMap { it.files }).flatMap { (context.externalPackageFragment.values + modules.flatMap { it.files }).memoryOptimizedFlatMap {
generateExport(it) generateExport(it)
} }
) )
@@ -84,7 +83,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
ExportedFunction( ExportedFunction(
function.getExportedIdentifier(), function.getExportedIdentifier(),
returnType = exportType(function.returnType), returnType = exportType(function.returnType),
typeParameters = function.typeParameters.map(::exportTypeParameter), typeParameters = function.typeParameters.memoryOptimizedMap(::exportTypeParameter),
isMember = parent is IrClass, isMember = parent is IrClass,
isStatic = function.isStaticMethod, isStatic = function.isStaticMethod,
isAbstract = parent is IrClass && !parent.isInterface && function.modality == Modality.ABSTRACT, isAbstract = parent is IrClass && !parent.isInterface && function.modality == Modality.ABSTRACT,
@@ -92,7 +91,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
ir = function, ir = function,
parameters = (listOfNotNull(function.extensionReceiverParameter) + function.valueParameters) parameters = (listOfNotNull(function.extensionReceiverParameter) + function.valueParameters)
.filter { it.shouldBeExported() } .filter { it.shouldBeExported() }
.map { exportParameter(it) }, .memoryOptimizedMap { exportParameter(it) },
) )
} }
} }
@@ -102,7 +101,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
if (!constructor.isPrimary) return null if (!constructor.isPrimary) return null
val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + constructor.valueParameters val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + constructor.valueParameters
return ExportedConstructor( return ExportedConstructor(
parameters = allValueParameters.filterNot { it.isBoxParameter }.map { exportParameter(it) }, parameters = allValueParameters.filterNot { it.isBoxParameter }.memoryOptimizedMap { exportParameter(it) },
visibility = constructor.visibility.toExportedVisibility() visibility = constructor.visibility.toExportedVisibility()
) )
} }
@@ -219,11 +218,11 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
} }
private fun exportDeclarationImplicitly(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration { private fun exportDeclarationImplicitly(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration {
val typeParameters = klass.typeParameters.map(::exportTypeParameter) val typeParameters = klass.typeParameters.memoryOptimizedMap(::exportTypeParameter)
val superInterfaces = superTypes val superInterfaces = superTypes
.filter { (it.classifierOrFail.owner as? IrDeclaration)?.isExportedImplicitlyOrExplicitly(context) ?: false } .filter { (it.classifierOrFail.owner as? IrDeclaration)?.isExportedImplicitlyOrExplicitly(context) ?: false }
.map { exportType(it) } .map { exportType(it) }
.filter { it !is ExportedType.ErrorType } .memoryOptimizedFilter { it !is ExportedType.ErrorType }
val name = klass.getExportedIdentifier() val name = klass.getExportedIdentifier()
val (members, nestedClasses) = exportClassDeclarations(klass, superTypes) val (members, nestedClasses) = exportClassDeclarations(klass, superTypes)
@@ -288,7 +287,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
return exportClass( return exportClass(
klass, klass,
superTypes, superTypes,
listOf(privateConstructor) + members, listOf(privateConstructor) memoryOptimizedPlus members,
nestedClasses nestedClasses
) )
} }
@@ -424,17 +423,17 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
members: List<ExportedDeclaration>, members: List<ExportedDeclaration>,
nestedClasses: List<ExportedClass>, nestedClasses: List<ExportedClass>,
): ExportedDeclaration { ): ExportedDeclaration {
val typeParameters = klass.typeParameters.map(::exportTypeParameter) val typeParameters = klass.typeParameters.memoryOptimizedMap(::exportTypeParameter)
val superClasses = superTypes val superClasses = superTypes
.filter { !it.classifierOrFail.isInterface && it.canBeUsedAsSuperTypeOfExportedClasses() } .filter { !it.classifierOrFail.isInterface && it.canBeUsedAsSuperTypeOfExportedClasses() }
.map { exportType(it, false) } .map { exportType(it, false) }
.filter { it !is ExportedType.ErrorType } .memoryOptimizedFilter { it !is ExportedType.ErrorType }
val superInterfaces = superTypes val superInterfaces = superTypes
.filter { it.shouldPresentInsideImplementsClause() } .filter { it.shouldPresentInsideImplementsClause() }
.map { exportType(it, false) } .map { exportType(it, false) }
.filter { it !is ExportedType.ErrorType } .memoryOptimizedFilter { it !is ExportedType.ErrorType }
val name = klass.getExportedIdentifier() val name = klass.getExportedIdentifier()
@@ -594,7 +593,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
nonNullType.isArray() -> ExportedType.Array(exportTypeArgument(nonNullType.arguments[0])) nonNullType.isArray() -> ExportedType.Array(exportTypeArgument(nonNullType.arguments[0]))
nonNullType.isSuspendFunction() -> ExportedType.ErrorType("Suspend functions are not supported") nonNullType.isSuspendFunction() -> ExportedType.ErrorType("Suspend functions are not supported")
nonNullType.isFunction() -> ExportedType.Function( nonNullType.isFunction() -> ExportedType.Function(
parameterTypes = nonNullType.arguments.dropLast(1).map { exportTypeArgument(it) }, parameterTypes = nonNullType.arguments.dropLast(1).memoryOptimizedMap { exportTypeArgument(it) },
returnType = exportTypeArgument(nonNullType.arguments.last()) returnType = exportTypeArgument(nonNullType.arguments.last())
) )
@@ -610,7 +609,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
val exportedSupertype = runIf(shouldCalculateExportedSupertypeForImplicit && isImplicitlyExported) { val exportedSupertype = runIf(shouldCalculateExportedSupertypeForImplicit && isImplicitlyExported) {
val transitiveExportedType = nonNullType.collectSuperTransitiveHierarchy() val transitiveExportedType = nonNullType.collectSuperTransitiveHierarchy()
if (transitiveExportedType.isEmpty()) return@runIf null if (transitiveExportedType.isEmpty()) return@runIf null
transitiveExportedType.map(::exportType).reduce(ExportedType::IntersectionType) transitiveExportedType.memoryOptimizedMap(::exportType).reduce(ExportedType::IntersectionType)
} ?: ExportedType.Primitive.Any } ?: ExportedType.Primitive.Any
when (klass.kind) { when (klass.kind) {
@@ -625,7 +624,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
ClassKind.ENUM_CLASS, ClassKind.ENUM_CLASS,
ClassKind.INTERFACE -> ExportedType.ClassType( ClassKind.INTERFACE -> ExportedType.ClassType(
name, name,
type.arguments.map { exportTypeArgument(it) }, type.arguments.memoryOptimizedMap { exportTypeArgument(it) },
klass klass
) )
}.withImplicitlyExported(isImplicitlyExported, exportedSupertype) }.withImplicitlyExported(isImplicitlyExported, exportedSupertype)
@@ -20,14 +20,14 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.util.companionObject
import org.jetbrains.kotlin.ir.util.isObject import org.jetbrains.kotlin.ir.util.isObject
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd import org.jetbrains.kotlin.utils.filterIsInstanceAnd
class ExportModelToJsStatements( class ExportModelToJsStatements(
private val staticContext: JsStaticContext, private val staticContext: JsStaticContext,
private val es6mode: Boolean, private val es6mode: Boolean,
private val declareNewNamespace: (String) -> String, private val declareNewNamespace: (String) -> String,
) { ) {
private val namespaceToRefMap = mutableMapOf<String, JsNameRef>() private val namespaceToRefMap = hashMapOf<String, JsNameRef>()
fun generateModuleExport( fun generateModuleExport(
module: ExportedModule, module: ExportedModule,
@@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.ic
import org.jetbrains.kotlin.backend.common.CommonJsKLibResolver import org.jetbrains.kotlin.backend.common.CommonJsKLibResolver
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.serialization.IrInterningService
import org.jetbrains.kotlin.backend.common.serialization.cityHash64 import org.jetbrains.kotlin.backend.common.serialization.cityHash64
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.backend.js.*
@@ -19,6 +20,10 @@ import org.jetbrains.kotlin.library.KLIB_PROPERTY_DEPENDS
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.memoryOptimizedFilter
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
import org.jetbrains.kotlin.utils.newHashSetWithExpectedSize
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.util.EnumSet import java.util.EnumSet
@@ -67,6 +72,8 @@ class CacheUpdater(
private val icHasher = ICHasher() private val icHasher = ICHasher()
private val internationService = IrInterningService()
private val cacheRootDir = run { private val cacheRootDir = run {
val configHash = icHasher.calculateConfigHash(compilerConfiguration) val configHash = icHasher.calculateConfigHash(compilerConfiguration)
File(cacheDir, "version.${configHash.hash.lowBytes.toString(Character.MAX_RADIX)}") File(cacheDir, "version.${configHash.hash.lowBytes.toString(Character.MAX_RADIX)}")
@@ -107,15 +114,15 @@ class CacheUpdater(
val nameToKotlinLibrary = libraries.associateBy { it.moduleName } val nameToKotlinLibrary = libraries.associateBy { it.moduleName }
libraries.associateWith { libraries.associateWith {
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName -> it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).memoryOptimizedMap { depName ->
nameToKotlinLibrary[depName] ?: notFoundIcError("library $depName") nameToKotlinLibrary[depName] ?: notFoundIcError("library $depName")
} }
} }
} }
val mainModuleFriendLibraries = libraryDependencies.keys.let { libs -> val mainModuleFriendLibraries = libraryDependencies.keys.let { libs ->
val friendPaths = mainModuleFriends.mapTo(HashSet(mainModuleFriends.size)) { File(it).canonicalPath } val friendPaths = mainModuleFriends.mapTo(newHashSetWithExpectedSize(mainModuleFriends.size)) { File(it).canonicalPath }
libs.filter { it.libraryFile.canonicalPath in friendPaths } libs.memoryOptimizedFilter { it.libraryFile.canonicalPath in friendPaths }
} }
private val klibCacheDirs = libraryDependencies.keys.map { lib -> private val klibCacheDirs = libraryDependencies.keys.map { lib ->
@@ -139,12 +146,12 @@ class CacheUpdater(
} }
private val incrementalCaches = libraryDependencies.keys.zip(klibCacheDirs).associate { (lib, libraryCacheDir) -> private val incrementalCaches = libraryDependencies.keys.zip(klibCacheDirs).associate { (lib, libraryCacheDir) ->
KotlinLibraryFile(lib) to IncrementalCache(KotlinLoadedLibraryHeader(lib), libraryCacheDir) KotlinLibraryFile(lib) to IncrementalCache(KotlinLoadedLibraryHeader(lib, internationService), libraryCacheDir)
} }
private val removedIncrementalCaches = buildList { private val removedIncrementalCaches = buildList {
if (cacheRootDir.isDirectory) { if (cacheRootDir.isDirectory) {
val availableCaches = incrementalCaches.values.mapTo(HashSet(incrementalCaches.size)) { it.cacheDir } val availableCaches = incrementalCaches.values.mapTo(newHashSetWithExpectedSize(incrementalCaches.size)) { it.cacheDir }
val allDirs = Files.walk(cacheRootDir.toPath(), 1).map { it.toFile() } val allDirs = Files.walk(cacheRootDir.toPath(), 1).map { it.toFile() }
allDirs.filter { it != cacheRootDir && it !in availableCaches }.forEach { removedCacheDir -> allDirs.filter { it != cacheRootDir && it !in availableCaches }.forEach { removedCacheDir ->
add(IncrementalCache(KotlinRemovedLibraryHeader(removedCacheDir), removedCacheDir)) add(IncrementalCache(KotlinRemovedLibraryHeader(removedCacheDir), removedCacheDir))
@@ -445,7 +452,7 @@ class CacheUpdater(
// if imports have been modified, metadata for the file will be rebuilt later, // if imports have been modified, metadata for the file will be rebuilt later,
// so if the imports haven't been modified, update the metadata manually // so if the imports haven't been modified, update the metadata manually
if (newMetadata.importedSignaturesState == ImportedSignaturesState.NON_MODIFIED) { if (newMetadata.importedSignaturesState == ImportedSignaturesState.NON_MODIFIED) {
val newDirectDependencies = newSignatures.associateWithTo(HashMap(newSignatures.size)) { val newDirectDependencies = newSignatures.associateWithTo(newHashMapWithExpectedSize(newSignatures.size)) {
signatureHashCalculator[it] ?: notFoundIcError("signature $it hash", libFile, srcFile) signatureHashCalculator[it] ?: notFoundIcError("signature $it hash", libFile, srcFile)
} }
newMetadata.directDependencies[libFile, srcFile] = newDirectDependencies newMetadata.directDependencies[libFile, srcFile] = newDirectDependencies
@@ -690,7 +697,7 @@ class CacheUpdater(
// Load declarations referenced during `context` initialization // Load declarations referenced during `context` initialization
loadedIr.loadUnboundSymbols() loadedIr.loadUnboundSymbols()
val dirtyFiles = dirtyFileExports.entries.associateTo(HashMap(dirtyFileExports.size)) { it.key to HashSet(it.value.keys) } val dirtyFiles = dirtyFileExports.entries.associateTo(newHashMapWithExpectedSize(dirtyFileExports.size)) { it.key to HashSet(it.value.keys) }
stopwatch.startNext("Processing IR - updating intrinsics and builtins dependencies") stopwatch.startNext("Processing IR - updating intrinsics and builtins dependencies")
updater.updateStdlibIntrinsicDependencies(loadedIr, mainModuleFragment, dirtyFiles) updater.updateStdlibIntrinsicDependencies(loadedIr, mainModuleFragment, dirtyFiles)
@@ -752,12 +759,13 @@ fun rebuildCacheForDirtyFiles(
mainArguments: List<String>?, mainArguments: List<String>?,
es6mode: Boolean es6mode: Boolean
): Pair<IrModuleFragment, List<Pair<IrFile, JsIrProgramFragment>>> { ): Pair<IrModuleFragment, List<Pair<IrFile, JsIrProgramFragment>>> {
val internationService = IrInterningService()
val emptyMetadata = object : KotlinSourceFileExports() { val emptyMetadata = object : KotlinSourceFileExports() {
override val inverseDependencies = KotlinSourceFileMap<Set<IdSignature>>(emptyMap()) override val inverseDependencies = KotlinSourceFileMap<Set<IdSignature>>(emptyMap())
} }
val libFile = KotlinLibraryFile(library) val libFile = KotlinLibraryFile(library)
val dirtySrcFiles = dirtyFiles?.map { KotlinSourceFile(it) } ?: KotlinLoadedLibraryHeader(library).sourceFileFingerprints.keys val dirtySrcFiles = dirtyFiles?.memoryOptimizedMap { KotlinSourceFile(it) } ?: KotlinLoadedLibraryHeader(library, internationService).sourceFileFingerprints.keys
val modifiedFiles = mapOf(libFile to dirtySrcFiles.associateWith { emptyMetadata }) val modifiedFiles = mapOf(libFile to dirtySrcFiles.associateWith { emptyMetadata })
@@ -767,7 +775,7 @@ fun rebuildCacheForDirtyFiles(
val currentIrModule = loadedIr.loadedFragments[libFile] ?: notFoundIcError("loaded fragment", libFile) val currentIrModule = loadedIr.loadedFragments[libFile] ?: notFoundIcError("loaded fragment", libFile)
val dirtyIrFiles = dirtyFiles?.let { val dirtyIrFiles = dirtyFiles?.let {
val files = it.toSet() val files = it.toSet()
currentIrModule.files.filter { irFile -> irFile.fileEntry.name in files } currentIrModule.files.memoryOptimizedFilter { irFile -> irFile.fileEntry.name in files }
} ?: currentIrModule.files } ?: currentIrModule.files
val compilerWithIC = JsIrCompilerWithIC( val compilerWithIC = JsIrCompilerWithIC(
@@ -781,8 +789,9 @@ fun rebuildCacheForDirtyFiles(
// Load declarations referenced during `context` initialization // Load declarations referenced during `context` initialization
loadedIr.loadUnboundSymbols() loadedIr.loadUnboundSymbols()
internationService.clear()
val fragments = compilerWithIC.compile(loadedIr.loadedFragments.values, dirtyIrFiles, mainArguments).map { it() } val fragments = compilerWithIC.compile(loadedIr.loadedFragments.values, dirtyIrFiles, mainArguments).memoryOptimizedMap { it() }
return currentIrModule to dirtyIrFiles.zip(fragments) return currentIrModule to dirtyIrFiles.zip(fragments)
} }
@@ -32,13 +32,13 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
private val signatureToIndexMappingFromMetadata = hashMapOf<KotlinSourceFile, MutableMap<IdSignature, Int>>() private val signatureToIndexMappingFromMetadata = hashMapOf<KotlinSourceFile, MutableMap<IdSignature, Int>>()
private val cacheHeaderFromDisk by lazy { private val cacheHeaderFromDisk by lazy(LazyThreadSafetyMode.NONE) {
cacheHeaderFile.useCodedInputIfExists { cacheHeaderFile.useCodedInputIfExists {
CacheHeader.fromProtoStream(this) CacheHeader.fromProtoStream(this)
} }
} }
val libraryFileFromHeader by lazy { cacheHeaderFromDisk?.libraryFile } val libraryFileFromHeader by lazy(LazyThreadSafetyMode.NONE) { cacheHeaderFromDisk?.libraryFile }
private class CacheHeader( private class CacheHeader(
val libraryFile: KotlinLibraryFile, val libraryFile: KotlinLibraryFile,
@@ -149,7 +149,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
private fun fetchSourceFileMetadata(srcFile: KotlinSourceFile, loadSignatures: Boolean) = private fun fetchSourceFileMetadata(srcFile: KotlinSourceFile, loadSignatures: Boolean) =
kotlinLibrarySourceFileMetadata.getOrPut(srcFile) { kotlinLibrarySourceFileMetadata.getOrPut(srcFile) {
val signatureToIndexMapping = signatureToIndexMappingFromMetadata.getOrPut(srcFile) { hashMapOf() } val signatureToIndexMapping = signatureToIndexMappingFromMetadata.getOrPut(srcFile) { hashMapOf() }
val deserializer: IdSignatureDeserializer by lazy { val deserializer: IdSignatureDeserializer by lazy(LazyThreadSafetyMode.NONE) {
library.sourceFileDeserializers[srcFile] ?: notFoundIcError("signature deserializer", library.libraryFile, srcFile) library.sourceFileDeserializers[srcFile] ?: notFoundIcError("signature deserializer", library.libraryFile, srcFile)
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.ic
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrProgramFragment import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrProgramFragment
import org.jetbrains.kotlin.ir.backend.js.utils.serialization.serializeTo import org.jetbrains.kotlin.ir.backend.js.utils.serialization.serializeTo
import org.jetbrains.kotlin.konan.file.use import org.jetbrains.kotlin.konan.file.use
import org.jetbrains.kotlin.utils.newHashSetWithExpectedSize
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.File import java.io.File
@@ -54,7 +55,7 @@ internal class IncrementalCacheArtifact(
private val srcCacheActions: List<SourceFileCacheArtifact>, private val srcCacheActions: List<SourceFileCacheArtifact>,
private val externalModuleName: String? private val externalModuleName: String?
) { ) {
fun getSourceFiles() = srcCacheActions.mapTo(HashSet(srcCacheActions.size)) { it.srcFile } fun getSourceFiles() = srcCacheActions.mapTo(newHashSetWithExpectedSize(srcCacheActions.size)) { it.srcFile }
fun buildModuleArtifactAndCommitCache( fun buildModuleArtifactAndCommitCache(
moduleName: String, moduleName: String,
@@ -73,6 +73,7 @@ internal data class LoadedJsIr(
ExternalDependenciesGenerator(linker.symbolTable, listOf(linker)).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(linker.symbolTable, listOf(linker)).generateUnboundSymbolsAsDependencies()
linker.postProcess(inOrAfterLinkageStep = true) linker.postProcess(inOrAfterLinkageStep = true)
linker.checkNoUnboundSymbols(linker.symbolTable, "at the end of IR linkage process") linker.checkNoUnboundSymbols(linker.symbolTable, "at the end of IR linkage process")
linker.clear()
} }
} }
@@ -23,7 +23,10 @@ internal interface KotlinLibraryHeader {
val jsOutputName: String? val jsOutputName: String?
} }
internal class KotlinLoadedLibraryHeader(private val library: KotlinLibrary) : KotlinLibraryHeader { internal class KotlinLoadedLibraryHeader(
private val library: KotlinLibrary,
private val internationService: IrInterningService
) : KotlinLibraryHeader {
private fun parseFingerprintsFromManifest(): Map<KotlinSourceFile, FingerprintHash>? { private fun parseFingerprintsFromManifest(): Map<KotlinSourceFile, FingerprintHash>? {
val manifestFingerprints = library.serializedIrFileFingerprints?.takeIf { it.size == sourceFiles.size } ?: return null val manifestFingerprints = library.serializedIrFileFingerprints?.takeIf { it.size == sourceFiles.size } ?: return null
return sourceFiles.withIndex().associate { it.value to manifestFingerprints[it.index].fileFingerprint } return sourceFiles.withIndex().associate { it.value to manifestFingerprints[it.index].fileFingerprint }
@@ -31,12 +34,12 @@ internal class KotlinLoadedLibraryHeader(private val library: KotlinLibrary) : K
override val libraryFile: KotlinLibraryFile = KotlinLibraryFile(library) override val libraryFile: KotlinLibraryFile = KotlinLibraryFile(library)
override val libraryFingerprint: FingerprintHash by lazy { override val libraryFingerprint: FingerprintHash by lazy(LazyThreadSafetyMode.NONE) {
val serializedKlib = library.serializedKlibFingerprint ?: SerializedKlibFingerprint(File(libraryFile.path)) val serializedKlib = library.serializedKlibFingerprint ?: SerializedKlibFingerprint(File(libraryFile.path))
serializedKlib.klibFingerprint serializedKlib.klibFingerprint
} }
override val sourceFileDeserializers: Map<KotlinSourceFile, IdSignatureDeserializer> by lazy { override val sourceFileDeserializers: Map<KotlinSourceFile, IdSignatureDeserializer> by lazy(LazyThreadSafetyMode.NONE) {
buildMapUntil(sourceFiles.size) { buildMapUntil(sourceFiles.size) {
val deserializer = IdSignatureDeserializer(IrLibraryFileFromBytes(object : IrLibraryBytesSource() { val deserializer = IdSignatureDeserializer(IrLibraryFileFromBytes(object : IrLibraryBytesSource() {
private fun err(): Nothing = icError("Not supported") private fun err(): Nothing = icError("Not supported")
@@ -46,13 +49,13 @@ internal class KotlinLoadedLibraryHeader(private val library: KotlinLibrary) : K
override fun string(index: Int): ByteArray = library.string(index, it) override fun string(index: Int): ByteArray = library.string(index, it)
override fun body(index: Int): ByteArray = err() override fun body(index: Int): ByteArray = err()
override fun debugInfo(index: Int): ByteArray? = null override fun debugInfo(index: Int): ByteArray? = null
}), null) }), null, internationService)
put(sourceFiles[it], deserializer) put(sourceFiles[it], deserializer)
} }
} }
override val sourceFileFingerprints: Map<KotlinSourceFile, FingerprintHash> by lazy { override val sourceFileFingerprints: Map<KotlinSourceFile, FingerprintHash> by lazy(LazyThreadSafetyMode.NONE) {
parseFingerprintsFromManifest() ?: buildMapUntil(sourceFiles.size) { parseFingerprintsFromManifest() ?: buildMapUntil(sourceFiles.size) {
put(sourceFiles[it], SerializedIrFileFingerprint(library, it).fileFingerprint) put(sourceFiles[it], SerializedIrFileFingerprint(library, it).fileFingerprint)
} }
@@ -61,7 +64,7 @@ internal class KotlinLoadedLibraryHeader(private val library: KotlinLibrary) : K
override val jsOutputName: String? override val jsOutputName: String?
get() = library.jsOutputName get() = library.jsOutputName
private val sourceFiles by lazy { private val sourceFiles by lazy(LazyThreadSafetyMode.NONE) {
val extReg = ExtensionRegistryLite.newInstance() val extReg = ExtensionRegistryLite.newInstance()
Array(library.fileCount()) { Array(library.fileCount()) {
val fileProto = IrFile.parseFrom(library.file(it).codedInputStream, extReg) val fileProto = IrFile.parseFrom(library.file(it).codedInputStream, extReg)
@@ -139,7 +139,7 @@ internal enum class ImportedSignaturesState { UNKNOWN, MODIFIED, NON_MODIFIED }
internal class UpdatedDependenciesMetadata(oldMetadata: KotlinSourceFileMetadata) : KotlinSourceFileMetadata() { internal class UpdatedDependenciesMetadata(oldMetadata: KotlinSourceFileMetadata) : KotlinSourceFileMetadata() {
private val oldInverseDependencies = oldMetadata.inverseDependencies private val oldInverseDependencies = oldMetadata.inverseDependencies
private val newExportedSignatures: Set<IdSignature> by lazy { inverseDependencies.flatSignatures() } private val newExportedSignatures: Set<IdSignature> by lazy(LazyThreadSafetyMode.NONE) { inverseDependencies.flatSignatures() }
var importedSignaturesState = ImportedSignaturesState.UNKNOWN var importedSignaturesState = ImportedSignaturesState.UNKNOWN
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.transformStatement import org.jetbrains.kotlin.ir.transformStatement
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isElseBranch import org.jetbrains.kotlin.ir.util.isElseBranch
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -399,7 +400,7 @@ class BlockDecomposerTransformer(
} }
if (compositeCount == 0) { if (compositeCount == 0) {
val branches = results.map { (cond, res, orig) -> val branches = results.memoryOptimizedMap { (cond, res, orig) ->
when { when {
isElseBranch(orig) -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res) isElseBranch(orig) -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res)
else /* IrBranch */ -> IrBranchImpl(orig.startOffset, orig.endOffset, cond, res) else /* IrBranch */ -> IrBranchImpl(orig.startOffset, orig.endOffset, cond, res)
@@ -509,7 +510,7 @@ class BlockDecomposerTransformer(
val newStatements = mutableListOf<IrStatement>() val newStatements = mutableListOf<IrStatement>()
val arguments = mapArguments(expression.arguments, compositeCount, newStatements) val arguments = mapArguments(expression.arguments, compositeCount, newStatements)
newStatements += expression.run { IrStringConcatenationImpl(startOffset, endOffset, type, arguments.map { it!! }) } newStatements += expression.run { IrStringConcatenationImpl(startOffset, endOffset, type, arguments.memoryOptimizedMap { it!! }) }
return JsIrBuilder.buildComposite(expression.type, newStatements) return JsIrBuilder.buildComposite(expression.type, newStatements)
} }
@@ -710,7 +711,7 @@ class BlockDecomposerTransformer(
val irVar = makeTempVar(aTry.type) val irVar = makeTempVar(aTry.type)
val newTryResult = wrap(aTry.tryResult, irVar) val newTryResult = wrap(aTry.tryResult, irVar)
val newCatches = aTry.catches.map { val newCatches = aTry.catches.memoryOptimizedMap {
val newCatchBody = wrap(it.result, irVar) val newCatchBody = wrap(it.result, irVar)
IrCatchImpl(it.startOffset, it.endOffset, it.catchParameter, newCatchBody) IrCatchImpl(it.startOffset, it.endOffset, it.catchParameter, newCatchBody)
} }
@@ -757,7 +758,7 @@ class BlockDecomposerTransformer(
if (hasComposites) { if (hasComposites) {
val irVar = makeTempVar(expression.type) val irVar = makeTempVar(expression.type)
val newBranches = decomposedResults.map { (branch, condition, result) -> val newBranches = decomposedResults.memoryOptimizedMap { (branch, condition, result) ->
val newResult = wrap(result, irVar) val newResult = wrap(result, irVar)
when { when {
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult) isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
@@ -771,7 +772,7 @@ class BlockDecomposerTransformer(
return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(irVar.symbol))) return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(irVar.symbol)))
} else { } else {
val newBranches = decomposedResults.map { (branch, condition, result) -> val newBranches = decomposedResults.memoryOptimizedMap { (branch, condition, result) ->
when { when {
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result) isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result)
else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, result) else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, result)
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.generateBridges import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -23,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
/** /**
* Constructs bridges for inherited generic functions * Constructs bridges for inherited generic functions
@@ -145,11 +145,10 @@ abstract class BridgesConstruction<T : JsCommonBackendContext>(val context: T) :
val substitutionMap = makeTypeParameterSubstitutionMap(bridge, this) val substitutionMap = makeTypeParameterSubstitutionMap(bridge, this)
copyReceiverParametersFrom(bridge, substitutionMap) copyReceiverParametersFrom(bridge, substitutionMap)
copyValueParametersFrom(bridge, substitutionMap) copyValueParametersFrom(bridge, substitutionMap)
annotations += bridge.annotations annotations = annotations memoryOptimizedPlus bridge.annotations
// the js function signature building process (jsFunctionSignature()) uses dfs throught overriddenSymbols for getting js name, // the js function signature building process (jsFunctionSignature()) uses dfs throught overriddenSymbols for getting js name,
// therefore it is very important to put bridge symbol at the beginning, it allows to get correct js function name // therefore it is very important to put bridge symbol at the beginning, it allows to get correct js function name
overriddenSymbols += bridge.symbol overriddenSymbols = overriddenSymbols memoryOptimizedPlus bridge.symbol memoryOptimizedPlus delegateTo.overriddenSymbols
overriddenSymbols += delegateTo.overriddenSymbols
} }
irFunction.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) { irFunction.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
@@ -179,7 +178,7 @@ abstract class BridgesConstruction<T : JsCommonBackendContext>(val context: T) :
val toTake = valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0 val toTake = valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0
valueParameters.subList(0, toTake).mapIndexed { i, valueParameter -> valueParameters.subList(0, toTake).forEachIndexed { i, valueParameter ->
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type)) call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
} }
@@ -203,7 +202,7 @@ abstract class BridgesConstruction<T : JsCommonBackendContext>(val context: T) :
valueParametersToCopy = bridge.valueParameters.take(varargIndex) valueParametersToCopy = bridge.valueParameters.take(varargIndex)
} }
} }
valueParameters += valueParametersToCopy.map { p -> p.copyTo(this, type = p.type.substitute(substitutionMap)) } valueParameters = valueParameters memoryOptimizedPlus valueParametersToCopy.map { p -> p.copyTo(this, type = p.type.substitute(substitutionMap)) }
} }
abstract fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin abstract fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.utils.memoryOptimizedMapIndexed
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class CallableReferenceLowering(private val context: CommonBackendContext) : BodyLoweringPass { class CallableReferenceLowering(private val context: CommonBackendContext) : BodyLoweringPass {
@@ -270,9 +272,11 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
private fun IrSimpleFunction.createLambdaInvokeMethod() { private fun IrSimpleFunction.createLambdaInvokeMethod() {
annotations = function.annotations annotations = function.annotations
val valueParameterMap = function.explicitParameters.withIndex().associate { (index, param) -> val valueParameterMap = function.explicitParameters
param to param.copyTo(this, index = index) .withIndex()
} .associate { (index, param) ->
param to param.copyTo(this, index = index)
}
valueParameters = valueParameterMap.values.toList() valueParameters = valueParameterMap.values.toList()
body = function.moveBodyTo(this, valueParameterMap) body = function.moveBodyTo(this, valueParameterMap)
} }
@@ -389,7 +393,7 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
val parameterTypes = (reference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type } val parameterTypes = (reference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
val argumentTypes = parameterTypes.dropLast(1) val argumentTypes = parameterTypes.dropLast(1)
valueParameters = argumentTypes.mapIndexed { i, t -> valueParameters = argumentTypes.memoryOptimizedMapIndexed { i, t ->
buildValueParameter(this) { buildValueParameter(this) {
name = Name.identifier("p$i") name = Name.identifier("p$i")
type = t type = t
@@ -432,7 +436,7 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
val getter = nameProperty.addGetter() { val getter = nameProperty.addGetter() {
returnType = stringType returnType = stringType
} }
getter.overriddenSymbols += supperGetter.symbol getter.overriddenSymbols = getter.overriddenSymbols memoryOptimizedPlus supperGetter.symbol
getter.dispatchReceiverParameter = buildValueParameter(getter) { getter.dispatchReceiverParameter = buildValueParameter(getter) {
name = SpecialNames.THIS name = SpecialNames.THIS
type = clazz.defaultType type = clazz.defaultType
@@ -19,8 +19,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isFunction import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.isThrowable import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
@@ -29,22 +29,22 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
private val reflectionSymbols get() = context.reflectionSymbols private val reflectionSymbols get() = context.reflectionSymbols
private val primitiveClassProperties by lazy { private val primitiveClassProperties by lazy(LazyThreadSafetyMode.NONE) {
reflectionSymbols.primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>() reflectionSymbols.primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
} }
private val primitiveClassFunctionClass by lazy { private val primitiveClassFunctionClass by lazy(LazyThreadSafetyMode.NONE) {
reflectionSymbols.primitiveClassesObject.owner.declarations reflectionSymbols.primitiveClassesObject.owner.declarations
.filterIsInstance<IrSimpleFunction>() .findIsInstanceAnd<IrSimpleFunction> { it.name == Name.identifier("functionClass") }!!
.find { it.name == Name.identifier("functionClass") }!!
} }
private fun primitiveClassProperty(name: String) = private fun primitiveClassProperty(name: String) =
primitiveClassProperties.singleOrNull { it.name == Name.identifier(name) }?.getter primitiveClassProperties.singleOrNull { it.name == Name.identifier(name) }?.getter
?: reflectionSymbols.primitiveClassesObject.owner.declarations ?: reflectionSymbols.primitiveClassesObject.owner.declarations
.filterIsInstance<IrSimpleFunction>().single { it.name == Name.special("<get-$name>") } .filterIsInstance<IrSimpleFunction>()
.single { it.name == Name.special("<get-$name>") }
private val finalPrimitiveClasses by lazy { private val finalPrimitiveClasses by lazy(LazyThreadSafetyMode.NONE) {
mapOf( mapOf(
IrType::isBoolean to "booleanClass", IrType::isBoolean to "booleanClass",
IrType::isByte to "byteClass", IrType::isByte to "byteClass",
@@ -67,7 +67,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
} }
} }
private val openPrimitiveClasses by lazy { private val openPrimitiveClasses by lazy(LazyThreadSafetyMode.NONE) {
mapOf( mapOf(
IrType::isAny to "anyClass", IrType::isAny to "anyClass",
IrType::isNumber to "numberClass", IrType::isNumber to "numberClass",
@@ -179,7 +179,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
startOffset = UNDEFINED_OFFSET, startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET,
arrayElementType = context.reflectionSymbols.kTypeClass.defaultType, arrayElementType = context.reflectionSymbols.kTypeClass.defaultType,
arrayElements = type.arguments.map { createKTypeProjection(it, visitedTypeParams) } arrayElements = type.arguments.memoryOptimizedMap { createKTypeProjection(it, visitedTypeParams) }
) )
val isMarkedNullable = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, type.isMarkedNullable()) val isMarkedNullable = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, type.isMarkedNullable())
@@ -225,7 +225,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
startOffset = UNDEFINED_OFFSET, startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET,
arrayElementType = context.reflectionSymbols.kTypeClass.defaultType, arrayElementType = context.reflectionSymbols.kTypeClass.defaultType,
arrayElements = typeParameter.superTypes.map { createKType(it, visitedTypeParams) } arrayElements = typeParameter.superTypes.memoryOptimizedMap { createKType(it, visitedTypeParams) }
) )
val variance = when (typeParameter.variance) { val variance = when (typeParameter.variance) {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
private object SCRIPT_FUNCTION : IrDeclarationOriginImpl("SCRIPT_FUNCTION") private object SCRIPT_FUNCTION : IrDeclarationOriginImpl("SCRIPT_FUNCTION")
@@ -37,12 +38,13 @@ class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweri
val (startOffset, endOffset) = getFunctionBodyOffsets(irScript) val (startOffset, endOffset) = getFunctionBodyOffsets(irScript)
val initializeStatements = irScript.statements val initializeStatements = irScript.statements
.asSequence()
.filterIsInstance<IrProperty>() .filterIsInstance<IrProperty>()
.mapNotNull { it.backingField } .mapNotNull { it.backingField }
.filter { it.initializer != null } .filter { it.initializer != null }
.map { Pair(it, it.initializer!!.expression) } .map { Pair(it, it.initializer!!.expression) }
.onEach { it.first.initializer = null }
initializeStatements.forEach { it.first.initializer = null } .toList()
val initializeScriptFunction = createFunction(irScript, "\$initializeScript\$", context.irBuiltIns.unitType).also { val initializeScriptFunction = createFunction(irScript, "\$initializeScript\$", context.irBuiltIns.unitType).also {
it.body = it.factory.createBlockBody( it.body = it.factory.createBlockBody(
@@ -51,7 +53,7 @@ class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweri
initializeStatements.let { initializeStatements.let {
if (irScript.resultProperty == null || initializeStatements.lastOrNull()?.first?.correspondingPropertySymbol != irScript.resultProperty) it if (irScript.resultProperty == null || initializeStatements.lastOrNull()?.first?.correspondingPropertySymbol != irScript.resultProperty) it
else it.dropLast(1) else it.dropLast(1)
}.map { (field, expression) -> createIrSetField(field, expression) } }.memoryOptimizedMap { (field, expression) -> createIrSetField(field, expression) }
) )
} }
@@ -7,21 +7,28 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.utils.hasStrictSignature import org.jetbrains.kotlin.ir.backend.js.utils.hasStrictSignature
import org.jetbrains.kotlin.ir.builders.irEqeqeqWithoutBox
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irIfThen
import org.jetbrains.kotlin.ir.builders.irSet
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.superClass
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
object ES6_BOX_PARAMETER : IrDeclarationOriginImpl("ES6_BOX_PARAMETER") object ES6_BOX_PARAMETER : IrDeclarationOriginImpl("ES6_BOX_PARAMETER")
object ES6_BOX_PARAMETER_DEFAULT_RESOLUTION : IrStatementOriginImpl("ES6_BOX_PARAMETER_DEFAULT_RESOLUTION") object ES6_BOX_PARAMETER_DEFAULT_RESOLUTION : IrStatementOriginImpl("ES6_BOX_PARAMETER_DEFAULT_RESOLUTION")
@@ -52,7 +59,7 @@ class ES6AddBoxParameterToConstructorsLowering(val context: JsIrBackendContext)
private fun IrConstructor.addBoxParameter() { private fun IrConstructor.addBoxParameter() {
val irClass = parentAsClass val irClass = parentAsClass
val boxParameter = generateBoxParameter(irClass).also { valueParameters += it } val boxParameter = generateBoxParameter(irClass).also { valueParameters = valueParameters memoryOptimizedPlus it }
val body = body as? IrBlockBody ?: return val body = body as? IrBlockBody ?: return
val isBoxUsed = body.replaceThisWithBoxBeforeSuperCall(irClass, boxParameter.symbol) val isBoxUsed = body.replaceThisWithBoxBeforeSuperCall(irClass, boxParameter.symbol)
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedFilterNot
class ES6ConstructorBoxParameterOptimizationLowering(private val context: JsIrBackendContext) : BodyLoweringPass { class ES6ConstructorBoxParameterOptimizationLowering(private val context: JsIrBackendContext) : BodyLoweringPass {
private val IrClass.needsOfBoxParameter by context.mapping.esClassWhichNeedBoxParameters private val IrClass.needsOfBoxParameter by context.mapping.esClassWhichNeedBoxParameters
@@ -36,7 +37,7 @@ class ES6ConstructorBoxParameterOptimizationLowering(private val context: JsIrBa
containerFunction?.isEs6ConstructorReplacement == true && !containerFunction.parentAsClass.requiredToHaveBoxParameter() containerFunction?.isEs6ConstructorReplacement == true && !containerFunction.parentAsClass.requiredToHaveBoxParameter()
if (containerFunction != null && shouldRemoveBoxRelatedDeclarationsAndStatements && irBody is IrBlockBody) { if (containerFunction != null && shouldRemoveBoxRelatedDeclarationsAndStatements && irBody is IrBlockBody) {
containerFunction.valueParameters = containerFunction.valueParameters.filter { !it.isBoxParameter } containerFunction.valueParameters = containerFunction.valueParameters.memoryOptimizedFilterNot { it.isBoxParameter }
} }
irBody.transformChildrenVoid(object : IrElementTransformerVoid() { irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
@@ -23,6 +23,10 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.memoryOptimizedFilterNot
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
object ES6_INIT_CALL : IrStatementOriginImpl("ES6_INIT_CALL") object ES6_INIT_CALL : IrStatementOriginImpl("ES6_INIT_CALL")
object ES6_CONSTRUCTOR_REPLACEMENT : IrDeclarationOriginImpl("ES6_CONSTRUCTOR_REPLACEMENT") object ES6_CONSTRUCTOR_REPLACEMENT : IrDeclarationOriginImpl("ES6_CONSTRUCTOR_REPLACEMENT")
@@ -62,7 +66,7 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTrans
private fun IrConstructor.generateExportedConstructorIfNeed(factoryFunction: IrSimpleFunction): IrConstructor? { private fun IrConstructor.generateExportedConstructorIfNeed(factoryFunction: IrSimpleFunction): IrConstructor? {
return runIf(isExported(context) && isPrimary) { return runIf(isExported(context) && isPrimary) {
apply { apply {
valueParameters = valueParameters.filterNot { it.isBoxParameter } valueParameters = valueParameters.memoryOptimizedFilterNot { it.isBoxParameter }
(body as? IrBlockBody)?.let { (body as? IrBlockBody)?.let {
val selfReplacedConstructorCall = JsIrBuilder.buildCall(factoryFunction.symbol).apply { val selfReplacedConstructorCall = JsIrBuilder.buildCall(factoryFunction.symbol).apply {
valueParameters.forEachIndexed { i, it -> putValueArgument(i, JsIrBuilder.buildGetValue(it.symbol)) } valueParameters.forEachIndexed { i, it -> putValueArgument(i, JsIrBuilder.buildGetValue(it.symbol)) }
@@ -170,9 +174,9 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTrans
transformChildrenVoid(object : ValueRemapper(emptyMap()) { transformChildrenVoid(object : ValueRemapper(emptyMap()) {
override val map: MutableMap<IrValueSymbol, IrValueSymbol> = currentConstructor.valueParameters override val map: MutableMap<IrValueSymbol, IrValueSymbol> = currentConstructor.valueParameters
.zip(constructorReplacement.valueParameters) .asSequence()
.associate { it.first.symbol to it.second.symbol } .zip(constructorReplacement.valueParameters.asSequence())
.toMutableMap() .associateTo(newHashMapWithExpectedSize(currentConstructor.valueParameters.size)) { it.first.symbol to it.second.symbol }
override fun visitReturn(expression: IrReturn): IrExpression { override fun visitReturn(expression: IrReturn): IrExpression {
return if (expression.returnTargetSymbol == currentConstructor.symbol) { return if (expression.returnTargetSymbol == currentConstructor.symbol) {
@@ -208,7 +212,7 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTrans
.apply { .apply {
putValueArgument(0, irClass.getCurrentConstructorReference(constructorReplacement)) putValueArgument(0, irClass.getCurrentConstructorReference(constructorReplacement))
putValueArgument(1, expression.symbol.owner.parentAsClass.jsConstructorReference(context)) putValueArgument(1, expression.symbol.owner.parentAsClass.jsConstructorReference(context))
putValueArgument(2, irAnyArray(expression.valueArguments.map { it ?: context.getVoid() })) putValueArgument(2, irAnyArray(expression.valueArguments.memoryOptimizedMap { it ?: context.getVoid() }))
putValueArgument(3, boxParameterGetter) putValueArgument(3, boxParameterGetter)
} }
constructor.parentAsClass.symbol == context.irBuiltIns.anyClass -> constructor.parentAsClass.symbol == context.irBuiltIns.anyClass ->
@@ -252,6 +256,6 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTrans
private fun IrDeclaration.excludeFromExport() { private fun IrDeclaration.excludeFromExport() {
val jsExportIgnoreClass = context.intrinsics.jsExportIgnoreAnnotationSymbol.owner val jsExportIgnoreClass = context.intrinsics.jsExportIgnoreAnnotationSymbol.owner
val jsExportIgnoreCtor = jsExportIgnoreClass.primaryConstructor ?: return val jsExportIgnoreCtor = jsExportIgnoreClass.primaryConstructor ?: return
annotations += JsIrBuilder.buildConstructorCall(jsExportIgnoreCtor.symbol) annotations = annotations memoryOptimizedPlus JsIrBuilder.buildConstructorCall(jsExportIgnoreCtor.symbol)
} }
} }
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
const val CREATE_EXTERNAL_THIS_CONSTRUCTOR_PARAMETERS = 2 const val CREATE_EXTERNAL_THIS_CONSTRUCTOR_PARAMETERS = 2
@@ -67,8 +68,7 @@ class ES6PrimaryConstructorOptimizationLowering(private val context: JsIrBackend
body.transformChildrenVoid(object : ValueRemapper(emptyMap()) { body.transformChildrenVoid(object : ValueRemapper(emptyMap()) {
override val map = original.valueParameters.zip(constructor.valueParameters) override val map = original.valueParameters.zip(constructor.valueParameters)
.associate { it.first.symbol to it.second.symbol } .associateTo(newHashMapWithExpectedSize<IrValueSymbol, IrValueSymbol>(original.valueParameters.size)) { it.first.symbol to it.second.symbol }
.toMutableMap<IrValueSymbol, IrValueSymbol>()
override fun visitReturn(expression: IrReturn): IrExpression { override fun visitReturn(expression: IrReturn): IrExpression {
return if (expression.returnTargetSymbol == original.symbol) { return if (expression.returnTargetSymbol == original.symbol) {
@@ -12,14 +12,11 @@ import org.jetbrains.kotlin.backend.common.ir.isExpect
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.PRIVATE import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.PRIVATE
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isInstantiableEnum import org.jetbrains.kotlin.ir.backend.js.utils.isInstantiableEnum
import org.jetbrains.kotlin.ir.backend.js.utils.parentEnumClassOrNull import org.jetbrains.kotlin.ir.backend.js.utils.parentEnumClassOrNull
@@ -36,6 +33,9 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.findIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class EnumUsageLowering(val context: JsCommonBackendContext) : BodyLoweringPass { class EnumUsageLowering(val context: JsCommonBackendContext) : BodyLoweringPass {
private var IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun private var IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun
@@ -99,7 +99,7 @@ class EnumClassConstructorLowering(val context: JsCommonBackendContext) : Declar
}.apply { }.apply {
parent = enumClass parent = enumClass
additionalParameters.forEachIndexed { index, (name, type) -> additionalParameters.forEachIndexed { index, (name, type) ->
valueParameters += JsIrBuilder.buildValueParameter(this, name, index, type) valueParameters = valueParameters memoryOptimizedPlus JsIrBuilder.buildValueParameter(this, name, index, type)
} }
copyParameterDeclarationsFrom(enumConstructor) copyParameterDeclarationsFrom(enumConstructor)
@@ -334,7 +334,7 @@ class EnumEntryInstancesBodyLowering(val context: JsCommonBackendContext) : Body
val entryClass = container.constructedClass val entryClass = container.constructedClass
val enum = entryClass.parentAsClass val enum = entryClass.parentAsClass
if (enum.isInstantiableEnum) { if (enum.isInstantiableEnum) {
val entry = enum.declarations.filterIsInstance<IrEnumEntry>().find { it.correspondingClass === entryClass }!! val entry = enum.declarations.findIsInstanceAnd<IrEnumEntry> { it.correspondingClass === entryClass }!!
//In ES6 using `this` before superCall is unavailable, so //In ES6 using `this` before superCall is unavailable, so
//need to find superCall and put `instance = this` after it //need to find superCall and put `instance = this` after it
@@ -476,7 +476,7 @@ class EnumSyntheticFunctionsAndPropertiesLowering(
declaration.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) { declaration.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
statements += context.createIrBuilder(declaration.symbol).irBlockBody { statements += context.createIrBuilder(declaration.symbol).irBlockBody {
+irCall(enumClass.initEntryInstancesFun!!.symbol) +irCall(enumClass.initEntryInstancesFun!!.symbol)
}.statements + originalBody.statements }.statements memoryOptimizedPlus originalBody.statements
} }
} }
} }
@@ -546,7 +546,7 @@ class EnumSyntheticFunctionsAndPropertiesLowering(
irBranch( irBranch(
irEquals(irGet(nameParameter), irString(it.name.identifier)), irReturn(irCall(it.getInstanceFun!!)) irEquals(irGet(nameParameter), irString(it.name.identifier)), irReturn(irCall(it.getInstanceFun!!))
) )
} + irElseBranch(irBlock { } memoryOptimizedPlus irElseBranch(irBlock {
+irCall(irClass.initEntryInstancesFun!!) +irCall(irClass.initEntryInstancesFun!!)
+irCall(throwISESymbol) +irCall(throwISESymbol)
}) })
@@ -561,8 +561,8 @@ class EnumSyntheticFunctionsAndPropertiesLowering(
} }
} }
private fun IrBuilderWithScope.arrayOfEnumEntriesOf(enumClass: IrClass) = private fun IrBuilderWithScope.arrayOfEnumEntriesOf(enumClass: IrClass) =
irVararg(enumClass.defaultType, enumClass.enumEntries.map { irCall(it.getInstanceFun!!) }) irVararg(enumClass.defaultType, enumClass.enumEntries.memoryOptimizedMap { irCall(it.getInstanceFun!!) })
} }
private val IrClass.enumEntries: List<IrEnumEntry> private val IrClass.enumEntries: List<IrEnumEntry>
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
@@ -18,6 +21,7 @@ import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.isPrimitiveArray import org.jetbrains.kotlin.ir.util.isPrimitiveArray
import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBackendContext) : DeclarationTransformer { class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
private val strictImplicitExport = context.configuration.getBoolean(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT) private val strictImplicitExport = context.configuration.getBoolean(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT)
@@ -38,9 +42,11 @@ class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBac
} }
private fun IrClass.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> { private fun IrClass.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
return typeParameters return typeParameters.asSequence()
.flatMap { it.superTypes }.toSet() .flatMap { it.superTypes }
.flatMap { it.collectImplicitlyExportedDeclarations() }.toSet() .distinct()
.flatMap { it.collectImplicitlyExportedDeclarations() }
.toSet()
} }
@@ -85,7 +91,7 @@ class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBac
private fun IrDeclaration.markWithJsImplicitExport() { private fun IrDeclaration.markWithJsImplicitExport() {
val jsImplicitExportCtor = context.intrinsics.jsImplicitExportAnnotationSymbol.constructors.single() val jsImplicitExportCtor = context.intrinsics.jsImplicitExportAnnotationSymbol.constructors.single()
annotations += JsIrBuilder.buildConstructorCall(jsImplicitExportCtor) annotations = annotations memoryOptimizedPlus JsIrBuilder.buildConstructorCall(jsImplicitExportCtor)
parentClassOrNull?.takeIf { it.shouldBeMarkedWithImplicitExport() }?.markWithJsImplicitExport() parentClassOrNull?.takeIf { it.shouldBeMarkedWithImplicitExport() }?.markWithJsImplicitExport()
} }
@@ -32,6 +32,9 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedMapIndexed
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass { class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass {
@@ -112,16 +115,16 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
// Regular contextless lambdas are always transformed to function references // Regular contextless lambdas are always transformed to function references
val ctorToFreeFunctionMap = mutableMapOf<IrConstructorSymbol, IrSimpleFunctionSymbol>() val ctorToFreeFunctionMap = hashMapOf<IrConstructorSymbol, IrSimpleFunctionSymbol>()
// Regular lambdas with captured variables are transformed to function expressions whenever possible. // Regular lambdas with captured variables are transformed to function expressions whenever possible.
// However, we don't do that if the lambda captures a variable declared in a loop, at least when variable // However, we don't do that if the lambda captures a variable declared in a loop, at least when variable
// declarations are lowered into 'var' statements in JS. See the CapturedVariablesDeclaredInLoops class. // declarations are lowered into 'var' statements in JS. See the CapturedVariablesDeclaredInLoops class.
// We also don't do that if there is more than one constructor call for a single lambda. // We also don't do that if there is more than one constructor call for a single lambda.
val ctorToFunctionExpressionMap = mutableMapOf<IrConstructorSymbol, FunctionExpressionFactory>() val ctorToFunctionExpressionMap = hashMapOf<IrConstructorSymbol, FunctionExpressionFactory>()
// Suspend lambdas are transformed to factory calls // Suspend lambdas are transformed to factory calls
val ctorToFactoryMap = mutableMapOf<IrConstructorSymbol, IrSimpleFunctionSymbol>() val ctorToFactoryMap = hashMapOf<IrConstructorSymbol, IrSimpleFunctionSymbol>()
val closureUsageAnalyser = ClosureUsageAnalyser() val closureUsageAnalyser = ClosureUsageAnalyser()
@@ -502,7 +505,7 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
val isSuspendLambda = invokeFun.overriddenSymbols.any { it.owner.isSuspend } val isSuspendLambda = invokeFun.overriddenSymbols.any { it.owner.isSuspend }
fun createOldToNewInvokeParametersMapping(lambdaDeclaration: IrSimpleFunction) = fun createOldToNewInvokeParametersMapping(lambdaDeclaration: IrSimpleFunction) =
invokeFun.valueParameters.associateBy({ it.symbol }, { lambdaDeclaration.valueParameters[it.index].symbol }) invokeFun.valueParameters.associateBy({ it.symbol }) { lambdaDeclaration.valueParameters[it.index].symbol }
fun lambdaInnerClasses() = fun lambdaInnerClasses() =
lambdaClass.declarations.filter { it is IrClass || (it is IrSimpleFunction && it.dispatchReceiverParameter == null) } lambdaClass.declarations.filter { it is IrClass || (it is IrSimpleFunction && it.dispatchReceiverParameter == null) }
@@ -620,7 +623,7 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
lambdaDeclaration.parent = parent lambdaDeclaration.parent = parent
lambdaDeclaration.valueParameters = superInvokeFun.valueParameters.mapIndexed { id, vp -> lambdaDeclaration.valueParameters = superInvokeFun.valueParameters.memoryOptimizedMapIndexed { id, vp ->
val originalValueParameter = invokeFun.valueParameters[id] val originalValueParameter = invokeFun.valueParameters[id]
vp.copyTo( vp.copyTo(
irFunction = lambdaDeclaration, irFunction = lambdaDeclaration,
@@ -652,11 +655,11 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
} }
} }
factoryDeclaration.valueParameters = constructor.valueParameters.map { it.copyTo(factoryDeclaration) } factoryDeclaration.valueParameters = constructor.valueParameters.memoryOptimizedMap { it.copyTo(factoryDeclaration) }
factoryDeclaration.typeParameters = constructor.typeParameters.map { factoryDeclaration.typeParameters = constructor.typeParameters.memoryOptimizedMap {
it.copyToWithoutSuperTypes(factoryDeclaration).also { tp -> it.copyToWithoutSuperTypes(factoryDeclaration).also { tp ->
// TODO: make sure it is done well // TODO: make sure it is done well
tp.superTypes += it.superTypes tp.superTypes = tp.superTypes memoryOptimizedPlus it.superTypes
} }
} }
@@ -70,7 +70,7 @@ class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<J
type = context.irBuiltIns.intType type = context.irBuiltIns.intType
} }
val firstTrailingParameterIndexVar = lazy { val firstTrailingParameterIndexVar = lazy(LazyThreadSafetyMode.NONE) {
irTemporary( irTemporary(
if (numberOfTrailingParameters == 0) if (numberOfTrailingParameters == 0)
getTotalNumberOfArguments getTotalNumberOfArguments
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentStubGenerator
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -24,6 +26,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
DefaultArgumentStubGenerator( DefaultArgumentStubGenerator(
@@ -62,9 +66,9 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
private fun IrFunction.introduceDefaultResolution(): IrFunction { private fun IrFunction.introduceDefaultResolution(): IrFunction {
val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET) val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val variables = mutableMapOf<IrValueParameter, IrValueParameter>() val variables = hashMapOf<IrValueParameter, IrValueParameter>()
valueParameters = valueParameters.map { param -> valueParameters = valueParameters.memoryOptimizedMap { param ->
param.takeIf { it.defaultValue != null } param.takeIf { it.defaultValue != null }
?.copyTo(this, isAssignable = true, origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER) ?.copyTo(this, isAssignable = true, origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER)
?.also { new -> variables[param] = new } ?: param ?.also { new -> variables[param] = new } ?: param
@@ -112,7 +116,7 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
context.additionalExportedDeclarations.add(defaultFunStub) context.additionalExportedDeclarations.add(defaultFunStub)
if (!originalFun.hasAnnotation(JsAnnotations.jsNameFqn)) { if (!originalFun.hasAnnotation(JsAnnotations.jsNameFqn)) {
annotations += originalFun.generateJsNameAnnotationCall() annotations = annotations memoryOptimizedPlus originalFun.generateJsNameAnnotationCall()
} }
} }
} }
@@ -125,7 +129,7 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
} }
originalFun.annotations = irrelevantAnnotations originalFun.annotations = irrelevantAnnotations
defaultFunStub.annotations += exportAnnotations defaultFunStub.annotations = defaultFunStub.annotations memoryOptimizedPlus exportAnnotations
originalFun.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT originalFun.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT
return listOf(originalFun, defaultFunStub) return listOf(originalFun, defaultFunStub)
@@ -135,7 +139,7 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
val ctx = context val ctx = context
val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET) val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val variables = mutableMapOf<IrValueParameter, IrValueDeclaration>().apply { val variables = hashMapOf<IrValueParameter, IrValueDeclaration>().apply {
originalDeclaration.dispatchReceiverParameter?.let { originalDeclaration.dispatchReceiverParameter?.let {
set(it, dispatchReceiverParameter!!) set(it, dispatchReceiverParameter!!)
} }
@@ -11,12 +11,12 @@ import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.backend.js.JsMapping import org.jetbrains.kotlin.ir.backend.js.JsMapping
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder.SYNTHESIZED_DECLARATION import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder.SYNTHESIZED_DECLARATION
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.ir.util.copyTo import org.jetbrains.kotlin.ir.util.copyTo
import org.jetbrains.kotlin.ir.util.copyTypeParametersFrom import org.jetbrains.kotlin.ir.util.copyTypeParametersFrom
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
@@ -98,7 +98,7 @@ class JsInnerClassesSupport(mapping: JsMapping, private val irFactory: IrFactory
newValueParameters += p.copyTo(newConstructor, index = p.index + 1) newValueParameters += p.copyTo(newConstructor, index = p.index + 1)
} }
newConstructor.valueParameters += newValueParameters newConstructor.valueParameters = newConstructor.valueParameters memoryOptimizedPlus newValueParameters
return newConstructor return newConstructor
} }
@@ -54,7 +54,7 @@ class JsReturnableBlockLowering(val context: CommonBackendContext) : BodyLowerin
class JsReturnableBlockTransformer(val context: CommonBackendContext) : IrElementTransformerVoidWithContext() { class JsReturnableBlockTransformer(val context: CommonBackendContext) : IrElementTransformerVoidWithContext() {
private var labelCnt = 0 private var labelCnt = 0
private var map = mutableMapOf<IrReturnableBlockSymbol, IrVariable>() private var map = hashMapOf<IrReturnableBlockSymbol, IrVariable>()
private val unitType = context.irBuiltIns.unitType private val unitType = context.irBuiltIns.unitType
private val unitValue get() = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, unitType, context.irBuiltIns.unitClass) private val unitValue get() = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, unitType, context.irBuiltIns.unitClass)
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.compilationException import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
@@ -15,10 +14,9 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.isChildOf import org.jetbrains.kotlin.name.isChildOf
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
private val BODILESS_BUILTIN_CLASSES = listOf( private val BODILESS_BUILTIN_CLASSES = listOf(
"kotlin.String", "kotlin.String",
@@ -73,10 +71,10 @@ class MoveBodilessDeclarationsToSeparatePlaceLowering(private val context: JsIrB
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? { override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
val irFile = declaration.parent as? IrFile ?: return null val irFile = declaration.parent as? IrFile ?: return null
val externalPackageFragment by lazy { val externalPackageFragment by lazy(LazyThreadSafetyMode.NONE) {
context.externalPackageFragment.getOrPut(irFile.symbol) { context.externalPackageFragment.getOrPut(irFile.symbol) {
IrFileImpl(fileEntry = irFile.fileEntry, fqName = irFile.fqName, symbol = IrFileSymbolImpl(), module = irFile.module).also { IrFileImpl(fileEntry = irFile.fileEntry, fqName = irFile.fqName, symbol = IrFileSymbolImpl(), module = irFile.module).also {
it.annotations += irFile.annotations it.annotations = it.annotations memoryOptimizedPlus irFile.annotations
} }
} }
} }
@@ -14,13 +14,14 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
fun moveOpenClassesToSeparateFiles(moduleFragment: IrModuleFragment) { fun moveOpenClassesToSeparateFiles(moduleFragment: IrModuleFragment) {
fun createFile(file: IrFile, klass: IrClass): IrFile = fun createFile(file: IrFile, klass: IrClass): IrFile =
IrFileImpl(fileEntry = file.fileEntry, fqName = file.fqName, symbol = IrFileSymbolImpl(), module = file.module).also { IrFileImpl(fileEntry = file.fileEntry, fqName = file.fqName, symbol = IrFileSymbolImpl(), module = file.module).also {
it.annotations += file.annotations it.annotations = it.annotations memoryOptimizedPlus file.annotations
it.declarations += klass it.declarations += klass
klass.parent = it klass.parent = it
} }
@@ -55,7 +56,7 @@ fun moveOpenClassesToSeparateFiles(moduleFragment: IrModuleFragment) {
return@transformFlat if (openClasses.isEmpty()) return@transformFlat if (openClasses.isEmpty())
null null
else else
listOf(file) + openClasses.map { createFile(file, it) } openClasses.mapTo(mutableListOf(file)) { createFile(file, it) }
} }
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.isLocal import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
private val STATIC_THIS_PARAMETER = object : IrDeclarationOriginImpl("STATIC_THIS_PARAMETER") {} private val STATIC_THIS_PARAMETER = object : IrDeclarationOriginImpl("STATIC_THIS_PARAMETER") {}
@@ -61,10 +62,11 @@ class PrivateMembersLowering(val context: JsIrBackendContext) : DeclarationTrans
it.parent = function.parent it.parent = function.parent
} }
staticFunction.typeParameters += function.typeParameters.map { it.deepCopyWithSymbols(staticFunction) } staticFunction.typeParameters =
staticFunction.typeParameters memoryOptimizedPlus function.typeParameters.map { it.deepCopyWithSymbols(staticFunction) }
staticFunction.extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(staticFunction) staticFunction.extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(staticFunction)
staticFunction.valueParameters += buildValueParameter(staticFunction) { staticFunction.valueParameters = staticFunction.valueParameters memoryOptimizedPlus buildValueParameter(staticFunction) {
origin = STATIC_THIS_PARAMETER origin = STATIC_THIS_PARAMETER
name = Name.identifier("\$this") name = Name.identifier("\$this")
index = 0 index = 0
@@ -73,7 +75,7 @@ class PrivateMembersLowering(val context: JsIrBackendContext) : DeclarationTrans
function.correspondingStatic = staticFunction function.correspondingStatic = staticFunction
staticFunction.valueParameters += function.valueParameters.map { staticFunction.valueParameters = staticFunction.valueParameters memoryOptimizedPlus function.valueParameters.map {
// TODO better way to avoid copying default value // TODO better way to avoid copying default value
it.copyTo(staticFunction, index = it.index + 1, defaultValue = null) it.copyTo(staticFunction, index = it.index + 1, defaultValue = null)
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
class PropertyReferenceLowering(private val context: JsIrBackendContext) : BodyLoweringPass { class PropertyReferenceLowering(private val context: JsIrBackendContext) : BodyLoweringPass {
@@ -144,7 +145,7 @@ class PropertyReferenceLowering(private val context: JsIrBackendContext) : BodyL
function.parent = factory function.parent = factory
val unboundValueParameters = supperAccessor.valueParameters.map { it.copyTo(function) } val unboundValueParameters = supperAccessor.valueParameters.memoryOptimizedMap { it.copyTo(function) }
function.valueParameters = unboundValueParameters function.valueParameters = unboundValueParameters
val arity = unboundValueParameters.size val arity = unboundValueParameters.size
val total = arity + boundValueParameters.size val total = arity + boundValueParameters.size
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
@@ -17,6 +16,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.utils.memoryOptimizedFilterNot
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -66,7 +66,7 @@ class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLowe
val result = with(super.visitFunctionReference(expression) as IrFunctionReference) { val result = with(super.visitFunctionReference(expression) as IrFunctionReference) {
// TODO do we really need to fix type or removing dispatchReceiver is enough? // TODO do we really need to fix type or removing dispatchReceiver is enough?
val arguments = (type as IrSimpleType).arguments.filterNot(::isScript) val arguments = (type as IrSimpleType).arguments.memoryOptimizedFilterNot(::isScript)
val newN = arguments.size - 1 val newN = arguments.size - 1
IrFunctionReferenceImpl( IrFunctionReferenceImpl(
@@ -103,7 +103,7 @@ class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLowe
val result = with(super.visitPropertyReference(expression) as IrPropertyReference) { val result = with(super.visitPropertyReference(expression) as IrPropertyReference) {
// TODO do we really need to fix type or removing dispatchReceiver is enough? // TODO do we really need to fix type or removing dispatchReceiver is enough?
val arguments = (type as IrSimpleType).arguments.filterNot(::isScript) val arguments = (type as IrSimpleType).arguments.memoryOptimizedFilterNot(::isScript)
val newN = arguments.size - 1 val newN = arguments.size - 1
IrPropertyReferenceImpl( IrPropertyReferenceImpl(
@@ -32,7 +32,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
class SecondaryConstructorLowering(val context: JsIrBackendContext) : DeclarationTransformer { class SecondaryConstructorLowering(val context: JsIrBackendContext) : DeclarationTransformer {
@@ -143,7 +144,9 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio
ThisUsageReplaceTransformer( ThisUsageReplaceTransformer(
constructor.symbol, constructor.symbol,
delegate.symbol, delegate.symbol,
oldValueParameters.zip(delegate.valueParameters).associate { (old, new) -> old.symbol to new.symbol } oldValueParameters
.zip(delegate.valueParameters)
.associate { (old, new) -> old.symbol to new.symbol }
) )
) )
} }
@@ -192,8 +195,8 @@ private fun JsIrBackendContext.buildInitDeclaration(constructor: IrConstructor,
it.parent = constructor.parent it.parent = constructor.parent
it.copyTypeParametersFrom(constructor.parentAsClass) it.copyTypeParametersFrom(constructor.parentAsClass)
it.valueParameters = constructor.valueParameters.map { p -> p.copyTo(it) } it.valueParameters = constructor.valueParameters.memoryOptimizedMap { p -> p.copyTo(it) }
it.valueParameters += JsIrBuilder.buildValueParameter(it, "\$this", constructor.valueParameters.size, type) it.valueParameters = it.valueParameters memoryOptimizedPlus JsIrBuilder.buildValueParameter(it, "\$this", constructor.valueParameters.size, type)
} }
} }
@@ -214,7 +217,7 @@ private fun JsIrBackendContext.buildFactoryDeclaration(constructor: IrConstructo
}.also { factory -> }.also { factory ->
factory.parent = constructor.parent factory.parent = constructor.parent
factory.copyTypeParametersFrom(constructor.parentAsClass) factory.copyTypeParametersFrom(constructor.parentAsClass)
factory.valueParameters += constructor.valueParameters.map { p -> p.copyTo(factory) } factory.valueParameters = factory.valueParameters memoryOptimizedPlus constructor.valueParameters.map { p -> p.copyTo(factory) }
factory.annotations = constructor.annotations factory.annotations = constructor.annotations
} }
} }
@@ -27,6 +27,9 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.findIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
fun generateJsTests(context: JsIrBackendContext, moduleFragment: IrModuleFragment) { fun generateJsTests(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
val generator = TestGenerator(context, false) val generator = TestGenerator(context, false)
@@ -40,6 +43,7 @@ class TestGenerator(val context: JsCommonBackendContext, val groupByPackage: Boo
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
// Additional copy to prevent ConcurrentModificationException // Additional copy to prevent ConcurrentModificationException
if (irFile.declarations.isEmpty()) return
ArrayList(irFile.declarations).forEach { ArrayList(irFile.declarations).forEach {
if (it is IrClass) { if (it is IrClass) {
generateTestCalls(it) { if (groupByPackage) suiteForPackage(irFile) else context.createTestContainerFun(irFile) } generateTestCalls(it) { if (groupByPackage) suiteForPackage(irFile) else context.createTestContainerFun(irFile) }
@@ -49,7 +53,7 @@ class TestGenerator(val context: JsCommonBackendContext, val groupByPackage: Boo
} }
} }
private val packageSuites = mutableMapOf<FqName, IrSimpleFunction>() private val packageSuites = hashMapOf<FqName, IrSimpleFunction>()
private fun suiteForPackage(irFile: IrFile) = packageSuites.getOrPut(irFile.fqName) { private fun suiteForPackage(irFile: IrFile) = packageSuites.getOrPut(irFile.fqName) {
context.suiteFun!!.createInvocation(irFile.fqName.asString(), context.createTestContainerFun(irFile)) context.suiteFun!!.createInvocation(irFile.fqName.asString(), context.createTestContainerFun(irFile))
@@ -84,12 +88,12 @@ class TestGenerator(val context: JsCommonBackendContext, val groupByPackage: Boo
private fun generateTestCalls(irClass: IrClass, parentFunction: () -> IrSimpleFunction) { private fun generateTestCalls(irClass: IrClass, parentFunction: () -> IrSimpleFunction) {
if (irClass.modality == Modality.ABSTRACT || irClass.isEffectivelyExternal() || irClass.isExpect) return if (irClass.modality == Modality.ABSTRACT || irClass.isEffectivelyExternal() || irClass.isExpect) return
val suiteFunBody by lazy { val suiteFunBody by lazy(LazyThreadSafetyMode.NONE) {
context.suiteFun!!.createInvocation(irClass.name.asString(), parentFunction(), irClass.isIgnored) context.suiteFun!!.createInvocation(irClass.name.asString(), parentFunction(), irClass.isIgnored)
} }
val beforeFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>().filter { it.isBefore } val beforeFunctions = irClass.declarations.filterIsInstanceAnd<IrSimpleFunction> { it.isBefore }
val afterFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>().filter { it.isAfter } val afterFunctions = irClass.declarations.filterIsInstanceAnd<IrSimpleFunction> { it.isAfter }
irClass.declarations.forEach { irClass.declarations.forEach {
when { when {
@@ -174,10 +178,7 @@ class TestGenerator(val context: JsCommonBackendContext, val groupByPackage: Boo
if (context is JsIrBackendContext && (testFun.returnType as? IrSimpleType)?.classifier == context.intrinsics.promiseClassSymbol) { if (context is JsIrBackendContext && (testFun.returnType as? IrSimpleType)?.classifier == context.intrinsics.promiseClassSymbol) {
val finally = context.intrinsics.promiseClassSymbol.owner.declarations val finally = context.intrinsics.promiseClassSymbol.owner.declarations
.filterIsInstance<IrSimpleFunction>() .findIsInstanceAnd<IrSimpleFunction> { it.name.asString() == "finally" }!!
.first {
it.name.asString() == "finally"
}
val refType = IrSimpleTypeImpl(context.ir.symbols.functionN(0), false, emptyList(), emptyList()) val refType = IrSimpleTypeImpl(context.ir.symbols.functionN(0), false, emptyList(), emptyList())
@@ -190,7 +191,7 @@ class TestGenerator(val context: JsCommonBackendContext, val groupByPackage: Boo
this.body = context.irFactory.createBlockBody( this.body = context.irFactory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
afterFuns.map { afterFuns.memoryOptimizedMap {
JsIrBuilder.buildCall(it.symbol).apply { JsIrBuilder.buildCall(it.symbol).apply {
dispatchReceiver = JsIrBuilder.buildGetValue(classVal.symbol) dispatchReceiver = JsIrBuilder.buildGetValue(classVal.symbol)
} }
@@ -17,13 +17,14 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.atMostOne
class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : CallsTransformer { class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
private val intrinsics = context.intrinsics private val intrinsics = context.intrinsics
private val irBuiltIns = context.irBuiltIns private val irBuiltIns = context.irBuiltIns
private val icUtils = context.inlineClassesUtils private val icUtils = context.inlineClassesUtils
private val symbolToTransformer: SymbolToTransformer = mutableMapOf() private val symbolToTransformer: SymbolToTransformer = hashMapOf()
init { init {
symbolToTransformer.run { symbolToTransformer.run {
@@ -178,11 +179,10 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
private fun IrType.findEqualsMethod(): IrSimpleFunction? { private fun IrType.findEqualsMethod(): IrSimpleFunction? {
val klass = getClass() ?: return null val klass = getClass() ?: return null
if (klass.isEnumClass && klass.isExternal) return null if (klass.isEnumClass && klass.isExternal) return null
return klass.declarations return klass.declarations.asSequence()
.filterIsInstance<IrSimpleFunction>() .filterIsInstance<IrSimpleFunction>()
.filter { it.isEqualsInheritedFromAny() && !it.isFakeOverriddenFromAny() } .filter { it.isEqualsInheritedFromAny() && !it.isFakeOverriddenFromAny() }
.also { assert(it.size <= 1) } .atMostOne()
.singleOrNull()
} }
private fun IrFunction.isMethodOfPrimitiveJSType() = private fun IrFunction.isMethodOfPrimitiveJSType() =
@@ -23,7 +23,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression> private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression>
init { init {
nameToTransformer = mutableMapOf() nameToTransformer = hashMapOf()
nameToTransformer.run { nameToTransformer.run {
put(Name.identifier("toString")) { call -> put(Name.identifier("toString")) { call ->
if (shouldReplaceToStringWithRuntimeCall(call)) { if (shouldReplaceToStringWithRuntimeCall(call)) {
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.util.irCall
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.ir.util.getSimpleFunction
class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendContext) : CallsTransformer { class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendContext) : CallsTransformer {
private val intrinsics = context.intrinsics private val intrinsics = context.intrinsics
private val symbolToTransformer: SymbolToTransformer = mutableMapOf() private val symbolToTransformer: SymbolToTransformer = hashMapOf()
init { init {
symbolToTransformer.run { symbolToTransformer.run {
@@ -82,7 +82,7 @@ private val IrClassSymbol.iterator
get() = getSimpleFunction("iterator")!! get() = getSimpleFunction("iterator")!!
private val IrClassSymbol.sizeConstructor private val IrClassSymbol.sizeConstructor
get() = owner.declarations.filterIsInstance<IrConstructor>().first { it.valueParameters.size == 1 }.symbol get() = owner.declarations.asSequence().filterIsInstance<IrConstructor>().first { it.valueParameters.size == 1 }.symbol
private val IrClassSymbol.lengthProperty private val IrClassSymbol.lengthProperty
get() = getPropertyGetter("length")!! get() = getPropertyGetter("length")!!
@@ -30,7 +30,7 @@ class ReflectionCallsTransformer(private val context: JsIrBackendContext) : Call
} }
init { init {
nameToTransformer = mutableMapOf() nameToTransformer = hashMapOf()
nameToTransformer.run { nameToTransformer.run {
addWithPredicate( addWithPredicate(
Name.special(Namer.KCALLABLE_GET_NAME), Name.special(Namer.KCALLABLE_GET_NAME),
@@ -63,20 +63,16 @@ private class CodeCleaner : IrElementVisitorVoid {
private fun IrStatementContainer.cleanUpStatements() { private fun IrStatementContainer.cleanUpStatements() {
var unreachable = false var unreachable = false
val newStatements = statements.filter { statements.removeIf {
when { when {
unreachable -> false unreachable -> true
it is IrExpression && it.isPure(true) -> false it is IrExpression && it.isPure(true) -> true
else -> { else -> {
unreachable = it.doesNotReturn() unreachable = it.doesNotReturn()
true false
} }
} }
} }
statements.clear()
statements += newStatements
} }
// Checks if it is safe to assume the statement doesn't return (e.g. throws an exception or loops infinitely) // Checks if it is safe to assume the statement doesn't return (e.g. throws an exception or loops infinitely)
@@ -33,6 +33,9 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedMapIndexed
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val context: C) : BodyLoweringPass { abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val context: C) : BodyLoweringPass {
@@ -61,7 +64,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
protected open fun IrBuilderWithScope.generateDelegatedCall(expectedType: IrType, delegatingCall: IrExpression): IrExpression = protected open fun IrBuilderWithScope.generateDelegatedCall(expectedType: IrType, delegatingCall: IrExpression): IrExpression =
delegatingCall delegatingCall
private val builtCoroutines = mutableMapOf<IrFunction, BuiltCoroutine>() private val builtCoroutines = hashMapOf<IrFunction, BuiltCoroutine>()
override fun lower(irBody: IrBody, container: IrDeclaration) { override fun lower(irBody: IrBody, container: IrDeclaration) {
if (container is IrSimpleFunction && container.isSuspend) { if (container is IrSimpleFunction && container.isSuspend) {
@@ -153,7 +156,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
private fun IrBlockBodyBuilder.createCoroutineInstance(function: IrSimpleFunction, parameters: Collection<IrValueParameter>, coroutine: BuiltCoroutine): IrExpression { private fun IrBlockBodyBuilder.createCoroutineInstance(function: IrSimpleFunction, parameters: Collection<IrValueParameter>, coroutine: BuiltCoroutine): IrExpression {
val constructor = coroutine.coroutineConstructor val constructor = coroutine.coroutineConstructor
val coroutineTypeArgs = function.typeParameters.map { val coroutineTypeArgs = function.typeParameters.memoryOptimizedMap {
IrSimpleTypeImpl(it.symbol, true, emptyList(), emptyList()) IrSimpleTypeImpl(it.symbol, true, emptyList(), emptyList())
} }
@@ -207,7 +210,8 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
private val continuationType = continuationClassSymbol.typeWith(function.returnType) private val continuationType = continuationClassSymbol.typeWith(function.returnType)
// Save all arguments to fields. // Save all arguments to fields.
private val argumentToPropertiesMap = functionParameters.associateWith { coroutineClass.addField(it.name, it.type, false) } private val argumentToPropertiesMap = functionParameters
.associateWith { coroutineClass.addField(it.name, it.type, false) }
private val coroutineBaseClass = getCoroutineBaseClass(function) private val coroutineBaseClass = getCoroutineBaseClass(function)
private val coroutineBaseClassConstructor = coroutineBaseClass.owner.constructors.single { it.valueParameters.size == 1 } private val coroutineBaseClassConstructor = coroutineBaseClass.owner.constructors.single { it.valueParameters.size == 1 }
@@ -228,17 +232,20 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
}.apply { }.apply {
parent = function.parent parent = function.parent
createParameterDeclarations() createParameterDeclarations()
typeParameters = function.typeParameters.map { typeParam -> typeParameters = function.typeParameters.memoryOptimizedMap { typeParam ->
// TODO: remap types // TODO: remap types
typeParam.copyToWithoutSuperTypes(this).apply { superTypes += typeParam.superTypes } typeParam.copyToWithoutSuperTypes(this).apply { superTypes = superTypes memoryOptimizedPlus typeParam.superTypes }
} }
} }
private fun buildConstructor(): IrConstructor { private fun buildConstructor(): IrConstructor {
if (isSuspendLambda) { if (isSuspendLambda) {
return coroutineClass.declarations.filterIsInstance<IrConstructor>().single().let { return coroutineClass.declarations
context.mapping.capturedConstructors[it] ?: it .filterIsInstance<IrConstructor>()
} .single()
.let {
context.mapping.capturedConstructors[it] ?: it
}
} }
return context.irFactory.buildConstructor { return context.irFactory.buildConstructor {
@@ -251,11 +258,11 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
parent = coroutineClass parent = coroutineClass
coroutineClass.addChild(this) coroutineClass.addChild(this)
valueParameters = functionParameters.mapIndexed { index, parameter -> valueParameters = functionParameters.memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index, defaultValue = null) parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index, defaultValue = null)
} }
val continuationParameter = coroutineBaseClassConstructor.valueParameters[0] val continuationParameter = coroutineBaseClassConstructor.valueParameters[0]
valueParameters += continuationParameter.copyTo( valueParameters = valueParameters memoryOptimizedPlus continuationParameter.copyTo(
this, DECLARATION_ORIGIN_COROUTINE_IMPL, this, DECLARATION_ORIGIN_COROUTINE_IMPL,
index = valueParameters.size, index = valueParameters.size,
startOffset = function.startOffset, startOffset = function.startOffset,
@@ -303,12 +310,12 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
parent = coroutineClass parent = coroutineClass
coroutineClass.addChild(this) coroutineClass.addChild(this)
typeParameters = stateMachineFunction.typeParameters.map { parameter -> typeParameters = stateMachineFunction.typeParameters.memoryOptimizedMap { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL) parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes } .apply { superTypes = superTypes memoryOptimizedPlus parameter.superTypes }
} }
valueParameters = stateMachineFunction.valueParameters.mapIndexed { index, parameter -> valueParameters = stateMachineFunction.valueParameters.memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index) parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
} }
@@ -338,14 +345,14 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
parent = coroutineClass parent = coroutineClass
coroutineClass.addChild(this) coroutineClass.addChild(this)
typeParameters = function.typeParameters.map { parameter -> typeParameters = function.typeParameters.memoryOptimizedMap { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL) parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes } .apply { superTypes = superTypes memoryOptimizedPlus parameter.superTypes }
} }
val unboundArgs = function.valueParameters val unboundArgs = function.valueParameters
val createValueParameters = (unboundArgs + create1CompletionParameter).mapIndexed { index, parameter -> val createValueParameters = (unboundArgs + create1CompletionParameter).memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index) parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
} }
@@ -441,7 +448,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
transformInvokeMethod(createMethod, invokeSuspendMethod) transformInvokeMethod(createMethod, invokeSuspendMethod)
} else { } else {
coroutineClass.superTypes += coroutineBaseClass.defaultType coroutineClass.superTypes = coroutineClass.superTypes memoryOptimizedPlus coroutineBaseClass.defaultType
} }
coroutineClass.addFakeOverrides(context.typeSystem, implementedMembers) coroutineClass.addFakeOverrides(context.typeSystem, implementedMembers)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
class JsSuspendArityStoreLowering(context: JsIrBackendContext) : DeclarationTransformer { class JsSuspendArityStoreLowering(context: JsIrBackendContext) : DeclarationTransformer {
@@ -19,11 +20,8 @@ class JsSuspendArityStoreLowering(context: JsIrBackendContext) : DeclarationTran
if (declaration !is IrClass) return null if (declaration !is IrClass) return null
declaration.declarations declaration.declarations
.filterIsInstance<IrSimpleFunction>() .filterIsInstanceAnd<IrSimpleFunction> { it.isSuspend }
.filter { it.isSuspend } .let { declaration.suspendArityStore = it }
.let {
declaration.suspendArityStore = it
}
return null return null
} }
@@ -179,7 +179,7 @@ class JsSuspendFunctionsLowering(ctx: JsCommonBackendContext) : AbstractSuspendF
val liveLocals = computeLivenessAtSuspensionPoints(functionBody).values.flatten().toSet() val liveLocals = computeLivenessAtSuspensionPoints(functionBody).values.flatten().toSet()
val localToPropertyMap = mutableMapOf<IrValueSymbol, IrFieldSymbol>() val localToPropertyMap = hashMapOf<IrValueSymbol, IrFieldSymbol>()
var localCounter = 0 var localCounter = 0
// TODO: optimize by using the same property for different locals. // TODO: optimize by using the same property for different locals.
liveLocals.forEach { liveLocals.forEach {
@@ -78,7 +78,7 @@ class StateMachineBuilder(
private val setSuspendResultValue: (IrExpression) -> IrStatement private val setSuspendResultValue: (IrExpression) -> IrStatement
) : IrElementVisitorVoid { ) : IrElementVisitorVoid {
private val loopMap = mutableMapOf<IrLoop, LoopBounds>() private val loopMap = hashMapOf<IrLoop, LoopBounds>()
private val unit = context.irBuiltIns.unitType private val unit = context.irBuiltIns.unitType
private val anyN = context.irBuiltIns.anyNType private val anyN = context.irBuiltIns.anyNType
private val nothing = context.irBuiltIns.nothingType private val nothing = context.irBuiltIns.nothingType
@@ -154,7 +154,7 @@ class StateMachineBuilder(
private var currentBlock = entryState.entryBlock private var currentBlock = entryState.entryBlock
private val catchBlockStack = mutableListOf(rootExceptionTrap) private val catchBlockStack = mutableListOf(rootExceptionTrap)
private val tryStateMap = mutableMapOf<IrExpression, TryState>() private val tryStateMap = hashMapOf<IrExpression, TryState>()
private val tryLoopStack = mutableListOf<IrExpression>() private val tryLoopStack = mutableListOf<IrExpression>()
private fun buildExceptionTrapState(): SuspendState { private fun buildExceptionTrapState(): SuspendState {
@@ -21,6 +21,9 @@ import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.utils.toSmartList
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> { class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> {
@@ -48,7 +51,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitVararg(expression: IrVararg, context: JsGenerationContext): JsExpression { override fun visitVararg(expression: IrVararg, context: JsGenerationContext): JsExpression {
assert(expression.elements.none { it is IrSpreadElement }) assert(expression.elements.none { it is IrSpreadElement })
return JsArrayLiteral(expression.elements.map { it.accept(this, context) }).withSource(expression, context) return JsArrayLiteral(expression.elements.map { it.accept(this, context) }.toSmartList()).withSource(expression, context)
} }
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression = override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression =
@@ -179,7 +182,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
return if (context.staticContext.backendContext.es6mode) { return if (context.staticContext.backendContext.es6mode) {
JsInvocation(JsSuperRef(), arguments) JsInvocation(JsSuperRef(), arguments)
} else { } else {
JsInvocation(callFuncRef, listOf(thisRef) + arguments) JsInvocation(callFuncRef, listOf(thisRef) memoryOptimizedPlus arguments)
}.withSource(expression, context) }.withSource(expression, context)
} }
@@ -301,7 +304,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
IrDynamicOperator.INVOKE -> IrDynamicOperator.INVOKE ->
JsInvocation( JsInvocation(
expression.receiver.accept(this, data), expression.receiver.accept(this, data),
expression.arguments.map { it.accept(this, data) } expression.arguments.memoryOptimizedMap { it.accept(this, data) }
) )
else -> compilationException( else -> compilationException(
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.backend.common.ir.inlineFunction import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.backend.common.ir.innerInlinedBlockOrThis import org.jetbrains.kotlin.backend.common.ir.innerInlinedBlockOrThis
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
import org.jetbrains.kotlin.ir.backend.js.utils.isTheLastReturnStatementIn import org.jetbrains.kotlin.ir.backend.js.utils.isTheLastReturnStatementIn
@@ -17,9 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.util.constructedClassType import org.jetbrains.kotlin.ir.util.constructedClassType
import org.jetbrains.kotlin.ir.util.file import org.jetbrains.kotlin.ir.util.file
@@ -27,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
import org.jetbrains.kotlin.utils.toSmartList
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> { class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> {
@@ -36,7 +34,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
} }
override fun visitBlockBody(body: IrBlockBody, context: JsGenerationContext): JsStatement { override fun visitBlockBody(body: IrBlockBody, context: JsGenerationContext): JsStatement {
return JsBlock(body.statements.map { it.accept(this, context) }).withSource(body, context, container = context.currentFunction) return JsBlock(body.statements.map { it.accept(this, context) }.toSmartList()).withSource(body, context, container = context.currentFunction)
} }
override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsStatement { override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsStatement {
@@ -45,7 +43,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
} ?: context } ?: context
val container = expression.innerInlinedBlockOrThis.statements val container = expression.innerInlinedBlockOrThis.statements
val statements = container.map { it.accept(this, newContext) } val statements = container.map { it.accept(this, newContext) }.toSmartList()
return if (expression is IrReturnableBlock) { return if (expression is IrReturnableBlock) {
val label = context.getNameForReturnableBlock(expression) val label = context.getNameForReturnableBlock(expression)
@@ -73,7 +71,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
return if (expression.statements.isEmpty()) { return if (expression.statements.isEmpty()) {
JsEmpty JsEmpty
} else { } else {
JsBlock(expression.statements.map { it.accept(this, context) }).withSource(expression, context) JsBlock(expression.statements.map { it.accept(this, context) }.toSmartList()).withSource(expression, context)
} }
} }
@@ -197,7 +195,6 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
} }
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, context: JsGenerationContext): JsStatement { override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, context: JsGenerationContext): JsStatement {
// TODO: implement // TODO: implement
return JsEmpty return JsEmpty
} }
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer
import org.jetbrains.kotlin.js.util.TextOutputImpl import org.jetbrains.kotlin.js.util.TextOutputImpl
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import java.io.File import java.io.File
@@ -128,18 +129,14 @@ class IrModuleToJsTransformer(
private fun doStaticMembersLowering(modules: Iterable<IrModuleFragment>) { private fun doStaticMembersLowering(modules: Iterable<IrModuleFragment>) {
modules.forEach { module -> modules.forEach { module ->
module.files.forEach { module.files.forEach {
it.accept( it.accept(backendContext.keeper, Keeper.KeepData(classInKeep = false, classShouldBeKept = false))
backendContext.keeper,
Keeper.KeepData(
classInKeep = false,
classShouldBeKept = false
)
)
} }
} }
modules.forEach { module -> modules.forEach { module ->
module.files.forEach { StaticMembersLowering(backendContext).lower(it) } module.files.forEach {
StaticMembersLowering(backendContext).lower(it)
}
} }
} }
@@ -213,9 +210,7 @@ class IrModuleToJsTransformer(
JsIrModule( JsIrModule(
data.fragment.safeName, data.fragment.safeName,
data.fragment.externalModuleName(), data.fragment.externalModuleName(),
data.files.map { data.files.map { generateProgramFragment(it, mode.minimizedMemberNames) }
generateProgramFragment(it, mode.minimizedMemberNames)
}
) )
} }
) )
@@ -289,7 +284,7 @@ class IrModuleToJsTransformer(
staticContext.classModels.entries.forEach { (symbol, model) -> staticContext.classModels.entries.forEach { (symbol, model) ->
result.classes[nameGenerator.getNameForClass(symbol.owner)] = result.classes[nameGenerator.getNameForClass(symbol.owner)] =
JsIrIcClassModel(model.superClasses.map { staticContext.getNameForClass(it.owner) }).also { JsIrIcClassModel(model.superClasses.memoryOptimizedMap { staticContext.getNameForClass(it.owner) }).also {
it.preDeclarationBlock.statements += model.preDeclarationBlock.statements it.preDeclarationBlock.statements += model.preDeclarationBlock.statements
it.postDeclarationBlock.statements += model.postDeclarationBlock.statements it.postDeclarationBlock.statements += model.postDeclarationBlock.statements
} }
@@ -22,14 +22,16 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.common.isValidES5Identifier import org.jetbrains.kotlin.js.common.isValidES5Identifier
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.toSmartList
class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationContext) { class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationContext) {
private val className = context.getNameForClass(irClass) private val className = context.getNameForClass(irClass)
private val classNameRef = className.makeRef() private val classNameRef = className.makeRef()
private val baseClass: IrType? = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface } private val baseClass: IrType? = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface }
private val classPrototypeRef by lazy { prototypeOf(classNameRef, context.staticContext) } private val classPrototypeRef by lazy(LazyThreadSafetyMode.NONE) { prototypeOf(classNameRef, context.staticContext) }
private val baseClassRef by lazy { // Lazy in case was not collected by namer during JsClassGenerator construction private val baseClassRef by lazy(LazyThreadSafetyMode.NONE) { // Lazy in case was not collected by namer during JsClassGenerator construction
if (baseClass != null && !baseClass.isAny()) baseClass.getClassRef(context) else null if (baseClass != null && !baseClass.isAny()) baseClass.getClassRef(context) else null
} }
private val classBlock = JsCompositeBlock() private val classBlock = JsCompositeBlock()
@@ -337,7 +339,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
JsNameRef(context.getNameForStaticFunction(setMetadataFor)), JsNameRef(context.getNameForStaticFunction(setMetadataFor)),
listOf(ctor, name, metadataConstructor, parent, interfaces, associatedObjectKey, associatedObjects, suspendArity) listOf(ctor, name, metadataConstructor, parent, interfaces, associatedObjectKey, associatedObjects, suspendArity)
.dropLastWhile { it == null } .dropLastWhile { it == null }
.map { it ?: undefined } .memoryOptimizedMap { it ?: undefined }
).makeStmt() ).makeStmt()
} }
@@ -375,7 +377,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
.takeIf { it.size > 1 || it.singleOrNull() != baseClass } .takeIf { it.size > 1 || it.singleOrNull() != baseClass }
?.mapNotNull { it.asConstructorRef() } ?.mapNotNull { it.asConstructorRef() }
?.takeIf { it.isNotEmpty() } ?: return null ?.takeIf { it.isNotEmpty() } ?: return null
return JsArrayLiteral(listRef) return JsArrayLiteral(listRef.toSmartList())
} }
private fun generateSuspendArity(): JsArrayLiteral? { private fun generateSuspendArity(): JsArrayLiteral? {
@@ -385,7 +387,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
.distinct() .distinct()
.map { JsIntLiteral(it) } .map { JsIntLiteral(it) }
return JsArrayLiteral(arity).takeIf { arity.isNotEmpty() } return JsArrayLiteral(arity.toSmartList()).takeIf { arity.isNotEmpty() }
} }
private fun generateAssociatedObjectKey(): JsIntLiteral? { private fun generateAssociatedObjectKey(): JsIntLiteral? {
@@ -402,7 +404,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
} }
} }
} }
} }.toSmartList()
return associatedObjects return associatedObjects
.takeIf { it.isNotEmpty() } .takeIf { it.isNotEmpty() }
@@ -466,7 +468,7 @@ private fun IrOverridableDeclaration<*>.overridesExternal(): Boolean {
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
class JsIrClassModel(val klass: IrClass) { class JsIrClassModel(val klass: IrClass) {
val superClasses = klass.superTypes.map { it.classifierOrNull as IrClassSymbol } val superClasses = klass.superTypes.memoryOptimizedMap { it.classifierOrNull as IrClassSymbol }
val preDeclarationBlock = JsCompositeBlock() val preDeclarationBlock = JsCompositeBlock()
val postDeclarationBlock = JsCompositeBlock() val postDeclarationBlock = JsCompositeBlock()
@@ -33,7 +33,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
init { init {
val intrinsics = backendContext.intrinsics val intrinsics = backendContext.intrinsics
transformers = mutableMapOf() transformers = hashMapOf()
transformers.apply { transformers.apply {
binOp(intrinsics.jsEqeqeq, JsBinaryOperator.REF_EQ) binOp(intrinsics.jsEqeqeq, JsBinaryOperator.REF_EQ)
@@ -67,7 +67,7 @@ class JsIrModuleHeader(
val hasJsExports: Boolean, val hasJsExports: Boolean,
var associatedModule: JsIrModule? var associatedModule: JsIrModule?
) { ) {
val externalNames: Set<String> by lazy { nameBindings.keys - definitions } val externalNames: Set<String> by lazy(LazyThreadSafetyMode.NONE) { nameBindings.keys - definitions }
} }
class JsIrProgram(private var modules: List<JsIrModule>) { class JsIrProgram(private var modules: List<JsIrModule>) {
@@ -154,14 +154,14 @@ class SwitchOptimizer(
lastStatement lastStatement
} else { } else {
val jsBody = case.body.accept(stmtTransformer, context).asBlock() val jsBody = case.body.accept(stmtTransformer, context).asBlock()
var lastStatement = jsBody.statements.lastOrNull() val lastStatement = jsBody.statements.lastOrNull()?.let { lastStatementTransformer { it } }
if (lastStatement != null) {
lastStatement = lastStatementTransformer { lastStatement!! }
jsBody.statements[jsBody.statements.lastIndex] = lastStatement
}
jsCase.statements += jsBody.statements jsCase.statements += jsBody.statements
if (lastStatement != null) {
jsCase.statements[jsCase.statements.lastIndex] = lastStatement
}
lastStatement lastStatement
} }
@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.js.config.SourceMapNamesPolicy
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import java.io.FileInputStream import java.io.FileInputStream
import java.io.IOException import java.io.IOException
import java.io.InputStreamReader import java.io.InputStreamReader
@@ -85,18 +87,18 @@ fun objectCreate(prototype: JsExpression, context: JsStaticContext) =
prototype prototype
) )
fun defineProperty(obj: JsExpression, name: String, getter: JsExpression?, setter: JsExpression?, context: JsStaticContext) = fun defineProperty(obj: JsExpression, name: String, getter: JsExpression?, setter: JsExpression?, context: JsStaticContext): JsExpression {
JsInvocation( val undefined by lazy(LazyThreadSafetyMode.NONE) { jsUndefined(context, context.backendContext) }
return JsInvocation(
context context
.getNameForStaticFunction(context.backendContext.intrinsics.jsDefinePropertySymbol.owner) .getNameForStaticFunction(context.backendContext.intrinsics.jsDefinePropertySymbol.owner)
.makeRef(), .makeRef(),
obj, obj,
JsStringLiteral(name), JsStringLiteral(name),
*listOf(getter, setter) getter ?: undefined,
.dropLastWhile { it == null } setter ?: undefined
.map { it ?: jsUndefined(context, context.backendContext) }
.toTypedArray()
) )
}
fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerationContext): JsFunction { fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerationContext): JsFunction {
context.staticContext.backendContext.getJsCodeForFunction(declaration.symbol)?.let { function -> context.staticContext.backendContext.getJsCodeForFunction(declaration.symbol)?.let { function ->
@@ -212,7 +214,7 @@ fun translateCall(
JsNameRef(Namer.CALL_FUNCTION, qPrototype) JsNameRef(Namer.CALL_FUNCTION, qPrototype)
} }
return JsInvocation(callRef, jsDispatchReceiver?.let { receiver -> listOf(receiver) + arguments } ?: arguments) return JsInvocation(callRef, jsDispatchReceiver?.let { receiver -> listOf(receiver) memoryOptimizedPlus arguments } ?: arguments)
} }
val varargParameterIndex = function.varargParameterIndex() val varargParameterIndex = function.varargParameterIndex()
@@ -291,7 +293,7 @@ fun translateCall(
} }
} }
} else { } else {
JsInvocation(ref, listOfNotNull(jsExtensionReceiver) + arguments).pureIfPossible(function, context) JsInvocation(ref, listOfNotNull(jsExtensionReceiver) memoryOptimizedPlus arguments).pureIfPossible(function, context)
} }
} }
@@ -392,37 +394,36 @@ fun translateCallArguments(
val varargParameterIndex = function.realOverrideTarget.varargParameterIndex() val varargParameterIndex = function.realOverrideTarget.varargParameterIndex()
val validWithNullArgs = expression.validWithNullArgs() val validWithNullArgs = expression.validWithNullArgs()
val arguments = (0 until size) val jsUndefined by lazy(LazyThreadSafetyMode.NONE) { jsUndefined(context, context.staticContext.backendContext) }
.mapTo(ArrayList(size)) { index ->
expression.getValueArgument(index).checkOnNullability(
validWithNullArgs || function.valueParameters[index].isBoxParameter
)
}
.dropLastWhile {
allowDropTailVoids &&
it is IrGetField &&
it.symbol.owner.correspondingPropertySymbol == context.staticContext.backendContext.intrinsics.void
}
.map {
it?.accept(transformer, context)
}
.mapIndexed { index, result ->
val isEmptyExternalVararg = validWithNullArgs &&
varargParameterIndex == index &&
result is JsArrayLiteral &&
result.expressions.isEmpty()
if (isEmptyExternalVararg && index == size - 1) { val arguments = (0 until size)
null .mapIndexedTo(ArrayList(size)) { i, _ ->
} else result expression.getValueArgument(i).checkOnNullability(validWithNullArgs || function.valueParameters[i].isBoxParameter)
}
.mapIndexed { i, it ->
val jsArgument = when {
allowDropTailVoids && (it == null || it.isVoidGetter(context)) -> null
else -> it?.accept(transformer, context)
}
val isEmptyExternalVararg = validWithNullArgs &&
varargParameterIndex == i &&
jsArgument is JsArrayLiteral &&
jsArgument.expressions.isEmpty()
jsArgument.takeIf { !isEmptyExternalVararg || i != size - 1 }
} }
.dropLastWhile { it == null } .dropLastWhile { it == null }
.map { it ?: jsUndefined(context, context.staticContext.backendContext) } .memoryOptimizedMap { it ?: jsUndefined }
check(!expression.symbol.isSuspend) { "Suspend functions should be lowered" } check(!expression.symbol.isSuspend) { "Suspend functions should be lowered" }
return arguments return arguments
} }
private fun IrExpression.isVoidGetter(context: JsGenerationContext): Boolean = this is IrGetField &&
symbol.owner.correspondingPropertySymbol == context.staticContext.backendContext.intrinsics.void
private fun IrExpression?.checkOnNullability(validWithNullArgs: Boolean) = private fun IrExpression?.checkOnNullability(validWithNullArgs: Boolean) =
also { also {
if (it == null) { if (it == null) {
@@ -24,7 +24,7 @@ fun JsNode.resolveTemporaryNames() {
private fun JsNode.resolveNames(): Map<JsName, JsName> { private fun JsNode.resolveNames(): Map<JsName, JsName> {
val rootScope = computeScopes().liftUsedNames() val rootScope = computeScopes().liftUsedNames()
val replacements = mutableMapOf<JsName, JsName>() val replacements = hashMapOf<JsName, JsName>()
fun traverse(scope: Scope) { fun traverse(scope: Scope) {
// Don't clash with non-temporary names declared in current scope. It's for rare cases like `_` or `Kotlin` names, // Don't clash with non-temporary names declared in current scope. It's for rare cases like `_` or `Kotlin` names,
// since most of local declarations are temporary. // since most of local declarations are temporary.
@@ -37,7 +37,7 @@ private fun JsNode.resolveNames(): Map<JsName, JsName> {
// Outer `foo` resolves first, so when traversing inner scope, we should take it into account. // Outer `foo` resolves first, so when traversing inner scope, we should take it into account.
occupiedNames += scope.usedNames.asSequence().mapNotNull { if (!it.isTemporary) it.ident else replacements[it]?.ident } occupiedNames += scope.usedNames.asSequence().mapNotNull { if (!it.isTemporary) it.ident else replacements[it]?.ident }
val nextSuffix = mutableMapOf<String, Int>() val nextSuffix = hashMapOf<String, Int>()
for (temporaryName in scope.declaredNames.asSequence().filter { it.isTemporary }) { for (temporaryName in scope.declaredNames.asSequence().filter { it.isTemporary }) {
var resolvedName = temporaryName.ident var resolvedName = temporaryName.ident
var suffix = nextSuffix.getOrDefault(temporaryName.ident, 0) var suffix = nextSuffix.getOrDefault(temporaryName.ident, 0)
@@ -74,7 +74,7 @@ abstract class IrNamerBase : IrNamer {
} }
} }
private val associatedObjectKeyMap = mutableMapOf<IrClass, Int>() private val associatedObjectKeyMap = hashMapOf<IrClass, Int>()
override fun getAssociatedObjectKey(irClass: IrClass): Int? { override fun getAssociatedObjectKey(irClass: IrClass): Int? {
if (irClass.isAssociatedObjectAnnotatedAnnotation) { if (irClass.isAssociatedObjectAnnotatedAnnotation) {
@@ -31,11 +31,11 @@ class JsGenerationContext(
val currentFunction: IrFunction?, val currentFunction: IrFunction?,
val staticContext: JsStaticContext, val staticContext: JsStaticContext,
val localNames: LocalNameGenerator? = null, val localNames: LocalNameGenerator? = null,
private val nameCache: MutableMap<IrElement, JsName> = mutableMapOf(), private val nameCache: MutableMap<IrElement, JsName> = hashMapOf(),
private val useBareParameterNames: Boolean = false, private val useBareParameterNames: Boolean = false,
) : IrNamer by staticContext { ) : IrNamer by staticContext {
private val startLocationCache = mutableMapOf<Int, JsLocation>() private val startLocationCache = hashMapOf<Int, JsLocation>()
private val endLocationCache = mutableMapOf<Int, JsLocation>() private val endLocationCache = hashMapOf<Int, JsLocation>()
fun newFile(file: IrFile, func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext { fun newFile(file: IrFile, func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext {
return JsGenerationContext( return JsGenerationContext(
@@ -54,7 +54,7 @@ abstract class NameScope {
class NameTable<T>( class NameTable<T>(
val parent: NameScope = EmptyScope, val parent: NameScope = EmptyScope,
val reserved: MutableSet<String> = mutableSetOf(), val reserved: MutableSet<String> = mutableSetOf(),
val mappedNames: MutableMap<String, String>? = null val mappedNames: MutableMap<String, String>? = null,
) : NameScope() { ) : NameScope() {
val names = mutableMapOf<T, String>() val names = mutableMapOf<T, String>()
@@ -153,13 +153,10 @@ fun calculateJsFunctionSignature(declaration: IrFunction, context: JsIrBackendCo
// TODO: Use better hashCode // TODO: Use better hashCode
val sanitizedName = sanitizeName(declarationName, withHash = false) val sanitizedName = sanitizeName(declarationName, withHash = false)
return "${sanitizedName}_$signature$RESERVED_MEMBER_NAME_SUFFIX".intern() return context.globalInternationService.string("${sanitizedName}_$signature$RESERVED_MEMBER_NAME_SUFFIX")
} }
fun jsFunctionSignature( fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): String {
declaration: IrFunction,
context: JsIrBackendContext
): String {
require(!declaration.isStaticMethodOfClass) require(!declaration.isStaticMethodOfClass)
require(declaration.dispatchReceiverParameter != null) require(declaration.dispatchReceiverParameter != null)
@@ -262,6 +262,7 @@ open class JvmIrCodegenFactory(
) )
irLinker.postProcess(inOrAfterLinkageStep = true) irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.clear()
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
@@ -75,6 +75,7 @@ fun compileToLoweredIr(
irLinker.postProcess(inOrAfterLinkageStep = true) irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process") irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
irLinker.clear()
for (module in allModules) for (module in allModules)
for (file in module.files) for (file in module.files)
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class IrAbstractDescriptorBasedFunctionFactory { abstract class IrAbstractDescriptorBasedFunctionFactory {
@@ -332,7 +334,7 @@ class IrDescriptorBasedFunctionFactory(
classifier = classifier =
symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType")) symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType"))
nullability = SimpleTypeNullability.fromHasQuestionMark(kotlinType.isMarkedNullable) nullability = SimpleTypeNullability.fromHasQuestionMark(kotlinType.isMarkedNullable)
arguments = kotlinType.arguments.map { arguments = kotlinType.arguments.memoryOptimizedMap {
if (it.isStarProjection) IrStarProjectionImpl if (it.isStarProjection) IrStarProjectionImpl
else makeTypeProjection(toIrType(it.type), it.projectionKind) else makeTypeProjection(toIrType(it.type), it.projectionKind)
} }
@@ -352,10 +354,11 @@ class IrDescriptorBasedFunctionFactory(
private fun IrClass.addFakeOverrides() { private fun IrClass.addFakeOverrides() {
val fakeOverrideDescriptors = val fakeOverrideDescriptors =
descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES).asSequence() descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
.filterIsInstance<CallableMemberDescriptor>() .filterIsInstanceAnd<CallableMemberDescriptor> {
.filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE && it.dispatchReceiverParameter != null } it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE && it.dispatchReceiverParameter != null &&
.filter { !DescriptorVisibilities.isPrivate(it.visibility) && it.visibility != DescriptorVisibilities.INVISIBLE_FAKE } !DescriptorVisibilities.isPrivate(it.visibility) && it.visibility != DescriptorVisibilities.INVISIBLE_FAKE
}
fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction { fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction {
val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor") val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor")
@@ -369,11 +372,11 @@ class IrDescriptorBasedFunctionFactory(
} }
newFunction.parent = this newFunction.parent = this
newFunction.overriddenSymbols = descriptor.overriddenDescriptors.map { symbolTable.referenceSimpleFunction(it.original) } newFunction.overriddenSymbols = descriptor.overriddenDescriptors.memoryOptimizedMap { symbolTable.referenceSimpleFunction(it.original) }
newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) } newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) } newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) }
newFunction.contextReceiverParametersCount = descriptor.contextReceiverParameters.size newFunction.contextReceiverParametersCount = descriptor.contextReceiverParameters.size
newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) } newFunction.valueParameters = descriptor.valueParameters.memoryOptimizedMap { newFunction.createValueParameter(it) }
newFunction.correspondingPropertySymbol = property newFunction.correspondingPropertySymbol = property
newFunction.annotations = descriptor.annotations.mapNotNull( newFunction.annotations = descriptor.annotations.mapNotNull(
typeTranslator.constantValueGenerator::generateAnnotationConstructorCall typeTranslator.constantValueGenerator::generateAnnotationConstructorCall
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.withScope import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
@@ -31,6 +31,10 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.error.ErrorUtils import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.findIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedMapIndexed
/* Descriptors that serve purely as a view into IR structures. /* Descriptors that serve purely as a view into IR structures.
Created each time at the borderline between IR-based and descriptor-based code (such as inliner). Created each time at the borderline between IR-based and descriptor-based code (such as inliner).
@@ -41,7 +45,7 @@ import org.jetbrains.kotlin.types.error.ErrorUtils
abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : DeclarationDescriptor { abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : DeclarationDescriptor {
override val annotations: Annotations by lazy { override val annotations: Annotations by lazy {
val ownerAnnotations = (owner as? IrAnnotationContainer)?.annotations ?: return@lazy Annotations.EMPTY val ownerAnnotations = (owner as? IrAnnotationContainer)?.annotations ?: return@lazy Annotations.EMPTY
Annotations.create(ownerAnnotations.map { it.toAnnotationDescriptor() }) Annotations.create(ownerAnnotations.memoryOptimizedMap { it.toAnnotationDescriptor() })
} }
private fun IrConstructorCall.toAnnotationDescriptor(): AnnotationDescriptor { private fun IrConstructorCall.toAnnotationDescriptor(): AnnotationDescriptor {
@@ -60,7 +64,7 @@ abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : D
} }
return AnnotationDescriptorImpl( return AnnotationDescriptorImpl(
annotationClass.defaultType.toIrBasedKotlinType(), annotationClass.defaultType.toIrBasedKotlinType(),
symbol.owner.valueParameters.map { it.name to getValueArgument(it.index) } symbol.owner.valueParameters.memoryOptimizedMap { it.name to getValueArgument(it.index) }
.filter { it.second != null } .filter { it.second != null }
.associate { it.first to it.second!!.toConstantValue() }, .associate { it.first to it.second!!.toConstantValue() },
source source
@@ -83,7 +87,7 @@ abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : D
} }
is IrVararg -> { is IrVararg -> {
val elements = elements.map { if (it is IrSpreadElement) error("$it is not expected") else it.toConstantValue() } val elements = elements.memoryOptimizedMap { if (it is IrSpreadElement) error("$it is not expected") else it.toConstantValue() }
ArrayValue(elements) { moduleDescriptor -> ArrayValue(elements) { moduleDescriptor ->
// TODO: substitute. // TODO: substitute.
moduleDescriptor.builtIns.array.defaultType moduleDescriptor.builtIns.array.defaultType
@@ -263,7 +267,7 @@ open class IrBasedTypeParameterDescriptor(owner: IrTypeParameter) : TypeParamete
override fun getVariance() = owner.variance override fun getVariance() = owner.variance
override fun getUpperBounds() = owner.superTypes.map { it.toIrBasedKotlinType() } override fun getUpperBounds() = owner.superTypes.memoryOptimizedMap { it.toIrBasedKotlinType() }
private val _typeConstructor: TypeConstructor by lazy { private val _typeConstructor: TypeConstructor by lazy {
object : AbstractTypeConstructor(LockBasedStorageManager.NO_LOCKS) { object : AbstractTypeConstructor(LockBasedStorageManager.NO_LOCKS) {
@@ -397,7 +401,7 @@ fun IrLocalDelegatedProperty.toIrBasedDescriptor() = IrBasedVariableDescriptorWi
open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunctionDescriptor, DescriptorWithContainerSource, open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunctionDescriptor, DescriptorWithContainerSource,
IrBasedCallableDescriptor<IrSimpleFunction>(owner) { IrBasedCallableDescriptor<IrSimpleFunction>(owner) {
override fun getOverriddenDescriptors(): List<FunctionDescriptor> = owner.overriddenSymbols.map { it.owner.toIrBasedDescriptor() } override fun getOverriddenDescriptors(): List<FunctionDescriptor> = owner.overriddenSymbols.memoryOptimizedMap { it.owner.toIrBasedDescriptor() }
override fun getModality() = owner.modality override fun getModality() = owner.modality
override fun getName() = owner.name override fun getName() = owner.name
@@ -409,7 +413,7 @@ open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunc
} }
override fun getExtensionReceiverParameter() = owner.extensionReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor override fun getExtensionReceiverParameter() = owner.extensionReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor
override fun getTypeParameters() = owner.typeParameters.map { it.toIrBasedDescriptor() } override fun getTypeParameters() = owner.typeParameters.memoryOptimizedMap { it.toIrBasedDescriptor() }
override fun getValueParameters() = owner.valueParameters override fun getValueParameters() = owner.valueParameters
.asSequence() .asSequence()
.mapNotNull { it.toIrBasedDescriptor() as? ValueParameterDescriptor } .mapNotNull { it.toIrBasedDescriptor() as? ValueParameterDescriptor }
@@ -486,7 +490,7 @@ open class IrBasedClassConstructorDescriptor(owner: IrConstructor) : ClassConstr
} }
override fun getTypeParameters() = override fun getTypeParameters() =
(owner.constructedClass.typeParameters + owner.typeParameters).map { it.toIrBasedDescriptor() } (owner.constructedClass.typeParameters + owner.typeParameters).memoryOptimizedMap { it.toIrBasedDescriptor() }
override fun getValueParameters() = owner.valueParameters.asSequence() override fun getValueParameters() = owner.valueParameters.asSequence()
.mapNotNull { it.toIrBasedDescriptor() as? ValueParameterDescriptor } .mapNotNull { it.toIrBasedDescriptor() as? ValueParameterDescriptor }
@@ -594,7 +598,7 @@ open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDecl
override fun getSource() = owner.source override fun getSource() = owner.source
override fun getConstructors() = override fun getConstructors() =
owner.declarations.filterIsInstance<IrConstructor>().filter { !it.origin.isSynthetic }.map { it.toIrBasedDescriptor() }.toList() owner.declarations.filterIsInstanceAnd<IrConstructor> { !it.origin.isSynthetic }.memoryOptimizedMap { it.toIrBasedDescriptor() }
private val _defaultType: SimpleType by lazy { private val _defaultType: SimpleType by lazy {
TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope, KotlinTypeFactory.EMPTY_REFINED_TYPE_FACTORY) TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope, KotlinTypeFactory.EMPTY_REFINED_TYPE_FACTORY)
@@ -607,7 +611,7 @@ open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDecl
override fun getModality() = owner.modality override fun getModality() = owner.modality
override fun getCompanionObjectDescriptor() = override fun getCompanionObjectDescriptor() =
owner.declarations.filterIsInstance<IrClass>().firstOrNull { it.isCompanion }?.toIrBasedDescriptor() owner.declarations.findIsInstanceAnd<IrClass> { it.isCompanion }?.toIrBasedDescriptor()
override fun getVisibility() = owner.visibility override fun getVisibility() = owner.visibility
@@ -630,7 +634,7 @@ open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDecl
override fun getUnsubstitutedPrimaryConstructor() = override fun getUnsubstitutedPrimaryConstructor() =
owner.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.isPrimary }?.toIrBasedDescriptor() owner.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.isPrimary }?.toIrBasedDescriptor()
override fun getDeclaredTypeParameters() = owner.typeParameters.map { it.toIrBasedDescriptor() } override fun getDeclaredTypeParameters() = owner.typeParameters.memoryOptimizedMap { it.toIrBasedDescriptor() }
override fun getSealedSubclasses(): Collection<ClassDescriptor> { override fun getSealedSubclasses(): Collection<ClassDescriptor> {
TODO("not implemented") TODO("not implemented")
@@ -652,7 +656,7 @@ open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDecl
LazyTypeConstructor( LazyTypeConstructor(
this, this,
::collectTypeParameters, ::collectTypeParameters,
{ owner.superTypes.map { it.toIrBasedKotlinType() } }, { owner.superTypes.memoryOptimizedMap { it.toIrBasedKotlinType() } },
LockBasedStorageManager.NO_LOCKS LockBasedStorageManager.NO_LOCKS
) )
} }
@@ -780,7 +784,7 @@ open class IrBasedEnumEntryDescriptor(owner: IrEnumEntry) : ClassDescriptor, IrB
ClassTypeConstructorImpl( ClassTypeConstructorImpl(
this, this,
emptyList(), emptyList(),
getCorrespondingClass().superTypes.map { it.toIrBasedKotlinType() }, getCorrespondingClass().superTypes.memoryOptimizedMap { it.toIrBasedKotlinType() },
LockBasedStorageManager.NO_LOCKS LockBasedStorageManager.NO_LOCKS
) )
} }
@@ -926,7 +930,7 @@ abstract class IrBasedPropertyAccessorDescriptor(owner: IrSimpleFunction) : IrBa
override fun getOriginal(): IrBasedPropertyAccessorDescriptor = this override fun getOriginal(): IrBasedPropertyAccessorDescriptor = this
override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().map { it as PropertyAccessorDescriptor } override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().memoryOptimizedMap { it as PropertyAccessorDescriptor }
override fun getCorrespondingProperty(): PropertyDescriptor = owner.correspondingPropertySymbol!!.owner.toIrBasedDescriptor() override fun getCorrespondingProperty(): PropertyDescriptor = owner.correspondingPropertySymbol!!.owner.toIrBasedDescriptor()
@@ -934,7 +938,7 @@ abstract class IrBasedPropertyAccessorDescriptor(owner: IrSimpleFunction) : IrBa
} }
open class IrBasedPropertyGetterDescriptor(owner: IrSimpleFunction) : IrBasedPropertyAccessorDescriptor(owner), PropertyGetterDescriptor { open class IrBasedPropertyGetterDescriptor(owner: IrSimpleFunction) : IrBasedPropertyAccessorDescriptor(owner), PropertyGetterDescriptor {
override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().map { it as PropertyGetterDescriptor } override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().memoryOptimizedMap { it as PropertyGetterDescriptor }
override fun getOriginal(): IrBasedPropertyGetterDescriptor = this override fun getOriginal(): IrBasedPropertyGetterDescriptor = this
@@ -943,7 +947,7 @@ open class IrBasedPropertyGetterDescriptor(owner: IrSimpleFunction) : IrBasedPro
} }
open class IrBasedPropertySetterDescriptor(owner: IrSimpleFunction) : IrBasedPropertyAccessorDescriptor(owner), PropertySetterDescriptor { open class IrBasedPropertySetterDescriptor(owner: IrSimpleFunction) : IrBasedPropertyAccessorDescriptor(owner), PropertySetterDescriptor {
override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().map { it as PropertySetterDescriptor } override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().memoryOptimizedMap { it as PropertySetterDescriptor }
override fun getOriginal(): IrBasedPropertySetterDescriptor = this override fun getOriginal(): IrBasedPropertySetterDescriptor = this
@@ -978,7 +982,7 @@ open class IrBasedTypeAliasDescriptor(owner: IrTypeAlias) : IrBasedDeclarationDe
override fun isInner(): Boolean = false override fun isInner(): Boolean = false
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = owner.typeParameters.map { it.toIrBasedDescriptor() } override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = owner.typeParameters.memoryOptimizedMap { it.toIrBasedDescriptor() }
override fun getName(): Name = owner.name override fun getName(): Name = owner.name
@@ -1172,7 +1176,7 @@ private fun makeKotlinType(
classifier.toIrBasedDescriptorIfPossible().defaultType.makeNullableAsSpecified(hasQuestionMark) classifier.toIrBasedDescriptorIfPossible().defaultType.makeNullableAsSpecified(hasQuestionMark)
is IrClassSymbol -> { is IrClassSymbol -> {
val classDescriptor = classifier.toIrBasedDescriptorIfPossible() val classDescriptor = classifier.toIrBasedDescriptorIfPossible()
val kotlinTypeArguments = arguments.mapIndexed { index, it -> val kotlinTypeArguments = arguments.memoryOptimizedMapIndexed { index, it ->
when (it) { when (it) {
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType()) is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType())
is IrStarProjection -> StarProjectionImpl(classDescriptor.typeConstructor.parameters[index]) is IrStarProjection -> StarProjectionImpl(classDescriptor.typeConstructor.parameters[index])
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.utils.SmartList
class IrBlockBodyImpl( class IrBlockBodyImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -33,7 +34,7 @@ class IrBlockBodyImpl(
this.initializer() this.initializer()
} }
override val statements: MutableList<IrStatement> = ArrayList() override val statements: MutableList<IrStatement> = ArrayList(2)
override val factory: IrFactory override val factory: IrFactory
get() = IrFactoryImpl get() = IrFactoryImpl
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
class IrCallImpl( class IrCallImpl(
@@ -38,9 +40,9 @@ class IrCallImpl(
override var superQualifierSymbol: IrClassSymbol? = null override var superQualifierSymbol: IrClassSymbol? = null
) : IrCall() { ) : IrCall() {
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount) override val valueArguments: Array<IrExpression?> = initializeParameterArguments(valueArgumentsCount)
override var contextReceiversCount = 0 override var contextReceiversCount = 0
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
class IrConstructorCallImpl( class IrConstructorCallImpl(
@@ -26,9 +28,9 @@ class IrConstructorCallImpl(
override var origin: IrStatementOrigin? = null, override var origin: IrStatementOrigin? = null,
override var source: SourceElement = SourceElement.NO_SOURCE override var source: SourceElement = SourceElement.NO_SOURCE
) : IrConstructorCall() { ) : IrConstructorCall() {
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount) override val valueArguments: Array<IrExpression?> = initializeParameterArguments(valueArgumentsCount)
override var contextReceiversCount = 0 override var contextReceiversCount = 0
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.ir.expressions.typeParametersCount
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.allTypeParameters import org.jetbrains.kotlin.ir.util.allTypeParameters
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
class IrDelegatingConstructorCallImpl( class IrDelegatingConstructorCallImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -35,9 +37,9 @@ class IrDelegatingConstructorCallImpl(
) : IrDelegatingConstructorCall() { ) : IrDelegatingConstructorCall() {
override var origin: IrStatementOrigin? = null override var origin: IrStatementOrigin? = null
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount) override val valueArguments: Array<IrExpression?> = initializeParameterArguments(valueArgumentsCount)
override var contextReceiversCount = 0 override var contextReceiversCount = 0
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
class IrEnumConstructorCallImpl( class IrEnumConstructorCallImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -33,9 +35,9 @@ class IrEnumConstructorCallImpl(
) : IrEnumConstructorCall() { ) : IrEnumConstructorCall() {
override var origin: IrStatementOrigin? = null override var origin: IrStatementOrigin? = null
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount) override val valueArguments: Array<IrExpression?> = initializeParameterArguments(valueArgumentsCount)
override var contextReceiversCount = 0 override var contextReceiversCount = 0
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
class IrFunctionReferenceImpl( class IrFunctionReferenceImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -33,9 +35,9 @@ class IrFunctionReferenceImpl(
override var reflectionTarget: IrFunctionSymbol? = symbol, override var reflectionTarget: IrFunctionSymbol? = symbol,
override var origin: IrStatementOrigin? = null, override var origin: IrStatementOrigin? = null,
) : IrFunctionReference() { ) : IrFunctionReference() {
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> = arrayOfNulls(valueArgumentsCount) override val valueArguments: Array<IrExpression?> = initializeParameterArguments(valueArgumentsCount)
companion object { companion object {
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
class IrLocalDelegatedPropertyReferenceImpl( class IrLocalDelegatedPropertyReferenceImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -34,14 +36,7 @@ class IrLocalDelegatedPropertyReferenceImpl(
override var setter: IrSimpleFunctionSymbol?, override var setter: IrSimpleFunctionSymbol?,
override var origin: IrStatementOrigin? = null, override var origin: IrStatementOrigin? = null,
) : IrLocalDelegatedPropertyReference() { ) : IrLocalDelegatedPropertyReference() {
override val typeArguments: Array<IrType?> override val typeArguments: Array<IrType?> = initializeTypeArguments(0)
get() = EMPTY_TYPE_ARGUMENTS
override val valueArguments: Array<IrExpression?> override val valueArguments: Array<IrExpression?> = initializeParameterArguments(0)
get() = EMPTY_VALUE_ARGUMENTS
companion object {
private val EMPTY_TYPE_ARGUMENTS = emptyArray<IrType?>()
private val EMPTY_VALUE_ARGUMENTS = emptyArray<IrExpression?>()
}
} }
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.initializeParameterArguments
import org.jetbrains.kotlin.ir.util.initializeTypeArguments
class IrPropertyReferenceImpl( class IrPropertyReferenceImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -35,12 +37,7 @@ class IrPropertyReferenceImpl(
override var setter: IrSimpleFunctionSymbol?, override var setter: IrSimpleFunctionSymbol?,
override var origin: IrStatementOrigin? = null, override var origin: IrStatementOrigin? = null,
) : IrPropertyReference() { ) : IrPropertyReference() {
override val typeArguments: Array<IrType?> = arrayOfNulls(typeArgumentsCount) override val typeArguments: Array<IrType?> = initializeTypeArguments(typeArgumentsCount)
override val valueArguments: Array<IrExpression?> override val valueArguments: Array<IrExpression?> = initializeParameterArguments(0)
get() = EMPTY_VALUE_ARGUMENTS
companion object {
private val EMPTY_VALUE_ARGUMENTS = emptyArray<IrExpression?>()
}
} }
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.utils.SmartList
class IrStringConcatenationImpl( class IrStringConcatenationImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -34,5 +35,5 @@ class IrStringConcatenationImpl(
this.arguments.addAll(arguments) this.arguments.addAll(arguments)
} }
override val arguments: MutableList<IrExpression> = ArrayList() override val arguments: MutableList<IrExpression> = ArrayList(2)
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.utils.SmartList
class IrWhenImpl( class IrWhenImpl(
override val startOffset: Int, override val startOffset: Int,
@@ -35,7 +36,7 @@ class IrWhenImpl(
this.branches.addAll(branches) this.branches.addAll(branches)
} }
override val branches: MutableList<IrBranch> = ArrayList() override val branches: MutableList<IrBranch> = ArrayList(2)
} }
open class IrBranchImpl( open class IrBranchImpl(
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.utils.memoryOptimizedMap
// This is basically modelled after the inliner copier. // This is basically modelled after the inliner copier.
class CopyIrTreeWithSymbolsForFakeOverrides( class CopyIrTreeWithSymbolsForFakeOverrides(
@@ -51,7 +52,7 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
override fun leaveScope() {} override fun leaveScope() {}
private fun remapTypeArguments(arguments: List<IrTypeArgument>) = private fun remapTypeArguments(arguments: List<IrTypeArgument>) =
arguments.map { argument -> arguments.memoryOptimizedMap { argument ->
(argument as? IrTypeProjection)?.let { makeTypeProjection(remapType(it.type), it.variance) } (argument as? IrTypeProjection)?.let { makeTypeProjection(remapType(it.type), it.variance) }
?: argument ?: argument
} }
@@ -66,7 +67,7 @@ class CopyIrTreeWithSymbolsForFakeOverrides(
kotlinType = null kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier) classifier = symbolRemapper.getReferencedClassifier(type.classifier)
arguments = remapTypeArguments(type.arguments) arguments = remapTypeArguments(type.arguments)
annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall } annotations = type.annotations.memoryOptimizedMap { it.transform(copier, null) as IrConstructorCall }
} }
} }
} }
@@ -17,6 +17,9 @@ import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.*
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
abstract class FakeOverrideBuilderStrategy( abstract class FakeOverrideBuilderStrategy(
private val friendModules: Map<String, Collection<String>>, private val friendModules: Map<String, Collection<String>>,
@@ -128,13 +131,13 @@ class IrOverridingUtil(
set(value) { set(value) {
when (this) { when (this) {
is IrSimpleFunction -> this.overriddenSymbols = is IrSimpleFunction -> this.overriddenSymbols =
value.map { it as? IrSimpleFunctionSymbol ?: error("Unexpected function overridden symbol: $it") } value.memoryOptimizedMap { it as? IrSimpleFunctionSymbol ?: error("Unexpected function overridden symbol: $it") }
is IrProperty -> { is IrProperty -> {
val overriddenProperties = value.map { it as? IrPropertySymbol ?: error("Unexpected property overridden symbol: $it") } val overriddenProperties = value.memoryOptimizedMap { it as? IrPropertySymbol ?: error("Unexpected property overridden symbol: $it") }
val getter = this.getter ?: error("Property has no getter: ${render()}") val getter = this.getter ?: error("Property has no getter: ${render()}")
getter.overriddenSymbols = overriddenProperties.map { it.owner.getter!!.symbol } getter.overriddenSymbols = overriddenProperties.memoryOptimizedMap { it.owner.getter!!.symbol }
this.setter?.let { setter -> this.setter?.let { setter ->
setter.overriddenSymbols = overriddenProperties.mapNotNull { it.owner.setter?.symbol } setter.overriddenSymbols = overriddenProperties.memoryOptimizedMapNotNull { it.owner.setter?.symbol }
} }
this.overriddenSymbols = overriddenProperties this.overriddenSymbols = overriddenProperties
} }
@@ -184,9 +187,8 @@ class IrOverridingUtil(
val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType -> val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType ->
val superClass = superType.getClass() ?: error("Unexpected super type: $superType") val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
superClass.declarations superClass.declarations
.filterIsInstance<IrOverridableMember>() .filterIsInstanceAnd<IrOverridableMember> {
.filterNot { it !in overriddenMembers && it.symbol !in ignoredParentSymbols && !it.isStaticMember && !DescriptorVisibilities.isPrivate(it.visibility)
it in overriddenMembers || it.symbol in ignoredParentSymbols || it.isStaticMember || DescriptorVisibilities.isPrivate(it.visibility)
} }
.map { overriddenMember -> .map { overriddenMember ->
val fakeOverride = fakeOverrideBuilder.fakeOverrideMember(superType, overriddenMember, clazz) val fakeOverride = fakeOverrideBuilder.fakeOverrideMember(superType, overriddenMember, clazz)
@@ -254,7 +256,7 @@ class IrOverridingUtil(
} }
} }
fromCurrent.overriddenSymbols = overridden.map { it.original.symbol } fromCurrent.overriddenSymbols = overridden.memoryOptimizedMap { it.original.symbol }
return bound return bound
} }
@@ -427,7 +429,7 @@ class IrOverridingUtil(
} }
} }
fakeOverride.overriddenSymbols = effectiveOverridden.map { it.original.symbol } fakeOverride.overriddenSymbols = effectiveOverridden.memoryOptimizedMap { it.original.symbol }
require( require(
fakeOverride.overriddenSymbols.isNotEmpty() fakeOverride.overriddenSymbols.isNotEmpty()
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.types package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
class IrTypeSystemContextWithAdditionalAxioms( class IrTypeSystemContextWithAdditionalAxioms(
typeSystem: IrTypeSystemContext, typeSystem: IrTypeSystemContext,
@@ -22,7 +22,9 @@ class IrTypeSystemContextWithAdditionalAxioms(
private val firstTypeParameterConstructors = firstParameters.map { it.symbol } private val firstTypeParameterConstructors = firstParameters.map { it.symbol }
private val secondTypeParameterConstructors = secondParameters.map { it.symbol } private val secondTypeParameterConstructors = secondParameters.map { it.symbol }
private val matchingTypeConstructors = firstTypeParameterConstructors.zip(secondTypeParameterConstructors).toMap() private val matchingTypeConstructors = firstTypeParameterConstructors
.zip(secondTypeParameterConstructors)
.toMap(newHashMapWithExpectedSize(firstTypeParameterConstructors.size))
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean { override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
if (super.areEqualTypeConstructors(c1, c2)) return true if (super.areEqualTypeConstructors(c1, c2)) return true
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.impl.* import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.utils.memoryOptimizedMap
abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : TypeSubstitutorMarker { abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : TypeSubstitutorMarker {
@@ -39,7 +40,7 @@ abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : T
return when (irType) { return when (irType) {
is IrSimpleType -> is IrSimpleType ->
with(irType.toBuilder()) { with(irType.toBuilder()) {
arguments = irType.arguments.map { substituteTypeArgument(it) } arguments = irType.arguments.memoryOptimizedMap { substituteTypeArgument(it) }
buildSimpleType() buildSimpleType()
} }
is IrDynamicType, is IrDynamicType,
@@ -32,6 +32,9 @@ import org.jetbrains.kotlin.ir.types.makeNotNull as irMakeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable as irMakeNullable import org.jetbrains.kotlin.ir.types.makeNullable as irMakeNullable
import org.jetbrains.kotlin.ir.types.isMarkedNullable as irIsMarkedNullable import org.jetbrains.kotlin.ir.types.isMarkedNullable as irIsMarkedNullable
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.memoryOptimizedFilterIsInstance
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.compactIfPossible
import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType
interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext, TypeSystemCommonBackendContext { interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesContext, TypeSystemCommonBackendContext {
@@ -268,7 +271,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
val newArguments = ArrayList<IrTypeArgument>(typeArguments.size) val newArguments = ArrayList<IrTypeArgument>(typeArguments.size)
val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.map { it.symbol }, typeArguments, capturedTypes, irBuiltIns) val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.memoryOptimizedMap { it.symbol }, typeArguments, capturedTypes, irBuiltIns)
for (index in typeArguments.indices) { for (index in typeArguments.indices) {
val oldArgument = typeArguments[index] val oldArgument = typeArguments[index]
@@ -341,12 +344,12 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
isExtensionFunction: Boolean, isExtensionFunction: Boolean,
attributes: List<AnnotationMarker>? attributes: List<AnnotationMarker>?
): SimpleTypeMarker { ): SimpleTypeMarker {
val ourAnnotations = attributes?.filterIsInstance<IrConstructorCall>() val ourAnnotations = attributes?.memoryOptimizedFilterIsInstance<IrConstructorCall>()
require(ourAnnotations?.size == attributes?.size) require(ourAnnotations?.size == attributes?.size)
return IrSimpleTypeImpl( return IrSimpleTypeImpl(
constructor as IrClassifierSymbol, constructor as IrClassifierSymbol,
if (nullable) SimpleTypeNullability.MARKED_NULLABLE else SimpleTypeNullability.DEFINITELY_NOT_NULL, if (nullable) SimpleTypeNullability.MARKED_NULLABLE else SimpleTypeNullability.DEFINITELY_NOT_NULL,
arguments.map { it as IrTypeArgument }, arguments.memoryOptimizedMap { it as IrTypeArgument },
ourAnnotations ?: emptyList() ourAnnotations ?: emptyList()
) )
} }
@@ -410,7 +413,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun KotlinTypeMarker.getAttributes(): List<AnnotationMarker> { override fun KotlinTypeMarker.getAttributes(): List<AnnotationMarker> {
require(this is IrType) require(this is IrType)
return this.annotations.map { object : AnnotationMarker, IrElement by it {} } return this.annotations.memoryOptimizedMap { object : AnnotationMarker, IrElement by it {} }
} }
override fun KotlinTypeMarker.hasCustomAttributes(): Boolean { override fun KotlinTypeMarker.hasCustomAttributes(): Boolean {
@@ -488,7 +491,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
getUnsubstitutedUnderlyingType()?.let { type -> getUnsubstitutedUnderlyingType()?.let { type ->
// Taking only the type parameters of the class (and not its outer classes) is OK since inner classes are always top level // Taking only the type parameters of the class (and not its outer classes) is OK since inner classes are always top level
IrTypeSubstitutor( IrTypeSubstitutor(
(this as IrType).getClass()!!.typeParameters.map { it.symbol }, (this as IrType).getClass()!!.typeParameters.memoryOptimizedMap { it.symbol },
(this as? IrSimpleType)?.arguments.orEmpty(), (this as? IrSimpleType)?.arguments.orEmpty(),
irBuiltIns irBuiltIns
).substitute(type as IrType) ).substitute(type as IrType)
@@ -572,7 +575,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy { override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy {
require(type is IrSimpleType) require(type is IrSimpleType)
val parameters = extractTypeParameters((type.classifier as IrClassSymbol).owner).map { it.symbol } val parameters = extractTypeParameters((type.classifier as IrClassSymbol).owner).memoryOptimizedMap { it.symbol }
val typeSubstitutor = IrTypeSubstitutor(parameters, type.arguments, irBuiltIns) val typeSubstitutor = IrTypeSubstitutor(parameters, type.arguments, irBuiltIns)
return object : TypeCheckerState.SupertypesPolicy.DoCustomTransform() { return object : TypeCheckerState.SupertypesPolicy.DoCustomTransform() {
@@ -610,7 +613,7 @@ fun extractTypeParameters(parent: IrDeclarationParent): List<IrTypeParameter> {
else -> null else -> null
} }
} }
return result return result.compactIfPossible()
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.utils.compactIfPossible
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -110,8 +111,8 @@ fun IrSimpleTypeBuilder.buildSimpleType() =
kotlinType, kotlinType,
classifier ?: throw AssertionError("Classifier not provided"), classifier ?: throw AssertionError("Classifier not provided"),
nullability, nullability,
arguments, arguments.compactIfPossible(),
annotations, annotations.compactIfPossible(),
abbreviation abbreviation
) )
@@ -20,6 +20,10 @@ import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.memoryOptimizedFilterNot
import org.jetbrains.kotlin.utils.memoryOptimizedMap
import org.jetbrains.kotlin.utils.memoryOptimizedMapIndexed
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
private fun IrType.withNullability(newNullability: Boolean): IrType = private fun IrType.withNullability(newNullability: Boolean): IrType =
when (this) { when (this) {
@@ -50,10 +54,10 @@ fun IrType.addAnnotations(newAnnotations: List<IrConstructorCall>): IrType =
else when (this) { else when (this) {
is IrSimpleType -> is IrSimpleType ->
toBuilder().apply { toBuilder().apply {
annotations = annotations + newAnnotations annotations = annotations memoryOptimizedPlus newAnnotations
}.buildSimpleType() }.buildSimpleType()
is IrDynamicType -> is IrDynamicType ->
IrDynamicTypeImpl(null, annotations + newAnnotations, Variance.INVARIANT) IrDynamicTypeImpl(null, annotations memoryOptimizedPlus newAnnotations, Variance.INVARIANT)
else -> else ->
this this
} }
@@ -62,10 +66,10 @@ fun IrType.removeAnnotations(predicate: (IrConstructorCall) -> Boolean): IrType
when (this) { when (this) {
is IrSimpleType -> is IrSimpleType ->
toBuilder().apply { toBuilder().apply {
annotations = annotations.filterNot(predicate) annotations = annotations.memoryOptimizedFilterNot(predicate)
}.buildSimpleType() }.buildSimpleType()
is IrDynamicType -> is IrDynamicType ->
IrDynamicTypeImpl(null, annotations.filterNot(predicate), Variance.INVARIANT) IrDynamicTypeImpl(null, annotations.memoryOptimizedFilterNot(predicate), Variance.INVARIANT)
else -> else ->
this this
} }
@@ -146,7 +150,7 @@ private fun makeKotlinType(
arguments: List<IrTypeArgument>, arguments: List<IrTypeArgument>,
hasQuestionMark: Boolean hasQuestionMark: Boolean
): SimpleType { ): SimpleType {
val kotlinTypeArguments = arguments.mapIndexed { index, it -> val kotlinTypeArguments = arguments.memoryOptimizedMapIndexed { index, it ->
when (it) { when (it) {
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toKotlinType()) is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toKotlinType())
is IrStarProjection -> StarProjectionImpl((classifier.descriptor as ClassDescriptor).typeConstructor.parameters[index]) is IrStarProjection -> StarProjectionImpl((classifier.descriptor as ClassDescriptor).typeConstructor.parameters[index])
@@ -219,7 +223,7 @@ fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
IrSimpleTypeImpl( IrSimpleTypeImpl(
this, this,
SimpleTypeNullability.NOT_SPECIFIED, SimpleTypeNullability.NOT_SPECIFIED,
arguments.map { makeTypeProjection(it, Variance.INVARIANT) }, arguments.memoryOptimizedMap { makeTypeProjection(it, Variance.INVARIANT) },
emptyList() emptyList()
) )
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import java.io.File import java.io.File
val IrConstructor.constructedClass get() = this.parent as IrClass val IrConstructor.constructedClass get() = this.parent as IrClass
@@ -259,7 +260,7 @@ class NaiveSourceBasedFileEntryImpl(
} }
private fun IrClass.getPropertyDeclaration(name: String): IrProperty? { private fun IrClass.getPropertyDeclaration(name: String): IrProperty? {
val properties = declarations.filterIsInstance<IrProperty>().filter { it.name.asString() == name } val properties = declarations.filterIsInstanceAnd<IrProperty> { it.name.asString() == name }
if (properties.size > 1) { if (properties.size > 1) {
error( error(
"More than one property with name $name in class $fqNameWhenAvailable:\n" + "More than one property with name $name in class $fqNameWhenAvailable:\n" +
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.error.ErrorClassDescriptor import org.jetbrains.kotlin.types.error.ErrorClassDescriptor
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
abstract class ConstantValueGenerator( abstract class ConstantValueGenerator(
private val moduleDescriptor: ModuleDescriptor, private val moduleDescriptor: ModuleDescriptor,
@@ -95,7 +96,7 @@ abstract class ConstantValueGenerator(
startOffset, endOffset, startOffset, endOffset,
constantType, constantType,
arrayElementType.toIrType(), arrayElementType.toIrType(),
constantValue.value.mapNotNull { constantValue.value.memoryOptimizedMapNotNull {
// For annotation arguments, the type of every subexpression can be inferred from the type of the parameter; // For annotation arguments, the type of every subexpression can be inferred from the type of the parameter;
// for arbitrary constants, we should always take the type inferred by the frontend. // for arbitrary constants, we should always take the type inferred by the frontend.
val newExpectedType = arrayElementType.takeIf { expectedType != null } val newExpectedType = arrayElementType.takeIf { expectedType != null }
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.memoryOptimizedMap
inline fun <reified T : IrElement> T.deepCopyWithSymbols( inline fun <reified T : IrElement> T.deepCopyWithSymbols(
initialParent: IrDeclarationParent? = null, initialParent: IrDeclarationParent? = null,
@@ -74,7 +75,7 @@ open class DeepCopyIrTreeWithSymbols(
transform(this@DeepCopyIrTreeWithSymbols, null) as T transform(this@DeepCopyIrTreeWithSymbols, null) as T
protected inline fun <reified T : IrElement> List<T>.transform() = protected inline fun <reified T : IrElement> List<T>.transform() =
map { it.transform() } memoryOptimizedMap { it.transform() }
protected inline fun <reified T : IrElement> List<T>.transformTo(destination: MutableList<T>) = protected inline fun <reified T : IrElement> List<T>.transformTo(destination: MutableList<T>) =
mapTo(destination) { it.transform() } mapTo(destination) { it.transform() }
@@ -132,9 +133,9 @@ open class DeepCopyIrTreeWithSymbols(
declaration.statements.mapTo(scriptCopy.statements) { it.transform() } declaration.statements.mapTo(scriptCopy.statements) { it.transform() }
scriptCopy.earlierScripts = declaration.earlierScripts scriptCopy.earlierScripts = declaration.earlierScripts
scriptCopy.earlierScriptsParameter = declaration.earlierScriptsParameter scriptCopy.earlierScriptsParameter = declaration.earlierScriptsParameter
scriptCopy.explicitCallParameters = declaration.explicitCallParameters.map { it.transform() } scriptCopy.explicitCallParameters = declaration.explicitCallParameters.memoryOptimizedMap { it.transform() }
scriptCopy.implicitReceiversParameters = declaration.implicitReceiversParameters.map { it.transform() } scriptCopy.implicitReceiversParameters = declaration.implicitReceiversParameters.memoryOptimizedMap { it.transform() }
scriptCopy.providedPropertiesParameters = declaration.providedPropertiesParameters.map { it.transform() } scriptCopy.providedPropertiesParameters = declaration.providedPropertiesParameters.memoryOptimizedMap { it.transform() }
} }
} }
@@ -157,10 +158,10 @@ open class DeepCopyIrTreeWithSymbols(
).apply { ).apply {
transformAnnotations(declaration) transformAnnotations(declaration)
copyTypeParametersFrom(declaration) copyTypeParametersFrom(declaration)
superTypes = declaration.superTypes.map { superTypes = declaration.superTypes.memoryOptimizedMap {
it.remapType() it.remapType()
} }
sealedSubclasses = declaration.sealedSubclasses.map { sealedSubclasses = declaration.sealedSubclasses.memoryOptimizedMap {
symbolRemapper.getReferencedClass(it) symbolRemapper.getReferencedClass(it)
} }
thisReceiver = declaration.thisReceiver?.transform() thisReceiver = declaration.thisReceiver?.transform()
@@ -187,7 +188,7 @@ open class DeepCopyIrTreeWithSymbols(
isFakeOverride = declaration.isFakeOverride, isFakeOverride = declaration.isFakeOverride,
containerSource = declaration.containerSource, containerSource = declaration.containerSource,
).apply { ).apply {
overriddenSymbols = declaration.overriddenSymbols.map { overriddenSymbols = declaration.overriddenSymbols.memoryOptimizedMap {
symbolRemapper.getReferencedFunction(it) as IrSimpleFunctionSymbol symbolRemapper.getReferencedFunction(it) as IrSimpleFunctionSymbol
} }
contextReceiverParametersCount = declaration.contextReceiverParametersCount contextReceiverParametersCount = declaration.contextReceiverParametersCount
@@ -256,7 +257,7 @@ open class DeepCopyIrTreeWithSymbols(
this.setter = declaration.setter?.transform()?.also { this.setter = declaration.setter?.transform()?.also {
it.correspondingPropertySymbol = symbol it.correspondingPropertySymbol = symbol
} }
this.overriddenSymbols = declaration.overriddenSymbols.map { this.overriddenSymbols = declaration.overriddenSymbols.memoryOptimizedMap {
symbolRemapper.getReferencedProperty(it) symbolRemapper.getReferencedProperty(it)
} }
} }
@@ -332,7 +333,7 @@ open class DeepCopyIrTreeWithSymbols(
override fun visitTypeParameter(declaration: IrTypeParameter): IrTypeParameter = override fun visitTypeParameter(declaration: IrTypeParameter): IrTypeParameter =
copyTypeParameter(declaration).apply { copyTypeParameter(declaration).apply {
// TODO type parameter scopes? // TODO type parameter scopes?
superTypes = declaration.superTypes.map { it.remapType() } superTypes = declaration.superTypes.memoryOptimizedMap { it.remapType() }
} }
private fun copyTypeParameter(declaration: IrTypeParameter): IrTypeParameter = private fun copyTypeParameter(declaration: IrTypeParameter): IrTypeParameter =
@@ -349,13 +350,13 @@ open class DeepCopyIrTreeWithSymbols(
} }
protected fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) { protected fun IrTypeParametersContainer.copyTypeParametersFrom(other: IrTypeParametersContainer) {
this.typeParameters = other.typeParameters.map { this.typeParameters = other.typeParameters.memoryOptimizedMap {
copyTypeParameter(it) copyTypeParameter(it)
} }
typeRemapper.withinScope(this) { typeRemapper.withinScope(this) {
for ((thisTypeParameter, otherTypeParameter) in this.typeParameters.zip(other.typeParameters)) { for ((thisTypeParameter, otherTypeParameter) in this.typeParameters.zip(other.typeParameters)) {
thisTypeParameter.superTypes = otherTypeParameter.superTypes.map { thisTypeParameter.superTypes = otherTypeParameter.superTypes.memoryOptimizedMap {
typeRemapper.remapType(it) typeRemapper.remapType(it)
} }
} }
@@ -403,7 +404,7 @@ open class DeepCopyIrTreeWithSymbols(
override fun visitBlockBody(body: IrBlockBody): IrBlockBody = override fun visitBlockBody(body: IrBlockBody): IrBlockBody =
body.factory.createBlockBody( body.factory.createBlockBody(
body.startOffset, body.endOffset, body.startOffset, body.endOffset,
body.statements.map { it.transform() } body.statements.memoryOptimizedMap { it.transform() }
) )
override fun visitSyntheticBody(body: IrSyntheticBody): IrSyntheticBody = override fun visitSyntheticBody(body: IrSyntheticBody): IrSyntheticBody =
@@ -420,7 +421,7 @@ open class DeepCopyIrTreeWithSymbols(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
symbolRemapper.getReferencedConstructor(expression.constructor), symbolRemapper.getReferencedConstructor(expression.constructor),
expression.valueArguments.transform(), expression.valueArguments.transform(),
expression.typeArguments.map { it.remapType() }, expression.typeArguments.memoryOptimizedMap { it.remapType() },
expression.type.remapType() expression.type.remapType()
).copyAttributes(expression) ).copyAttributes(expression)
@@ -457,7 +458,7 @@ open class DeepCopyIrTreeWithSymbols(
expression.type.remapType(), expression.type.remapType(),
symbolRemapper.getReferencedReturnableBlock(expression.symbol), symbolRemapper.getReferencedReturnableBlock(expression.symbol),
mapStatementOrigin(expression.origin), mapStatementOrigin(expression.origin),
expression.statements.map { it.transform() } expression.statements.memoryOptimizedMap { it.transform() }
).copyAttributes(expression) ).copyAttributes(expression)
else if (expression is IrInlinedFunctionBlock) else if (expression is IrInlinedFunctionBlock)
IrInlinedFunctionBlockImpl( IrInlinedFunctionBlockImpl(
@@ -465,14 +466,14 @@ open class DeepCopyIrTreeWithSymbols(
expression.type.remapType(), expression.type.remapType(),
expression.inlineCall, expression.inlinedElement, expression.inlineCall, expression.inlinedElement,
mapStatementOrigin(expression.origin), mapStatementOrigin(expression.origin),
statements = expression.statements.map { it.transform() }, statements = expression.statements.memoryOptimizedMap { it.transform() },
).copyAttributes(expression) ).copyAttributes(expression)
else else
IrBlockImpl( IrBlockImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type.remapType(), expression.type.remapType(),
mapStatementOrigin(expression.origin), mapStatementOrigin(expression.origin),
expression.statements.map { it.transform() } expression.statements.memoryOptimizedMap { it.transform() }
).copyAttributes(expression) ).copyAttributes(expression)
override fun visitComposite(expression: IrComposite): IrComposite = override fun visitComposite(expression: IrComposite): IrComposite =
@@ -480,14 +481,14 @@ open class DeepCopyIrTreeWithSymbols(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type.remapType(), expression.type.remapType(),
mapStatementOrigin(expression.origin), mapStatementOrigin(expression.origin),
expression.statements.map { it.transform() } expression.statements.memoryOptimizedMap { it.transform() }
).copyAttributes(expression) ).copyAttributes(expression)
override fun visitStringConcatenation(expression: IrStringConcatenation): IrStringConcatenation = override fun visitStringConcatenation(expression: IrStringConcatenation): IrStringConcatenation =
IrStringConcatenationImpl( IrStringConcatenationImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type.remapType(), expression.type.remapType(),
expression.arguments.map { it.transform() } expression.arguments.memoryOptimizedMap { it.transform() }
).copyAttributes(expression) ).copyAttributes(expression)
override fun visitGetObjectValue(expression: IrGetObjectValue): IrGetObjectValue = override fun visitGetObjectValue(expression: IrGetObjectValue): IrGetObjectValue =
@@ -725,7 +726,7 @@ open class DeepCopyIrTreeWithSymbols(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type.remapType(), expression.type.remapType(),
mapStatementOrigin(expression.origin), mapStatementOrigin(expression.origin),
expression.branches.map { it.transform() } expression.branches.memoryOptimizedMap { it.transform() }
).copyAttributes(expression) ).copyAttributes(expression)
override fun visitBranch(branch: IrBranch): IrBranch = override fun visitBranch(branch: IrBranch): IrBranch =
@@ -782,7 +783,7 @@ open class DeepCopyIrTreeWithSymbols(
aTry.startOffset, aTry.endOffset, aTry.startOffset, aTry.endOffset,
aTry.type.remapType(), aTry.type.remapType(),
aTry.tryResult.transform(), aTry.tryResult.transform(),
aTry.catches.map { it.transform() }, aTry.catches.memoryOptimizedMap { it.transform() },
aTry.finallyExpression?.transform() aTry.finallyExpression?.transform()
).copyAttributes(aTry) ).copyAttributes(aTry)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.utils.memoryOptimizedMap
class DeepCopyTypeRemapper( class DeepCopyTypeRemapper(
private val symbolRemapper: SymbolRemapper private val symbolRemapper: SymbolRemapper
@@ -32,8 +33,8 @@ class DeepCopyTypeRemapper(
null, null,
symbolRemapper.getReferencedClassifier(type.classifier), symbolRemapper.getReferencedClassifier(type.classifier),
type.nullability, type.nullability,
type.arguments.map { remapTypeArgument(it) }, type.arguments.memoryOptimizedMap { remapTypeArgument(it) },
type.annotations.map { it.transform(deepCopy, null) as IrConstructorCall }, type.annotations.memoryOptimizedMap { it.transform(deepCopy, null) as IrConstructorCall },
type.abbreviation?.remapTypeAbbreviation() type.abbreviation?.remapTypeAbbreviation()
) )
else -> type else -> type
@@ -50,7 +51,7 @@ class DeepCopyTypeRemapper(
IrTypeAbbreviationImpl( IrTypeAbbreviationImpl(
symbolRemapper.getReferencedTypeAlias(typeAlias), symbolRemapper.getReferencedTypeAlias(typeAlias),
hasQuestionMark, hasQuestionMark,
arguments.map { remapTypeArgument(it) }, arguments.memoryOptimizedMap { remapTypeArgument(it) },
annotations annotations
) )
} }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.utils.memoryOptimizedMap
/** /**
* After moving an [org.jetbrains.kotlin.ir.IrElement], some type parameter references within it may become out of scope. * After moving an [org.jetbrains.kotlin.ir.IrElement], some type parameter references within it may become out of scope.
@@ -31,7 +32,7 @@ class IrTypeParameterRemapper(
null, null,
type.classifier.remap(), type.classifier.remap(),
type.nullability, type.nullability,
type.arguments.map { it.remap() }, type.arguments.memoryOptimizedMap { it.remap() },
type.annotations, type.annotations,
type.abbreviation?.remap() type.abbreviation?.remap()
).apply { ).apply {
@@ -52,7 +53,7 @@ class IrTypeParameterRemapper(
IrTypeAbbreviationImpl( IrTypeAbbreviationImpl(
typeAlias, typeAlias,
hasQuestionMark, hasQuestionMark,
arguments.map { it.remap() }, arguments.memoryOptimizedMap { it.remap() },
annotations annotations
).apply { ).apply {
annotations.forEach { it.remapTypes(this@IrTypeParameterRemapper) } annotations.forEach { it.remapTypes(this@IrTypeParameterRemapper) }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.memoryOptimizedMap
val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin")) val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin"))
private val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflect")) private val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflect"))
@@ -92,7 +93,7 @@ fun IrType.substitute(params: List<IrTypeParameter>, arguments: List<IrType>): I
fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType { fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
if (this !is IrSimpleType || substitutionMap.isEmpty()) return this if (this !is IrSimpleType || substitutionMap.isEmpty()) return this
val newAnnotations = annotations.map { it.deepCopyWithSymbols() } val newAnnotations = annotations.memoryOptimizedMap { it.deepCopyWithSymbols() }
substitutionMap[classifier]?.let { substitutedType -> substitutionMap[classifier]?.let { substitutedType ->
// Add nullability and annotations from original type // Add nullability and annotations from original type
@@ -101,7 +102,7 @@ fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrTy
.addAnnotations(newAnnotations) .addAnnotations(newAnnotations)
} }
val newArguments = arguments.map { val newArguments = arguments.memoryOptimizedMap {
when (it) { when (it) {
is IrTypeProjection -> makeTypeProjection(it.type.substitute(substitutionMap), it.variance) is IrTypeProjection -> makeTypeProjection(it.type.substitute(substitutionMap), it.variance)
is IrStarProjection -> it is IrStarProjection -> it
@@ -127,7 +128,7 @@ private fun getImmediateSupertypes(irType: IrSimpleType): List<IrSimpleType> {
} }
return originalSupertypes return originalSupertypes
.filter { it.classOrNull != null } .filter { it.classOrNull != null }
.map { superType -> .memoryOptimizedMap { superType ->
superType.substitute(irClass.typeParameters, arguments) as IrSimpleType superType.substitute(irClass.typeParameters, arguments) as IrSimpleType
} }
} }
@@ -29,8 +29,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.StringWriter import java.io.StringWriter
/** /**
@@ -731,7 +730,7 @@ fun IrClass.addSimpleDelegatingConstructor(
this.visibility = superConstructor.visibility this.visibility = superConstructor.visibility
this.isPrimary = isPrimary this.isPrimary = isPrimary
}.also { constructor -> }.also { constructor ->
constructor.valueParameters = superConstructor.valueParameters.mapIndexed { index, parameter -> constructor.valueParameters = superConstructor.valueParameters.memoryOptimizedMapIndexed { index, parameter ->
parameter.copyTo(constructor, index = index) parameter.copyTo(constructor, index = index)
} }
@@ -842,7 +841,7 @@ fun IrFunction.copyReceiverParametersFrom(from: IrFunction, substitutionMap: Map
fun IrFunction.copyValueParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) { fun IrFunction.copyValueParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) {
copyReceiverParametersFrom(from, substitutionMap) copyReceiverParametersFrom(from, substitutionMap)
val shift = valueParameters.size val shift = valueParameters.size
valueParameters += from.valueParameters.map { valueParameters = valueParameters memoryOptimizedPlus from.valueParameters.map {
it.copyTo(this, index = it.index + shift, type = it.type.substitute(substitutionMap)) it.copyTo(this, index = it.index + shift, type = it.type.substitute(substitutionMap))
} }
} }
@@ -866,12 +865,12 @@ fun IrTypeParametersContainer.copyTypeParameters(
val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap() val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap()
// Any type parameter can figure in a boundary type for any other parameter. // Any type parameter can figure in a boundary type for any other parameter.
// 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.memoryOptimizedMapIndexed { 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 = typeParameters memoryOptimizedPlus newTypeParameters
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) -> srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap) dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap)
} }
@@ -888,13 +887,13 @@ private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDst
val target = this val target = this
val sourceParent = source.parent as IrTypeParametersContainer val sourceParent = source.parent as IrTypeParametersContainer
val targetParent = target.parent as IrTypeParametersContainer val targetParent = target.parent as IrTypeParametersContainer
target.superTypes = source.superTypes.map { target.superTypes = source.superTypes.memoryOptimizedMap {
it.remapTypeParameters(sourceParent, targetParent, srcToDstParameterMap) it.remapTypeParameters(sourceParent, targetParent, srcToDstParameterMap)
} }
} }
fun IrAnnotationContainer.copyAnnotations(): List<IrConstructorCall> { fun IrAnnotationContainer.copyAnnotations(): List<IrConstructorCall> {
return annotations.map { it.deepCopyWithSymbols(this as? IrDeclarationParent) } return annotations.memoryOptimizedMap { it.deepCopyWithSymbols(this as? IrDeclarationParent) }
} }
fun IrAnnotationContainer.copyAnnotationsWhen(filter: IrConstructorCall.() -> Boolean): List<IrConstructorCall> { fun IrAnnotationContainer.copyAnnotationsWhen(filter: IrConstructorCall.() -> Boolean): List<IrConstructorCall> {
@@ -902,7 +901,7 @@ fun IrAnnotationContainer.copyAnnotationsWhen(filter: IrConstructorCall.() -> Bo
} }
fun IrMutableAnnotationContainer.copyAnnotationsFrom(source: IrAnnotationContainer) { fun IrMutableAnnotationContainer.copyAnnotationsFrom(source: IrAnnotationContainer) {
annotations += source.copyAnnotations() annotations = annotations memoryOptimizedPlus source.copyAnnotations()
} }
fun makeTypeParameterSubstitutionMap( fun makeTypeParameterSubstitutionMap(
@@ -935,7 +934,7 @@ fun IrFunction.copyValueParametersToStatic(
target.classIfConstructor target.classIfConstructor
) )
target.valueParameters += originalDispatchReceiver.copyTo( target.valueParameters = target.valueParameters memoryOptimizedPlus originalDispatchReceiver.copyTo(
target, target,
origin = originalDispatchReceiver.origin, origin = originalDispatchReceiver.origin,
index = shift++, index = shift++,
@@ -944,7 +943,7 @@ fun IrFunction.copyValueParametersToStatic(
) )
} }
source.extensionReceiverParameter?.let { originalExtensionReceiver -> source.extensionReceiverParameter?.let { originalExtensionReceiver ->
target.valueParameters += originalExtensionReceiver.copyTo( target.valueParameters = target.valueParameters memoryOptimizedPlus originalExtensionReceiver.copyTo(
target, target,
origin = originalExtensionReceiver.origin, origin = originalExtensionReceiver.origin,
index = shift++, index = shift++,
@@ -954,7 +953,7 @@ fun IrFunction.copyValueParametersToStatic(
for (oldValueParameter in source.valueParameters) { for (oldValueParameter in source.valueParameters) {
if (oldValueParameter.index >= numValueParametersToCopy) break if (oldValueParameter.index >= numValueParametersToCopy) break
target.valueParameters += oldValueParameter.copyTo( target.valueParameters = target.valueParameters memoryOptimizedPlus oldValueParameter.copyTo(
target, target,
origin = origin, origin = origin,
index = oldValueParameter.index + shift index = oldValueParameter.index + shift
@@ -1002,7 +1001,7 @@ fun IrType.remapTypeParameters(
IrSimpleTypeImpl( IrSimpleTypeImpl(
classifier.symbol, classifier.symbol,
nullability, nullability,
arguments.map { arguments.memoryOptimizedMap {
when (it) { when (it) {
is IrTypeProjection -> makeTypeProjection( is IrTypeProjection -> makeTypeProjection(
it.type.remapTypeParameters(source, target, srcToDstParameterMap), it.type.remapTypeParameters(source, target, srcToDstParameterMap),
@@ -1218,7 +1217,7 @@ fun IrFactory.createStaticFunctionWithReceivers(
fun remap(type: IrType): IrType = fun remap(type: IrType): IrType =
type.remapTypeParameters(oldFunction, this, typeParameterMap) type.remapTypeParameters(oldFunction, this, typeParameterMap)
typeParameters.forEach { it.superTypes = it.superTypes.map(::remap) } typeParameters.forEach { it.superTypes = it.superTypes.memoryOptimizedMap(::remap) }
annotations = oldFunction.annotations annotations = oldFunction.annotations
@@ -1321,7 +1320,7 @@ private fun IrSimpleFunction.copyAndRenameConflictingTypeParametersFrom(
newParameter.copySuperTypesFrom(oldParameter, parameterMap) newParameter.copySuperTypesFrom(oldParameter, parameterMap)
} }
typeParameters = typeParameters + newParameters typeParameters = typeParameters memoryOptimizedPlus newParameters
return newParameters return newParameters
} }

Some files were not shown because too many files have changed in this diff Show More