]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: unify fetching of locals and arguments maps
authorAustin Clements <austin@google.com>
Fri, 27 Apr 2018 01:20:41 +0000 (21:20 -0400)
committerAustin Clements <austin@google.com>
Mon, 14 May 2018 00:20:16 +0000 (00:20 +0000)
Currently we have two nearly identical copies of the code that fetches
the locals and arguments liveness maps for a frame, plus a third
that's a poor knock-off. Unify these all into a single function.

Change-Id: Ibce7926a0b0e3d23182112da4e25df899579a585
Reviewed-on: https://go-review.googlesource.com/109698
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/mbitmap.go
src/runtime/mgcmark.go
src/runtime/stack.go

index 5c7d812403f882b393564a9199c4b2646eaf06a2..513e6b9eed6bdc731a6d291e6b2978dcfad4eb27 100644 (file)
@@ -1999,30 +1999,16 @@ func getgcmask(ep interface{}) (mask []byte) {
                _g_ := getg()
                gentraceback(_g_.m.curg.sched.pc, _g_.m.curg.sched.sp, 0, _g_.m.curg, 0, nil, 1000, getgcmaskcb, noescape(unsafe.Pointer(&frame)), 0)
                if frame.fn.valid() {
-                       f := frame.fn
-                       targetpc := frame.continpc
-                       if targetpc == 0 {
+                       locals, _ := getStackMap(&frame, nil, false)
+                       if locals.n == 0 {
                                return
                        }
-                       pcdata := int32(-1) // Use the entry map at function entry
-                       if targetpc != f.entry {
-                               targetpc--
-                               pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
-                       }
-                       if pcdata == -1 {
-                               return
-                       }
-                       stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
-                       if stkmap == nil || stkmap.n <= 0 {
-                               return
-                       }
-                       bv := stackmapdata(stkmap, pcdata)
-                       size := uintptr(bv.n) * sys.PtrSize
+                       size := uintptr(locals.n) * sys.PtrSize
                        n := (*ptrtype)(unsafe.Pointer(t)).elem.size
                        mask = make([]byte, n/sys.PtrSize)
                        for i := uintptr(0); i < n; i += sys.PtrSize {
                                off := (uintptr(p) + i - frame.varp + size) / sys.PtrSize
-                               mask[i/sys.PtrSize] = bv.ptrbit(off)
+                               mask[i/sys.PtrSize] = locals.ptrbit(off)
                        }
                }
                return
index 12a232a005e516787bcb14681fe47cb6f1d13491..e8cfdce4fc1b30ffaf06cb5f8a7b312facd1503f 100644 (file)
@@ -791,82 +791,21 @@ func scanstack(gp *g, gcw *gcWork) {
 // Scan a stack frame: local variables and function arguments/results.
 //go:nowritebarrier
 func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
-
-       f := frame.fn
-       targetpc := frame.continpc
-       if targetpc == 0 {
-               // Frame is dead.
-               return
-       }
-       if _DebugGC > 1 {
-               print("scanframe ", funcname(f), "\n")
-       }
-       pcdata := int32(-1)
-       if targetpc != f.entry {
-               // Back up to the CALL. If we're at the function entry
-               // point, we want to use the entry map (-1), even if
-               // the first instruction of the function changes the
-               // stack map.
-               targetpc--
-               pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
-       }
-       if pcdata == -1 {
-               // We do not have a valid pcdata value but there might be a
-               // stackmap for this function. It is likely that we are looking
-               // at the function prologue, assume so and hope for the best.
-               pcdata = 0
+       if _DebugGC > 1 && frame.continpc != 0 {
+               print("scanframe ", funcname(frame.fn), "\n")
        }
 
-       // Scan local variables if stack frame has been allocated.
-       size := frame.varp - frame.sp
-       var minsize uintptr
-       switch sys.ArchFamily {
-       case sys.ARM64:
-               minsize = sys.SpAlign
-       default:
-               minsize = sys.MinFrameSize
-       }
-       if size > minsize {
-               stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
-               if stkmap == nil || stkmap.n <= 0 {
-                       print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
-                       throw("missing stackmap")
-               }
+       locals, args := getStackMap(frame, cache, false)
 
-               // Locals bitmap information, scan just the pointers in locals.
-               if pcdata < 0 || pcdata >= stkmap.n {
-                       // don't know where we are
-                       print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-                       throw("scanframe: bad symbol table")
-               }
-               if stkmap.nbit > 0 {
-                       bv := stackmapdata(stkmap, pcdata)
-                       size = uintptr(bv.n) * sys.PtrSize
-                       scanblock(frame.varp-size, size, bv.bytedata, gcw)
-               }
+       // Scan local variables if stack frame has been allocated.
+       if locals.n > 0 {
+               size := uintptr(locals.n) * sys.PtrSize
+               scanblock(frame.varp-size, size, locals.bytedata, gcw)
        }
 
        // Scan arguments.
-       if frame.arglen > 0 {
-               var bv bitvector
-               if frame.argmap != nil {
-                       bv = *frame.argmap
-               } else {
-                       stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
-                       if stkmap == nil || stkmap.n <= 0 {
-                               print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
-                               throw("missing stackmap")
-                       }
-                       if pcdata < 0 || pcdata >= stkmap.n {
-                               // don't know where we are
-                               print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-                               throw("scanframe: bad symbol table")
-                       }
-                       bv = stackmapdata(stkmap, pcdata)
-               }
-               if bv.n > 0 {
-                       scanblock(frame.argp, uintptr(bv.n)*sys.PtrSize, bv.bytedata, gcw)
-               }
+       if args.n > 0 {
+               scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw)
        }
 }
 
index 0813497ca715c8f4c6738925b3b59874350fe5cd..cbe49355a9eaaf57d4c069a5ec8db9377c5b5901 100644 (file)
@@ -606,8 +606,7 @@ func adjustpointers(scanp unsafe.Pointer, bv *bitvector, adjinfo *adjustinfo, f
 // Note: the argument/return area is adjusted by the callee.
 func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
        adjinfo := (*adjustinfo)(arg)
-       targetpc := frame.continpc
-       if targetpc == 0 {
+       if frame.continpc == 0 {
                // Frame is dead.
                return true
        }
@@ -621,47 +620,13 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
                // have full GC info for it (because it is written in asm).
                return true
        }
-       pcdata := int32(-1) // Use the entry map at function entry
-       if targetpc != f.entry {
-               targetpc--
-               pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
-       }
-       if pcdata == -1 {
-               pcdata = 0 // in prologue
-       }
+
+       locals, args := getStackMap(frame, &adjinfo.cache, true)
 
        // Adjust local variables if stack frame has been allocated.
-       size := frame.varp - frame.sp
-       var minsize uintptr
-       switch sys.ArchFamily {
-       case sys.ARM64:
-               minsize = sys.SpAlign
-       default:
-               minsize = sys.MinFrameSize
-       }
-       if size > minsize {
-               stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
-               if stackmap == nil || stackmap.n <= 0 {
-                       print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
-                       throw("missing stackmap")
-               }
-               // If nbit == 0, there's no work to do.
-               if stackmap.nbit > 0 {
-                       // Locals bitmap information, scan just the pointers in locals.
-                       if pcdata < 0 || pcdata >= stackmap.n {
-                               // don't know where we are
-                               print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-                               throw("bad symbol table")
-                       }
-                       bv := stackmapdata(stackmap, pcdata)
-                       size = uintptr(bv.n) * sys.PtrSize
-                       if stackDebug >= 3 {
-                               print("      locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n")
-                       }
-                       adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
-               } else if stackDebug >= 3 {
-                       print("      no locals to adjust\n")
-               }
+       if locals.n > 0 {
+               size := uintptr(locals.n) * sys.PtrSize
+               adjustpointers(unsafe.Pointer(frame.varp-size), &locals, adjinfo, f)
        }
 
        // Adjust saved base pointer if there is one.
@@ -688,29 +653,11 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
        }
 
        // Adjust arguments.
-       if frame.arglen > 0 {
-               var bv bitvector
-               if frame.argmap != nil {
-                       bv = *frame.argmap
-               } else {
-                       stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
-                       if stackmap == nil || stackmap.n <= 0 {
-                               print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", frame.arglen, "\n")
-                               throw("missing stackmap")
-                       }
-                       if pcdata < 0 || pcdata >= stackmap.n {
-                               // don't know where we are
-                               print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-                               throw("bad symbol table")
-                       }
-                       bv = stackmapdata(stackmap, pcdata)
-               }
+       if args.n > 0 {
                if stackDebug >= 3 {
                        print("      args\n")
                }
-               if bv.n > 0 {
-                       adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, funcInfo{})
-               }
+               adjustpointers(unsafe.Pointer(frame.argp), &args, adjinfo, funcInfo{})
        }
        return true
 }
@@ -1186,6 +1133,86 @@ func freeStackSpans() {
        unlock(&stackLarge.lock)
 }
 
+// getStackMap returns the locals and arguments live pointer maps for
+// frame.
+func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args bitvector) {
+       targetpc := frame.continpc
+       if targetpc == 0 {
+               // Frame is dead. Return empty bitvectors.
+               return
+       }
+
+       f := frame.fn
+       pcdata := int32(-1)
+       if targetpc != f.entry {
+               // Back up to the CALL. If we're at the function entry
+               // point, we want to use the entry map (-1), even if
+               // the first instruction of the function changes the
+               // stack map.
+               targetpc--
+               pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
+       }
+       if pcdata == -1 {
+               // We do not have a valid pcdata value but there might be a
+               // stackmap for this function. It is likely that we are looking
+               // at the function prologue, assume so and hope for the best.
+               pcdata = 0
+       }
+
+       // Local variables.
+       size := frame.varp - frame.sp
+       var minsize uintptr
+       switch sys.ArchFamily {
+       case sys.ARM64:
+               minsize = sys.SpAlign
+       default:
+               minsize = sys.MinFrameSize
+       }
+       if size > minsize {
+               stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+               if stackmap == nil || stackmap.n <= 0 {
+                       print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
+                       throw("missing stackmap")
+               }
+               // If nbit == 0, there's no work to do.
+               if stackmap.nbit > 0 {
+                       if pcdata < 0 || pcdata >= stackmap.n {
+                               // don't know where we are
+                               print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
+                               throw("bad symbol table")
+                       }
+                       locals = stackmapdata(stackmap, pcdata)
+                       if stackDebug >= 3 && debug {
+                               print("      locals ", pcdata, "/", stackmap.n, " ", locals.n, " words ", locals.bytedata, "\n")
+                       }
+               } else if stackDebug >= 3 && debug {
+                       print("      no locals to adjust\n")
+               }
+       }
+
+       // Arguments.
+       if frame.arglen > 0 {
+               if frame.argmap != nil {
+                       args = *frame.argmap
+               } else {
+                       stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
+                       if stackmap == nil || stackmap.n <= 0 {
+                               print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
+                               throw("missing stackmap")
+                       }
+                       if pcdata < 0 || pcdata >= stackmap.n {
+                               // don't know where we are
+                               print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
+                               throw("bad symbol table")
+                       }
+                       if stackmap.nbit > 0 {
+                               args = stackmapdata(stackmap, pcdata)
+                       }
+               }
+       }
+       return
+}
+
 //go:nosplit
 func morestackc() {
        throw("attempt to execute system stack code on user stack")