gcfuncs.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 754 行 · 第 1/2 页
C
754 行
/* * gcFuncs.c * Methods to implement gc-related activities of objects and classes * * Copyright (c) 1996, 1997, 1998, 1999 * Transvirtual Technologies, Inc. All rights reserved. * * Copyright (c) 2004 * Kaffe.org contributors. See ChangeLog for details. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. *//* * This file contains those functions that have to do with gc */#include "config.h"#include "debug.h"#include "config-std.h"#include "config-mem.h"#include "defs.h"#include "gtypes.h"#include "slots.h"#include "access.h"#include "object.h"#include "errors.h"#include "code.h"#include "file.h"#include "readClass.h"#include "classMethod.h"#include "baseClasses.h"#include "stringSupport.h"#include "thread.h"#include "jthread.h"#include "itypes.h"#include "bytecode.h"#include "exception.h"#include "md.h"#include "external.h"#include "lookup.h"#include "support.h"#include "gc.h"#include "locks.h"#include "md.h"#include "jni.h"#include "soft.h"#include "thread.h"#include "jvmpi_kaffe.h"#include "methodcalls.h"/***************************************************************************** * Class-related functions *//* * Destroy a class object. */static void/* ARGSUSED */destroyClass(Collector *collector, void* c){ int i; unsigned int idx; Hjava_lang_Class* clazz = c; constants* pool;DBG(CLASSGC, dprintf("destroying class %s @ %p\n", clazz->name ? clazz->name->data : "newborn", c); ); assert(!CLASS_IS_PRIMITIVE(clazz)); /* NB: Make sure that we don't unload fully loaded classes without * classloaders. This is wrong and indicate of a bug. * * NB: Note that this function must destroy any partially * initialized class. Class processing may fail at any * state, and the discarded class objects destroyed. */ assert(clazz->state != CSTATE_COMPLETE || clazz->loader != 0);#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_CLASS_UNLOAD) && clazz->state >= CSTATE_PREPARED) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_CLASS_UNLOAD; ev.u.class_unload.class_id = c; jvmpiPostEvent(&ev); }#endif if (Kaffe_JavaVMArgs.enableVerboseGC > 0 && clazz->name) { DBG(CLASSGC, dprintf("<GC: unloading class `%s'>\n", CLASS_CNAME(clazz)); ); } /* destroy all fields */ if (CLASS_FIELDS(clazz) != 0) { Field *f = CLASS_FIELDS(clazz); for (i = 0; i < CLASS_NFIELDS(clazz); i++) { utf8ConstRelease(f->name); /* if the field was never resolved, we must release the * Utf8Const to which its type field points */ utf8ConstRelease(f->signature); f++; } KFREE(CLASS_FIELDS(clazz)); } /* destroy all methods, only if this class has indeed a method table */ if (!CLASS_IS_ARRAY(clazz) && Kaffe_get_class_methods(clazz) != NULL) { Method *m = Kaffe_get_class_methods(clazz); for (i = 0; i < CLASS_NMETHODS(clazz); i++) { void *ncode = NULL; if (!CLASS_IS_INTERFACE(clazz)) { ncode = METHOD_NATIVECODE(m); if (METHOD_JITTED(m)) {#if defined(TRANSLATOR) && defined (MD_UNREGISTER_JIT_EXCEPTION_INFO) MD_UNREGISTER_JIT_EXCEPTION_INFO (getMethodCodeStart(m), ncode, m->c.ncode.ncode_end);#endif#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_COMPILED_METHOD_UNLOAD) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_COMPILED_METHOD_UNLOAD; ev.u.compiled_method_unload. method_id = m; jvmpiPostEvent(&ev); }#endif } } utf8ConstRelease(m->name); utf8ConstRelease(METHOD_SIG(m)); KFREE(METHOD_PSIG(m)); KFREE(m->lines); KFREE(m->lvars); if( m->ndeclared_exceptions != -1 ) KFREE(m->declared_exceptions); KFREE(m->exception_table); /* ncode is swept by the GC. */ m++; } KFREE(Kaffe_get_class_methods(clazz)); } /* release remaining refs to utf8consts in constant pool */ pool = CLASS_CONSTANTS (clazz); for (idx = 0; idx < pool->size; idx++) { switch (pool->tags[idx]) { case CONSTANT_String: /* unresolved strings */ case CONSTANT_Utf8: utf8ConstRelease(WORD2UTF(pool->data[idx])); break; default: break; } } /* free constant pool */ if (pool->data != NULL) { KFREE(pool->data); } /* free various other fixed things */ KFREE(CLASS_STATICDATA(clazz)); if(clazz->vtable != NULL) { /* The native methods in the vtable are swept by the GC. */ KFREE(clazz->vtable); } KFREE(clazz->if2itable); if (clazz->implementors != NULL) { uintp len, uidx; len = (uintp)clazz->implementors[0] + 1; for (uidx = 1; uidx < len; uidx++) { void *impl = clazz->implementors[uidx]; Hjava_lang_Class **impl_clazz; if (impl == NULL) continue; impl_clazz = (Hjava_lang_Class **)KGC_getObjectBase(collector, impl); assert(impl_clazz != NULL); /* We must walk the list of interfaces for this class and * unregister this interface. As the class should also be * freed (in the other case this interface would not have * been destroyed), there is no problem with this. */ for (i = 0; i < (*impl_clazz)->total_interface_len; i++) if ((*impl_clazz)->interfaces[i] == clazz) { (*impl_clazz)->interfaces[i] = NULL; /* We cannot break here because there may exist * duplicates in the current list. */ } } KFREE(clazz->implementors); } if (clazz->interfaces) gc_rm_ref(clazz->interfaces); if( clazz->itable2dtable ) { for (i = 0; i < clazz->total_interface_len; i++) { Hjava_lang_Class* iface = clazz->interfaces[i]; /* only if interface has not been freed already. We * update the implementors section of the interface * accordingly. */ if (iface != NULL) iface->implementors[clazz->impl_index] = NULL; } /* The itable2dtable table will be automatically swept by the * GC when the class becomes unused as it is only marked while * the class is being walked (see walkClass). */ KGC_rmRef(collector, clazz->itable2dtable); } if (clazz->gc_layout != NULL && clazz->superclass != NULL && getSuperclass(clazz)->gc_layout != clazz->gc_layout) KFREE(clazz->gc_layout); KFREE(clazz->sourcefile); KFREE(clazz->inner_classes); utf8ConstRelease(clazz->name);}/* * Walk the methods of a class. */staticvoidwalkMethods(Collector* collector, void *gc_info, Method* m, int nm){ while (nm-- > 0) { int objIndex; KGC_markObject(collector, gc_info, m->class); objIndex = KGC_getObjectIndex(collector, m->ncode); if (objIndex == KGC_ALLOC_JITCODE || objIndex == KGC_ALLOC_TRAMPOLINE) KGC_markObject(collector, gc_info, m->ncode); objIndex = KGC_getObjectIndex(collector, m->c.bcode.code); if (objIndex == KGC_ALLOC_JITCODE || objIndex == KGC_ALLOC_TRAMPOLINE || objIndex == KGC_ALLOC_BYTECODE) KGC_markObject(collector, gc_info, m->c.bcode.code); /* walk exception table in order to keep resolved catch types alive */ if (m->exception_table != 0) { jexceptionEntry* eptr = &m->exception_table->entry[0]; unsigned int i; for (i = 0; i < m->exception_table->length; i++) { Hjava_lang_Class* c = eptr[i].catch_type; if (c != 0 && c != UNRESOLVABLE_CATCHTYPE) { KGC_markObject(collector, gc_info, c); } } } m++; }}/* * Walk a class object. */static voidwalkClass(Collector* collector, void *gc_info, void* base, uint32 size UNUSED){ Hjava_lang_Class* class; Field* fld; int n; constants* pool; unsigned int idx; iLock *lk; class = (Hjava_lang_Class*)base;DBG(GCPRECISE, dprintf("walkClass `%s' state=%d\n", CLASS_CNAME(class), class->state); ); lk = GET_HEAVYLOCK(class->lock); if (lk != NULL && KGC_getObjectIndex(collector, lk) == KGC_ALLOC_LOCK) KGC_markObject(collector, gc_info, lk); lk = GET_HEAVYLOCK(class->head.lock); if (lk != NULL && KGC_getObjectIndex(collector, lk) == KGC_ALLOC_LOCK) KGC_markObject(collector, gc_info, lk); if (class->state >= CSTATE_PREPARED) { KGC_markObject(collector, gc_info, class->superclass); } if (class->itable2dtable != NULL) { unsigned int len = class->if2itable[class->total_interface_len]; KGC_markObject(collector, gc_info, class->itable2dtable); for (idx = 1; idx < len; idx++) { void *method = class->itable2dtable[idx]; int objIndex; if (method == (void*)-1) continue; objIndex = KGC_getObjectIndex(collector, method); if (objIndex == KGC_ALLOC_JITCODE || objIndex == KGC_ALLOC_TRAMPOLINE) KGC_markObject(collector, gc_info, method); } } /* walk constant pool - only resolved classes and strings count */ pool = CLASS_CONSTANTS(class); for (idx = 0; idx < pool->size; idx++) { switch (pool->tags[idx]) { case CONSTANT_ResolvedClass: assert(!CLASS_IS_PRIMITIVE(CLASS_CLASS(idx, pool))); KGC_markObject(collector, gc_info, CLASS_CLASS(idx, pool)); break; case CONSTANT_ResolvedString: KGC_markObject(collector, gc_info, (void*)pool->data[idx]); break; default: break; } } /* walk the local vtable */ if (class->vtable != NULL && !CLASS_IS_PRIMITIVE(class)) for (idx = 0; idx < class->msize; idx++) { void *method = class->vtable->method[idx]; int objIndex = KGC_getObjectIndex(collector, method); if (objIndex == KGC_ALLOC_JITCODE || objIndex == KGC_ALLOC_TRAMPOLINE || objIndex == KGC_ALLOC_BYTECODE) KGC_markObject(collector, gc_info, method); } /* * NB: We suspect that walking the class pool should suffice if * we ensured that all classes referenced from this would show up * as a ResolvedClass entry in the pool. However, this is not
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?