📄 gcfuncs.c
字号:
/* * gcFuncs.c * Methods to implement gc-related activities of objects and classes * * Copyright (c) 1996, 1997, 1998, 1999 * Transvirtual Technologies, Inc. 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 "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 "gcRefs.h"#include "methodCache.h"#include "jvmpi_kaffe.h"/***************************************************************************** * Class-related functions *//* * Destroy a class object. */static void/* ARGSUSED */destroyClass(Collector *collector, void* c){ int i, j; 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) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_CLASS_UNLOAD; ev.u.class_unload.class_id = c; jvmpiPostEvent(&ev); }#endif if (Kaffe_JavaVMArgs[0].enableVerboseGC > 0 && clazz->name) { 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) && CLASS_METHODS(clazz) != 0) { Method *m = CLASS_METHODS(clazz); for (i = 0; i < CLASS_NMETHODS(clazz); i++) { void *ncode = 0; if (!CLASS_IS_INTERFACE(clazz)) { ncode = METHOD_NATIVECODE(m);#if defined(TRANSLATOR) && (defined (MD_UNREGISTER_JIT_EXCEPTION_INFO) || defined (JIT3)) if (METHOD_JITTED(m)) {#if defined(MD_UNREGISTER_JIT_EXCEPTION_INFO) MD_UNREGISTER_JIT_EXCEPTION_INFO (m->c.ncode.ncode_start, 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 }#endif } utf8ConstRelease(m->name); utf8ConstRelease(METHOD_SIG(m)); KFREE(METHOD_PSIG(m)); KFREE(m->lines); if( m->ndeclared_exceptions != -1 ) KFREE(m->declared_exceptions); KFREE(m->exception_table); KFREE(m->c.bcode.code); /* aka c.ncode.ncode_start */ /* Free ncode if necessary: this concerns * any uninvoked trampolines */ if (GC_getObjectIndex(collector, ncode) != -1) { KFREE(ncode); } m++; } KFREE(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; } } /* free constant pool */ if (pool->data != 0) { KFREE(pool->data); } /* free various other fixed things */ KFREE(CLASS_STATICDATA(clazz)); if( clazz->dtable ) { for( i = 0; i < clazz->msize; i++ ) { if( clazz->dtable->method[i] == 0 ) continue; /* Free ncode if necessary: this concerns * any uninvoked trampolines */ if (GC_getObjectIndex(collector, clazz->dtable->method[i]) == GC_ALLOC_DISPATCHTABLE) { KFREE(clazz->dtable->method[i]); } } KFREE(clazz->dtable); } KFREE(clazz->if2itable); 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 */ if (GC_getObjectIndex(collector, iface) == GC_ALLOC_CLASSOBJECT) { iface->implementors[clazz->impl_index] = -1; } } /* NB: we can't just sum up the msizes of the interfaces * here because they might be destroyed simultaneously */ j = GC_getObjectSize(collector, clazz->itable2dtable) / sizeof (void*); for( i = 0; i < j; i++ ) { if (GC_getObjectIndex(collector, clazz->itable2dtable[i]) == GC_ALLOC_DISPATCHTABLE) { GC_free(collector, clazz->itable2dtable[i]); } } GC_free(collector, clazz->itable2dtable); } if( clazz->gc_layout && (clazz->superclass->gc_layout != clazz->gc_layout) ) { KFREE(clazz->gc_layout); } KFREE(clazz->sourcefile); KFREE(clazz->implementors); KFREE(clazz->inner_classes); /* The interface table for array classes points to static memory */ if (!CLASS_IS_ARRAY(clazz)) { KFREE(clazz->interfaces); } utf8ConstRelease(clazz->name);}/* * Walk the methods of a class. */staticvoidwalkMethods(Collector* collector, Method* m, int nm){ while (nm-- > 0) {#if defined(TRANSLATOR) && 0 /* walk the block of jitted code conservatively. * Is this really needed? */ if (METHOD_TRANSLATED(m) && (m->accflags & ACC_NATIVE) == 0) { void *mem = m->c.ncode.ncode_start; if (mem != 0) { GC_walkConservative(collector, mem, GC_getObjectSize(collector, mem)); } }#endif GC_markObject(collector, m->class); /* walk exception table in order to keep resolved catch types alive */ if (m->exception_table != 0) { jexceptionEntry* eptr = &m->exception_table->entry[0]; 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) { GC_markObject(collector, c); } } } m++; }}/* * Walk a class object. */static voidwalkClass(Collector* collector, void* base, uint32 size){ Hjava_lang_Class* class; Field* fld; int n; constants* pool; int idx; class = (Hjava_lang_Class*)base;DBG(GCPRECISE, dprintf("walkClass `%s' state=%d\n", CLASS_CNAME(class), class->state); ) if (class->state >= CSTATE_PREPARED) { GC_markObject(collector, class->superclass); } /* 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))); GC_markObject(collector, CLASS_CLASS(idx, pool)); break; case CONSTANT_ResolvedString: GC_markObject(collector, (void*)pool->data[idx]); break; } } /* * 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 * currently the case: for instance, resolved field type are not * marked as resolved in the constant pool, even though they do * have an index there! XXX * * The second hypothesis is that if the class is loaded by the * system and thus anchored, then everything that we can reach from * here is anchored as well. If that property holds, we should be * able to just return if class->loader == null here. XXX */ /* walk fields */ if (CLASS_FIELDS(class) != 0) { /* walk all fields to keep their types alive */ fld = CLASS_FIELDS(class);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -