/[cmucl]/src/lisp/gencgc.c
ViewVC logotype

Diff of /src/lisp/gencgc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.95.2.1 by rtoy, Wed May 14 16:12:06 2008 UTC revision 1.95.2.1.2.7 by rtoy, Tue May 5 01:48:17 2009 UTC
# Line 247  unsigned counters_verbose = 0; Line 247  unsigned counters_verbose = 0;
247   * To enable the use of page protection to help avoid the scavenging   * To enable the use of page protection to help avoid the scavenging
248   * of pages that don't have pointers to younger generations.   * of pages that don't have pointers to younger generations.
249   */   */
 #if defined(DARWIN) && defined(__i386__)  
 boolean enable_page_protection = FALSE;  
 #else  
250  boolean enable_page_protection = TRUE;  boolean enable_page_protection = TRUE;
 #endif  
251    
252  /*  /*
253   * Hunt for pointers to old-space, when GCing generations >= verify_gen.   * Hunt for pointers to old-space, when GCing generations >= verify_gen.
# Line 389  static char *heap_base = NULL; Line 385  static char *heap_base = NULL;
385  /*  /*
386   * Calculate the start address for the given page number.   * Calculate the start address for the given page number.
387   */   */
388  inline char *  static char *
389  page_address(int page_num)  page_address(int page_num)
390  {  {
391      return heap_base + PAGE_SIZE * page_num;      return heap_base + PAGE_SIZE * page_num;
# Line 399  page_address(int page_num) Line 395  page_address(int page_num)
395   * Find the page index within the page_table for the given address.   * Find the page index within the page_table for the given address.
396   * Returns -1 on failure.   * Returns -1 on failure.
397   */   */
398  inline int  int
399  find_page_index(void *addr)  find_page_index(void *addr)
400  {  {
401      int index = (char *) addr - heap_base;      int index = (char *) addr - heap_base;
# Line 413  find_page_index(void *addr) Line 409  find_page_index(void *addr)
409      return -1;      return -1;
410  }  }
411    
412    /*
413     * This routine implements a write barrier used to record stores into
414     * to boxed regions outside of generation 0.  When such a store occurs
415     * this routine will be automatically invoked by the page fault
416     * handler.  If passed an address outside of the dynamic space, this
417     * routine will return immediately with a value of 0.  Otherwise, the
418     * page belonging to the address is made writable, the protection
419     * change is recorded in the garbage collector page table, and a value
420     * of 1 is returned.
421     */
422    int
423    gc_write_barrier(void *addr)
424    {
425        int page_index = find_page_index(addr);
426    
427        /* Check if the fault is within the dynamic space. */
428        if (page_index == -1) {
429             return 0;
430        }
431    
432        /* The page should have been marked write protected */
433        if (!PAGE_WRITE_PROTECTED(page_index))
434             fprintf(stderr,
435                     "*** Page fault in page not marked as write protected\n");
436    
437        /* Un-protect the page */
438        os_protect(page_address(page_index), PAGE_SIZE, OS_VM_PROT_ALL);
439        page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK;
440        page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK;
441    
442        return 1;
443    }
444    
445  /*  /*
446   * A structure to hold the state of a generation.   * A structure to hold the state of a generation.
# Line 1561  gc_alloc_large(int nbytes, int unboxed, Line 1589  gc_alloc_large(int nbytes, int unboxed,
1589  }  }
1590    
1591  /*  /*
1592     * If the current region has more than this much space left, we don't
1593     * want to abandon the region (wasting space), but do a "large" alloc
1594     * to a new region.
1595     */
1596    
1597    int region_empty_threshold = 32;
1598    
1599    
1600    /*
1601     * How many consecutive large alloc we can do before we abandon the
1602     * current region
1603     */
1604    int consecutive_large_alloc_limit = 10;
1605    
1606    
1607    /*
1608     * This is for debugging.  It gets incremented every time we have to
1609     * abandon the current region, because we done too many gc_alloc's in
1610     * the current region without changing the region.
1611     */
1612    int abandon_boxed_region_count = 0;
1613    int abandon_unboxed_region_count = 0;
1614    int saved_and_boxed_region_differ = 0;
1615    
1616    
1617    /*
1618   * Allocate bytes from the boxed_region. It first checks if there is   * Allocate bytes from the boxed_region. It first checks if there is
1619   * room, if not then it calls gc_alloc_new_region to find a new region   * room, if not then it calls gc_alloc_new_region to find a new region
1620   * with enough space. A pointer to the start of the region is returned.   * with enough space. A pointer to the start of the region is returned.
# Line 1569  static void * Line 1623  static void *
1623  gc_alloc(int nbytes)  gc_alloc(int nbytes)
1624  {  {
1625      char *new_free_pointer;      char *new_free_pointer;
1626        static int consecutive_large_alloc = 0;
1627        static struct alloc_region *saved_boxed = NULL;
1628    
1629  #if 0  #if 0
1630      fprintf(stderr, "gc_alloc %d\n", nbytes);      fprintf(stderr, "gc_alloc %d\n", nbytes);
# Line 1590  gc_alloc(int nbytes) Line 1646  gc_alloc(int nbytes)
1646              /* Setup a new region. */              /* Setup a new region. */
1647              gc_alloc_new_region(32, 0, &boxed_region);              gc_alloc_new_region(32, 0, &boxed_region);
1648          }          }
1649    
1650            consecutive_large_alloc = 0;
1651            if (saved_boxed) {
1652                free(saved_boxed);
1653                saved_boxed = NULL;
1654            }
1655    
1656          return (void *) new_obj;          return (void *) new_obj;
1657      }      }
1658    
# Line 1599  gc_alloc(int nbytes) Line 1662  gc_alloc(int nbytes)
1662       * If there is a bit of room left in the current region then       * If there is a bit of room left in the current region then
1663       * allocate a large object.       * allocate a large object.
1664       */       */
1665      if (boxed_region.end_addr - boxed_region.free_pointer > 32)  
1666        /*
1667         * This has potentially very bad behavior on sparc if the current
1668         * boxed region is too small for the allocation, but the free
1669         * space is greater than 32.  The scenario is where we're always
1670         * allocating something that won't fit in the boxed region and we
1671         * keep calling gc_alloc_large.  Since gc_alloc_large doesn't
1672         * change boxed_region, the next allocation will again be
1673         * out-of-line and we hit a kernel trap again.  And so on, so we
1674         * waste all of our time doing kernel traps to allocate small
1675         * things.  This also affects ppc.
1676         *
1677         * X86 has the same issue, but the affect is less because the
1678         * out-of-line allocation is a just a function call, not a kernel
1679         * trap.
1680         *
1681         * We should also do a large alloc if the object is large, even if
1682         * the free space left in the region is too small.  This helps GC
1683         * so we don't have to copy this object again.
1684         *
1685         * Heuristic: If we do too many consecutive large allocations
1686         * because the current region has some space left, we give up and
1687         * abandon the region. This will prevent the bad scenario above
1688         * from killing gc allocation performance.
1689         *
1690         */
1691        if (((boxed_region.end_addr - boxed_region.free_pointer > region_empty_threshold)
1692             || (nbytes >= large_object_size))
1693            && (consecutive_large_alloc < consecutive_large_alloc_limit)) {
1694            if (nbytes < large_object_size) {
1695                /* Large objects don't count */
1696                if (saved_boxed) {
1697                    /* Is the saved region the same as the current region?
1698                     * If so, update the counter.  If not, that means we
1699                     * did some other allocation, so reset the counter and region
1700                     */
1701                    if (memcmp(saved_boxed, &boxed_region, sizeof(*saved_boxed)) == 0) {
1702                        ++consecutive_large_alloc;
1703                    } else {
1704                        consecutive_large_alloc = 0;
1705    #if 0
1706                        fprintf(stderr, "saved and current boxed regions are different!  Resetting!\n");
1707    #endif
1708                        ++saved_and_boxed_region_differ;
1709    
1710                        memcpy(saved_boxed, &boxed_region, sizeof(*saved_boxed));
1711                    }
1712                } else {
1713                    /* No saved region, so copy it */
1714                    saved_boxed = (struct alloc_region *) malloc(sizeof(*saved_boxed));
1715                    memcpy(saved_boxed, &boxed_region, sizeof(*saved_boxed));
1716                    ++consecutive_large_alloc;
1717                }
1718            }
1719    
1720          return gc_alloc_large(nbytes, 0, &boxed_region);          return gc_alloc_large(nbytes, 0, &boxed_region);
1721        }
1722    
1723        consecutive_large_alloc = 0;
1724        ++abandon_boxed_region_count;
1725    
1726      /* Else find a new region. */      /* Else find a new region. */
1727    
# Line 1630  gc_alloc(int nbytes) Line 1751  gc_alloc(int nbytes)
1751              gc_alloc_new_region(32, 0, &boxed_region);              gc_alloc_new_region(32, 0, &boxed_region);
1752          }          }
1753    
1754            if (saved_boxed) {
1755                free(saved_boxed);
1756                saved_boxed = NULL;
1757            }
1758    
1759          return (void *) new_obj;          return (void *) new_obj;
1760      }      }
1761    
# Line 1699  static void * Line 1825  static void *
1825  gc_alloc_unboxed(int nbytes)  gc_alloc_unboxed(int nbytes)
1826  {  {
1827      char *new_free_pointer;      char *new_free_pointer;
1828        static int consecutive_large_alloc = 0;
1829    
1830  #if 0  #if 0
1831      fprintf(stderr, "gc_alloc_unboxed %d\n", nbytes);      fprintf(stderr, "gc_alloc_unboxed %d\n", nbytes);
# Line 1722  gc_alloc_unboxed(int nbytes) Line 1849  gc_alloc_unboxed(int nbytes)
1849              gc_alloc_new_region(32, 1, &unboxed_region);              gc_alloc_new_region(32, 1, &unboxed_region);
1850          }          }
1851    
1852            consecutive_large_alloc = 0;
1853          return (void *) new_obj;          return (void *) new_obj;
1854      }      }
1855    
# Line 1731  gc_alloc_unboxed(int nbytes) Line 1859  gc_alloc_unboxed(int nbytes)
1859       * If there is a bit of room left in the current region then       * If there is a bit of room left in the current region then
1860       * allocate a large object.       * allocate a large object.
1861       */       */
1862      if (unboxed_region.end_addr - unboxed_region.free_pointer > 32)  
1863        /* See gc_alloc for what we're doing here. */
1864        if (((unboxed_region.end_addr - unboxed_region.free_pointer > region_empty_threshold)
1865             || (nbytes >= large_object_size))
1866            && (consecutive_large_alloc < consecutive_large_alloc_limit)) {
1867            ++consecutive_large_alloc;
1868          return gc_alloc_large(nbytes, 1, &unboxed_region);          return gc_alloc_large(nbytes, 1, &unboxed_region);
1869        }
1870    
1871        consecutive_large_alloc = 0;
1872        ++abandon_unboxed_region_count;
1873    
1874      /* Else find a new region. */      /* Else find a new region. */
1875    

Legend:
Removed from v.1.95.2.1  
changed lines
  Added in v.1.95.2.1.2.7

  ViewVC Help
Powered by ViewVC 1.1.5