]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use reflect·call() to enter the function gc()
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Tue, 27 Nov 2012 18:04:59 +0000 (13:04 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 27 Nov 2012 18:04:59 +0000 (13:04 -0500)
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
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 5ad09d53b1e69c938d3f3607bff69471bb0dc68a..32e030c51861731347a66177039838e6f61ff013 100644 (file)
@@ -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
index 9da748f2f66709ca599a9a05669d12c7786a26a3..7dfd3c73fb398674d61909bd864230453041ef14 100644 (file)
@@ -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;
index c6b30ac73c2637f4689dfd37418fc416905972c3..e6a78ba5709e4a77d872b6c479f8762367b5efaa 100644 (file)
@@ -273,6 +273,7 @@ struct      M
        GCStats gcstats;
        bool    racecall;
        void*   racepc;
+       uint32  moreframesize_minalloc;
 
        uintptr settype_buf[1024];
        uintptr settype_bufsize;