cvmmethodinfo.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,382 行 · 第 1/4 页

JAVA
1,382
字号
/* * @(#)CVMMethodInfo.java	1.25 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.  * */package vm;/* * VM-specific internal representation of * a method. Target-machine independent. * * See also CVMClass for VM-specific info associated with each class. * See also CVMVM for VM-specific info not associated directly with any class. */import components.*;import vm.VMMethodInfo;import consts.Const;import consts.CVMConst;import util.DataFormatException;import java.util.Enumeration;import java.util.Vector;import java.util.Hashtable;import java.util.StringTokenizer;public classCVMMethodInfo extends VMMethodInfo implements Const, CVMConst {    private boolean		impureCode = false;    private boolean		mustAlign  = false;    private boolean		hasJsr     = false;    private boolean		isStrictFP;    private boolean		codeExamined = false;    public  MethodInfo		method;    public  CVMMethodType	sigType;    private String		myNativeName;    public CVMMethodStats.Entry statsEntry;        private int inlining;    static final int NO_INLINE_FLAG = (0x1 << 24);    static final int SAME_CLASS_FLAG = (0x1 << 25);    static final int REDO_INLINING_FLAG = (0x1 << 26);    /**     * Flag used in quickenCode() to save old methodblock info so we can     * use it here for inlining.  This affects invokevirtual_quick which     * typically overwrites the methodblock info with <methodtable offset>     * and <nargs>.     */    public static final boolean SAVE_TARGET_METHODS = true;    public CVMMethodInfo( MethodInfo m ){	method = m;	method.vmMethodInfo = this;	sigType = CVMMethodType.parseSignature( m.type.string );	this.isStrictFP = ((m.access & Const.ACC_STRICT) != 0);    }    private void examineCode( ) throws DataFormatException {	ConstantPool cp = method.parent.getConstantPool();	boolean needsTypeTable = false;	impureCode = false;	mustAlign  = false;	hasJsr     = false;	if ( method.code == null ){	    codeExamined = true;	    return;	}	byte [] code = method.code;	int	ncode  = code.length;	int	opcode;	for( int i = 0; i < ncode; i += method.opcodeLength(i)) {	    switch (opcode = (int)code[i]&0xff) {	    case opc_tableswitch:	    case opc_lookupswitch:		mustAlign = true;		break;	    case opc_jsr:	    case opc_jsr_w:		hasJsr = true;		break;	    case opc_ldc2_w:	    case opc_getstatic:	    case opc_putstatic:	    case opc_getfield:	    case opc_putfield:	    case opc_invokevirtual:	    case opc_invokespecial:	    case opc_invokestatic:	    case opc_invokeinterface:	    case opc_new:	    case opc_anewarray:	    case opc_checkcast:	    case opc_instanceof:	    case opc_multianewarray:		impureCode = true; // all get quicked.		break;	    // We don't currently quicken ldc of a Class constant	    case opc_ldc:	    {		ConstantObject co = cp.elementAt((int)code[i + 1] & 0xff);		if (!(co instanceof ClassConstant)) {		    impureCode = true; // all the rest get quickened.		} else {		    needsTypeTable = true;		}		break;	    }	    case opc_ldc_w:	    {		int index = method.getUnsignedShort(i + 1);		ConstantObject co = cp.elementAt(index);		if (!(co instanceof ClassConstant)) {		    impureCode = true; // all the rest get quickened.		} else {		    needsTypeTable = true;		}		break;	    }	    }	}	if (impureCode || needsTypeTable) {	    cp.setNeedsTypeTable();	}	codeExamined = true;    }    public boolean isCodePure() throws DataFormatException {	if ( ! codeExamined ){	    examineCode(); // may throw exception without setting codeExamined	}	return !impureCode;    }    public int alignment() throws DataFormatException {	if ( ! codeExamined ){	    examineCode(); // may throw exception without setting codeExamined	}	return mustAlign ? 4 : 1;    }    public boolean codeHasJsr() throws DataFormatException {	if ( ! codeExamined ){	    examineCode(); // may throw exception without setting codeExamined	}	return hasJsr;    }    public boolean isStrictFP() {	return isStrictFP;    }    private static int methodNumber = 0;    public String getNativeName() {	if ( myNativeName == null ){	    myNativeName = ((CVMClass)(method.parent.vmClass)).getNativeName()+ methodNumber;	    methodNumber+= 1;	}	return myNativeName;    }    public boolean    hasBody(){	return ( (method.access & (ACC_ABSTRACT|ACC_NATIVE) )== 0 );    }    public int    CVMflags(){	int flagval = 0;	int a = method.access;	if ( (a&ACC_PUBLIC) != 0 ) flagval |= CVM_METHOD_ACC_PUBLIC;	if ( (a&ACC_PRIVATE) != 0 ) flagval |= CVM_METHOD_ACC_PRIVATE;	if ( (a&ACC_PROTECTED) != 0 ) flagval |= CVM_METHOD_ACC_PROTECTED;	if ( (a&ACC_STATIC) != 0 ) flagval |= CVM_METHOD_ACC_STATIC;	if ( (a&ACC_FINAL) != 0 ) flagval |= CVM_METHOD_ACC_FINAL;	if ( (a&ACC_SYNCHRONIZED) != 0 ) flagval |= CVM_METHOD_ACC_SYNCHRONIZED;	if ( (a&ACC_NATIVE) != 0 ) flagval |= CVM_METHOD_ACC_NATIVE;	if ( (a&ACC_ABSTRACT) != 0 ) flagval |= CVM_METHOD_ACC_ABSTRACT;	return flagval;    }    public int methodOffset( ){	int off = method.methodTableIndex;	if ( off < 0 ){	    /*	     * off < 0 means that we do not have a methodtable or	     * imethodtable entry for this method. This is ok if it is:	     * - private, or	     * - static, or	     * - <init>	     * Otherwise, this is an error.	     */	    if ( method.isStaticMember( ) 		|| method.isPrivateMember( ) 		|| method.name.string.equals("<init>") ) {		    return 0;	    } else {		throw new Error("Bad method offset for "+method.qualifiedName() );	    }	}	return off;    }    /** Attempt to inline the code of this method */    final static int inline_NOT_DONE = 0;    final static int inline_IN_PROGRESS = 1;    final static int inline_DONE = 2;    private int inlineState = inline_NOT_DONE;    public void inlineCode() {        boolean isRewritten = false;	if (inlineState == inline_NOT_DONE) { 	    inlineState = inline_IN_PROGRESS;	} else { 	    return;	}	ConstantObject[] cp = method.parent.getConstantPool().getConstants();	byte[] code = method.code;	byte[] rewrite;	int tmi = 0;			// target method index	for (int pc = 0; pc < code.length; ) {	    int opcode = code[pc] & 0xff;	    switch (opcode) {	    case opc_invokevirtual_quick:	    case opc_ainvokevirtual_quick:	    case opc_dinvokevirtual_quick:	    case opc_vinvokevirtual_quick:	    case opc_invokevirtualobject_quick: {		// Target method is stored in array instead of code		VMMethodInfo targetMethod = 		    method.targetMethods[tmi++].vmMethodInfo;		rewrite = MethodCallInline(pc, (CVMMethodInfo)targetMethod);		if (rewrite != null) { 		    isRewritten = true;		    System.arraycopy(rewrite, 0, code, pc, 3);		}		pc += 3;		break;	    }	    case opc_invokevirtual_quick_w:	    case opc_invokenonvirtual_quick:	    case opc_invokesuper_quick: // not currently used by JavaCodeCompact	    case opc_invokestatic_quick: {		int index = method.getUnsignedShort(pc + 1);		MethodConstant mc = (MethodConstant) cp[index];		VMMethodInfo targetMethod = mc.find().vmMethodInfo;		rewrite = MethodCallInline(pc, (CVMMethodInfo)targetMethod);		if (rewrite != null) {		    isRewritten = true;		    System.arraycopy(rewrite, 0, code, pc, 3);		}		pc += 3;		break;	    }	    default:	        pc += method.opcodeLength(pc);		break;	    }	}	if (isRewritten) 	    compress();	inlineState = inline_DONE;    }    /* This method is called to determine whether the method "mb" called at     * from instruction "pc" can be inlined.  If not, the value null is     * returned.  If so, an array of three bytes, which should overwrite the     * method invocation, is returned     */    private byte[] MethodCallInline(int pc, CVMMethodInfo mb) {	byte code[] = method.code;	int opcode = code[pc] & 0xff;	if (opcode == opc_invokevirtual_quick ||	    opcode == opc_ainvokevirtual_quick ||	    opcode == opc_dinvokevirtual_quick ||	    opcode == opc_vinvokevirtual_quick ||	    opcode == opc_invokevirtual_quick_w)	    /* This is a virtual method call.  No use even bother trying to	     * inline the method, unless its final	     */	    if (((mb.method.access & ACC_FINAL) == 0) 		   && ((mb.method.parent.access & ACC_FINAL) == 0))		return null;	int mbInlining = mb.getInlining();	if ((mbInlining & NO_INLINE_FLAG) != 0)	    return null;	/* Does this inlining have a dependency on the constant pool, and so	 * can only be used on a method in the same class. */	if ((mbInlining & SAME_CLASS_FLAG) != 0) {	    if (this.method.parent != mb.method.parent)		return null;	}	/* There is a inlining.  Copy that value into "result" */	byte[] result = new byte[3];	result[0] = INLINING_WORD1(mbInlining);	result[1] = INLINING_WORD2(mbInlining);	result[2] = INLINING_WORD3(mbInlining);	return result;    }    public int getInlining() { 	MethodInfo mi = this.method;	if (inlining == 0) { 	    if (   ((mi.access & (ACC_ABSTRACT | ACC_NATIVE |				  ACC_SYNCHRONIZED)) != 0)		|| (mi.exceptionTable.length > 0)) {		inlining = NO_INLINE_FLAG;	    } else { 		inlineCode();		inlining = calculateInlining();				/*******

⌨️ 快捷键说明

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