diff options
Diffstat (limited to 'libgo/runtime/malloc.goc')
-rw-r--r-- | libgo/runtime/malloc.goc | 114 |
1 files changed, 81 insertions, 33 deletions
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc index a484642..dfab683 100644 --- a/libgo/runtime/malloc.goc +++ b/libgo/runtime/malloc.goc @@ -18,7 +18,7 @@ package runtime #include "go-type.h" #include "race.h" -MHeap runtime_mheap; +MHeap *runtime_mheap; int32 runtime_checking; @@ -46,7 +46,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed) g = runtime_g(); if(g->status == Gsyscall) dogc = 0; - if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && g->status != Gsyscall) { + if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && dogc) { runtime_gosched(); m = runtime_m(); } @@ -78,7 +78,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed) npages = size >> PageShift; if((size & PageMask) != 0) npages++; - s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, zeroed); + s = runtime_MHeap_Alloc(runtime_mheap, npages, 0, 1, zeroed); if(s == nil) runtime_throw("out of memory"); size = npages<<PageShift; @@ -92,9 +92,9 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed) if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) { // purge cache stats to prevent overflow - runtime_lock(&runtime_mheap); + runtime_lock(runtime_mheap); runtime_purgecachedstats(c); - runtime_unlock(&runtime_mheap); + runtime_unlock(runtime_mheap); } if(!(flag & FlagNoGC)) @@ -175,17 +175,17 @@ __go_free(void *v) if(sizeclass == 0) { // Large object. size = s->npages<<PageShift; - *(uintptr*)(s->start<<PageShift) = 1; // mark as "needs to be zeroed" + *(uintptr*)(s->start<<PageShift) = (uintptr)0xfeedfeedfeedfeedll; // mark as "needs to be zeroed" // Must mark v freed before calling unmarkspan and MHeap_Free: // they might coalesce v into other spans and change the bitmap further. runtime_markfreed(v, size); runtime_unmarkspan(v, 1<<PageShift); - runtime_MHeap_Free(&runtime_mheap, s, 1); + runtime_MHeap_Free(runtime_mheap, s, 1); } else { // Small object. size = runtime_class_to_size[sizeclass]; if(size > sizeof(uintptr)) - ((uintptr*)v)[1] = 1; // mark as "needs to be zeroed" + ((uintptr*)v)[1] = (uintptr)0xfeedfeedfeedfeedll; // mark as "needs to be zeroed" // Must mark v freed before calling MCache_Free: // it might coalesce v and other blocks into a bigger span // and change the bitmap further. @@ -213,12 +213,12 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp) m->mcache->local_nlookup++; if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) { // purge cache stats to prevent overflow - runtime_lock(&runtime_mheap); + runtime_lock(runtime_mheap); runtime_purgecachedstats(m->mcache); - runtime_unlock(&runtime_mheap); + runtime_unlock(runtime_mheap); } - s = runtime_MHeap_LookupMaybe(&runtime_mheap, v); + s = runtime_MHeap_LookupMaybe(runtime_mheap, v); if(sp) *sp = s; if(s == nil) { @@ -262,11 +262,11 @@ runtime_allocmcache(void) intgo rate; MCache *c; - runtime_lock(&runtime_mheap); - c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc); - mstats.mcache_inuse = runtime_mheap.cachealloc.inuse; - mstats.mcache_sys = runtime_mheap.cachealloc.sys; - runtime_unlock(&runtime_mheap); + runtime_lock(runtime_mheap); + c = runtime_FixAlloc_Alloc(&runtime_mheap->cachealloc); + mstats.mcache_inuse = runtime_mheap->cachealloc.inuse; + mstats.mcache_sys = runtime_mheap->cachealloc.sys; + runtime_unlock(runtime_mheap); runtime_memclr((byte*)c, sizeof(*c)); // Set first allocation sample size. @@ -283,10 +283,10 @@ void runtime_freemcache(MCache *c) { runtime_MCache_ReleaseAll(c); - runtime_lock(&runtime_mheap); + runtime_lock(runtime_mheap); runtime_purgecachedstats(c); - runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c); - runtime_unlock(&runtime_mheap); + runtime_FixAlloc_Free(&runtime_mheap->cachealloc, c); + runtime_unlock(runtime_mheap); } void @@ -334,9 +334,15 @@ runtime_mallocinit(void) USED(arena_size); USED(bitmap_size); + if((runtime_mheap = runtime_SysAlloc(sizeof(*runtime_mheap))) == nil) + runtime_throw("runtime: cannot allocate heap metadata"); + runtime_InitSizes(); - limit = runtime_memlimit(); + // limit = runtime_memlimit(); + // See https://code.google.com/p/go/issues/detail?id=5049 + // TODO(rsc): Fix after 1.1. + limit = 0; // Set up the allocation arena, a contiguous area of memory where // allocated data will be found. The arena begins with a bitmap large @@ -414,13 +420,13 @@ runtime_mallocinit(void) if((uintptr)p & (((uintptr)1<<PageShift)-1)) runtime_throw("runtime: SysReserve returned unaligned address"); - runtime_mheap.bitmap = p; - runtime_mheap.arena_start = p + bitmap_size; - runtime_mheap.arena_used = runtime_mheap.arena_start; - runtime_mheap.arena_end = runtime_mheap.arena_start + arena_size; + runtime_mheap->bitmap = p; + runtime_mheap->arena_start = p + bitmap_size; + runtime_mheap->arena_used = runtime_mheap->arena_start; + runtime_mheap->arena_end = runtime_mheap->arena_start + arena_size; // Initialize the rest of the allocator. - runtime_MHeap_Init(&runtime_mheap, runtime_SysAlloc); + runtime_MHeap_Init(runtime_mheap, runtime_SysAlloc); runtime_m()->mcache = runtime_allocmcache(); // See if it works. @@ -519,8 +525,8 @@ runtime_settype_flush(M *mp, bool sysalloc) // (Manually inlined copy of runtime_MHeap_Lookup) p = (uintptr)v>>PageShift; if(sizeof(void*) == 8) - p -= (uintptr)runtime_mheap.arena_start >> PageShift; - s = runtime_mheap.map[p]; + p -= (uintptr)runtime_mheap->arena_start >> PageShift; + s = runtime_mheap->map[p]; if(s->sizeclass == 0) { s->types.compression = MTypes_Single; @@ -537,9 +543,11 @@ runtime_settype_flush(M *mp, bool sysalloc) nbytes3 = 8*sizeof(uintptr) + 1*ntypes; if(!sysalloc) { - data3 = runtime_mallocgc(nbytes3, FlagNoPointers, 0, 1); + data3 = runtime_mallocgc(nbytes3, FlagNoProfiling|FlagNoPointers, 0, 1); } else { data3 = runtime_SysAlloc(nbytes3); + if(data3 == nil) + runtime_throw("runtime: cannot allocate memory"); if(0) runtime_printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3); } @@ -573,9 +581,11 @@ runtime_settype_flush(M *mp, bool sysalloc) nbytes2 = ntypes * sizeof(uintptr); if(!sysalloc) { - data2 = runtime_mallocgc(nbytes2, FlagNoPointers, 0, 1); + data2 = runtime_mallocgc(nbytes2, FlagNoProfiling|FlagNoPointers, 0, 1); } else { data2 = runtime_SysAlloc(nbytes2); + if(data2 == nil) + runtime_throw("runtime: cannot allocate memory"); if(0) runtime_printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2); } @@ -633,7 +643,7 @@ runtime_settype(void *v, uintptr t) } if(DebugTypeAtBlockEnd) { - s = runtime_MHeap_Lookup(&runtime_mheap, v); + s = runtime_MHeap_Lookup(runtime_mheap, v); *(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t; } } @@ -672,7 +682,7 @@ runtime_gettype(void *v) uintptr t, ofs; byte *data; - s = runtime_MHeap_LookupMaybe(&runtime_mheap, v); + s = runtime_MHeap_LookupMaybe(runtime_mheap, v); if(s != nil) { t = 0; switch(s->types.compression) { @@ -731,9 +741,8 @@ runtime_new(const Type *typ) ret = runtime_mallocgc(typ->__size, flag, 1, 1); if(UseSpanType && !flag) { - if(false) { + if(false) runtime_printf("new %S: %p\n", *typ->__reflection, ret); - } runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject); } } @@ -741,6 +750,45 @@ runtime_new(const Type *typ) return ret; } +static void* +cnew(const Type *typ, intgo n, int32 objtyp) +{ + uint32 flag; + void *ret; + + if((objtyp&(PtrSize-1)) != objtyp) + runtime_throw("runtime: invalid objtyp"); + if(n < 0 || (typ->__size > 0 && (uintptr)n > (MaxMem/typ->__size))) + runtime_panicstring("runtime: allocation size out of range"); + if(typ->__size == 0 || n == 0) { + // All 0-length allocations use this pointer. + // The language does not require the allocations to + // have distinct values. + return &runtime_zerobase; + } + flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0; + ret = runtime_mallocgc(typ->__size*n, flag, 1, 1); + if(UseSpanType && !flag) { + if(false) + runtime_printf("cnew [%D]%S: %p\n", (int64)n, *typ->__reflection, ret); + runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject); + } + return ret; +} + +// same as runtime_new, but callable from C +void* +runtime_cnew(const Type *typ) +{ + return cnew(typ, 1, TypeInfo_SingleObject); +} + +void* +runtime_cnewarray(const Type *typ, intgo n) +{ + return cnew(typ, n, TypeInfo_Array); +} + func GC() { runtime_gc(1); } |