lvm.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 857 行 · 第 1/2 页

C
857
字号
/* * @(#)lvm.c	1.10 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */#ifndef CVM_REMOTE_EXCEPTIONS_SUPPORTED#error Remote exception support is required for Logical VM#endif#include "javavm/include/defs.h"#include "javavm/include/interpreter.h"#include "javavm/include/preloader.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/globals.h"#include "javavm/include/indirectmem.h"#include "javavm/include/globalroots.h"#include "javavm/export/jni.h"#include "native/common/jni_util.h"/* For printing heavy duty debugging messages, etc. *//* #define EXTRA_DEBUG */#undef  EXTRA_DEBUG_EXEC#if defined(CVM_DEBUG) && defined(EXTRA_DEBUG)#define EXTRA_DEBUG_EXEC(cmd) cmd #else#define EXTRA_DEBUG_EXEC(cmd) ((void)0)#endif/* Debug helpers */#undef  INVALID_VAL#define INVALID_VAL (0x55555555) /* == 1431655765 */#undef  INVALID_PTR#define INVALID_PTR ((void*)INVALID_VAL)#undef  ASSERT_VALID_VAL#define ASSERT_VALID_VAL(n) CVMassert((n) != 0 && (n) != INVALID_VAL)#undef  ASSERT_VALID_PTR#define ASSERT_VALID_PTR(p) CVMassert((p) != NULL && (void*)(p) != INVALID_PTR)/* Lock for syncing modifications on a CVMLVMContext: */#undef  LVM_LOCK#define LVM_LOCK(ee)	CVMmutexLock(&CVMglobals.lvm.lvmLock)#undef  LVM_UNLOCK#define LVM_UNLOCK(ee)	CVMmutexUnlock(&CVMglobals.lvm.lvmLock)#if defined(CVM_DEBUG) && defined(EXTRA_DEBUG)voidCVMLVMcontextDumpAll(CVMExecEnv *ee){    CVMLVMContext *context;    LVM_LOCK(ee);    context = CVMglobals.lvm.contexts;    {	CVMUint32 numRef = (context != NULL)?(context->statics[0].raw):(-1);	CVMconsolePrintf("*** LVM: CVMLVMcontextDumpAll:\n");	while (context != NULL) {	    CVMconsolePrintf("\t%2d: %I, context: 0x%x\n",		context->id, context->lvmICell, context);	    /* Sanity check: the number of object references stored at the 	     * 0th slot should be the same across all the statics buffers. */	    CVMassert(numRef == context->statics[0].raw);	    CVMassert(context->next == NULL		      || context->next->prevPtr == &context->next);	    context = context->next;	}    }    LVM_UNLOCK(ee);}#endif /* CVM_DEBUG && EXTRA_DEBUG *//* * Allocate a CVMLVMContext structure, initialize it, and * link it in the list of CVMLVMContexts. */static CVMLVMContext *CVMLVMcontextAlloc(CVMExecEnv* ee, jobject lvmObj){    CVMLVMContext *context;    CVMLVMGlobals *lvm = &CVMglobals.lvm;    CVMUint32 numStatics = lvm->numStatics;    const CVMJavaVal32* staticDataMaster = lvm->staticDataMaster;    ASSERT_VALID_VAL(numStatics);    ASSERT_VALID_PTR(staticDataMaster);    /* Allocate the buffer. Note that CVMLVMContext already includes      * one slot for a static field (so subtract 1 from numStatics). */    context = (CVMLVMContext *)	malloc(sizeof(CVMLVMContext) + (numStatics-1) * sizeof(CVMJavaVal32));    if (context == NULL) {	return NULL; /* Out of memory */    }    if (lvmObj == NULL) {	/* Should be invoked during the VM startup. The main LVM is not	 * initialized.  Cannot allocate global root yet. */	CVMassert(lvm->mainLVM == NULL);    } else {	context->lvmICell = CVMID_getGlobalRoot(ee);	if (context->lvmICell == NULL) {	    free(context);	    return NULL; /* Out of memory */	}	CVMID_icellAssign(ee, context->lvmICell, lvmObj);    }    context->halting = CVM_FALSE;    /* systemClassLoader is initialized lazily in     * CVMclassGetSystemClassLoader() */    context->systemClassLoader = NULL;    /* Initialize the static fields */    memcpy(context->statics, staticDataMaster,	   numStatics * sizeof(CVMJavaVal32));    /* Link it into the linked list */    LVM_LOCK(ee);    context->id = lvm->numberOfContexts++;    {	CVMLVMContext **list= &lvm->contexts;	context->prevPtr = list;	context->next = *list;	if (*list != NULL) {	    /* At least one context exists; the main context must	     * have been initialized. */	    CVMassert(lvm->mainLVM != NULL);	    (*list)->prevPtr = &context->next;	}	*list = context;    }    LVM_UNLOCK(ee);    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM[%d]: CVMLVMcontextAlloc: "	"context: 0x%x\n", context->id, context));    return context;}static voidCVMLVMcontextFree(CVMExecEnv *ee, CVMLVMContext *context){    CVMwithAssertsOnly(CVMLVMGlobals* lvm = &CVMglobals.lvm);    /* There should be at least one context: */    ASSERT_VALID_PTR(lvm->contexts);    ASSERT_VALID_PTR(context);    ASSERT_VALID_PTR(context->prevPtr);    ASSERT_VALID_PTR(context->lvmICell);    ASSERT_VALID_VAL(context->id + 1 /* id can be 0 */);    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM[%d]: CVMLVMcontextFree: "	"context: 0x%x\n", context->id, context));    /* Unlink it from the list */    LVM_LOCK(ee);    {	*context->prevPtr = context->next;	if (context->next != NULL) {	    context->next->prevPtr = context->prevPtr;	}    }    LVM_UNLOCK(ee);    CVMID_freeGlobalRoot(ee, context->lvmICell);    if (context->systemClassLoader != NULL) {	CVMID_freeGlobalRoot(ee, context->systemClassLoader);    }    /* Invalidates entries */    CVMwithAssertsOnly({	context->prevPtr = (CVMLVMContext**)INVALID_PTR;	context->next = (CVMLVMContext*)INVALID_PTR;	context->lvmICell = (CVMObjectICell*)INVALID_PTR;	context->halting = CVM_FALSE;	context->systemClassLoader = (CVMObjectICell*)INVALID_PTR;	context->id = INVALID_VAL;	memset(context->statics, (int)((char)INVALID_VAL),	    lvm->numStatics * sizeof(CVMJavaVal32));    });    free(context);}/* * Walk through the static references referred by all the contexts. * Invoked from CVMgcScanRoots() if CVM_LVM is defined. */voidCVMLVMwalkStatics(CVMRefCallbackFunc callback, void* callbackData){    CVMLVMGlobals *lvm = &CVMglobals.lvm;    CVMLVMContext *context;    /* FIXME: This is usually only called from GC to scan all the static refs.       Consider adding an assert here to ensure that we don't call this at       other times.  Otherwise, we can have a race condition on the access of       the list of LVM contexts. */    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM: CVMLVMwalkStatics: "	"callback: 0x%x, callabckData: 0x%x\n", callback, callbackData));    context = lvm->contexts;    do {	CVMUint32 numRefStatics = context->statics[0].raw;	CVMJavaVal32* refStatics = &context->statics[1];	EXTRA_DEBUG_EXEC(CVMconsolePrintf("\t%2d: context: 0x%x, "	    "refStatics: 0x%x, " "numRefStatics: %d\n",	    context->id, context, refStatics, numRefStatics));	CVMwalkContiguousRefs(refStatics, numRefStatics, callback,                              callbackData);	context = context->next;    } while (context != NULL);}/* * Logical VM global variables initialization -- Phase 1. * Invoke this before invoking CVMinitExecEnv(). */CVMBoolCVMLVMglobalsInitPhase1(CVMLVMGlobals* lvm){    /* NOTE: CVMLVMGlobals is part of CVMGlobals.  Hence, it should contain       all 0 and NULL values to begin with.  So, instead of setting the       respective fields to 0 and NULL below, we have an assert to ensure       that the values are as we expect it. */    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM: CVMLVMglobalsInitPhase1\n"));    /* Just in case, make sure that CVM_nStaticData is not      * equal to INVALID_VAL. */    ASSERT_VALID_VAL(CVM_nStaticData);    lvm->numClasses = CVM_nROMClasses;    lvm->numStatics = CVM_nStaticData;    /* CVM_StaticDataMaster is defined as CVMInt32 by JavaCodeCompact     * for convenience of initialization.     * We cast it to the right type here. */    lvm->staticDataMaster = (CVMJavaVal32*)CVM_StaticDataMaster;    /* mainLVM will be initialized in Phase 2.     * Need to be set to NULL since CVMLVMinitExecEnv() need to behave     * differently if it is invoked for mainLVM, and this field is used     * as a flag to tell it. */    CVMassert(lvm->mainLVM == NULL);    CVMwithAssertsOnly(lvm->mainStatics = (CVMJavaVal32*)INVALID_PTR);    /* contexts will be initialized right after returning      * from this call (in CVMLVMcontextAlloc() that is invoked      * subsequently from CVMinitExecEnv()). */    CVMassert(lvm->contexts == NULL);    /* Do this here before CVMLVMinitExecEnv() gets invoked */    CVMmutexInit(&lvm->lvmLock);    CVMassert(lvm->numberOfContexts == 0);    CVMtraceLVM(("LVM: Logical VM related globals initialized:\n"	"\tNumber of target classes: %d\n"	"\tNumber of static fields: %d\n"	"\tPointer to static data master: 0x%x\n",	lvm->numClasses,	lvm->numStatics,	lvm->staticDataMaster));    return CVM_TRUE;}/* * Initialize the main (primordial) Logical VM. * Invoke private Isolate() constructor that is provided for * main Logical VM initialization only. */static jobjectCVMLVMcreateMainLVM(JNIEnv* env){    jclass cls = CVMcbJavaInstance(CVMsystemClass(sun_misc_Isolate));    jmethodID mid = CVMjniGetMethodID(env, cls, "<init>", "()V");    CVMassert(mid != NULL);    return CVMjniNewObject(env, cls, mid);}/* * Logical VM global variables initialization -- Phase 2. * Creates the main Logical VM and save a global reference to it  * into CVMglobals structure. */CVMBoolCVMLVMglobalsInitPhase2(CVMExecEnv* ee, CVMLVMGlobals* lvm){    JNIEnv* env = CVMexecEnv2JniEnv(ee);    jobject mainLVM;    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM: CVMLVMglobalsInitPhase2\n"));    /* CVMLVMglobalsInitPhase1() should have run already */    ASSERT_VALID_VAL(lvm->numClasses);    ASSERT_VALID_VAL(lvm->numStatics);    ASSERT_VALID_PTR(lvm->staticDataMaster);    /* Must have been initialized in the CVMLVMinitExecEnv() call      * against the main 'ee'. */    ASSERT_VALID_PTR(lvm->mainStatics);    /* mainLVM should be NULL as set in CVMLVMglobalsInitPhase1() */    CVMassert(lvm->mainLVM == NULL);    mainLVM = CVMLVMcreateMainLVM(env);    if (mainLVM == NULL) {	return CVM_FALSE;    }    if (!CVMLVMjobjectInit(env, mainLVM, NULL)) {	return CVM_FALSE;    }    lvm->mainLVM = CVMID_getGlobalRoot(ee);    if (lvm->mainLVM == NULL) {	CVMLVMjobjectDestroy(env, mainLVM);	return CVM_FALSE;    }    /* Hold a global reference to the main Logical VM     * throughout the lifecycle of the JVM */    CVMID_icellAssign(ee, lvm->mainLVM, mainLVM);    CVMjniDeleteLocalRef(env, mainLVM);    /* Print the mainLVM info here using %I; we cannot use %I in      * earlier stage. */    CVMtraceLVM(("LVM: Main Logical VM registered\n"));    return CVM_TRUE;}CVMBoolCVMLVMfinishUpBootstrapping(CVMExecEnv* ee){    JNIEnv* env = CVMexecEnv2JniEnv(ee);    CVMLVMGlobals* lvm = &CVMglobals.lvm;    jclass lvmCls = CVMcbJavaInstance(CVMsystemClass(sun_misc_Isolate));    jmethodID mid = CVMjniGetMethodID(env, lvmCls,				      "startMainRequestHandler", "()V");    EXTRA_DEBUG_EXEC(CVMconsolePrintf("*** LVM: "				      "CVMLVMstartMainRequestHandler\n"));    CVMassert(mid != NULL);    CVMjniCallVoidMethod(env, lvm->mainLVM, mid);    if (CVMlocalExceptionOccurred(ee)) {	CVMtraceLVM(("LVM: Error during starting the main request handler\n"));	return CVM_FALSE;    }    return CVM_TRUE;}/* * Destroy Logical VM related global states. * Free the global reference to the main Logical VM. */voidCVMLVMglobalsDestroy(CVMExecEnv* ee, CVMLVMGlobals* lvm){    ASSERT_VALID_VAL(lvm->numClasses);    ASSERT_VALID_VAL(lvm->numStatics);    ASSERT_VALID_PTR(lvm->staticDataMaster);    ASSERT_VALID_PTR(lvm->mainLVM);    ASSERT_VALID_PTR(lvm->mainStatics);    ASSERT_VALID_PTR(lvm->contexts);    /* systemClassLoader has been freed in CVMunloadApplicationclasses()      * already. Clear the reference before calling CVMLVMjobjectDestroy(). */    CVMLVMeeGetContext(ee)->systemClassLoader = NULL;    /* Free up mainLVM's context here at the end of VM execution */    CVMLVMjobjectDestroy(CVMexecEnv2JniEnv(ee), lvm->mainLVM);    CVMtraceLVM(("LVM: Main Logical VM deregistered\n"));    CVMID_freeGlobalRoot(ee, lvm->mainLVM);    CVMmutexDestroy(&lvm->lvmLock);    CVMtraceLVM(("LVM: Logical VM related globals destroyed\n"));    CVMwithAssertsOnly({	lvm->numClasses       = INVALID_VAL;	lvm->numStatics       = INVALID_VAL;	lvm->staticDataMaster = (CVMJavaVal32 *)INVALID_PTR;	lvm->mainLVM          = (jobject)INVALID_PTR;	lvm->mainStatics      = (CVMJavaVal32 *)INVALID_PTR;	lvm->contexts         = (CVMLVMContext *)INVALID_PTR;    });}/* * Initialize CVMLVMEEInitAux structure from given 'ee'. * It is used to pass Logical VM related info from parent thread to child.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?