Ticket #1741: 0009-Important-fixes.patch

File 0009-Important-fixes.patch, 6.0 KB (added by luben, 4 years ago)
  • src/hash.c

    From 639817de90dafbc8cc98a63ff05a7a5ade5dffc1 Mon Sep 17 00:00:00 2001
    From: luben <karavelov@spnet.net>
    Date: Mon, 16 Aug 2010 18:34:46 +0300
    Subject: [PATCH 9/9] Important fixes
    
    * make hash again work with N_BUCKETS(X) != X
    * fix memory allocation problems catched by
      more strict allocators. libhoard catched some
      use-after-free bugs.
    * realocate pointers in linear scan - it's faster
    ---
     src/hash.c |   88 ++++++++++++++++++++++++++++++++++--------------------------
     1 files changed, 50 insertions(+), 38 deletions(-)
    
    diff --git a/src/hash.c b/src/hash.c
    index 07a9b18..145cea5 100644
    a b  
    781781expand_hash(PARROT_INTERP, ARGMOD(Hash *hash)) 
    782782{ 
    783783    ASSERT_ARGS(expand_hash) 
    784     HashBucket  **old_index, **new_index; 
    785     HashBucket   *old_buckets,*new_buckets, *bucket; 
    786     HashBucket * const old_offset = (HashBucket *)((char *)hash + sizeof (Hash)); 
     784 
     785    HashBucket  **new_index,  **index; 
     786    HashBucket   *new_buckets, *bucket; 
     787 
     788    HashBucket * const initial_offset = (HashBucket *)((char *)hash + sizeof (Hash)); 
    787789 
    788790    void *        new_mem; 
    789791    void * const  old_mem    = hash->buckets; 
    790792    const UINTVAL old_size   = hash->mask + 1; 
    791     const UINTVAL new_size   = old_size << 1; /* Double. Right-shift is 2x */ 
    792     const UINTVAL new_mask   = new_size - 1 ; 
     793    const UINTVAL new_size   = old_size  << 1; /* Double. Right-shift is 2x */ 
     794    const UINTVAL new_mask   = new_size   - 1; 
    793795    size_t        offset, i; 
    794796 
    795797    /* 
     
    804806    */ 
    805807 
    806808    /* resize mem */ 
    807     if (old_offset != old_mem) { 
     809    if (initial_offset != old_mem) { 
    808810        /* This buffer has been reallocated at least once before. */ 
    809         new_mem = Parrot_gc_reallocate_memory_chunk_with_interior_pointers( 
    810                 interp, old_mem, HASH_ALLOC_SIZE(new_size), HASH_ALLOC_SIZE(old_size)); 
    811     } 
     811        new_mem   = Parrot_gc_reallocate_memory_chunk_with_interior_pointers( 
     812                interp, old_mem,  
     813                HASH_ALLOC_SIZE(new_size),  
     814                HASH_ALLOC_SIZE(old_size)); 
     815 
     816        new_buckets = (HashBucket *)  new_mem; 
     817        new_index   = (HashBucket **)(new_buckets + N_BUCKETS(new_size)); 
     818 
     819        offset = (char *)new_mem - (char *)old_mem; 
     820 
     821        /* old index is here */ 
     822        index  = (HashBucket **)(new_buckets + N_BUCKETS(old_size)); 
     823        /* reallocate index */ 
     824        mem_sys_memcopy(new_index, index, sizeof(HashBucket *) * old_size); 
     825 
     826        /* clear second half of the buckets, freed by old the index */ 
     827        memset(new_buckets + N_BUCKETS(old_size), 0,  
     828                sizeof (HashBucket *) * old_size); 
     829    }  
    812830    else { 
    813831        /* Allocate a new buffer. */ 
    814832        new_mem = Parrot_gc_allocate_memory_chunk_with_interior_pointers( 
    815833                interp, HASH_ALLOC_SIZE(new_size)); 
    816         memcpy(new_mem, old_mem, HASH_ALLOC_SIZE(old_size)); 
     834 
     835        new_buckets = (HashBucket *)  new_mem; 
     836        new_index   = (HashBucket **)(new_buckets + N_BUCKETS(new_size)); 
     837 
     838        offset = (char *)new_buckets - (char *)hash->buckets; 
     839         
     840        mem_sys_memcopy(new_buckets, hash->buckets , 
     841                N_BUCKETS(old_size) * sizeof (HashBucket)); 
     842        mem_sys_memcopy(new_index,   hash->index,  
     843                sizeof(HashBucket *) * old_size); 
    817844    } 
    818845 
    819846    /* 
    820847         +---+---+---+---+---+---+-+-+-+-+-+-+-+-+ 
    821          |  buckets  | old_index    |  new_index       | 
     848         |  buckets  | old_index    |  new_index | 
    822849         +---+---+---+---+---+---+-+-+-+-+-+-+-+-+ 
    823850         ^                       ^ 
    824851         | new_mem               | hash->index 
    825852    */ 
    826853 
    827     old_buckets = hash->buckets; 
    828     old_index   = hash->index; 
    829  
    830     new_buckets = (HashBucket *) new_mem; 
    831     new_index   = (HashBucket **)(new_buckets + N_BUCKETS(new_size)); 
    832  
    833     /* things can have moved by this offset */ 
    834     offset = (char *)new_buckets - (char *)old_buckets; 
    835  
    836     /* relocate the bucket index */ 
    837     mem_sys_memmove(new_index, old_index, old_size * sizeof (HashBucket *)); 
    838854 
    839855    /* update hash data */ 
    840856    hash->index     = new_index; 
    841857    hash->buckets   = new_buckets; 
    842858    hash->mask      = new_mask; 
    843859 
    844     /* clear freshly allocated bucket index */ 
    845     memset(new_index + old_size, 0, sizeof (HashBucket *) * old_size); 
    846  
    847860    /* 
    848861     * reloc pointers - this part would be also needed, if we 
    849862     * allocate hash memory from GC movable memory, and then 
     
    851864     * as expand_hash is only called for that case). 
    852865     */ 
    853866    if (offset) { 
    854         size_t j; 
    855         for (j = 0; j < old_size; ++j) { 
    856             HashBucket **next_p = new_index + j; 
    857             while (*next_p) { 
    858                 *next_p = (HashBucket *)((char *)*next_p + offset); 
    859                 bucket  = *next_p; 
    860                 next_p  = &bucket->next; 
     867        for (i = 0; i < old_size; ++i) { 
     868            index = new_index + i; 
     869            while (*index) { 
     870                *index = (HashBucket *)((char *)*index + offset); 
     871                bucket = *index; 
     872                index  = &bucket->next; 
    861873            } 
    862874        } 
    863875    } 
    864876 
    865877    /* recalc bucket index */ 
    866878    for (i = 0; i < old_size; ++i) { 
    867         HashBucket **next_p = new_index + i; 
     879        index = new_index + i; 
    868880 
    869         while ((bucket = *next_p) != NULL) { 
     881        while ((bucket = *index) != NULL) { 
    870882            /* rehash the bucket */ 
    871883            const size_t new_loc = 
    872884                get_hash_val(interp, hash, bucket->key) & new_mask; 
    873885 
    874886            if (i != new_loc) { 
    875                 *next_p             = bucket->next; 
    876                 bucket->next        = new_index[new_loc]; 
    877                 new_index[new_loc]  = bucket; 
     887                *index             = bucket->next; 
     888                bucket->next       = new_index[new_loc]; 
     889                new_index[new_loc] = bucket; 
    878890            } 
    879891            else 
    880                 next_p = &bucket->next; 
     892                index = &bucket->next; 
    881893        } 
    882894    } 
    883895