github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/msize.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Malloc small size classes. 6 // 7 // See malloc.h for overview. 8 // 9 // The size classes are chosen so that rounding an allocation 10 // request up to the next size class wastes at most 12.5% (1.125x). 11 // 12 // Each size class has its own page count that gets allocated 13 // and chopped up when new objects of the size class are needed. 14 // That page count is chosen so that chopping up the run of 15 // pages into objects of the given size wastes at most 12.5% (1.125x) 16 // of the memory. It is not necessary that the cutoff here be 17 // the same as above. 18 // 19 // The two sources of waste multiply, so the worst possible case 20 // for the above constraints would be that allocations of some 21 // size might have a 26.6% (1.266x) overhead. 22 // In practice, only one of the wastes comes into play for a 23 // given size (sizes < 512 waste mainly on the round-up, 24 // sizes > 512 waste mainly on the page chopping). 25 // 26 // TODO(rsc): Compute max waste for any given size. 27 28 #include "runtime.h" 29 #include "arch.h" 30 #include "malloc.h" 31 32 int32 runtime_class_to_size[NumSizeClasses]; 33 int32 runtime_class_to_allocnpages[NumSizeClasses]; 34 35 // The SizeToClass lookup is implemented using two arrays, 36 // one mapping sizes <= 1024 to their class and one mapping 37 // sizes >= 1024 and <= MaxSmallSize to their class. 38 // All objects are 8-aligned, so the first array is indexed by 39 // the size divided by 8 (rounded up). Objects >= 1024 bytes 40 // are 128-aligned, so the second array is indexed by the 41 // size divided by 128 (rounded up). The arrays are filled in 42 // by InitSizes. 43 44 int8 runtime_size_to_class8[1024/8 + 1]; 45 int8 runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1]; 46 47 int32 48 runtime_SizeToClass(int32 size) 49 { 50 if(size > MaxSmallSize) 51 runtime_throw("SizeToClass - invalid size"); 52 if(size > 1024-8) 53 return runtime_size_to_class128[(size-1024+127) >> 7]; 54 return runtime_size_to_class8[(size+7)>>3]; 55 } 56 57 void 58 runtime_InitSizes(void) 59 { 60 int32 align, sizeclass, size, nextsize, n; 61 uint32 i; 62 uintptr allocsize, npages; 63 64 // Initialize the runtime_class_to_size table (and choose class sizes in the process). 65 runtime_class_to_size[0] = 0; 66 sizeclass = 1; // 0 means no class 67 align = 8; 68 for(size = align; size <= MaxSmallSize; size += align) { 69 if((size&(size-1)) == 0) { // bump alignment once in a while 70 if(size >= 2048) 71 align = 256; 72 else if(size >= 128) 73 align = size / 8; 74 else if(size >= 16) 75 align = 16; // required for x86 SSE instructions, if we want to use them 76 } 77 if((align&(align-1)) != 0) 78 runtime_throw("InitSizes - bug"); 79 80 // Make the allocnpages big enough that 81 // the leftover is less than 1/8 of the total, 82 // so wasted space is at most 12.5%. 83 allocsize = PageSize; 84 while(allocsize%size > allocsize/8) 85 allocsize += PageSize; 86 npages = allocsize >> PageShift; 87 88 // If the previous sizeclass chose the same 89 // allocation size and fit the same number of 90 // objects into the page, we might as well 91 // use just this size instead of having two 92 // different sizes. 93 if(sizeclass > 1 && 94 (int32)npages == runtime_class_to_allocnpages[sizeclass-1] && 95 allocsize/size == allocsize/runtime_class_to_size[sizeclass-1]) { 96 runtime_class_to_size[sizeclass-1] = size; 97 continue; 98 } 99 100 runtime_class_to_allocnpages[sizeclass] = npages; 101 runtime_class_to_size[sizeclass] = size; 102 sizeclass++; 103 } 104 if(sizeclass != NumSizeClasses) { 105 runtime_printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses); 106 runtime_throw("InitSizes - bad NumSizeClasses"); 107 } 108 109 // Initialize the size_to_class tables. 110 nextsize = 0; 111 for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) { 112 for(; nextsize < 1024 && nextsize <= runtime_class_to_size[sizeclass]; nextsize+=8) 113 runtime_size_to_class8[nextsize/8] = sizeclass; 114 if(nextsize >= 1024) 115 for(; nextsize <= runtime_class_to_size[sizeclass]; nextsize += 128) 116 runtime_size_to_class128[(nextsize-1024)/128] = sizeclass; 117 } 118 119 // Double-check SizeToClass. 120 if(0) { 121 for(n=0; n < MaxSmallSize; n++) { 122 sizeclass = runtime_SizeToClass(n); 123 if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime_class_to_size[sizeclass] < n) { 124 runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]); 125 runtime_printf("incorrect SizeToClass"); 126 goto dump; 127 } 128 if(sizeclass > 1 && runtime_class_to_size[sizeclass-1] >= n) { 129 runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]); 130 runtime_printf("SizeToClass too big"); 131 goto dump; 132 } 133 } 134 } 135 136 // Copy out for statistics table. 137 for(i=0; i<nelem(runtime_class_to_size); i++) 138 mstats.by_size[i].size = runtime_class_to_size[i]; 139 return; 140 141 dump: 142 if(1){ 143 runtime_printf("NumSizeClasses=%d\n", NumSizeClasses); 144 runtime_printf("runtime_class_to_size:"); 145 for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++) 146 runtime_printf(" %d", runtime_class_to_size[sizeclass]); 147 runtime_printf("\n\n"); 148 runtime_printf("size_to_class8:"); 149 for(i=0; i<nelem(runtime_size_to_class8); i++) 150 runtime_printf(" %d=>%d(%d)\n", i*8, runtime_size_to_class8[i], 151 runtime_class_to_size[runtime_size_to_class8[i]]); 152 runtime_printf("\n"); 153 runtime_printf("size_to_class128:"); 154 for(i=0; i<nelem(runtime_size_to_class128); i++) 155 runtime_printf(" %d=>%d(%d)\n", i*128, runtime_size_to_class128[i], 156 runtime_class_to_size[runtime_size_to_class128[i]]); 157 runtime_printf("\n"); 158 } 159 runtime_throw("InitSizes failed"); 160 } 161 162 // Returns size of the memory block that mallocgc will allocate if you ask for the size. 163 uintptr 164 runtime_roundupsize(uintptr size) 165 { 166 if(size < MaxSmallSize) { 167 if(size <= 1024-8) 168 return runtime_class_to_size[runtime_size_to_class8[(size+7)>>3]]; 169 else 170 return runtime_class_to_size[runtime_size_to_class128[(size-1024+127) >> 7]]; 171 } 172 if(size + PageSize < size) 173 return size; 174 return ROUND(size, PageSize); 175 }