Example #1
0
/* with GC_gcj_debug_kind.						*/
GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
			   GC_EXTRA_PARAMS)
{
    GC_PTR result;

    /* We're careful to avoid extra calls, which could		 */
    /* confuse the backtrace.					*/
    LOCK();
    maybe_finalize();
    result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
    if (result == 0) {
	UNLOCK();
        GC_err_printf2("GC_debug_gcj_malloc(%ld, 0x%lx) returning NIL (",
        	       (unsigned long) lb,
		       (unsigned long) ptr_to_struct_containing_descr);
        GC_err_puts(s);
        GC_err_printf1(":%ld)\n", (unsigned long)i);
        return(GC_oom_fn(lb));
    }
    *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
    UNLOCK();
    if (!GC_debugging_started) {
    	GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
Example #2
0
/* And a debugging version of the above:	*/
void * GC_debug_gcj_fast_malloc(size_t lw,
				void * ptr_to_struct_containing_descr,
				GC_EXTRA_PARAMS)
{
    GC_PTR result;
    size_t lb = WORDS_TO_BYTES(lw);

    /* We clone the code from GC_debug_gcj_malloc, so that we 	*/
    /* dont end up with extra frames on the stack, which could	*/
    /* confuse the backtrace.					*/
    LOCK();
    maybe_finalize();
    result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
    if (result == 0) {
	UNLOCK();
        GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (",
        	       (unsigned long) lw,
		       (unsigned long) ptr_to_struct_containing_descr);
        GC_err_puts(s);
        GC_err_printf1(":%ld)\n", (unsigned long)i);
        return GC_oom_fn(WORDS_TO_BYTES(lw));
    }
    *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
    UNLOCK();
    if (!GC_debugging_started) {
    	GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
Example #3
0
void GC_print_obj(ptr_t p)
{
    register oh * ohdr = (oh *)GC_base(p);
    
    GC_ASSERT(I_DONT_HOLD_LOCK());
    GC_err_printf("%p (", ((ptr_t)ohdr + sizeof(oh)));
    GC_err_puts(ohdr -> oh_string);
#   ifdef SHORT_DBG_HDRS
      GC_err_printf(":%ld, ", (unsigned long)(ohdr -> oh_int));
#   else
      GC_err_printf(":%ld, sz=%ld, ", (unsigned long)(ohdr -> oh_int),
          			        (unsigned long)(ohdr -> oh_sz));
#   endif
    GC_print_type((ptr_t)(ohdr + 1));
    GC_err_puts(")\n");
    PRINT_CALL_CHAIN(ohdr);
}
Example #4
0
/* to somewhere inside an object with the debugging info.               */
STATIC void GC_print_obj(ptr_t p)
{
    oh * ohdr = (oh *)GC_base(p);

    GC_ASSERT(I_DONT_HOLD_LOCK());
#   ifdef LINT2
      if (!ohdr) ABORT("Invalid GC_print_obj argument");
#   endif
    GC_err_printf("%p (", ((ptr_t)ohdr + sizeof(oh)));
    GC_err_puts(ohdr -> oh_string);
#   ifdef SHORT_DBG_HDRS
      GC_err_printf(":%d, ", GET_OH_LINENUM(ohdr));
#   else
      GC_err_printf(":%d, sz=%lu, ",
                    GET_OH_LINENUM(ohdr), (unsigned long)(ohdr -> oh_sz));
#   endif
    GC_print_type((ptr_t)(ohdr + 1));
    GC_err_puts(")\n");
    PRINT_CALL_CHAIN(ohdr);
}
Example #5
0
void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr)
{
    register oh * ohdr = (oh *)GC_base(p);
    
    GC_ASSERT(I_DONT_HOLD_LOCK());
    GC_err_printf("%p in object at %p(", clobbered_addr, p);
    if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
        || ohdr -> oh_string == 0) {
        GC_err_printf("<smashed>, appr. sz = %ld)\n",
        	       (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
    } else {
        if (ohdr -> oh_string[0] == '\0') {
            GC_err_puts("EMPTY(smashed?)");
        } else {
            GC_err_puts(ohdr -> oh_string);
        }
        GC_err_printf(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
        			          (unsigned long)(ohdr -> oh_sz));
        PRINT_CALL_CHAIN(ohdr);
    }
}
Example #6
0
GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
{
    void * result = GC_malloc_atomic(lb + DEBUG_BYTES);

    if (result == 0) {
        GC_err_printf("GC_debug_malloc_atomic(%lu) returning NULL (",
                      (unsigned long) lb);
        GC_err_puts(s);
        GC_err_printf(":%lu)\n", (unsigned long)i);
        return(0);
    }
    if (!GC_debugging_started) {
        GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, i));
}
Example #7
0
void * GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
{
    void * result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
    
    if (result == 0) {
        GC_err_printf("GC_debug_malloc_uncollectable(%lu) returning NIL (",
        	      (unsigned long) lb);
        GC_err_puts(s);
        GC_err_printf(":%lu)\n", (unsigned long)i);
        return(0);
    }
    if (!GC_debugging_started) {
        GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
Example #8
0
GC_API void * GC_CALL GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
{
    void * result;
    /* Note that according to malloc() specification, if size is 0 then */
    /* malloc() returns either NULL, or a unique pointer value that can */
    /* later be successfully passed to free(). We always do the latter. */
    result = GC_malloc(lb + DEBUG_BYTES);

    if (result == 0) {
        GC_err_printf("GC_debug_malloc(%lu) returning NULL (",
                      (unsigned long) lb);
        GC_err_puts(s);
        GC_err_printf(":%ld)\n", (unsigned long)i);
        return(0);
    }
    if (!GC_debugging_started) {
        GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, i));
}
Example #9
0
        /*longPtr = proc->pr_ReturnAddr;
        size = longPtr[0];*/

        return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
    } else {
        return (char *)proc->pr_Task.tc_SPUpper;
    }
}

#if 0 /* old version */
ptr_t GC_get_stack_base()
{
    extern struct WBStartup *_WBenchMsg;
    extern long __base;
    extern long __stack;
    struct Task *task;
    struct Process *proc;
    struct CommandLineInterface *cli;
    long size;

    if ((task = FindTask(0)) == 0) {
        GC_err_puts("Cannot find own task structure\n");
        ABORT("task missing");
    }
    proc = (struct Process *)task;
    cli = BADDR(proc->pr_CLI);

    if (_WBenchMsg != 0 || cli == 0) {
        size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
    } else {
        size = cli->cli_DefaultStack * 4;
    }
    return (ptr_t)(__base + GC_max(size, __stack));
}
Example #10
0
/* is p.                                                                */
STATIC void GC_print_type(ptr_t p)
{
    hdr * hhdr = GC_find_header(p);
    char buffer[GC_TYPE_DESCR_LEN + 1];
    int kind = hhdr -> hb_obj_kind;

    if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) {
        /* This should preclude free list objects except with   */
        /* thread-local allocation.                             */
        buffer[GC_TYPE_DESCR_LEN] = 0;
        (GC_describe_type_fns[kind])(p, buffer);
        GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);
        GC_err_puts(buffer);
    } else {
        switch(kind) {
          case PTRFREE:
            GC_err_puts("PTRFREE");
            break;
          case NORMAL:
            GC_err_puts("NORMAL");
            break;
          case UNCOLLECTABLE:
            GC_err_puts("UNCOLLECTABLE");
            break;
#         ifdef ATOMIC_UNCOLLECTABLE
            case AUNCOLLECTABLE:
              GC_err_puts("ATOMIC UNCOLLECTABLE");
              break;
#         endif
          case STUBBORN:
            GC_err_puts("STUBBORN");
            break;
          default:
            GC_err_printf("kind=%d descr=0x%lx", kind,
                          (unsigned long)(hhdr -> hb_descr));
        }
    }
}
Example #11
0
    /* xoper hunks Shell Process */

    num=0;
    for (data = (ULONG *)BADDR(myseglist); data != NULL;
            data = (ULONG *)BADDR(data[0])) {
        if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
                ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
#             ifdef __GNUC__
            if (dataSegSize == data[-1]) {
                found_segment = TRUE;
            }
# 	      endif
            GC_add_roots_inner((char *)&data[1],
                               ((char *)&data[1]) + data[-1], FALSE);
        }
        ++num;
    } /* for */
