utils.c

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

C
2,268
字号
/* * @(#)utils.c	1.158 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.  * */#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/int.h"#include "javavm/include/porting/time.h"#include "javavm/include/porting/path.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/clib.h"#include "javavm/include/utils.h"#include "javavm/include/indirectmem.h"#include "javavm/include/preloader.h"#include "javavm/include/localroots.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/stacks.h"#include "javavm/include/path_md.h"#include "javavm/include/globalroots.h"#include "generated/javavm/include/build_defs.h"#include "generated/offsets/java_lang_String.h"#include "generated/offsets/java_lang_Class.h"#include "generated/offsets/java_lang_Boolean.h"#include "generated/offsets/java_lang_Character.h"#include "generated/offsets/java_lang_Float.h"#include "generated/offsets/java_lang_Double.h"#include "generated/offsets/java_lang_Byte.h"#include "generated/offsets/java_lang_Short.h"#include "generated/offsets/java_lang_Integer.h"#include "generated/offsets/java_lang_Long.h"#include "generated/offsets/java_lang_Throwable.h"#ifdef CVM_CLASSLOADING#include "generated/offsets/java_lang_ClassLoader.h"#endif#ifdef CVM_DEBUG#include "generated/offsets/java_lang_Thread.h"#endif#include "jni_util.h"/* * Console I/O. Same as printf, but supports special formats like * %C, %P, and %F. See CVMformatStringVaList for details. * * WARNING: may crash if you pass bad arguments. See CVMformatStringVaList * for details on safety checking limitations. */voidCVMconsolePrintf(const char* format, ...){    va_list argList;    char buf[256];    va_start(argList, format);    CVMformatStringVaList(buf, sizeof(buf), format, argList);    va_end(argList);    fprintf(stderr, "%s", buf);    fflush(stderr);}/* * Dump an exception using CVMconsolePrintf. Useful for failures during * vm startup and for debugging in gdb. */voidCVMdumpException(CVMExecEnv* ee) {    CVMClassBlock* exceptionCb;    CVMObjectICell* exceptionICell = CVMID_getGlobalRoot(ee);    CVMStringICell* exceptionMessage;    /* print the exception class name */    CVMID_objectGetClass(ee, CVMlocalExceptionICell(ee), exceptionCb);    CVMconsolePrintf("%C: ", exceptionCb);    if (exceptionICell == NULL) {      CVMconsolePrintf("backtrace not available\n");      return;    }    /* Fetch and clear the exception. Required if calling CVMprintStackTrace */    CVMID_icellAssign(ee, exceptionICell,		      CVMlocalExceptionICell(ee));    CVMclearLocalException(ee);    /* print the exception detailedMessage if there is one */    exceptionMessage = CVMID_getGlobalRoot(ee);    if (exceptionMessage != NULL) {        CVMID_fieldReadRef(ee, exceptionICell,         	       CVMoffsetOfjava_lang_Throwable_detailMessage,		       exceptionMessage);        if (!CVMID_icellIsNull(exceptionMessage)) {	    JNIEnv* env = CVMexecEnv2JniEnv(ee);	    const char* str =		    CVMjniGetStringUTFChars(env, exceptionMessage, NULL);	    if (str != NULL) {	        CVMconsolePrintf("%s", str);	        CVMjniReleaseStringUTFChars(env, exceptionMessage, str);	    } else {		CVMclearLocalException(ee);	    }        }        CVMconsolePrintf("\n");        CVMID_freeGlobalRoot(ee, exceptionMessage);    }    /* print the exception backtrace */    CVMprintStackTrace(ee, exceptionICell, NULL);    /* restore the local exception */    CVMID_icellAssign(ee, CVMlocalExceptionICell(ee),		      exceptionICell);    /* delete the global root */    CVMID_freeGlobalRoot(ee, exceptionICell);}/* * Random number generation. * * Standard, well-known linear congruential random generator with * *     s(n+1) = 16807 * s(n) mod(2^31 - 1) * * For references, see: * * (1) "Random Number Generators: Good Ones Are Hard to Find", *      S.K. Park and K.W. Miller, Communications of the ACM 31:10  *      (Oct 1988), * * (2) "Two Fast Implementations of the 'Minimal Standard' Random  *     Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990),  *     pp. 87-88.  */CVMInt32CVMrandomNext(){    const CVMInt32 a = 16807;    const CVMInt32 m = 2147483647;    CVMInt32 lastRandom = CVMglobals.lastRandom;        /* compute az=2^31p+q */    CVMUint32 lo = a * (CVMInt32)(lastRandom & 0xFFFF);    CVMUint32 hi = a * (CVMInt32)((CVMUint32)lastRandom >> 16);    lo += (hi & 0x7FFF) << 16;        /* if q overflowed, ignore the overflow and increment q */    if (lo > m) {	lo &= m;	++lo;    }    lo += hi >> 15;        /* if (p+q) overflowed, ignore the overflow and increment (p+q) */    if (lo > m) {	lo &= m;	++lo;    }    CVMglobals.lastRandom = lo;    return lo;}voidCVMrandomInit(){    CVMInt32 seed;    CVMInt64 millis = CVMtimeMillis();    seed = CVMlong2Int(millis);    if (seed == 0) {	seed = 32461;    }    CVMglobals.lastRandom = seed;}/* * Functions for accessing the debugging flags. All of the following functions * return the previous state of the flag. * * You can pass in more than one flag at a time to any of the functions. */#ifdef CVM_TRACE_ENABLED/* NOTE: CVMcheckDebugFlags() is a macro and is defined in utils.h. */CVMInt32CVMsetDebugFlags(CVMInt32 flags){    CVMInt32 result = CVMcheckDebugFlags(flags);    CVMInt32 oldValue = CVMglobals.debugFlags;    CVMInt32 newValue = CVMglobals.debugFlags | flags;    CVMglobals.debugFlags = newValue;    CVMtraceReset(oldValue, newValue);    return result;}CVMInt32CVMclearDebugFlags(CVMInt32 flags){    CVMInt32 result = CVMcheckDebugFlags(flags);    CVMInt32 oldValue = CVMglobals.debugFlags;    CVMInt32 newValue = CVMglobals.debugFlags & ~flags;    CVMglobals.debugFlags &= ~flags;    CVMtraceReset(oldValue, newValue);    return result;}CVMInt32CVMrestoreDebugFlags(CVMInt32 flags, CVMInt32 oldvalue){    CVMInt32 result = CVMcheckDebugFlags(flags);    CVMInt32 oldValue = CVMglobals.debugFlags;    CVMInt32 newValue = (CVMglobals.debugFlags & ~flags) | oldvalue;    CVMglobals.debugFlags = newValue;    CVMtraceReset(oldValue, newValue);    return result;}#endif /* CVM_TRACE_ENABLED */#if defined(CVM_DEBUG) || defined(CVM_TRACE_ENABLED)void CVMlong2String(CVMInt64 number, char *s, char *limit){#undef MAGIC#define MAGIC    10000000       /* slightly more than (2^64) ^ (1/3) */    int group1, group2, group3;    CVMInt64 group1l, group2l, group3l;    CVMInt64 magic;    char *sign;    if (CVMlongGez(number)) {        sign = "";	/* number = -number */	number = CVMlongNeg(number);	/* this lets -2^63 still work! */    } else {        sign = "-";    }#if 0    group3 = -(number % MAGIC); /* low 7 digits */    number = (number + group3)/MAGIC;    group2 = -(number % MAGIC); /* next 7 digits */    number = (number + group2)/MAGIC;    group1 = -number;           /* high 7 digits */#endif    magic = CVMint2Long(MAGIC);    group3l = CVMlongRem(number, magic); /* low 7 digits */    group3l = CVMlongNeg(group3l);    number = CVMlongAdd(number, group3l);    number = CVMlongDiv(number, magic); /* truncate middle 7 digits */    group2l = CVMlongRem(number, magic); /* next 7 digits */    group2l = CVMlongNeg(group2l);    number = CVMlongAdd(number, group2l);    number = CVMlongDiv(number, magic); /* truncate middle 7 digits */    group1l = CVMlongNeg(number);         /* high 7 digits */    group1 = CVMlong2Int(group1l);    group2 = CVMlong2Int(group2l);    group3 = CVMlong2Int(group3l);    if (group1 != 0) {	(void) sprintf(s, "%s%d%07d%07d", sign, group1, group2, group3);    } else if (group2 != 0) {	(void) sprintf(s, "%s%d%07d", sign, group2, group3);    } else {	(void) sprintf(s, "%s%d", sign, group3);    }}#endif/* * CVMdumpThread - prints thread name and stack trace. */#ifdef CVM_DEBUGvoidCVMdumpThread(JNIEnv* env){    CVMExecEnv *ee = CVMjniEnv2ExecEnv(env);    CVMconsolePrintf("Thread \"");    CVMprintThreadName(env, CVMcurrentThreadICell(ee));    CVMconsolePrintf("\"\n");#ifdef CVM_DEBUG_DUMPSTACK    CVMdumpStack(&ee->interpreterStack, 0, 0, 0);#endif}static voidCVMdumpThreadFromEENoAlloc(CVMExecEnv* ee){    CVMconsolePrintf("Thread ee=0x%x, ID=%d\n", ee, ee->threadID);#ifdef CVM_DEBUG_DUMPSTACK    CVMdumpStack(&ee->interpreterStack, 0, 0, 0);#endif}voidCVMdumpAllThreads(){    CVMExecEnv* ee = CVMgetEE();        CVMsysMutexLock(ee, &CVMglobals.threadLock);    CVM_WALK_ALL_THREADS(ee, currentEE, {	/*	 * Ideally, we should be calling CVMdumpThread() here. But we	 * are not allowed to allocate within CVM_WALK_ALL_THREADS(), so	 * we call a non-allocating version of a thread dump that does not	 * print the thread's name.	 */	CVMdumpThreadFromEENoAlloc(currentEE);	CVMconsolePrintf("\n");    });    CVMsysMutexUnlock(ee, &CVMglobals.threadLock);}voidCVMprintThreadName(JNIEnv* env, CVMObjectICell* threadICell){    CVMExecEnv *ee = CVMjniEnv2ExecEnv(env);    jchar *charArrayElements;    jobject nameString;    const char* name;    /* mixes local roots and JNI */    CVMID_localrootBegin(ee) {	CVMID_localrootDeclare(CVMObjectICell, nameICell);	CVMID_fieldReadRef(ee, threadICell,			   CVMoffsetOfjava_lang_Thread_name,			   nameICell);	if (!CVMID_icellIsNull(nameICell)) {	    charArrayElements =		(*env)->GetCharArrayElements(env, (jcharArray) nameICell,					     NULL);	    nameString =		(*env)->NewString(env, charArrayElements,				  (*env)->GetArrayLength(env,							 (jarray) nameICell));	    name = (*env)->GetStringUTFChars(env, nameString, NULL);	    CVMconsolePrintf("%s", name);	    (*env)->ReleaseStringUTFChars(env, nameString, name);	    (*env)->ReleaseCharArrayElements(env, (jcharArray) nameICell,					     charArrayElements, JNI_ABORT);	} else {	    CVMconsolePrintf("<unnamed thread>");	}    } CVMID_localrootEnd();}#endif/* * CVMclassname2String - copies the class name in src to dst, converting * each '/' to '.' in the process. */char*CVMclassname2String(CVMClassTypeID typeID, char *dst, int size){    char *buf = dst;    CVMtypeidClassNameToCString(typeID, dst, size);    for (; (--size > 0) && (*dst != '\0') ;  dst++) {	if (*dst == '/') {	    *dst = '.';	}    }    return buf;}/* * Returns the size of the utf8 char. */static intCVMutfCharSize(const char* utfstring) {    switch ((CVMUint8)utfstring[0] >> 4) {    default:	return 1;	    case 0xC: case 0xD:		/* 110xxxxx  10xxxxxx */	return 2;	    case 0xE:	/* 1110xxxx 10xxxxxx 10xxxxxx */	return 3;    } /* end of switch */}/* * Returns # of unicode chars needed to represent the utf8 string */CVMSizeCVMutfLength(const char* utf8string){    CVMSize length;    for (length = 0; *utf8string != 0; length++) {       utf8string += CVMutfCharSize(utf8string);    }    return length;}/* * Copy a utf8 array into a counted unicode array. * Return number of UTF characters moved from the source. * This is to allow a user to re-start the copying at a known * stopping point. */intCVMutfCountedCopyIntoCharArray(    const char * utf8Bytes,    CVMJavaChar* unicodeChars,    CVMSize      unicodeLength){    int nutf = 0;    while( unicodeLength-- > 0 ){	char utfchar = *utf8Bytes++;	CVMJavaChar t;	switch ( utfchar & 0xf0 ){	default:	    *unicodeChars++ = utfchar;	    nutf+= 1;	    continue;	case 0xC0: case 0xD0:	    /* 110xxxxx  10xxxxxx */	    *unicodeChars++ = ((utfchar&0x1f)<<6) | ((*utf8Bytes++)&0x3f);	    nutf+= 2;	    continue;	    

⌨️ 快捷键说明

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