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

Side by Side Diff: src/cmd/gc/reflect.c

Issue 106260045: code review 106260045: runtime: simpler and faster GC (Closed)
Patch Set: diff -r 2fa7b95cf34c https://dvyukov%40google.com@code.google.com/p/go/ Created 10 years, 8 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:
View unified diff | Download patch
OLDNEW
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 #include <u.h> 5 #include <u.h>
6 #include <libc.h> 6 #include <libc.h>
7 #include "go.h" 7 #include "go.h"
8 #include "../ld/textflag.h" 8 #include "../ld/textflag.h"
9 #include "../../pkg/runtime/mgc0.h" 9 #include "../../pkg/runtime/mgc0.h"
10 #include "../../pkg/runtime/typekind.h"
10 11
11 /* 12 /*
12 * runtime interface and reflection data structures 13 * runtime interface and reflection data structures
13 */ 14 */
14 15
15 static NodeList* signatlist; 16 static NodeList* signatlist;
16 static Sym* dtypesym(Type*); 17 static Sym* dtypesym(Type*);
17 static Sym* weaktypesym(Type*); 18 static Sym* weaktypesym(Type*);
18 static Sym* dalgsym(Type*); 19 static Sym* dalgsym(Type*);
19 static» Sym*» dgcsym(Type*); 20 static» int» usegcprog(Type*);
21 static» void» gengcprog(Type*, Sym**, Sym**);
22 static» void» gengcmask(Type*, uint8[16]);
20 23
21 static int 24 static int
22 sigcmp(Sig *a, Sig *b) 25 sigcmp(Sig *a, Sig *b)
23 { 26 {
24 int i; 27 int i;
25 28
26 i = strcmp(a->name, b->name); 29 i = strcmp(a->name, b->name);
27 if(i != 0) 30 if(i != 0)
28 return i; 31 return i;
29 if(a->pkg == b->pkg) 32 if(a->pkg == b->pkg)
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 ot = duintptr(s, ot, 0); 608 ot = duintptr(s, ot, 0);
606 if(a->tsym) 609 if(a->tsym)
607 ot = dsymptr(s, ot, a->tsym, 0); 610 ot = dsymptr(s, ot, a->tsym, 0);
608 else 611 else
609 ot = duintptr(s, ot, 0); 612 ot = duintptr(s, ot, 0);
610 } 613 }
611 614
612 return ot; 615 return ot;
613 } 616 }
614 617
615 enum {
616 KindBool = 1,
617 KindInt,
618 KindInt8,
619 KindInt16,
620 KindInt32,
621 KindInt64,
622 KindUint,
623 KindUint8,
624 KindUint16,
625 KindUint32,
626 KindUint64,
627 KindUintptr,
628 KindFloat32,
629 KindFloat64,
630 KindComplex64,
631 KindComplex128,
632 KindArray,
633 KindChan,
634 KindFunc,
635 KindInterface,
636 KindMap,
637 KindPtr,
638 KindSlice,
639 KindString,
640 KindStruct,
641 KindUnsafePointer,
642
643 KindNoPointers = 1<<7,
644 };
645
646 static int 618 static int
647 kinds[] = 619 kinds[] =
648 { 620 {
649 [TINT] = KindInt, 621 [TINT] = KindInt,
650 [TUINT] = KindUint, 622 [TUINT] = KindUint,
651 [TINT8] = KindInt8, 623 [TINT8] = KindInt8,
652 [TUINT8] = KindUint8, 624 [TUINT8] = KindUint8,
653 [TINT16] = KindInt16, 625 [TINT16] = KindInt16,
654 [TUINT16] = KindUint16, 626 [TUINT16] = KindUint16,
655 [TINT32] = KindInt32, 627 [TINT32] = KindInt32,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 return ret; 711 return ret;
740 } 712 }
741 713
742 /* 714 /*
743 * commonType 715 * commonType
744 * ../../pkg/runtime/type.go:/commonType 716 * ../../pkg/runtime/type.go:/commonType
745 */ 717 */
746 static int 718 static int
747 dcommontype(Sym *s, int ot, Type *t) 719 dcommontype(Sym *s, int ot, Type *t)
748 { 720 {
749 » int i, alg, sizeofAlg; 721 » int i, alg, sizeofAlg, gcprog;
750 » Sym *sptr, *algsym, *zero; 722 » Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1;
723 » uint8 gcmask[16];
751 static Sym *algarray; 724 static Sym *algarray;
752 char *p; 725 char *p;
753 ········ 726 ········
754 if(ot != 0) 727 if(ot != 0)
755 fatal("dcommontype %d", ot); 728 fatal("dcommontype %d", ot);
756 729
757 sizeofAlg = 4*widthptr; 730 sizeofAlg = 4*widthptr;
758 if(algarray == nil) 731 if(algarray == nil)
759 algarray = pkglookup("algarray", runtimepkg); 732 algarray = pkglookup("algarray", runtimepkg);
760 alg = algtype(t); 733 alg = algtype(t);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 775
803 // runtime (and common sense) expects alignment to be a power of two. 776 // runtime (and common sense) expects alignment to be a power of two.
804 i = t->align; 777 i = t->align;
805 if(i == 0) 778 if(i == 0)
806 i = 1; 779 i = 1;
807 if((i&(i-1)) != 0) 780 if((i&(i-1)) != 0)
808 fatal("invalid alignment %d for %T", t->align, t); 781 fatal("invalid alignment %d for %T", t->align, t);
809 ot = duint8(s, ot, t->align); // align 782 ot = duint8(s, ot, t->align); // align
810 ot = duint8(s, ot, t->align); // fieldAlign 783 ot = duint8(s, ot, t->align); // fieldAlign
811 784
785 gcprog = usegcprog(t);
812 i = kinds[t->etype]; 786 i = kinds[t->etype];
813 if(t->etype == TARRAY && t->bound < 0) 787 if(t->etype == TARRAY && t->bound < 0)
814 i = KindSlice; 788 i = KindSlice;
815 if(!haspointers(t)) 789 if(!haspointers(t))
816 i |= KindNoPointers; 790 i |= KindNoPointers;
791 if(gcprog)
792 i |= KindGCProg;
817 ot = duint8(s, ot, i); // kind 793 ot = duint8(s, ot, i); // kind
818 if(alg >= 0) 794 if(alg >= 0)
819 ot = dsymptr(s, ot, algarray, alg*sizeofAlg); 795 ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
820 else 796 else
821 ot = dsymptr(s, ot, algsym, 0); 797 ot = dsymptr(s, ot, algsym, 0);
822 » ot = dsymptr(s, ot, dgcsym(t), 0); // gc 798 » // gc
799 » if(gcprog) {
800 » » gengcprog(t, &gcprog0, &gcprog1);
801 » » if(gcprog0 != S)
802 » » » ot = dsymptr(s, ot, gcprog0, 0);
803 » » else
804 » » » ot = duintptr(s, ot, 0);
805 » » ot = dsymptr(s, ot, gcprog1, 0);
806 » } else {
807 » » gengcmask(t, gcmask);
808 » » for(i = 0; i < 2*widthptr; i++)
809 » » » ot = duint8(s, ot, gcmask[i]);
810 » }
823 p = smprint("%-uT", t); 811 p = smprint("%-uT", t);
824 //print("dcommontype: %s\n", p); 812 //print("dcommontype: %s\n", p);
825 ot = dgostringptr(s, ot, p); // string 813 ot = dgostringptr(s, ot, p); // string
826 free(p); 814 free(p);
827 815
828 // skip pointer to extraType, 816 // skip pointer to extraType,
829 // which follows the rest of this type structure. 817 // which follows the rest of this type structure.
830 // caller will fill in if needed. 818 // caller will fill in if needed.
831 // otherwise linker will assume 0. 819 // otherwise linker will assume 0.
832 ot += widthptr; 820 ot += widthptr;
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8); 1256 snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
1269 ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0); 1257 ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
1270 break; 1258 break;
1271 } 1259 }
1272 1260
1273 ggloblsym(s, ot, DUPOK|RODATA); 1261 ggloblsym(s, ot, DUPOK|RODATA);
1274 return s; 1262 return s;
1275 } 1263 }
1276 1264
1277 static int 1265 static int
1278 gcinline(Type *t) 1266 usegcprog(Type *t)
1279 { 1267 {
1280 » switch(t->etype) { 1268 » vlong size, nptr;
1281 » case TARRAY: 1269
1282 » » if(t->bound == 1) 1270 » if(!haspointers(t))
1283 » » » return 1; 1271 » » return 0;
1284 » » if(t->width <= 4*widthptr)
1285 » » » return 1;
1286 » » break;
1287 » }
1288 » return 0;
1289 }
1290
1291 static int
1292 dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
1293 {
1294 » Type *t1;
1295 » vlong o, off2, fieldoffset, i;
1296
1297 » if(t->align > 0 && (*off % t->align) != 0)
1298 » » fatal("dgcsym1: invalid initial alignment, %T", t);
1299
1300 if(t->width == BADWIDTH) 1272 if(t->width == BADWIDTH)
1301 dowidth(t); 1273 dowidth(t);
1302 »······· 1274 » // Calculate size of the unrolled GC mask.
1275 » nptr = (t->width+widthptr-1)/widthptr;
1276 » size = nptr;
1277 » if(size%2)
1278 » » size *= 2;» // repeated
1279 » size = size*PointersPerByte/8;» // 4 bits per word
1280 » // Decide whether to use unrolled GC mask or GC program.
1281 » // We could use a more elaborate condition, but this seems to work good in practice.
1282 » // For small objects GC program can't give significant reduction.
1283 » // While large objects usually contain arrays; and even if it don't
1284 » // the program uses 2-bits per word while mask uses 4-bits per word,
1285 » // so the program is still smaller.
1286 » return size > 2*widthptr;
1287 }
1288
1289 // Generates sparse GC bitmask (4 bits per word).
1290 static void
1291 gengcmask(Type *t, uint8 gcmask[16])
1292 {
1293 » Bvec *vec;
1294 » vlong xoffset, nptr, i, j;
1295 » int half, mw;
1296 » uint8 bits, *pos;
1297
1298 » memset(gcmask, 0, 16);
1299 » if(!haspointers(t))
1300 » » return;
1301
1302 » // Generate compact mask as stacks use.
1303 » xoffset = 0;
1304 » vec = bvalloc(2*widthptr*8);
1305 » twobitwalktype1(t, &xoffset, vec);
1306
1307 » // Unfold the mask for the GC bitmap format:
1308 » // 4 bits per word, 2 high bits encode pointer info.
1309 » pos = (uint8*)gcmask;
1310 » nptr = (t->width+widthptr-1)/widthptr;
1311 » half = 0;
1312 » mw = 0;
1313 » // If number of words is odd, repeat the mask.
1314 » // This makes simpler handling of arrays in runtime.
1315 » for(j=0; j<=(nptr%2); j++) {
1316 » » for(i=0; i<nptr; i++) {
1317 » » » bits = bvget(vec, i*BitsPerPointer) | bvget(vec, i*BitsP erPointer+1)<<1;
1318
1319 » » » //bits = ((uint8*)vec->b)[i*BitsPerPointer/8];
rsc 2014/07/23 16:23:20 Delete debugging dregs.
dvyukov 2014/07/23 19:01:44 Done.
1320 » » » //bits >>= (i*BitsPerPointer)%8;
1321 » » » //bits &= (1<<BitsPerPointer)-1;
1322 » » » //print("BITS %d %d [%d %d]\n", bits, (bvget(vec, i*Bits PerPointer)<<1) | bvget(vec, i*BitsPerPointer+1), bvget(vec, i*BitsPerPointer), bvget(vec, i*BitsPerPointer+1));
1323
1324 » » » // Some fake types (e.g. Hmap) has missing fileds.
1325 » » » // twobitwalktype1 generates BitsDead for that holes,
1326 » » » // replace BitsDead with BitsScalar.
1327 » » » if(!mw && bits == BitsDead)
1328 » » » » bits = BitsScalar;
1329 » » » mw = !mw && bits == BitsMultiWord;
1330 » » » bits <<= 2;
1331 » » » if(half)
1332 » » » » bits <<= 4;
1333 » » » *pos |= bits;
1334 » » » half = !half;
1335 » » » if(!half)
1336 » » » » pos++;
1337 » » }
1338 » }
1339 }
1340
1341 // Helper object for generation of GC programs.
1342 typedef struct ProgGen ProgGen;
1343 struct ProgGen
1344 {
1345 » Sym*» s;
1346 » int32» datasize;
1347 » uint8» data[256/PointersPerByte];
1348 » vlong» ot;
1349 };
1350
1351 static void
1352 proggeninit(ProgGen *g, Sym *s)
1353 {
1354 » g->s = s;
1355 » g->datasize = 0;
1356 » g->ot = 0;
1357 » memset(g->data, 0, sizeof(g->data));
1358 }
1359
1360 static void
1361 proggenemit(ProgGen *g, uint8 v)
1362 {
1363 » g->ot = duint8(g->s, g->ot, v);
1364 }
1365
1366 // Emits insData block from g->data.
1367 static void
1368 proggendataflush(ProgGen *g)
1369 {
1370 » int32 i, s;
1371
1372 » if(g->datasize == 0)
1373 » » return;
1374 » proggenemit(g, insData);
1375 » proggenemit(g, g->datasize);
1376 » s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
1377 » for(i = 0; i < s; i++)
1378 » » proggenemit(g, g->data[i]);
1379 » g->datasize = 0;
1380 » memset(g->data, 0, sizeof(g->data));
1381 }
1382
1383 static void
1384 proggendata(ProgGen *g, uint8 d)
1385 {
1386 » g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerBy te)*BitsPerPointer);
1387 » g->datasize++;
1388 » if(g->datasize == 255)
1389 » » proggendataflush(g);
1390 }
1391
1392 // Skip v bytes due to alignment, etc.
1393 static void
1394 proggenskip(ProgGen *g, vlong off, vlong v)
1395 {
1396 » vlong i;
1397
1398 » for(i = off; i < off+v; i++) {
1399 » » if((i%widthptr) == 0)
1400 » » » proggendata(g, BitsScalar);
1401 » }
1402 }
1403
1404 // Emit insArray instruction.
1405 static void
1406 proggenarray(ProgGen *g, vlong len)
1407 {
1408 » int32 i;
1409
1410 » proggendataflush(g);
1411 » proggenemit(g, insArray);
1412 » for(i = 0; i < widthptr; i++, len >>= 8)
1413 » » proggenemit(g, len);
1414 }
1415
1416 static void
1417 proggenarrayend(ProgGen *g)
1418 {
1419 » proggendataflush(g);
1420 » proggenemit(g, insArrayEnd);
1421 }
1422
1423 static vlong
1424 proggenfini(ProgGen *g)
1425 {
1426 » proggendataflush(g);
1427 » proggenemit(g, insEnd);
1428 » return g->ot;
1429 }
1430
1431 static void gengcprog1(ProgGen *g, Type *t, vlong *xoffset);
1432
1433 // Generates GC program for large types.
1434 static void
1435 gengcprog(Type *t, Sym **pgc0, Sym **pgc1)
1436 {
1437 » Sym *gc0, *gc1;
1438 » vlong nptr, size, ot, xoffset;
1439 » ProgGen g;
1440
rsc 2014/07/23 16:23:19 please add g.type = t;
rsc 2014/07/23 16:24:17 Ignore. This was a dreg from a suggestion to detec
dvyukov 2014/07/23 19:01:44 Acknowledged.
1441 » nptr = (t->width+widthptr-1)/widthptr;
1442 » size = nptr;
1443 » if(size%2)
1444 » » size *= 2;» // repeated twice
1445 » size = size*PointersPerByte/8;» // 4 bits per word
1446 » size++;»// unroll flag in the beginning
1447 » // emity space in BSS for unrolled program
1448 » *pgc0 = S;
1449 » // Don't generate it if it's too large, runtime will unroll directly int o GC bitmap.
1450 » if(size <= MaxGCMask) {
1451 » » gc0 = typesymprefix(".gc", t);
1452 » » ggloblsym(gc0, size, DUPOK|NOPTR);
1453 » » *pgc0 = gc0;
1454 » }
1455
1456 » // program in RODATA
1457 » gc1 = typesymprefix(".gcprog", t);
1458 » proggeninit(&g, gc1);
1459 » xoffset = 0;
1460 » gengcprog1(&g, t, &xoffset);
1461 » ot = proggenfini(&g);
1462 » ggloblsym(gc1, ot, DUPOK|RODATA);
1463 » *pgc1 = gc1;
1464 }
1465
1466 // Recursively walks type t and writes GC program into g.
1467 static void
1468 gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
1469 {
1470 » vlong fieldoffset, i, o, n;
1471 » Type *t1;
1472
1303 switch(t->etype) { 1473 switch(t->etype) {
1304 case TINT8: 1474 case TINT8:
1305 case TUINT8: 1475 case TUINT8:
1306 case TINT16: 1476 case TINT16:
1307 case TUINT16: 1477 case TUINT16:
1308 case TINT32: 1478 case TINT32:
1309 case TUINT32: 1479 case TUINT32:
1310 case TINT64: 1480 case TINT64:
1311 case TUINT64: 1481 case TUINT64:
1312 case TINT: 1482 case TINT:
1313 case TUINT: 1483 case TUINT:
1314 case TUINTPTR: 1484 case TUINTPTR:
1315 case TBOOL: 1485 case TBOOL:
1316 case TFLOAT32: 1486 case TFLOAT32:
1317 case TFLOAT64: 1487 case TFLOAT64:
1318 case TCOMPLEX64: 1488 case TCOMPLEX64:
1319 case TCOMPLEX128: 1489 case TCOMPLEX128:
1320 » » *off += t->width; 1490 » » proggenskip(g, *xoffset, t->width);
1491 » » *xoffset += t->width;
1321 break; 1492 break;
1322
1323 case TPTR32: 1493 case TPTR32:
1324 case TPTR64: 1494 case TPTR64:
1325 // NOTE: Any changes here need to be made to reflect.PtrTo as we ll.
1326 if(*off % widthptr != 0)
1327 fatal("dgcsym1: invalid alignment, %T", t);
1328
1329 // NOTE(rsc): Emitting GC_APTR here for *nonptrtype
1330 // (pointer to non-pointer-containing type) means that
1331 // we do not record 'nonptrtype' and instead tell the·
1332 // garbage collector to look up the type of the memory in
1333 // type information stored in the heap. In effect we are telling
1334 // the collector "we don't trust our information - use yours".
1335 // It's not completely clear why we want to do this.
1336 // It does have the effect that if you have a *SliceHeader and a *[]int
1337 // pointing at the same actual slice header, *SliceHeader will n ot be
1338 // used as an authoritative type for the memory, which is good:
1339 // if the collector scanned the memory as type *SliceHeader, it would
1340 // see no pointers inside but mark the block as scanned, prevent ing
1341 // the seeing of pointers when we followed the *[]int pointer.
1342 // Perhaps that kind of situation is the rationale.
1343 if(!haspointers(t->type)) {
1344 ot = duintptr(s, ot, GC_APTR);
1345 ot = duintptr(s, ot, *off);
1346 } else {
1347 ot = duintptr(s, ot, GC_PTR);
1348 ot = duintptr(s, ot, *off);
1349 ot = dsymptr(s, ot, dgcsym(t->type), 0);
1350 }
1351 *off += t->width;
1352 break;
1353
1354 case TUNSAFEPTR: 1495 case TUNSAFEPTR:
1355 case TFUNC: 1496 case TFUNC:
1356 » » if(*off % widthptr != 0) 1497 » case TCHAN:
1357 » » » fatal("dgcsym1: invalid alignment, %T", t); 1498 » case TMAP:
1358 » » ot = duintptr(s, ot, GC_APTR); 1499 » » proggendata(g, BitsPointer);
1359 » » ot = duintptr(s, ot, *off); 1500 » » *xoffset += t->width;
1360 » » *off += t->width;
1361 break; 1501 break;
1362 1502 » case TSTRING:
1363 » // struct Hchan* 1503 » » proggendata(g, BitsMultiWord);
1364 » case TCHAN: 1504 » » proggendata(g, BitsString);
1365 » » // NOTE: Any changes here need to be made to reflect.ChanOf as w ell. 1505 » » *xoffset += t->width;
1366 » » if(*off % widthptr != 0)
1367 » » » fatal("dgcsym1: invalid alignment, %T", t);
1368 » » ot = duintptr(s, ot, GC_CHAN_PTR);
1369 » » ot = duintptr(s, ot, *off);
1370 » » ot = dsymptr(s, ot, dtypesym(t), 0);
1371 » » *off += t->width;
1372 break; 1506 break;
1373 1507 » case TINTER:
1374 » // struct Hmap* 1508 » » proggendata(g, BitsMultiWord);
1375 » case TMAP: 1509 » » if(isnilinter(t))
1376 » » // NOTE: Any changes here need to be made to reflect.MapOf as we ll. 1510 » » » proggendata(g, BitsEface);
1377 » » if(*off % widthptr != 0) 1511 » » else
1378 » » » fatal("dgcsym1: invalid alignment, %T", t); 1512 » » » proggendata(g, BitsIface);
1379 » » ot = duintptr(s, ot, GC_PTR); 1513 » » *xoffset += t->width;
1380 » » ot = duintptr(s, ot, *off);
1381 » » ot = dsymptr(s, ot, dgcsym(hmap(t)), 0);
1382 » » *off += t->width;
1383 break; 1514 break;
1384 1515 » case TARRAY:
1385 » // struct { byte *str; int32 len; } 1516 » » if(isslice(t)) {
1386 » case TSTRING: 1517 » » » proggendata(g, BitsMultiWord);
1387 » » if(*off % widthptr != 0) 1518 » » » proggendata(g, BitsSlice);
1388 » » » fatal("dgcsym1: invalid alignment, %T", t); 1519 » » » proggendata(g, BitsScalar);
1389 » » ot = duintptr(s, ot, GC_STRING);
1390 » » ot = duintptr(s, ot, *off);
1391 » » *off += t->width;
1392 » » break;
1393
1394 » // struct { Itab* tab; void* data; }
1395 » // struct { Type* type; void* data; }» // When isnilinter(t)==true
1396 » case TINTER:
1397 » » if(*off % widthptr != 0)
1398 » » » fatal("dgcsym1: invalid alignment, %T", t);
1399 » » if(isnilinter(t)) {
1400 » » » ot = duintptr(s, ot, GC_EFACE);
1401 » » » ot = duintptr(s, ot, *off);
1402 } else { 1520 } else {
1403 » » » ot = duintptr(s, ot, GC_IFACE); 1521 » » » t1 = t->type;
1404 » » » ot = duintptr(s, ot, *off); 1522 » » » if(t1->width == 0) {
1405 » » } 1523 » » » » // ignore
1406 » » *off += t->width; 1524 » » » } if(t->bound*t1->width < 32*widthptr) {
rsc 2014/07/23 16:23:20 } else if(t->bound <= 1 || t->bound*t1->width < 32
dvyukov 2014/07/23 19:01:44 Done.
1407 » » break; 1525 » » » » for(i = 0; i < t->bound; i++)
1408 1526 » » » » » gengcprog1(g, t1, xoffset);
1409 » case TARRAY: 1527 » » » } else if(!haspointers(t1)) {
1410 » » if(t->bound < -1) 1528 » » » » n = t->width;
1411 » » » fatal("dgcsym1: invalid bound, %T", t); 1529 » » » » n -= -*xoffset&(widthptr-1); // skip to next ptr boundary
1412 » » if(t->type->width == BADWIDTH) 1530 » » » » proggenarray(g, (n+widthptr-1)/widthptr);
1413 » » » dowidth(t->type); 1531 » » » » proggendata(g, BitsScalar);
1414 » » if(isslice(t)) { 1532 » » » » proggenarrayend(g);
1415 » » » // NOTE: Any changes here need to be made to reflect.Sli ceOf as well.
1416 » » » // struct { byte* array; uint32 len; uint32 cap; }
1417 » » » if(*off % widthptr != 0)
1418 » » » » fatal("dgcsym1: invalid alignment, %T", t);
1419 » » » if(t->type->width != 0) {
1420 » » » » ot = duintptr(s, ot, GC_SLICE);
1421 » » » » ot = duintptr(s, ot, *off);
1422 » » » » ot = dsymptr(s, ot, dgcsym(t->type), 0);
1423 } else { 1533 } else {
1424 » » » » ot = duintptr(s, ot, GC_APTR); 1534 » » » » proggenarray(g, t->bound);
1425 » » » » ot = duintptr(s, ot, *off); 1535 » » » » gengcprog1(g, t1, xoffset);
1426 » » » } 1536 » » » » *xoffset += (t->bound-1)*t1->width;
1427 » » » *off += t->width; 1537 » » » » proggenarrayend(g);
1428 » » } else {
1429 » » » // NOTE: Any changes here need to be made to reflect.Arr ayOf as well,
1430 » » » // at least once ArrayOf's gc info is implemented and Ar rayOf is exported.
1431 » » » // struct { byte* array; uint32 len; uint32 cap; }
1432 » » » if(t->bound < 1 || !haspointers(t->type)) {
1433 » » » » *off += t->width;
1434 » » » } else if(gcinline(t)) {
1435 » » » » for(i=0; i<t->bound; i++)
1436 » » » » » ot = dgcsym1(s, ot, t->type, off, stack_ size); // recursive call of dgcsym1
1437 » » » } else {
1438 » » » » if(stack_size < GC_STACK_CAPACITY) {
1439 » » » » » ot = duintptr(s, ot, GC_ARRAY_START); / / a stack push during GC
1440 » » » » » ot = duintptr(s, ot, *off);
1441 » » » » » ot = duintptr(s, ot, t->bound);
1442 » » » » » ot = duintptr(s, ot, t->type->width);
1443 » » » » » off2 = 0;
1444 » » » » » ot = dgcsym1(s, ot, t->type, &off2, stac k_size+1); // recursive call of dgcsym1
1445 » » » » » ot = duintptr(s, ot, GC_ARRAY_NEXT); // a stack pop during GC
1446 » » » » } else {
1447 » » » » » ot = duintptr(s, ot, GC_REGION);
1448 » » » » » ot = duintptr(s, ot, *off);
1449 » » » » » ot = duintptr(s, ot, t->width);
1450 » » » » » ot = dsymptr(s, ot, dgcsym(t), 0);
1451 » » » » }
1452 » » » » *off += t->width;
1453 } 1538 }
1454 } 1539 }
1455 break; 1540 break;
1456
1457 case TSTRUCT: 1541 case TSTRUCT:
1458 o = 0; 1542 o = 0;
1459 » » for(t1=t->type; t1!=T; t1=t1->down) { 1543 » » for(t1 = t->type; t1 != T; t1 = t1->down) {
1460 fieldoffset = t1->width; 1544 fieldoffset = t1->width;
1461 » » » *off += fieldoffset - o; 1545 » » » proggenskip(g, *xoffset, fieldoffset - o);
1462 » » » ot = dgcsym1(s, ot, t1->type, off, stack_size); // recu rsive call of dgcsym1 1546 » » » *xoffset += fieldoffset - o;
1547 » » » gengcprog1(g, t1->type, xoffset);
1463 o = fieldoffset + t1->type->width; 1548 o = fieldoffset + t1->type->width;
1464 } 1549 }
1465 » » *off += t->width - o; 1550 » » proggenskip(g, *xoffset, t->width - o);
1551 » » *xoffset += t->width - o;
1466 break; 1552 break;
1467
1468 default: 1553 default:
1469 » » fatal("dgcsym1: unexpected type %T", t); 1554 » » fatal("gengcprog1: unexpected type, %T", t);
1470 } 1555 }
1471
1472 return ot;
1473 } 1556 }
1474
1475 static Sym*
1476 dgcsym(Type *t)
1477 {
1478 int ot;
1479 vlong off;
1480 Sym *s;
1481
1482 s = typesymprefix(".gc", t);
1483 if(s->flags & SymGcgen)
1484 return s;
1485 s->flags |= SymGcgen;
1486
1487 if(t->width == BADWIDTH)
1488 dowidth(t);
1489
1490 ot = 0;
1491 off = 0;
1492 ot = duintptr(s, ot, t->width);
1493 ot = dgcsym1(s, ot, t, &off, 0);
1494 ot = duintptr(s, ot, GC_END);
1495 ggloblsym(s, ot, DUPOK|RODATA);
1496
1497 if(t->align > 0)
1498 off = rnd(off, t->align);
1499 if(off != t->width)
1500 fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t);
1501
1502 return s;
1503 }
OLDNEW
« no previous file with comments | « src/cmd/gc/plive.c ('k') | src/cmd/ld/data.c » ('j') | src/pkg/runtime/chan.h » ('J')

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