Left: | ||
Right: |
OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |