@@ -38,17 +38,16 @@ type deferFrame struct {
3838 JumpPC unsafe.Pointer // pc to return to
3939 ExtraRegs [deferExtraRegs ]unsafe.Pointer // extra registers (depending on the architecture)
4040 Previous * deferFrame // previous recover buffer pointer
41- Panicking panicState // not panicking, panicking, or in Goexit
41+ Panicking panicState // panic/ Goexit state
4242 PanicValue interface {} // panic value, might be nil for panic(nil) for example
4343 DeferPtr unsafe.Pointer // head of the stack-allocated defer list
44- Goexit bool // whether Goexit is still pending after a recovered deferred panic
4544}
4645
4746type panicState uint8
4847
4948const (
50- panicFalse panicState = iota
51- panicTrue
49+ panicFalse panicState = 0
50+ panicTrue panicState = 1 << iota
5251 panicGoexit
5352)
5453
@@ -66,10 +65,10 @@ func panicOrGoexit(message interface{}, panicking panicState) {
6665 if supportsRecover () && ! interrupt .In () {
6766 frame := (* deferFrame )(task .Current ().DeferFrame )
6867 if frame != nil {
69- if panicking == panicGoexit {
70- frame .Goexit = true
71- }
7268 frame .PanicValue = message
69+ if panicking & panicTrue != 0 {
70+ panicking |= frame .Panicking & panicGoexit
71+ }
7372 frame .Panicking = panicking
7473 tinygo_longjmp (frame )
7574 // unreachable
@@ -103,7 +102,7 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
103102 // Use the normal panic mechanism so that this runtime error
104103 // can be recovered with recover().
105104 frame .PanicValue = plainError (msg )
106- frame .Panicking = panicTrue
105+ frame .Panicking = panicTrue | ( frame . Panicking & panicGoexit )
107106 tinygo_longjmp (frame )
108107 // unreachable
109108 }
@@ -142,7 +141,6 @@ func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
142141 frame .JumpSP = jumpSP
143142 frame .Panicking = panicFalse
144143 frame .DeferPtr = nil
145- frame .Goexit = false
146144 currentTask .DeferFrame = unsafe .Pointer (frame )
147145}
148146
@@ -154,12 +152,12 @@ func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
154152//go:nobounds
155153func destroyDeferFrame (frame * deferFrame ) {
156154 task .Current ().DeferFrame = unsafe .Pointer (frame .Previous )
157- if frame .Panicking != panicFalse {
155+ if frame .Panicking & panicTrue != 0 {
158156 // We're still panicking!
159157 // Re-raise the panic now.
160- panicOrGoexit (frame .PanicValue , frame . Panicking )
158+ panicOrGoexit (frame .PanicValue , panicTrue )
161159 }
162- if frame .Goexit {
160+ if frame .Panicking & panicGoexit != 0 {
163161 // A deferred function panicked during Goexit, and that panic was
164162 // recovered. Continue the original Goexit instead of returning.
165163 panicOrGoexit (nil , panicGoexit )
@@ -195,14 +193,14 @@ func _recover(useParentFrame bool) interface{} {
195193 frame = frame .Previous
196194 }
197195 if frame != nil && frame .Panicking != panicFalse {
198- if frame .Panicking == panicGoexit {
196+ if frame .Panicking & panicTrue == 0 {
199197 // Special value that indicates we're exiting the goroutine using
200198 // Goexit(). Therefore, make this recover call a no-op.
201199 return nil
202200 }
203201 // Only the first call to recover returns the panic value. It also stops
204202 // the panicking sequence, hence setting panicking to false.
205- frame .Panicking = panicFalse
203+ frame .Panicking &^= panicTrue
206204 return frame .PanicValue
207205 }
208206 // Not panicking, so return a nil interface.
0 commit comments