LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Garbage collector. | 5 // Garbage collector. |
6 | 6 |
7 #include "runtime.h" | 7 #include "runtime.h" |
8 #include "arch_GOARCH.h" | 8 #include "arch_GOARCH.h" |
9 #include "malloc.h" | 9 #include "malloc.h" |
10 #include "stack.h" | 10 #include "stack.h" |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 | 164 |
165 enum { | 165 enum { |
166 GC_DEFAULT_PTR = GC_NUM_INSTR, | 166 GC_DEFAULT_PTR = GC_NUM_INSTR, |
167 GC_MAP_NEXT, | 167 GC_MAP_NEXT, |
168 GC_CHAN, | 168 GC_CHAN, |
169 | 169 |
170 GC_NUM_INSTR2 | 170 GC_NUM_INSTR2 |
171 }; | 171 }; |
172 | 172 |
173 static struct { | 173 static struct { |
174 » uint64 ptr_sum; | 174 » struct { |
175 » uint64 ptr_cnt; | 175 » » uint64 sum; |
| 176 » » uint64 cnt; |
| 177 » } ptr; |
176 uint64 nbytes; | 178 uint64 nbytes; |
177 » uint64 nobj_sum; | 179 » struct { |
178 » uint64 nobj_cnt; | 180 » » uint64 sum; |
179 » uint64 nobj_notype; | 181 » » uint64 cnt; |
180 » uint64 nobj_typelookups_ok; | 182 » » uint64 notype; |
181 » uint64 rescans; | 183 » » uint64 typelookup; |
182 » uint64 rescan_nbytes; | 184 » } obj; |
| 185 » uint64 rescan; |
| 186 » uint64 rescanbytes; |
183 uint64 instr[GC_NUM_INSTR2]; | 187 uint64 instr[GC_NUM_INSTR2]; |
184 uint64 putempty; | 188 uint64 putempty; |
185 uint64 getfull; | 189 uint64 getfull; |
186 } gcstats; | 190 } gcstats; |
187 | 191 |
188 // markonly marks an object. It returns true if the object | 192 // markonly marks an object. It returns true if the object |
189 // has been marked by this function, false otherwise. | 193 // has been marked by this function, false otherwise. |
190 // This function isn't thread-safe and doesn't append the object to any buffer. | 194 // This function isn't thread-safe and doesn't append the object to any buffer. |
191 static bool | 195 static bool |
192 markonly(void *obj) | 196 markonly(void *obj) |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 331 |
328 wp = *_wp; | 332 wp = *_wp; |
329 wbuf = *_wbuf; | 333 wbuf = *_wbuf; |
330 nobj = *_nobj; | 334 nobj = *_nobj; |
331 | 335 |
332 ptrbuf_end = *ptrbufpos; | 336 ptrbuf_end = *ptrbufpos; |
333 n = ptrbuf_end - ptrbuf; | 337 n = ptrbuf_end - ptrbuf; |
334 *ptrbufpos = ptrbuf; | 338 *ptrbufpos = ptrbuf; |
335 | 339 |
336 if(CollectStats) { | 340 if(CollectStats) { |
337 » » runtime·xadd64(&gcstats.ptr_sum, n); | 341 » » runtime·xadd64(&gcstats.ptr.sum, n); |
338 » » runtime·xadd64(&gcstats.ptr_cnt, 1); | 342 » » runtime·xadd64(&gcstats.ptr.cnt, 1); |
339 } | 343 } |
340 | 344 |
341 // If buffer is nearly full, get a new one. | 345 // If buffer is nearly full, get a new one. |
342 if(wbuf == nil || nobj+n >= nelem(wbuf->obj)) { | 346 if(wbuf == nil || nobj+n >= nelem(wbuf->obj)) { |
343 if(wbuf != nil) | 347 if(wbuf != nil) |
344 wbuf->nobj = nobj; | 348 wbuf->nobj = nobj; |
345 wbuf = getempty(wbuf); | 349 wbuf = getempty(wbuf); |
346 wp = wbuf->obj; | 350 wp = wbuf->obj; |
347 nobj = 0; | 351 nobj = 0; |
348 | 352 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 | 643 |
640 for(;;) { | 644 for(;;) { |
641 // Each iteration scans the block b of length n, queueing pointe
rs in | 645 // Each iteration scans the block b of length n, queueing pointe
rs in |
642 // the work buffer. | 646 // the work buffer. |
643 if(Debug > 1) { | 647 if(Debug > 1) { |
644 runtime·printf("scanblock %p %D\n", b, (int64)n); | 648 runtime·printf("scanblock %p %D\n", b, (int64)n); |
645 } | 649 } |
646 | 650 |
647 if(CollectStats) { | 651 if(CollectStats) { |
648 runtime·xadd64(&gcstats.nbytes, n); | 652 runtime·xadd64(&gcstats.nbytes, n); |
649 » » » runtime·xadd64(&gcstats.nobj_sum, nobj); | 653 » » » runtime·xadd64(&gcstats.obj.sum, nobj); |
650 » » » runtime·xadd64(&gcstats.nobj_cnt, 1); | 654 » » » runtime·xadd64(&gcstats.obj.cnt, 1); |
651 } | 655 } |
652 | 656 |
653 if(ti != 0) { | 657 if(ti != 0) { |
654 pc = (uintptr*)(ti & ~(uintptr)PC_BITS); | 658 pc = (uintptr*)(ti & ~(uintptr)PC_BITS); |
655 precise_type = (ti & PRECISE); | 659 precise_type = (ti & PRECISE); |
656 stack_top.elemsize = pc[0]; | 660 stack_top.elemsize = pc[0]; |
657 if(!precise_type) | 661 if(!precise_type) |
658 nominal_size = pc[0]; | 662 nominal_size = pc[0]; |
659 if(ti & LOOP) { | 663 if(ti & LOOP) { |
660 stack_top.count = 0; // 0 means an infinite n
umber of iterations | 664 stack_top.count = 0; // 0 means an infinite n
umber of iterations |
661 stack_top.loop_or_ret = pc+1; | 665 stack_top.loop_or_ret = pc+1; |
662 } else { | 666 } else { |
663 stack_top.count = 1; | 667 stack_top.count = 1; |
664 } | 668 } |
665 } else if(UseSpanType) { | 669 } else if(UseSpanType) { |
666 if(CollectStats) | 670 if(CollectStats) |
667 » » » » runtime·xadd64(&gcstats.nobj_notype, 1); | 671 » » » » runtime·xadd64(&gcstats.obj.notype, 1); |
668 | 672 |
669 type = runtime·gettype(b); | 673 type = runtime·gettype(b); |
670 if(type != 0) { | 674 if(type != 0) { |
671 if(CollectStats) | 675 if(CollectStats) |
672 » » » » » runtime·xadd64(&gcstats.nobj_typelookups
_ok, 1); | 676 » » » » » runtime·xadd64(&gcstats.obj.typelookup,
1); |
673 | 677 |
674 t = (Type*)(type & ~(uintptr)(PtrSize-1)); | 678 t = (Type*)(type & ~(uintptr)(PtrSize-1)); |
675 switch(type & (PtrSize-1)) { | 679 switch(type & (PtrSize-1)) { |
676 case TypeInfo_SingleObject: | 680 case TypeInfo_SingleObject: |
677 pc = (uintptr*)t->gc; | 681 pc = (uintptr*)t->gc; |
678 precise_type = true; // type informatio
n about 'b' is precise | 682 precise_type = true; // type informatio
n about 'b' is precise |
679 stack_top.count = 1; | 683 stack_top.count = 1; |
680 stack_top.elemsize = pc[0]; | 684 stack_top.elemsize = pc[0]; |
681 break; | 685 break; |
682 case TypeInfo_Array: | 686 case TypeInfo_Array: |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 } | 842 } |
839 i = (uintptr)b + nominal_size; | 843 i = (uintptr)b + nominal_size; |
840 } | 844 } |
841 if(!precise_type) { | 845 if(!precise_type) { |
842 // Quickly scan [b+i,b+n) for possible pointers. | 846 // Quickly scan [b+i,b+n) for possible pointers. |
843 for(; i<=end_b; i+=PtrSize) { | 847 for(; i<=end_b; i+=PtrSize) { |
844 if(*(byte**)i != nil) { | 848 if(*(byte**)i != nil) { |
845 // Found a value that may be a p
ointer. | 849 // Found a value that may be a p
ointer. |
846 // Do a rescan of the entire blo
ck. | 850 // Do a rescan of the entire blo
ck. |
847 enqueue((Obj){b, n, 0}, &wbuf, &
wp, &nobj); | 851 enqueue((Obj){b, n, 0}, &wbuf, &
wp, &nobj); |
| 852 if(CollectStats) { |
| 853 runtime·xadd64(&gcstats.
rescan, 1); |
| 854 runtime·xadd64(&gcstats.
rescanbytes, n); |
| 855 } |
848 break; | 856 break; |
849 } | 857 } |
850 } | 858 } |
851 } | 859 } |
852 goto next_block; | 860 goto next_block; |
853 | 861 |
854 case GC_ARRAY_START: | 862 case GC_ARRAY_START: |
855 i = stack_top.b + pc[1]; | 863 i = stack_top.b + pc[1]; |
856 count = pc[2]; | 864 count = pc[2]; |
857 elemsize = pc[3]; | 865 elemsize = pc[3]; |
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 runtime·printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-
%D) objects," | 1909 runtime·printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-
%D) objects," |
1902 " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\
n", | 1910 " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\
n", |
1903 mstats.numgc, work.nproc, (t2-t1)/1000000, (t3-t2)/10000
00, (t1-t0+t4-t3)/1000000, | 1911 mstats.numgc, work.nproc, (t2-t1)/1000000, (t3-t2)/10000
00, (t1-t0+t4-t3)/1000000, |
1904 heap0>>20, heap1>>20, obj0, obj1, | 1912 heap0>>20, heap1>>20, obj0, obj1, |
1905 mstats.nmalloc, mstats.nfree, | 1913 mstats.nmalloc, mstats.nfree, |
1906 stats.nhandoff, stats.nhandoffcnt, | 1914 stats.nhandoff, stats.nhandoffcnt, |
1907 work.sweepfor->nsteal, work.sweepfor->nstealcnt, | 1915 work.sweepfor->nsteal, work.sweepfor->nstealcnt, |
1908 stats.nprocyield, stats.nosyield, stats.nsleep); | 1916 stats.nprocyield, stats.nosyield, stats.nsleep); |
1909 if(CollectStats) { | 1917 if(CollectStats) { |
1910 runtime·printf("scan: %D bytes, %D objects, %D untyped,
%D types from MSpan\n", | 1918 runtime·printf("scan: %D bytes, %D objects, %D untyped,
%D types from MSpan\n", |
1911 » » » » gcstats.nbytes, gcstats.nobj_cnt, gcstats.nobj_n
otype, gcstats.nobj_typelookups_ok); | 1919 » » » » gcstats.nbytes, gcstats.obj.cnt, gcstats.obj.not
ype, gcstats.obj.typelookup); |
1912 » » » if(gcstats.ptr_cnt != 0) | 1920 » » » if(gcstats.ptr.cnt != 0) |
1913 runtime·printf("avg ptrbufsize: %D (%D/%D)\n", | 1921 runtime·printf("avg ptrbufsize: %D (%D/%D)\n", |
1914 » » » » » gcstats.ptr_sum/gcstats.ptr_cnt, gcstats
.ptr_sum, gcstats.ptr_cnt); | 1922 » » » » » gcstats.ptr.sum/gcstats.ptr.cnt, gcstats
.ptr.sum, gcstats.ptr.cnt); |
1915 » » » if(gcstats.nobj_cnt != 0) | 1923 » » » if(gcstats.obj.cnt != 0) |
1916 runtime·printf("avg nobj: %D (%D/%D)\n", | 1924 runtime·printf("avg nobj: %D (%D/%D)\n", |
1917 » » » » » gcstats.nobj_sum/gcstats.nobj_cnt, gcsta
ts.nobj_sum, gcstats.nobj_cnt); | 1925 » » » » » gcstats.obj.sum/gcstats.obj.cnt, gcstats
.obj.sum, gcstats.obj.cnt); |
1918 » » » runtime·printf("rescans: %D, %D bytes\n", gcstats.rescan
s, gcstats.rescan_nbytes); | 1926 » » » runtime·printf("rescans: %D, %D bytes\n", gcstats.rescan
, gcstats.rescanbytes); |
1919 | 1927 |
1920 runtime·printf("instruction counts:\n"); | 1928 runtime·printf("instruction counts:\n"); |
1921 ninstr = 0; | 1929 ninstr = 0; |
1922 for(i=0; i<nelem(gcstats.instr); i++) { | 1930 for(i=0; i<nelem(gcstats.instr); i++) { |
1923 runtime·printf("\t%d:\t%D\n", i, gcstats.instr[i
]); | 1931 runtime·printf("\t%d:\t%D\n", i, gcstats.instr[i
]); |
1924 ninstr += gcstats.instr[i]; | 1932 ninstr += gcstats.instr[i]; |
1925 } | 1933 } |
1926 runtime·printf("\ttotal:\t%D\n", ninstr); | 1934 runtime·printf("\ttotal:\t%D\n", ninstr); |
1927 | 1935 |
1928 runtime·printf("putempty: %D, getfull: %D\n", gcstats.pu
tempty, gcstats.getfull); | 1936 runtime·printf("putempty: %D, getfull: %D\n", gcstats.pu
tempty, gcstats.getfull); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2244 uintptr n; | 2252 uintptr n; |
2245 | 2253 |
2246 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; | 2254 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; |
2247 n = (n+bitmapChunk-1) & ~(bitmapChunk-1); | 2255 n = (n+bitmapChunk-1) & ~(bitmapChunk-1); |
2248 if(h->bitmap_mapped >= n) | 2256 if(h->bitmap_mapped >= n) |
2249 return; | 2257 return; |
2250 | 2258 |
2251 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped); | 2259 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped); |
2252 h->bitmap_mapped = n; | 2260 h->bitmap_mapped = n; |
2253 } | 2261 } |
LEFT | RIGHT |