// Ensure that defer arg sizes that map to the same defer size class // also map to the same malloc size class. void runtime·testdefersizes(void) { P *p; int32 i, siz, defersc, mallocsc; int32 map[nelem(p->deferpool)]; for(i=0; i<nelem(p->deferpool); i++) map[i] = -1; for(i=0;; i++) { defersc = DEFERCLASS(i); if(defersc >= nelem(p->deferpool)) break; siz = TOTALSIZE(i); mallocsc = runtime·SizeToClass(siz); siz = runtime·class_to_size[mallocsc]; // runtime·printf("defer class %d: arg size %d, block size %d(%d)\n", defersc, i, siz, mallocsc); if(map[defersc] < 0) { map[defersc] = mallocsc; continue; } if(map[defersc] != mallocsc) { runtime·printf("bad defer size class: i=%d siz=%d mallocsc=%d/%d\n", i, siz, map[defersc], mallocsc); runtime·throw("bad defer size class"); } } }
runtime·mallocgc ( uintptr size , uint32 flag , int32 dogc , int32 zeroed ) { int32 sizeclass , rate; MCache *c; uintptr npages; MSpan *s; void *v; #line 2080 "C:\Go\src\pkg\runtime\malloc.goc" if ( runtime·gcwaiting && g != m->g0 && m->locks == 0 ) runtime·gosched ( ) ; if ( m->mallocing ) runtime·throw ( "malloc/free - deadlock" ) ; m->mallocing = 1; if ( size == 0 ) size = 1; #line 2088 "C:\Go\src\pkg\runtime\malloc.goc" c = m->mcache; c->local_nmalloc++; if ( size <= MaxSmallSize ) { #line 2092 "C:\Go\src\pkg\runtime\malloc.goc" sizeclass = runtime·SizeToClass ( size ) ; size = runtime·class_to_size[sizeclass]; v = runtime·MCache_Alloc ( c , sizeclass , size , zeroed ) ; if ( v == nil ) runtime·throw ( "out of memory" ) ; c->local_alloc += size; c->local_total_alloc += size; c->local_by_size[sizeclass].nmalloc++; } else { #line 2104 "C:\Go\src\pkg\runtime\malloc.goc" npages = size >> PageShift; if ( ( size & PageMask ) != 0 ) npages++; s = runtime·MHeap_Alloc ( &runtime·mheap , npages , 0 , 1 ) ; if ( s == nil ) runtime·throw ( "out of memory" ) ; size = npages<<PageShift; c->local_alloc += size; c->local_total_alloc += size; v = ( void* ) ( s->start << PageShift ) ; #line 2116 "C:\Go\src\pkg\runtime\malloc.goc" runtime·markspan ( v , 0 , 0 , true ) ; } if ( ! ( flag & FlagNoGC ) ) runtime·markallocated ( v , size , ( flag&FlagNoPointers ) != 0 ) ; #line 2121 "C:\Go\src\pkg\runtime\malloc.goc" m->mallocing = 0; #line 2123 "C:\Go\src\pkg\runtime\malloc.goc" if ( ! ( flag & FlagNoProfiling ) && ( rate = runtime·MemProfileRate ) > 0 ) { if ( size >= rate ) goto profile; if ( m->mcache->next_sample > size ) m->mcache->next_sample -= size; else { #line 2131 "C:\Go\src\pkg\runtime\malloc.goc" if ( rate > 0x3fffffff ) rate = 0x3fffffff; m->mcache->next_sample = runtime·fastrand1 ( ) % ( 2*rate ) ; profile: runtime·setblockspecial ( v , true ) ; runtime·MProf_Malloc ( v , size ) ; } } #line 2140 "C:\Go\src\pkg\runtime\malloc.goc" if ( dogc && mstats.heap_alloc >= mstats.next_gc ) runtime·gc ( 0 ) ; return v; }
void runtime·InitSizes(void) { int32 align, sizeclass, size, osize, nextsize, n; uint32 i; uintptr allocsize, npages; // Initialize the runtime·class_to_size table (and choose class sizes in the process). runtime·class_to_size[0] = 0; sizeclass = 1; // 0 means no class align = 8; for(size = align; size <= MaxSmallSize; size += align) { if((size&(size-1)) == 0) { // bump alignment once in a while if(size >= 2048) align = 256; else if(size >= 128) align = size / 8; else if(size >= 16) align = 16; // required for x86 SSE instructions, if we want to use them } if((align&(align-1)) != 0) runtime·throw("InitSizes - bug"); // Make the allocnpages big enough that // the leftover is less than 1/8 of the total, // so wasted space is at most 12.5%. allocsize = PageSize; osize = size + RefcountOverhead; while(allocsize%osize > (allocsize/8)) allocsize += PageSize; npages = allocsize >> PageShift; // If the previous sizeclass chose the same // allocation size and fit the same number of // objects into the page, we might as well // use just this size instead of having two // different sizes. if(sizeclass > 1 && npages == runtime·class_to_allocnpages[sizeclass-1] && allocsize/osize == allocsize/(runtime·class_to_size[sizeclass-1]+RefcountOverhead)) { runtime·class_to_size[sizeclass-1] = size; continue; } runtime·class_to_allocnpages[sizeclass] = npages; runtime·class_to_size[sizeclass] = size; sizeclass++; } if(sizeclass != NumSizeClasses) { runtime·printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses); runtime·throw("InitSizes - bad NumSizeClasses"); } // Initialize the size_to_class tables. nextsize = 0; for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) { for(; nextsize < 1024 && nextsize <= runtime·class_to_size[sizeclass]; nextsize+=8) size_to_class8[nextsize/8] = sizeclass; if(nextsize >= 1024) for(; nextsize <= runtime·class_to_size[sizeclass]; nextsize += 128) size_to_class128[(nextsize-1024)/128] = sizeclass; } // Double-check SizeToClass. if(0) { for(n=0; n < MaxSmallSize; n++) { sizeclass = runtime·SizeToClass(n); if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime·class_to_size[sizeclass] < n) { runtime·printf("size=%d sizeclass=%d runtime·class_to_size=%d\n", n, sizeclass, runtime·class_to_size[sizeclass]); runtime·printf("incorrect SizeToClass"); goto dump; } if(sizeclass > 1 && runtime·class_to_size[sizeclass-1] >= n) { runtime·printf("size=%d sizeclass=%d runtime·class_to_size=%d\n", n, sizeclass, runtime·class_to_size[sizeclass]); runtime·printf("SizeToClass too big"); goto dump; } } } // Copy out for statistics table. for(i=0; i<nelem(runtime·class_to_size); i++) mstats.by_size[i].size = runtime·class_to_size[i]; // Initialize the runtime·class_to_transfercount table. for(sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) { n = 64*1024 / runtime·class_to_size[sizeclass]; if(n < 2) n = 2; if(n > 32) n = 32; runtime·class_to_transfercount[sizeclass] = n; } return; dump: if(1){ runtime·printf("NumSizeClasses=%d\n", NumSizeClasses); runtime·printf("runtime·class_to_size:"); for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++) runtime·printf(" %d", runtime·class_to_size[sizeclass]); runtime·printf("\n\n"); runtime·printf("size_to_class8:"); for(i=0; i<nelem(size_to_class8); i++) runtime·printf(" %d=>%d(%d)\n", i*8, size_to_class8[i], runtime·class_to_size[size_to_class8[i]]); runtime·printf("\n"); runtime·printf("size_to_class128:"); for(i=0; i<nelem(size_to_class128); i++) runtime·printf(" %d=>%d(%d)\n", i*128, size_to_class128[i], runtime·class_to_size[size_to_class128[i]]); runtime·printf("\n"); } runtime·throw("InitSizes failed"); }