+++ /dev/null
-// run
-// +build !nacl,!js
-
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Runs a build -S to capture the assembly language
-// output, checks that the line numbers associated with
-// the stream of instructions do not change "too much".
-// The changes that fixes this (that reduces the amount
-// of change) does so by treating register spill, reload,
-// copy, and rematerializations as being "unimportant" and
-// just assigns them the line numbers of whatever "real"
-// instructions preceded them.
-
-// nacl is excluded because this runs a compiler.
-
-package main
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "os"
- "os/exec"
- "strconv"
- "strings"
-)
-
-// updateEnv modifies env to ensure that key=val
-func updateEnv(env *[]string, key, val string) {
- if val != "" {
- var found bool
- key = key + "="
- for i, kv := range *env {
- if strings.HasPrefix(kv, key) {
- (*env)[i] = key + val
- found = true
- break
- }
- }
- if !found {
- *env = append(*env, key+val)
- }
- }
-}
-
-func main() {
- testarch := os.Getenv("TESTARCH") // Targets other platform in test compilation.
- debug := os.Getenv("TESTDEBUG") != "" // Output the relevant assembly language.
-
- cmd := exec.Command("go", "tool", "compile", "-S", "fixedbugs/issue18902b.go")
- var buf bytes.Buffer
- cmd.Stdout = &buf
- cmd.Stderr = &buf
- cmd.Env = os.Environ()
-
- if testarch != "" {
- updateEnv(&cmd.Env, "GOARCH", testarch)
- updateEnv(&cmd.Env, "GOOS", "linux") // Simplify multi-arch testing
- }
-
- err := cmd.Run()
- if err != nil {
- fmt.Printf("%s\n%s", err, buf.Bytes())
- return
- }
- begin := "\"\".(*gcSortBuf).flush" // Text at beginning of relevant dissassembly.
- s := buf.String()
- i := strings.Index(s, begin)
- if i < 0 {
- fmt.Printf("Failed to find expected symbol %s in output\n%s\n", begin, s)
- return
- }
- s = s[i:]
- r := strings.NewReader(s)
- scanner := bufio.NewScanner(r)
- first := true // The first line after the begin text will be skipped
- beforeLineNumber := "issue18902b.go:" // Text preceding line number in each line.
- lbln := len(beforeLineNumber)
-
- var scannedCount, changes, sumdiffs float64
-
- prevVal := 0
- for scanner.Scan() {
- line := scanner.Text()
- if first {
- first = false
- continue
- }
- i = strings.Index(line, beforeLineNumber)
- if i < 0 {
- // Done reading lines
- const minLines = 150
- if scannedCount <= minLines { // When test was written, 251 lines observed on amd64; arm64 now obtains 184
- fmt.Printf("Scanned only %d lines, was expecting more than %d\n", int(scannedCount), minLines)
- return
- }
- // Note: when test was written, before changes=92, after=50 (was 62 w/o rematerialization NoXPos in *Value.copyInto())
- // and before sumdiffs=784, after=180 (was 446 w/o rematerialization NoXPos in *Value.copyInto())
- // Set the dividing line between pass and fail at the midpoint.
- // Normalize against instruction count in case we unroll loops, etc.
- if changes/scannedCount >= (50+92)/(2*scannedCount) || sumdiffs/scannedCount >= (180+784)/(2*scannedCount) {
- fmt.Printf("Line numbers change too much, # of changes=%.f, sumdiffs=%.f, # of instructions=%.f\n", changes, sumdiffs, scannedCount)
- }
- return
- }
- scannedCount++
- i += lbln
- lineVal, err := strconv.Atoi(line[i : i+3])
- if err != nil {
- fmt.Printf("Expected 3-digit line number after %s in %s\n", beforeLineNumber, line)
- }
- if prevVal == 0 {
- prevVal = lineVal
- }
- diff := lineVal - prevVal
- if diff < 0 {
- diff = -diff
- }
- if diff != 0 {
- changes++
- sumdiffs += float64(diff)
- }
- // If things change too much, set environment variable TESTDEBUG to help figure out what's up.
- // The "before" behavior can be recreated in DebugFriendlySetPosFrom (currently in gc/ssa.go)
- // by inserting unconditional
- // s.SetPos(v.Pos)
- // at the top of the function.
-
- if debug {
- fmt.Printf("%d %.f %.f %s\n", lineVal, changes, sumdiffs, line)
- }
- prevVal = lineVal
- }
- if err := scanner.Err(); err != nil {
- fmt.Println("Reading standard input:", err)
- return
- }
-}
+++ /dev/null
-// skip
-
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package foo
-
-import (
- "unsafe"
-)
-
-type gcMaxTreeNodeVal uint64
-
-var work struct {
- full uint64 // lock-free list of full blocks workbuf
- empty uint64 // lock-free list of empty blocks workbuf
- pad0 [64]uint8 // prevents false-sharing between full/empty and nproc/nwait
- bytesMarked uint64
- markrootNext uint32 // next markroot job
- markrootJobs uint32 // number of markroot jobs
- nproc uint32
- tstart int64
- nwait uint32
- ndone uint32
-}
-
-type gcShardQueue1 struct {
- partial *workbuf
- full *workbuf
- n uintptr
- maxTree gcMaxTreeNodeVal
-}
-type gcShardQueue struct {
- gcShardQueue1
- pad [64 - unsafe.Sizeof(gcShardQueue1{})]byte
-}
-
-const gcSortBufPointers = (64 << 10) / 8
-
-type gcSortBuf struct {
- buf *gcSortArray
- tmp *gcSortArray
- n uintptr
-}
-
-//go:notinheap
-type gcSortArray [gcSortBufPointers]uintptr
-
-const (
- _DebugGC = 0
- _ConcurrentSweep = true
- _FinBlockSize = 4 * 1024
- sweepMinHeapDistance = 1024 * 1024
- gcShardShift = 2 + 20
- gcShardBytes = 1 << gcShardShift
-)
-
-//go:notinheap
-type mheap struct {
- shardQueues []gcShardQueue
- _ uint32 // align uint64 fields on 32-bit for atomics
- pagesInUse uint64 // pages of spans in stats _MSpanInUse; R/W with mheap.lock
- spanBytesAlloc uint64 // bytes of spans allocated this cycle; updated atomically
- pagesSwept uint64 // pages swept this cycle; updated atomically
- sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without
- largefree uint64 // bytes freed for large objects (>maxsmallsize)
- nlargefree uint64 // number of frees for large objects (>maxsmallsize)
- nsmallfree [67]uint64 // number of frees for small objects (<=maxsmallsize)
- bitmap uintptr // Points to one byte past the end of the bitmap
- bitmap_mapped uintptr
- arena_start uintptr
- arena_used uintptr // always mHeap_Map{Bits,Spans} before updating
- arena_end uintptr
- arena_reserved bool
-}
-
-var mheap_ mheap
-
-type lfnode struct {
- next uint64
- pushcnt uintptr
-}
-type workbufhdr struct {
- node lfnode // must be first
- next *workbuf
- nobj int
-}
-
-//go:notinheap
-type workbuf struct {
- workbufhdr
- obj [(2048 - unsafe.Sizeof(workbufhdr{})) / 8]uintptr
-}
-
-//go:noinline
-func (b *workbuf) checkempty() {
- if b.nobj != 0 {
- b.nobj = 0
- }
-}
-func putempty(b *workbuf) {
- b.checkempty()
- lfstackpush(&work.empty, &b.node)
-}
-
-//go:noinline
-func lfstackpush(head *uint64, node *lfnode) {
-}
-
-//go:noinline
-func (q *gcShardQueue) add(qidx uintptr, ptrs []uintptr, spare *workbuf) *workbuf {
- return spare
-}
-
-func (b *gcSortBuf) flush() {
- if b.n == 0 {
- return
- }
- const sortDigitBits = 11
- buf, tmp := b.buf[:b.n], b.tmp[:b.n]
- moreBits := true
- for shift := uint(gcShardShift); moreBits; shift += sortDigitBits {
- const k = 1 << sortDigitBits
- var pos [k]uint16
- nshift := shift + sortDigitBits
- nbits := buf[0] >> nshift
- moreBits = false
- for _, v := range buf {
- pos[(v>>shift)%k]++
- moreBits = moreBits || v>>nshift != nbits
- }
- var sum uint16
- for i, count := range &pos {
- pos[i] = sum
- sum += count
- }
- for _, v := range buf {
- digit := (v >> shift) % k
- tmp[pos[digit]] = v
- pos[digit]++
- }
- buf, tmp = tmp, buf
- }
- start := mheap_.arena_start
- i0 := 0
- shard0 := (buf[0] - start) / gcShardBytes
- var spare *workbuf
- for i, p := range buf {
- shard := (p - start) / gcShardBytes
- if shard != shard0 {
- spare = mheap_.shardQueues[shard0].add(shard0, buf[i0:i], spare)
- i0, shard0 = i, shard
- }
- }
- spare = mheap_.shardQueues[shard0].add(shard0, buf[i0:], spare)
- b.n = 0
- if spare != nil {
- putempty(spare)
- }
-}