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 IrSimpleFunction -> unfoldFunction(element, environment)
|
||||||
is IrConstructor -> unfoldConstructor(element, callStack)
|
is IrConstructor -> unfoldConstructor(element, callStack)
|
||||||
is IrCall -> unfoldCall(element, callStack)
|
is IrCall -> unfoldCall(element, callStack)
|
||||||
is IrConstructorCall -> unfoldConstructorCall(element, environment)
|
is IrConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||||
is IrEnumConstructorCall -> unfoldEnumConstructorCall(element, callStack)
|
is IrEnumConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||||
is IrDelegatingConstructorCall -> unfoldDelegatingConstructorCall(element, callStack)
|
is IrDelegatingConstructorCall -> unfoldConstructorCall(element, callStack)
|
||||||
is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack)
|
is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack)
|
||||||
is IrField -> unfoldField(element, callStack)
|
is IrField -> unfoldField(element, callStack)
|
||||||
is IrBody -> unfoldBody(element, callStack)
|
is IrBody -> unfoldBody(element, callStack)
|
||||||
@@ -113,23 +113,9 @@ private fun unfoldCall(call: IrCall, callStack: CallStack) {
|
|||||||
unfoldValueParameters(call, callStack)
|
unfoldValueParameters(call, callStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) {
|
// This function is responsible for IrConstructorCall, IrDelegatingConstructorCall and IrEnumConstructorCall
|
||||||
val callStack = environment.callStack
|
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, callStack: CallStack) {
|
||||||
val constructor = constructorCall.symbol.owner
|
|
||||||
val irClass = constructor.parentAsClass
|
|
||||||
unfoldValueParameters(constructorCall, 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) {
|
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)
|
if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) dispatchReceiver.loadOuterClassesInto(callStack)
|
||||||
|
|
||||||
// 6. load up values onto stack
|
// 6. load up values onto stack
|
||||||
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
|
|
||||||
if (dispatchReceiver is StateWithClosure) callStack.loadUpValues(dispatchReceiver)
|
if (dispatchReceiver is StateWithClosure) callStack.loadUpValues(dispatchReceiver)
|
||||||
if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver)
|
if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver)
|
||||||
|
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
|
||||||
|
|
||||||
callInterceptor.interceptCall(call, irFunction, args) {
|
callInterceptor.interceptCall(call, irFunction, args) {
|
||||||
callStack.addInstruction(CompoundInstruction(irFunction))
|
callStack.addInstruction(CompoundInstruction(irFunction))
|
||||||
@@ -243,7 +243,16 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
val irClass = constructor.parentAsClass
|
val irClass = constructor.parentAsClass
|
||||||
val receiverSymbol = constructor.dispatchReceiverParameter?.symbol
|
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)
|
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
||||||
val outerClass = receiverSymbol?.let { callStack.getState(it) }
|
val outerClass = receiverSymbol?.let { callStack.getState(it) }
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ internal interface Complex : State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadOuterClassesInto(callStack: CallStack) {
|
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