aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-07-19 16:04:09 -0400
committerRuss Cox <rsc@golang.org>2013-07-19 16:04:09 -0400
commit48769bf546ba7ad830c2edc05656e217d15a20c8 (patch)
treee3110fce615f1250f56a7c68d69ade5ad3ff3bbb /src/pkg/runtime
parent5d340de1f682d3b2cf10b2319c25ef3799e84078 (diff)
downloadgo-48769bf546ba7ad830c2edc05656e217d15a20c8.tar.xz
runtime: use funcdata to supply garbage collection information
This CL introduces a FUNCDATA number for runtime-specific garbage collection metadata, changes the C and Go compilers to emit that metadata, and changes the runtime to expect it. The old pseudo-instructions that carried this information are gone, as is the linker code to process them. R=golang-dev, dvyukov, cshapiro CC=golang-dev https://golang.org/cl/11406044
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/funcdata.h4
-rw-r--r--src/pkg/runtime/mgc0.c36
-rw-r--r--src/pkg/runtime/runtime.h10
-rw-r--r--src/pkg/runtime/symtab.c8
-rw-r--r--src/pkg/runtime/traceback_arm.c27
-rw-r--r--src/pkg/runtime/traceback_x86.c22
6 files changed, 46 insertions, 61 deletions
diff --git a/src/pkg/runtime/funcdata.h b/src/pkg/runtime/funcdata.h
index 850288bf64..f12bf49fb1 100644
--- a/src/pkg/runtime/funcdata.h
+++ b/src/pkg/runtime/funcdata.h
@@ -7,7 +7,9 @@
// be written using #defines. It is included by the runtime package
// as well as the compilers.
-#define PCDATA_ArgSize 0
+#define PCDATA_ArgSize 0 /* argument size at CALL instruction */
+
+#define FUNCDATA_GC 0 /* garbage collector block */
// To be used in assembly.
#define ARGSIZE(n) PCDATA $PCDATA_ArgSize, $n
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index abf93e425b..8654e38544 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -13,6 +13,7 @@
#include "type.h"
#include "typekind.h"
#include "hashmap.h"
+#include "funcdata.h"
enum {
Debug = 0,
@@ -1385,6 +1386,14 @@ addroot(Obj obj)
extern byte pclntab[]; // base for f->ptrsoff
+typedef struct GCFunc GCFunc;
+struct GCFunc
+{
+ uint32 locals; // size of local variables in bytes
+ uint32 nptrs; // number of words that follow
+ uint32 ptrs[1]; // bitmap of pointers in arguments
+};
+
// Scan a stack frame: local variables and function arguments/results.
static void
addframeroots(Stkframe *frame, void*)
@@ -1392,21 +1401,28 @@ addframeroots(Stkframe *frame, void*)
Func *f;
byte *ap;
int32 i, j, nuintptr;
- uint32 w, b, *ptrs;
+ uint32 w, b;
+ GCFunc *gcf;
+ f = frame->fn;
+ gcf = runtime·funcdata(f, FUNCDATA_GC);
+
// Scan local variables if stack frame has been allocated.
- if(frame->varlen > 0)
- addroot((Obj){frame->varp, frame->varlen, 0});
+ i = frame->varp - (byte*)frame->sp;
+ if(i > 0) {
+ if(gcf == nil)
+ addroot((Obj){frame->varp - i, i, 0});
+ else if(i >= gcf->locals)
+ addroot((Obj){frame->varp - gcf->locals, gcf->locals, 0});
+ }
// Scan arguments.
// Use pointer information if known.
- f = frame->fn;
- if(f->args > 0 && f->ptrslen > 0) {
+ if(f->args > 0 && gcf != nil && gcf->nptrs > 0) {
ap = frame->argp;
nuintptr = f->args / sizeof(uintptr);
- ptrs = (uint32*)(pclntab + f->ptrsoff);
- for(i = 0; i < f->ptrslen; i++) {
- w = ptrs[i];
+ for(i = 0; i < gcf->nptrs; i++) {
+ w = gcf->ptrs[i];
b = 1;
j = nuintptr;
if(j > 32)
@@ -2017,8 +2033,10 @@ runtime·gc(int32 force)
// all done
m->gcing = 0;
+ m->locks++;
runtime·semrelease(&runtime·worldsema);
runtime·starttheworld();
+ m->locks--;
// now that gc is done and we're back on g stack, kick off finalizer thread if needed
if(finq != nil) {
@@ -2185,8 +2203,10 @@ runtime·ReadMemStats(MStats *stats)
updatememstats(nil);
*stats = mstats;
m->gcing = 0;
+ m->locks++;
runtime·semrelease(&runtime·worldsema);
runtime·starttheworld();
+ m->locks--;
}
void
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 811ec76653..f405287aa8 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -407,10 +407,10 @@ struct Func
// TODO: Remove these fields.
int32 args; // in/out args size
- int32 locals; // locals size
+ int32 x1; // locals size
int32 frame; // legacy frame size; use pcsp if possible
- int32 ptrsoff;
- int32 ptrslen;
+ int32 x2;
+ int32 x3;
int32 pcsp;
int32 pcfile;
@@ -677,10 +677,9 @@ struct Stkframe
uintptr lr; // program counter at caller aka link register
uintptr sp; // stack pointer at pc
uintptr fp; // stack pointer at caller aka frame pointer
+ byte* varp; // top of local variables
byte* argp; // pointer to function arguments
uintptr arglen; // number of bytes at argp
- byte* varp; // pointer to local variables
- uintptr varlen; // number of bytes at varp
};
int32 runtime·gentraceback(uintptr, uintptr, uintptr, G*, int32, uintptr*, int32, void(*)(Stkframe*, void*), void*, bool);
@@ -856,6 +855,7 @@ void runtime·netpollready(G**, PollDesc*, int32);
void runtime·crash(void);
void runtime·parsedebugvars(void);
void _rt0_go(void);
+void* runtime·funcdata(Func*, int32);
#pragma varargck argpos runtime·printf 1
#pragma varargck type "c" int32
diff --git a/src/pkg/runtime/symtab.c b/src/pkg/runtime/symtab.c
index e877a60cd9..053e255079 100644
--- a/src/pkg/runtime/symtab.c
+++ b/src/pkg/runtime/symtab.c
@@ -78,17 +78,17 @@ readvarint(byte **pp)
return v;
}
-static uintptr
-funcdata(Func *f, int32 i)
+void*
+runtime·funcdata(Func *f, int32 i)
{
byte *p;
if(i < 0 || i >= f->nfuncdata)
- return 0;
+ return nil;
p = (byte*)&f->nfuncdata + 4 + f->npcdata*4;
if(sizeof(void*) == 8 && ((uintptr)p & 4))
p += 4;
- return ((uintptr*)p)[i];
+ return ((void**)p)[i];
}
static bool
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
index 5aea699e34..563ba28c94 100644
--- a/src/pkg/runtime/traceback_arm.c
+++ b/src/pkg/runtime/traceback_arm.c
@@ -95,7 +95,9 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
runtime·throw("unknown caller pc");
}
}
-
+
+ frame.varp = (byte*)frame.fp;
+
// Derive size of arguments.
// Most functions have a fixed-size argument block,
// so we can use metadata about the function f.
@@ -121,27 +123,6 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
}
}
- // Derive location and size of local variables.
- if(frame.fp == frame.sp) {
- // Function has not created a frame for itself yet.
- frame.varp = nil;
- frame.varlen = 0;
- } else if(f->locals == 0) {
- // Assume no information, so use whole frame.
- // TODO: Distinguish local==0 from local==unknown.
- frame.varp = (byte*)frame.sp;
- frame.varlen = frame.fp - frame.sp;
- } else {
- if(f->locals > frame.fp - frame.sp) {
- runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, runtime·funcname(f));
- if(callback != nil)
- runtime·throw("invalid stack");
- }
- frame.varp = (byte*)frame.fp - f->locals;
- frame.varlen = f->locals;
- }
-
-
if(skip > 0) {
skip--;
goto skipped;
@@ -203,7 +184,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.fn = f = runtime·findfunc(frame.pc);
if(f == nil)
frame.pc = x;
- else if (f->frame == 0)
+ else if(f->frame == 0)
frame.lr = x;
}
}
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
index 3153103d34..b88797210e 100644
--- a/src/pkg/runtime/traceback_x86.c
+++ b/src/pkg/runtime/traceback_x86.c
@@ -111,6 +111,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
runtime·throw("unknown caller pc");
}
}
+
+ frame.varp = (byte*)frame.fp - sizeof(uintptr);
// Derive size of arguments.
// Most functions have a fixed-size argument block,
@@ -137,26 +139,6 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
}
}
- // Derive location and size of local variables.
- if(frame.fp == frame.sp + sizeof(uintptr)) {
- // Function has not created a frame for itself yet.
- frame.varp = nil;
- frame.varlen = 0;
- } else if(f->locals == 0) {
- // Assume no information, so use whole frame.
- // TODO: Distinguish local==0 from local==unknown.
- frame.varp = (byte*)frame.sp;
- frame.varlen = frame.fp - sizeof(uintptr) - frame.sp;
- } else {
- if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) {
- runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, runtime·funcname(f));
- if(callback != nil)
- runtime·throw("invalid stack");
- }
- frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->locals;
- frame.varlen = f->locals;
- }
-
if(skip > 0) {
skip--;
goto skipped;