Esempio n. 1
0
/* Allocate lb bytes of pointerful, traced, but not collectable data */
GC_API void * GC_CALL GC_malloc_uncollectable(size_t lb)
{
    void *op;
    void **opp;
    size_t lg;
    DCL_LOCK_STATE;

    if( SMALL_OBJ(lb) ) {
        if (EXTRA_BYTES != 0 && lb != 0) lb--;
                  /* We don't need the extra byte, since this won't be  */
                  /* collected anyway.                                  */
        lg = GC_size_map[lb];
        opp = &(GC_uobjfreelist[lg]);
        LOCK();
        if( (op = *opp) != 0 ) {
            *opp = obj_link(op);
            obj_link(op) = 0;
            GC_bytes_allocd += GRANULES_TO_BYTES(lg);
            /* Mark bit ws already set on free list.  It will be        */
            /* cleared only temporarily during a collection, as a       */
            /* result of the normal free list mark bit clearing.        */
            GC_non_gc_bytes += GRANULES_TO_BYTES(lg);
            UNLOCK();
        } else {
            UNLOCK();
            op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
            /* For small objects, the free lists are completely marked. */
        }
        GC_ASSERT(0 == op || GC_is_marked(op));
        return((void *) op);
    } else {
        hdr * hhdr;

        op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
        if (0 == op) return(0);

        GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */
        hhdr = HDR(op);
        /* We don't need the lock here, since we have an undisguised    */
        /* pointer.  We do need to hold the lock while we adjust        */
        /* mark bits.                                                   */
        LOCK();
        set_mark_bit_from_hdr(hhdr, 0); /* Only object. */
#       ifndef THREADS
          GC_ASSERT(hhdr -> hb_n_marks == 0);
                /* This is not guaranteed in the multi-threaded case    */
                /* because the counter could be updated before locking. */
#       endif
        hhdr -> hb_n_marks = 1;
        UNLOCK();
        return((void *) op);
    }
}
Esempio n. 2
0
  GC_API void * GC_CALL GC_malloc(size_t lb)
#endif
{
    void *op;
    void **opp;
    size_t lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
        lg = GC_size_map[lb];
        opp = (void **)&(GC_objfreelist[lg]);
        LOCK();
        if (EXPECT((op = *opp) == 0, FALSE)) {
            UNLOCK();
            return (GENERAL_MALLOC((word)lb, NORMAL));
        }
        GC_ASSERT(0 == obj_link(op)
                  || ((word)obj_link(op)
                        <= (word)GC_greatest_plausible_heap_addr
                     && (word)obj_link(op)
                        >= (word)GC_least_plausible_heap_addr));
        *opp = obj_link(op);
        obj_link(op) = 0;
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        UNLOCK();
        return op;
   } else {
       return(GENERAL_MALLOC(lb, NORMAL));
   }
}
Esempio n. 3
0
/* hold lock:                                   */
GC_INNER void * GC_generic_malloc_inner(size_t lb, int k)
{
    void *op;

    if(SMALL_OBJ(lb)) {
        struct obj_kind * kind = GC_obj_kinds + k;
        size_t lg = GC_size_map[lb];
        void ** opp = &(kind -> ok_freelist[lg]);

        if( (op = *opp) == 0 ) {
            if (GC_size_map[lb] == 0) {
              if (!GC_is_initialized) GC_init();
              if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
              return(GC_generic_malloc_inner(lb, k));
            }
            if (kind -> ok_reclaim_list == 0) {
                if (!GC_alloc_reclaim_list(kind)) goto out;
            }
            op = GC_allocobj(lg, k);
            if (op == 0) goto out;
        }
        *opp = obj_link(op);
        obj_link(op) = 0;
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
    } else {
        op = (ptr_t)GC_alloc_large_and_clear(ADD_SLOP(lb), k, 0);
        GC_bytes_allocd += lb;
    }

out:
    return op;
}
Esempio n. 4
0
GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc(size_t lb)
#endif
{
    void *op;
    size_t lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
        GC_DBG_COLLECT_AT_MALLOC(lb);
        lg = GC_size_map[lb];
        LOCK();
        op = GC_freelists[NORMAL][lg];
        if (EXPECT(0 == op, FALSE)) {
            UNLOCK();
            return (GENERAL_MALLOC((word)lb, NORMAL));
        }
        GC_ASSERT(0 == obj_link(op)
                  || ((word)obj_link(op)
                      <= (word)GC_greatest_plausible_heap_addr
                      && (word)obj_link(op)
                      >= (word)GC_least_plausible_heap_addr));
        GC_freelists[NORMAL][lg] = obj_link(op);
        obj_link(op) = 0;
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        UNLOCK();
        return op;
    } else {
        return(GENERAL_MALLOC(lb, NORMAL));
    }
}
Esempio n. 5
0
  /* A size of 0 granules is used for large objects.                    */
  GC_INNER GC_bool GC_add_map_entry(size_t granules)
  {
    unsigned displ;
    unsigned short * new_map;

    if (granules > BYTES_TO_GRANULES(MAXOBJBYTES)) granules = 0;
    if (GC_obj_map[granules] != 0) {
        return(TRUE);
    }
    new_map = (unsigned short *)GC_scratch_alloc(MAP_LEN * sizeof(short));
    if (new_map == 0) return(FALSE);
    GC_COND_LOG_PRINTF(
                "Adding block map for size of %u granules (%u bytes)\n",
                (unsigned)granules, (unsigned)GRANULES_TO_BYTES(granules));
    if (granules == 0) {
      for (displ = 0; displ < BYTES_TO_GRANULES(HBLKSIZE); displ++) {
        new_map[displ] = 1;  /* Nonzero to get us out of marker fast path. */
      }
    } else {
      for (displ = 0; displ < BYTES_TO_GRANULES(HBLKSIZE); displ++) {
        new_map[displ] = (unsigned short)(displ % granules);
      }
    }
    GC_obj_map[granules] = new_map;
    return(TRUE);
  }
