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 + -
显示快捷键?