LEFT | RIGHT |
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" |
11 #include "mgc0.h" | 11 #include "mgc0.h" |
12 #include "race.h" | 12 #include "race.h" |
13 #include "type.h" | 13 #include "type.h" |
14 #include "typekind.h" | 14 #include "typekind.h" |
15 #include "hashmap.h" | 15 #include "hashmap.h" |
16 | 16 |
17 enum { | 17 enum { |
18 Debug = 0, | 18 Debug = 0, |
19 DebugMark = 0, // run second pass to check mark | 19 DebugMark = 0, // run second pass to check mark |
20 CollectStats = 0, | 20 CollectStats = 0, |
| 21 ScanStackByFrames = 0, |
21 | 22 |
22 // Four bits per word (see #defines below). | 23 // Four bits per word (see #defines below). |
23 wordsPerBitmapWord = sizeof(void*)*8/4, | 24 wordsPerBitmapWord = sizeof(void*)*8/4, |
24 bitShift = sizeof(void*)*8/4, | 25 bitShift = sizeof(void*)*8/4, |
25 | 26 |
26 handoffThreshold = 4, | 27 handoffThreshold = 4, |
27 IntermediateBufferCapacity = 64, | 28 IntermediateBufferCapacity = 64, |
28 | 29 |
29 // Bits in type information | 30 // Bits in type information |
30 PRECISE = 1, | 31 PRECISE = 1, |
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 runtime·SysFree(work.roots, work.rootcap*sizeof(Obj)); | 1311 runtime·SysFree(work.roots, work.rootcap*sizeof(Obj)); |
1311 } | 1312 } |
1312 work.roots = new; | 1313 work.roots = new; |
1313 work.rootcap = cap; | 1314 work.rootcap = cap; |
1314 } | 1315 } |
1315 work.roots[work.nroot] = obj; | 1316 work.roots[work.nroot] = obj; |
1316 work.nroot++; | 1317 work.nroot++; |
1317 } | 1318 } |
1318 | 1319 |
1319 // Scan a stack frame. The doframe parameter is a signal that the previously | 1320 // Scan a stack frame. The doframe parameter is a signal that the previously |
1320 // scanned activation has an unknown argument size. When doframe is true the | 1321 // scanned activation has an unknown argument size. When *doframe is true the |
1321 // current activation must have its entire frame scanned. Otherwise, only the | 1322 // current activation must have its entire frame scanned. Otherwise, only the |
1322 // locals need to be scanned. | 1323 // locals need to be scanned. |
1323 static void | 1324 static void |
1324 addframeroots(Func *f, byte*, byte *sp, void *doframe) | 1325 addframeroots(Func *f, byte*, byte *sp, void *doframe) |
1325 { | 1326 { |
1326 uintptr outs; | 1327 uintptr outs; |
1327 | 1328 |
1328 if(thechar == '5') | 1329 if(thechar == '5') |
1329 sp += sizeof(uintptr); | 1330 sp += sizeof(uintptr); |
1330 if(f->locals == 0 || *(bool*)doframe == true) | 1331 if(f->locals == 0 || *(bool*)doframe == true) |
1331 addroot((Obj){sp, f->frame - sizeof(uintptr), 0}); | 1332 addroot((Obj){sp, f->frame - sizeof(uintptr), 0}); |
1332 else if(f->locals > 0) { | 1333 else if(f->locals > 0) { |
1333 outs = f->frame - sizeof(uintptr) - f->locals; | 1334 outs = f->frame - sizeof(uintptr) - f->locals; |
1334 addroot((Obj){sp + outs, f->locals, 0}); | 1335 addroot((Obj){sp + outs, f->locals, 0}); |
1335 } | 1336 } |
1336 if(f->args > 0) | 1337 if(f->args > 0) |
1337 addroot((Obj){sp + f->frame, f->args, 0}); | 1338 addroot((Obj){sp + f->frame, f->args, 0}); |
1338 » *(bool*)doframe = (f->args < 0); | 1339 » *(bool*)doframe = (f->args == ArgsSizeUnknown); |
1339 } | 1340 } |
1340 | 1341 |
1341 static void | 1342 static void |
1342 addstackroots(G *gp) | 1343 addstackroots(G *gp) |
1343 { | 1344 { |
1344 M *mp; | 1345 M *mp; |
| 1346 int32 n; |
| 1347 Stktop *stk; |
| 1348 byte *sp, *guard, *pc; |
1345 Func *f; | 1349 Func *f; |
1346 byte *sp, *pc; | |
1347 bool doframe; | 1350 bool doframe; |
| 1351 |
| 1352 stk = (Stktop*)gp->stackbase; |
| 1353 guard = (byte*)gp->stackguard; |
1348 | 1354 |
1349 if(gp == g) { | 1355 if(gp == g) { |
1350 // Scanning our own stack: start at &gp. | 1356 // Scanning our own stack: start at &gp. |
1351 sp = runtime·getcallersp(&gp); | 1357 sp = runtime·getcallersp(&gp); |
1352 pc = runtime·getcallerpc(&gp); | 1358 pc = runtime·getcallerpc(&gp); |
1353 } else if((mp = gp->m) != nil && mp->helpgc) { | 1359 } else if((mp = gp->m) != nil && mp->helpgc) { |
1354 // gchelper's stack is in active use and has no interesting poin
ters. | 1360 // gchelper's stack is in active use and has no interesting poin
ters. |
1355 return; | 1361 return; |
1356 } else if(gp->gcstack != (uintptr)nil) { | 1362 } else if(gp->gcstack != (uintptr)nil) { |
1357 // Scanning another goroutine that is about to enter or might | 1363 // Scanning another goroutine that is about to enter or might |
1358 // have just exited a system call. It may be executing code such | 1364 // have just exited a system call. It may be executing code such |
1359 // as schedlock and may have needed to start a new stack segment
. | 1365 // as schedlock and may have needed to start a new stack segment
. |
1360 // Use the stack segment and stack pointer at the time of | 1366 // Use the stack segment and stack pointer at the time of |
1361 // the system call instead, since that won't change underfoot. | 1367 // the system call instead, since that won't change underfoot. |
1362 sp = (byte*)gp->gcsp; | 1368 sp = (byte*)gp->gcsp; |
1363 pc = gp->gcpc; | 1369 pc = gp->gcpc; |
| 1370 stk = (Stktop*)gp->gcstack; |
| 1371 guard = (byte*)gp->gcguard; |
1364 } else { | 1372 } else { |
1365 // Scanning another goroutine's stack. | 1373 // Scanning another goroutine's stack. |
1366 // The goroutine is usually asleep (the world is stopped). | 1374 // The goroutine is usually asleep (the world is stopped). |
1367 sp = (byte*)gp->sched.sp; | 1375 sp = (byte*)gp->sched.sp; |
1368 pc = gp->sched.pc; | 1376 pc = gp->sched.pc; |
1369 » » if(pc == (byte*)runtime·goexit && gp->fnstart != nil) { | 1377 » » if(ScanStackByFrames && pc == (byte*)runtime·goexit && gp->fnsta
rt != nil) { |
1370 // The goroutine has not started. However, its incoming | 1378 // The goroutine has not started. However, its incoming |
1371 // arguments are live at the top of the stack and must | 1379 // arguments are live at the top of the stack and must |
1372 // be scanned. No other live values should be on the | 1380 // be scanned. No other live values should be on the |
1373 // stack. | 1381 // stack. |
1374 f = runtime·findfunc((uintptr)gp->fnstart->fn); | 1382 f = runtime·findfunc((uintptr)gp->fnstart->fn); |
1375 if(f->args > 0) { | 1383 if(f->args > 0) { |
1376 if(thechar == '5') | 1384 if(thechar == '5') |
1377 sp += sizeof(uintptr); | 1385 sp += sizeof(uintptr); |
1378 addroot((Obj){sp, f->args, 0}); | 1386 addroot((Obj){sp, f->args, 0}); |
1379 } | 1387 } |
1380 return; | 1388 return; |
1381 } | 1389 } |
1382 } | 1390 } |
1383 » doframe = false; | 1391 » if (ScanStackByFrames) { |
1384 » runtime·gentraceback(pc, sp, nil, gp, 0, nil, 0x7fffffff, addframeroots,
&doframe); | 1392 » » doframe = false; |
| 1393 » » runtime·gentraceback(pc, sp, nil, gp, 0, nil, 0x7fffffff, addfra
meroots, &doframe); |
| 1394 » } else { |
| 1395 » » USED(pc); |
| 1396 » » n = 0; |
| 1397 » » while(stk) { |
| 1398 » » » if(sp < guard-StackGuard || (byte*)stk < sp) { |
| 1399 » » » » runtime·printf("scanstack inconsistent: g%D#%d s
p=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk); |
| 1400 » » » » runtime·throw("scanstack"); |
| 1401 » » » } |
| 1402 » » » addroot((Obj){sp, (byte*)stk - sp, (uintptr)defaultProg
| PRECISE | LOOP}); |
| 1403 » » » sp = (byte*)stk->gobuf.sp; |
| 1404 » » » guard = stk->stackguard; |
| 1405 » » » stk = (Stktop*)stk->stackbase; |
| 1406 » » » n++; |
| 1407 » » } |
| 1408 » } |
1385 } | 1409 } |
1386 | 1410 |
1387 static void | 1411 static void |
1388 addfinroots(void *v) | 1412 addfinroots(void *v) |
1389 { | 1413 { |
1390 uintptr size; | 1414 uintptr size; |
1391 void *base; | 1415 void *base; |
1392 | 1416 |
1393 size = 0; | 1417 size = 0; |
1394 if(!runtime·mlookup(v, &base, &size, nil) || !runtime·blockspecial(base)
) | 1418 if(!runtime·mlookup(v, &base, &size, nil) || !runtime·blockspecial(base)
) |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 uintptr n; | 2332 uintptr n; |
2309 | 2333 |
2310 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; | 2334 n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; |
2311 n = (n+bitmapChunk-1) & ~(bitmapChunk-1); | 2335 n = (n+bitmapChunk-1) & ~(bitmapChunk-1); |
2312 if(h->bitmap_mapped >= n) | 2336 if(h->bitmap_mapped >= n) |
2313 return; | 2337 return; |
2314 | 2338 |
2315 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped); | 2339 runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped); |
2316 h->bitmap_mapped = n; | 2340 h->bitmap_mapped = n; |
2317 } | 2341 } |
LEFT | RIGHT |