Use direct calls for constant constructors
This commit is contained in:
parent
30c9a5a565
commit
ffa64d691b
@ -874,6 +874,11 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun emitCallDirect(callee: Obj, argBase: Int, encodedCount: Int, dst: Int) {
|
||||||
|
val calleeId = builder.addConst(BytecodeConst.ObjRef(callee))
|
||||||
|
builder.emit(Opcode.CALL_DIRECT, calleeId, argBase, encodedCount, dst)
|
||||||
|
}
|
||||||
|
|
||||||
private fun compileValueFnRef(ref: ValueFnRef): CompiledValue? {
|
private fun compileValueFnRef(ref: ValueFnRef): CompiledValue? {
|
||||||
if (ref is LambdaFnRef && ref.bytecodeFn != null) {
|
if (ref is LambdaFnRef && ref.bytecodeFn != null) {
|
||||||
val captures = (lambdaCaptureEntriesByRef[ref] ?: ref.captureEntries).orEmpty()
|
val captures = (lambdaCaptureEntriesByRef[ref] ?: ref.captureEntries).orEmpty()
|
||||||
@ -998,11 +1003,8 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun compileMapLiteral(ref: MapLiteralRef): CompiledValue? {
|
private fun compileMapLiteral(ref: MapLiteralRef): CompiledValue? {
|
||||||
val mapClassId = builder.addConst(BytecodeConst.ObjRef(ObjMap.type))
|
|
||||||
val mapClassSlot = allocSlot()
|
|
||||||
builder.emit(Opcode.CONST_OBJ, mapClassId, mapClassSlot)
|
|
||||||
val dst = allocSlot()
|
val dst = allocSlot()
|
||||||
builder.emit(Opcode.CALL_SLOT, mapClassSlot, 0, 0, dst)
|
emitCallDirect(ObjMap.type, 0, 0, dst)
|
||||||
updateSlotType(dst, SlotType.OBJ)
|
updateSlotType(dst, SlotType.OBJ)
|
||||||
slotObjClass[dst] = ObjMap.type
|
slotObjClass[dst] = ObjMap.type
|
||||||
for (entry in ref.entries()) {
|
for (entry in ref.entries()) {
|
||||||
@ -1285,11 +1287,8 @@ class BytecodeCompiler(
|
|||||||
emitMove(leftObj, argLeft)
|
emitMove(leftObj, argLeft)
|
||||||
val argRight = allocSlot()
|
val argRight = allocSlot()
|
||||||
emitMove(rightObj, argRight)
|
emitMove(rightObj, argRight)
|
||||||
val mapEntryClassId = builder.addConst(BytecodeConst.ObjRef(ObjMapEntry.type))
|
|
||||||
val mapEntryClassSlot = allocSlot()
|
|
||||||
builder.emit(Opcode.CONST_OBJ, mapEntryClassId, mapEntryClassSlot)
|
|
||||||
val dst = allocSlot()
|
val dst = allocSlot()
|
||||||
builder.emit(Opcode.CALL_SLOT, mapEntryClassSlot, argBase, 2, dst)
|
emitCallDirect(ObjMapEntry.type, argBase, 2, dst)
|
||||||
updateSlotType(dst, SlotType.OBJ)
|
updateSlotType(dst, SlotType.OBJ)
|
||||||
slotObjClass[dst] = ObjMapEntry.type
|
slotObjClass[dst] = ObjMapEntry.type
|
||||||
return CompiledValue(dst, SlotType.OBJ)
|
return CompiledValue(dst, SlotType.OBJ)
|
||||||
@ -5090,7 +5089,6 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun compileInlineDirectLambdaCall(ref: CallRef, lambdaRef: LambdaFnRef): CompiledValue? {
|
private fun compileInlineDirectLambdaCall(ref: CallRef, lambdaRef: LambdaFnRef): CompiledValue? {
|
||||||
if (ref.isOptionalInvoke) return null
|
|
||||||
if (ref.tailBlock) return null
|
if (ref.tailBlock) return null
|
||||||
if (!ref.explicitTypeArgs.isNullOrEmpty()) return null
|
if (!ref.explicitTypeArgs.isNullOrEmpty()) return null
|
||||||
val inlineRef = lambdaRef.inlineBodyRef ?: return null
|
val inlineRef = lambdaRef.inlineBodyRef ?: return null
|
||||||
@ -5279,12 +5277,8 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createEmptyMutableList(): CompiledValue? {
|
private fun createEmptyMutableList(): CompiledValue? {
|
||||||
val calleeId = builder.addConst(BytecodeConst.ObjRef(ObjList.type))
|
|
||||||
val calleeSlot = allocSlot()
|
|
||||||
builder.emit(Opcode.CONST_OBJ, calleeId, calleeSlot)
|
|
||||||
updateSlotType(calleeSlot, SlotType.OBJ)
|
|
||||||
val dst = allocSlot()
|
val dst = allocSlot()
|
||||||
builder.emit(Opcode.CALL_SLOT, calleeSlot, 0, 0, dst)
|
emitCallDirect(ObjList.type, 0, 0, dst)
|
||||||
updateSlotType(dst, SlotType.OBJ)
|
updateSlotType(dst, SlotType.OBJ)
|
||||||
slotObjClass[dst] = ObjList.type
|
slotObjClass[dst] = ObjList.type
|
||||||
return CompiledValue(dst, SlotType.OBJ)
|
return CompiledValue(dst, SlotType.OBJ)
|
||||||
|
|||||||
@ -361,6 +361,23 @@ class BytecodeRecentOpsTest {
|
|||||||
assertEquals(11, scope.eval("calc()").toInt())
|
assertEquals(11, scope.eval("calc()").toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun optionalExactLambdaCallUsesInlineBytecode() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
type IntFn = (Int)->Int
|
||||||
|
fun calc() {
|
||||||
|
val f: IntFn? = { x -> x + 1 }
|
||||||
|
f?(10)
|
||||||
|
}
|
||||||
|
""".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()
|
||||||
@ -516,6 +533,40 @@ class BytecodeRecentOpsTest {
|
|||||||
assertEquals(6, scope.eval("calc()").toInt())
|
assertEquals(6, scope.eval("calc()").toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapLiteralUsesDirectConstructorCall() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
fun calc() {
|
||||||
|
val m = { a: 1, b: 2 }
|
||||||
|
m.size
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
val disasm = scope.disassembleSymbol("calc")
|
||||||
|
assertTrue(disasm.contains("CALL_DIRECT"), disasm)
|
||||||
|
assertFalse(disasm.contains("CALL_SLOT"), disasm)
|
||||||
|
assertEquals(2, scope.eval("calc()").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapEntryLiteralUsesDirectConstructorCall() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
fun calc() {
|
||||||
|
val e = "a" => 2
|
||||||
|
e.value
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
val disasm = scope.disassembleSymbol("calc")
|
||||||
|
assertTrue(disasm.contains("CALL_DIRECT"), disasm)
|
||||||
|
assertFalse(disasm.contains("CALL_SLOT"), disasm)
|
||||||
|
assertEquals(2, scope.eval("calc()").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun optionalIndexPreIncSkipsOnNullReceiver() = runTest {
|
fun optionalIndexPreIncSkipsOnNullReceiver() = runTest {
|
||||||
eval(
|
eval(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user