Propagate exact lambda refs across bytecode slots
This commit is contained in:
parent
db3a780645
commit
30c9a5a565
@ -909,6 +909,7 @@ class BytecodeCompiler(
|
|||||||
val slot = allocSlot()
|
val slot = allocSlot()
|
||||||
builder.emit(Opcode.MAKE_LAMBDA_FN, id, slot)
|
builder.emit(Opcode.MAKE_LAMBDA_FN, id, slot)
|
||||||
updateSlotType(slot, SlotType.OBJ)
|
updateSlotType(slot, SlotType.OBJ)
|
||||||
|
trackExactLambdaAtSlot(slot, ref)
|
||||||
return CompiledValue(slot, SlotType.OBJ)
|
return CompiledValue(slot, SlotType.OBJ)
|
||||||
}
|
}
|
||||||
val pos = (ref as? LambdaFnRef)?.pos ?: Pos.builtIn
|
val pos = (ref as? LambdaFnRef)?.pos ?: Pos.builtIn
|
||||||
@ -7724,6 +7725,7 @@ class BytecodeCompiler(
|
|||||||
|
|
||||||
private fun emitMove(value: CompiledValue, dstSlot: Int) {
|
private fun emitMove(value: CompiledValue, dstSlot: Int) {
|
||||||
val srcSlot = value.slot
|
val srcSlot = value.slot
|
||||||
|
if (srcSlot == dstSlot) return
|
||||||
val srcIsScope = srcSlot < scopeSlotCount
|
val srcIsScope = srcSlot < scopeSlotCount
|
||||||
val dstIsScope = dstSlot < scopeSlotCount
|
val dstIsScope = dstSlot < scopeSlotCount
|
||||||
if (value.type != SlotType.UNKNOWN) {
|
if (value.type != SlotType.UNKNOWN) {
|
||||||
@ -7731,12 +7733,14 @@ class BytecodeCompiler(
|
|||||||
val addrSlot = ensureScopeAddr(srcSlot)
|
val addrSlot = ensureScopeAddr(srcSlot)
|
||||||
emitLoadFromAddr(addrSlot, dstSlot, value.type)
|
emitLoadFromAddr(addrSlot, dstSlot, value.type)
|
||||||
propagateObjClass(value.type, srcSlot, dstSlot)
|
propagateObjClass(value.type, srcSlot, dstSlot)
|
||||||
|
propagateExactLambdaRef(value.type, srcSlot, dstSlot)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (dstIsScope) {
|
if (dstIsScope) {
|
||||||
val addrSlot = ensureScopeAddr(dstSlot)
|
val addrSlot = ensureScopeAddr(dstSlot)
|
||||||
emitStoreToAddr(srcSlot, addrSlot, value.type)
|
emitStoreToAddr(srcSlot, addrSlot, value.type)
|
||||||
propagateObjClass(value.type, srcSlot, dstSlot)
|
propagateObjClass(value.type, srcSlot, dstSlot)
|
||||||
|
propagateExactLambdaRef(value.type, srcSlot, dstSlot)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7748,6 +7752,7 @@ class BytecodeCompiler(
|
|||||||
else -> builder.emit(Opcode.BOX_OBJ, srcSlot, dstSlot)
|
else -> builder.emit(Opcode.BOX_OBJ, srcSlot, dstSlot)
|
||||||
}
|
}
|
||||||
propagateObjClass(value.type, srcSlot, dstSlot)
|
propagateObjClass(value.type, srcSlot, dstSlot)
|
||||||
|
propagateExactLambdaRef(value.type, srcSlot, dstSlot)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun propagateObjClass(type: SlotType, srcSlot: Int, dstSlot: Int) {
|
private fun propagateObjClass(type: SlotType, srcSlot: Int, dstSlot: Int) {
|
||||||
@ -7776,6 +7781,14 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun propagateExactLambdaRef(type: SlotType, srcSlot: Int, dstSlot: Int) {
|
||||||
|
if (type == SlotType.OBJ || type == SlotType.UNKNOWN) {
|
||||||
|
trackExactLambdaAtSlot(dstSlot, exactLambdaRefBySlot[srcSlot])
|
||||||
|
} else {
|
||||||
|
trackExactLambdaAtSlot(dstSlot, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setPos(pos: Pos?) {
|
private fun setPos(pos: Pos?) {
|
||||||
currentPos = pos
|
currentPos = pos
|
||||||
builder.setPos(pos)
|
builder.setPos(pos)
|
||||||
|
|||||||
@ -346,6 +346,21 @@ class BytecodeRecentOpsTest {
|
|||||||
assertEquals(12, scope.eval("calc()").toInt())
|
assertEquals(12, scope.eval("calc()").toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nestedInlineLambdaParamCallAvoidsCallSlot() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
fun calc() {
|
||||||
|
{ g -> g(10) }({ x -> x + 1 })
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
val disasm = scope.disassembleSymbol("calc")
|
||||||
|
assertFalse(disasm.contains("CALL_SLOT"), disasm)
|
||||||
|
assertEquals(11, scope.eval("calc()").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun letLiteralUsesInlineBytecode() = runTest {
|
fun letLiteralUsesInlineBytecode() = runTest {
|
||||||
val scope = Script.newScope()
|
val scope = Script.newScope()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user