From 77b4ed349e57ec5ff6e940ffd586a574867298cc Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 4 Nov 2024 23:12:37 +0100 Subject: [PATCH] 1148: invoke user recover with implicit panics --- gnovm/pkg/gnolang/machine.go | 33 +++++++++++++++++++++++++++++++++ gnovm/pkg/gnolang/op_call.go | 7 +++++++ 2 files changed, 40 insertions(+) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 09be71682a5..3b927f2036c 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -831,6 +831,15 @@ func (m *Machine) RunFunc(fn Name) { func (m *Machine) RunMain() { defer func() { if r := recover(); r != nil { + // we panicked because there was an invalid operation + // if the user had a recover, do it + hasRecover := m.setupRecoverPanic() + + if hasRecover { + m.Run() + return + } + switch r := r.(type) { case UnhandledPanicError: fmt.Printf("Machine.RunMain() panic: %s\nStacktrace: %s\n", @@ -2179,6 +2188,30 @@ func (m *Machine) CheckEmpty() error { } } +func (m *Machine) setupRuntimePanic(ex TypedValue) bool { + frm := m.LastCallFrame(1) + + if frm == nil { + return false + } + + m.Exceptions = append( + m.Exceptions, + Exception{ + Value: ex, + Frame: frm, + Stacktrace: m.Stacktrace(), + }, + ) + + m.PanicScope++ + m.PopUntilLastCallFrame() + m.PushOp(OpPanic2) + m.PushOp(OpReturnCallDefers) + + return true +} + func (m *Machine) Panic(ex TypedValue) { m.Exceptions = append( m.Exceptions, diff --git a/gnovm/pkg/gnolang/op_call.go b/gnovm/pkg/gnolang/op_call.go index ba5b7507cff..ebc5b530cb0 100644 --- a/gnovm/pkg/gnolang/op_call.go +++ b/gnovm/pkg/gnolang/op_call.go @@ -432,6 +432,13 @@ func (m *Machine) doOpDefer() { } } +func (m *Machine) setupRecoverPanic() bool { + // Pop exception + ex := m.PopValue().Copy(m.Alloc) + // Panic + return m.setupRuntimePanic(ex) +} + func (m *Machine) doOpPanic1() { // Pop exception var ex TypedValue = m.PopValue().Copy(m.Alloc)