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");
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.sergeych.lyng
|
||||
|
||||
import net.sergeych.lyng.obj.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
|
||||
import net.sergeych.lyng.obj.*
|
||||
|
||||
data class ClassDeclBaseSpec(
|
||||
val name: String,
|
||||
@ -51,11 +46,16 @@ internal suspend fun executeClassDecl(
|
||||
bodyCaptureRecords: List<ObjRecord>? = null,
|
||||
bodyCaptureNames: List<String>? = null
|
||||
): 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) {
|
||||
val parentClasses = spec.baseSpecs.map { baseSpec ->
|
||||
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")
|
||||
}
|
||||
checkClosedParents(parentClasses, spec.startPos)
|
||||
|
||||
val newClass = ObjInstanceClass(spec.className, *parentClasses.toTypedArray())
|
||||
newClass.isAnonymous = spec.isAnonymous
|
||||
@ -106,6 +106,7 @@ internal suspend fun executeClassDecl(
|
||||
if (rec == null) throw ScriptError(spec.startPos, "unknown base class: ${baseSpec.name}")
|
||||
throw ScriptError(spec.startPos, "${baseSpec.name} is not a class")
|
||||
}
|
||||
checkClosedParents(parentClasses, spec.startPos)
|
||||
|
||||
val constructorCode = object : Statement() {
|
||||
override val pos: Pos = spec.startPos
|
||||
|
||||
@ -18,11 +18,7 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
import net.sergeych.lyng.Compiler.Companion.compile
|
||||
import net.sergeych.lyng.bytecode.BytecodeStatement
|
||||
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.bytecode.*
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
@ -1643,6 +1639,7 @@ class Compiler(
|
||||
forcedLocalSlotInfo = forcedLocalInfo,
|
||||
forcedLocalScopeId = forcedLocalScopeId,
|
||||
slotTypeByScopeId = slotTypeByScopeId,
|
||||
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||
knownNameObjClass = knownClassMapForBytecode(),
|
||||
knownObjectNames = objectDeclNames,
|
||||
classFieldTypesByName = classFieldTypesByName,
|
||||
@ -1941,6 +1938,7 @@ class Compiler(
|
||||
scopeSlotNameSet = scopeSlotNameSet,
|
||||
moduleScopeId = moduleScopeId,
|
||||
slotTypeByScopeId = slotTypeByScopeId,
|
||||
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||
knownNameObjClass = knownClassMapForBytecode(),
|
||||
knownObjectNames = objectDeclNames,
|
||||
classFieldTypesByName = classFieldTypesByName,
|
||||
@ -1969,6 +1967,7 @@ class Compiler(
|
||||
scopeSlotNameSet = scopeSlotNameSet,
|
||||
moduleScopeId = moduleScopeId,
|
||||
slotTypeByScopeId = slotTypeByScopeId,
|
||||
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||
knownNameObjClass = knownClassMapForBytecode(),
|
||||
knownObjectNames = objectDeclNames,
|
||||
classFieldTypesByName = classFieldTypesByName,
|
||||
@ -2022,6 +2021,7 @@ class Compiler(
|
||||
globalSlotInfo = globalSlotInfo,
|
||||
globalSlotScopeId = globalSlotScopeId,
|
||||
slotTypeByScopeId = slotTypeByScopeId,
|
||||
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||
knownNameObjClass = knownNames,
|
||||
knownObjectNames = objectDeclNames,
|
||||
classFieldTypesByName = classFieldTypesByName,
|
||||
@ -7580,6 +7580,10 @@ class Compiler(
|
||||
val info = compileClassInfos[name] ?: return null
|
||||
val stub = compileClassStubs.getOrPut(info.name) {
|
||||
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())
|
||||
}
|
||||
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(),
|
||||
externCallableNames: Set<String> = emptySet(),
|
||||
lambdaCaptureEntriesByRef: Map<ValueFnRef, List<LambdaCaptureEntry>> = emptyMap(),
|
||||
slotTypeDeclByScopeId: Map<Int, Map<Int, TypeDecl>> = emptyMap(),
|
||||
): Statement {
|
||||
if (statement is BytecodeStatement) return statement
|
||||
val hasUnsupported = containsUnsupportedStatement(statement)
|
||||
@ -83,6 +84,7 @@ class BytecodeStatement private constructor(
|
||||
globalSlotInfo = globalSlotInfo,
|
||||
globalSlotScopeId = globalSlotScopeId,
|
||||
slotTypeByScopeId = slotTypeByScopeId,
|
||||
slotTypeDeclByScopeId = slotTypeDeclByScopeId,
|
||||
knownNameObjClass = knownNameObjClass,
|
||||
knownObjectNames = knownObjectNames,
|
||||
classFieldTypesByName = classFieldTypesByName,
|
||||
|
||||
@ -102,7 +102,7 @@ class CmdBuilder {
|
||||
}
|
||||
operands[i] = v
|
||||
}
|
||||
cmds.add(createCmd(ins.op, operands, scopeSlotCount))
|
||||
cmds.add(createCmd(ins.op, operands, scopeSlotCount, localSlotCaptures))
|
||||
}
|
||||
return CmdFunction(
|
||||
name = name,
|
||||
@ -128,6 +128,7 @@ class CmdBuilder {
|
||||
Opcode.NOP, Opcode.RET_VOID, Opcode.POP_SCOPE, Opcode.POP_SLOT_PLAN, Opcode.POP_TRY,
|
||||
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING -> emptyList()
|
||||
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.OBJ_TO_BOOL, Opcode.GET_OBJ_CLASS,
|
||||
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_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_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.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.AND_BOOL, Opcode.OR_BOOL ->
|
||||
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
||||
@ -241,19 +249,37 @@ class CmdBuilder {
|
||||
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) {
|
||||
Opcode.NOP -> CmdNop()
|
||||
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)
|
||||
} else {
|
||||
CmdMoveInt(operands[0], operands[1])
|
||||
}
|
||||
Opcode.MOVE_REAL -> CmdMoveReal(operands[0], operands[1])
|
||||
Opcode.MOVE_BOOL -> CmdMoveBool(operands[0], operands[1])
|
||||
Opcode.MOVE_REAL -> if (isFastLocal(operands[0]) && isFastLocal(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_INT -> if (operands[1] >= scopeSlotCount) {
|
||||
Opcode.CONST_INT -> if (isFastLocal(operands[1])) {
|
||||
CmdConstIntLocal(operands[0], operands[1] - scopeSlotCount)
|
||||
} else {
|
||||
CmdConstInt(operands[0], operands[1])
|
||||
@ -263,6 +289,16 @@ class CmdBuilder {
|
||||
Opcode.CONST_NULL -> CmdConstNull(operands[0])
|
||||
Opcode.MAKE_LAMBDA_FN -> CmdMakeLambda(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.GET_OBJ_CLASS -> CmdGetObjClass(operands[0], operands[1])
|
||||
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.LOAD_BOOL_ADDR -> CmdLoadBoolAddr(operands[0], operands[1])
|
||||
Opcode.STORE_BOOL_ADDR -> CmdStoreBoolAddr(operands[0], operands[1])
|
||||
Opcode.INT_TO_REAL -> CmdIntToReal(operands[0], operands[1])
|
||||
Opcode.REAL_TO_INT -> CmdRealToInt(operands[0], operands[1])
|
||||
Opcode.BOOL_TO_INT -> CmdBoolToInt(operands[0], operands[1])
|
||||
Opcode.INT_TO_BOOL -> CmdIntToBool(operands[0], operands[1])
|
||||
Opcode.ADD_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
||||
Opcode.INT_TO_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||
CmdIntToRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||
} else {
|
||||
CmdIntToReal(operands[0], operands[1])
|
||||
}
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
CmdModInt(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.NEG_INT -> CmdNegInt(operands[0], operands[1])
|
||||
Opcode.INC_INT -> if (operands[0] >= scopeSlotCount) {
|
||||
Opcode.NEG_INT -> if (isFastLocal(operands[0]) && isFastLocal(operands[1])) {
|
||||
CmdNegIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount)
|
||||
} else {
|
||||
CmdNegInt(operands[0], operands[1])
|
||||
}
|
||||
Opcode.INC_INT -> if (isFastLocal(operands[0])) {
|
||||
CmdIncIntLocal(operands[0] - scopeSlotCount)
|
||||
} else {
|
||||
CmdIncInt(operands[0])
|
||||
}
|
||||
Opcode.DEC_INT -> if (operands[0] >= scopeSlotCount) {
|
||||
Opcode.DEC_INT -> if (isFastLocal(operands[0])) {
|
||||
CmdDecIntLocal(operands[0] - scopeSlotCount)
|
||||
} else {
|
||||
CmdDecInt(operands[0])
|
||||
}
|
||||
Opcode.ADD_REAL -> CmdAddReal(operands[0], operands[1], operands[2])
|
||||
Opcode.SUB_REAL -> CmdSubReal(operands[0], operands[1], operands[2])
|
||||
Opcode.MUL_REAL -> CmdMulReal(operands[0], operands[1], operands[2])
|
||||
Opcode.DIV_REAL -> CmdDivReal(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.OR_INT -> CmdOrInt(operands[0], operands[1], operands[2])
|
||||
Opcode.XOR_INT -> CmdXorInt(operands[0], operands[1], operands[2])
|
||||
Opcode.SHL_INT -> CmdShlInt(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.INV_INT -> CmdInvInt(operands[0], operands[1])
|
||||
Opcode.CMP_EQ_INT -> if (operands[0] >= scopeSlotCount && operands[1] >= scopeSlotCount && operands[2] >= scopeSlotCount) {
|
||||
Opcode.ADD_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdAddRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdAddReal(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.SUB_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdSubRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdSubReal(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.MUL_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdMulRealLocal(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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
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)
|
||||
} else {
|
||||
CmdCmpGteInt(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.CMP_EQ_REAL -> CmdCmpEqReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_NEQ_REAL -> CmdCmpNeqReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_LT_REAL -> CmdCmpLtReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_LTE_REAL -> CmdCmpLteReal(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_EQ_BOOL -> CmdCmpEqBool(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_NEQ_BOOL -> CmdCmpNeqBool(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_EQ_INT_REAL -> CmdCmpEqIntReal(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_INT -> CmdCmpLtRealInt(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_LTE_INT_REAL -> CmdCmpLteIntReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_LTE_REAL_INT -> CmdCmpLteRealInt(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_GTE_INT_REAL -> CmdCmpGteIntReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_GTE_REAL_INT -> CmdCmpGteRealInt(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_NEQ_INT_REAL -> CmdCmpNeqIntReal(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_NEQ_REAL_INT -> CmdCmpNeqRealInt(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_EQ_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdCmpEqRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdCmpEqReal(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.CMP_NEQ_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdCmpNeqRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdCmpNeqReal(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.CMP_LT_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdCmpLtRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdCmpLtReal(operands[0], operands[1], operands[2])
|
||||
}
|
||||
Opcode.CMP_LTE_REAL -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdCmpLteRealLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} else {
|
||||
CmdCmpLteReal(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_NEQ_OBJ -> CmdCmpNeqObj(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.NOT_BOOL -> CmdNotBool(operands[0], operands[1])
|
||||
Opcode.AND_BOOL -> CmdAndBool(operands[0], operands[1], operands[2])
|
||||
Opcode.OR_BOOL -> CmdOrBool(operands[0], operands[1], operands[2])
|
||||
Opcode.CMP_EQ_STR -> if (isFastLocal(operands[0]) && isFastLocal(operands[1]) && isFastLocal(operands[2])) {
|
||||
CmdCmpEqStrLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2] - scopeSlotCount)
|
||||
} 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_LTE_OBJ -> CmdCmpLteObj(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.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.SUB_OBJ -> CmdSubObj(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.ASSIGN_OP_OBJ -> CmdAssignOpObj(operands[0], operands[1], operands[2], operands[3], operands[4])
|
||||
Opcode.JMP -> CmdJmp(operands[0])
|
||||
Opcode.JMP_IF_TRUE -> CmdJmpIfTrue(operands[0], operands[1])
|
||||
Opcode.JMP_IF_FALSE -> CmdJmpIfFalse(operands[0], operands[1])
|
||||
Opcode.JMP_IF_TRUE -> if (operands[0] >= scopeSlotCount) {
|
||||
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) {
|
||||
CmdJmpIfEqIntLocal(operands[0] - scopeSlotCount, operands[1] - scopeSlotCount, operands[2])
|
||||
} 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");
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.sergeych.lyng.bytecode
|
||||
@ -76,6 +77,8 @@ object CmdDisassembler {
|
||||
is CmdMoveObj -> Opcode.MOVE_OBJ 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 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 CmdMoveBool -> Opcode.MOVE_BOOL to intArrayOf(cmd.src, 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 CmdStoreBoolAddr -> Opcode.STORE_BOOL_ADDR to intArrayOf(cmd.src, cmd.addrSlot)
|
||||
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 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 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 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 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)
|
||||
@ -128,22 +135,35 @@ object CmdDisassembler {
|
||||
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 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 CmdIncIntLocal -> Opcode.INC_INT to intArrayOf(cmd.slot + fn.scopeSlotCount)
|
||||
is CmdDecInt -> Opcode.DEC_INT to intArrayOf(cmd.slot)
|
||||
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 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 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 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 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 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 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 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 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 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 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 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 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 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)
|
||||
@ -157,25 +177,45 @@ object CmdDisassembler {
|
||||
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 CmdJmpIfEqIntLocal -> Opcode.JMP_IF_EQ_INT to intArrayOf(
|
||||
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 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 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 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 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 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 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 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 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)
|
||||
@ -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 CmdJmp -> Opcode.JMP to intArrayOf(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 CmdJmpIfFalseLocal -> Opcode.JMP_IF_FALSE to intArrayOf(cmd.cond + fn.scopeSlotCount, cmd.target)
|
||||
is CmdRet -> Opcode.RET to intArrayOf(cmd.slot)
|
||||
is CmdRetLabel -> Opcode.RET_LABEL to intArrayOf(cmd.labelId, cmd.slot)
|
||||
is CmdRetVoid -> Opcode.RET_VOID to intArrayOf()
|
||||
@ -298,6 +521,7 @@ object CmdDisassembler {
|
||||
Opcode.CLEAR_PENDING_THROWABLE, Opcode.RETHROW_PENDING,
|
||||
Opcode.ITER_POP, Opcode.ITER_CANCEL -> emptyList()
|
||||
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.NEG_INT, Opcode.NEG_REAL, Opcode.NOT_BOOL, Opcode.INV_INT ->
|
||||
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_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_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.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.AND_BOOL, Opcode.OR_BOOL ->
|
||||
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");
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.sergeych.lyng.bytecode
|
||||
@ -98,6 +99,36 @@ enum class Opcode(val code: Int) {
|
||||
CMP_NEQ_OBJ(0x6D),
|
||||
CMP_REF_EQ_OBJ(0x6E),
|
||||
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),
|
||||
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");
|
||||
* 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 {
|
||||
return ObjBool(decoder.unpackBoolean())
|
||||
}
|
||||
}.apply {
|
||||
isClosed = 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 isAbstract: Boolean = false
|
||||
var isClosed: Boolean = false
|
||||
|
||||
// Stable identity and simple structural version for PICs
|
||||
val classId: Long = ClassIdGen.nextId()
|
||||
@ -399,7 +400,16 @@ open class ObjClass(
|
||||
internal fun fieldSlotMap(): Map<String, FieldSlot> = ensureFieldSlots()
|
||||
internal fun fieldRecordForId(fieldId: Int): ObjRecord? {
|
||||
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 methodSlotCount(): Int {
|
||||
@ -423,9 +433,18 @@ open class ObjClass(
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
internal fun instanceFieldIdMap(): Map<String, Int> {
|
||||
val result = mutableMapOf<String, Int>()
|
||||
for (cls in mro) {
|
||||
@ -479,7 +498,13 @@ open class ObjClass(
|
||||
fieldIdMap[name] = 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
|
||||
}
|
||||
|
||||
@ -493,7 +518,13 @@ open class ObjClass(
|
||||
}
|
||||
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) {
|
||||
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");
|
||||
* 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")
|
||||
}
|
||||
}.apply {
|
||||
isClosed = true
|
||||
addFnDoc(
|
||||
name = "toInt",
|
||||
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");
|
||||
* 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.JsonPrimitive
|
||||
import net.sergeych.lyng.Pos
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.miniast.addConstDoc
|
||||
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 =
|
||||
of(decoder.unpackDouble())
|
||||
}.apply {
|
||||
isClosed = true
|
||||
// roundToInt: number rounded to the nearest integer
|
||||
addConstDoc(
|
||||
name = "roundToInt",
|
||||
|
||||
@ -25,8 +25,8 @@ import net.sergeych.lyng.PerfFlags
|
||||
import net.sergeych.lyng.Pos
|
||||
import net.sergeych.lyng.RegexCache
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lynon.LynonDecoder
|
||||
import net.sergeych.lynon.LynonEncoder
|
||||
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 =
|
||||
ObjString(decoder.unpackBinaryData().decodeToString())
|
||||
}.apply {
|
||||
isClosed = true
|
||||
addFnDoc(
|
||||
name = "iterator",
|
||||
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]
|
||||
acceptInts([...base, 3])
|
||||
""".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> {
|
||||
eval("""
|
||||
fun acceptInts<T: Int>(xs: List<T>) { }
|
||||
acceptInts([1, "a"])
|
||||
""".trimIndent())
|
||||
}
|
||||
assertFailsWith<net.sergeych.lyng.ScriptError> {
|
||||
eval("""
|
||||
fun acceptReals<T: Real>(xs: List<T>) { }
|
||||
acceptReals([1.0, "a"])
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -37,6 +37,12 @@
|
||||
- 2026-02-15 baseline (fused int-compare jumps): 74 ms.
|
||||
- Command: `./gradlew :lynglib:jvmTest -Pbenchmarks=true --tests '*NestedRangeBenchmarkTest*'`
|
||||
- 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
|
||||
- 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