diff options
author | Ingo Oeser <ingo@jimdo.com> | 2013-06-14 23:22:50 +0200 |
---|---|---|
committer | Ingo Oeser <ingo@jimdo.com> | 2013-06-14 23:22:50 +0200 |
commit | 09f84a75bc63a6316d575f531489d69ec8ade2e8 (patch) | |
tree | b74a4dcecf087639a6898acb55c71dae1e54b299 /src | |
parent | efcc50dfdc94c82ee0292bf71992ecb7c0123061 (diff) | |
download | golang-09f84a75bc63a6316d575f531489d69ec8ade2e8.tar.gz |
Imported Upstream version 1.1.1upstream/1.1.1
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/gc/export.c | 6 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 1 | ||||
-rw-r--r-- | src/cmd/gc/inl.c | 5 | ||||
-rw-r--r-- | src/cmd/gc/sinit.c | 14 | ||||
-rw-r--r-- | src/pkg/reflect/all_test.go | 19 | ||||
-rw-r--r-- | src/pkg/runtime/gc_test.go | 52 | ||||
-rw-r--r-- | src/pkg/runtime/iface.c | 32 | ||||
-rw-r--r-- | src/pkg/runtime/malloc.goc | 50 | ||||
-rw-r--r-- | src/pkg/runtime/malloc.h | 1 | ||||
-rw-r--r-- | src/pkg/runtime/mgc0.c | 14 | ||||
-rw-r--r-- | src/pkg/runtime/proc.c | 1 | ||||
-rw-r--r-- | src/pkg/runtime/slice.c | 20 |
12 files changed, 131 insertions, 84 deletions
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c index b7311665a..4a9b8c8ba 100644 --- a/src/cmd/gc/export.c +++ b/src/cmd/gc/export.c @@ -164,13 +164,17 @@ reexportdep(Node *n) case ODOTTYPE: case ODOTTYPE2: case OSTRUCTLIT: + case OARRAYLIT: case OPTRLIT: + case OMAKEMAP: + case OMAKESLICE: + case OMAKECHAN: t = n->type; if(!t->sym && t->type) t = t->type; if(t && t->sym && t->sym->def && !exportedsym(t->sym)) { if(debug['E']) - print("reexport type for convnop %S\n", t->sym); + print("reexport type for expression %S\n", t->sym); exportlist = list(exportlist, t->sym->def); } break; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 48bcf0233..e94eb90ee 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -282,6 +282,7 @@ struct Node NodeList* cvars; // closure params NodeList* dcl; // autodcl for this func/closure NodeList* inl; // copy of the body for use in inlining + NodeList* inldcl; // copy of dcl for use in inlining // OLITERAL/OREGISTER Val val; diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c index f77b51d70..08b462e13 100644 --- a/src/cmd/gc/inl.c +++ b/src/cmd/gc/inl.c @@ -146,6 +146,7 @@ caninl(Node *fn) fn->nname->inl = fn->nbody; fn->nbody = inlcopylist(fn->nname->inl); + fn->nname->inldcl = inlcopylist(fn->nname->defn->dcl); // hack, TODO, check for better way to link method nodes back to the thing with the ->inl // this is so export can find the body of a method @@ -558,8 +559,8 @@ mkinlcall1(Node **np, Node *fn, int isddd) //dumplist("ninit pre", ninit); - if (fn->defn) // local function - dcl = fn->defn->dcl; + if(fn->defn) // local function + dcl = fn->inldcl; else // imported function dcl = fn->dcl; diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index f8c61828c..51c5f7022 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -50,9 +50,10 @@ init1(Node *n, NodeList **out) case PFUNC: break; default: - if(isblank(n) && n->defn != N && n->defn->initorder == InitNotStarted) { - n->defn->initorder = InitDone; - *out = list(*out, n->defn); + if(isblank(n) && n->curfn == N && n->defn != N && n->defn->initorder == InitNotStarted) { + // blank names initialization is part of init() but not + // when they are inside a function. + break; } return; } @@ -62,7 +63,7 @@ init1(Node *n, NodeList **out) if(n->initorder == InitPending) { if(n->class == PFUNC) return; - + // if there have already been errors printed, // those errors probably confused us and // there might not be a loop. let the user @@ -127,8 +128,8 @@ init1(Node *n, NodeList **out) init2(n->defn->right, out); if(debug['j']) print("%S\n", n->sym); - if(!staticinit(n, out)) { -if(debug['%']) dump("nonstatic", n->defn); + if(isblank(n) || !staticinit(n, out)) { + if(debug['%']) dump("nonstatic", n->defn); *out = list(*out, n->defn); } } else if(0) { @@ -149,6 +150,7 @@ if(debug['%']) dump("nonstatic", n->defn); n->defn->initorder = InitDone; for(l=n->defn->rlist; l; l=l->next) init1(l->n, out); + if(debug['%']) dump("nonstatic", n->defn); *out = list(*out, n->defn); break; } diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go index 56cb315ad..a61f66308 100644 --- a/src/pkg/reflect/all_test.go +++ b/src/pkg/reflect/all_test.go @@ -3032,6 +3032,25 @@ func TestSliceOf(t *testing.T) { checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{}) } +func TestSliceOverflow(t *testing.T) { + // check that MakeSlice panics when size of slice overflows uint + const S = 1e6 + s := uint(S) + l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1 + if l*s >= s { + t.Fatal("slice size does not overflow") + } + var x [S]byte + st := SliceOf(TypeOf(x)) + defer func() { + err := recover() + if err == nil { + t.Fatal("slice overflow does not panic") + } + }() + MakeSlice(st, int(l), int(l)) +} + func TestSliceOfGC(t *testing.T) { type T *uintptr tt := TypeOf(T(nil)) diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go index 26fc77de1..a3c731ccb 100644 --- a/src/pkg/runtime/gc_test.go +++ b/src/pkg/runtime/gc_test.go @@ -97,3 +97,55 @@ func TestGcHashmapIndirection(t *testing.T) { m[a] = T{} } } + +func TestGcArraySlice(t *testing.T) { + type X struct { + buf [1]byte + nextbuf []byte + next *X + } + var head *X + for i := 0; i < 10; i++ { + p := &X{} + p.buf[0] = 42 + p.next = head + if head != nil { + p.nextbuf = head.buf[:] + } + head = p + runtime.GC() + } + for p := head; p != nil; p = p.next { + if p.buf[0] != 42 { + t.Fatal("corrupted heap") + } + } +} + +func TestGcRescan(t *testing.T) { + type X struct { + c chan error + nextx *X + } + type Y struct { + X + nexty *Y + p *int + } + var head *Y + for i := 0; i < 10; i++ { + p := &Y{} + p.c = make(chan error) + p.nextx = &head.X + p.nexty = head + p.p = new(int) + *p.p = 42 + head = p + runtime.GC() + } + for p := head; p != nil; p = p.nexty { + if *p.p != 42 { + t.Fatal("corrupted heap") + } + } +} diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c index 370edffb8..5973d6d03 100644 --- a/src/pkg/runtime/iface.c +++ b/src/pkg/runtime/iface.c @@ -687,42 +687,14 @@ reflect·unsafe_Typeof(Eface e, Eface ret) void reflect·unsafe_New(Type *t, void *ret) { - uint32 flag; - - flag = t->kind&KindNoPointers ? FlagNoPointers : 0; - ret = runtime·mallocgc(t->size, flag, 1, 1); - - if(UseSpanType && !flag) { - if(false) { - runtime·printf("unsafe_New %S: %p\n", *t->string, ret); - } - runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject); - } - + ret = runtime·cnew(t); FLUSH(&ret); } void reflect·unsafe_NewArray(Type *t, intgo n, void *ret) { - uint64 size; - - size = n*t->size; - if(size == 0) - ret = (byte*)&runtime·zerobase; - else if(t->kind&KindNoPointers) - ret = runtime·mallocgc(size, FlagNoPointers, 1, 1); - else { - ret = runtime·mallocgc(size, 0, 1, 1); - - if(UseSpanType) { - if(false) { - runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret); - } - runtime·settype(ret, (uintptr)t | TypeInfo_Array); - } - } - + ret = runtime·cnewarray(t, n); FLUSH(&ret); } diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc index f1d25a793..ef755f25c 100644 --- a/src/pkg/runtime/malloc.goc +++ b/src/pkg/runtime/malloc.goc @@ -717,9 +717,8 @@ runtime·new(Type *typ, uint8 *ret) ret = runtime·mallocgc(typ->size, flag, 1, 1); if(UseSpanType && !flag) { - if(false) { + if(false) runtime·printf("new %S: %p\n", *typ->string, ret); - } runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject); } } @@ -727,36 +726,45 @@ runtime·new(Type *typ, uint8 *ret) FLUSH(&ret); } -// same as runtime·new, but callable from C -void* -runtime·cnew(Type *typ) +static void* +cnew(Type *typ, intgo n, int32 objtyp) { uint32 flag; void *ret; - if(raceenabled) - m->racepc = runtime·getcallerpc(&typ); - - if(typ->size == 0) { + if((objtyp&(PtrSize-1)) != objtyp) + runtime·throw("runtime: invalid objtyp"); + if(n < 0 || (typ->size > 0 && 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. - ret = (uint8*)&runtime·zerobase; - } else { - flag = typ->kind&KindNoPointers ? FlagNoPointers : 0; - ret = runtime·mallocgc(typ->size, flag, 1, 1); - - if(UseSpanType && !flag) { - if(false) { - runtime·printf("new %S: %p\n", *typ->string, ret); - } - runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject); - } + return &runtime·zerobase; + } + flag = typ->kind&KindNoPointers ? 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->string, ret); + runtime·settype(ret, (uintptr)typ | objtyp); } - return ret; } +// same as runtime·new, but callable from C +void* +runtime·cnew(Type *typ) +{ + return cnew(typ, 1, TypeInfo_SingleObject); +} + +void* +runtime·cnewarray(Type *typ, intgo n) +{ + return cnew(typ, n, TypeInfo_Array); +} + func GC() { runtime·gc(1); } diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h index 52b76d557..7bbc1b2b3 100644 --- a/src/pkg/runtime/malloc.h +++ b/src/pkg/runtime/malloc.h @@ -461,6 +461,7 @@ bool runtime·blockspecial(void*); void runtime·setblockspecial(void*, bool); void runtime·purgecachedstats(MCache*); void* runtime·cnew(Type*); +void* runtime·cnewarray(Type*, intgo); void runtime·settype(void*, uintptr); void runtime·settype_flush(M*, bool); diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index f9dbdbb4a..c83f1892c 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -623,7 +623,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) byte *b, *arena_start, *arena_used; uintptr n, i, end_b, elemsize, size, ti, objti, count, type; uintptr *pc, precise_type, nominal_size; - uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret; + uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret, chancap; void *obj; Type *t; Slice *sliceptr; @@ -799,7 +799,11 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) sliceptr = (Slice*)(stack_top.b + pc[1]); if(sliceptr->cap != 0) { obj = sliceptr->array; - objti = pc[2] | PRECISE | LOOP; + // Can't use slice element type for scanning, + // because if it points to an array embedded + // in the beginning of a struct, + // we will scan the whole struct as the slice. + // So just obtain type info from heap. } pc += 3; break; @@ -1058,13 +1062,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) if(!(chantype->elem->kind & KindNoPointers)) { // Channel's buffer follows Hchan immediately in memory. // Size of buffer (cap(c)) is second int in the chan struct. - n = ((uintgo*)chan)[1]; - if(n > 0) { + chancap = ((uintgo*)chan)[1]; + if(chancap > 0) { // TODO(atom): split into two chunks so that only the // in-use part of the circular buffer is scanned. // (Channel routines zero the unused part, so the current // code does not lead to leaks, it's just a little inefficient.) - *objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, n*chantype->elem->size, + *objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, chancap*chantype->elem->size, (uintptr)chantype->elem->gc | PRECISE | LOOP}; if(objbufpos == objbuf_end) flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj); diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 018a453d6..31876b62a 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -1232,6 +1232,7 @@ static void goexit0(G *gp) { gp->status = Gdead; + gp->fnstart = nil; gp->m = nil; gp->lockedm = nil; m->curg = nil; diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c index 354c54c86..dd92a59a9 100644 --- a/src/pkg/runtime/slice.c +++ b/src/pkg/runtime/slice.c @@ -48,27 +48,9 @@ uintptr runtime·zerobase; static void makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret) { - uintptr size; - - size = cap*t->elem->size; - ret->len = len; ret->cap = cap; - - if(size == 0) - ret->array = (byte*)&runtime·zerobase; - else if((t->elem->kind&KindNoPointers)) - ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1); - else { - ret->array = runtime·mallocgc(size, 0, 1, 1); - - if(UseSpanType) { - if(false) { - runtime·printf("new slice [%D]%S: %p\n", (int64)cap, *t->elem->string, ret->array); - } - runtime·settype(ret->array, (uintptr)t->elem | TypeInfo_Array); - } - } + ret->array = runtime·cnewarray(t->elem, cap); } // appendslice(type *Type, x, y, []T) []T |