Esempio n. 6
0
void * GC_gcj_malloc_ignore_off_page(size_t lb,
				     void * ptr_to_struct_containing_descr) 
{
    ptr_t op;
    ptr_t * opp;
    word lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
	lg = GC_size_map[lb];
	opp = &(GC_gcjobjfreelist[lg]);
	LOCK();
        if( (op = *opp) == 0 ) {
	    maybe_finalize();
            op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
	    lg = GC_size_map[lb];	/* May have been uninitialized.	*/
        } else {
            *opp = obj_link(op);
            GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        }
	*(void **)op = ptr_to_struct_containing_descr;
	UNLOCK();
    } else {
	LOCK();
	maybe_finalize();
        op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
        if (0 != op) {
          *(void **)op = ptr_to_struct_containing_descr;
	}
        UNLOCK();
    }
    return((void *) op);
}
Esempio n. 7
0
GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k)
{
    void * result;
    DCL_LOCK_STATE;

    if (EXPECT(GC_have_errors, FALSE))
        GC_print_all_errors();
    GC_INVOKE_FINALIZERS();
    GC_DBG_COLLECT_AT_MALLOC(lb);
    if (SMALL_OBJ(lb)) {
        LOCK();
        result = GC_generic_malloc_inner(lb, k);
        UNLOCK();
    } else {
        size_t lg;
        size_t lb_rounded;
        word n_blocks;
        GC_bool init;

        lg = ROUNDED_UP_GRANULES(lb);
        lb_rounded = GRANULES_TO_BYTES(lg);
        if (lb_rounded < lb)
            return((*GC_get_oom_fn())(lb));
        n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded);
        init = GC_obj_kinds[k].ok_init;
        LOCK();
        result = (ptr_t)GC_alloc_large(lb_rounded, k, 0);
        if (0 != result) {
            if (GC_debugging_started) {
                BZERO(result, n_blocks * HBLKSIZE);
            } else {
#           ifdef THREADS
                /* Clear any memory that might be used for GC descriptors */
                /* before we release the lock.                            */
                ((word *)result)[0] = 0;
                ((word *)result)[1] = 0;
                ((word *)result)[GRANULES_TO_WORDS(lg)-1] = 0;
                ((word *)result)[GRANULES_TO_WORDS(lg)-2] = 0;
#           endif
            }
        }
        GC_bytes_allocd += lb_rounded;
        UNLOCK();
        if (init && !GC_debugging_started && 0 != result) {
            BZERO(result, n_blocks * HBLKSIZE);
        }
    }
    if (0 == result) {
        return((*GC_get_oom_fn())(lb));
    } else {
        return(result);
    }
}
Esempio n. 8
0
/* require special handling on allocation.      */
GC_INNER void * GC_generic_malloc_inner(size_t lb, int k)
{
    void *op;

    GC_ASSERT(I_HOLD_LOCK());
    if(SMALL_OBJ(lb)) {
        struct obj_kind * kind = GC_obj_kinds + k;
        size_t lg = GC_size_map[lb];
        void ** opp = &(kind -> ok_freelist[lg]);

        op = *opp;
        if (EXPECT(0 == op, FALSE)) {
            if (lg == 0) {
                if (!EXPECT(GC_is_initialized, TRUE)) {
                    DCL_LOCK_STATE;
                    UNLOCK(); /* just to unset GC_lock_holder */
                    GC_init();
                    LOCK();
                    lg = GC_size_map[lb];
                }
                if (0 == lg) {
                    GC_extend_size_map(lb);
                    lg = GC_size_map[lb];
                    GC_ASSERT(lg != 0);
                }
                /* Retry */
                opp = &(kind -> ok_freelist[lg]);
                op = *opp;
            }
            if (0 == op) {
                if (0 == kind -> ok_reclaim_list &&
                        !GC_alloc_reclaim_list(kind))
                    return NULL;
                op = GC_allocobj(lg, k);
                if (0 == op)
                    return NULL;
            }
        }
        *opp = obj_link(op);
        obj_link(op) = 0;
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
    } else {
        op = (ptr_t)GC_alloc_large_and_clear(ADD_SLOP(lb), k, 0);
        GC_bytes_allocd += lb;
    }

    return op;
}
Esempio n. 9
0
  GC_API void * GC_CALL GC_finalized_malloc(size_t lb,
                                const struct GC_finalizer_closure *fclos)
