diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt index f55f4f9dbd5..41a16dbfe69 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmReflectSymbols import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.ir.IrInlineScopeResolver import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder @@ -83,7 +84,7 @@ internal class ReflectiveAccessLowering( // reflective access . We record these _before_ transformation, in order to // later predict the compilation strategy for fields. See the uses of // `fieldLocationAndReceiver`. - val callsOnCompanionObjects: MutableMap = mutableMapOf() + val callsOnCompanionObjects: MutableMap = mutableMapOf() private fun recordCompanionObjectAsDispatchReceiver(expression: IrCall) { if ((expression.dispatchReceiver as? IrGetObjectValue)?.symbol?.owner?.isCompanion == true) { @@ -169,6 +170,7 @@ internal class ReflectiveAccessLowering( */ private val symbols = context.ir.symbols + private val reflectSymbols = symbols.javaLangReflectSymbols private fun IrBuilderWithScope.javaClassObject(klass: IrType): IrExpression = irCall(symbols.kClassJava.owner.getter!!).apply { @@ -182,26 +184,26 @@ internal class ReflectiveAccessLowering( } private fun IrBuilderWithScope.getDeclaredField(declaringClass: IrExpression, fieldName: String): IrExpression = - irCall(symbols.getDeclaredField).apply { + irCall(reflectSymbols.getDeclaredField).apply { dispatchReceiver = declaringClass putValueArgument(0, irString(fieldName)) } private fun IrBuilderWithScope.fieldSetAccessible(field: IrExpression): IrExpression = - irCall(symbols.javaLangReflectFieldSetAccessible).apply { + irCall(reflectSymbols.javaLangReflectFieldSetAccessible).apply { dispatchReceiver = field putValueArgument(0, irTrue()) } private fun IrBuilderWithScope.fieldSet(fieldObject: IrExpression, receiver: IrExpression, value: IrExpression): IrExpression = - irCall(symbols.javaLangReflectFieldSet).apply { + irCall(reflectSymbols.javaLangReflectFieldSet).apply { dispatchReceiver = fieldObject putValueArgument(0, receiver) putValueArgument(1, value) } private fun IrBuilderWithScope.fieldGet(fieldObject: IrExpression, receiver: IrExpression): IrExpression = - irCall(symbols.javaLangReflectFieldGet).apply { + irCall(reflectSymbols.javaLangReflectFieldGet).apply { dispatchReceiver = fieldObject putValueArgument(0, receiver) } @@ -211,14 +213,14 @@ internal class ReflectiveAccessLowering( methodName: String, parameterTypes: List ): IrExpression = - irCall(symbols.getDeclaredMethod).apply { + irCall(reflectSymbols.getDeclaredMethod).apply { dispatchReceiver = declaringClass putValueArgument(0, irString(methodName)) putValueArgument(1, irVararg(symbols.javaLangClass.defaultType, parameterTypes.map { javaClassObject(it) })) } private fun IrBuilderWithScope.methodSetAccessible(method: IrExpression): IrExpression = - irCall(symbols.javaLangReflectMethodSetAccessible).apply { + irCall(reflectSymbols.javaLangReflectMethodSetAccessible).apply { dispatchReceiver = method putValueArgument(0, irTrue()) } @@ -228,7 +230,7 @@ internal class ReflectiveAccessLowering( receiver: IrExpression, arguments: List ): IrExpression = - irCall(symbols.javaLangReflectMethodInvoke).apply { + irCall(reflectSymbols.javaLangReflectMethodInvoke).apply { dispatchReceiver = method putValueArgument(0, receiver) putValueArgument(1, irVararg(context.irBuiltIns.anyNType, arguments)) @@ -238,20 +240,20 @@ internal class ReflectiveAccessLowering( declaringClass: IrExpression, parameterTypes: List ): IrExpression = - irCall(symbols.getDeclaredConstructor).apply { + irCall(reflectSymbols.getDeclaredConstructor).apply { dispatchReceiver = declaringClass putValueArgument(0, irVararg(symbols.javaLangClass.defaultType, parameterTypes.map { javaClassObject(it) })) } private fun IrBuilderWithScope.constructorSetAccessible(constructor: IrExpression): IrExpression = - irCall(symbols.javaLangReflectConstructorSetAccessible).apply { + irCall(reflectSymbols.javaLangReflectConstructorSetAccessible).apply { dispatchReceiver = constructor putValueArgument(0, irTrue()) } private fun IrBuilderWithScope.constructorNewInstance(constructor: IrExpression, arguments: List): IrExpression = - irCall(symbols.javaLangReflectConstructorNewInstance).apply { + irCall(reflectSymbols.javaLangReflectConstructorNewInstance).apply { dispatchReceiver = constructor putValueArgument(0, irVararg(context.irBuiltIns.anyNType, arguments)) } @@ -278,7 +280,7 @@ internal class ReflectiveAccessLowering( parameterTypes ), nameHint = "method", - irType = symbols.javaLangReflectMethod.defaultType + irType = reflectSymbols.javaLangReflectMethod.defaultType ) +methodSetAccessible(irGet(methodVar)) +methodInvoke(irGet(methodVar), receiver ?: irNull(), arguments) @@ -330,7 +332,7 @@ internal class ReflectiveAccessLowering( call.valueParameterTypes() ), nameHint = "constructor", - irType = symbols.javaLangReflectConstructor.defaultType + irType = reflectSymbols.javaLangReflectConstructor.defaultType ) +constructorSetAccessible(irGet(constructorVar)) +constructorNewInstance(irGet(constructorVar), call.getValueArguments()) @@ -353,7 +355,7 @@ internal class ReflectiveAccessLowering( val fieldVar = createTmpVariable( getDeclaredField(irGet(classVar), fieldName), nameHint = "field", - irType = symbols.javaLangReflectField.defaultType + irType = reflectSymbols.javaLangReflectField.defaultType ) +fieldSetAccessible(irGet(fieldVar)) +fieldGet(irGet(fieldVar), instance ?: irGet(classVar)) @@ -385,7 +387,7 @@ internal class ReflectiveAccessLowering( fieldName ), nameHint = "field", - irType = symbols.javaLangReflectField.defaultType + irType = reflectSymbols.javaLangReflectField.defaultType ) +fieldSetAccessible(irGet(fieldVar)) +fieldSet(irGet(fieldVar), instance ?: irNull(), value) @@ -502,7 +504,7 @@ internal class ReflectiveAccessLowering( val builder = context.createJvmIrBuilder(expression.symbol) // invokeSpecial(owner: String, name: String, descriptor: String, isInterface: Boolean): T - return builder.irCall(context.irIntrinsics.symbols.jvmDebuggerInvokeSpecialIntrinsic).apply { + return builder.irCall(context.ir.symbols.jvmDebuggerInvokeSpecialIntrinsic).apply { dispatchReceiver = expression.dispatchReceiver this.type = expression.symbol.owner.returnType putValueArgument(0, builder.irString("${owner.packageFqName}/${owner.name}")) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmReflectSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmReflectSymbols.kt new file mode 100644 index 00000000000..ea59340a90a --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmReflectSymbols.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +package org.jetbrains.kotlin.backend.jvm + +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrBuiltIns +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrPackageFragment +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +class JvmReflectSymbols(val context: JvmBackendContext) { + private val irBuiltIns: IrBuiltIns = context.irBuiltIns + + private val javaLangReflect: FqName = FqName("java.lang.reflect") + + private val javaLangReflectPackage: IrPackageFragment = + IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(context.state.module, javaLangReflect) + + val javaLangReflectField: IrClassSymbol = + createJavaLangReflectClass(FqName("java.lang.reflect.Field")) { klass -> + klass.addFunction("setAccessible", irBuiltIns.unitType).apply { + addValueParameter("isAccessible", irBuiltIns.booleanType) + } + klass.addFunction("get", irBuiltIns.anyNType).apply { + addValueParameter("receiver", irBuiltIns.anyNType) + } + klass.addFunction("set", irBuiltIns.unitType).apply { + addValueParameter("receiver", irBuiltIns.anyNType) + addValueParameter("value", irBuiltIns.anyNType) + } + } + + val javaLangReflectMethod: IrClassSymbol = + createJavaLangReflectClass(FqName("java.lang.reflect.Method")) { klass -> + klass.addFunction("setAccessible", irBuiltIns.unitType).apply { + addValueParameter("isAccessible", irBuiltIns.booleanType) + } + klass.addFunction("invoke", irBuiltIns.anyNType).apply { + addValueParameter("receiver", irBuiltIns.anyNType) + addValueParameter { + name = Name.identifier("args") + type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType) + varargElementType = irBuiltIns.anyNType + } + } + } + + val javaLangReflectConstructor: IrClassSymbol = + createJavaLangReflectClass(FqName("java.lang.reflect.Constructor")) { klass -> + klass.addFunction("setAccessible", irBuiltIns.unitType).apply { + addValueParameter("isAccessible", irBuiltIns.booleanType) + } + klass.addFunction("newInstance", irBuiltIns.anyNType).apply { + addValueParameter { + name = Name.identifier("args") + type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType) + varargElementType = irBuiltIns.anyNType + } + } + } + + init { + val klass = context.ir.symbols.javaLangClass.owner + klass.addFunction("getDeclaredMethod", javaLangReflectMethod.defaultType.makeNullable()).apply { + addValueParameter("methodName", irBuiltIns.stringType.makeNullable()) + addValueParameter { + name = Name.identifier("args") + type = irBuiltIns.arrayClass.typeWith(klass.defaultType).makeNullable() + varargElementType = klass.defaultType + } + } + klass.addFunction("getDeclaredField", javaLangReflectField.defaultType).apply { + addValueParameter("fieldName", irBuiltIns.stringType) + } + klass.addFunction("getDeclaredConstructor", javaLangReflectConstructor.defaultType.makeNullable()).apply { + addValueParameter { + name = Name.identifier("args") + type = irBuiltIns.arrayClass.typeWith(klass.defaultType).makeNullable() + varargElementType = klass.defaultType + } + } + } + + val javaLangReflectFieldSetAccessible: IrSimpleFunctionSymbol = + javaLangReflectField.functionByName("setAccessible") + + val javaLangReflectMethodSetAccessible: IrSimpleFunctionSymbol = + javaLangReflectMethod.functionByName("setAccessible") + + val javaLangReflectConstructorSetAccessible: IrSimpleFunctionSymbol = + javaLangReflectConstructor.functionByName("setAccessible") + + val getDeclaredField: IrSimpleFunctionSymbol = + context.ir.symbols.javaLangClass.functionByName("getDeclaredField") + + val getDeclaredMethod: IrSimpleFunctionSymbol = + context.ir.symbols.javaLangClass.functionByName("getDeclaredMethod") + + val getDeclaredConstructor: IrSimpleFunctionSymbol = + context.ir.symbols.javaLangClass.functionByName("getDeclaredConstructor") + + val javaLangReflectFieldGet: IrSimpleFunctionSymbol = + javaLangReflectField.functionByName("get") + + val javaLangReflectFieldSet: IrSimpleFunctionSymbol = + javaLangReflectField.functionByName("set") + + val javaLangReflectMethodInvoke: IrSimpleFunctionSymbol = + javaLangReflectMethod.functionByName("invoke") + + val javaLangReflectConstructorNewInstance: IrSimpleFunctionSymbol = + javaLangReflectConstructor.functionByName("newInstance") + + private fun createJavaLangReflectClass( + fqName: FqName, + classKind: ClassKind = ClassKind.CLASS, + classModality: Modality = Modality.FINAL, + classIsInline: Boolean = false, + block: (IrClass) -> Unit = {} + ): IrClassSymbol = + context.irFactory.buildClass { + name = fqName.shortName() + kind = classKind + modality = classModality + isInline = classIsInline + }.apply { + parent = javaLangReflectPackage + createImplicitParameterDeclarationWithWrappedDescriptor() + block(this) + }.symbol +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt index 785be96aab6..157cf67f56f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt @@ -60,7 +60,6 @@ class JvmSymbols( private val kotlinReflectPackage: IrPackageFragment = createPackage(FqName("kotlin.reflect")) private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang")) private val javaLangInvokePackage: IrPackageFragment = createPackage(FqName("java.lang.invoke")) - private val javaLangReflectPackage: IrPackageFragment = createPackage(FqName("java.lang.reflect")) private val javaUtilPackage: IrPackageFragment = createPackage(FqName("java.util")) @@ -105,7 +104,6 @@ class JvmSymbols( "kotlin.reflect" -> kotlinReflectPackage "java.lang" -> javaLangPackage "java.lang.invoke" -> javaLangInvokePackage - "java.lang.reflect" -> javaLangReflectPackage "java.util" -> javaUtilPackage "kotlin.internal" -> kotlinInternalPackage else -> error("Other packages are not supported yet: $fqName") @@ -232,103 +230,12 @@ class JvmSymbols( private val kDeclarationContainer: IrClassSymbol = createClass(StandardNames.FqNames.kDeclarationContainer.toSafe(), ClassKind.INTERFACE, Modality.ABSTRACT) - val javaLangReflectField: IrClassSymbol = - createClass(FqName("java.lang.reflect.Field")) { klass -> - klass.addFunction("setAccessible", irBuiltIns.unitType).apply { - addValueParameter("isAccessible", irBuiltIns.booleanType) - } - klass.addFunction("get", irBuiltIns.anyNType).apply { - addValueParameter("receiver", irBuiltIns.anyNType) - } - klass.addFunction("set", irBuiltIns.unitType).apply { - addValueParameter("receiver", irBuiltIns.anyNType) - addValueParameter("value", irBuiltIns.anyNType) - } - } - - val javaLangReflectMethod: IrClassSymbol = - createClass(FqName("java.lang.reflect.Method")) { klass -> - klass.addFunction("setAccessible", irBuiltIns.unitType).apply { - addValueParameter("isAccessible", irBuiltIns.booleanType) - } - klass.addFunction("invoke", irBuiltIns.anyNType).apply { - addValueParameter("receiver", irBuiltIns.anyNType) - addValueParameter { - name = Name.identifier("args") - type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType) - varargElementType = irBuiltIns.anyNType - } - } - } - - val javaLangReflectConstructor: IrClassSymbol = - createClass(FqName("java.lang.reflect.Constructor")) { klass -> - klass.addFunction("setAccessible", irBuiltIns.unitType).apply { - addValueParameter("isAccessible", irBuiltIns.booleanType) - } - klass.addFunction("newInstance", irBuiltIns.anyNType).apply { - addValueParameter { - name = Name.identifier("args") - type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType) - varargElementType = irBuiltIns.anyNType - } - } - } - - val javaLangReflectFieldSetAccessible: IrSimpleFunctionSymbol = - javaLangReflectField.functionByName("setAccessible") - - val javaLangReflectMethodSetAccessible: IrSimpleFunctionSymbol = - javaLangReflectMethod.functionByName("setAccessible") - - val javaLangReflectConstructorSetAccessible: IrSimpleFunctionSymbol = - javaLangReflectConstructor.functionByName("setAccessible") - val javaLangClass: IrClassSymbol = createClass(FqName("java.lang.Class")) { klass -> klass.addTypeParameter("T", irBuiltIns.anyNType, Variance.INVARIANT) klass.addFunction("desiredAssertionStatus", irBuiltIns.booleanType) - klass.addFunction("getDeclaredMethod", javaLangReflectMethod.defaultType.makeNullable()).apply { - addValueParameter("methodName", irBuiltIns.stringType.makeNullable()) - addValueParameter { - name = Name.identifier("args") - type = irBuiltIns.arrayClass.typeWith(klass.defaultType).makeNullable() - varargElementType = klass.defaultType - } - } - klass.addFunction("getDeclaredField", javaLangReflectField.defaultType).apply { - addValueParameter("fieldName", irBuiltIns.stringType) - } - klass.addFunction("getDeclaredConstructor", javaLangReflectConstructor.defaultType.makeNullable()).apply { - addValueParameter { - name = Name.identifier("args") - type = irBuiltIns.arrayClass.typeWith(klass.defaultType).makeNullable() - varargElementType = klass.defaultType - } - } } - val getDeclaredField: IrSimpleFunctionSymbol = - javaLangClass.functionByName("getDeclaredField") - - val getDeclaredMethod: IrSimpleFunctionSymbol = - javaLangClass.functionByName("getDeclaredMethod") - - val getDeclaredConstructor: IrSimpleFunctionSymbol = - javaLangClass.functionByName("getDeclaredConstructor") - - val javaLangReflectFieldGet: IrSimpleFunctionSymbol = - javaLangReflectField.functionByName("get") - - val javaLangReflectFieldSet: IrSimpleFunctionSymbol = - javaLangReflectField.functionByName("set") - - val javaLangReflectMethodInvoke: IrSimpleFunctionSymbol = - javaLangReflectMethod.functionByName("invoke") - - val javaLangReflectConstructorNewInstance: IrSimpleFunctionSymbol = - javaLangReflectConstructor.functionByName("newInstance") - private val javaLangDeprecatedWithDeprecatedFlag: IrClassSymbol = createClass(FqName("java.lang.Deprecated"), classKind = ClassKind.ANNOTATION_CLASS) { klass -> klass.addConstructor { isPrimary = true } @@ -630,6 +537,10 @@ class JvmSymbols( } } + val javaLangReflectSymbols: JvmReflectSymbols by lazy { + JvmReflectSymbols(context) + } + override val functionAdapter: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.FunctionAdapter"), ClassKind.INTERFACE) { klass -> klass.addFunction("getFunctionDelegate", irBuiltIns.functionClass.starProjectedType, Modality.ABSTRACT) } @@ -1198,8 +1109,8 @@ class JvmSymbols( } } -private fun IrClassSymbol.functionByName(name: String): IrSimpleFunctionSymbol = +fun IrClassSymbol.functionByName(name: String): IrSimpleFunctionSymbol = functions.single { it.owner.name.asString() == name } -private fun IrClassSymbol.fieldByName(name: String): IrFieldSymbol = +fun IrClassSymbol.fieldByName(name: String): IrFieldSymbol = fields.single { it.owner.name.asString() == name }