]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix tiny allocator
authorMatthew Dempsky <mdempsky@google.com>
Mon, 26 Oct 2015 19:38:47 +0000 (12:38 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 26 Oct 2015 21:14:15 +0000 (21:14 +0000)
When a new tiny block is allocated because we're allocating an object
that won't fit into the current block, mallocgc saves the new block if
it has more space leftover than the old block.  However, the logic for
this was subtly broken in golang.org/cl/2814, resulting in never
saving (or consequently reusing) a tiny block.

Change-Id: Ib5f6769451fb82877ddeefe75dfe79ed4a04fd40
Reviewed-on: https://go-review.googlesource.com/16330
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/malloc.go
src/runtime/malloc_test.go

index 564e2296a2ae3395f9c62878aeec4a8d31025adf..ae28a3c31908f9b92f66375608a7743a1ff98ed5 100644 (file)
@@ -615,7 +615,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
                        (*[2]uint64)(x)[1] = 0
                        // See if we need to replace the existing tiny block with the new one
                        // based on amount of remaining free space.
-                       if size < c.tinyoffset {
+                       if size < c.tinyoffset || c.tiny == nil {
                                c.tiny = x
                                c.tinyoffset = size
                        }
index f0e73baea59385a6eea1536eeb052aff31b36a13..b8278bb4bcaf6b8d43f6b4fd4d7cff2cb4d907db 100644 (file)
@@ -82,6 +82,23 @@ func TestStringConcatenationAllocs(t *testing.T) {
        }
 }
 
+func TestTinyAlloc(t *testing.T) {
+       const N = 16
+       var v [N]unsafe.Pointer
+       for i := range v {
+               v[i] = unsafe.Pointer(new(byte))
+       }
+
+       chunks := make(map[uintptr]bool, N)
+       for _, p := range v {
+               chunks[uintptr(p)&^7] = true
+       }
+
+       if len(chunks) == N {
+               t.Fatal("no bytes allocated within the same 8-byte chunk")
+       }
+}
+
 var mallocSink uintptr
 
 func BenchmarkMalloc8(b *testing.B) {