# 	ifdef __GNUC__
    if (!found_segment) {
        ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
    }
# 	endif
}

#if 0 /* old version */
void GC_register_data_segments()
{
    extern struct WBStartup *_WBenchMsg;
    struct Process	*proc;
    struct CommandLineInterface *cli;
    BPTR myseglist;
    ULONG *data;

    if ( _WBenchMsg != 0 ) {
        if ((myseglist = _WBenchMsg->sm_Segment) == 0) {
            GC_err_puts("No seglist from workbench\n");
            return;
        }
    } else {
        if ((proc = (struct Process *)FindTask(0)) == 0) {
            GC_err_puts("Cannot find process structure\n");
            return;
        }
        if ((cli = BADDR(proc->pr_CLI)) == 0) {
            GC_err_puts("No CLI\n");
            return;
        }
        if ((myseglist = cli->cli_Module) == 0) {
            GC_err_puts("No seglist from CLI\n");
            return;
        }
    }

    for (data = (ULONG *)BADDR(myseglist); data != 0;
            data = (ULONG *)BADDR(data[0])) {
#        ifdef AMIGA_SKIP_SEG
        if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
                ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
#	 else
        {
#	 endif /* AMIGA_SKIP_SEG */
            GC_add_roots_inner((char *)&data[1],
            ((char *)&data[1]) + data[-1], FALSE);
        }
    }
}
#endif /* old version */


