Rewrite interpreter logic around arguments evaluation
For now calculated arguments will be stored on stack instead of memory. At first this was done because of problems with default arguments, but in the next commit this problem will be solved.
This commit is contained in:
committed by
TeamCityServer
parent
d41c6e900a
commit
7852d01da6
+1
-1
@@ -60,7 +60,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
|||||||
)
|
)
|
||||||
return interpreter.withNewCallStack(irCall) {
|
return interpreter.withNewCallStack(irCall) {
|
||||||
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
|
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
|
||||||
valueArguments.forEach { this@withNewCallStack.environment.callStack.addVariable(it) }
|
valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) }
|
||||||
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass)
|
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-24
@@ -157,31 +157,34 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callSt
|
|||||||
|
|
||||||
val valueParametersSymbols = irFunction.valueParameters.map { it.symbol }
|
val valueParametersSymbols = irFunction.valueParameters.map { it.symbol }
|
||||||
|
|
||||||
// interpret defaults for null arguments (at the end)
|
|
||||||
(expression.valueArgumentsCount - 1 downTo 0).forEach { index ->
|
|
||||||
if (expression.getValueArgument(index) != null) return@forEach
|
|
||||||
callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner))
|
|
||||||
|
|
||||||
getDefaultForParameterAt(index)
|
|
||||||
?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
|
||||||
?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing
|
|
||||||
callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpret not null arguments (after evaluation of arguments)
|
|
||||||
expression.dispatchReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!)) }
|
|
||||||
expression.extensionReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!)) }
|
|
||||||
(0 until expression.valueArgumentsCount).forEach {
|
|
||||||
if (expression.getValueArgument(it) != null) callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[it]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// evaluate arguments
|
// evaluate arguments
|
||||||
(expression.valueArgumentsCount - 1 downTo 0).forEach {
|
(expression.valueArgumentsCount - 1 downTo 0).forEach { index ->
|
||||||
callStack.addInstruction(CompoundInstruction(expression.getValueArgument(it)))
|
when {
|
||||||
|
expression.getValueArgument(index) != null -> {
|
||||||
|
// interpret arguments that were passed
|
||||||
|
callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[index]))
|
||||||
|
callStack.addInstruction(CompoundInstruction(expression.getValueArgument(index)))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// interpret defaults for null arguments
|
||||||
|
callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner))
|
||||||
|
|
||||||
|
getDefaultForParameterAt(index)
|
||||||
|
?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
||||||
|
?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing
|
||||||
|
callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expression.extensionReceiver?.let {
|
||||||
|
callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!))
|
||||||
|
callStack.addInstruction(CompoundInstruction(it))
|
||||||
|
}
|
||||||
|
expression.dispatchReceiver?.let {
|
||||||
|
callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!))
|
||||||
|
callStack.addInstruction(CompoundInstruction(it))
|
||||||
}
|
}
|
||||||
expression.extensionReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
|
||||||
expression.dispatchReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unfoldInstanceInitializerCall(instanceInitializerCall: IrInstanceInitializerCall, callStack: CallStack) {
|
private fun unfoldInstanceInitializerCall(instanceInitializerCall: IrInstanceInitializerCall, callStack: CallStack) {
|
||||||
@@ -378,7 +381,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ
|
|||||||
val toStringCall = state.createToStringIrCall()
|
val toStringCall = state.createToStringIrCall()
|
||||||
callStack.newSubFrame(toStringCall)
|
callStack.newSubFrame(toStringCall)
|
||||||
callStack.addInstruction(SimpleInstruction(toStringCall))
|
callStack.addInstruction(SimpleInstruction(toStringCall))
|
||||||
callStack.addVariable(Variable(toStringCall.symbol.owner.dispatchReceiverParameter!!.symbol, state))
|
callStack.pushState(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -164,6 +164,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
|
|
||||||
// outer classes can be used in default args evaluation
|
// outer classes can be used in default args evaluation
|
||||||
if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack)
|
if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack)
|
||||||
|
callStack.pushState(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun interpretCall(call: IrCall) {
|
private fun interpretCall(call: IrCall) {
|
||||||
@@ -176,9 +177,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
|
|
||||||
val owner = call.symbol.owner
|
val owner = call.symbol.owner
|
||||||
// 1. load evaluated arguments from stack
|
// 1. load evaluated arguments from stack
|
||||||
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.getState(it) }
|
val valueArguments = owner.valueParameters.map { callStack.popState() }.reversed().toMutableList()
|
||||||
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.getState(it) }
|
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.popState() }
|
||||||
val valueArguments = owner.valueParameters.map { callStack.getState(it.symbol) }.toMutableList()
|
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.popState() }
|
||||||
|
|
||||||
// 2. get correct function for interpretation
|
// 2. get correct function for interpretation
|
||||||
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(call) ?: call.symbol.owner
|
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(call) ?: call.symbol.owner
|
||||||
@@ -199,7 +200,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
|
|
||||||
// 4. store arguments in memory (remap args on actual names)
|
// 4. store arguments in memory (remap args on actual names)
|
||||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
||||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: valueArguments.removeFirst())) }
|
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
|
||||||
irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) }
|
irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) }
|
||||||
|
|
||||||
// 5. store reified type parameters
|
// 5. store reified type parameters
|
||||||
@@ -240,7 +241,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
|
|
||||||
private fun interpretConstructorCall(constructorCall: IrFunctionAccessExpression) {
|
private fun interpretConstructorCall(constructorCall: IrFunctionAccessExpression) {
|
||||||
val constructor = constructorCall.symbol.owner
|
val constructor = constructorCall.symbol.owner
|
||||||
val valueArguments = constructor.valueParameters.map { callStack.getState(it.symbol) }
|
val valueArguments = constructor.valueParameters.map { callStack.popState() }.reversed()
|
||||||
val irClass = constructor.parentAsClass
|
val irClass = constructor.parentAsClass
|
||||||
val receiverSymbol = constructor.dispatchReceiverParameter?.symbol
|
val receiverSymbol = constructor.dispatchReceiverParameter?.symbol
|
||||||
|
|
||||||
@@ -255,7 +256,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
||||||
val outerClass = receiverSymbol?.let { callStack.getState(it) }
|
val outerClass = receiverSymbol?.let { callStack.popState() }
|
||||||
|
|
||||||
callStack.dropSubFrame()
|
callStack.dropSubFrame()
|
||||||
callStack.newFrame(constructor)
|
callStack.newFrame(constructor)
|
||||||
@@ -603,8 +604,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
private fun interpretFunctionReference(reference: IrFunctionReference) {
|
private fun interpretFunctionReference(reference: IrFunctionReference) {
|
||||||
val irFunction = reference.symbol.owner
|
val irFunction = reference.symbol.owner
|
||||||
|
|
||||||
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.getState(irFunction.getDispatchReceiver()!!) }
|
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.popState() }
|
||||||
val extensionReceiver = reference.extensionReceiver?.let { callStack.getState(irFunction.getExtensionReceiver()!!) }
|
val extensionReceiver = reference.extensionReceiver?.let { callStack.popState() }
|
||||||
|
|
||||||
callStack.dropSubFrame()
|
callStack.dropSubFrame()
|
||||||
|
|
||||||
@@ -618,10 +619,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun interpretPropertyReference(propertyReference: IrPropertyReference) {
|
private fun interpretPropertyReference(propertyReference: IrPropertyReference) {
|
||||||
val receiverSymbol = propertyReference.getter?.owner?.let { it.getDispatchReceiver() ?: it.getExtensionReceiver() }
|
|
||||||
// it is impossible to get KProperty2 through ::, so only one receiver can be not null (or both null)
|
// it is impossible to get KProperty2 through ::, so only one receiver can be not null (or both null)
|
||||||
val receiver = (propertyReference.dispatchReceiver ?: propertyReference.extensionReceiver)
|
val receiver = (propertyReference.dispatchReceiver ?: propertyReference.extensionReceiver)
|
||||||
?.let { callStack.getState(receiverSymbol!!) }
|
?.let { callStack.popState() }
|
||||||
|
|
||||||
callStack.dropSubFrame()
|
callStack.dropSubFrame()
|
||||||
val propertyState = KPropertyState(propertyReference, receiver)
|
val propertyState = KPropertyState(propertyReference, receiver)
|
||||||
|
|||||||
+4
-4
@@ -83,13 +83,13 @@ internal class KFunctionState(
|
|||||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||||
val extensionParameter = irFunction.extensionReceiverParameter
|
val extensionParameter = irFunction.extensionReceiverParameter
|
||||||
|
|
||||||
if (dispatchParameter != null && getField(dispatchParameter.symbol) == null) {
|
if (dispatchParameter != null) {
|
||||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol)
|
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol)
|
||||||
(this@impl.valueParameters as MutableList).add(dispatchParameter)
|
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(dispatchParameter)
|
||||||
}
|
}
|
||||||
if (extensionParameter != null && getField(extensionParameter.symbol) == null) {
|
if (extensionParameter != null) {
|
||||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol)
|
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol)
|
||||||
(this@impl.valueParameters as MutableList).add(extensionParameter)
|
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(extensionParameter)
|
||||||
}
|
}
|
||||||
irFunction.valueParameters.forEach {
|
irFunction.valueParameters.forEach {
|
||||||
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))
|
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))
|
||||||
|
|||||||
Reference in New Issue
Block a user