Access this through the dispatch parameter when available
This commit is contained in:
committed by
Georgy Bronnikov
parent
9b9236efcb
commit
b04dc69157
+10
-16
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.builders.irSetField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
// This pass has to run after LocalDeclarationsLowering, since we don't handle nested functions.
|
||||
val innerClassesPhase = makeIrFilePhase(
|
||||
::InnerClassesLowering,
|
||||
name = "InnerClasses",
|
||||
@@ -76,21 +79,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
|
||||
irClass.transformDeclarationsFlat { irMember -> (irMember as? IrConstructor)?.let { listOf(lowerConstructor(it)) } }
|
||||
irClass.transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew))
|
||||
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
private var enclosingConstructor: IrConstructor? = null
|
||||
|
||||
// TODO: maybe add another transformer that skips specified elements
|
||||
override fun visitClass(declaration: IrClass): IrStatement =
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
override fun visitClassNew(declaration: IrClass): IrStatement =
|
||||
declaration
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement =
|
||||
try {
|
||||
enclosingConstructor = declaration
|
||||
super.visitConstructor(declaration)
|
||||
} finally {
|
||||
enclosingConstructor = null
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
@@ -100,8 +92,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
val origin = expression.origin
|
||||
val function = currentFunction?.irElement as? IrFunction
|
||||
val enclosingThisReceiver = function?.dispatchReceiverParameter ?: irClass.thisReceiver!!
|
||||
|
||||
var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin)
|
||||
var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, enclosingThisReceiver.symbol, origin)
|
||||
var innerClass = irClass
|
||||
while (innerClass != implicitThisClass) {
|
||||
if (!innerClass.isInner) {
|
||||
@@ -110,10 +104,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
|
||||
return expression
|
||||
}
|
||||
|
||||
irThis = if (enclosingConstructor != null && irClass == innerClass) {
|
||||
irThis = if (function is IrConstructor && irClass == innerClass) {
|
||||
// Might be before a super() call (e.g. an argument to one), in which case the JVM bytecode verifier will reject
|
||||
// an attempt to access the field. Good thing we have a local variable as well.
|
||||
IrGetValueImpl(startOffset, endOffset, enclosingConstructor!!.valueParameters[0].symbol, origin)
|
||||
IrGetValueImpl(startOffset, endOffset, function.valueParameters[0].symbol, origin)
|
||||
} else {
|
||||
val outerThisField = context.declarationFactory.getOuterThisField(innerClass)
|
||||
IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, outerThisField.type, irThis, origin)
|
||||
|
||||
+2
-2
@@ -234,7 +234,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
||||
functionReferenceClass = buildClass {
|
||||
setSourceRange(irFunctionReference)
|
||||
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
name = "${callee.name}\$${functionReferenceCount++}".synthesizedName
|
||||
name = "${callee.name.safeName()}\$${functionReferenceCount++}".synthesizedName
|
||||
kind = ClassKind.CLASS
|
||||
visibility = Visibilities.PUBLIC
|
||||
modality = Modality.FINAL
|
||||
@@ -403,7 +403,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
||||
val argument = when {
|
||||
!unboundArgsSet.contains(parameter) ->
|
||||
// Bound parameter - read from field.
|
||||
irGetField(irGet(functionReferenceThis.owner), argumentToFieldMap[parameter]!!)
|
||||
irGetField(irGet(dispatchReceiverParameter!!), argumentToFieldMap[parameter]!!)
|
||||
function.isSuspend && unboundIndex == valueParameters.size ->
|
||||
// For suspend functions the last argument is continuation and it is implicit.
|
||||
TODO()
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : Cl
|
||||
target.returnType,
|
||||
target.returnType.classifierOrFail,
|
||||
irCall(target).apply {
|
||||
dispatchReceiver = irGet(irClass.thisReceiver!!)
|
||||
dispatchReceiver = irGet(dispatchReceiverParameter!!)
|
||||
target.valueParameters.forEachIndexed { i, irValueParameter ->
|
||||
val type = irValueParameter.type
|
||||
putValueArgument(
|
||||
|
||||
+38
-29
@@ -292,70 +292,79 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
}
|
||||
}
|
||||
|
||||
fun buildOverride(method: IrSimpleFunction, build: IrBlockBodyBuilder.(List<IrValueParameter>) -> IrExpression) =
|
||||
buildFun {
|
||||
setSourceRange(expression)
|
||||
name = method.name
|
||||
returnType = method.returnType
|
||||
visibility = method.visibility
|
||||
origin = referenceClass.origin
|
||||
}.apply {
|
||||
parent = referenceClass
|
||||
referenceClass.declarations.add(this)
|
||||
|
||||
overriddenSymbols.add(method.symbol)
|
||||
dispatchReceiverParameter = referenceThis.copyTo(this)
|
||||
for (parameter in method.valueParameters)
|
||||
valueParameters.add(parameter.copyTo(this))
|
||||
body = context.createIrBuilder(symbol).irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(build(valueParameters))
|
||||
}
|
||||
fun buildOverride(
|
||||
method: IrSimpleFunction,
|
||||
build: IrBlockBodyBuilder.(IrValueParameter, List<IrValueParameter>) -> IrExpression
|
||||
) = referenceClass.addFunction {
|
||||
setSourceRange(expression)
|
||||
name = method.name
|
||||
returnType = method.returnType
|
||||
visibility = method.visibility
|
||||
origin = referenceClass.origin
|
||||
}.apply {
|
||||
overriddenSymbols.add(method.symbol)
|
||||
val thisParameter = referenceThis.copyTo(this)
|
||||
dispatchReceiverParameter = thisParameter
|
||||
for (parameter in method.valueParameters)
|
||||
valueParameters.add(parameter.copyTo(this))
|
||||
body = context.createIrBuilder(symbol).irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(build(thisParameter, valueParameters))
|
||||
}
|
||||
}
|
||||
|
||||
val receiverField = superClass.properties.single { it.name.asString() == "receiver" }.backingField!!
|
||||
fun IrBuilderWithScope.setReceiversOn(call: IrCall, valueParameters: List<IrValueParameter>) {
|
||||
fun IrBuilderWithScope.setReceiversOn(
|
||||
call: IrCall,
|
||||
dispatchReceiverParameter: IrValueParameter,
|
||||
valueParameters: List<IrValueParameter>
|
||||
) {
|
||||
var index = 0
|
||||
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
||||
if (expression.dispatchReceiver != null)
|
||||
irGetField(irGet(referenceThis), receiverField)
|
||||
irGetField(irGet(dispatchReceiverParameter), receiverField)
|
||||
else
|
||||
irImplicitCast(irGet(valueParameters[index++]), it.type)
|
||||
}
|
||||
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
||||
if (expression.extensionReceiver != null)
|
||||
irGetField(irGet(referenceThis), receiverField)
|
||||
irGetField(irGet(dispatchReceiverParameter), receiverField)
|
||||
else
|
||||
irImplicitCast(irGet(valueParameters[index++]), it.type)
|
||||
}
|
||||
}
|
||||
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getName" }) {
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getName" }) { _, _ ->
|
||||
irString(expression.descriptor.name.asString())
|
||||
}
|
||||
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getOwner" }) {
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getOwner" }) { _, _ ->
|
||||
buildReflectedContainerReference(expression)
|
||||
}
|
||||
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getSignature" }) {
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "getSignature" }) { _, _ ->
|
||||
irString(expression.signature)
|
||||
}
|
||||
|
||||
expression.getter?.owner?.let { getter ->
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "get" }) { valueParameters ->
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "get" }) { dispatchReceiverParameter, valueParameters ->
|
||||
irGet(getter.returnType, null, getter.symbol).apply {
|
||||
copyTypeArgumentsFrom(expression)
|
||||
setReceiversOn(this, valueParameters)
|
||||
setReceiversOn(
|
||||
this,
|
||||
dispatchReceiverParameter,
|
||||
valueParameters
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expression.setter?.owner?.let { setter ->
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "set" }) { valueParameters ->
|
||||
val value = irGet(valueParameters.last())
|
||||
buildOverride(superClass.functions.single { it.name.asString() == "set" }) { dispatchReceiverParameter, valueParameters ->
|
||||
val type = setter.valueParameters.last().type
|
||||
val value = irImplicitCast(irGet(valueParameters.last()), type)
|
||||
irSet(setter.returnType, null, setter.symbol, value).apply {
|
||||
copyTypeArgumentsFrom(expression)
|
||||
setReceiversOn(this, valueParameters)
|
||||
setReceiversOn(this, dispatchReceiverParameter, valueParameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user