[WASM] Implementation of Class references

This commit is contained in:
Igor Yakovlev
2021-10-26 19:26:17 +02:00
committed by TeamCityServer
parent d9f2bd7963
commit ce360bb10b
43 changed files with 350 additions and 109 deletions
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -17,7 +16,9 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.getPropertyGetter
@@ -29,10 +30,16 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
interface JsCommonBackendContext : CommonBackendContext {
override val mapping: JsMapping
val intrinsics: Intrinsics
val dynamicType: IrDynamicType
val inlineClassesUtils: InlineClassesUtils
val coroutineSymbols: JsCommonCoroutineSymbols
val primitiveClassesObject: IrClassSymbol
val catchAllThrowableType: IrType
get() = irBuiltIns.throwableType
@@ -50,7 +57,7 @@ internal fun <T> BackendContext.lazy2(fn: () -> T) = lazy { irFactory.stageContr
class JsCommonCoroutineSymbols(
symbolTable: SymbolTable,
module: ModuleDescriptor,
val module: ModuleDescriptor,
val context: JsCommonBackendContext
) {
val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
@@ -114,10 +121,10 @@ class JsCommonCoroutineSymbols(
}
}
internal fun findClass(memberScope: MemberScope, name: Name): ClassDescriptor =
fun findClass(memberScope: MemberScope, name: Name): ClassDescriptor =
memberScope.getContributedClassifier(name, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
internal fun findFunctions(memberScope: MemberScope, name: Name): List<SimpleFunctionDescriptor> =
fun findFunctions(memberScope: MemberScope, name: Name): List<SimpleFunctionDescriptor> =
memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).toList()
interface InlineClassesUtils {
@@ -21,7 +21,21 @@ import org.jetbrains.kotlin.psi2ir.findSingleFunction
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import java.util.*
class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendContext) {
interface Intrinsics {
val jsGetKClassFromExpression: IrSimpleFunctionSymbol
val jsGetKClass: IrSimpleFunctionSymbol
val jsClass: IrSimpleFunctionSymbol
val createKType: IrSimpleFunctionSymbol?
val createDynamicKType: IrSimpleFunctionSymbol?
val createKTypeParameter: IrSimpleFunctionSymbol?
val getStarKTypeProjection: IrSimpleFunctionSymbol?
val createCovariantKTypeProjection: IrSimpleFunctionSymbol?
val createInvariantKTypeProjection: IrSimpleFunctionSymbol?
val createContravariantKTypeProjection: IrSimpleFunctionSymbol?
val arrayLiteral: IrSimpleFunctionSymbol
}
class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendContext) : Intrinsics {
// TODO: Should we drop operator intrinsics in favor of IrDynamicOperatorExpression?
@@ -169,10 +183,10 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendSuperTypeWithReceiver")
val jsInvokeSuspendSuperTypeWithReceiverAndParam =
getInternalWithoutPackage("kotlin.coroutines.intrinsics.invokeSuspendSuperTypeWithReceiverAndParam")
val jsGetKClass = getInternalWithoutPackage("getKClass")
val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression")
val jsClass = getInternalFunction("jsClassIntrinsic")
override val jsGetKClass = getInternalWithoutPackage("getKClass")
override val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression")
override val jsClass = getInternalFunction("jsClassIntrinsic")
val jsNumberRangeToNumber = getInternalFunction("numberRangeToNumber")
val jsNumberRangeToLong = getInternalFunction("numberRangeToLong")
@@ -235,7 +249,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val jsPrimitiveArrayIteratorFunctions =
PrimitiveType.values().associate { it to getInternalFunction("${it.typeName.asString().toLowerCaseAsciiOnly()}ArrayIterator") }
val arrayLiteral = getInternalFunction("arrayLiteral")
override val arrayLiteral = getInternalFunction("arrayLiteral")
val primitiveToTypedArrayMap = EnumMap(
mapOf(
@@ -247,13 +261,13 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
)
)
val createKType = getInternalWithoutPackageOrNull("createKType")
val createDynamicKType = getInternalWithoutPackageOrNull("createDynamicKType")
val createKTypeParameter = getInternalWithoutPackageOrNull("createKTypeParameter")
val getStarKTypeProjection = getInternalWithoutPackageOrNull("getStarKTypeProjection")
val createCovariantKTypeProjection = getInternalWithoutPackageOrNull("createCovariantKTypeProjection")
val createInvariantKTypeProjection = getInternalWithoutPackageOrNull("createInvariantKTypeProjection")
val createContravariantKTypeProjection = getInternalWithoutPackageOrNull("createContravariantKTypeProjection")
override val createKType = getInternalWithoutPackageOrNull("createKType")
override val createDynamicKType = getInternalWithoutPackageOrNull("createDynamicKType")
override val createKTypeParameter = getInternalWithoutPackageOrNull("createKTypeParameter")
override val getStarKTypeProjection = getInternalWithoutPackageOrNull("getStarKTypeProjection")
override val createCovariantKTypeProjection = getInternalWithoutPackageOrNull("createCovariantKTypeProjection")
override val createInvariantKTypeProjection = getInternalWithoutPackageOrNull("createInvariantKTypeProjection")
override val createContravariantKTypeProjection = getInternalWithoutPackageOrNull("createContravariantKTypeProjection")
val primitiveToSizeConstructor =
PrimitiveType.values().associate { type ->
@@ -315,8 +329,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val jsUndefined = getInternalFunction("jsUndefined")
// Helpers:
private fun getInternalFunction(name: String) =
context.symbolTable.referenceSimpleFunction(context.getJsInternalFunction(name))
@@ -333,4 +345,4 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
private fun getInternalClassWithoutPackage(fqName: String) =
context.symbolTable.referenceClass(context.getClass(FqName(fqName)))
}
}
@@ -68,6 +68,7 @@ class JsIrBackendContext(
val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
override val builtIns = module.builtIns
override val typeSystem: IrTypeSystemContext = IrTypeSystemContextImpl(irBuiltIns)
override val irFactory: IrFactory = symbolTable.irFactory
@@ -156,9 +157,8 @@ class JsIrBackendContext(
private val internalPackage = module.getPackage(JS_PACKAGE_FQNAME)
val dynamicType: IrDynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
val intrinsics = JsIntrinsics(irBuiltIns, this)
override val dynamicType: IrDynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
override val intrinsics = JsIntrinsics(irBuiltIns, this)
override val catchAllThrowableType: IrType
get() = dynamicType
@@ -284,7 +284,7 @@ class JsIrBackendContext(
val errorCodeSymbol: IrSimpleFunctionSymbol? =
if (errorPolicy.allowErrors) symbolTable.referenceSimpleFunction(getJsInternalFunction("errorCode")) else null
val primitiveClassesObject = getIrClass(FqName("kotlin.reflect.js.internal.PrimitiveClasses"))
override val primitiveClassesObject = getIrClass(FqName("kotlin.reflect.js.internal.PrimitiveClasses"))
val throwableClass = getIrClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable")))
@@ -323,16 +323,6 @@ class JsIrBackendContext(
override val suiteFun = getFunctions(FqName("kotlin.test.suite")).singleOrNull()?.let { symbolTable.referenceSimpleFunction(it) }
override val testFun = getFunctions(FqName("kotlin.test.test")).singleOrNull()?.let { symbolTable.referenceSimpleFunction(it) }
val primitiveClassProperties by lazy2 {
primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
}
val primitiveClassFunctionClass by lazy2 {
primitiveClassesObject.owner.declarations
.filterIsInstance<IrSimpleFunction>()
.find { it.name == Name.identifier("functionClass") }!!
}
val throwableConstructors by lazy2 { throwableClass.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } }
val defaultThrowableCtor by lazy2 { throwableConstructors.single { !it.owner.isPrimary && it.owner.valueParameters.size == 0 } }
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.toJsArrayLiteral
import org.jetbrains.kotlin.ir.declarations.*
@@ -24,13 +23,20 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.*
class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass {
private val intrinsics = context.intrinsics
class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLoweringPass {
private val primitiveClassProperties by lazy {
primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
}
private val primitiveClassFunctionClass by lazy {
primitiveClassesObject.owner.declarations
.filterIsInstance<IrSimpleFunction>()
.find { it.name == Name.identifier("functionClass") }!!
}
private val primitiveClassesObject = context.primitiveClassesObject
private val primitiveClassProperties = context.primitiveClassProperties
private fun primitiveClassProperty(name: String) =
primitiveClassProperties.singleOrNull { it.name == Name.identifier(name) }?.getter
?: primitiveClassesObject.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.special("<get-$name>") }
@@ -74,7 +80,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
if (primitiveKClass != null)
return JsIrBuilder.buildBlock(returnType, listOf(argument, primitiveKClass))
return JsIrBuilder.buildCall(intrinsics.jsGetKClassFromExpression, returnType, listOf(typeArgument)).apply {
return JsIrBuilder.buildCall(context.intrinsics.jsGetKClassFromExpression, returnType, listOf(typeArgument)).apply {
putValueArgument(0, argument)
}
}
@@ -103,7 +109,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
if (typeArgument.isFunction()) {
val functionInterface = typeArgument.getClass()!!
val arity = functionInterface.typeParameters.size - 1
return getPrimitiveClass(context.primitiveClassFunctionClass, returnType).apply {
return getPrimitiveClass(primitiveClassFunctionClass, returnType).apply {
putValueArgument(0, JsIrBuilder.buildInt(context.irBuiltIns.intType, arity))
}
}
@@ -112,7 +118,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
}
private fun callGetKClass(
returnType: IrType = intrinsics.jsGetKClass.owner.returnType,
returnType: IrType = context.intrinsics.jsGetKClass.owner.returnType,
typeArgument: IrType
): IrCall {
val primitiveKClass =
@@ -121,7 +127,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
if (primitiveKClass != null)
return primitiveKClass
return JsIrBuilder.buildCall(intrinsics.jsGetKClass, returnType, listOf(typeArgument))
return JsIrBuilder.buildCall(context.intrinsics.jsGetKClass, returnType, listOf(typeArgument))
.apply {
putValueArgument(0, callJsClass(typeArgument))
}
@@ -129,7 +135,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
private fun callJsClass(type: IrType) =
JsIrBuilder.buildCall(
intrinsics.jsClass,
context.intrinsics.jsClass,
typeArguments = listOf(type),
origin = JsLoweredDeclarationOrigin.CLASS_REFERENCE
)
@@ -71,7 +71,7 @@ fun IrDeclaration.hasStaticDispatch() = when (this) {
else -> true
}
fun List<IrExpression>.toJsArrayLiteral(context: JsIrBackendContext, arrayType: IrType, elementType: IrType): IrExpression {
fun List<IrExpression>.toJsArrayLiteral(context: JsCommonBackendContext, arrayType: IrType, elementType: IrType): IrExpression {
val irVararg = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arrayType, elementType, this)
return IrCallImpl(