// obj is the start of an object with mark mbits. // If it isn't already marked, mark it and enqueue into gcw. // base and off are for debugging only and could be removed. //go:nowritebarrierrec func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork, objIndex uintptr) { // obj should be start of allocation, and so must be at least pointer-aligned. if obj&(sys.PtrSize-1) != 0 { throw("greyobject: obj not pointer-aligned") } mbits := span.markBitsForIndex(objIndex) if useCheckmark { if !mbits.isMarked() { printlock() print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n") print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n") // Dump the source (base) object gcDumpObject("base", base, off) // Dump the object gcDumpObject("obj", obj, ^uintptr(0)) throw("checkmark found unmarked object") } if hbits.isCheckmarked(span.elemsize) { return } hbits.setCheckmarked(span.elemsize) if !hbits.isCheckmarked(span.elemsize) { throw("setCheckmarked and isCheckmarked disagree") } } else { if debug.gccheckmark > 0 && span.isFree(objIndex) { print("runtime: marking free object ", hex(obj), " found at *(", hex(base), "+", hex(off), ")\n") gcDumpObject("base", base, off) gcDumpObject("obj", obj, ^uintptr(0)) throw("marking free object") } // If marked we have nothing to do. if mbits.isMarked() { return } // mbits.setMarked() // Avoid extra call overhead with manual inlining. atomic.Or8(mbits.bytep, mbits.mask) // If this is a noscan object, fast-track it to black // instead of greying it. if !hbits.hasPointers(span.elemsize) { gcw.bytesMarked += uint64(span.elemsize) return } } // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but // seems like a nice optimization that can be added back in. // There needs to be time between the PREFETCH and the use. // Previously we put the obj in an 8 element buffer that is drained at a rate // to give the PREFETCH time to do its work. // Use of PREFETCHNTA might be more appropriate than PREFETCH if !gcw.putFast(obj) { gcw.put(obj) } }
func check() { var ( a int8 b uint8 c int16 d uint16 e int32 f uint32 g int64 h uint64 i, i1 float32 j, j1 float64 k, k1 unsafe.Pointer l *uint16 m [4]byte ) type x1t struct { x uint8 } type y1t struct { x1 x1t y uint8 } var x1 x1t var y1 y1t if unsafe.Sizeof(a) != 1 { throw("bad a") } if unsafe.Sizeof(b) != 1 { throw("bad b") } if unsafe.Sizeof(c) != 2 { throw("bad c") } if unsafe.Sizeof(d) != 2 { throw("bad d") } if unsafe.Sizeof(e) != 4 { throw("bad e") } if unsafe.Sizeof(f) != 4 { throw("bad f") } if unsafe.Sizeof(g) != 8 { throw("bad g") } if unsafe.Sizeof(h) != 8 { throw("bad h") } if unsafe.Sizeof(i) != 4 { throw("bad i") } if unsafe.Sizeof(j) != 8 { throw("bad j") } if unsafe.Sizeof(k) != sys.PtrSize { throw("bad k") } if unsafe.Sizeof(l) != sys.PtrSize { throw("bad l") } if unsafe.Sizeof(x1) != 1 { throw("bad unsafe.Sizeof x1") } if unsafe.Offsetof(y1.y) != 1 { throw("bad offsetof y1.y") } if unsafe.Sizeof(y1) != 2 { throw("bad unsafe.Sizeof y1") } if timediv(12345*1000000000+54321, 1000000000, &e) != 12345 || e != 54321 { throw("bad timediv") } var z uint32 z = 1 if !atomic.Cas(&z, 1, 2) { throw("cas1") } if z != 2 { throw("cas2") } z = 4 if atomic.Cas(&z, 5, 6) { throw("cas3") } if z != 4 { throw("cas4") } z = 0xffffffff if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) { throw("cas5") } if z != 0xfffffffe { throw("cas6") } k = unsafe.Pointer(uintptr(0xfedcb123)) if sys.PtrSize == 8 { k = unsafe.Pointer(uintptr(k) << 10) } if casp(&k, nil, nil) { throw("casp1") } k1 = add(k, 1) if !casp(&k, k, k1) { throw("casp2") } if k != k1 { throw("casp3") } m = [4]byte{1, 1, 1, 1} atomic.Or8(&m[1], 0xf0) if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 { throw("atomicor8") } *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0) if j == j { throw("float64nan") } if !(j != j) { throw("float64nan1") } *(*uint64)(unsafe.Pointer(&j1)) = ^uint64(1) if j == j1 { throw("float64nan2") } if !(j != j1) { throw("float64nan3") } *(*uint32)(unsafe.Pointer(&i)) = ^uint32(0) if i == i { throw("float32nan") } if i == i { throw("float32nan1") } *(*uint32)(unsafe.Pointer(&i1)) = ^uint32(1) if i == i1 { throw("float32nan2") } if i == i1 { throw("float32nan3") } testAtomic64() if _FixedStack != round2(_FixedStack) { throw("FixedStack is not power-of-2") } if !checkASM() { throw("assembly checks failed") } }
func mapiterinit(t *maptype, h *hmap, it *hiter) { // Clear pointer fields so garbage collector does not complain. it.key = nil it.value = nil it.t = nil it.h = nil it.buckets = nil it.bptr = nil it.overflow[0] = nil it.overflow[1] = nil if raceenabled && h != nil { callerpc := getcallerpc(unsafe.Pointer(&t)) racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiterinit)) } if h == nil || h.count == 0 { it.key = nil it.value = nil return } if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 { throw("hash_iter size incorrect") // see ../../cmd/internal/gc/reflect.go } it.t = t it.h = h // grab snapshot of bucket state it.B = h.B it.buckets = h.buckets if t.bucket.kind&kindNoPointers != 0 { // Allocate the current slice and remember pointers to both current and old. // This preserves all relevant overflow buckets alive even if // the table grows and/or overflow buckets are added to the table // while we are iterating. h.createOverflow() it.overflow = *h.overflow } // decide where to start r := uintptr(fastrand()) if h.B > 31-bucketCntBits { r += uintptr(fastrand()) << 31 } it.startBucket = r & (uintptr(1)<<h.B - 1) it.offset = uint8(r >> h.B & (bucketCnt - 1)) // iterator state it.bucket = it.startBucket it.wrapped = false it.bptr = nil // Remember we have an iterator. // Can run concurrently with another hash_iter_init(). if old := h.flags; old&(iterator|oldIterator) != iterator|oldIterator { atomic.Or8(&h.flags, iterator|oldIterator) } mapiternext(it) }
func check() { // This doesn't currently work for gccgo. Because escape // analysis is not turned on by default, the code below that // takes the address of local variables causes memory // allocation, but this function is called before the memory // allocator has been initialized. return var ( a int8 b uint8 c int16 d uint16 e int32 f uint32 g int64 h uint64 i, i1 float32 j, j1 float64 k, k1 unsafe.Pointer l *uint16 m [4]byte ) type x1t struct { x uint8 } type y1t struct { x1 x1t y uint8 } var x1 x1t var y1 y1t if unsafe.Sizeof(a) != 1 { throw("bad a") } if unsafe.Sizeof(b) != 1 { throw("bad b") } if unsafe.Sizeof(c) != 2 { throw("bad c") } if unsafe.Sizeof(d) != 2 { throw("bad d") } if unsafe.Sizeof(e) != 4 { throw("bad e") } if unsafe.Sizeof(f) != 4 { throw("bad f") } if unsafe.Sizeof(g) != 8 { throw("bad g") } if unsafe.Sizeof(h) != 8 { throw("bad h") } if unsafe.Sizeof(i) != 4 { throw("bad i") } if unsafe.Sizeof(j) != 8 { throw("bad j") } if unsafe.Sizeof(k) != sys.PtrSize { throw("bad k") } if unsafe.Sizeof(l) != sys.PtrSize { throw("bad l") } if unsafe.Sizeof(x1) != 1 { throw("bad unsafe.Sizeof x1") } if unsafe.Offsetof(y1.y) != 1 { throw("bad offsetof y1.y") } if unsafe.Sizeof(y1) != 2 { throw("bad unsafe.Sizeof y1") } if timediv(12345*1000000000+54321, 1000000000, &e) != 12345 || e != 54321 { throw("bad timediv") } var z uint32 z = 1 if !atomic.Cas(&z, 1, 2) { throw("cas1") } if z != 2 { throw("cas2") } z = 4 if atomic.Cas(&z, 5, 6) { throw("cas3") } if z != 4 { throw("cas4") } z = 0xffffffff if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) { throw("cas5") } if z != 0xfffffffe { throw("cas6") } k = unsafe.Pointer(uintptr(0xfedcb123)) if sys.PtrSize == 8 { k = unsafe.Pointer(uintptr(k) << 10) } if casp(&k, nil, nil) { throw("casp1") } k1 = add(k, 1) if !casp(&k, k, k1) { throw("casp2") } if k != k1 { throw("casp3") } m = [4]byte{1, 1, 1, 1} atomic.Or8(&m[1], 0xf0) if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 { throw("atomicor8") } *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0) if j == j { throw("float64nan") } if !(j != j) { throw("float64nan1") } *(*uint64)(unsafe.Pointer(&j1)) = ^uint64(1) if j == j1 { throw("float64nan2") } if !(j != j1) { throw("float64nan3") } *(*uint32)(unsafe.Pointer(&i)) = ^uint32(0) if i == i { throw("float32nan") } if i == i { throw("float32nan1") } *(*uint32)(unsafe.Pointer(&i1)) = ^uint32(1) if i == i1 { throw("float32nan2") } if i == i1 { throw("float32nan3") } testAtomic64() // if _FixedStack != round2(_FixedStack) { // throw("FixedStack is not power-of-2") // } if !checkASM() { throw("assembly checks failed") } }