@@ -38,17 +38,15 @@ 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+ panicTrue panicState = 1 << iota
5250 panicGoexit
5351)
5452
@@ -66,10 +64,10 @@ func panicOrGoexit(message interface{}, panicking panicState) {
6664 if supportsRecover () && ! interrupt .In () {
6765 frame := (* deferFrame )(task .Current ().DeferFrame )
6866 if frame != nil {
69- if panicking == panicGoexit {
70- frame .Goexit = true
71- }
7267 frame .PanicValue = message
68+ if panicking & panicTrue != 0 {
69+ panicking |= frame .Panicking & panicGoexit
70+ }
7371 frame .Panicking = panicking
7472 tinygo_longjmp (frame )
7573 // unreachable
@@ -103,7 +101,7 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
103101 // Use the normal panic mechanism so that this runtime error
104102 // can be recovered with recover().
105103 frame .PanicValue = plainError (msg )
106- frame .Panicking = panicTrue
104+ frame .Panicking = panicTrue | ( frame . Panicking & panicGoexit )
107105 tinygo_longjmp (frame )
108106 // unreachable
109107 }
@@ -140,9 +138,8 @@ func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
140138 currentTask := task .Current ()
141139 frame .Previous = (* deferFrame )(currentTask .DeferFrame )
142140 frame .JumpSP = jumpSP
143- frame .Panicking = panicFalse
141+ frame .Panicking = 0
144142 frame .DeferPtr = nil
145- frame .Goexit = false
146143 currentTask .DeferFrame = unsafe .Pointer (frame )
147144}
148145
@@ -154,12 +151,12 @@ func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
154151//go:nobounds
155152func destroyDeferFrame (frame * deferFrame ) {
156153 task .Current ().DeferFrame = unsafe .Pointer (frame .Previous )
157- if frame .Panicking != panicFalse {
154+ if frame .Panicking & panicTrue != 0 {
158155 // We're still panicking!
159156 // Re-raise the panic now.
160- panicOrGoexit (frame .PanicValue , frame . Panicking )
157+ panicOrGoexit (frame .PanicValue , panicTrue )
161158 }
162- if frame .Goexit {
159+ if frame .Panicking & panicGoexit != 0 {
163160 // A deferred function panicked during Goexit, and that panic was
164161 // recovered. Continue the original Goexit instead of returning.
165162 panicOrGoexit (nil , panicGoexit )
@@ -194,15 +191,15 @@ func _recover(useParentFrame bool) interface{} {
194191 // already), but instead from the previous frame.
195192 frame = frame .Previous
196193 }
197- if frame != nil && frame .Panicking != panicFalse {
198- if frame .Panicking == panicGoexit {
194+ if frame != nil && frame .Panicking != 0 {
195+ if frame .Panicking & panicTrue == 0 {
199196 // Special value that indicates we're exiting the goroutine using
200197 // Goexit(). Therefore, make this recover call a no-op.
201198 return nil
202199 }
203200 // Only the first call to recover returns the panic value. It also stops
204201 // the panicking sequence, hence setting panicking to false.
205- frame .Panicking = panicFalse
202+ frame .Panicking &^= panicTrue
206203 return frame .PanicValue
207204 }
208205 // Not panicking, so return a nil interface.
0 commit comments