Changeset 15374


Ignore:
Timestamp:
May 23, 2012, 10:00:51 AM (7 years ago)
Author:
gb
Message:

Maintain a single version of mark_memoized_area().
In mark_memoized_area(), fix another fencepost (don't reference bitsp
if we're already past the end; it can end on a page boundary.)

The same bug existed (with the same symptom) in mark_managed_static_refs(),
and was fixed around a year ago.

Fixes ticket:972.

Location:
trunk/source/lisp-kernel
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/lisp-kernel/arm-gc.c

    r15367 r15374  
    790790
    791791
    792 void
    793 mark_memoized_area(area *a, natural num_memo_dnodes)
    794 {
    795   bitvector refbits = a->refbits;
    796   LispObj *p = (LispObj *) a->low, x1, x2;
    797   natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    798   Boolean keep_x1, keep_x2;
    799   natural hash_dnode_limit = 0;
    800   hash_table_vector_header *hashp = NULL;
    801   int mark_method = 3;
    802 
    803   if (num_memo_dnodes) {
    804     if (GCDebug) {
    805       check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    806     }
    807 
    808     /* The distinction between "inbits" and "outbits" is supposed to help us
    809        detect cases where "uninteresting" setfs have been memoized.  Storing
    810        NIL, fixnums, immediates (characters, etc.) or node pointers to static
    811        or readonly areas is definitely uninteresting, but other cases are
    812        more complicated (and some of these cases are hard to detect.)
    813 
    814        Some headers are "interesting", to the forwarder if not to us.
    815 
    816     */
    817 
    818     /*
    819       We need to ensure that there are no bits set at or beyond
    820       "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
    821       tenures/untenures things.)  We find bits by grabbing a fullword at
    822       a time and doing a cntlzw instruction; and don't want to have to
    823       check for (< memo_dnode num_memo_dnodes) in the loop.
    824     */
    825 
    826     {
    827       natural
    828         bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
    829         index_of_last_word = (num_memo_dnodes >> bitmap_shift);
    830 
    831       if (bits_in_last_word != 0) {
    832         natural mask = ~((1L<<(nbits_in_word-bits_in_last_word))-1L);
    833         refbits[index_of_last_word] &= mask;
    834       }
    835     }
    836        
    837     set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
    838     inbits = outbits = bits;
    839     while (memo_dnode < num_memo_dnodes) {
    840       if (bits == 0) {
    841         int remain = nbits_in_word - bitidx;
    842         memo_dnode += remain;
    843         p += (remain+remain);
    844         if (outbits != inbits) {
    845           *bitsp = outbits;
    846         }
    847         bits = *++bitsp;
    848         inbits = outbits = bits;
    849         bitidx = 0;
    850       } else {
    851         nextbit = count_leading_zeros(bits);
    852         if ((diff = (nextbit - bitidx)) != 0) {
    853           memo_dnode += diff;
    854           bitidx = nextbit;
    855           p += (diff+diff);
    856         }
    857         x1 = *p++;
    858         x2 = *p++;
    859         bits &= ~(BIT0_MASK >> bitidx);
    860 
    861         if (hashp) {
    862           Boolean force_x1 = false;
    863           if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
    864             /* if vector_header_count is odd, x1 might be the last word of the header */
    865             force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
    866             /* was marking header, switch to data */
    867             hash_dnode_limit = area_dnode(((LispObj *)hashp)
    868                                           + 1
    869                                           + header_element_count(hashp->header),
    870                                           a->low);
    871             /* In traditional weak method, don't mark vector entries at all. */
    872             /* Otherwise mark the non-weak elements only */
    873             mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
    874                            ((hashp->flags & nhash_weak_value_mask)
    875                             ? (1 + (hash_table_vector_header_count & 1))
    876                             : (2 - (hash_table_vector_header_count & 1))));
    877           }
    878 
    879           if (memo_dnode < hash_dnode_limit) {
    880             /* perhaps ignore one or both of the elements */
    881             if (!force_x1 && !(mark_method & 1)) x1 = 0;
    882             if (!(mark_method & 2)) x2 = 0;
    883           } else {
    884             hashp = NULL;
    885           }
    886         }
    887 
    888         if (header_subtag(x1) == subtag_hash_vector) {
    889           if (hashp) Bug(NULL, "header inside hash vector?");
    890           hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
    891           if (hp->flags & nhash_weak_mask) {
    892             /* Workaround for ticket:817 */
    893             if (!(hp->flags & nhash_weak_value_mask)) {
    894               /* If header_count is odd, this cuts off the last header field */
    895               /* That case is handled specially above */
    896               hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
    897               hashp = hp;
    898               mark_method = 3;
    899             }
    900           }
    901         }
    902 
    903         keep_x1 = mark_ephemeral_root(x1);
    904         keep_x2 = mark_ephemeral_root(x2);
    905         if ((keep_x1 == false) &&
    906             (keep_x2 == false) &&
    907             (hashp == NULL)) {
    908           outbits &= ~(BIT0_MASK >> bitidx);
    909         }
    910         memo_dnode++;
    911         bitidx++;
    912       }
    913     }
    914     if (GCDebug) {
    915       p = (LispObj *) a->low;
    916       check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    917     }
    918   }
    919 }
     792
    920793
    921794
  • trunk/source/lisp-kernel/gc-common.c

    r15366 r15374  
    13541354}
    13551355
     1356void
     1357mark_memoized_area(area *a, natural num_memo_dnodes)
     1358{
     1359  bitvector refbits = a->refbits;
     1360  LispObj *p = (LispObj *) a->low, x1, x2;
     1361  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
     1362  Boolean keep_x1, keep_x2;
     1363  natural hash_dnode_limit = 0;
     1364  hash_table_vector_header *hashp = NULL;
     1365  int mark_method = 3;
     1366
     1367  if (num_memo_dnodes) {
     1368    if (GCDebug) {
     1369      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
     1370    }
     1371
     1372    /* The distinction between "inbits" and "outbits" is supposed to help us
     1373       detect cases where "uninteresting" setfs have been memoized.  Storing
     1374       NIL, fixnums, immediates (characters, etc.) or node pointers to static
     1375       or readonly areas is definitely uninteresting, but other cases are
     1376       more complicated (and some of these cases are hard to detect.)
     1377
     1378       Some headers are "interesting", to the forwarder if not to us.
     1379
     1380    */
     1381
     1382    /*
     1383      We need to ensure that there are no bits set at or beyond
     1384      "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
     1385      tenures/untenures things.)  We find bits by grabbing a fullword at
     1386      a time and doing a cntlzw instruction; and don't want to have to
     1387      check for (< memo_dnode num_memo_dnodes) in the loop.
     1388    */
     1389
     1390    {
     1391      natural
     1392        bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
     1393        index_of_last_word = (num_memo_dnodes >> bitmap_shift);
     1394
     1395      if (bits_in_last_word != 0) {
     1396        natural mask = ~((NATURAL1<<(nbits_in_word-bits_in_last_word))- NATURAL1);
     1397        refbits[index_of_last_word] &= mask;
     1398      }
     1399    }
     1400       
     1401    set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
     1402    inbits = outbits = bits;
     1403    while (memo_dnode < num_memo_dnodes) {
     1404      if (bits == 0) {
     1405        int remain = nbits_in_word - bitidx;
     1406        memo_dnode += remain;
     1407        p += (remain+remain);
     1408        if (outbits != inbits) {
     1409          *bitsp = outbits;
     1410        }
     1411        if (memo_dnode < num_memo_dnodes) {
     1412          bits = *++bitsp;
     1413        }
     1414        inbits = outbits = bits;
     1415        bitidx = 0;
     1416      } else {
     1417        nextbit = count_leading_zeros(bits);
     1418        if ((diff = (nextbit - bitidx)) != 0) {
     1419          memo_dnode += diff;
     1420          bitidx = nextbit;
     1421          p += (diff+diff);
     1422        }
     1423        x1 = *p++;
     1424        x2 = *p++;
     1425        bits &= ~(BIT0_MASK >> bitidx);
     1426
     1427
     1428        if (hashp) {
     1429          Boolean force_x1 = false;
     1430          if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
     1431            /* if vector_header_count is odd, x1 might be the last word of the header */
     1432            force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
     1433            /* was marking header, switch to data */
     1434            hash_dnode_limit = area_dnode(((LispObj *)hashp)
     1435                                          + 1
     1436                                          + header_element_count(hashp->header),
     1437                                          a->low);
     1438            /* In traditional weak method, don't mark vector entries at all. */
     1439            /* Otherwise mark the non-weak elements only */
     1440            mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
     1441                           ((hashp->flags & nhash_weak_value_mask)
     1442                            ? (1 + (hash_table_vector_header_count & 1))
     1443                            : (2 - (hash_table_vector_header_count & 1))));
     1444          }
     1445
     1446          if (memo_dnode < hash_dnode_limit) {
     1447            /* perhaps ignore one or both of the elements */
     1448            if (!force_x1 && !(mark_method & 1)) x1 = 0;
     1449            if (!(mark_method & 2)) x2 = 0;
     1450          } else {
     1451            hashp = NULL;
     1452          }
     1453        }
     1454
     1455        if (header_subtag(x1) == subtag_hash_vector) {
     1456          if (hashp) Bug(NULL, "header inside hash vector?");
     1457          hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
     1458          if (hp->flags & nhash_weak_mask) {
     1459            /* Work around the issue that seems to cause ticket:817,
     1460               which is that tenured hash vectors that are weak on value
     1461               aren't always maintained on GCweakvll.  If they aren't and
     1462               we process them weakly here, nothing will delete the unreferenced
     1463               elements. */
     1464            if (!(hp->flags & nhash_weak_value_mask)) {
     1465              /* If header_count is odd, this cuts off the last header field */
     1466              /* That case is handled specially above */
     1467              hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
     1468              hashp = hp;
     1469              mark_method = 3;
     1470            }
     1471          }
     1472        }
     1473
     1474        keep_x1 = mark_ephemeral_root(x1);
     1475        keep_x2 = mark_ephemeral_root(x2);
     1476        if ((keep_x1 == false) &&
     1477            (keep_x2 == false) &&
     1478            (hashp == NULL)) {
     1479          outbits &= ~(BIT0_MASK >> bitidx);
     1480        }
     1481        memo_dnode++;
     1482        bitidx++;
     1483      }
     1484    }
     1485    if (GCDebug) {
     1486      p = (LispObj *) a->low;
     1487      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
     1488    }
     1489  }
     1490}
     1491
    13561492extern void zero_dnodes(void *,natural);
    13571493
  • trunk/source/lisp-kernel/ppc-gc.c

    r14723 r15374  
    906906
    907907
    908 void
    909 mark_memoized_area(area *a, natural num_memo_dnodes)
    910 {
    911   bitvector refbits = a->refbits;
    912   LispObj *p = (LispObj *) a->low, x1, x2;
    913   natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    914   Boolean keep_x1, keep_x2;
    915   natural hash_dnode_limit = 0;
    916   hash_table_vector_header *hashp = NULL;
    917   int mark_method = 3;
    918 
    919   if (GCDebug) {
    920     check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    921   }
    922 
    923   /* The distinction between "inbits" and "outbits" is supposed to help us
    924      detect cases where "uninteresting" setfs have been memoized.  Storing
    925      NIL, fixnums, immediates (characters, etc.) or node pointers to static
    926      or readonly areas is definitely uninteresting, but other cases are
    927      more complicated (and some of these cases are hard to detect.)
    928 
    929      Some headers are "interesting", to the forwarder if not to us.
    930 
    931   */
    932 
    933   /*
    934     We need to ensure that there are no bits set at or beyond
    935     "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
    936     tenures/untenures things.)  We find bits by grabbing a fullword at
    937     a time and doing a cntlzw instruction; and don't want to have to
    938     check for (< memo_dnode num_memo_dnodes) in the loop.
    939   */
    940 
    941   {
    942     natural
    943       bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
    944       index_of_last_word = (num_memo_dnodes >> bitmap_shift);
    945 
    946     if (bits_in_last_word != 0) {
    947       natural mask = ~((1L<<(nbits_in_word-bits_in_last_word))-1L);
    948       refbits[index_of_last_word] &= mask;
    949     }
    950   }
    951        
    952   set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
    953   inbits = outbits = bits;
    954   while (memo_dnode < num_memo_dnodes) {
    955     if (bits == 0) {
    956       int remain = nbits_in_word - bitidx;
    957       memo_dnode += remain;
    958       p += (remain+remain);
    959       if (outbits != inbits) {
    960         *bitsp = outbits;
    961       }
    962       bits = *++bitsp;
    963       inbits = outbits = bits;
    964       bitidx = 0;
    965     } else {
    966       nextbit = count_leading_zeros(bits);
    967       if ((diff = (nextbit - bitidx)) != 0) {
    968         memo_dnode += diff;
    969         bitidx = nextbit;
    970         p += (diff+diff);
    971       }
    972       x1 = *p++;
    973       x2 = *p++;
    974       bits &= ~(BIT0_MASK >> bitidx);
    975 
    976       if (hashp) {
    977         Boolean force_x1 = false;
    978         if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
    979           /* if vector_header_count is odd, x1 might be the last word of the header */
    980           force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
    981           /* was marking header, switch to data */
    982           hash_dnode_limit = area_dnode(((LispObj *)hashp)
    983                                         + 1
    984                                         + header_element_count(hashp->header),
    985                                         a->low);
    986           /* In traditional weak method, don't mark vector entries at all. */
    987           /* Otherwise mark the non-weak elements only */
    988           mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
    989                          ((hashp->flags & nhash_weak_value_mask)
    990                           ? (1 + (hash_table_vector_header_count & 1))
    991                           : (2 - (hash_table_vector_header_count & 1))));
    992         }
    993 
    994         if (memo_dnode < hash_dnode_limit) {
    995           /* perhaps ignore one or both of the elements */
    996           if (!force_x1 && !(mark_method & 1)) x1 = 0;
    997           if (!(mark_method & 2)) x2 = 0;
    998         } else {
    999           hashp = NULL;
    1000         }
    1001       }
    1002 
    1003       if (header_subtag(x1) == subtag_hash_vector) {
    1004         if (hashp) Bug(NULL, "header inside hash vector?");
    1005         hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
    1006         /* Workaround for ticket:817 */
    1007         if (!(hp->flags & nhash_weak_value_mask)) {
    1008           if (hp->flags & nhash_weak_mask) {
    1009             /* If header_count is odd, this cuts off the last header field */
    1010             /* That case is handled specially above */
    1011             hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
    1012             hashp = hp;
    1013             mark_method = 3;
    1014           }
    1015         }
    1016       }
    1017 
    1018       keep_x1 = mark_ephemeral_root(x1);
    1019       keep_x2 = mark_ephemeral_root(x2);
    1020       if ((keep_x1 == false) &&
    1021           (keep_x2 == false) &&
    1022           (hashp == NULL)) {
    1023         outbits &= ~(BIT0_MASK >> bitidx);
    1024       }
    1025       memo_dnode++;
    1026       bitidx++;
    1027     }
    1028   }
    1029   if (GCDebug) {
    1030     p = (LispObj *) a->low;
    1031     check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    1032   }
    1033 }
    1034908
    1035909
  • trunk/source/lisp-kernel/x86-gc.c

    r15368 r15374  
    12341234
    12351235
    1236 void
    1237 mark_memoized_area(area *a, natural num_memo_dnodes)
    1238 {
    1239   bitvector refbits = a->refbits;
    1240   LispObj *p = (LispObj *) a->low, x1, x2;
    1241   natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    1242   Boolean keep_x1, keep_x2;
    1243   natural hash_dnode_limit = 0;
    1244   hash_table_vector_header *hashp = NULL;
    1245   int mark_method = 3;
    1246 
    1247   if (num_memo_dnodes) {
    1248     if (GCDebug) {
    1249       check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    1250     }
    1251 
    1252     /* The distinction between "inbits" and "outbits" is supposed to help us
    1253        detect cases where "uninteresting" setfs have been memoized.  Storing
    1254        NIL, fixnums, immediates (characters, etc.) or node pointers to static
    1255        or readonly areas is definitely uninteresting, but other cases are
    1256        more complicated (and some of these cases are hard to detect.)
    1257 
    1258        Some headers are "interesting", to the forwarder if not to us.
    1259 
    1260     */
    1261 
    1262     /*
    1263       We need to ensure that there are no bits set at or beyond
    1264       "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
    1265       tenures/untenures things.)  We find bits by grabbing a fullword at
    1266       a time and doing a cntlzw instruction; and don't want to have to
    1267       check for (< memo_dnode num_memo_dnodes) in the loop.
    1268     */
    1269 
    1270     {
    1271       natural
    1272         bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
    1273         index_of_last_word = (num_memo_dnodes >> bitmap_shift);
    1274 
    1275       if (bits_in_last_word != 0) {
    1276         natural mask = ~((NATURAL1<<(nbits_in_word-bits_in_last_word))- NATURAL1);
    1277         refbits[index_of_last_word] &= mask;
    1278       }
    1279     }
    1280        
    1281     set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
    1282     inbits = outbits = bits;
    1283     while (memo_dnode < num_memo_dnodes) {
    1284       if (bits == 0) {
    1285         int remain = nbits_in_word - bitidx;
    1286         memo_dnode += remain;
    1287         p += (remain+remain);
    1288         if (outbits != inbits) {
    1289           *bitsp = outbits;
    1290         }
    1291         bits = *++bitsp;
    1292         inbits = outbits = bits;
    1293         bitidx = 0;
    1294       } else {
    1295         nextbit = count_leading_zeros(bits);
    1296         if ((diff = (nextbit - bitidx)) != 0) {
    1297           memo_dnode += diff;
    1298           bitidx = nextbit;
    1299           p += (diff+diff);
    1300         }
    1301         x1 = *p++;
    1302         x2 = *p++;
    1303         bits &= ~(BIT0_MASK >> bitidx);
    1304 
    1305 
    1306         if (hashp) {
    1307           Boolean force_x1 = false;
    1308           if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
    1309             /* if vector_header_count is odd, x1 might be the last word of the header */
    1310             force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
    1311             /* was marking header, switch to data */
    1312             hash_dnode_limit = area_dnode(((LispObj *)hashp)
    1313                                           + 1
    1314                                           + header_element_count(hashp->header),
    1315                                           a->low);
    1316             /* In traditional weak method, don't mark vector entries at all. */
    1317             /* Otherwise mark the non-weak elements only */
    1318             mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
    1319                            ((hashp->flags & nhash_weak_value_mask)
    1320                             ? (1 + (hash_table_vector_header_count & 1))
    1321                             : (2 - (hash_table_vector_header_count & 1))));
    1322           }
    1323 
    1324           if (memo_dnode < hash_dnode_limit) {
    1325             /* perhaps ignore one or both of the elements */
    1326             if (!force_x1 && !(mark_method & 1)) x1 = 0;
    1327             if (!(mark_method & 2)) x2 = 0;
    1328           } else {
    1329             hashp = NULL;
    1330           }
    1331         }
    1332 
    1333         if (header_subtag(x1) == subtag_hash_vector) {
    1334           if (hashp) Bug(NULL, "header inside hash vector?");
    1335           hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
    1336           if (hp->flags & nhash_weak_mask) {
    1337             /* Work around the issue that seems to cause ticket:817,
    1338                which is that tenured hash vectors that are weak on value
    1339                aren't always maintained on GCweakvll.  If they aren't and
    1340                we process them weakly here, nothing will delete the unreferenced
    1341                elements. */
    1342             if (!(hp->flags & nhash_weak_value_mask)) {
    1343               /* If header_count is odd, this cuts off the last header field */
    1344               /* That case is handled specially above */
    1345               hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
    1346               hashp = hp;
    1347               mark_method = 3;
    1348 
    1349 
    1350 
    1351 
    1352 
    1353             }
    1354           }
    1355         }
    1356 
    1357         keep_x1 = mark_ephemeral_root(x1);
    1358         keep_x2 = mark_ephemeral_root(x2);
    1359         if ((keep_x1 == false) &&
    1360             (keep_x2 == false) &&
    1361             (hashp == NULL)) {
    1362           outbits &= ~(BIT0_MASK >> bitidx);
    1363         }
    1364         memo_dnode++;
    1365         bitidx++;
    1366       }
    1367     }
    1368     if (GCDebug) {
    1369       p = (LispObj *) a->low;
    1370       check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    1371     }
    1372   }
    1373 }
     1236
    13741237
    13751238void
Note: See TracChangeset for help on using the changeset viewer.