#endif
{
    ptr_t op;
    word lg;
    DCL_LOCK_STATE;

    lb += sizeof(void *);
    GC_ASSERT(done_init);
    if (SMALL_OBJ(lb)) {
        GC_DBG_COLLECT_AT_MALLOC(lb);
        lg = GC_size_map[lb];
        LOCK();
        op = GC_finalized_objfreelist[lg];
        if (EXPECT(0 == op, FALSE)) {
            UNLOCK();
            op = GC_generic_malloc(lb, GC_finalized_kind);
            if (NULL == op)
                return NULL;
            /* GC_generic_malloc has extended the size map for us.      */
            lg = GC_size_map[lb];
        } else {
            GC_finalized_objfreelist[lg] = obj_link(op);
            obj_link(op) = 0;
            GC_bytes_allocd += GRANULES_TO_BYTES(lg);
            UNLOCK();
        }
        GC_ASSERT(lg > 0);
        ((const void **)op)[GRANULES_TO_WORDS(lg) - 1] = fclos;
    } else {
        size_t op_sz;

        op = GC_generic_malloc(lb, GC_finalized_kind);
        if (NULL == op)
            return NULL;
        op_sz = GC_size(op);
        GC_ASSERT(op_sz >= lb);
        ((const void **)op)[op_sz / sizeof(void *) - 1] = fclos;
    }
    return GC_clear_stack(op);
}
Esempio n. 10
0
/* Will fail to do anything if we are out of memory.                    */
GC_INNER void GC_new_hblk(size_t gran, int kind)
{
  struct hblk *h;       /* the new heap block */
  GC_bool clear = GC_obj_kinds[kind].ok_init;

  GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE);

  if (GC_debugging_started) clear = TRUE;

  /* Allocate a new heap block */
    h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0);
    if (h == 0) return;

  /* Mark all objects if appropriate. */
      if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));

  /* Build the free list */
      GC_obj_kinds[kind].ok_freelist[gran] =
        GC_build_fl(h, GRANULES_TO_WORDS(gran), clear,
                    GC_obj_kinds[kind].ok_freelist[gran]);
}
Esempio n. 11
0
  void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
#endif
{
    ptr_t op;
    ptr_t * opp;
    word lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
	lg = GC_size_map[lb];
	opp = &(GC_gcjobjfreelist[lg]);
	LOCK();
	op = *opp;
        if(EXPECT(op == 0, 0)) {
	    maybe_finalize();
            op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
	    if (0 == op) {
		UNLOCK();
		return(GC_oom_fn(lb));
	    }
        } else {
            *opp = obj_link(op);
            GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        }
	*(void **)op = ptr_to_struct_containing_descr;
	GC_ASSERT(((void **)op)[1] == 0);
	UNLOCK();
    } else {
	LOCK();
	maybe_finalize();
	op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
	if (0 == op) {
	    UNLOCK();
	    return(GC_oom_fn(lb));
	}
	*(void **)op = ptr_to_struct_containing_descr;
	UNLOCK();
    }
    return((void *) op);
}
Esempio n. 12
0
  GC_API void * GC_CALL GC_malloc_atomic(size_t lb)
#endif
{
    void *op;
    void ** opp;
    size_t lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
        lg = GC_size_map[lb];
        opp = &(GC_aobjfreelist[lg]);
        LOCK();
        if (EXPECT((op = *opp) == 0, FALSE)) {
            UNLOCK();
            return(GENERAL_MALLOC((word)lb, PTRFREE));
        }
        *opp = obj_link(op);
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        UNLOCK();
        return((void *) op);
   } else {
       return(GENERAL_MALLOC((word)lb, PTRFREE));
   }
}
Esempio n. 13
0
GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_atomic(size_t lb)
#endif
{
    void *op;
    size_t lg;
    DCL_LOCK_STATE;

    if(SMALL_OBJ(lb)) {
        GC_DBG_COLLECT_AT_MALLOC(lb);
        lg = GC_size_map[lb];
        LOCK();
        op = GC_freelists[PTRFREE][lg];
        if (EXPECT(0 == op, FALSE)) {
            UNLOCK();
            return(GENERAL_MALLOC((word)lb, PTRFREE));
        }
        GC_freelists[PTRFREE][lg] = obj_link(op);
        GC_bytes_allocd += GRANULES_TO_BYTES(lg);
        UNLOCK();
        return((void *) op);
    } else {
        return(GENERAL_MALLOC((word)lb, PTRFREE));
    }
}