diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt index 7920f0d..942dc52 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt @@ -86,6 +86,7 @@ class BytecodeCompiler( private val loopVarSlots = HashSet() private val loopStack = ArrayDeque() private var currentPos: Pos? = null + private var cachedVoidSlot: Int? = null private data class LoopContext( val label: String?, @@ -5623,6 +5624,17 @@ class BytecodeCompiler( private fun emitInlineBlock(stmt: BlockStatement, needResult: Boolean): CompiledValue? = emitInlineStatements(stmt.statements(), needResult) + private fun ensureVoidSlot(): Int { + val existing = cachedVoidSlot + if (existing != null) return existing + val slot = allocSlot() + val voidId = builder.addConst(BytecodeConst.ObjRef(ObjVoid)) + builder.emit(Opcode.CONST_OBJ, voidId, slot) + updateSlotType(slot, SlotType.OBJ) + cachedVoidSlot = slot + return slot + } + private fun shouldInlineBlock(stmt: BlockStatement): Boolean { return allowLocalSlots } @@ -6449,10 +6461,7 @@ class BytecodeCompiler( restoreFlowTypeOverride(elseRestore) } builder.mark(endLabel) - val slot = allocSlot() - val voidId = builder.addConst(BytecodeConst.ObjRef(ObjVoid)) - builder.emit(Opcode.CONST_OBJ, voidId, slot) - return CompiledValue(slot, SlotType.OBJ) + return CompiledValue(ensureVoidSlot(), SlotType.OBJ) } private fun updateSlotTypeByName(name: String, type: SlotType) { diff --git a/notes/fast_ops_optimizations_plan.md b/notes/fast_ops_optimizations_plan.md index def0503..01df7b9 100644 --- a/notes/fast_ops_optimizations_plan.md +++ b/notes/fast_ops_optimizations_plan.md @@ -13,9 +13,9 @@ Candidates (not started) 3) Boolean conversion (done; do not revert without review) - Skip redundant OBJ_TO_BOOL in logical AND/OR when compiler already emits BOOL. - MixedCompareBenchmarkTest: 275 ms -> 249 ms. -4) Range/loop hot path - - Keep range iteration in INT ops, avoid accidental boxing. - - Confirm loop-var slots avoid re-boxing in loop bodies. +4) Range/loop hot path (done) + - Reuse a cached ObjVoid slot for if-statements in statement context (avoids per-iteration CONST_OBJ). + - MixedCompareBenchmarkTest: 249 ms -> 247 ms. 5) String ops - Extend fast path for string comparisons in hot loops. 6) Box/unbox audit