internal/gocore: fix pointer locations for small objects in green tea

The tests are currently broken when GOEXPERIMENT=greenteagc because that
shifted where the pointer/scalar bits are located for small objects a
little bit. This change modifies gocore to look in the right place and
detect if GOEXPERIMENT=greenteagc is enabled (and if we're using Green
Tea in general, if/when it becomes the default).

This was not caught by the builders because we don't have an x/debug
builder that sets the GOEXPERIMENT.

Change-Id: I746ce601ebc12738920616889200f23642f7280f
Reviewed-on: https://go-review.googlesource.com/c/debug/+/699975
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
Commit-Queue: Nicolas Hillegeer <aktau@google.com>
diff --git a/internal/gocore/process.go b/internal/gocore/process.go
index e01480e..03606b9 100644
--- a/internal/gocore/process.go
+++ b/internal/gocore/process.go
@@ -362,6 +362,9 @@
 	spanManual := uint8(p.rtConsts.get("runtime.mSpanManual"))
 	spanDead := uint8(p.rtConsts.get("runtime.mSpanDead"))
 
+	// Green Tea GC.
+	spanInlineMarkBitsTyp := p.rtTypeByName["runtime.spanInlineMarkBits"]
+
 	// Malloc header constants (go 1.22+)
 	minSizeForMallocHeader := int64(p.rtConsts.get("runtime.minSizeForMallocHeader"))
 	mallocHeaderSize := int64(p.rtConsts.get("runtime.mallocHeaderSize"))
@@ -474,7 +477,16 @@
 			if elemSize <= minSizeForMallocHeader {
 				// Heap bits in span.
 				bitmapSize := spanSize / int64(heap.ptrSize) / 8
-				bitmapAddr := min.Add(spanSize - bitmapSize)
+				markBitsSize := int64(0)
+				if spanInlineMarkBitsTyp != nil && elemSize >= 16 {
+					// Green Tea GC only: we store the mark bits inline
+					// in the span for small objects >= 16 bytes in size.
+					markBitsSize = spanInlineMarkBitsTyp.Size
+				}
+				objectsSize := spanSize - (bitmapSize + markBitsSize)
+
+				// Span layout: [objects][heapbits][markbits] (mark bits with Green Tea GC only)
+				bitmapAddr := min.Add(objectsSize)
 				for i := int64(0); i < bitmapSize; i++ {
 					bits := p.proc.ReadUint8(bitmapAddr.Add(int64(i)))
 					for j := int64(0); j < 8; j++ {