📄 gc2.c
字号:
/* * gc2.c * This interfaces the VM to the Hans-J. Boehm Incremental Garbage * Collector (version 6.3) * * Copyright (c) 2001 * Transvirtual Technologies, Inc. All rights reserved. * * Copyright (c) 2004-2005 * The Kaffe.org's developers. All rights reserved. * See ChangeLog for details. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "config-std.h"#include "config-mem.h"#include "jni_md.h"#include "access.h"#include "classMethod.h"#include "locks.h"#include "errors.h"#include "boehm/include/gc.h"#include "boehm/include/gc_mark.h"#include "gtypes.h"#include "java_lang_Thread.h"#include "debug.h"#include "thread.h"#include "gc-refs.h"#include "gc-kaffe.h"#include "gc2.h"#include "jvmpi_kaffe.h"/* * This record describes an allocation type. */typedef struct _gcFuncs { walk_func_t walk; final_func_t final; destroy_func_t destroy; const char* description; int nr; /* only used ifdef STATS */ int mem; /* only used ifdef STATS */} gcFuncs;static iStaticLock gcman_lock;static iStaticLock gcmanend_lock;static iStaticLock finman_lock;static volatile int finalRunning = -1; static volatile int gcRunning = -1;static volatile int gcDisabled = 0;static Hjava_lang_Thread* finalman;static Hjava_lang_Thread* garbageman;static ssize_t KGC_max_heap_size;#define GCSTACKSIZE (1024*1024)#define FINALIZERSTACKSIZE (128*1024)typedef struct{ struct _Collector collector;} BoehmGarbageCollector;static BoehmGarbageCollector boehm_gc;#define MAGIC_GC 0xcaffe130static inline voidclearAndAddDescriptor(void *mem, MemDescriptor *desc){ MemDescriptor *idx = (MemDescriptor *)mem; *idx = *desc; memset(ALIGN_FORWARD(idx), 0, desc->memsize);}static void KaffeGC_InvokeGC(Collector* gcif, int mustgc); /* ===================================================================== * GC Type handling * --------------------------------------------------------------------- */static gcFuncs gcFunctions[KGC_ALLOC_MAX_INDEX];/* * register an allocation type under a certain index * NB: we could instead return a pointer to the record describing the * allocation type. This would give us more flexibility, but it wouldn't * allow us to use compile-time constants. */static voidregisterTypeByIndex(gc_alloc_type_t idx, walk_func_t walk, final_func_t final, destroy_func_t destroy, const char *description){ /* once only, please */ assert (gcFunctions[idx].description == 0); /* don't exceed bounds */ assert (idx < sizeof(gcFunctions)/sizeof(gcFunctions[0])); gcFunctions[idx].walk = walk; gcFunctions[idx].final = final; gcFunctions[idx].destroy = destroy; gcFunctions[idx].description = description;}/* * Register a fixed allocation type. The only reason we tell them apart * is for statistical purposes. */static voidKaffeGC_RegisterFixedTypeByIndex (Collector* gcif UNUSED, gc_alloc_type_t idx, const char *description){ registerTypeByIndex(idx, 0, KGC_OBJECT_FIXED, 0, description);}/* * Register a allocation type that is subject to gc. */static voidKaffeGC_RegisterGcTypeByIndex (Collector* gcif UNUSED, gc_alloc_type_t idx, walk_func_t walk, final_func_t final, destroy_func_t destroy, const char *description){ registerTypeByIndex(idx, walk, final, destroy, description);}/* ===================================================================== * Finalizer * --------------------------------------------------------------------- */staticvoidfinalizeObject(void* ob, UNUSED void* descriptor){ MemDescriptor *desc = (MemDescriptor *)ob; gcFuncs *f = &gcFunctions[desc->memtype]; assert(desc->magic == MAGIC_GC); if (f->final != KGC_OBJECT_NORMAL && f->final != NULL && desc->needFinal) { f->final(&boehm_gc.collector, ALIGN_FORWARD(ob)); desc->needFinal = false; GC_REGISTER_FINALIZER_NO_ORDER(ob, finalizeObject, 0, 0, 0); return; }#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_OBJECT_FREE) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_OBJECT_FREE; ev.u.obj_free.obj_id = ALIGN_FORWARD(ob); jvmpiPostEvent(&ev); }#endif KaffeGC_clearWeakRef(&boehm_gc.collector, ALIGN_FORWARD(ob)); if (f->destroy != NULL) f->destroy(&boehm_gc.collector, ALIGN_FORWARD(ob));}static void NONRETURNINGfinaliserMan(void* arg UNUSED){ lockStaticMutex(&finman_lock); for (;;) { finalRunning = 0; while (finalRunning == 0) { waitStaticCond(&finman_lock, (jlong)0); } assert(finalRunning == 1); GC_invoke_finalizers(); /* Wake up anyone waiting for the finalizer to finish */ broadcastStaticCond(&finman_lock); } unlockStaticMutex(&finman_lock);}staticvoidKaffeGC_SignalFinalizer(void){ lockStaticMutex(&finman_lock); if (finalRunning == 0) { finalRunning = 1; signalStaticCond(&finman_lock); } unlockStaticMutex(&finman_lock);}static voidKaffeGC_InvokeFinalizer(Collector *gcif){ KaffeGC_InvokeGC(gcif, 1); KaffeGC_SignalFinalizer();}/* ===================================================================== * Garbage Collector * --------------------------------------------------------------------- *//* * Explicity invoke the garbage collector and wait for it to complete. */staticvoidKaffeGC_InvokeGC(Collector* gcif UNUSED, int mustgc){ while (gcRunning < 0) KTHREAD(yield)(); lockStaticMutex(&gcman_lock); if (gcRunning == 0) { gcRunning = mustgc ? 2 : 1; if (!gcDisabled) signalStaticCond(&gcman_lock); } lockStaticMutex(&gcmanend_lock); unlockStaticMutex(&gcman_lock); while (gcRunning != 0) { waitStaticCond(&gcmanend_lock, (jlong)0); } unlockStaticMutex(&gcmanend_lock);}static void NONRETURNINGgcMan(UNUSED void* arg){ lockStaticMutex(&gcman_lock); gcRunning = 0; for (;;) { while (gcRunning == 0) { waitStaticCond(&gcman_lock, 0); } GC_gcollect(); /* Wake up anyone waiting for the finalizer to finish */ lockStaticMutex(&gcmanend_lock); gcRunning = 0; broadcastStaticCond(&gcmanend_lock); unlockStaticMutex(&gcmanend_lock); }}static voidKaffeGC_EnableGC(Collector* gcif UNUSED){ lockStaticMutex(&gcman_lock); gcDisabled -= 1; if( gcDisabled == 0 ) broadcastStaticCond(&gcman_lock); unlockStaticMutex(&gcman_lock);}static voidKaffeGC_DisableGC(Collector* gcif UNUSED){ lockStaticMutex(&gcman_lock); gcDisabled += 1; unlockStaticMutex(&gcman_lock);}/* ===================================================================== * Memory allocation * --------------------------------------------------------------------- */static void*KaffeGC_realloc(Collector *gcif, void* mem, size_t sz, gc_alloc_type_t type){ void *new_ptr; if (mem == NULL) return KGC_malloc(gcif, sz, type); assert(sz > 0); new_ptr = GC_realloc ( ALIGN_BACKWARD(mem), (size_t)SYSTEM_SIZE(sz)); if (new_ptr) { MemDescriptor *desc = (MemDescriptor *)new_ptr; assert(desc->magic == MAGIC_GC); if (sz > desc->memsize) { memset((void *)((uintp)new_ptr + SYSTEM_SIZE(desc->memsize)), 0, sz-desc->memsize); } desc->memtype = type; desc->memsize = sz; desc->needFinal = true; return ALIGN_FORWARD(new_ptr); } return NULL;}static voidKaffeGC_free(Collector *gcif UNUSED, void* mem){ MemDescriptor *desc = (MemDescriptor *)ALIGN_BACKWARD(mem); if (mem == NULL) return; assert(desc->magic == MAGIC_GC); GC_free(desc);}static void*KaffeGC_malloc(Collector *gcif UNUSED, size_t sz, gc_alloc_type_t type){ void* mem; MemDescriptor desc; assert(gcFunctions[type].description != NULL); assert(sz != 0); assert(sz > 0); desc.memtype = type; desc.memsize = sz; desc.magic = MAGIC_GC; desc.needFinal = true; // Allocate memory if (gcFunctions[type].final == KGC_OBJECT_FIXED) { if (type == KGC_ALLOC_THREADCTX) mem = GC_malloc_uncollectable(SYSTEM_SIZE(sz)); else mem = GC_malloc_atomic_uncollectable(SYSTEM_SIZE(sz)); } else mem = GC_kaffe_malloc(SYSTEM_SIZE(sz)); // Attach finalizer if (mem != 0) { clearAndAddDescriptor(mem, &desc); if ( gcFunctions[type].final != KGC_OBJECT_FIXED && (gcFunctions[type].final != KGC_OBJECT_NORMAL || gcFunctions[type].destroy != NULL)) { GC_REGISTER_FINALIZER_NO_ORDER(mem, finalizeObject, 0, 0, 0); } return ALIGN_FORWARD(mem); } return NULL;}/* ===================================================================== * Utilities * --------------------------------------------------------------------- */static uint32KaffeGC_GetObjectSize(Collector *gcif UNUSED, const void* mem){ MemDescriptor *desc; if (mem == NULL) return 0; desc = (MemDescriptor *)GC_base((void *)(uintp)mem); if (desc == NULL) return 0; assert(desc->magic == MAGIC_GC); return desc->memsize;}static void*KaffeGC_GetObjectBase(Collector *gcif UNUSED, void* mem){ void *ptr; if (mem == NULL) return NULL; ptr = GC_base(mem); if (ptr == NULL) return NULL; return ALIGN_FORWARD(ptr);}static int KaffeGC_GetObjectIndex(Collector *gcif UNUSED, const void *mem){ MemDescriptor *desc = (MemDescriptor *)GC_base((void *)(uintp)mem); if (desc != NULL) { assert(desc->magic == MAGIC_GC); return desc->memtype; } else return -1;}static const char*KaffeGC_GetObjectDescription(Collector* gcif, const void* mem){ int idx = KaffeGC_GetObjectIndex(gcif, mem); if (idx >= 0) return gcFunctions[idx].description; else return NULL;}static Hjava_lang_Throwable *KaffeGC_ThrowOOM(Collector* gcif UNUSED){ dprintf( "Throwing OutOfMemoryError is not implemented in Boehm-GC.\n"); KAFFEVM_ABORT(); return NULL;}static uintpKaffeGC_HeapFree(Collector *gcif UNUSED){ return GC_get_free_bytes();}static uintpKaffeGC_HeapLimit(Collector *gcif UNUSED){ return KGC_max_heap_size;}static uintpKaffeGC_HeapTotal(Collector *gcif UNUSED){ return GC_get_heap_size();}static const char *KaffeGC_getCollectorName(Collector *gcif UNUSED){ return "boehm-gc";}/* ===================================================================== * Address marking * --------------------------------------------------------------------- */static voidKaffeGC_MarkAddress(UNUSED Collector* gcif, void *gc_info, const void* mem){ gcMark *info_mark = (gcMark *)gc_info; info_mark->mark_current = GC_mark_and_push(ALIGN_BACKWARD(mem), info_mark->mark_current, info_mark->mark_limit, (GC_PTR *) info_mark->original_object);}static struct GC_ms_entry *onObjectMarking(GC_word *addr, struct GC_ms_entry * mark_stack_ptr, struct GC_ms_entry * mark_stack_limit, UNUSED GC_word env){ MemDescriptor *desc = (MemDescriptor *)addr; int type = desc->memtype; gcMark info_mark; walk_func_t walkf; /* Temporary hack. If the magic bytes are not there it means the descriptor has not * been initialized. The Boehm-Weiser GC should not call the function but it actually happens * we just silently ignore the problem. :( */ if (desc->magic != MAGIC_GC) return mark_stack_ptr; info_mark.mark_current = mark_stack_ptr; info_mark.mark_limit = mark_stack_limit; info_mark.original_object = addr; walkf = gcFunctions[type].walk; if (walkf != NULL) { walkf(&boehm_gc.collector, &info_mark, ALIGN_FORWARD(addr), desc->memsize); } return info_mark.mark_current;}/* ===================================================================== * Initialization * --------------------------------------------------------------------- */static voidKaffeGC_warnproc(char *msg, GC_word arg){DBG(GCDIAG, dprintf(msg, arg); );}static voidKaffeGC_Init(Collector *collector UNUSED){ GC_all_interior_pointers = 0; GC_finalizer_notifier = KaffeGC_SignalFinalizer; GC_java_finalization = 1; GC_finalize_on_demand = 1; GC_set_warn_proc(KaffeGC_warnproc); GC_init(); if (Kaffe_JavaVMArgs.maxHeapSize == UNLIMITED_HEAP) GC_set_max_heap_size(0); else GC_set_max_heap_size((size_t)Kaffe_JavaVMArgs.maxHeapSize); KGC_max_heap_size = Kaffe_JavaVMArgs.maxHeapSize; if (GC_get_heap_size() < (size_t)Kaffe_JavaVMArgs.minHeapSize) GC_expand_hp( Kaffe_JavaVMArgs.minHeapSize - GC_get_heap_size()); GC_kaffe_init(onObjectMarking);}/* ===================================================================== * GC starter * --------------------------------------------------------------------- */static void/* ARGSUSED */KaffeGC_Enable(Collector* collector){ errorInfo info; if (DBGEXPR(NOGC, false, true)) { /* Start the GC daemons we need */ finalman = createDaemon(&finaliserMan, "finaliser", collector, THREAD_MAXPRIO, FINALIZERSTACKSIZE, &info); garbageman = createDaemon(&gcMan, "gc", collector, THREAD_MAXPRIO, GCSTACKSIZE, &info); assert(finalman && garbageman); }}/* * vtable for object implementing the collector interface. */static struct GarbageCollectorInterface_Ops GC_Ops = { KaffeGC_getCollectorName, /* reserved */ 0, /* reserved */ 0, /* reserved */ KaffeGC_malloc, KaffeGC_realloc, KaffeGC_free, KaffeGC_InvokeGC, KaffeGC_InvokeFinalizer, KaffeGC_Init, KaffeGC_Enable, KaffeGC_MarkAddress, KaffeGC_MarkAddress, KaffeGC_GetObjectSize, KaffeGC_GetObjectDescription, KaffeGC_GetObjectIndex, KaffeGC_GetObjectBase, KaffeGC_RegisterFixedTypeByIndex, KaffeGC_RegisterGcTypeByIndex, KaffeGC_ThrowOOM, KaffeGC_EnableGC, KaffeGC_DisableGC, KaffeGC_HeapFree, KaffeGC_HeapLimit, KaffeGC_HeapTotal, KaffeGC_addRef, KaffeGC_rmRef, KaffeGC_addWeakRef, KaffeGC_rmWeakRef};/* * Initialise the Garbage Collection system. */Collector* createGC(void){ boehm_gc.collector.ops = &GC_Ops; initStaticLock(&gcman_lock); initStaticLock(&gcmanend_lock); initStaticLock(&finman_lock); KaffeGC_initRefs(); return (&boehm_gc.collector);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -