diff --git a/hbrdd/ntx/ntx.go b/hbrdd/ntx/ntx.go index 0886967..6e38d4d 100644 --- a/hbrdd/ntx/ntx.go +++ b/hbrdd/ntx/ntx.go @@ -283,7 +283,8 @@ func (idx *Index) remapFile() { idx.mmapFile() } -func (idx *Index) KeyLen() int { return idx.keyLen } +func (idx *Index) KeyLen() int { return idx.keyLen } +func (idx *Index) TestGetMmap() []byte { return idx.mmapData } func (idx *Index) Close() error { if idx.mmapData != nil { diff --git a/hbrt/thread.go b/hbrt/thread.go index 624be00..b1ac8cf 100644 --- a/hbrt/thread.go +++ b/hbrt/thread.go @@ -250,12 +250,21 @@ func (t *Thread) EndProc() { if hbErr, ok := r.(*HbError); ok { t.handleSequenceError(hbErr) } else { - // Print error to stderr before re-panic fmt.Fprintf(os.Stderr, "Five runtime error: %v\n", r) panic(r) } } + t.endFrame() +} +// EndProcFast is called by RTL functions that don't need recover(). +// ~3x faster than EndProc (no defer recover overhead). +func (t *Thread) EndProcFast() { + t.endFrame() +} + +// endFrame restores the previous call frame. +func (t *Thread) endFrame() { if t.callSP > 0 { t.callSP-- if t.callSP > 0 { diff --git a/hbrtl/database.go b/hbrtl/database.go index e54480c..333a139 100644 --- a/hbrtl/database.go +++ b/hbrtl/database.go @@ -15,7 +15,7 @@ import ( // FIELDPUT(nField, xValue) → xValue func rtlFieldPut(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -36,7 +36,7 @@ func rtlFieldPut(t *hbrt.Thread) { func rtlAlias(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetString("") @@ -54,7 +54,7 @@ func rtlAlias(t *hbrt.Thread) { func rtlDbEval(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { @@ -141,7 +141,7 @@ func rtlDbEval(t *hbrt.Thread) { func rtlDbUseArea(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -174,7 +174,7 @@ func rtlDbUseArea(t *hbrt.Thread) { // DBCLOSEAREA() → NIL func rtlDbCloseArea(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam != nil { wam.Close() @@ -185,7 +185,7 @@ func rtlDbCloseArea(t *hbrt.Thread) { // DBGOTO(nRecNo) → NIL func rtlDbGoTo(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -202,7 +202,7 @@ func rtlDbGoTo(t *hbrt.Thread) { func rtlDbSkip(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -224,7 +224,7 @@ func rtlDbSkip(t *hbrt.Thread) { // DBGOTOP() → NIL func rtlDbGoTop(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -240,7 +240,7 @@ func rtlDbGoTop(t *hbrt.Thread) { // DBGOBOTTOM() → NIL func rtlDbGoBottom(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -257,7 +257,7 @@ func rtlDbGoBottom(t *hbrt.Thread) { func rtlDbAppend(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -273,7 +273,7 @@ func rtlDbAppend(t *hbrt.Thread) { // DBDELETE() → NIL func rtlDbDelete(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -289,7 +289,7 @@ func rtlDbDelete(t *hbrt.Thread) { // DBRECALL() → NIL func rtlDbRecall(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -305,7 +305,7 @@ func rtlDbRecall(t *hbrt.Thread) { // DBCOMMIT() → NIL func rtlDbCommit(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -322,7 +322,7 @@ func rtlDbCommit(t *hbrt.Thread) { func rtlDbSeek(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetBool(false) @@ -354,7 +354,7 @@ func rtlDbSeek(t *hbrt.Thread) { // DBSELECTAREA(nArea | cAlias) → NIL func rtlDbSelectArea(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -372,7 +372,7 @@ func rtlDbSelectArea(t *hbrt.Thread) { // DBPACK() → NIL func rtlDbPack(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -388,7 +388,7 @@ func rtlDbPack(t *hbrt.Thread) { // DBZAP() → NIL func rtlDbZap(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { t.RetNil() @@ -408,7 +408,7 @@ func rtlDbZap(t *hbrt.Thread) { func rtlDbLocate(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { @@ -507,7 +507,7 @@ func rtlDbLocate(t *hbrt.Thread) { // Harbour: __dbContinue() func rtlDbContinue(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { @@ -548,7 +548,7 @@ func rtlDbContinue(t *hbrt.Thread) { func rtlDbSetFilter(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { @@ -579,7 +579,7 @@ func rtlDbSetFilter(t *hbrt.Thread) { // DBCLEARFILTER() func rtlDbClearFilter(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam == nil { @@ -595,7 +595,7 @@ func rtlDbClearFilter(t *hbrt.Thread) { // DBFILTER() → cFilterExpression func rtlDbFilter(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() // TODO: return stored filter expression from area t.RetString("") diff --git a/hbrtl/missing.go b/hbrtl/missing.go index 67613f3..a1fcdd6 100644 --- a/hbrtl/missing.go +++ b/hbrtl/missing.go @@ -16,7 +16,7 @@ import ( // At returns position of cSearch in cTarget (1-based, 0 if not found). func At(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() search := t.Local(1).AsString() target := t.Local(2).AsString() idx := strings.Index(target, search) @@ -30,7 +30,7 @@ func At(t *hbrt.Thread) { // Left returns leftmost n characters. func Left(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() n := int(t.Local(2).AsNumInt()) if n >= len(s) { @@ -46,7 +46,7 @@ func Left(t *hbrt.Thread) { // Right returns rightmost n characters. func Right(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() n := int(t.Local(2).AsNumInt()) if n >= len(s) { @@ -62,7 +62,7 @@ func Right(t *hbrt.Thread) { // Asc returns ASCII code of first character. func Asc(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() if len(s) > 0 { t.RetInt(int64(s[0])) @@ -74,7 +74,7 @@ func Asc(t *hbrt.Thread) { // Chr returns character from ASCII code. func Chr(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() n := int(t.Local(1).AsNumInt()) t.PushString(string([]byte{byte(n)})) t.RetValue() @@ -84,7 +84,7 @@ func Chr(t *hbrt.Thread) { func StrTran(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() search := t.Local(2).AsString() replace := "" @@ -98,7 +98,7 @@ func StrTran(t *hbrt.Thread) { // Stuff inserts/replaces characters in string. func Stuff(t *hbrt.Thread) { t.Frame(4, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() start := int(t.Local(2).AsNumInt()) - 1 // 1-based nDel := int(t.Local(3).AsNumInt()) @@ -120,7 +120,7 @@ func Stuff(t *hbrt.Thread) { // PadC pads string centered. func PadC(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() s := valueToDisplay(t.Local(1)) n := int(t.Local(2).AsNumInt()) if len(s) >= n { @@ -138,7 +138,7 @@ func PadC(t *hbrt.Thread) { // Round rounds a number to specified decimal places. func Round(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() val := t.Local(1).AsNumDouble() dec := int(t.Local(2).AsNumInt()) mult := math.Pow(10, float64(dec)) @@ -150,7 +150,7 @@ func Round(t *hbrt.Thread) { // Max returns larger of two values. func Max(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() a := t.Local(1) b := t.Local(2) if a.IsNumeric() && b.IsNumeric() { @@ -174,7 +174,7 @@ func Max(t *hbrt.Thread) { // Min returns smaller of two values. func Min(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() a := t.Local(1) b := t.Local(2) if a.IsNumeric() && b.IsNumeric() { @@ -198,7 +198,7 @@ func Min(t *hbrt.Thread) { // Sqrt returns square root. func Sqrt(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() t.PushValue(hbrt.MakeDoubleAuto(math.Sqrt(t.Local(1).AsNumDouble()))) t.RetValue() } @@ -206,7 +206,7 @@ func Sqrt(t *hbrt.Thread) { // Log returns natural logarithm. func Log(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() t.PushValue(hbrt.MakeDoubleAuto(math.Log(t.Local(1).AsNumDouble()))) t.RetValue() } @@ -214,7 +214,7 @@ func Log(t *hbrt.Thread) { // Exp returns e^x. func Exp(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() t.PushValue(hbrt.MakeDoubleAuto(math.Exp(t.Local(1).AsNumDouble()))) t.RetValue() } @@ -222,7 +222,7 @@ func Exp(t *hbrt.Thread) { // Mod returns modulus (same as %). func Mod(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() a := t.Local(1).AsNumDouble() b := t.Local(2).AsNumDouble() if b == 0 { @@ -240,7 +240,7 @@ func Mod(t *hbrt.Thread) { // Type returns type of an expression (as string). func TypeFunc(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) var c string switch { @@ -272,7 +272,7 @@ func TypeFunc(t *hbrt.Thread) { // PCount returns number of parameters passed. func PCount(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() t.RetInt(int64(t.ParamCount())) } @@ -281,7 +281,7 @@ func PCount(t *hbrt.Thread) { // Array creates array of given size. func ArrayFunc(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() n := int(t.Local(1).AsNumInt()) t.PushValue(hbrt.MakeArray(n)) t.RetValue() @@ -290,7 +290,7 @@ func ArrayFunc(t *hbrt.Thread) { // FCount returns number of fields in current workarea. func FCount(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() wam := getWA(t) if wam != nil { if area := wam.Current(); area != nil { @@ -304,7 +304,7 @@ func FCount(t *hbrt.Thread) { // FieldName returns field name by position (1-based). func FieldName(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() nField := int(t.Local(1).AsNumInt()) wam := getWA(t) if wam != nil { @@ -322,7 +322,7 @@ func FieldName(t *hbrt.Thread) { // Select returns current workarea number. func SelectFunc(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() // TODO: integrate with RDD t.RetInt(0) } @@ -330,7 +330,7 @@ func SelectFunc(t *hbrt.Thread) { // File checks if file exists. func FileFunc(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() // Simple implementation t.PushBool(false) t.RetValue() @@ -342,7 +342,7 @@ func FileFunc(t *hbrt.Thread) { func Inkey(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() // Check keyboard buffer first if k := PopKeyBuffer(); k >= 0 { @@ -390,7 +390,7 @@ func Inkey(t *hbrt.Thread) { func Transform(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() val := t.Local(1) pic := "" if nParams >= 2 && !t.Local(2).IsNil() { @@ -402,7 +402,7 @@ func Transform(t *hbrt.Thread) { // hb_StrReplace replaces multiple substrings. func HbStrReplace(t *hbrt.Thread) { t.Frame(3, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() search := t.Local(2) // array of search strings replace := t.Local(3) // array of replace strings @@ -420,7 +420,7 @@ func HbStrReplace(t *hbrt.Thread) { // hb_NToS converts number to string without leading spaces. func HbNToS(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsNumInt() { t.PushString(fmt_int64(v.AsNumInt())) diff --git a/hbrtl/rdd.go b/hbrtl/rdd.go index 53473bb..5e81b32 100644 --- a/hbrtl/rdd.go +++ b/hbrtl/rdd.go @@ -12,7 +12,7 @@ import ( func rtlEOF(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { t.PushBool(area.EOF()) @@ -26,7 +26,7 @@ func rtlEOF(t *hbrt.Thread) { func rtlBOF(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { t.PushBool(area.BOF()) @@ -40,7 +40,7 @@ func rtlBOF(t *hbrt.Thread) { func rtlFound(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { t.PushBool(area.Found()) @@ -54,7 +54,7 @@ func rtlFound(t *hbrt.Thread) { func rtlRecNo(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { t.RetInt(int64(area.RecNo())) @@ -66,7 +66,7 @@ func rtlRecNo(t *hbrt.Thread) { func rtlRecCount(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { rc, _ := area.RecCount() @@ -79,7 +79,7 @@ func rtlRecCount(t *hbrt.Thread) { func rtlDeleted(t *hbrt.Thread) { t.Frame(0, 0) - defer t.EndProc() + defer t.EndProcFast() if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { t.PushBool(area.Deleted()) @@ -93,7 +93,7 @@ func rtlDeleted(t *hbrt.Thread) { func rtlFieldGet(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() n := int(t.Local(1).AsNumInt()) if wa := getWA(t); wa != nil { if area := wa.Current(); area != nil { diff --git a/hbrtl/strings.go b/hbrtl/strings.go index 367635b..a2420f9 100644 --- a/hbrtl/strings.go +++ b/hbrtl/strings.go @@ -38,7 +38,7 @@ func spaces(n int) string { func Str(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if !v.IsNumeric() { @@ -85,7 +85,7 @@ func Str(t *hbrt.Thread) { // Harbour: Val(cString) → nValue func Val(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if !v.IsString() { @@ -129,7 +129,7 @@ func Val(t *hbrt.Thread) { // Harbour: Len(xValue) → nLen func Len(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) switch { @@ -149,7 +149,7 @@ func Len(t *hbrt.Thread) { func SubStr(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if !v.IsString() { @@ -197,7 +197,7 @@ func SubStr(t *hbrt.Thread) { // Harbour: Upper(cString) → cString func Upper(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsString() { t.PushString(strings.ToUpper(v.AsString())) @@ -210,7 +210,7 @@ func Upper(t *hbrt.Thread) { // Lower converts string to lowercase. func Lower(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsString() { t.PushString(strings.ToLower(v.AsString())) @@ -223,7 +223,7 @@ func Lower(t *hbrt.Thread) { // AllTrim removes leading and trailing spaces. func AllTrim(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsString() { t.PushString(strings.TrimSpace(v.AsString())) @@ -236,7 +236,7 @@ func AllTrim(t *hbrt.Thread) { // LTrim trims leading spaces only. Harbour: LTRIM(cString) → cString func LTrim(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsString() { t.PushString(strings.TrimLeft(v.AsString(), " ")) @@ -249,7 +249,7 @@ func LTrim(t *hbrt.Thread) { // RTrim trims trailing spaces only. Harbour: RTRIM(cString) / TRIM(cString) func RTrim(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsString() { t.PushString(strings.TrimRight(v.AsString(), " ")) @@ -263,7 +263,7 @@ func RTrim(t *hbrt.Thread) { // Harbour: Space(nCount) → cString func Space(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() n := t.Local(1).AsNumInt() if n < 0 { n = 0 @@ -276,7 +276,7 @@ func Space(t *hbrt.Thread) { func PadR(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() s := valueToDisplay(t.Local(1)) n := int(t.Local(2).AsNumInt()) fill := " " @@ -303,7 +303,7 @@ func PadR(t *hbrt.Thread) { func PadL(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) - defer t.EndProc() + defer t.EndProcFast() s := valueToDisplay(t.Local(1)) n := int(t.Local(2).AsNumInt()) fill := " " @@ -329,7 +329,7 @@ func PadL(t *hbrt.Thread) { // Replicate repeats a string n times. func Replicate(t *hbrt.Thread) { t.Frame(2, 0) - defer t.EndProc() + defer t.EndProcFast() s := t.Local(1).AsString() n := int(t.Local(2).AsNumInt()) if n < 0 { @@ -345,7 +345,7 @@ func Replicate(t *hbrt.Thread) { // Harbour: ValType(xValue) → cType func ValType(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) var c string switch { @@ -382,7 +382,7 @@ func ValType(t *hbrt.Thread) { // Harbour: Empty(xValue) → lEmpty func Empty(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) var empty bool switch { @@ -412,7 +412,7 @@ func Empty(t *hbrt.Thread) { // Abs returns the absolute value. func Abs(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsNumInt() { n := v.AsNumInt() @@ -432,7 +432,7 @@ func Abs(t *hbrt.Thread) { // Int returns the integer part of a numeric value. func Int(t *hbrt.Thread) { t.Frame(1, 0) - defer t.EndProc() + defer t.EndProcFast() v := t.Local(1) if v.IsNumInt() { t.PushValue(v)