jitregman.c

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

C
2,195
字号
/* * @(#)jitregman.c	1.9 06/10/23 *  * Portions Copyright  2000-2008 Sun Microsystems, Inc. All Rights * Reserved.  Use is subject to license terms. * 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. *//* * Register manager implementation. */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/utils.h"#include "javavm/include/bcutils.h"#include "javavm/include/ccee.h"#include "javavm/include/jit/jit.h"#include "javavm/include/jit/jitir.h"#include "javavm/include/jit/jitcontext.h"#include "javavm/include/jit/jitcodebuffer.h"#include "javavm/include/jit/jitirnode.h"#include "javavm/include/jit/jitirblock.h"#include "javavm/include/jit/jitcomments.h"#include "javavm/include/jit/jitmemory.h"#include "javavm/include/jit/jitirdump.h"#include "javavm/include/jit/jitstackmap.h"#include "javavm/include/jit/jitarchemitter.h"#include "javavm/include/jit/jitregman.h"#include "javavm/include/jit/jitopcodes.h"#include "javavm/include/jit/jitstackman.h"#include "javavm/include/jit/jitgrammar.h"#include "javavm/include/clib.h"#ifdef CVM_TRACE_ENABLED#include "javavm/include/globals.h"#endif#ifdef CVM_DEBUG_ASSERTS/* FIXME: undef for now */#undef CVMJIT_STRICT_REFLOCAL_ASSERTS#endif#define RM_INITIAL_REF_COUNT_SIZE	64 /* more than ever needed */#define RM_STICKY_REF_COUNT		255#ifdef CVM_JIT_USE_FP_HARDWARE#define RM_MAX_INTERESTING_REG	(con)->maxInteresting#define RM_MIN_INTERESTING_REG	(con)->minInteresting#define RM_SAFE_SET 		(con)->safeSet#define RM_UNSAFE_SET 		(con)->unsafeSet#define RM_ANY_SET 		(con)->anySet#define RM_SINGLE_REG_ALIGN	(con)->singleRegAlignment#define RM_DOUBLE_REG_ALIGN	(con)->doubleRegAlignment#define RM_MOV_OPCODE(_con)	(_con)->movOpcode#define RM_MAX_REG_SIZE(_con)	(_con)->maxRegSize#else    /* not using FP hardware */#define RM_MAX_INTERESTING_REG	CVMCPU_MAX_INTERESTING_REG#define RM_MIN_INTERESTING_REG	CVMCPU_MIN_INTERESTING_REG#define RM_SAFE_SET 		CVMRM_SAFE_SET#define RM_UNSAFE_SET 		CVMRM_UNSAFE_SET#define RM_ANY_SET 		CVMRM_ANY_SET#define RM_SINGLE_REG_ALIGN	CVMCPU_SINGLE_REG_ALIGNMENT#define RM_DOUBLE_REG_ALIGN	CVMCPU_DOUBLE_REG_ALIGNMENT#define RM_MAX_REG_SIZE(_con)	CVMCPU_MAX_REG_SIZE#define RM_MOV_OPCODE(_con)	CVMCPU_MOV_OPCODE#endif#if defined(CVM_64)#define RM_STORE_OPCODE(_con,_res)	((_con)->storeOpcode[ (CVMRMisRef((_res)) || CVMRMisAddr((_res))) ? ((_res)->size) : ((_res)->size)-1])#define RM_LOAD_OPCODE(_con,_res)	((_con)->loadOpcode[  (CVMRMisRef((_res)) || CVMRMisAddr((_res))) ? ((_res)->size) : ((_res)->size)-1])#else#define RM_STORE_OPCODE(_con,_res)	((_con)->storeOpcode[((_res)->size)-1])#define RM_LOAD_OPCODE(_con,_res)	((_con)->loadOpcode[((_res)->size)-1])#endif   /* CVM_64 */#if ((CVMCPU_MAX_REG_SIZE != 1) || \	(defined(CVM_JIT_USE_FP_HARDWARE) && (CVMCPU_FP_MAX_REG_SIZE != 1)))/* there are some double-word registers */#define RM_NREGISTERS(_con,_size)	((_size) <= RM_MAX_REG_SIZE(_con) ? 1 : 2)#else/* all the registers are single-word */#define RM_NREGISTERS(_con,_size) 	(_size)#endif#ifdef  CVM_DEBUG_ASSERTS#define RM_INT_KEY	1#define RM_FP_KEY	2#define CVMRMassertContextMatch(cx,rp) CVMassert((cx) == (rp)->rmContext)#else#define CVMRMassertContextMatch(cx,rp)#endiftypedef enum {    CVMRM_REGPREF_TARGET,    CVMRM_REGPREF_SCRATCH,    CVMRM_REGPREF_PERSISTENT} CVMRMRegisterPreference;#define DEFAULT_CONSTANT_PREF	CVMRM_REGPREF_PERSISTENT#define DEFAULT_LOCAL_PREF	CVMRM_REGPREF_PERSISTENT#ifndef CVMCPU_NO_REGPREF_PERSISTENT#define DEFAULT_RESOURCE_PREF	CVMRM_REGPREF_PERSISTENT#else#define DEFAULT_RESOURCE_PREF  CVMRM_REGPREF_TARGET#endifstatic voidCVMRMpinResource0(CVMJITRMContext*, CVMRMResource*,    CVMRMregset target, CVMRMregset avoid,    CVMRMRegisterPreference pref, CVMBool strict);#ifdef CVM_JIT_REGISTER_LOCALSstatic voidCVMRMbindAllIncomingLocalNodes(CVMJITCompilationContext* con,			       CVMJITIRBlock* b);#endifstatic voidCVMRMbindAllUsedNodes(CVMJITCompilationContext* con, CVMJITIRBlock* b);static voidCVMRMbindUseToResource(CVMJITCompilationContext* con, CVMJITIRNode* expr);/* Purpose: Gets an available reg from the specified register set. */static intfindMaxRegInSet(    CVMJITRMContext* con,     CVMRMregset target,    int minInteresting,    int maxInteresting,    int alignment){    int i;#ifdef CVM_JIT_ROUND_ROBIN_REGISTER_SELECTION    {       /* SVMC_JIT c5041613 (dk) 2004-01-26.  round robin-based	* register selection.  The original naive strategy lead to	* massive register reuse of the largest available registers	* causing tremendous spilling overhead.	*	* Improved register selection variant is based on a round	* robin strategy.  The idea is to select that register which	* had not been selected for the longest time among all	* registers between which to choose.  This is context and flow	* insensitive, but should yield a better register utilization	* and prevent bottlenecks in register usage.  The selection is	* done in two stages: first we try to find an unoccupied	* register - subject to the round robin strategy. If none can	* be found, then we just select one and have to generate spill	* code later on. */       /* SVMC_JIT d022609 (ML) 2004-05-18. improved code. */       CVMRMResource* rp;       int mru = con->lastRegNo;       CVMRMregset o = con->occupiedRegisters;        CVMassert((minInteresting <= mru) && (mru <= maxInteresting));       if (alignment == 2) {	  minInteresting = (1 + minInteresting) & ~1 /* round up to even */;  	  maxInteresting = maxInteresting & ~1 /* round down to even */;	  mru = mru & ~1 /* round down to even */;       }       for (i = mru - alignment; i >= minInteresting; i -= alignment) {	  if (target & (1U<<i)) {	     rp = con->reg2res[i];	     if (rp == NULL) {		if (!(o & (1U<<i)))		   return i;	     }	     else {		CVMassert(!(rp->flags & CVMRMpinned));		if (!((o & (1U<<i)) && (rp->flags & CVMRMdirty)))		   return i;	     }	  }       }       for (i = maxInteresting; i >= mru; i -= alignment) {	  if (target & (1U<<i)) {	     rp = con->reg2res[i];	     if (rp == NULL) {		if (!(o & (1U<<i)))		   return i;	     }	     else {		CVMassert(!(rp->flags & CVMRMpinned));		if (!((o & (1U<<i)) 		      && (rp->flags & CVMRMdirty)))		   return i;	     }	  }       }       /* We did not find an unoccupied register. So now we try to	  select one we have to generate spill code for. */       for (i = mru - alignment; i >= minInteresting; i -= alignment) {	  if (target & (1U<<i))	     return i;       }       for (i = maxInteresting; i >= mru; i -= alignment) {	  if (target & (1U<<i))	     return i;       }    }#else /* CVM_JIT_ROUND_ROBIN_REGISTER_SELECTION */    /* The register with the highest ID value in the specified set       will be selected first: */    if (alignment == 2 )	maxInteresting &= ~1; /* round down to even */    for (i=maxInteresting; i>=minInteresting; i-= alignment ) {	if ((target & (1U<<i)) != 0)	    return i;    }#endif /* CVM_JIT_ROUND_ROBIN_REGISTER_SELECTION */    return -1;}/* Purpose: Gets an available reg from the specified register set. */static intfindMinRegInSet(    CVMRMregset target,    int minInteresting,    int maxInteresting,    int alignment,    int nregs){    int i;    /*     * Make search easier if a 32-bit pair is needed by masking off the upper     * register of each pair if the lower register is not available.      * This way we know if any bit is set, then the following bit is also set.     */    if (nregs > 1) {	target = target & (target >> 1);    }    /* The register with the lowest ID value in the specified set       will be selected first: */    CVMassert(alignment > 0);    if (alignment != 1) {	int left = (minInteresting % alignment);	if (left > 0) {	    /* round up to alignment */	    minInteresting += alignment - left;	}    }    CVMassert(minInteresting % alignment == 0);    for (i=minInteresting; i<=maxInteresting; i+= alignment ) {	if ((target & (1U<<i)) != 0)	    return i;    }    return -1;}/* * Spill Location Management. Finding and relinquishing spill locations * using CVMJITSet structures */static voidresizeSpillRefCount(CVMJITCompilationContext* con, int needed){    int newsize = needed;    CVMUint8* newallocation;    /* round up to multiple of 64 */    newsize = (newsize+63) & ~63;    CVMassert(newsize > con->RMcommonContext.spillBusyRefSize);    newallocation = CVMJITmemNew(con, JIT_ALLOC_CGEN_REGMAN,				 newsize*sizeof(CVMUint8));    memcpy(newallocation, con->RMcommonContext.spillBusyRefCount,	   con->RMcommonContext.spillBusyRefSize*sizeof(CVMUint8));    con->RMcommonContext.spillBusyRefCount = newallocation;    con->RMcommonContext.spillBusyRefSize = newsize;}static voidresetSpillMap(CVMJITCompilationContext* con, CVMJITIRBlock* b){	CVMJITRMCommonContext* common = &(con->RMcommonContext);	/* reset the spill set */	CVMJITsetClear(con, &(common->spillBusySet));	memset(common->spillBusyRefCount, 0,	       common->spillBusyRefSize * sizeof(CVMUint8));	/* mark all phiWords as busy */	if (con->maxPhiSize > 0){	    int i;	    int maxPhi = con->maxPhiSize;	    CVMUint8* refElement;	    CVMJITsetPopulate(con, &(common->spillBusySet),			      maxPhi);	    if (maxPhi > common->spillBusyRefSize){		resizeSpillRefCount(con, maxPhi);	    }	    refElement = common->spillBusyRefCount;	    for( i = 0; i < maxPhi; i++){		*(refElement++) = RM_STICKY_REF_COUNT;	    }			}	/* initialize the spill ref set */	CVMJITsetClear(con, &(con->RMcommonContext.spillRefSet));	con->RMcommonContext.maxPhiSize     = con->maxPhiSize;	con->RMcommonContext.maxSpillNumber = con->maxPhiSize-1;}int findSpillLoc(    CVMJITCompilationContext* con,    int                       size,    CVMBool                   isRef){    int spilloff, topoff;     CVMBool isBusy;    CVMJITSet*	busySet = &con->RMcommonContext.spillBusySet;    CVMUint8*   refCount=  con->RMcommonContext.spillBusyRefCount;    CVMJITSet*	refSet  = &con->RMcommonContext.spillRefSet;    CVMassert((size == 1) || (size == 2));    CVMassert((size == 1) || !isRef);    for ( spilloff = con->maxPhiSize; ;spilloff += 1){	CVMJITsetContains(busySet, spilloff, isBusy);	if (!isBusy){	    /* this one is available. If double word, look for next, too. */	    if (size > 1){		CVMJITsetContains(busySet, (spilloff+1), isBusy);		if (!isBusy){		    /* a pair of winners */		    CVMJITsetAdd(con, busySet, spilloff);		    CVMJITsetAdd(con, busySet, spilloff+1);		    CVMJITsetRemove(con, refSet, spilloff);		    CVMJITsetRemove(con, refSet, spilloff+1);		    break;		}		/* else keep trying */	    } else {		/* a winner */		CVMJITsetAdd(con, busySet, spilloff);		if (isRef){		    CVMJITsetAdd(con, refSet, spilloff);		} else {		    CVMJITsetRemove(con, refSet, spilloff);		}		break;	    }	}    }    /* location spilloff is available. see if it is a new hight water mark */    topoff = spilloff+size-1;    if (topoff > con->RMcommonContext.maxSpillNumber){	con->RMcommonContext.maxSpillNumber = topoff;    }    if (topoff >= con->RMcommonContext.spillBusyRefSize){	resizeSpillRefCount(con, topoff+1);	refCount=  con->RMcommonContext.spillBusyRefCount;    }    refCount[spilloff] = 1;    if (size > 1){	refCount[spilloff+1] = 1;    }        if (spilloff > CVMRM_MAX_SPILL_LOCATION) {        CVMJITlimitExceeded(con, "exceeding max spill locations");    }    return spilloff;}static voidrelinquishSpillLoc(CVMJITCompilationContext*con, int loc, int size){    CVMJITSet*	busySet = &con->RMcommonContext.spillBusySet;    CVMUint8*   refCount=  con->RMcommonContext.spillBusyRefCount;    CVMassert(loc>=0);    CVMassert((size == 1) || (size == 2));#ifdef CVM_DEBUG_ASSERTS    {	CVMBool isBusy;	CVMJITsetContains(busySet, loc, isBusy);	CVMassert(isBusy);	CVMassert((loc+size) <= con->RMcommonContext.spillBusyRefSize);	CVMassert(refCount[loc] > 0);	if (size > 1){	    CVMJITsetContains(busySet, (loc+1), isBusy);	    CVMassert(isBusy);	    CVMassert(refCount[loc+1] == refCount[loc]);	}    }#endif    if (refCount[loc] == RM_STICKY_REF_COUNT)	return; /* cannot deallocate */    if ((refCount[loc] -= 1) == 0){	CVMJITsetRemove(con, busySet, loc);	if (size > 1){	    CVMJITsetRemove(con, busySet, (loc+1));	}    }    if (size > 1){	refCount[loc+1] -= 1;    }}static voidincrementSpillCount(CVMJITCompilationContext*con, int loc, int size){    CVMUint8*   refCount= con->RMcommonContext.spillBusyRefCount;    CVMassert((loc+size) <= con->RMcommonContext.spillBusyRefSize);    if (refCount[loc] == RM_STICKY_REF_COUNT)	return; /* maxed out */    refCount[loc] += 1;    if (size > 1)	refCount[loc+1] += 1;}static voidflushResource(CVMJITRMContext* con, CVMRMResource* rp){

⌨️ 快捷键说明

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