compiler: optimize GAS cost of type conversion

CONVERT call base price is 8192. DUP, ISTYPE and JMPIF all cost 2. So we add
0.07% overhead in the worst case and save 99.93% otherwise.

At the same time, old code was just two bytes and new one is seven, but I
think it's tolerable considering how much GAS it can potentially save.

Fix #2250.
This commit is contained in:
Roman Khimov 2021-11-12 19:58:21 +03:00
parent b31a8d750e
commit db99368e96

View file

@ -1272,7 +1272,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
goTyp := c.typeOf(n.Type) goTyp := c.typeOf(n.Type)
if canConvert(goTyp.String()) { if canConvert(goTyp.String()) {
typ := toNeoType(goTyp) typ := toNeoType(goTyp)
emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)}) c.emitConvert(typ)
} }
return nil return nil
} }
@ -1763,6 +1763,9 @@ func transformArgs(fs *funcScope, fun ast.Expr, args []ast.Expr) []ast.Expr {
// emitConvert converts top stack item to the specified type. // emitConvert converts top stack item to the specified type.
func (c *codegen) emitConvert(typ stackitem.Type) { func (c *codegen) emitConvert(typ stackitem.Type) {
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
emit.Instruction(c.prog.BinWriter, opcode.ISTYPE, []byte{byte(typ)})
emit.Instruction(c.prog.BinWriter, opcode.JMPIF, []byte{2 + 2}) // After CONVERT.
emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)}) emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)})
} }