Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1484)

Delta Between Two Patch Sets: src/pkg/runtime/mgc0.c

Issue 12328044: code review 12328044: cmd/cc, cmd/gc, runtime: emit bitmaps for scanning locals. (Closed)
Left Patch Set: diff -r d656f46cfb72 https://code.google.com/p/go/ Created 11 years, 7 months ago
Right Patch Set: diff -r 6058f523a441 https://code.google.com/p/go/ Created 11 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/funcdata.h ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Garbage collector. 5 // Garbage collector.
6 6
7 #include "runtime.h" 7 #include "runtime.h"
8 #include "arch_GOARCH.h" 8 #include "arch_GOARCH.h"
9 #include "malloc.h" 9 #include "malloc.h"
10 #include "stack.h" 10 #include "stack.h"
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 } 1380 }
1381 work.roots = new; 1381 work.roots = new;
1382 work.rootcap = cap; 1382 work.rootcap = cap;
1383 } 1383 }
1384 work.roots[work.nroot] = obj; 1384 work.roots[work.nroot] = obj;
1385 work.nroot++; 1385 work.nroot++;
1386 } 1386 }
1387 1387
1388 extern byte pclntab[]; // base for f->ptrsoff 1388 extern byte pclntab[]; // base for f->ptrsoff
1389 1389
1390 typedef struct BitVector BitVector;
1390 struct BitVector 1391 struct BitVector
1391 { 1392 {
1392 int32 n; 1393 int32 n;
1393 uint32 data[]; 1394 uint32 data[];
1394 }; 1395 };
1395 typedef struct BitVector BitVector;
1396 1396
1397 // Starting from scanp, scans words corresponding to set bits. 1397 // Starting from scanp, scans words corresponding to set bits.
1398 static void 1398 static void
1399 scanbitvector(byte* scanp, BitVector *bv) 1399 scanbitvector(byte *scanp, BitVector *bv)
1400 { 1400 {
1401 » int32 i, j, remptrs; 1401 » uint32 *wp;
1402 » uint32 w, b; 1402 » uint32 w;
1403 1403 » int32 i, remptrs;
1404 » for(i = 0, remptrs = bv->n; i < bv->n; i++) { 1404
1405 » » w = bv->data[i]; 1405 » wp = bv->data;
1406 » » b = 1; 1406 » for(remptrs = bv->n; remptrs > 0; remptrs -= 32) {
1407 » » j = remptrs; 1407 » » w = *wp++;
1408 » » if(j > 32) 1408 » » if(remptrs < 32)
1409 » » » j = 32; 1409 » » » i = remptrs;
1410 » » for(; j > 0; j--) { 1410 » » else
1411 » » » if(w & b) { 1411 » » » i = 32;
1412 » » for(; i > 0; i--) {
1413 » » » if(w & 1)
1412 addroot((Obj){scanp, PtrSize, 0}); 1414 addroot((Obj){scanp, PtrSize, 0});
1413 » » » } 1415 » » » w >>= 1;
1414 » » » b <<= 1;
1415 scanp += PtrSize; 1416 scanp += PtrSize;
1416 } 1417 }
1417 remptrs -= 32;
1418 } 1418 }
1419 } 1419 }
1420 1420
1421 // Scan a stack frame: local variables and function arguments/results. 1421 // Scan a stack frame: local variables and function arguments/results.
1422 static void 1422 static void
1423 addframeroots(Stkframe *frame, void*) 1423 addframeroots(Stkframe *frame, void*)
1424 { 1424 {
1425 Func *f; 1425 Func *f;
1426 byte *scanp;
1427 BitVector *args, *locals; 1426 BitVector *args, *locals;
1428 » intptr sz; 1427 » uintptr size;
1429 1428
1430 f = frame->fn; 1429 f = frame->fn;
1431 1430
1432 // Scan local variables if stack frame has been allocated. 1431 // Scan local variables if stack frame has been allocated.
1433 // Use pointer information if known. 1432 // Use pointer information if known.
1434 » sz = frame->varp - (byte*)frame->sp; 1433 » if(frame->varp > (byte*)frame->sp) {
1435 » if(sz > 0) { 1434 » » locals = runtime·funcdata(f, FUNCDATA_GCLocals);
1436 » » locals = runtime·funcdata(f, FUNCDATA_GCLOCALS);
1437 if(locals == nil) { 1435 if(locals == nil) {
1438 » » » addroot((Obj){frame->varp - sz, sz, 0}); 1436 » » » // No locals information, scan everything.
1439 » » } else if(locals->n >= 0) { 1437 » » » size = frame->varp - (byte*)frame->sp;
1440 » » » if(locals->n > 0) { 1438 » » » addroot((Obj){frame->varp - size, size, 0});
1441 » » » » scanp = frame->varp - locals->n*PtrSize; 1439 » » } else if(locals->n < 0) {
1442 » » » » scanbitvector(scanp, locals); 1440 » » » // Locals size information, scan just the
1443 » » » } 1441 » » » // locals.
1444 » » } else { 1442 » » » size = -locals->n;
1445 » » » addroot((Obj){frame->varp - -locals->n, -locals->n, 0}); 1443 » » » addroot((Obj){frame->varp - size, size, 0});
1444 » » } else if(locals->n > 0) {
1445 » » » // Locals bitmap information, scan just the
1446 » » » // pointers in locals.
1447 » » » size = locals->n*PtrSize;
1448 » » » scanbitvector(frame->varp - size, locals);
1446 } 1449 }
1447 } 1450 }
1448 1451
1449 // Scan arguments. 1452 // Scan arguments.
1450 // Use pointer information if known. 1453 // Use pointer information if known.
1451 » args = runtime·funcdata(f, FUNCDATA_GCARGS); 1454 » args = runtime·funcdata(f, FUNCDATA_GCArgs);
1452 » if(f->args > 0 && args != nil && args->n > 0) { 1455 » if(args != nil && args->n > 0)
1453 » » scanp = frame->argp; 1456 » » scanbitvector(frame->argp, args);
1454 » » scanbitvector(scanp, args); 1457 » else
1455 » } else
1456 addroot((Obj){frame->argp, frame->arglen, 0}); 1458 addroot((Obj){frame->argp, frame->arglen, 0});
1457 } 1459 }
1458 1460
1459 static void 1461 static void
1460 addstackroots(G *gp) 1462 addstackroots(G *gp)
1461 { 1463 {
1462 M *mp; 1464 M *mp;
1463 int32 n; 1465 int32 n;
1464 Stktop *stk; 1466 Stktop *stk;
1465 uintptr sp, guard, pc, lr; 1467 uintptr sp, guard, pc, lr;
1466 void *base; 1468 void *base;
1467 uintptr size; 1469 uintptr size;
1468 1470
1469 stk = (Stktop*)gp->stackbase; 1471 stk = (Stktop*)gp->stackbase;
1470 guard = gp->stackguard; 1472 guard = gp->stackguard;
1471 1473
1472 if(gp == g) 1474 if(gp == g)
1473 runtime·throw("can't scan our own stack"); 1475 runtime·throw("can't scan our own stack");
1474 if((mp = gp->m) != nil && mp->helpgc) 1476 if((mp = gp->m) != nil && mp->helpgc)
1475 runtime·throw("can't scan gchelper stack"); 1477 runtime·throw("can't scan gchelper stack");
1476 » if(gp->gcstack != (uintptr)nil) { 1478 » if(gp->syscallstack != (uintptr)nil) {
1477 // Scanning another goroutine that is about to enter or might 1479 // Scanning another goroutine that is about to enter or might
1478 // have just exited a system call. It may be executing code such 1480 // have just exited a system call. It may be executing code such
1479 // as schedlock and may have needed to start a new stack segment . 1481 // as schedlock and may have needed to start a new stack segment .
1480 // Use the stack segment and stack pointer at the time of 1482 // Use the stack segment and stack pointer at the time of
1481 // the system call instead, since that won't change underfoot. 1483 // the system call instead, since that won't change underfoot.
1482 » » sp = gp->gcsp; 1484 » » sp = gp->syscallsp;
1483 » » pc = gp->gcpc; 1485 » » pc = gp->syscallpc;
1484 lr = 0; 1486 lr = 0;
1485 » » stk = (Stktop*)gp->gcstack; 1487 » » stk = (Stktop*)gp->syscallstack;
1486 » » guard = gp->gcguard; 1488 » » guard = gp->syscallguard;
1487 } else { 1489 } else {
1488 // Scanning another goroutine's stack. 1490 // Scanning another goroutine's stack.
1489 // The goroutine is usually asleep (the world is stopped). 1491 // The goroutine is usually asleep (the world is stopped).
1490 sp = gp->sched.sp; 1492 sp = gp->sched.sp;
1491 pc = gp->sched.pc; 1493 pc = gp->sched.pc;
1492 lr = gp->sched.lr; 1494 lr = gp->sched.lr;
1493 1495
1494 // For function about to start, context argument is a root too. 1496 // For function about to start, context argument is a root too.
1495 if(gp->sched.ctxt != 0 && runtime·mlookup(gp->sched.ctxt, &base, &size, nil)) 1497 if(gp->sched.ctxt != 0 && runtime·mlookup(gp->sched.ctxt, &base, &size, nil))
1496 addroot((Obj){base, size, 0}); 1498 addroot((Obj){base, size, 0});
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2093 M *mp; 2095 M *mp;
2094 uint32 i; 2096 uint32 i;
2095 Eface eface; 2097 Eface eface;
2096 2098
2097 t0 = args->start_time; 2099 t0 = args->start_time;
2098 2100
2099 if(CollectStats) 2101 if(CollectStats)
2100 runtime·memclr((byte*)&gcstats, sizeof(gcstats)); 2102 runtime·memclr((byte*)&gcstats, sizeof(gcstats));
2101 2103
2102 for(mp=runtime·allm; mp; mp=mp->alllink) 2104 for(mp=runtime·allm; mp; mp=mp->alllink)
2103 » » runtime·settype_flush(mp, false); 2105 » » runtime·settype_flush(mp);
2104 2106
2105 heap0 = 0; 2107 heap0 = 0;
2106 obj0 = 0; 2108 obj0 = 0;
2107 if(runtime·debug.gctrace) { 2109 if(runtime·debug.gctrace) {
2108 updatememstats(nil); 2110 updatememstats(nil);
2109 heap0 = mstats.heap_alloc; 2111 heap0 = mstats.heap_alloc;
2110 obj0 = mstats.nmalloc - mstats.nfree; 2112 obj0 = mstats.nmalloc - mstats.nfree;
2111 } 2113 }
2112 2114
2113 m->locks++; // disable gc during mallocs in parforalloc 2115 m->locks++; // disable gc during mallocs in parforalloc
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 2358
2357 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset 2359 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
2358 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1; 2360 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
2359 shift = off % wordsPerBitmapWord; 2361 shift = off % wordsPerBitmapWord;
2360 2362
2361 for(;;) { 2363 for(;;) {
2362 obits = *b; 2364 obits = *b;
2363 bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift); 2365 bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift);
2364 if(noptr) 2366 if(noptr)
2365 bits |= bitNoPointers<<shift; 2367 bits |= bitNoPointers<<shift;
2366 » » if(runtime·singleproc) { 2368 » » if(runtime·gomaxprocs == 1) {
2367 *b = bits; 2369 *b = bits;
2368 break; 2370 break;
2369 } else { 2371 } else {
2370 // more than one goroutine is potentially running: use a tomic op 2372 // more than one goroutine is potentially running: use a tomic op
2371 if(runtime·casp((void**)b, (void*)obits, (void*)bits)) 2373 if(runtime·casp((void**)b, (void*)obits, (void*)bits))
2372 break; 2374 break;
2373 } 2375 }
2374 } 2376 }
2375 } 2377 }
2376 2378
2377 // mark the block at v of size n as freed. 2379 // mark the block at v of size n as freed.
2378 void 2380 void
2379 runtime·markfreed(void *v, uintptr n) 2381 runtime·markfreed(void *v, uintptr n)
2380 { 2382 {
2381 uintptr *b, obits, bits, off, shift; 2383 uintptr *b, obits, bits, off, shift;
2382 2384
2383 if(0) 2385 if(0)
2384 runtime·printf("markallocated %p+%p\n", v, n); 2386 runtime·printf("markallocated %p+%p\n", v, n);
2385 2387
2386 if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mh eap.arena_start) 2388 if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mh eap.arena_start)
2387 runtime·throw("markallocated: bad pointer"); 2389 runtime·throw("markallocated: bad pointer");
2388 2390
2389 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset 2391 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
2390 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1; 2392 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
2391 shift = off % wordsPerBitmapWord; 2393 shift = off % wordsPerBitmapWord;
2392 2394
2393 for(;;) { 2395 for(;;) {
2394 obits = *b; 2396 obits = *b;
2395 bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift); 2397 bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
2396 » » if(runtime·singleproc) { 2398 » » if(runtime·gomaxprocs == 1) {
2397 *b = bits; 2399 *b = bits;
2398 break; 2400 break;
2399 } else { 2401 } else {
2400 // more than one goroutine is potentially running: use a tomic op 2402 // more than one goroutine is potentially running: use a tomic op
2401 if(runtime·casp((void**)b, (void*)obits, (void*)bits)) 2403 if(runtime·casp((void**)b, (void*)obits, (void*)bits))
2402 break; 2404 break;
2403 } 2405 }
2404 } 2406 }
2405 } 2407 }
2406 2408
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2506 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; 2508 off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;
2507 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1; 2509 b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
2508 shift = off % wordsPerBitmapWord; 2510 shift = off % wordsPerBitmapWord;
2509 2511
2510 for(;;) { 2512 for(;;) {
2511 obits = *b; 2513 obits = *b;
2512 if(s) 2514 if(s)
2513 bits = obits | (bitSpecial<<shift); 2515 bits = obits | (bitSpecial<<shift);
2514 else 2516 else
2515 bits = obits & ~(bitSpecial<<shift); 2517 bits = obits & ~(bitSpecial<<shift);
2516 » » if(runtime·singleproc) { 2518 » » if(runtime·gomaxprocs == 1) {
2517 *b = bits; 2519 *b = bits;
2518 break; 2520 break;
2519 } else { 2521 } else {
2520 // more than one goroutine is potentially running: use a tomic op 2522 // more than one goroutine is potentially running: use a tomic op
2521 if(runtime·casp((void**)b, (void*)obits, (void*)bits)) 2523 if(runtime·casp((void**)b, (void*)obits, (void*)bits))
2522 break; 2524 break;
2523 } 2525 }
2524 } 2526 }
2525 } 2527 }
2526 2528
2527 void 2529 void
2528 runtime·MHeap_MapBits(MHeap *h) 2530 runtime·MHeap_MapBits(MHeap *h)
2529 { 2531 {
2530 // Caller has added extra mappings to the arena. 2532 // Caller has added extra mappings to the arena.
2531 // Add extra mappings of bitmap words as needed. 2533 // Add extra mappings of bitmap words as needed.
2532 // We allocate extra bitmap pieces in chunks of bitmapChunk. 2534 // We allocate extra bitmap pieces in chunks of bitmapChunk.
2533 enum { 2535 enum {
2534 bitmapChunk = 8192 2536 bitmapChunk = 8192
2535 }; 2537 };
2536 uintptr n; 2538 uintptr n;
2537 2539
2538 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; 2540 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
2539 n = ROUND(n, bitmapChunk); 2541 n = ROUND(n, bitmapChunk);
2540 if(h->bitmap_mapped >= n) 2542 if(h->bitmap_mapped >= n)
2541 return; 2543 return;
2542 2544
2543 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped); 2545 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped);
2544 h->bitmap_mapped = n; 2546 h->bitmap_mapped = n;
2545 } 2547 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b