VM optimizations
This commit is contained in:
parent
637258581d
commit
fd2da1efd3
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2026 Sergey S. Chernov
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -12,17 +12,12 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.sergeych.lyng
|
package net.sergeych.lyng
|
||||||
|
|
||||||
import net.sergeych.lyng.obj.Obj
|
import net.sergeych.lyng.obj.*
|
||||||
import net.sergeych.lyng.obj.ObjClass
|
|
||||||
import net.sergeych.lyng.obj.ObjException
|
|
||||||
import net.sergeych.lyng.obj.ObjInstance
|
|
||||||
import net.sergeych.lyng.obj.ObjInstanceClass
|
|
||||||
import net.sergeych.lyng.obj.ObjNull
|
|
||||||
import net.sergeych.lyng.obj.ObjRecord
|
|
||||||
|
|
||||||
data class ClassDeclBaseSpec(
|
data class ClassDeclBaseSpec(
|
||||||
val name: String,
|
val name: String,
|
||||||
@ -51,11 +46,16 @@ internal suspend fun executeClassDecl(
|
|||||||
bodyCaptureRecords: List<ObjRecord>? = null,
|
bodyCaptureRecords: List<ObjRecord>? = null,
|
||||||
bodyCaptureNames: List<String>? = null
|
bodyCaptureNames: List<String>? = null
|
||||||
): Obj {
|
): Obj {
|
||||||
|
fun checkClosedParents(parents: List<ObjClass>, pos: Pos) {
|
||||||
|
val closedParent = parents.firstOrNull { it.isClosed } ?: return
|
||||||
|
throw ScriptError(pos, "can't inherit from closed class ${closedParent.className}")
|
||||||
|
}
|
||||||
if (spec.isObject) {
|
if (spec.isObject) {
|
||||||
val parentClasses = spec.baseSpecs.map { baseSpec ->
|
val parentClasses = spec.baseSpecs.map { baseSpec ->
|
||||||
val rec = scope[baseSpec.name] ?: throw ScriptError(spec.startPos, "unknown base class: ${baseSpec.name}")
|
val rec = scope[baseSpec.name] ?: throw ScriptError(spec.startPos, "unknown base class: ${baseSpec.name}")
|
||||||
(rec.value as? ObjClass) ?: throw ScriptError(spec.startPos, "${baseSpec.name} is not a class")
|
(rec.value as? ObjClass) ?: throw ScriptError(spec.startPos, "${baseSpec.name} is not a class")
|
||||||
}
|
}
|
||||||
|
checkClosedParents(parentClasses, spec.startPos)
|
||||||
|
|
||||||
val newClass = ObjInstanceClass(spec.className, *parentClasses.toTypedArray())
|
val newClass = ObjInstanceClass(spec.className, *parentClasses.toTypedArray())
|
||||||
newClass.isAnonymous = spec.isAnonymous
|
newClass.isAnonymous = spec.isAnonymous
|
||||||
@ -106,6 +106,7 @@ internal suspend fun executeClassDecl(
|
|||||||
if (rec == null) throw ScriptError(spec.startPos, "unknown base class: ${baseSpec.name}")
|
if (rec == null) throw ScriptError(spec.startPos, "unknown base class: ${baseSpec.name}")
|
||||||
throw ScriptError(spec.startPos, "${baseSpec.name} is not a class")
|
throw ScriptError(spec.startPos, "${baseSpec.name} is not a class")
|
||||||
}
|
}
|
||||||
|
checkClosedParents(parentClasses, spec.startPos)
|
||||||
|
|
||||||
val constructorCode = object : Statement() {
|
val constructorCode = object : Statement() {
|
||||||
override val pos: Pos = spec.startPos
|
override val pos: Pos = spec.startPos
|
||||||
|
|||||||
@ -18,11 +18,7 @@
|
|||||||
package net.sergeych.lyng
|
package net.sergeych.lyng
|
||||||
|
|
||||||
import net.sergeych.lyng.Compiler.Companion.compile
|
import net.sergeych.lyng.Compiler.Companion.compile
|
||||||
import net.sergeych.lyng.bytecode.BytecodeStatement
|
import net.sergeych.lyng.bytecode.*
|
||||||
import net.sergeych.lyng.bytecode.ForcedLocalSlotInfo
|
|
||||||
import net.sergeych.lyng.bytecode.CmdListLiteral
|
|
||||||
import net.sergeych.lyng.bytecode.CmdMakeRange
|
|
||||||
import net.sergeych.lyng.bytecode.CmdRangeIntBounds
|
|
||||||
import net.sergeych.lyng.miniast.*
|
import net.sergeych.lyng.miniast.*
|
||||||
import net.sergeych.lyng.obj.*
|
import net.sergeych.lyng.obj.*
|
||||||
import net.sergeych.lyng.pacman.ImportManager
|
import net.sergeych.lyng.pacman.ImportManager
|
||||||
@ -1643,6 +1639,7 @@ class Compiler(
|
|||||||
forcedLocalSlotInfo = forcedLocalInfo,
|
forcedLocalSlotInfo = forcedLocalInfo,
|
||||||
forcedLocalScopeId = forcedLocalScopeId,
|
forcedLocalScopeId = forcedLocalScopeId,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
|
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||||
knownNameObjClass = knownClassMapForBytecode(),
|
knownNameObjClass = knownClassMapForBytecode(),
|
||||||
knownObjectNames = objectDeclNames,
|
knownObjectNames = objectDeclNames,
|
||||||
classFieldTypesByName = classFieldTypesByName,
|
classFieldTypesByName = classFieldTypesByName,
|
||||||
@ -1941,6 +1938,7 @@ class Compiler(
|
|||||||
scopeSlotNameSet = scopeSlotNameSet,
|
scopeSlotNameSet = scopeSlotNameSet,
|
||||||
moduleScopeId = moduleScopeId,
|
moduleScopeId = moduleScopeId,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
|
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||||
knownNameObjClass = knownClassMapForBytecode(),
|
knownNameObjClass = knownClassMapForBytecode(),
|
||||||
knownObjectNames = objectDeclNames,
|
knownObjectNames = objectDeclNames,
|
||||||
classFieldTypesByName = classFieldTypesByName,
|
classFieldTypesByName = classFieldTypesByName,
|
||||||
@ -1969,6 +1967,7 @@ class Compiler(
|
|||||||
scopeSlotNameSet = scopeSlotNameSet,
|
scopeSlotNameSet = scopeSlotNameSet,
|
||||||
moduleScopeId = moduleScopeId,
|
moduleScopeId = moduleScopeId,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
|
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||||
knownNameObjClass = knownClassMapForBytecode(),
|
knownNameObjClass = knownClassMapForBytecode(),
|
||||||
knownObjectNames = objectDeclNames,
|
knownObjectNames = objectDeclNames,
|
||||||
classFieldTypesByName = classFieldTypesByName,
|
classFieldTypesByName = classFieldTypesByName,
|
||||||
@ -2022,6 +2021,7 @@ class Compiler(
|
|||||||
globalSlotInfo = globalSlotInfo,
|
globalSlotInfo = globalSlotInfo,
|
||||||
globalSlotScopeId = globalSlotScopeId,
|
globalSlotScopeId = globalSlotScopeId,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
|
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||||
knownNameObjClass = knownNames,
|
knownNameObjClass = knownNames,
|
||||||
knownObjectNames = objectDeclNames,
|
knownObjectNames = objectDeclNames,
|
||||||
classFieldTypesByName = classFieldTypesByName,
|
classFieldTypesByName = classFieldTypesByName,
|
||||||
@ -7580,6 +7580,10 @@ class Compiler(
|
|||||||
val info = compileClassInfos[name] ?: return null
|
val info = compileClassInfos[name] ?: return null
|
||||||
val stub = compileClassStubs.getOrPut(info.name) {
|
val stub = compileClassStubs.getOrPut(info.name) {
|
||||||
val parents = info.baseNames.mapNotNull { resolveClassByName(it) }
|
val parents = info.baseNames.mapNotNull { resolveClassByName(it) }
|
||||||
|
val closedParent = parents.firstOrNull { it.isClosed }
|
||||||
|
if (closedParent != null) {
|
||||||
|
throw ScriptError(Pos.builtIn, "can't inherit from closed class ${closedParent.className}")
|
||||||
|
}
|
||||||
ObjInstanceClass(info.name, *parents.toTypedArray())
|
ObjInstanceClass(info.name, *parents.toTypedArray())
|
||||||
}
|
}
|
||||||
if (stub is ObjInstanceClass) {
|
if (stub is ObjInstanceClass) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,7 @@ class BytecodeStatement private constructor(
|
|||||||
callableReturnTypeByName: Map<String, ObjClass> = emptyMap(),
|
callableReturnTypeByName: Map<String, ObjClass> = emptyMap(),
|
||||||
externCallableNames: Set<String> = emptySet(),
|
externCallableNames: Set<String> = emptySet(),
|
||||||
lambdaCaptureEntriesByRef: Map<ValueFnRef, List<LambdaCaptureEntry>> = emptyMap(),
|
lambdaCaptureEntriesByRef: Map<ValueFnRef, List<LambdaCaptureEntry>> = emptyMap(),
|
||||||
|
slotTypeDeclByScopeId: Map<Int, Map<Int, TypeDecl>> = emptyMap(),
|
||||||
): Statement {
|
): Statement {
|
||||||
if (statement is BytecodeStatement) return statement
|
if (statement is BytecodeStatement) return statement
|
||||||
val hasUnsupported = containsUnsupportedStatement(statement)
|
val hasUnsupported = containsUnsupportedStatement(statement)
|
||||||
@ -83,6 +84,7 @@ class BytecodeStatement private constructor(
|
|||||||
globalSlotInfo = globalSlotInfo,
|
globalSlotInfo = globalSlotInfo,
|
||||||
globalSlotScopeId = globalSlotScopeId,
|
globalSlotScopeId = globalSlotScopeId,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
|
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||||
knownNameObjClass = knownNameObjClass,
|
knownNameObjClass = knownNameObjClass,
|
||||||
knownObjectNames = knownObjectNames,
|
knownObjectNames = knownObjectNames,
|
||||||
classFieldTypesByName = classFieldTypesByName,
|
classFieldTypesByName = classFieldTypesByName,
|
||||||
|
|||||||
@ -102,7 +102,7 @@ class CmdBuilder {
|
|||||||
}
|
}
|
||||||
operands[i] = v
|
operands[i] = v
|
||||||
}
|
}
|
||||||
cmds.add(createCmd(ins.op, operands, scopeSlotCount))
|
cmds.add(createCmd(ins.op, operands, scopeSlotCount, localSlotCaptures))
|
||||||
}
|
}
|
||||||
return CmdFunction(
|
return CmdFunction(
|
||||||
name = name,
|
name = name,
|
||||||
@ -128,6 +128,7 @@ class CmdBuilder {
|
|||||||
Opcode.NOP, Opcode.RET_VOID, Opcode.POP_SCOPE, Opcode.POP_SLOT_PLAN, Opcode.POP_TRY,
|
Opcode.NOP, Opcode.RET_VOID, Opcode.POP_SCOPE, Opcode.POP_SLOT_PLAN, Opcode.POP_TRY,
|
||||||
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING -> emptyList()
|
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING -> emptyList()
|
||||||
Opcode.MOVE_OBJ, Opcode.MOVE_INT, Opcode.MOVE_REAL, Opcode.MOVE_BOOL, Opcode.BOX_OBJ,
|
Opcode.MOVE_OBJ, Opcode.MOVE_INT, Opcode.MOVE_REAL, Opcode.MOVE_BOOL, Opcode.BOX_OBJ,
|
||||||
|
Opcode.UNBOX_INT_OBJ, Opcode.UNBOX_REAL_OBJ,
|
||||||
Opcode.INT_TO_REAL, Opcode.REAL_TO_INT, Opcode.BOOL_TO_INT, Opcode.INT_TO_BOOL,
|
Opcode.INT_TO_REAL, Opcode.REAL_TO_INT, Opcode.BOOL_TO_INT, Opcode.INT_TO_BOOL,
|
||||||
Opcode.OBJ_TO_BOOL, Opcode.GET_OBJ_CLASS,
|
Opcode.OBJ_TO_BOOL, Opcode.GET_OBJ_CLASS,
|
||||||
Opcode.NEG_INT, Opcode.NEG_REAL, Opcode.NOT_BOOL, Opcode.INV_INT,
|
Opcode.NEG_INT, Opcode.NEG_REAL, Opcode.NOT_BOOL, Opcode.INV_INT,
|
||||||
@ -179,7 +180,14 @@ class CmdBuilder {
|
|||||||
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
||||||
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
||||||
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
||||||
|
Opcode.CMP_EQ_STR, Opcode.CMP_NEQ_STR, Opcode.CMP_LT_STR, Opcode.CMP_LTE_STR,
|
||||||
|
Opcode.CMP_GT_STR, Opcode.CMP_GTE_STR,
|
||||||
|
Opcode.CMP_EQ_INT_OBJ, Opcode.CMP_NEQ_INT_OBJ, Opcode.CMP_LT_INT_OBJ, Opcode.CMP_LTE_INT_OBJ,
|
||||||
|
Opcode.CMP_GT_INT_OBJ, Opcode.CMP_GTE_INT_OBJ, Opcode.CMP_EQ_REAL_OBJ, Opcode.CMP_NEQ_REAL_OBJ,
|
||||||
|
Opcode.CMP_LT_REAL_OBJ, Opcode.CMP_LTE_REAL_OBJ, Opcode.CMP_GT_REAL_OBJ, Opcode.CMP_GTE_REAL_OBJ,
|
||||||
Opcode.CMP_LT_OBJ, Opcode.CMP_LTE_OBJ, Opcode.CMP_GT_OBJ, Opcode.CMP_GTE_OBJ,
|
Opcode.CMP_LT_OBJ, Opcode.CMP_LTE_OBJ, Opcode.CMP_GT_OBJ, Opcode.CMP_GTE_OBJ,
|
||||||
|
Opcode.ADD_INT_OBJ, Opcode.SUB_INT_OBJ, Opcode.MUL_INT_OBJ, Opcode.DIV_INT_OBJ, Opcode.MOD_INT_OBJ,
|
||||||
|
Opcode.ADD_REAL_OBJ, Opcode.SUB_REAL_OBJ, Opcode.MUL_REAL_OBJ, Opcode.DIV_REAL_OBJ, Opcode.MOD_REAL_OBJ,
|
||||||
Opcode.ADD_OBJ, Opcode.SUB_OBJ, Opcode.MUL_OBJ, Opcode.DIV_OBJ, Opcode.MOD_OBJ, Opcode.CONTAINS_OBJ,
|
Opcode.ADD_OBJ, Opcode.SUB_OBJ, Opcode.MUL_OBJ, Opcode.DIV_OBJ, Opcode.MOD_OBJ, Opcode.CONTAINS_OBJ,
|
||||||
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
||||||
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
||||||
@ -241,19 +249,37 @@ class CmdBuilder {
|
|||||||
ID,
|
ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCmd(op: Opcode, operands: IntArray, scopeSlotCount: Int): Cmd {
|
private fun createCmd(
|
||||||
|
op: Opcode,
|
||||||
|
operands: IntArray,
|
||||||
|
scopeSlotCount: Int,
|
||||||
|
localSlotCaptures: BooleanArray
|
||||||
|
): Cmd {
|
||||||
|
fun isFastLocal(slot: Int): Boolean {
|
||||||
|
if (slot < scopeSlotCount) return false
|
||||||
|
val localIndex = slot - scopeSlotCount
|
||||||
|
return localSlotCaptures.getOrNull(localIndex) != true
|
||||||
|
}
|
||||||
return when (op) {
|
return when (op) {
|
||||||
Opcode.NOP -> CmdNop()
|
Opcode.NOP -> CmdNop()
|
||||||
Opcode.MOVE_OBJ -> CmdMoveObj(operands[0], operands[1])
|
Opcode.MOVE_OBJ -> CmdMoveObj(operands[0], operands[1])
|
||||||
Opcode.MOVE_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount) {
|
Opcode.MOVE_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
CmdMoveIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
CmdMoveIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdMoveInt(operands[0], operands[1])
|
CmdMoveInt(operands[0], operands[1])
|
||||||
}
|
}
|
||||||
Opcode.MOVE_REAL -> CmdMoveReal(operands[0], operands[1])
|
Opcode.MOVE_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
Opcode.MOVE_BOOL -> CmdMoveBool(operands[0], operands[1])
|
CmdMoveRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdMoveReal(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.MOVE_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdMoveBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdMoveBool(operands[0], operands[1])
|
||||||
|
}
|
||||||
Opcode.CONST_OBJ -> CmdConstObj(operands[0], operands[1])
|
Opcode.CONST_OBJ -> CmdConstObj(operands[0], operands[1])
|
||||||
Opcode.CONST_INT -> if (operands[1] >= scopeSlotCount) {
|
Opcode.CONST_INT -> if (isFastLocal(operands[1])) {
|
||||||
CmdConstIntLocal(operands[0], operands[1] - scopeSlotCount)
|
CmdConstIntLocal(operands[0], operands[1] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdConstInt(operands[0], operands[1])
|
CmdConstInt(operands[0], operands[1])
|
||||||
@ -263,6 +289,16 @@ class CmdBuilder {
|
|||||||
Opcode.CONST_NULL -> CmdConstNull(operands[0])
|
Opcode.CONST_NULL -> CmdConstNull(operands[0])
|
||||||
Opcode.MAKE_LAMBDA_FN -> CmdMakeLambda(operands[0], operands[1])
|
Opcode.MAKE_LAMBDA_FN -> CmdMakeLambda(operands[0], operands[1])
|
||||||
Opcode.BOX_OBJ -> CmdBoxObj(operands[0], operands[1])
|
Opcode.BOX_OBJ -> CmdBoxObj(operands[0], operands[1])
|
||||||
|
Opcode.UNBOX_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdUnboxIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdUnboxIntObj(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.UNBOX_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdUnboxRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdUnboxRealObj(operands[0], operands[1])
|
||||||
|
}
|
||||||
Opcode.OBJ_TO_BOOL -> CmdObjToBool(operands[0], operands[1])
|
Opcode.OBJ_TO_BOOL -> CmdObjToBool(operands[0], operands[1])
|
||||||
Opcode.GET_OBJ_CLASS -> CmdGetObjClass(operands[0], operands[1])
|
Opcode.GET_OBJ_CLASS -> CmdGetObjClass(operands[0], operands[1])
|
||||||
Opcode.RANGE_INT_BOUNDS -> CmdRangeIntBounds(operands[0], operands[1], operands[2], operands[3])
|
Opcode.RANGE_INT_BOUNDS -> CmdRangeIntBounds(operands[0], operands[1], operands[2], operands[3])
|
||||||
@ -287,119 +323,419 @@ class CmdBuilder {
|
|||||||
Opcode.STORE_REAL_ADDR -> CmdStoreRealAddr(operands[0], operands[1])
|
Opcode.STORE_REAL_ADDR -> CmdStoreRealAddr(operands[0], operands[1])
|
||||||
Opcode.LOAD_BOOL_ADDR -> CmdLoadBoolAddr(operands[0], operands[1])
|
Opcode.LOAD_BOOL_ADDR -> CmdLoadBoolAddr(operands[0], operands[1])
|
||||||
Opcode.STORE_BOOL_ADDR -> CmdStoreBoolAddr(operands[0], operands[1])
|
Opcode.STORE_BOOL_ADDR -> CmdStoreBoolAddr(operands[0], operands[1])
|
||||||
Opcode.INT_TO_REAL -> CmdIntToReal(operands[0], operands[1])
|
Opcode.INT_TO_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
Opcode.REAL_TO_INT -> CmdRealToInt(operands[0], operands[1])
|
CmdIntToRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
Opcode.BOOL_TO_INT -> CmdBoolToInt(operands[0], operands[1])
|
} else {
|
||||||
Opcode.INT_TO_BOOL -> CmdIntToBool(operands[0], operands[1])
|
CmdIntToReal(operands[0], operands[1])
|
||||||
Opcode.ADD_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
}
|
||||||
|
Opcode.REAL_TO_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdRealToIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdRealToInt(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.BOOL_TO_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdBoolToIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdBoolToInt(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.INT_TO_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdIntToBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdIntToBool(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.ADD_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdAddIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdAddIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdAddInt(operands[0], operands[1], operands[2])
|
CmdAddInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.SUB_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.SUB_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdSubIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdSubIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdSubInt(operands[0], operands[1], operands[2])
|
CmdSubInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.MUL_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.MUL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdMulIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdMulIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdMulInt(operands[0], operands[1], operands[2])
|
CmdMulInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.DIV_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.DIV_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdDivIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdDivIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdDivInt(operands[0], operands[1], operands[2])
|
CmdDivInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.MOD_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.MOD_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdModIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdModIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdModInt(operands[0], operands[1], operands[2])
|
CmdModInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.NEG_INT -> CmdNegInt(operands[0], operands[1])
|
Opcode.NEG_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
Opcode.INC_INT -> if (operands[0] >= scopeSlotCount) {
|
CmdNegIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdNegInt(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.INC_INT -> if (isFastLocal(operands[0])) {
|
||||||
CmdIncIntLocal(operands[0] - scopeSlotCount)
|
CmdIncIntLocal(operands[0] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdIncInt(operands[0])
|
CmdIncInt(operands[0])
|
||||||
}
|
}
|
||||||
Opcode.DEC_INT -> if (operands[0] >= scopeSlotCount) {
|
Opcode.DEC_INT -> if (isFastLocal(operands[0])) {
|
||||||
CmdDecIntLocal(operands[0] - scopeSlotCount)
|
CmdDecIntLocal(operands[0] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdDecInt(operands[0])
|
CmdDecInt(operands[0])
|
||||||
}
|
}
|
||||||
Opcode.ADD_REAL -> CmdAddReal(operands[0], operands[1], operands[2])
|
Opcode.ADD_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.SUB_REAL -> CmdSubReal(operands[0], operands[1], operands[2])
|
CmdAddRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.MUL_REAL -> CmdMulReal(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.DIV_REAL -> CmdDivReal(operands[0], operands[1], operands[2])
|
CmdAddReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.NEG_REAL -> CmdNegReal(operands[0], operands[1])
|
}
|
||||||
Opcode.AND_INT -> CmdAndInt(operands[0], operands[1], operands[2])
|
Opcode.SUB_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.OR_INT -> CmdOrInt(operands[0], operands[1], operands[2])
|
CmdSubRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.XOR_INT -> CmdXorInt(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.SHL_INT -> CmdShlInt(operands[0], operands[1], operands[2])
|
CmdSubReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.SHR_INT -> CmdShrInt(operands[0], operands[1], operands[2])
|
}
|
||||||
Opcode.USHR_INT -> CmdUshrInt(operands[0], operands[1], operands[2])
|
Opcode.MUL_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.INV_INT -> CmdInvInt(operands[0], operands[1])
|
CmdMulRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.CMP_EQ_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
} else {
|
||||||
|
CmdMulReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.DIV_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdDivRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdDivReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.NEG_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdNegRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdNegReal(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.AND_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdAndIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdAndInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.OR_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdOrIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdOrInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.XOR_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdXorIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdXorInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.SHL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdShlIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdShlInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.SHR_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdShrIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdShrInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.USHR_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdUshrIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdUshrInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.INV_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdInvIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdInvInt(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpEqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpEqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpEqInt(operands[0], operands[1], operands[2])
|
CmdCmpEqInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_NEQ_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.CMP_NEQ_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpNeqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpNeqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpNeqInt(operands[0], operands[1], operands[2])
|
CmdCmpNeqInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_LT_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.CMP_LT_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpLtIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpLtIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpLtInt(operands[0], operands[1], operands[2])
|
CmdCmpLtInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_LTE_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.CMP_LTE_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpLteIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpLteIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpLteInt(operands[0], operands[1], operands[2])
|
CmdCmpLteInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_GT_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.CMP_GT_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpGtIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpGtIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpGtInt(operands[0], operands[1], operands[2])
|
CmdCmpGtInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_GTE_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
Opcode.CMP_GTE_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
CmdCmpGteIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
CmdCmpGteIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
} else {
|
} else {
|
||||||
CmdCmpGteInt(operands[0], operands[1], operands[2])
|
CmdCmpGteInt(operands[0], operands[1], operands[2])
|
||||||
}
|
}
|
||||||
Opcode.CMP_EQ_REAL -> CmdCmpEqReal(operands[0], operands[1], operands[2])
|
Opcode.CMP_EQ_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.CMP_NEQ_REAL -> CmdCmpNeqReal(operands[0], operands[1], operands[2])
|
CmdCmpEqRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.CMP_LT_REAL -> CmdCmpLtReal(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.CMP_LTE_REAL -> CmdCmpLteReal(operands[0], operands[1], operands[2])
|
CmdCmpEqReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_GT_REAL -> CmdCmpGtReal(operands[0], operands[1], operands[2])
|
}
|
||||||
Opcode.CMP_GTE_REAL -> CmdCmpGteReal(operands[0], operands[1], operands[2])
|
Opcode.CMP_NEQ_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.CMP_EQ_BOOL -> CmdCmpEqBool(operands[0], operands[1], operands[2])
|
CmdCmpNeqRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.CMP_NEQ_BOOL -> CmdCmpNeqBool(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.CMP_EQ_INT_REAL -> CmdCmpEqIntReal(operands[0], operands[1], operands[2])
|
CmdCmpNeqReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_EQ_REAL_INT -> CmdCmpEqRealInt(operands[0], operands[1], operands[2])
|
}
|
||||||
Opcode.CMP_LT_INT_REAL -> CmdCmpLtIntReal(operands[0], operands[1], operands[2])
|
Opcode.CMP_LT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.CMP_LT_REAL_INT -> CmdCmpLtRealInt(operands[0], operands[1], operands[2])
|
CmdCmpLtRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.CMP_LTE_INT_REAL -> CmdCmpLteIntReal(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.CMP_LTE_REAL_INT -> CmdCmpLteRealInt(operands[0], operands[1], operands[2])
|
CmdCmpLtReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_GT_INT_REAL -> CmdCmpGtIntReal(operands[0], operands[1], operands[2])
|
}
|
||||||
Opcode.CMP_GT_REAL_INT -> CmdCmpGtRealInt(operands[0], operands[1], operands[2])
|
Opcode.CMP_LTE_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.CMP_GTE_INT_REAL -> CmdCmpGteIntReal(operands[0], operands[1], operands[2])
|
CmdCmpLteRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.CMP_GTE_REAL_INT -> CmdCmpGteRealInt(operands[0], operands[1], operands[2])
|
} else {
|
||||||
Opcode.CMP_NEQ_INT_REAL -> CmdCmpNeqIntReal(operands[0], operands[1], operands[2])
|
CmdCmpLteReal(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_NEQ_REAL_INT -> CmdCmpNeqRealInt(operands[0], operands[1], operands[2])
|
}
|
||||||
|
Opcode.CMP_GT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpEqBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpEqBool(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqBool(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpEqIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpEqIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpEqRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpEqRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LT_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLtIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLtIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LT_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLtRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLtRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LTE_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLteIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLteIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LTE_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLteRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLteRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GT_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GT_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_INT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqIntRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqIntReal(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_REAL_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqRealIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqRealInt(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
Opcode.CMP_EQ_OBJ -> CmdCmpEqObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_EQ_OBJ -> CmdCmpEqObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_NEQ_OBJ -> CmdCmpNeqObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_NEQ_OBJ -> CmdCmpNeqObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_REF_EQ_OBJ -> CmdCmpRefEqObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_REF_EQ_OBJ -> CmdCmpRefEqObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_REF_NEQ_OBJ -> CmdCmpRefNeqObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_REF_NEQ_OBJ -> CmdCmpRefNeqObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.NOT_BOOL -> CmdNotBool(operands[0], operands[1])
|
Opcode.CMP_EQ_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
Opcode.AND_BOOL -> CmdAndBool(operands[0], operands[1], operands[2])
|
CmdCmpEqStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
Opcode.OR_BOOL -> CmdOrBool(operands[0], operands[1], operands[2])
|
} else {
|
||||||
|
CmdCmpEqStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LT_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLtStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLtStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LTE_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLteStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLteStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GT_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteStr(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpEqIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpEqIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LT_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLtIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLtIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LTE_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLteIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLteIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GT_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_EQ_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpEqRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpEqRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_NEQ_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpNeqRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpNeqRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LT_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLtRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLtRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_LTE_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpLteRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpLteRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GT_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGtRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGtRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.CMP_GTE_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdCmpGteRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdCmpGteRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.NOT_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||||
|
CmdNotBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdNotBool(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.AND_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdAndBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdAndBool(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.OR_BOOL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdOrBoolLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdOrBool(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
Opcode.CMP_LT_OBJ -> CmdCmpLtObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_LT_OBJ -> CmdCmpLtObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_LTE_OBJ -> CmdCmpLteObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_LTE_OBJ -> CmdCmpLteObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_GT_OBJ -> CmdCmpGtObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_GT_OBJ -> CmdCmpGtObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.CMP_GTE_OBJ -> CmdCmpGteObj(operands[0], operands[1], operands[2])
|
Opcode.CMP_GTE_OBJ -> CmdCmpGteObj(operands[0], operands[1], operands[2])
|
||||||
|
Opcode.ADD_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdAddIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdAddIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.SUB_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdSubIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdSubIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.MUL_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdMulIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdMulIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.DIV_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdDivIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdDivIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.MOD_INT_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdModIntObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdModIntObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.ADD_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdAddRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdAddRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.SUB_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdSubRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdSubRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.MUL_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdMulRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdMulRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.DIV_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdDivRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdDivRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
|
Opcode.MOD_REAL_OBJ -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||||
|
CmdModRealObjLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||||
|
} else {
|
||||||
|
CmdModRealObj(operands[0], operands[1], operands[2])
|
||||||
|
}
|
||||||
Opcode.ADD_OBJ -> CmdAddObj(operands[0], operands[1], operands[2])
|
Opcode.ADD_OBJ -> CmdAddObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.SUB_OBJ -> CmdSubObj(operands[0], operands[1], operands[2])
|
Opcode.SUB_OBJ -> CmdSubObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.MUL_OBJ -> CmdMulObj(operands[0], operands[1], operands[2])
|
Opcode.MUL_OBJ -> CmdMulObj(operands[0], operands[1], operands[2])
|
||||||
@ -408,8 +744,16 @@ class CmdBuilder {
|
|||||||
Opcode.CONTAINS_OBJ -> CmdContainsObj(operands[0], operands[1], operands[2])
|
Opcode.CONTAINS_OBJ -> CmdContainsObj(operands[0], operands[1], operands[2])
|
||||||
Opcode.ASSIGN_OP_OBJ -> CmdAssignOpObj(operands[0], operands[1], operands[2], operands[3], operands[4])
|
Opcode.ASSIGN_OP_OBJ -> CmdAssignOpObj(operands[0], operands[1], operands[2], operands[3], operands[4])
|
||||||
Opcode.JMP -> CmdJmp(operands[0])
|
Opcode.JMP -> CmdJmp(operands[0])
|
||||||
Opcode.JMP_IF_TRUE -> CmdJmpIfTrue(operands[0], operands[1])
|
Opcode.JMP_IF_TRUE -> if (operands[0] >= scopeSlotCount) {
|
||||||
Opcode.JMP_IF_FALSE -> CmdJmpIfFalse(operands[0], operands[1])
|
CmdJmpIfTrueLocal(operands[0] - scopeSlotCount, operands[1])
|
||||||
|
} else {
|
||||||
|
CmdJmpIfTrue(operands[0], operands[1])
|
||||||
|
}
|
||||||
|
Opcode.JMP_IF_FALSE -> if (operands[0] >= scopeSlotCount) {
|
||||||
|
CmdJmpIfFalseLocal(operands[0] - scopeSlotCount, operands[1])
|
||||||
|
} else {
|
||||||
|
CmdJmpIfFalse(operands[0], operands[1])
|
||||||
|
}
|
||||||
Opcode.JMP_IF_EQ_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount) {
|
Opcode.JMP_IF_EQ_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount) {
|
||||||
CmdJmpIfEqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2])
|
CmdJmpIfEqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2])
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2026 Sergey S. Chernov
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.sergeych.lyng.bytecode
|
package net.sergeych.lyng.bytecode
|
||||||
@ -76,6 +77,8 @@ object CmdDisassembler {
|
|||||||
is CmdMoveObj -> Opcode.MOVE_OBJ to intArrayOf(cmd.src, cmd.dst)
|
is CmdMoveObj -> Opcode.MOVE_OBJ to intArrayOf(cmd.src, cmd.dst)
|
||||||
is CmdMoveInt -> Opcode.MOVE_INT to intArrayOf(cmd.src, cmd.dst)
|
is CmdMoveInt -> Opcode.MOVE_INT to intArrayOf(cmd.src, cmd.dst)
|
||||||
is CmdMoveIntLocal -> Opcode.MOVE_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
is CmdMoveIntLocal -> Opcode.MOVE_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
|
is CmdMoveRealLocal -> Opcode.MOVE_REAL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
|
is CmdMoveBoolLocal -> Opcode.MOVE_BOOL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdMoveReal -> Opcode.MOVE_REAL to intArrayOf(cmd.src, cmd.dst)
|
is CmdMoveReal -> Opcode.MOVE_REAL to intArrayOf(cmd.src, cmd.dst)
|
||||||
is CmdMoveBool -> Opcode.MOVE_BOOL to intArrayOf(cmd.src, cmd.dst)
|
is CmdMoveBool -> Opcode.MOVE_BOOL to intArrayOf(cmd.src, cmd.dst)
|
||||||
is CmdConstObj -> Opcode.CONST_OBJ to intArrayOf(cmd.constId, cmd.dst)
|
is CmdConstObj -> Opcode.CONST_OBJ to intArrayOf(cmd.constId, cmd.dst)
|
||||||
@ -114,9 +117,13 @@ object CmdDisassembler {
|
|||||||
is CmdLoadBoolAddr -> Opcode.LOAD_BOOL_ADDR to intArrayOf(cmd.addrSlot, cmd.dst)
|
is CmdLoadBoolAddr -> Opcode.LOAD_BOOL_ADDR to intArrayOf(cmd.addrSlot, cmd.dst)
|
||||||
is CmdStoreBoolAddr -> Opcode.STORE_BOOL_ADDR to intArrayOf(cmd.src, cmd.addrSlot)
|
is CmdStoreBoolAddr -> Opcode.STORE_BOOL_ADDR to intArrayOf(cmd.src, cmd.addrSlot)
|
||||||
is CmdIntToReal -> Opcode.INT_TO_REAL to intArrayOf(cmd.src, cmd.dst)
|
is CmdIntToReal -> Opcode.INT_TO_REAL to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdIntToRealLocal -> Opcode.INT_TO_REAL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdRealToInt -> Opcode.REAL_TO_INT to intArrayOf(cmd.src, cmd.dst)
|
is CmdRealToInt -> Opcode.REAL_TO_INT to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdRealToIntLocal -> Opcode.REAL_TO_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdBoolToInt -> Opcode.BOOL_TO_INT to intArrayOf(cmd.src, cmd.dst)
|
is CmdBoolToInt -> Opcode.BOOL_TO_INT to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdBoolToIntLocal -> Opcode.BOOL_TO_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdIntToBool -> Opcode.INT_TO_BOOL to intArrayOf(cmd.src, cmd.dst)
|
is CmdIntToBool -> Opcode.INT_TO_BOOL to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdIntToBoolLocal -> Opcode.INT_TO_BOOL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdAddInt -> Opcode.ADD_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdAddInt -> Opcode.ADD_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdAddIntLocal -> Opcode.ADD_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
is CmdAddIntLocal -> Opcode.ADD_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdSubInt -> Opcode.SUB_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdSubInt -> Opcode.SUB_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
@ -128,22 +135,35 @@ object CmdDisassembler {
|
|||||||
is CmdModInt -> Opcode.MOD_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdModInt -> Opcode.MOD_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdModIntLocal -> Opcode.MOD_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
is CmdModIntLocal -> Opcode.MOD_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdNegInt -> Opcode.NEG_INT to intArrayOf(cmd.src, cmd.dst)
|
is CmdNegInt -> Opcode.NEG_INT to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdNegIntLocal -> Opcode.NEG_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdIncInt -> Opcode.INC_INT to intArrayOf(cmd.slot)
|
is CmdIncInt -> Opcode.INC_INT to intArrayOf(cmd.slot)
|
||||||
is CmdIncIntLocal -> Opcode.INC_INT to intArrayOf(cmd.slot + fn.scopeSlotCount)
|
is CmdIncIntLocal -> Opcode.INC_INT to intArrayOf(cmd.slot + fn.scopeSlotCount)
|
||||||
is CmdDecInt -> Opcode.DEC_INT to intArrayOf(cmd.slot)
|
is CmdDecInt -> Opcode.DEC_INT to intArrayOf(cmd.slot)
|
||||||
is CmdDecIntLocal -> Opcode.DEC_INT to intArrayOf(cmd.slot + fn.scopeSlotCount)
|
is CmdDecIntLocal -> Opcode.DEC_INT to intArrayOf(cmd.slot + fn.scopeSlotCount)
|
||||||
is CmdAddReal -> Opcode.ADD_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdAddReal -> Opcode.ADD_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAddRealLocal -> Opcode.ADD_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdSubReal -> Opcode.SUB_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdSubReal -> Opcode.SUB_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdSubRealLocal -> Opcode.SUB_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdMulReal -> Opcode.MUL_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdMulReal -> Opcode.MUL_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdMulRealLocal -> Opcode.MUL_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdDivReal -> Opcode.DIV_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdDivReal -> Opcode.DIV_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdDivRealLocal -> Opcode.DIV_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdNegReal -> Opcode.NEG_REAL to intArrayOf(cmd.src, cmd.dst)
|
is CmdNegReal -> Opcode.NEG_REAL to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdNegRealLocal -> Opcode.NEG_REAL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdAndInt -> Opcode.AND_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdAndInt -> Opcode.AND_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAndIntLocal -> Opcode.AND_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdOrInt -> Opcode.OR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdOrInt -> Opcode.OR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdOrIntLocal -> Opcode.OR_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdXorInt -> Opcode.XOR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdXorInt -> Opcode.XOR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdXorIntLocal -> Opcode.XOR_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdShlInt -> Opcode.SHL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdShlInt -> Opcode.SHL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdShlIntLocal -> Opcode.SHL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdShrInt -> Opcode.SHR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdShrInt -> Opcode.SHR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdShrIntLocal -> Opcode.SHR_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdUshrInt -> Opcode.USHR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdUshrInt -> Opcode.USHR_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdUshrIntLocal -> Opcode.USHR_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdInvInt -> Opcode.INV_INT to intArrayOf(cmd.src, cmd.dst)
|
is CmdInvInt -> Opcode.INV_INT to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdInvIntLocal -> Opcode.INV_INT to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpEqInt -> Opcode.CMP_EQ_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpEqInt -> Opcode.CMP_EQ_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpEqIntLocal -> Opcode.CMP_EQ_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
is CmdCmpEqIntLocal -> Opcode.CMP_EQ_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpNeqInt -> Opcode.CMP_NEQ_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqInt -> Opcode.CMP_NEQ_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
@ -157,25 +177,45 @@ object CmdDisassembler {
|
|||||||
is CmdCmpGteInt -> Opcode.CMP_GTE_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGteInt -> Opcode.CMP_GTE_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpGteIntLocal -> Opcode.CMP_GTE_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
is CmdCmpGteIntLocal -> Opcode.CMP_GTE_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpEqReal -> Opcode.CMP_EQ_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpEqReal -> Opcode.CMP_EQ_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqRealLocal -> Opcode.CMP_EQ_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpNeqReal -> Opcode.CMP_NEQ_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqReal -> Opcode.CMP_NEQ_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqRealLocal -> Opcode.CMP_NEQ_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLtReal -> Opcode.CMP_LT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLtReal -> Opcode.CMP_LT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtRealLocal -> Opcode.CMP_LT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLteReal -> Opcode.CMP_LTE_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLteReal -> Opcode.CMP_LTE_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteRealLocal -> Opcode.CMP_LTE_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGtReal -> Opcode.CMP_GT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGtReal -> Opcode.CMP_GT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtRealLocal -> Opcode.CMP_GT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGteReal -> Opcode.CMP_GTE_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGteReal -> Opcode.CMP_GTE_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteRealLocal -> Opcode.CMP_GTE_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpEqBool -> Opcode.CMP_EQ_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpEqBool -> Opcode.CMP_EQ_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqBoolLocal -> Opcode.CMP_EQ_BOOL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpNeqBool -> Opcode.CMP_NEQ_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqBool -> Opcode.CMP_NEQ_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqBoolLocal -> Opcode.CMP_NEQ_BOOL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpEqIntReal -> Opcode.CMP_EQ_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpEqIntReal -> Opcode.CMP_EQ_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqIntRealLocal -> Opcode.CMP_EQ_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpEqRealInt -> Opcode.CMP_EQ_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpEqRealInt -> Opcode.CMP_EQ_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqRealIntLocal -> Opcode.CMP_EQ_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLtIntReal -> Opcode.CMP_LT_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLtIntReal -> Opcode.CMP_LT_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtIntRealLocal -> Opcode.CMP_LT_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLtRealInt -> Opcode.CMP_LT_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLtRealInt -> Opcode.CMP_LT_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtRealIntLocal -> Opcode.CMP_LT_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLteIntReal -> Opcode.CMP_LTE_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLteIntReal -> Opcode.CMP_LTE_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteIntRealLocal -> Opcode.CMP_LTE_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpLteRealInt -> Opcode.CMP_LTE_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLteRealInt -> Opcode.CMP_LTE_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteRealIntLocal -> Opcode.CMP_LTE_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGtIntReal -> Opcode.CMP_GT_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGtIntReal -> Opcode.CMP_GT_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtIntRealLocal -> Opcode.CMP_GT_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGtRealInt -> Opcode.CMP_GT_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGtRealInt -> Opcode.CMP_GT_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtRealIntLocal -> Opcode.CMP_GT_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGteIntReal -> Opcode.CMP_GTE_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGteIntReal -> Opcode.CMP_GTE_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteIntRealLocal -> Opcode.CMP_GTE_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpGteRealInt -> Opcode.CMP_GTE_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGteRealInt -> Opcode.CMP_GTE_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteRealIntLocal -> Opcode.CMP_GTE_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpNeqIntReal -> Opcode.CMP_NEQ_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqIntReal -> Opcode.CMP_NEQ_INT_REAL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqIntRealLocal -> Opcode.CMP_NEQ_INT_REAL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdCmpNeqRealInt -> Opcode.CMP_NEQ_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqRealInt -> Opcode.CMP_NEQ_REAL_INT to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqRealIntLocal -> Opcode.CMP_NEQ_REAL_INT to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdJmpIfEqInt -> Opcode.JMP_IF_EQ_INT to intArrayOf(cmd.a, cmd.b, cmd.target)
|
is CmdJmpIfEqInt -> Opcode.JMP_IF_EQ_INT to intArrayOf(cmd.a, cmd.b, cmd.target)
|
||||||
is CmdJmpIfEqIntLocal -> Opcode.JMP_IF_EQ_INT to intArrayOf(
|
is CmdJmpIfEqIntLocal -> Opcode.JMP_IF_EQ_INT to intArrayOf(
|
||||||
cmd.a + fn.scopeSlotCount,
|
cmd.a + fn.scopeSlotCount,
|
||||||
@ -216,13 +256,194 @@ object CmdDisassembler {
|
|||||||
is CmdCmpNeqObj -> Opcode.CMP_NEQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpNeqObj -> Opcode.CMP_NEQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpRefEqObj -> Opcode.CMP_REF_EQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpRefEqObj -> Opcode.CMP_REF_EQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpRefNeqObj -> Opcode.CMP_REF_NEQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpRefNeqObj -> Opcode.CMP_REF_NEQ_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqStr -> Opcode.CMP_EQ_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqStrLocal -> Opcode.CMP_EQ_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpNeqStr -> Opcode.CMP_NEQ_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqStrLocal -> Opcode.CMP_NEQ_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLtStr -> Opcode.CMP_LT_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtStrLocal -> Opcode.CMP_LT_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLteStr -> Opcode.CMP_LTE_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteStrLocal -> Opcode.CMP_LTE_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGtStr -> Opcode.CMP_GT_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtStrLocal -> Opcode.CMP_GT_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGteStr -> Opcode.CMP_GTE_STR to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteStrLocal -> Opcode.CMP_GTE_STR to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpEqIntObj -> Opcode.CMP_EQ_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqIntObjLocal -> Opcode.CMP_EQ_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpNeqIntObj -> Opcode.CMP_NEQ_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqIntObjLocal -> Opcode.CMP_NEQ_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLtIntObj -> Opcode.CMP_LT_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtIntObjLocal -> Opcode.CMP_LT_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLteIntObj -> Opcode.CMP_LTE_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteIntObjLocal -> Opcode.CMP_LTE_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGtIntObj -> Opcode.CMP_GT_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtIntObjLocal -> Opcode.CMP_GT_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGteIntObj -> Opcode.CMP_GTE_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteIntObjLocal -> Opcode.CMP_GTE_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpEqRealObj -> Opcode.CMP_EQ_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpEqRealObjLocal -> Opcode.CMP_EQ_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpNeqRealObj -> Opcode.CMP_NEQ_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpNeqRealObjLocal -> Opcode.CMP_NEQ_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLtRealObj -> Opcode.CMP_LT_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLtRealObjLocal -> Opcode.CMP_LT_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpLteRealObj -> Opcode.CMP_LTE_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpLteRealObjLocal -> Opcode.CMP_LTE_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGtRealObj -> Opcode.CMP_GT_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGtRealObjLocal -> Opcode.CMP_GT_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdCmpGteRealObj -> Opcode.CMP_GTE_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdCmpGteRealObjLocal -> Opcode.CMP_GTE_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
is CmdNotBool -> Opcode.NOT_BOOL to intArrayOf(cmd.src, cmd.dst)
|
is CmdNotBool -> Opcode.NOT_BOOL to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdNotBoolLocal -> Opcode.NOT_BOOL to intArrayOf(cmd.src + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdAndBool -> Opcode.AND_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdAndBool -> Opcode.AND_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAndBoolLocal -> Opcode.AND_BOOL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
is CmdOrBool -> Opcode.OR_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdOrBool -> Opcode.OR_BOOL to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdOrBoolLocal -> Opcode.OR_BOOL to intArrayOf(cmd.a + fn.scopeSlotCount, cmd.b + fn.scopeSlotCount, cmd.dst + fn.scopeSlotCount)
|
||||||
|
is CmdUnboxIntObj -> Opcode.UNBOX_INT_OBJ to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdUnboxIntObjLocal -> Opcode.UNBOX_INT_OBJ to intArrayOf(
|
||||||
|
cmd.src + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdUnboxRealObj -> Opcode.UNBOX_REAL_OBJ to intArrayOf(cmd.src, cmd.dst)
|
||||||
|
is CmdUnboxRealObjLocal -> Opcode.UNBOX_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.src + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
is CmdCmpLtObj -> Opcode.CMP_LT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLtObj -> Opcode.CMP_LT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpLteObj -> Opcode.CMP_LTE_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpLteObj -> Opcode.CMP_LTE_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpGtObj -> Opcode.CMP_GT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGtObj -> Opcode.CMP_GT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdCmpGteObj -> Opcode.CMP_GTE_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdCmpGteObj -> Opcode.CMP_GTE_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAddIntObj -> Opcode.ADD_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAddIntObjLocal -> Opcode.ADD_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdSubIntObj -> Opcode.SUB_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdSubIntObjLocal -> Opcode.SUB_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdMulIntObj -> Opcode.MUL_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdMulIntObjLocal -> Opcode.MUL_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdDivIntObj -> Opcode.DIV_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdDivIntObjLocal -> Opcode.DIV_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdModIntObj -> Opcode.MOD_INT_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdModIntObjLocal -> Opcode.MOD_INT_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdAddRealObj -> Opcode.ADD_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdAddRealObjLocal -> Opcode.ADD_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdSubRealObj -> Opcode.SUB_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdSubRealObjLocal -> Opcode.SUB_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdMulRealObj -> Opcode.MUL_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdMulRealObjLocal -> Opcode.MUL_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdDivRealObj -> Opcode.DIV_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdDivRealObjLocal -> Opcode.DIV_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
|
is CmdModRealObj -> Opcode.MOD_REAL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
|
is CmdModRealObjLocal -> Opcode.MOD_REAL_OBJ to intArrayOf(
|
||||||
|
cmd.a + fn.scopeSlotCount,
|
||||||
|
cmd.b + fn.scopeSlotCount,
|
||||||
|
cmd.dst + fn.scopeSlotCount
|
||||||
|
)
|
||||||
is CmdAddObj -> Opcode.ADD_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdAddObj -> Opcode.ADD_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdSubObj -> Opcode.SUB_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdSubObj -> Opcode.SUB_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
is CmdMulObj -> Opcode.MUL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
is CmdMulObj -> Opcode.MUL_OBJ to intArrayOf(cmd.a, cmd.b, cmd.dst)
|
||||||
@ -232,7 +453,9 @@ object CmdDisassembler {
|
|||||||
is CmdAssignOpObj -> Opcode.ASSIGN_OP_OBJ to intArrayOf(cmd.opId, cmd.targetSlot, cmd.valueSlot, cmd.dst, cmd.nameId)
|
is CmdAssignOpObj -> Opcode.ASSIGN_OP_OBJ to intArrayOf(cmd.opId, cmd.targetSlot, cmd.valueSlot, cmd.dst, cmd.nameId)
|
||||||
is CmdJmp -> Opcode.JMP to intArrayOf(cmd.target)
|
is CmdJmp -> Opcode.JMP to intArrayOf(cmd.target)
|
||||||
is CmdJmpIfTrue -> Opcode.JMP_IF_TRUE to intArrayOf(cmd.cond, cmd.target)
|
is CmdJmpIfTrue -> Opcode.JMP_IF_TRUE to intArrayOf(cmd.cond, cmd.target)
|
||||||
|
is CmdJmpIfTrueLocal -> Opcode.JMP_IF_TRUE to intArrayOf(cmd.cond + fn.scopeSlotCount, cmd.target)
|
||||||
is CmdJmpIfFalse -> Opcode.JMP_IF_FALSE to intArrayOf(cmd.cond, cmd.target)
|
is CmdJmpIfFalse -> Opcode.JMP_IF_FALSE to intArrayOf(cmd.cond, cmd.target)
|
||||||
|
is CmdJmpIfFalseLocal -> Opcode.JMP_IF_FALSE to intArrayOf(cmd.cond + fn.scopeSlotCount, cmd.target)
|
||||||
is CmdRet -> Opcode.RET to intArrayOf(cmd.slot)
|
is CmdRet -> Opcode.RET to intArrayOf(cmd.slot)
|
||||||
is CmdRetLabel -> Opcode.RET_LABEL to intArrayOf(cmd.labelId, cmd.slot)
|
is CmdRetLabel -> Opcode.RET_LABEL to intArrayOf(cmd.labelId, cmd.slot)
|
||||||
is CmdRetVoid -> Opcode.RET_VOID to intArrayOf()
|
is CmdRetVoid -> Opcode.RET_VOID to intArrayOf()
|
||||||
@ -298,6 +521,7 @@ object CmdDisassembler {
|
|||||||
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING,
|
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING,
|
||||||
Opcode.ITER_POP, Opcode.ITER_CANCEL -> emptyList()
|
Opcode.ITER_POP, Opcode.ITER_CANCEL -> emptyList()
|
||||||
Opcode.MOVE_OBJ, Opcode.MOVE_INT, Opcode.MOVE_REAL, Opcode.MOVE_BOOL, Opcode.BOX_OBJ,
|
Opcode.MOVE_OBJ, Opcode.MOVE_INT, Opcode.MOVE_REAL, Opcode.MOVE_BOOL, Opcode.BOX_OBJ,
|
||||||
|
Opcode.UNBOX_INT_OBJ, Opcode.UNBOX_REAL_OBJ,
|
||||||
Opcode.INT_TO_REAL, Opcode.REAL_TO_INT, Opcode.BOOL_TO_INT, Opcode.INT_TO_BOOL,
|
Opcode.INT_TO_REAL, Opcode.REAL_TO_INT, Opcode.BOOL_TO_INT, Opcode.INT_TO_BOOL,
|
||||||
Opcode.NEG_INT, Opcode.NEG_REAL, Opcode.NOT_BOOL, Opcode.INV_INT ->
|
Opcode.NEG_INT, Opcode.NEG_REAL, Opcode.NOT_BOOL, Opcode.INV_INT ->
|
||||||
listOf(OperandKind.SLOT, OperandKind.SLOT)
|
listOf(OperandKind.SLOT, OperandKind.SLOT)
|
||||||
@ -351,7 +575,14 @@ object CmdDisassembler {
|
|||||||
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
||||||
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
||||||
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
||||||
|
Opcode.CMP_EQ_STR, Opcode.CMP_NEQ_STR, Opcode.CMP_LT_STR, Opcode.CMP_LTE_STR,
|
||||||
|
Opcode.CMP_GT_STR, Opcode.CMP_GTE_STR,
|
||||||
|
Opcode.CMP_EQ_INT_OBJ, Opcode.CMP_NEQ_INT_OBJ, Opcode.CMP_LT_INT_OBJ, Opcode.CMP_LTE_INT_OBJ,
|
||||||
|
Opcode.CMP_GT_INT_OBJ, Opcode.CMP_GTE_INT_OBJ, Opcode.CMP_EQ_REAL_OBJ, Opcode.CMP_NEQ_REAL_OBJ,
|
||||||
|
Opcode.CMP_LT_REAL_OBJ, Opcode.CMP_LTE_REAL_OBJ, Opcode.CMP_GT_REAL_OBJ, Opcode.CMP_GTE_REAL_OBJ,
|
||||||
Opcode.CMP_LT_OBJ, Opcode.CMP_LTE_OBJ, Opcode.CMP_GT_OBJ, Opcode.CMP_GTE_OBJ,
|
Opcode.CMP_LT_OBJ, Opcode.CMP_LTE_OBJ, Opcode.CMP_GT_OBJ, Opcode.CMP_GTE_OBJ,
|
||||||
|
Opcode.ADD_INT_OBJ, Opcode.SUB_INT_OBJ, Opcode.MUL_INT_OBJ, Opcode.DIV_INT_OBJ, Opcode.MOD_INT_OBJ,
|
||||||
|
Opcode.ADD_REAL_OBJ, Opcode.SUB_REAL_OBJ, Opcode.MUL_REAL_OBJ, Opcode.DIV_REAL_OBJ, Opcode.MOD_REAL_OBJ,
|
||||||
Opcode.ADD_OBJ, Opcode.SUB_OBJ, Opcode.MUL_OBJ, Opcode.DIV_OBJ, Opcode.MOD_OBJ, Opcode.CONTAINS_OBJ,
|
Opcode.ADD_OBJ, Opcode.SUB_OBJ, Opcode.MUL_OBJ, Opcode.DIV_OBJ, Opcode.MOD_OBJ, Opcode.CONTAINS_OBJ,
|
||||||
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
||||||
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2026 Sergey S. Chernov
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.sergeych.lyng.bytecode
|
package net.sergeych.lyng.bytecode
|
||||||
@ -98,6 +99,36 @@ enum class Opcode(val code: Int) {
|
|||||||
CMP_NEQ_OBJ(0x6D),
|
CMP_NEQ_OBJ(0x6D),
|
||||||
CMP_REF_EQ_OBJ(0x6E),
|
CMP_REF_EQ_OBJ(0x6E),
|
||||||
CMP_REF_NEQ_OBJ(0x6F),
|
CMP_REF_NEQ_OBJ(0x6F),
|
||||||
|
CMP_EQ_STR(0xD6),
|
||||||
|
CMP_NEQ_STR(0xD7),
|
||||||
|
CMP_LT_STR(0xD8),
|
||||||
|
CMP_LTE_STR(0xD9),
|
||||||
|
CMP_GT_STR(0xDA),
|
||||||
|
CMP_GTE_STR(0xDB),
|
||||||
|
CMP_EQ_INT_OBJ(0xDC),
|
||||||
|
CMP_NEQ_INT_OBJ(0xDD),
|
||||||
|
CMP_LT_INT_OBJ(0xDE),
|
||||||
|
CMP_LTE_INT_OBJ(0xDF),
|
||||||
|
CMP_GT_INT_OBJ(0xE0),
|
||||||
|
CMP_GTE_INT_OBJ(0xE1),
|
||||||
|
CMP_EQ_REAL_OBJ(0xE2),
|
||||||
|
CMP_NEQ_REAL_OBJ(0xE3),
|
||||||
|
CMP_LT_REAL_OBJ(0xE4),
|
||||||
|
CMP_LTE_REAL_OBJ(0xE5),
|
||||||
|
CMP_GT_REAL_OBJ(0xE6),
|
||||||
|
CMP_GTE_REAL_OBJ(0xE7),
|
||||||
|
UNBOX_INT_OBJ(0xF2),
|
||||||
|
UNBOX_REAL_OBJ(0xF3),
|
||||||
|
ADD_INT_OBJ(0xE8),
|
||||||
|
SUB_INT_OBJ(0xE9),
|
||||||
|
MUL_INT_OBJ(0xEA),
|
||||||
|
DIV_INT_OBJ(0xEB),
|
||||||
|
MOD_INT_OBJ(0xEC),
|
||||||
|
ADD_REAL_OBJ(0xED),
|
||||||
|
SUB_REAL_OBJ(0xEE),
|
||||||
|
MUL_REAL_OBJ(0xEF),
|
||||||
|
DIV_REAL_OBJ(0xF0),
|
||||||
|
MOD_REAL_OBJ(0xF1),
|
||||||
|
|
||||||
NOT_BOOL(0x70),
|
NOT_BOOL(0x70),
|
||||||
AND_BOOL(0x71),
|
AND_BOOL(0x71),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -73,9 +73,11 @@ data class ObjBool(val value: Boolean) : Obj() {
|
|||||||
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder,lynonType: LynonType?): Obj {
|
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder,lynonType: LynonType?): Obj {
|
||||||
return ObjBool(decoder.unpackBoolean())
|
return ObjBool(decoder.unpackBoolean())
|
||||||
}
|
}
|
||||||
|
}.apply {
|
||||||
|
isClosed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val ObjTrue = ObjBool(true)
|
val ObjTrue = ObjBool(true)
|
||||||
val ObjFalse = ObjBool(false)
|
val ObjFalse = ObjBool(false)
|
||||||
|
|||||||
@ -109,6 +109,7 @@ open class ObjClass(
|
|||||||
var isAnonymous: Boolean = false
|
var isAnonymous: Boolean = false
|
||||||
|
|
||||||
var isAbstract: Boolean = false
|
var isAbstract: Boolean = false
|
||||||
|
var isClosed: Boolean = false
|
||||||
|
|
||||||
// Stable identity and simple structural version for PICs
|
// Stable identity and simple structural version for PICs
|
||||||
val classId: Long = ClassIdGen.nextId()
|
val classId: Long = ClassIdGen.nextId()
|
||||||
@ -399,7 +400,16 @@ open class ObjClass(
|
|||||||
internal fun fieldSlotMap(): Map<String, FieldSlot> = ensureFieldSlots()
|
internal fun fieldSlotMap(): Map<String, FieldSlot> = ensureFieldSlots()
|
||||||
internal fun fieldRecordForId(fieldId: Int): ObjRecord? {
|
internal fun fieldRecordForId(fieldId: Int): ObjRecord? {
|
||||||
ensureFieldSlots()
|
ensureFieldSlots()
|
||||||
return fieldSlotMap.values.firstOrNull { it.slot == fieldId }?.record
|
fieldSlotMap.values.firstOrNull { it.slot == fieldId }?.record?.let { return it }
|
||||||
|
// Fallback: resolve by id through name mapping if slot map is stale.
|
||||||
|
val name = fieldIdMap.entries.firstOrNull { it.value == fieldId }?.key
|
||||||
|
if (name != null) {
|
||||||
|
for (cls in mro) {
|
||||||
|
cls.members[name]?.let { return it }
|
||||||
|
cls.classScope?.objects?.get(name)?.let { return it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
internal fun resolveInstanceMember(name: String): ResolvedMember? = ensureInstanceMemberCache()[name]
|
internal fun resolveInstanceMember(name: String): ResolvedMember? = ensureInstanceMemberCache()[name]
|
||||||
internal fun methodSlotCount(): Int {
|
internal fun methodSlotCount(): Int {
|
||||||
@ -423,9 +433,18 @@ open class ObjClass(
|
|||||||
if (rec.methodId == methodId) return rec
|
if (rec.methodId == methodId) return rec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Final fallback: resolve by id through name mapping if slot map is stale.
|
||||||
|
val name = methodIdMap.entries.firstOrNull { it.value == methodId }?.key
|
||||||
|
if (name != null) {
|
||||||
|
for (cls in mro) {
|
||||||
|
cls.members[name]?.let { return it }
|
||||||
|
cls.classScope?.objects?.get(name)?.let { return it }
|
||||||
|
}
|
||||||
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun instanceFieldIdMap(): Map<String, Int> {
|
internal fun instanceFieldIdMap(): Map<String, Int> {
|
||||||
val result = mutableMapOf<String, Int>()
|
val result = mutableMapOf<String, Int>()
|
||||||
for (cls in mro) {
|
for (cls in mro) {
|
||||||
@ -479,7 +498,13 @@ open class ObjClass(
|
|||||||
fieldIdMap[name] = existingId
|
fieldIdMap[name] = existingId
|
||||||
return existingId
|
return existingId
|
||||||
}
|
}
|
||||||
val id = fieldIdMap.getOrPut(name) { nextFieldId++ }
|
val id = fieldIdMap[name] ?: run {
|
||||||
|
val next = nextFieldId++
|
||||||
|
fieldIdMap[name] = next
|
||||||
|
// Field id map affects slot layout; invalidate caches when a new id is assigned.
|
||||||
|
layoutVersion += 1
|
||||||
|
next
|
||||||
|
}
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +518,13 @@ open class ObjClass(
|
|||||||
}
|
}
|
||||||
return existingId
|
return existingId
|
||||||
}
|
}
|
||||||
val id = methodIdMap.getOrPut(name) { nextMethodId++ }
|
val id = methodIdMap[name] ?: run {
|
||||||
|
val next = nextMethodId++
|
||||||
|
methodIdMap[name] = next
|
||||||
|
// Method id map affects slot layout; invalidate caches when a new id is assigned.
|
||||||
|
layoutVersion += 1
|
||||||
|
next
|
||||||
|
}
|
||||||
if (id >= nextMethodId) {
|
if (id >= nextMethodId) {
|
||||||
nextMethodId = id + 1
|
nextMethodId = id + 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -189,6 +189,7 @@ class ObjInt(val value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
|||||||
else -> scope.raiseIllegalState("illegal type code for Int: $lynonType")
|
else -> scope.raiseIllegalState("illegal type code for Int: $lynonType")
|
||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
|
isClosed = true
|
||||||
addFnDoc(
|
addFnDoc(
|
||||||
name = "toInt",
|
name = "toInt",
|
||||||
doc = "Returns this integer (identity operation).",
|
doc = "Returns this integer (identity operation).",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,7 +19,6 @@ package net.sergeych.lyng.obj
|
|||||||
|
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import net.sergeych.lyng.Pos
|
|
||||||
import net.sergeych.lyng.Scope
|
import net.sergeych.lyng.Scope
|
||||||
import net.sergeych.lyng.miniast.addConstDoc
|
import net.sergeych.lyng.miniast.addConstDoc
|
||||||
import net.sergeych.lyng.miniast.addFnDoc
|
import net.sergeych.lyng.miniast.addFnDoc
|
||||||
@ -122,6 +121,7 @@ data class ObjReal(val value: Double) : Obj(), Numeric {
|
|||||||
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
|
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
|
||||||
of(decoder.unpackDouble())
|
of(decoder.unpackDouble())
|
||||||
}.apply {
|
}.apply {
|
||||||
|
isClosed = true
|
||||||
// roundToInt: number rounded to the nearest integer
|
// roundToInt: number rounded to the nearest integer
|
||||||
addConstDoc(
|
addConstDoc(
|
||||||
name = "roundToInt",
|
name = "roundToInt",
|
||||||
|
|||||||
@ -25,8 +25,8 @@ import net.sergeych.lyng.PerfFlags
|
|||||||
import net.sergeych.lyng.Pos
|
import net.sergeych.lyng.Pos
|
||||||
import net.sergeych.lyng.RegexCache
|
import net.sergeych.lyng.RegexCache
|
||||||
import net.sergeych.lyng.Scope
|
import net.sergeych.lyng.Scope
|
||||||
import net.sergeych.lyng.requireScope
|
|
||||||
import net.sergeych.lyng.miniast.*
|
import net.sergeych.lyng.miniast.*
|
||||||
|
import net.sergeych.lyng.requireScope
|
||||||
import net.sergeych.lynon.LynonDecoder
|
import net.sergeych.lynon.LynonDecoder
|
||||||
import net.sergeych.lynon.LynonEncoder
|
import net.sergeych.lynon.LynonEncoder
|
||||||
import net.sergeych.lynon.LynonType
|
import net.sergeych.lynon.LynonType
|
||||||
@ -137,6 +137,7 @@ data class ObjString(val value: String) : Obj() {
|
|||||||
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
|
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
|
||||||
ObjString(decoder.unpackBinaryData().decodeToString())
|
ObjString(decoder.unpackBinaryData().decodeToString())
|
||||||
}.apply {
|
}.apply {
|
||||||
|
isClosed = true
|
||||||
addFnDoc(
|
addFnDoc(
|
||||||
name = "iterator",
|
name = "iterator",
|
||||||
doc = "Iterator over characters of this string.",
|
doc = "Iterator over characters of this string.",
|
||||||
|
|||||||
79
lynglib/src/commonTest/kotlin/RepresentativeBenchmarkTest.kt
Normal file
79
lynglib/src/commonTest/kotlin/RepresentativeBenchmarkTest.kt
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import net.sergeych.lyng.Benchmarks
|
||||||
|
import net.sergeych.lyng.Script
|
||||||
|
import net.sergeych.lyng.obj.ObjInt
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.time.TimeSource
|
||||||
|
|
||||||
|
class RepresentativeBenchmarkTest {
|
||||||
|
@Test
|
||||||
|
fun benchmarkMixedOps() = runTest {
|
||||||
|
if (!Benchmarks.enabled) return@runTest
|
||||||
|
val iterations = 40000
|
||||||
|
val script = """
|
||||||
|
fun mixedBench(n) {
|
||||||
|
var acc = 0
|
||||||
|
var len = 0
|
||||||
|
val list = [1,2,3,4,5,6,7,8]
|
||||||
|
val map = {"a":1, "b":2, "c":3}
|
||||||
|
fun bump(x) { x + 1 }
|
||||||
|
var i = 0
|
||||||
|
while(i < n) {
|
||||||
|
acc += i
|
||||||
|
acc += bump(i)
|
||||||
|
if( i % 2 == 0 ) acc += 3 else acc -= 1
|
||||||
|
acc += list[i % 8]
|
||||||
|
acc += map["a"]
|
||||||
|
if( i % 7 == 0 ) len += 1
|
||||||
|
if( i % 11 == 0 ) len += 1
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
acc + len
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(script)
|
||||||
|
val expected = expectedValue(iterations)
|
||||||
|
|
||||||
|
val start = TimeSource.Monotonic.markNow()
|
||||||
|
val result = scope.eval("mixedBench($iterations)") as ObjInt
|
||||||
|
val elapsedMs = start.elapsedNow().inWholeMilliseconds
|
||||||
|
println("[DEBUG_LOG] [BENCH] mixed-ops elapsed=${elapsedMs} ms")
|
||||||
|
assertEquals(expected, result.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expectedValue(iterations: Int): Long {
|
||||||
|
val list = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8)
|
||||||
|
var acc = 0L
|
||||||
|
var len = 0L
|
||||||
|
for (i in 0 until iterations) {
|
||||||
|
acc += i
|
||||||
|
acc += i + 1L
|
||||||
|
if (i % 2 == 0) acc += 3 else acc -= 1
|
||||||
|
acc += list[i % list.size]
|
||||||
|
acc += 1
|
||||||
|
if (i % 7 == 0) len += 1
|
||||||
|
if (i % 11 == 0) len += 1
|
||||||
|
}
|
||||||
|
return acc + len
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import net.sergeych.lyng.Benchmarks
|
||||||
|
import net.sergeych.lyng.BytecodeBodyProvider
|
||||||
|
import net.sergeych.lyng.Script
|
||||||
|
import net.sergeych.lyng.Statement
|
||||||
|
import net.sergeych.lyng.bytecode.*
|
||||||
|
import net.sergeych.lyng.obj.ObjInt
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.time.TimeSource
|
||||||
|
|
||||||
|
class RepresentativeObjectBenchmarkTest {
|
||||||
|
@Test
|
||||||
|
fun benchmarkObjectOps() = runTest {
|
||||||
|
if (!Benchmarks.enabled) return@runTest
|
||||||
|
val iterations = 20000
|
||||||
|
val script = """
|
||||||
|
fun objectBench(n) {
|
||||||
|
var acc = 0
|
||||||
|
var s = ""
|
||||||
|
val list = ["a","b","c","d","e","f","g","h","i","j"]
|
||||||
|
val rlist = [1.0,2.0,3.0,4.0,5.0]
|
||||||
|
val map = {"a":1, "b":2, "c":3, "d":4}
|
||||||
|
var i = 0
|
||||||
|
while(i < n) {
|
||||||
|
val k = list[i % 10]
|
||||||
|
val v = map[k] ?: 0
|
||||||
|
val j = i % 10
|
||||||
|
val r = i * 0.5
|
||||||
|
val rr = rlist[j % 5]
|
||||||
|
val oi: Object = i
|
||||||
|
val oj: Object = j
|
||||||
|
val or: Object = r
|
||||||
|
val or2: Object = r + 1.0
|
||||||
|
s = s + k
|
||||||
|
if( k in list ) acc += 1
|
||||||
|
if( k == "a" ) acc += v else acc -= 1
|
||||||
|
if( k != "z" ) acc += 1
|
||||||
|
if( k < "m" ) acc += 1 else acc -= 1
|
||||||
|
if( k >= "d" ) acc += 1 else acc -= 1
|
||||||
|
if( j < 7 ) acc += 1 else acc -= 1
|
||||||
|
if( j >= 3 ) acc += 1 else acc -= 1
|
||||||
|
if( r <= 2.5 ) acc += 1 else acc -= 1
|
||||||
|
if( r > 3.5 ) acc += 1 else acc -= 1
|
||||||
|
if( rr < 3.5 ) acc += 1 else acc -= 1
|
||||||
|
if( rr >= 2.5 ) acc += 1 else acc -= 1
|
||||||
|
if( oi == oj ) acc += 1 else acc -= 1
|
||||||
|
if( oi < oj ) acc += 1 else acc -= 1
|
||||||
|
if( or > or2 ) acc += 1 else acc -= 1
|
||||||
|
if( or <= or2 ) acc += 1 else acc -= 1
|
||||||
|
if( i % 4 == 0 ) acc += list.size
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
acc + s.size
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(script)
|
||||||
|
val expected = expectedValue(iterations)
|
||||||
|
dumpFunctionBytecode(scope, "objectBench")
|
||||||
|
dumpFastCompareStats(scope, "objectBench")
|
||||||
|
|
||||||
|
val start = TimeSource.Monotonic.markNow()
|
||||||
|
val result = scope.eval("objectBench($iterations)") as ObjInt
|
||||||
|
val elapsedMs = start.elapsedNow().inWholeMilliseconds
|
||||||
|
println("[DEBUG_LOG] [BENCH] object-ops elapsed=${elapsedMs} ms")
|
||||||
|
assertEquals(expected, result.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expectedValue(iterations: Int): Long {
|
||||||
|
val list = arrayOf("a","b","c","d","e","f","g","h","i","j")
|
||||||
|
val rlist = doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0)
|
||||||
|
val map = mapOf("a" to 1, "b" to 2, "c" to 3, "d" to 4)
|
||||||
|
var acc = 0L
|
||||||
|
var s = ""
|
||||||
|
for (i in 0 until iterations) {
|
||||||
|
val k = list[i % list.size]
|
||||||
|
val v = map[k] ?: 0
|
||||||
|
val j = i % 10
|
||||||
|
val r = i * 0.5
|
||||||
|
val rr = rlist[j % 5]
|
||||||
|
val oi = i
|
||||||
|
val oj = j
|
||||||
|
val or = r
|
||||||
|
val or2 = r + 1.0
|
||||||
|
s += k
|
||||||
|
acc += 1
|
||||||
|
if (k == "a") acc += v else acc -= 1
|
||||||
|
if (k != "z") acc += 1
|
||||||
|
if (k < "m") acc += 1 else acc -= 1
|
||||||
|
if (k >= "d") acc += 1 else acc -= 1
|
||||||
|
if (j < 7) acc += 1 else acc -= 1
|
||||||
|
if (j >= 3) acc += 1 else acc -= 1
|
||||||
|
if (r <= 2.5) acc += 1 else acc -= 1
|
||||||
|
if (r > 3.5) acc += 1 else acc -= 1
|
||||||
|
if (rr < 3.5) acc += 1 else acc -= 1
|
||||||
|
if (rr >= 2.5) acc += 1 else acc -= 1
|
||||||
|
if (oi == oj) acc += 1 else acc -= 1
|
||||||
|
if (oi < oj) acc += 1 else acc -= 1
|
||||||
|
if (or > or2) acc += 1 else acc -= 1
|
||||||
|
if (or <= or2) acc += 1 else acc -= 1
|
||||||
|
if (i % 4 == 0) acc += list.size
|
||||||
|
}
|
||||||
|
return acc + s.length
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dumpFunctionBytecode(scope: net.sergeych.lyng.Scope, name: String) {
|
||||||
|
val disasm = scope.disassembleSymbol(name)
|
||||||
|
println("[DEBUG_LOG] [BENCH] object-ops cmd:\n$disasm")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dumpFastCompareStats(scope: net.sergeych.lyng.Scope, name: String) {
|
||||||
|
val fn = resolveBytecodeFunction(scope, name) ?: return
|
||||||
|
var strLocal = 0
|
||||||
|
var intObjLocal = 0
|
||||||
|
var realObjLocal = 0
|
||||||
|
for (cmd in fn.cmds) {
|
||||||
|
when (cmd) {
|
||||||
|
is CmdCmpEqStrLocal,
|
||||||
|
is CmdCmpNeqStrLocal,
|
||||||
|
is CmdCmpLtStrLocal,
|
||||||
|
is CmdCmpGteStrLocal -> strLocal += 1
|
||||||
|
is CmdCmpEqIntObjLocal,
|
||||||
|
is CmdCmpNeqIntObjLocal,
|
||||||
|
is CmdCmpLtIntObjLocal,
|
||||||
|
is CmdCmpGteIntObjLocal -> intObjLocal += 1
|
||||||
|
is CmdCmpEqRealObjLocal,
|
||||||
|
is CmdCmpNeqRealObjLocal,
|
||||||
|
is CmdCmpLtRealObjLocal,
|
||||||
|
is CmdCmpGteRealObjLocal -> realObjLocal += 1
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(
|
||||||
|
"[DEBUG_LOG] [BENCH] object-ops fast-compare local cmds: str=$strLocal intObj=$intObjLocal realObj=$realObjLocal"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveBytecodeFunction(scope: net.sergeych.lyng.Scope, name: String): CmdFunction? {
|
||||||
|
val record = scope.get(name) ?: return null
|
||||||
|
val stmt = record.value as? Statement ?: return null
|
||||||
|
return (stmt as? BytecodeStatement)?.bytecodeFunction()
|
||||||
|
?: (stmt as? BytecodeBodyProvider)?.bytecodeBody()?.bytecodeFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -187,12 +187,24 @@ class TypesTest {
|
|||||||
val base = [1, 2]
|
val base = [1, 2]
|
||||||
acceptInts([...base, 3])
|
acceptInts([...base, 3])
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
eval("""
|
||||||
|
fun acceptReals<T: Real>(xs: List<T>) { }
|
||||||
|
acceptReals([1.0, 2.0, 3.0])
|
||||||
|
val base = [1.0, 2.0]
|
||||||
|
acceptReals([...base, 3.0])
|
||||||
|
""".trimIndent())
|
||||||
assertFailsWith<net.sergeych.lyng.ScriptError> {
|
assertFailsWith<net.sergeych.lyng.ScriptError> {
|
||||||
eval("""
|
eval("""
|
||||||
fun acceptInts<T: Int>(xs: List<T>) { }
|
fun acceptInts<T: Int>(xs: List<T>) { }
|
||||||
acceptInts([1, "a"])
|
acceptInts([1, "a"])
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
assertFailsWith<net.sergeych.lyng.ScriptError> {
|
||||||
|
eval("""
|
||||||
|
fun acceptReals<T: Real>(xs: List<T>) { }
|
||||||
|
acceptReals([1.0, "a"])
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -37,6 +37,12 @@
|
|||||||
- 2026-02-15 baseline (fused int-compare jumps): 74 ms.
|
- 2026-02-15 baseline (fused int-compare jumps): 74 ms.
|
||||||
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
||||||
- Notes: loop range checks use `JMP_IF_GTE_INT` (no CMP+bool temp).
|
- Notes: loop range checks use `JMP_IF_GTE_INT` (no CMP+bool temp).
|
||||||
|
- 2026-02-15 experiment (fast non-suspend cmds in hot path): 57 ms.
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
||||||
|
- Notes: fast path for local int ops + local JMP_IF_FALSE/TRUE in VM.
|
||||||
|
- 2026-02-15 experiment (full fast-path sweep + capture-safe locals): 59 ms.
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
||||||
|
- Notes: local numeric/bool/mixed-compare fast ops gated by non-captured locals.
|
||||||
|
|
||||||
### Hypothesis for Native slowdown
|
### Hypothesis for Native slowdown
|
||||||
- Suspend/virtual dispatch per opcode dominates on K/N, even with no allocations in int ops.
|
- Suspend/virtual dispatch per opcode dominates on K/N, even with no allocations in int ops.
|
||||||
|
|||||||
49
notes/vm_fastpath_plan.md
Normal file
49
notes/vm_fastpath_plan.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# VM Fast-Path Plan (Non-Suspending Ops)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
Reduce suspend overhead by routing safe, local-only ops through non-suspending fast paths while preserving semantics for captured locals and dynamic objects.
|
||||||
|
|
||||||
|
## Completed
|
||||||
|
- [x] Local numeric/bool/conversion ops: add fast local variants and guard by non-captured locals.
|
||||||
|
- [x] Local jumps: `JMP_IF_TRUE/FALSE` and fused int jumps fast path.
|
||||||
|
- [x] **Object arithmetic ops** (`ADD_OBJ/SUB_OBJ/MUL_OBJ/DIV_OBJ/MOD_OBJ`): add fast-path for local numeric slots with fallback to slow path when non-numeric or captured.
|
||||||
|
- [x] Full `:lynglib:jvmTest` green after changes.
|
||||||
|
|
||||||
|
## In Progress / Next
|
||||||
|
- [ ] Object comparisons (`CMP_*_OBJ`) fast-path on local numeric slots (guarded, fallback to slow path).
|
||||||
|
- [ ] Local `MOVE_OBJ` safe fast-path (only if slot is not `FrameSlotRef`/`RecordSlotRef`, or add explicit unwrapping).
|
||||||
|
- [ ] Address ops (`LOAD_*_ADDR` / `STORE_*_ADDR`) non-suspend variants when addr already resolved.
|
||||||
|
- [ ] Confirm wasm/js behavior unchanged (if needed).
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
- Never treat captured locals as fast locals; route them through slow path.
|
||||||
|
- Fast path must only execute when slot types are primitive numeric/bool and stored directly in frame.
|
||||||
|
- If fast-path preconditions fail, fall back to suspend `perform()`.
|
||||||
|
|
||||||
|
## Test Gate
|
||||||
|
- `./gradlew :lynglib:jvmTest`
|
||||||
|
- Benchmarks optional: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
||||||
|
|
||||||
|
## A/B Benchmark (Representative)
|
||||||
|
- Baseline (fast-path stashed): 194 ms
|
||||||
|
- With fast-path changes: 186 ms
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*RepresentativeBenchmarkTest*'`
|
||||||
|
|
||||||
|
## A/B Benchmark (Representative Object Ops)
|
||||||
|
- Baseline (fast-path stashed): 106 ms
|
||||||
|
- With fast-path changes: 108 ms
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*RepresentativeObjectBenchmarkTest*'`
|
||||||
|
|
||||||
|
## A/B Benchmark (Representative Object Ops, extended comparisons)
|
||||||
|
- Baseline (ObjString only): 141 ms
|
||||||
|
- With ObjString + ObjInt/ObjReal compare ops: 137 ms
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*RepresentativeObjectBenchmarkTest*'`
|
||||||
|
|
||||||
|
## A/B Benchmark (Representative Object Ops, object numeric compares)
|
||||||
|
- Baseline (no Obj* compare ops): 153 ms
|
||||||
|
- With ObjString + ObjInt/ObjReal compare ops: 149 ms
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*RepresentativeObjectBenchmarkTest*'`
|
||||||
|
|
||||||
|
## A/B Benchmark (Trust type decls for Obj* compares)
|
||||||
|
- With ObjString + ObjInt/ObjReal compare ops + type-decl trust: 157 ms
|
||||||
|
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*RepresentativeObjectBenchmarkTest*'`
|
||||||
Loading…
x
Reference in New Issue
Block a user