From 51b8edcb37e7f20859b69623f69e9032e9601add Mon Sep 17 00:00:00 2001 From: Jan Ziak <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 27 Nov 2012 13:04:59 -0500 Subject: [PATCH] =?UTF-8?q?runtime:=20use=20reflect=C2=B7call()=20to=20ent?= =?UTF-8?q?er=20the=20function=20gc()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Garbage collection code (to be merged later) is calling functions which have many local variables. This increases the probability that the stack capacity won't be big enough to hold the local variables. So, start gc() on a bigger stack to eliminate a potentially large number of calls to runtime·morestack(). R=rsc, remyoudompheng, dsymonds, minux.ma, iant, iant CC=golang-dev https://golang.org/cl/6846044 --- src/pkg/runtime/mgc0.c | 43 +++++++++++++++++++++++++++++++-------- src/pkg/runtime/proc.c | 16 +++++++++++---- src/pkg/runtime/runtime.h | 1 + 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 5ad09d53b1..32e030c518 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -881,6 +881,7 @@ runtime·memorydump(void) dumpspan(spanidx); } } + void runtime·gchelper(void) { @@ -957,15 +958,20 @@ cachestats(GCStats *stats) mstats.stacks_sys = stacks_sys; } +// Structure of arguments passed to function gc(). +// This allows the arguments to be passed via reflect·call. +struct gc_args +{ + int32 force; +}; + +static void gc(struct gc_args *args); + void runtime·gc(int32 force) { - int64 t0, t1, t2, t3; - uint64 heap0, heap1, obj0, obj1; byte *p; - GCStats stats; - M *m1; - uint32 i; + struct gc_args a, *ap; // The atomic operations are not atomic if the uint64s // are not aligned on uint64 boundaries. This has been @@ -1000,8 +1006,30 @@ runtime·gc(int32 force) if(gcpercent < 0) return; + // Run gc on a bigger stack to eliminate + // a potentially large number of calls to runtime·morestack. + a.force = force; + ap = &a; + m->moreframesize_minalloc = StackBig; + reflect·call((byte*)gc, (byte*)&ap, sizeof(ap)); + + if(gctrace > 1 && !force) { + a.force = 1; + gc(&a); + } +} + +static void +gc(struct gc_args *args) +{ + int64 t0, t1, t2, t3; + uint64 heap0, heap1, obj0, obj1; + GCStats stats; + M *m1; + uint32 i; + runtime·semacquire(&runtime·worldsema); - if(!force && mstats.heap_alloc < mstats.next_gc) { + if(!args->force && mstats.heap_alloc < mstats.next_gc) { runtime·semrelease(&runtime·worldsema); return; } @@ -1107,9 +1135,6 @@ runtime·gc(int32 force) // give the queued finalizers, if any, a chance to run if(finq != nil) runtime·gosched(); - - if(gctrace > 1 && !force) - runtime·gc(1); } void diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 9da748f2f6..7dfd3c73fb 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -1134,7 +1134,7 @@ runtime·oldstack(void) void runtime·newstack(void) { - int32 framesize, argsize; + int32 framesize, minalloc, argsize; Stktop *top; byte *stk, *sp; G *g1; @@ -1143,9 +1143,12 @@ runtime·newstack(void) uintptr free; framesize = m->moreframesize; + minalloc = m->moreframesize_minalloc; argsize = m->moreargsize; g1 = m->curg; + m->moreframesize_minalloc = 0; + if(m->morebuf.sp < g1->stackguard - StackGuard) { runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, g1->stackguard - StackGuard); runtime·throw("runtime: split stack overflow"); @@ -1159,7 +1162,10 @@ runtime·newstack(void) if(reflectcall) framesize = 0; - if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > g1->stackguard) { + if(framesize < minalloc) + framesize = minalloc; + + if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > g1->stackguard) { // special case: called from reflect.call (framesize==1) // to call code with an arbitrary argument size, // and we have enough space on the current stack. @@ -1180,8 +1186,10 @@ runtime·newstack(void) free = framesize; } -//runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n", -//framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, g1->stackbase); + if(0) { + runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n", + framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, g1->stackbase); + } top->stackbase = (byte*)g1->stackbase; top->stackguard = (byte*)g1->stackguard; diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index c6b30ac73c..e6a78ba570 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -273,6 +273,7 @@ struct M GCStats gcstats; bool racecall; void* racepc; + uint32 moreframesize_minalloc; uintptr settype_buf[1024]; uintptr settype_bufsize;