stringintern.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,144 行 · 第 1/3 页
C
1,144 行
/* * @(#)stringintern.c 1.38 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/defs.h"#include "javavm/export/jni.h"#include "native/common/jni_util.h"#include "javavm/include/indirectmem.h"#include "javavm/include/localroots.h"#include "generated/offsets/java_lang_String.h"#include "javavm/include/string_impl.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/globals.h"#undef MIN#define MIN(a,b) (((a)<(b))?(a):(b))/* #define CVMInternSegmentSize 943 / * or 2003, choose one. * / struct CVMInternSegment { struct CVMInternSegment * next; CVMUint32 capacity; CVMUint32 load; CVMUint32 maxLoad; CVMStringICell data[capacity]; CVMUint8 refCount[capacity]; } CVMInternSegment; / * // count == 255 means unused (CVMInternUnused) // count == 254 means sticky (CVMInternSticky) // count == 253 means deleted!! (CVMInternDeleted) * /*//* * Acceptable segment sizes. * All must be relatively prime to the secondary hash, h1, * and, as a bonus, should be relatively prime to 37, used * in the initial hash value computation * Since 1 <= h1 <= 16, these sizes cannot contain the * factors 2, 3, 5, 7, 11, or 13. */static const int CVMinternSegmentSizes[] = { 943, /* 41*23 */ 1511, /* prime */ 2147, /* 113 * 19 */ 3233, /* 61 * 53 */ 4891, /* 73 * 67 */ 7313, /* 103 * 71 */ 10961, /* 113 * 97 */ 15943 /* 149 * 107 */};#define CVM_INTERN_INITIAL_SEGMENT_SIZE_IDX 0#define CVM_INTERN_MAX_SEGMENT_SIZE_IDX 7#ifdef CVM_DEBUG/* * CALL ONLY FROM DEBUGGER: NO LOCKING!! */static voidCVMInternValidateSegment( struct CVMInternSegment * segp, CVMBool verbose ) { int capacity, i; CVMUint8 * refCount; CVMStringICell * data; int nUnused, nSticky, nDeleted, nNoRef, nRef, nBad; CVMBool cellIsNull; /* do trivial consistancy checks first */ if ( segp->nextp == NULL ){ CVMconsolePrintf("Intern segment 0x%x->nextp == NULL\n", segp ); } else if ( verbose ){ CVMconsolePrintf("Intern segment 0x%x->nextp != NULL (OK)\n", segp ); } if ( (capacity = segp->capacity) < CVM_INTERN_INITIAL_SEGMENT_SIZE_IDX ){ /* could be ok for very small romized set, so don't panic! */ CVMconsolePrintf("Intern segment 0x%x->capacity == %d\n", segp, segp->capacity ); } else if ( verbose ){ CVMconsolePrintf("Intern segment 0x%x->capacity == %d (OK)\n", segp, segp->capacity ); } if ( segp->load > capacity ){ CVMconsolePrintf("Intern segment 0x%x->load == %d > capacity == %d\n", segp, segp->load, capacity ); } else if (verbose){ CVMconsolePrintf("Intern segment 0x%x->load == %d (OK)\n", segp, segp->load ); } if ( segp->maxLoad > (((segp->capacity*65)/100)+1) ){ CVMconsolePrintf("Intern segment 0x%x->maxLoad == %d\n", segp, segp->maxLoad ); } else if ( verbose ){ CVMconsolePrintf("Intern segment 0x%x->maxLoad == %d (OK)\n", segp, segp->maxLoad ); } /* now look at all the data. */ nUnused = nSticky = nDeleted = nNoRef = nRef = nBad = 0; refCount = CVMInternRefCount( segp ); data = segp->data; for ( i = 0; i < capacity; i++ ){ cellIsNull = CVMID_icellIsNull( &data[i] ); switch ( refCount[i] ){ case CVMInternUnused: nUnused += 1; if ( !cellIsNull ){ CVMconsolePrintf("Intern segment 0x%x->data[%d] Unused but not null\n", segp, i ); nBad += 1; } break; case CVMInternSticky: nSticky += 1; if ( cellIsNull ){ CVMconsolePrintf("Intern segment 0x%x->data[%d] Sticky but null\n", segp, i ); nBad += 1; } break; case CVMInternDeleted: nDeleted += 1; if ( !cellIsNull ){ CVMconsolePrintf("Intern segment 0x%x->data[%d] Deleted but not null\n", segp, i ); nBad += 1; } break; default: if ( refCount[i] == 0 ) nNoRef += 1; else nRef += 1; if ( cellIsNull ){ CVMconsolePrintf("Intern segment 0x%x->data[%d] null with ref count %d\n", segp, i, refCount[i] ); nBad += 1; } break; } } if ( verbose ){ CVMconsolePrintf("Intern segment 0x%x has:\n", segp ); CVMconsolePrintf(" %d unused cells\n", nUnused ); CVMconsolePrintf(" %d sticky cells\n", nSticky ); CVMconsolePrintf(" %d deleted cells\n", nDeleted ); CVMconsolePrintf(" %d 0-ref-count cells\n", nNoRef ); CVMconsolePrintf(" %d non-0-ref-count cells\n", nRef ); } if ( segp->load != ( nSticky+nDeleted+nNoRef+nRef ) ){ CVMconsolePrintf("Intern segment 0x%x->load == %d, should be %d\n", segp->load, ( nSticky+nDeleted+nNoRef+nRef ) ); } if ( nBad != 0 ){ CVMconsolePrintf("Intern segment 0x%x has %d bad cells\n", segp, nBad ); }}/* * CALL ONLY FROM DEBUGGER: NO LOCKING!! */voidCVMInternValidateAllSegments( CVMBool verbose ) { CVMInternSegment * curSeg, *nextSeg; nextSeg = (CVMInternSegment*)&CVMInternTable; /* cast away const */ do { curSeg = nextSeg; CVMInternValidateSegment( curSeg, verbose ); nextSeg = CVMInternNext(curSeg); } while ( nextSeg != NULL );}/* * CALL ONLY FROM DEBUGGER!! * Not a good user of the memory interface! * Not suitable for any general purpose whatsoever. * Assumes that we really have ASCII strings. */static voidCVMInternPrintString( CVMStringICell *icellp ){ struct java_lang_String *stringp = *(struct java_lang_String**)icellp; struct CVMArrayOfChar *datap; int i, n, off;#undef MAXINTERNPRINTLENGTH#define MAXINTERNPRINTLENGTH 20 char c[MAXINTERNPRINTLENGTH+1]; if ( stringp == NULL ){ CVMconsolePrintf("<null>"); return; } n = stringp->count; off = stringp->offset; datap = *(CVMArrayOfChar**)&(stringp->value); CVMconsolePrintf("(%d)", n ); if ( n > MAXINTERNPRINTLENGTH ) n = MAXINTERNPRINTLENGTH; for ( i = 0; i < n ; i ++ ){ c[i] = (char)(datap->elems[off++]); } c[i] = 0; CVMconsolePrintf("%s", c ); if ( n < stringp->count ) CVMconsolePrintf("...");}/* * CALL ONLY FROM DEBUGGER: NO LOCKING!! * ASSUMES SEGMENT VALIDATED ALREADY! */voidCVMInternPrintSegment( struct CVMInternSegment * segp ) { int capacity, i; CVMUint8 * refCount; CVMStringICell * data; capacity = segp->capacity; /* now look at all the data. */ refCount = CVMInternRefCount( segp ); data = segp->data; CVMconsolePrintf("Printing all Strings in 0x%x\n", segp ); for ( i = 0; i < capacity; i++ ){ switch ( refCount[i] ){ case CVMInternUnused: case CVMInternDeleted: break; case CVMInternSticky: CVMconsolePrintf(" S "); CVMInternPrintString( &data[i] ); CVMconsolePrintf("\n"); break; default: CVMconsolePrintf("%4d ", refCount[i] ); CVMInternPrintString( &data[i] ); CVMconsolePrintf("\n"); break; } }}#endif /* CVM_DEBUG */typedef CVMBool (*helperFunction)( CVMExecEnv* ee, CVMStringICell * candidate, void * stuff);typedef void (*consumerFunction)( CVMExecEnv* ee, CVMStringICell * stringCell, CVMUint8 * refCell, void * stuff);/* all our forwards for all our helper functions here */static CVMInternSegment * allocateNewSegment();static CVMBoolinternJavaCompare( CVMExecEnv* ee, CVMStringICell * candidate, void * stuff);static CVMBoolinternJavaProduce( CVMExecEnv *ee, CVMStringICell * target, void * stuff );static voidinternJavaConsume( CVMExecEnv* ee, CVMStringICell * stringCell, CVMUint8 * refCell, void * stuff);static CVMBoolinternUTFCompare( CVMExecEnv* ee, CVMStringICell * candidate, void * stuff);static CVMBoolinternUTFProduce( CVMExecEnv *ee, CVMStringICell * target, void * stuff );static voidinternUTFConsume( CVMExecEnv* ee, CVMStringICell * stringCell, CVMUint8 * refCell, void * stuff);/* * Max chars to look at when computing simple string hash value. * This constant is known by JavaCodeCompact. */#undef MAX_HASH_LENGTH#define MAX_HASH_LENGTH 16/* * If gc latency is of concern, you may want to reduce these buffer sizes. * They affect the maximum amount of time spent gc-unsafe while copying * characters from the heap to a local buffer. * Note that PREFIX_BUFFER_SIZE MUST BE > MAX_HASH_LENGTH, which is a constant * of the implementation shared with the preLoader! */#undef PREFIX_BUFFER_SIZE#define PREFIX_BUFFER_SIZE 100#undef ITERATION_BUFFER_SIZE#define ITERATION_BUFFER_SIZE 50/* * This intern function is shared by the the function that * takes a java.lang.String as an argument (called by Java code) * and the one that take a UTF8 string as an argument * (called by the linker). In order to allow us to inline * a simple (or usually, all) comparison, we require that the * string's prefix be provided us in a buffer. The length provided * (in bufferLength) must be MIN( fullStringLength, PREFIX_BUFFER_SIZE ). * * If the string is actually longer, the compare function will be called * to finish comparing the candidate to the input data. * compareData will be passed along to it. * * If the string is not alread in the table, the function produceData * will be called to (if necessary) construct the String, and fill * the slot in the table. * * a note on reference counts: * 255: unused slot, unreferenced * 254: sticky object. Immortal. ROMized or very popular * 253: used slot, but was deleted from table when reference count * went down. Needed to make hashing work! * [1, 252]: produced by class loader from UTF8 string. We trust * that class UNloading will cause these to be decremented. */static voidinternInner( CVMExecEnv * ee, CVMJavaChar buffer[], CVMSize bufferLength, CVMSize fullLength, helperFunction compare, helperFunction produce, consumerFunction consume, void * callbackData){ CVMUint32 h, h1; CVMSize i, j, n; CVMSize slotWithOpening=0; CVMSize capacity; CVMUint8 refCount; CVMUint8* refArray; CVMInternSegment* curSeg, * nextSeg, * segWithOpening = NULL; CVMStringICell * candidate; /* calculate hash code. * This is similar to the one in java.lang.String, but this * is just a coincidence. Make sure that the ROMizer uses the * same one! (in order to make this easier, we will mask off * the high order bit.) */ n = MIN(bufferLength, MAX_HASH_LENGTH); h = 0; for ( i = 0; i < n; i++ ){ h = (h*37) + buffer[i]; } h &= ~0x80000000; h1 = (h&15)+1; /* * Look through the segments until we either find a match. * or run out of places to look. Keep track of any deleted * cells we find along the way, because if we have to * do an insertion, we'd prefer to insert in one of them. */ /* too bad we have to lock ourselves against mutation */ CVMsysMutexLock(ee, &CVMglobals.internLock ); nextSeg = (CVMInternSegment*)&CVMInternTable; /* cast away const */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?