Skip to content

Commit

Permalink
Remove LValue.assert* functions.
Browse files Browse the repository at this point in the history
GopherLua is a relatively old project. Old Go runtime had  slow interface
type assertions, but now Go runtime better its performance.
  • Loading branch information
yuin committed Dec 2, 2023
1 parent 1e3d646 commit 1388221
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 92 deletions.
40 changes: 20 additions & 20 deletions _vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,8 @@ func init() {
rhs := L.rkValue(C)
ret := false

if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
ret = v1 <= v2
} else {
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
Expand Down Expand Up @@ -572,7 +572,7 @@ func init() {
nret := C - 1
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
if fn, ok := lv.(*LFunction); ok {
callable = fn
meta = false
} else {
Expand All @@ -598,7 +598,7 @@ func init() {
lv := reg.Get(RA)
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
if fn, ok := lv.(*LFunction); ok {
callable = fn
meta = false
} else {
Expand Down Expand Up @@ -685,9 +685,9 @@ func init() {
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
if init, ok1 := reg.Get(RA).(LNumber); ok1 {
if limit, ok2 := reg.Get(RA + 1).(LNumber); ok2 {
if step, ok3 := reg.Get(RA + 2).(LNumber); ok3 {
init += step
v := LNumber(init)
// +inline-call reg.SetNumber RA v
Expand Down Expand Up @@ -716,8 +716,8 @@ func init() {
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
if init, ok1 := reg.Get(RA).(LNumber); ok1 {
if step, ok2 := reg.Get(RA + 2).(LNumber); ok2 {
// +inline-call reg.SetNumber RA LNumber(init-step)
} else {
L.RaiseError("for statement step must be a number")
Expand Down Expand Up @@ -839,8 +839,8 @@ func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SU
C := int(inst>>9) & 0x1ff //GETC
lhs := L.rkValue(B)
rhs := L.rkValue(C)
v1, ok1 := lhs.assertFloat64()
v2, ok2 := rhs.assertFloat64()
v1, ok1 := lhs.(LNumber)
v2, ok2 := rhs.(LNumber)
if ok1 && ok2 {
v := numberArith(L, opcode, LNumber(v1), LNumber(v2))
// +inline-call reg.SetNumber RA v
Expand Down Expand Up @@ -899,25 +899,25 @@ func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
event = "__pow"
}
op := L.metaOp2(lhs, rhs, event)
if _, ok := op.assertFunction(); ok {
if _, ok := op.(*LFunction); ok {
L.reg.Push(op)
L.reg.Push(lhs)
L.reg.Push(rhs)
L.Call(2, 1)
return L.reg.Pop()
}
if str, ok := lhs.assertString(); ok {
if str, ok := lhs.(LString); ok {
if lnum, err := parseNumber(string(str)); err == nil {
lhs = lnum
}
}
if str, ok := rhs.assertString(); ok {
if str, ok := rhs.(LString); ok {
if rnum, err := parseNumber(string(str)); err == nil {
rhs = rnum
}
}
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
return numberArith(L, opcode, LNumber(v1), LNumber(v2))
}
}
Expand Down Expand Up @@ -966,8 +966,8 @@ func stringConcat(L *LState, total, last int) LValue {

func lessThan(L *LState, lhs, rhs LValue) bool {
// optimization for numbers
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
return v1 < v2
}
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
Expand Down Expand Up @@ -997,8 +997,8 @@ func equals(L *LState, lhs, rhs LValue, raw bool) bool {
case LTNil:
ret = true
case LTNumber:
v1, _ := lhs.assertFloat64()
v2, _ := rhs.assertFloat64()
v1, _ := lhs.(LNumber)
v2, _ := rhs.(LNumber)
ret = v1 == v2
case LTBool:
ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
Expand Down
2 changes: 1 addition & 1 deletion auxlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ func (ls *LState) DoString(source string) error {
// ToStringMeta returns string representation of given LValue.
// This method calls the `__tostring` meta method if defined.
func (ls *LState) ToStringMeta(lv LValue) LValue {
if fn, ok := ls.metaOp1(lv, "__tostring").assertFunction(); ok {
if fn, ok := ls.metaOp1(lv, "__tostring").(*LFunction); ok {
ls.Push(fn)
ls.Push(lv)
ls.Call(1, 1)
Expand Down
4 changes: 2 additions & 2 deletions debuglib.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ func debugTraceback(L *LState) int {
level := L.OptInt(2, 1)
ls := L
if L.GetTop() > 0 {
if s, ok := L.Get(1).assertString(); ok {
msg = s
if s, ok := L.Get(1).(LString); ok {
msg = string(s)
}
if l, ok := L.Get(1).(*LState); ok {
ls = l
Expand Down
65 changes: 16 additions & 49 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ func (vt LValueType) String() string {
type LValue interface {
String() string
Type() LValueType
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertFloat64() (float64, bool)
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertString() (string, bool)
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertFunction() (*LFunction, bool)
}

// LVIsFalse returns true if a given LValue is a nil or false otherwise false.
Expand Down Expand Up @@ -80,11 +74,8 @@ func LVAsNumber(v LValue) LNumber {

type LNilType struct{}

func (nl *LNilType) String() string { return "nil" }
func (nl *LNilType) Type() LValueType { return LTNil }
func (nl *LNilType) assertFloat64() (float64, bool) { return 0, false }
func (nl *LNilType) assertString() (string, bool) { return "", false }
func (nl *LNilType) assertFunction() (*LFunction, bool) { return nil, false }
func (nl *LNilType) String() string { return "nil" }
func (nl *LNilType) Type() LValueType { return LTNil }

var LNil = LValue(&LNilType{})

Expand All @@ -96,21 +87,15 @@ func (bl LBool) String() string {
}
return "false"
}
func (bl LBool) Type() LValueType { return LTBool }
func (bl LBool) assertFloat64() (float64, bool) { return 0, false }
func (bl LBool) assertString() (string, bool) { return "", false }
func (bl LBool) assertFunction() (*LFunction, bool) { return nil, false }
func (bl LBool) Type() LValueType { return LTBool }

var LTrue = LBool(true)
var LFalse = LBool(false)

type LString string

func (st LString) String() string { return string(st) }
func (st LString) Type() LValueType { return LTString }
func (st LString) assertFloat64() (float64, bool) { return 0, false }
func (st LString) assertString() (string, bool) { return string(st), true }
func (st LString) assertFunction() (*LFunction, bool) { return nil, false }
func (st LString) String() string { return string(st) }
func (st LString) Type() LValueType { return LTString }

// fmt.Formatter interface
func (st LString) Format(f fmt.State, c rune) {
Expand All @@ -133,10 +118,7 @@ func (nm LNumber) String() string {
return fmt.Sprint(float64(nm))
}

func (nm LNumber) Type() LValueType { return LTNumber }
func (nm LNumber) assertFloat64() (float64, bool) { return float64(nm), true }
func (nm LNumber) assertString() (string, bool) { return "", false }
func (nm LNumber) assertFunction() (*LFunction, bool) { return nil, false }
func (nm LNumber) Type() LValueType { return LTNumber }

// fmt.Formatter interface
func (nm LNumber) Format(f fmt.State, c rune) {
Expand Down Expand Up @@ -168,11 +150,8 @@ type LTable struct {
k2i map[LValue]int
}

func (tb *LTable) String() string { return fmt.Sprintf("table: %p", tb) }
func (tb *LTable) Type() LValueType { return LTTable }
func (tb *LTable) assertFloat64() (float64, bool) { return 0, false }
func (tb *LTable) assertString() (string, bool) { return "", false }
func (tb *LTable) assertFunction() (*LFunction, bool) { return nil, false }
func (tb *LTable) String() string { return fmt.Sprintf("table: %p", tb) }
func (tb *LTable) Type() LValueType { return LTTable }

type LFunction struct {
IsG bool
Expand All @@ -183,11 +162,8 @@ type LFunction struct {
}
type LGFunction func(*LState) int

func (fn *LFunction) String() string { return fmt.Sprintf("function: %p", fn) }
func (fn *LFunction) Type() LValueType { return LTFunction }
func (fn *LFunction) assertFloat64() (float64, bool) { return 0, false }
func (fn *LFunction) assertString() (string, bool) { return "", false }
func (fn *LFunction) assertFunction() (*LFunction, bool) { return fn, true }
func (fn *LFunction) String() string { return fmt.Sprintf("function: %p", fn) }
func (fn *LFunction) Type() LValueType { return LTFunction }

type Global struct {
MainThread *LState
Expand Down Expand Up @@ -221,28 +197,19 @@ type LState struct {
ctxCancelFn context.CancelFunc
}

func (ls *LState) String() string { return fmt.Sprintf("thread: %p", ls) }
func (ls *LState) Type() LValueType { return LTThread }
func (ls *LState) assertFloat64() (float64, bool) { return 0, false }
func (ls *LState) assertString() (string, bool) { return "", false }
func (ls *LState) assertFunction() (*LFunction, bool) { return nil, false }
func (ls *LState) String() string { return fmt.Sprintf("thread: %p", ls) }
func (ls *LState) Type() LValueType { return LTThread }

type LUserData struct {
Value interface{}
Env *LTable
Metatable LValue
}

func (ud *LUserData) String() string { return fmt.Sprintf("userdata: %p", ud) }
func (ud *LUserData) Type() LValueType { return LTUserData }
func (ud *LUserData) assertFloat64() (float64, bool) { return 0, false }
func (ud *LUserData) assertString() (string, bool) { return "", false }
func (ud *LUserData) assertFunction() (*LFunction, bool) { return nil, false }
func (ud *LUserData) String() string { return fmt.Sprintf("userdata: %p", ud) }
func (ud *LUserData) Type() LValueType { return LTUserData }

type LChannel chan LValue

func (ch LChannel) String() string { return fmt.Sprintf("channel: %p", ch) }
func (ch LChannel) Type() LValueType { return LTChannel }
func (ch LChannel) assertFloat64() (float64, bool) { return 0, false }
func (ch LChannel) assertString() (string, bool) { return "", false }
func (ch LChannel) assertFunction() (*LFunction, bool) { return nil, false }
func (ch LChannel) String() string { return fmt.Sprintf("channel: %p", ch) }
func (ch LChannel) Type() LValueType { return LTChannel }
38 changes: 18 additions & 20 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@ func init() {
rhs := L.rkValue(C)
ret := false

if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
ret = v1 <= v2
} else {
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
Expand Down Expand Up @@ -1181,7 +1181,7 @@ func init() {
nret := C - 1
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
if fn, ok := lv.(*LFunction); ok {
callable = fn
meta = false
} else {
Expand Down Expand Up @@ -1324,7 +1324,7 @@ func init() {
lv := reg.Get(RA)
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
if fn, ok := lv.(*LFunction); ok {
callable = fn
meta = false
} else {
Expand Down Expand Up @@ -1795,9 +1795,9 @@ func init() {
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
if init, ok1 := reg.Get(RA).(LNumber); ok1 {
if limit, ok2 := reg.Get(RA + 1).(LNumber); ok2 {
if step, ok3 := reg.Get(RA + 2).(LNumber); ok3 {
init += step
v := LNumber(init)
// this section is inlined by go-inline
Expand Down Expand Up @@ -1893,8 +1893,8 @@ func init() {
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
if init, ok1 := reg.Get(RA).(LNumber); ok1 {
if step, ok2 := reg.Get(RA + 2).(LNumber); ok2 {
// this section is inlined by go-inline
// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go'
{
Expand Down Expand Up @@ -2217,8 +2217,6 @@ func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SU
C := int(inst>>9) & 0x1ff //GETC
lhs := L.rkValue(B)
rhs := L.rkValue(C)
// v1, ok1 := lhs.assertFloat64()
// v2, ok2 := rhs.assertFloat64()
v1, ok1 := lhs.(LNumber)
v2, ok2 := rhs.(LNumber)
if ok1 && ok2 {
Expand Down Expand Up @@ -2317,25 +2315,25 @@ func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
event = "__pow"
}
op := L.metaOp2(lhs, rhs, event)
if _, ok := op.assertFunction(); ok {
if _, ok := op.(*LFunction); ok {
L.reg.Push(op)
L.reg.Push(lhs)
L.reg.Push(rhs)
L.Call(2, 1)
return L.reg.Pop()
}
if str, ok := lhs.assertString(); ok {
if str, ok := lhs.(LString); ok {
if lnum, err := parseNumber(string(str)); err == nil {
lhs = lnum
}
}
if str, ok := rhs.assertString(); ok {
if str, ok := rhs.(LString); ok {
if rnum, err := parseNumber(string(str)); err == nil {
rhs = rnum
}
}
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
return numberArith(L, opcode, LNumber(v1), LNumber(v2))
}
}
Expand Down Expand Up @@ -2384,8 +2382,8 @@ func stringConcat(L *LState, total, last int) LValue {

func lessThan(L *LState, lhs, rhs LValue) bool {
// optimization for numbers
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
if v1, ok1 := lhs.(LNumber); ok1 {
if v2, ok2 := rhs.(LNumber); ok2 {
return v1 < v2
}
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
Expand Down Expand Up @@ -2415,8 +2413,8 @@ func equals(L *LState, lhs, rhs LValue, raw bool) bool {
case LTNil:
ret = true
case LTNumber:
v1, _ := lhs.assertFloat64()
v2, _ := rhs.assertFloat64()
v1, _ := lhs.(LNumber)
v2, _ := rhs.(LNumber)
ret = v1 == v2
case LTBool:
ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
Expand Down

0 comments on commit 1388221

Please sign in to comment.