Skip to content

Commit

Permalink
Merge remote-tracking branch 'hook/debugger-sup'
Browse files Browse the repository at this point in the history
  • Loading branch information
willwu5047 committed Mar 22, 2023
2 parents fa815b5 + 92ca436 commit 5449aa7
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 10 deletions.
20 changes: 20 additions & 0 deletions _state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,26 @@ func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string {
return ""
}

func (ls *LState) SetHook(callback *LFunction, event string, count int) error {
frame := ls.stack.At(0)
if count > 0 {
ls.cthook = newCTHook(callback, count)
}
for _, c := range event {
switch c {
case 'l':
ls.lhook = newLHook(callback, frame.Fn.Proto.DbgSourcePositions[frame.Pc-1])
case 'c':
ls.chook = newCHook(callback)
case 'r':
ls.rhook = newRHook(callback)
default:
return newApiErrorS(ApiErrorRun, fmt.Sprintf("invalid hook event: %c", c))
}
}
return nil
}

/* }}} */

/* env operations {{{ */
Expand Down
18 changes: 18 additions & 0 deletions _vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ func mainLoop(L *LState, baseframe *callFrame) {
cf = L.currentFrame
inst = cf.Fn.Proto.Code[cf.Pc]
cf.Pc++
if L.lhook != nil {
L.lhook.call(L, cf)
}
if L.cthook != nil {
L.cthook.call(L, cf)
}
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
Expand Down Expand Up @@ -53,6 +59,12 @@ func mainLoopWithContext(L *LState, baseframe *callFrame) {
L.RaiseError(L.ctx.Err().Error())
return
default:
if L.lhook != nil {
L.lhook.call(L, cf)
}
if L.cthook != nil {
L.cthook.call(L, cf)
}
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
Expand Down Expand Up @@ -545,6 +557,9 @@ func init() {
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL
if L.chook != nil {
L.chook.call(L, baseframe)
}
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
Expand Down Expand Up @@ -638,6 +653,9 @@ func init() {
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
if L.rhook != nil {
L.rhook.call(L, baseframe)
}
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
Expand Down
39 changes: 30 additions & 9 deletions compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,13 @@ type varNamePoolValue struct {
}

type varNamePool struct {
names []string
offset int
names []string
globalIndex []int
offset int
}

func newVarNamePool(offset int) *varNamePool {
return &varNamePool{make([]string, 0, 16), offset}
return &varNamePool{make([]string, 0, 16), make([]int, 0, 16), offset}
}

func (vp *varNamePool) Names() []string {
Expand All @@ -324,6 +325,15 @@ func (vp *varNamePool) List() []varNamePoolValue {
return result
}

func (vp *varNamePool) ListGlobalIndex() []varNamePoolValue {
result := make([]varNamePoolValue, len(vp.names), len(vp.names))
for i, name := range vp.names {
result[i].Index = vp.globalIndex[i]
result[i].Name = name
}
return result
}

func (vp *varNamePool) LastIndex() int {
return vp.offset + len(vp.names)
}
Expand All @@ -340,13 +350,14 @@ func (vp *varNamePool) Find(name string) int {
func (vp *varNamePool) RegisterUnique(name string) int {
index := vp.Find(name)
if index < 0 {
return vp.Register(name)
return vp.Register(name, -1)
}
return index
}

func (vp *varNamePool) Register(name string) int {
func (vp *varNamePool) Register(name string, globalIndex int) int {
vp.names = append(vp.names, name)
vp.globalIndex = append(vp.globalIndex, globalIndex)
return len(vp.names) - 1 + vp.offset
}

Expand Down Expand Up @@ -541,8 +552,8 @@ func (fc *funcContext) BlockLocalVarsCount() int {
}

func (fc *funcContext) RegisterLocalVar(name string) int {
ret := fc.Block.LocalVars.Register(name)
fc.Proto.DbgLocals = append(fc.Proto.DbgLocals, &DbgLocalInfo{Name: name, StartPc: fc.Code.LastPC() + 1})
ret := fc.Block.LocalVars.Register(name, len(fc.Proto.DbgLocals))
fc.Proto.DbgLocals = append(fc.Proto.DbgLocals, &DbgLocalInfo{Name: name, StartPc: fc.Code.pc})
fc.SetRegTop(fc.RegTop() + 1)
return ret
}
Expand Down Expand Up @@ -596,9 +607,15 @@ func (fc *funcContext) LeaveBlock() int {
}

func (fc *funcContext) EndScope() {
for _, vr := range fc.Block.LocalVars.List() {
for _, vr := range fc.Block.LocalVars.ListGlobalIndex() {
fc.Proto.DbgLocals[vr.Index].EndPc = fc.Code.LastPC()
}

//for _, dbLocal := range fc.Proto.DbgLocals {
// if fc.Block.LocalVars.Find(dbLocal.Name) != -1 {
// dbLocal.EndPc = fc.Code.LastPC()
// }
//}
}

func (fc *funcContext) SetRegTop(top int) {
Expand Down Expand Up @@ -1382,7 +1399,11 @@ func compileTableExpr(context *funcContext, reg int, ex *ast.TableExpr, ec *expc
if _, ok := field.Key.(*ast.StringExpr); ok {
opcode = OP_SETTABLEKS
}
code.AddABC(opcode, tablereg, b, c, sline(ex))
line := field.Value
if field.Key != nil {
line = field.Key
}
code.AddABC(opcode, tablereg, b, c, sline(line))
reg = regorg
}
flush := arraycount % FieldsPerFlush
Expand Down
13 changes: 13 additions & 0 deletions debuglib.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,26 @@ var debugFuncs = map[string]LGFunction{
"setmetatable": debugSetMetatable,
"setupvalue": debugSetUpvalue,
"traceback": debugTraceback,
"sethook": debugSetHook,
}

func debugGetFEnv(L *LState) int {
L.Push(L.GetFEnv(L.CheckAny(1)))
return 1
}

func debugSetHook(L *LState) int {
L.CheckTypes(1, LTFunction)
L.CheckTypes(2, LTString)
L.CheckTypes(3, LTNumber)
callbackArg := L.OptFunction(1, nil)
eventArg := L.OptString(2, "")
countArg := L.OptInt(3, 0)
L.Pop(3)
_ = L.SetHook(callbackArg, eventArg, countArg)
return 0
}

func debugGetInfo(L *LState) int {
L.CheckTypes(1, LTFunction, LTNumber)
arg1 := L.Get(1)
Expand Down
2 changes: 1 addition & 1 deletion function.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (fn *LFunction) LocalName(regno, pc int) (string, bool) {
return "", false
}
p := fn.Proto
for i := 0; i < len(p.DbgLocals) && p.DbgLocals[i].StartPc < pc; i++ {
for i := 0; i < len(p.DbgLocals) && p.DbgLocals[i].StartPc <= pc; i++ {
if pc < p.DbgLocals[i].EndPc {
regno--
if regno == 0 {
Expand Down
106 changes: 106 additions & 0 deletions hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package lua

import "fmt"

type Hooker interface {
call(L *LState, cf *callFrame)
String() string
}

type LHook struct {
callback *LFunction
line int
}

func newLHook(callback *LFunction, line int) *LHook {
return &LHook{
callback: callback,
line: line,
}
}

func (lh *LHook) call(L *LState, cf *callFrame) {
currentline := cf.Fn.Proto.DbgSourcePositions[cf.Pc-1]
if currentline != 0 && cf.Fn != lh.callback && currentline != L.prevline {
L.reg.Push(lh.callback)
L.reg.Push(LString("line"))
L.reg.Push(LNumber(currentline))
L.callR(2, 0, -1)
L.prevline = currentline
}
}

func (lh *LHook) String() string {
return fmt.Sprintf("hook: %p", lh)
}

type CTHook struct {
callback *LFunction
count int
currentCount int
}

func newCTHook(callback *LFunction, count int) *CTHook {
return &CTHook{
callback: callback,
count: count,
}
}

func (ct *CTHook) call(L *LState, cf *callFrame) {
ct.currentCount++
if ct.currentCount == ct.count {
L.reg.Push(ct.callback)
L.reg.Push(LString("count"))
L.callR(1, 0, -1)
ct.currentCount = 0
}
}

func (ct *CTHook) String() string {
return fmt.Sprintf("hook: %p", ct)
}

type CHook struct {
callback *LFunction
}

func newCHook(callback *LFunction) *CHook {
return &CHook{
callback: callback,
}
}

func (ch *CHook) call(L *LState, cf *callFrame) {
if ch.callback != cf.Fn {
L.reg.Push(ch.callback)
L.reg.Push(LString("call"))
L.callR(1, 0, -1)
}
}

func (ch *CHook) String() string {
return fmt.Sprintf("hook: %p", ch)
}

type RHook struct {
callback *LFunction
}

func newRHook(callback *LFunction) *RHook {
return &RHook{
callback: callback,
}
}

func (rh *RHook) call(L *LState, cf *callFrame) {
if rh.callback != cf.Fn {
L.reg.Push(rh.callback)
L.reg.Push(LString("return"))
L.callR(1, 0, -1)
}
}

func (rh *RHook) String() string {
return fmt.Sprintf("hook: %p", rh)
}
28 changes: 28 additions & 0 deletions state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,34 @@ func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string {
return ""
}

func (ls *LState) SetHook(callback *LFunction, event string, count int) error {
if event == "" {
ls.cthook = nil
ls.lhook = nil
ls.chook = nil
ls.rhook = nil
return nil
}

frame := ls.stack.At(0)
if count > 0 {
ls.cthook = newCTHook(callback, count)
}
for _, c := range event {
switch c {
case 'l':
ls.lhook = newLHook(callback, frame.Fn.Proto.DbgSourcePositions[frame.Pc-1])
case 'c':
ls.chook = newCHook(callback)
case 'r':
ls.rhook = newRHook(callback)
default:
return newApiErrorS(ApiErrorRun, fmt.Sprintf("invalid hook event: %c", c))
}
}
return nil
}

/* }}} */

/* env operations {{{ */
Expand Down
5 changes: 5 additions & 0 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ type LState struct {
hasErrorFunc bool
mainLoop func(*LState, *callFrame)
ctx context.Context
lhook Hooker
chook Hooker
rhook Hooker
cthook Hooker
prevline int
}

func (ls *LState) String() string { return fmt.Sprintf("thread: %p", ls) }
Expand Down
18 changes: 18 additions & 0 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ func mainLoop(L *LState, baseframe *callFrame) {
cf = L.currentFrame
inst = cf.Fn.Proto.Code[cf.Pc]
cf.Pc++
if L.lhook != nil {
L.lhook.call(L, cf)
}
if L.cthook != nil {
L.cthook.call(L, cf)
}
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
Expand Down Expand Up @@ -57,6 +63,12 @@ func mainLoopWithContext(L *LState, baseframe *callFrame) {
L.RaiseError(L.ctx.Err().Error())
return
default:
if L.lhook != nil {
L.lhook.call(L, cf)
}
if L.cthook != nil {
L.cthook.call(L, cf)
}
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
Expand Down Expand Up @@ -679,6 +691,9 @@ func init() {
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL
if L.chook != nil {
L.chook.call(L, baseframe)
}
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
Expand Down Expand Up @@ -1044,6 +1059,9 @@ func init() {
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
if L.rhook != nil {
L.rhook.call(L, baseframe)
}
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
Expand Down

0 comments on commit 5449aa7

Please sign in to comment.