Move object creation logic into constructor interpretation
This newly created object is not used in arguments interpretation so there is no need to create it in InstructionsUnfolder. Moreover this object can interfere with other objects in memory, for example, when creating outer object from inner.
This commit is contained in:
committed by
TeamCityServer
parent
1af1a3c84e
commit
e5ca646de4
+5
-19
@@ -39,9 +39,9 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn
|
||||
is IrSimpleFunction -> unfoldFunction(element, environment)
|
||||
is IrConstructor -> unfoldConstructor(element, callStack)
|
||||
is IrCall -> unfoldCall(element, callStack)
|
||||
is IrConstructorCall -> unfoldConstructorCall(element, environment)
|
||||
is IrEnumConstructorCall -> unfoldEnumConstructorCall(element, callStack)
|
||||
is IrDelegatingConstructorCall -> unfoldDelegatingConstructorCall(element, callStack)
|
||||
is IrConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||
is IrEnumConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||
is IrDelegatingConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||
is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack)
|
||||
is IrField -> unfoldField(element, callStack)
|
||||
is IrBody -> unfoldBody(element, callStack)
|
||||
@@ -113,23 +113,9 @@ private fun unfoldCall(call: IrCall, callStack: CallStack) {
|
||||
unfoldValueParameters(call, callStack)
|
||||
}
|
||||
|
||||
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) {
|
||||
val callStack = environment.callStack
|
||||
val constructor = constructorCall.symbol.owner
|
||||
val irClass = constructor.parentAsClass
|
||||
// This function is responsible for IrConstructorCall, IrDelegatingConstructorCall and IrEnumConstructorCall
|
||||
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, callStack: CallStack) {
|
||||
unfoldValueParameters(constructorCall, callStack)
|
||||
// this state is used to create object once
|
||||
val state = if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass)
|
||||
if (irClass.isObject) environment.mapOfObjects[irClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
||||
callStack.addVariable(Variable(constructorCall.getThisReceiver(), state))
|
||||
}
|
||||
|
||||
private fun unfoldEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall, callStack: CallStack) {
|
||||
unfoldValueParameters(enumConstructorCall, callStack)
|
||||
}
|
||||
|
||||
private fun unfoldDelegatingConstructorCall(delegatingConstructorCall: IrFunctionAccessExpression, callStack: CallStack) {
|
||||
unfoldValueParameters(delegatingConstructorCall, callStack)
|
||||
}
|
||||
|
||||
private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callStack: CallStack) {
|
||||
|
||||
+11
-2
@@ -204,9 +204,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) dispatchReceiver.loadOuterClassesInto(callStack)
|
||||
|
||||
// 6. load up values onto stack
|
||||
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
|
||||
if (dispatchReceiver is StateWithClosure) callStack.loadUpValues(dispatchReceiver)
|
||||
if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver)
|
||||
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
|
||||
|
||||
callInterceptor.interceptCall(call, irFunction, args) {
|
||||
callStack.addInstruction(CompoundInstruction(irFunction))
|
||||
@@ -243,7 +243,16 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val irClass = constructor.parentAsClass
|
||||
val receiverSymbol = constructor.dispatchReceiverParameter?.symbol
|
||||
|
||||
val objectState = callStack.getState(constructorCall.getThisReceiver())
|
||||
// this check is used to be sure that object will be created once
|
||||
val objectState = when (constructorCall) {
|
||||
!is IrConstructorCall -> callStack.getState(constructorCall.getThisReceiver())
|
||||
else -> (if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass))
|
||||
.apply {
|
||||
// must set object's state here, before actual initialization, to avoid cyclic evaluation
|
||||
if (irClass.isObject) environment.mapOfObjects[irClass.symbol] = this
|
||||
}
|
||||
}
|
||||
|
||||
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
||||
val outerClass = receiverSymbol?.let { callStack.getState(it) }
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ internal interface Complex : State {
|
||||
}
|
||||
|
||||
fun loadOuterClassesInto(callStack: CallStack) {
|
||||
generateSequence(outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) }
|
||||
generateSequence(outerClass) { (it.state as? Complex)?.outerClass }
|
||||
.forEach { variable ->
|
||||
callStack.addVariable(variable)
|
||||
(variable.state as? StateWithClosure)?.let { callStack.loadUpValues(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user