#endif



#ifdef GC_AMIGA_AM

#ifndef GC_AMIGA_FASTALLOC

void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)) {
    return (*AllocFunction)(size);
}

void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
    =GC_amiga_allocwrapper;

#else




void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));

void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
    =GC_amiga_allocwrapper_firsttime;


/******************************************************************
   Amiga-spesific routines to obtain memory, and force GC to give
   back fast-mem whenever possible.
	These hacks makes gc-programs go many times faster when
   the amiga is low on memory, and are therefore strictly necesarry.

   -Kjetil S. Matheussen, 2000.
******************************************************************/



/* List-header for all allocated memory. */

struct GC_Amiga_AllocedMemoryHeader {
    ULONG size;
    struct GC_Amiga_AllocedMemoryHeader *next;
};
struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);



/* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */

ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;


/* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
#ifndef GC_AMIGA_ONLYFAST
BOOL GC_amiga_dontalloc=FALSE;
#endif

#ifdef GC_AMIGA_PRINTSTATS
int succ=0,succ2=0;
int nsucc=0,nsucc2=0;
int nullretries=0;
int numcollects=0;
int chipa=0;
int allochip=0;
int allocfast=0;
int cur0=0;
int cur1=0;
int cur10=0;
int cur50=0;
int cur150=0;
int cur151=0;
int ncur0=0;
int ncur1=0;
int ncur10=0;
int ncur50=0;
int ncur150=0;
int ncur151=0;
#endif

/* Free everything at program-end. */

void GC_amiga_free_all_mem(void) {
    struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
    struct GC_Amiga_AllocedMemoryHeader *temp;

#ifdef GC_AMIGA_PRINTSTATS
    printf("\n\n"
           "%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
           allochip,allocfast
          );
    printf(
        "%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
        chipa
    );
    printf("\n");
    printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
    printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
    printf("\n");
    printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
    printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
    printf("\n");
    printf(
        "Number of retries before succeding a chip->fast force:\n"
        "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
        cur0,cur1,cur10,cur50,cur150,cur151
    );
    printf(
        "Number of retries before giving up a chip->fast force:\n"
        "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
        ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
    );
#endif

    while(gc_am!=NULL) {
        temp=gc_am->next;
        FreeMem(gc_am,gc_am->size);
        gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
    }
}

#ifndef GC_AMIGA_ONLYFAST

/* All memory with address lower than this one is chip-mem. */

char *chipmax;


/*
 * Allways set to the last size of memory tried to be allocated.
 * Needed to ensure allocation when the size is bigger than 100000.
 *
 */
size_t latestsize;

#endif


/*
 * The actual function that is called with the GET_MEM macro.
 *
 */

void *GC_amiga_get_mem(size_t size) {
    struct GC_Amiga_AllocedMemoryHeader *gc_am;

#ifndef GC_AMIGA_ONLYFAST
    if(GC_amiga_dontalloc==TRUE) {
//		printf("rejected, size: %d, latestsize: %d\n",size,latestsize);
        return NULL;
    }

    // We really don't want to use chip-mem, but if we must, then as little as possible.
    if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
#endif

    gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
    if(gc_am==NULL) return NULL;

    gc_am->next=GC_AMIGAMEM;
    gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
    GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));

//	printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize);

#ifdef GC_AMIGA_PRINTSTATS
    if((char *)gc_am<chipmax) {
        allochip+=size;
    } else {
        allocfast+=size;
    }
#endif

    return gc_am+1;

}




#ifndef GC_AMIGA_ONLYFAST

/* Tries very hard to force GC to find fast-mem to return. Done recursively
 * to hold the rejected memory-pointers reachable from the collector in an
 * easy way.
 *
 */
#ifdef GC_AMIGA_RETRY
void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec) {
    void *ret;

    ret=(*AllocFunction)(size);

#ifdef GC_AMIGA_PRINTSTATS
    if((char *)ret>chipmax || ret==NULL) {
        if(ret==NULL) {
            nsucc++;
            nsucc2+=size;
            if(rec==0) ncur0++;
            if(rec==1) ncur1++;
            if(rec>1 && rec<10) ncur10++;
            if(rec>=10 && rec<50) ncur50++;
            if(rec>=50 && rec<150) ncur150++;
            if(rec>=150) ncur151++;
        } else {
            succ++;
            succ2+=size;
            if(rec==0) cur0++;
            if(rec==1) cur1++;
            if(rec>1 && rec<10) cur10++;
            if(rec>=10 && rec<50) cur50++;
            if(rec>=50 && rec<150) cur150++;
            if(rec>=150) cur151++;
        }
    }
#endif

    if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))) {
        ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
//		GC_free(ret2);
    }

    return ret;
}