Add configuration into IrInterpreterEnvironment
This configuration will contains all necessary setting for interpreter and will be replenished over time
This commit is contained in:
committed by
TeamCityServer
parent
b150cc9537
commit
cc56acc2c2
+1
-1
@@ -80,7 +80,7 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun unfoldFunction(function: IrSimpleFunction, environment: IrInterpreterEnvironment) {
|
private fun unfoldFunction(function: IrSimpleFunction, environment: IrInterpreterEnvironment) {
|
||||||
if (environment.callStack.getStackCount() >= IrInterpreterEnvironment.MAX_STACK)
|
if (environment.callStack.getStackCount() >= environment.configuration.maxStack)
|
||||||
return StackOverflowError().handleUserException(environment)
|
return StackOverflowError().handleUserException(environment)
|
||||||
// SimpleInstruction with function is added in IrCall
|
// SimpleInstruction with function is added in IrCall
|
||||||
// It will serve as endpoint for all possible calls, there we drop frame and copy result to new one
|
// It will serve as endpoint for all possible calls, there we drop frame and copy result to new one
|
||||||
|
|||||||
+7
-11
@@ -39,9 +39,7 @@ internal class CustomInstruction(val evaluate: () -> Unit) : Instruction {
|
|||||||
get() = null
|
get() = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class IrInterpreter private constructor(
|
class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val bodyMap: Map<IdSignature, IrBody>) {
|
||||||
internal val bodyMap: Map<IdSignature, IrBody>, internal val environment: IrInterpreterEnvironment
|
|
||||||
) {
|
|
||||||
val irBuiltIns: IrBuiltIns
|
val irBuiltIns: IrBuiltIns
|
||||||
get() = environment.irBuiltIns
|
get() = environment.irBuiltIns
|
||||||
private val callStack: CallStack
|
private val callStack: CallStack
|
||||||
@@ -50,16 +48,13 @@ class IrInterpreter private constructor(
|
|||||||
private var commandCount = 0
|
private var commandCount = 0
|
||||||
|
|
||||||
constructor(irBuiltIns: IrBuiltIns, bodyMap: Map<IdSignature, IrBody> = emptyMap()) :
|
constructor(irBuiltIns: IrBuiltIns, bodyMap: Map<IdSignature, IrBody> = emptyMap()) :
|
||||||
this(bodyMap, IrInterpreterEnvironment(irBuiltIns, CallStack()))
|
this(IrInterpreterEnvironment(irBuiltIns), bodyMap)
|
||||||
|
|
||||||
private constructor(environment: IrInterpreterEnvironment, bodyMap: Map<IdSignature, IrBody> = emptyMap()) :
|
constructor(irModule: IrModuleFragment) : this(IrInterpreterEnvironment(irModule), emptyMap())
|
||||||
this(bodyMap, environment)
|
|
||||||
|
|
||||||
constructor(irModule: IrModuleFragment) : this(emptyMap(), IrInterpreterEnvironment(irModule))
|
|
||||||
|
|
||||||
private fun incrementAndCheckCommands() {
|
private fun incrementAndCheckCommands() {
|
||||||
commandCount++
|
commandCount++
|
||||||
if (commandCount >= IrInterpreterEnvironment.MAX_COMMANDS) InterpreterTimeOutError().handleUserException(environment)
|
if (commandCount >= environment.configuration.maxCommands) InterpreterTimeOutError().handleUserException(environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getUnitState(): State = environment.mapOfObjects[irBuiltIns.unitClass]!!
|
private fun getUnitState(): State = environment.mapOfObjects[irBuiltIns.unitClass]!!
|
||||||
@@ -395,8 +390,9 @@ class IrInterpreter private constructor(
|
|||||||
environment.mapOfObjects[objectClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
environment.mapOfObjects[objectClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
||||||
callStack.addVariable(Variable(objectClass.thisReceiver!!.symbol, state))
|
callStack.addVariable(Variable(objectClass.thisReceiver!!.symbol, state))
|
||||||
|
|
||||||
// non compile time objects can be used in interpreter, for example, to evaluate const properties
|
// non compile time objects can be used in interpreter, for example, to evaluate const properties or in tests
|
||||||
if (!objectClass.hasAnnotation(compileTimeAnnotation)) return@interceptGetObjectValue callStack.pushState(state)
|
if (!objectClass.hasAnnotation(compileTimeAnnotation) && !environment.configuration.createNonCompileTimeObjects)
|
||||||
|
return@interceptGetObjectValue callStack.pushState(state)
|
||||||
|
|
||||||
val constructor = objectClass.constructors.firstOrNull() ?: return@interceptGetObjectValue callStack.pushState(state)
|
val constructor = objectClass.constructors.firstOrNull() ?: return@interceptGetObjectValue callStack.pushState(state)
|
||||||
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.ir.interpreter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxStack describes the maximum allowed call stack size
|
||||||
|
* @param maxCommands describes the maximum allowed number of simple instructions performed
|
||||||
|
* @param createNonCompileTimeObjects
|
||||||
|
* 'true' - interpreter will construct object and initialize its properties despite the fact it is not marked as compile time;
|
||||||
|
* 'false' - interpreter will create a representation of empty object, that can be used to get const properties
|
||||||
|
*/
|
||||||
|
// TODO maybe create some sort of builder
|
||||||
|
class IrInterpreterConfiguration(
|
||||||
|
val maxStack: Int = 10_000,
|
||||||
|
val maxCommands: Int = 1_000_000,
|
||||||
|
val createNonCompileTimeObjects: Boolean = false,
|
||||||
|
)
|
||||||
+10
-11
@@ -14,22 +14,26 @@ import org.jetbrains.kotlin.ir.interpreter.state.Complex
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||||
|
|
||||||
internal class IrInterpreterEnvironment(val irBuiltIns: IrBuiltIns, val callStack: CallStack) {
|
class IrInterpreterEnvironment(
|
||||||
val irExceptions = mutableListOf<IrClass>()
|
val irBuiltIns: IrBuiltIns,
|
||||||
var mapOfEnums = mutableMapOf<IrSymbol, Complex>()
|
val configuration: IrInterpreterConfiguration = IrInterpreterConfiguration(),
|
||||||
var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
|
) {
|
||||||
|
internal val callStack: CallStack = CallStack()
|
||||||
|
internal val irExceptions = mutableListOf<IrClass>()
|
||||||
|
internal var mapOfEnums = mutableMapOf<IrSymbol, Complex>()
|
||||||
|
internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner)
|
mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, CallStack()) {
|
private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, configuration = environment.configuration) {
|
||||||
irExceptions.addAll(environment.irExceptions)
|
irExceptions.addAll(environment.irExceptions)
|
||||||
mapOfEnums = environment.mapOfEnums
|
mapOfEnums = environment.mapOfEnums
|
||||||
mapOfObjects = environment.mapOfObjects
|
mapOfObjects = environment.mapOfObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(irModule: IrModuleFragment) : this(irModule.irBuiltins, CallStack()) {
|
constructor(irModule: IrModuleFragment) : this(irModule.irBuiltins) {
|
||||||
irExceptions.addAll(
|
irExceptions.addAll(
|
||||||
irModule.files
|
irModule.files
|
||||||
.flatMap { it.declarations }
|
.flatMap { it.declarations }
|
||||||
@@ -41,9 +45,4 @@ internal class IrInterpreterEnvironment(val irBuiltIns: IrBuiltIns, val callStac
|
|||||||
fun copyWithNewCallStack(): IrInterpreterEnvironment {
|
fun copyWithNewCallStack(): IrInterpreterEnvironment {
|
||||||
return IrInterpreterEnvironment(this)
|
return IrInterpreterEnvironment(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val MAX_STACK = 10_000
|
|
||||||
const val MAX_COMMANDS = 1_000_000
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user