⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evmmethodinfo.java

📁 已经移植好的java虚拟机
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* *	EVMMethodInfo.java	1.6	01/04/27 SMI * * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information").  You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * Use is subject to license terms. */package vm;/* * VM-specific internal representation of * a method. Target-machine independent. * * See also EVMClass for VM-specific info associated with each class. * See also EVMVM for VM-specific info not associated directly with any class. */import components.*;import vm.VMMethodInfo;import vm.Const;import vm.EVMConst;import util.DataFormatException;import java.util.Enumeration;import java.util.Vector;import java.util.Hashtable;import java.util.StringTokenizer;public classEVMMethodInfo extends VMMethodInfo implements Const, EVMConst {    private boolean		impureCode = false;    private boolean		mustAlign  = false;    private boolean		codeExamined = false;    public  MethodInfo method;    private String		myNativeName;    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);    /** Keep this var to make code look the same as in inline.c */    static final boolean UseLosslessQuickOpcodes = false;    /**     * 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 EVMMethodInfo( MethodInfo m  ){	method = m;	method.vmMethodInfo = this;    }    private void examineCode( ) throws DataFormatException {	impureCode = false;	mustAlign  = 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_ldc:	    case opc_ldc_w:	    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;	    }	}	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;    }    private static int methodNumber = 0;    public String getNativeName() {	if ( myNativeName == null ){	    // need to take parameter list into account.	    // OR just enumerate, as the actual name doesn't matter.	    // FIXME	    myNativeName = ((EVMClass)(method.parent.vmClass)).getNativeName()+ methodNumber;	    methodNumber+= 1;	}	return myNativeName;    }    public boolean    hasBody(){	return ( (method.access & (ACC_ABSTRACT|ACC_NATIVE) )== 0 );    }    public int    EVMflags(){	int flagval = 0;	int a = method.access;	if ( (a&ACC_PUBLIC) != 0 ) flagval |= EVM_METHOD_ACC_PUBLIC;	if ( (a&ACC_PRIVATE) != 0 ) flagval |= EVM_METHOD_ACC_PRIVATE;	if ( (a&ACC_PROTECTED) != 0 ) flagval |= EVM_METHOD_ACC_PROTECTED;	if ( (a&ACC_STATIC) != 0 ) flagval |= EVM_METHOD_ACC_STATIC;	if ( (a&ACC_FINAL) != 0 ) flagval |= EVM_METHOD_ACC_FINAL;	if ( (a&ACC_SYNCHRONIZED) != 0 ) flagval |= EVM_METHOD_ACC_SYNCHRONIZED;	if ( (a&ACC_NATIVE) != 0 ) flagval |= EVM_METHOD_ACC_NATIVE;	if ( (a&ACC_ABSTRACT) != 0 ) flagval |= EVM_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() {        new Error().printStackTrace();        boolean isRewritten = false;	if (inlineState == inline_NOT_DONE) { 	    inlineState = inline_IN_PROGRESS;	} else { 	    return;	}	ConstantObject[] cp = method.parent.constants;	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_fast:	    case opc_invokespecial_fast: 	    case opc_invokestatic_fast: {		int index = method.getUnsignedShort(pc + 1);		MethodConstant mc = (MethodConstant) cp[index];		VMMethodInfo targetMethod = mc.find().vmMethodInfo;		rewrite = MethodCallInline(pc, (EVMMethodInfo)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, EVMMethodInfo mb) {	byte code[] = method.code;	int opcode = code[pc] & 0xff;	if (opcode == opc_invokevirtual_fast) {   	    /* 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();				/*******		if (inlining != NO_INLINE_FLAG) { 		    String sameClass = 			((inlining & SAME_CLASS_FLAG) != 0) ? "*" : "";		    System.out.print("get: " + this + " =>" + sameClass);		    System.out.println(" " + disassembleInlining());		}		********/	    }	}	return inlining;    }    /* Given a method, determine if it can be "inlined" into three or fewer     * bytes.     */    private int calculateInlining() {         MethodInfo mb = this.method;	byte[] code = mb.code;	/* The checkThis flag indicates that the resulting code must 	 * throw a NullPointerException if the first argument is null	 */	boolean checkThis = ((mb.access & ACC_STATIC) == 0) 	                 && !method.name.string.equals("<init>");	    	boolean redoInlining = false;	int stackSize, stackBase;	OpcodeInfoType opPtr;	stackSize = 0;	stackBase = 0;			// Prevent javac warning	for (int pc = 0; ; pc++) { 	    /* At this point in our simulation of the execution of the	     * method, registers stackBase .. stackBase+stackSize - 1 are	     * pushed onto the the stack.  pc points to the next	     * instruction to look at.	     */	    int opcode = code[pc] & 0xff;	    int opcode2;	    int reg, regSize, nextReg;	    if (stackSize == 0)		stackBase = 0;	    nextReg = stackBase + stackSize;	    opPtr = OpcodeInfo[opcode];	    switch (opPtr.opcode) { 	    case opc_iload_0: /* register load.  regnum from opcode */	    case opc_iload:	/* register load.  regnum from pc[1] */	        if (opPtr.opcode == opc_iload_0) { 		    reg = REGNUM(opPtr);		} else { 		    reg = code[pc + 1] & 0xff; pc++;		}		regSize = REGSIZE(opPtr);		if (stackSize == 0) /* stack is currently empty */		    stackBase = reg;		else if (nextReg != reg)		    return NO_INLINE_FLAG;		stackSize += regSize;		continue;	    case opc_pop:	/* pop stack, or nop */		stackSize -= REGSIZE(opPtr);		continue;	    case opc_nonnull_quick: /* special instruction */		if (nextReg == 1) {		    /* We're checking register 0 to ensure that it isn't null */		    stackSize = 0; checkThis = true;		    continue;		}		return NO_INLINE_FLAG;	    case opc_invokeignored_quick: /* special instruction */	    {				int popCount = code[pc + 1] & 0xff;		if (code[pc + 2] != 0) {  		    /* We only know how to check register 0 for non-null ness */		    if (nextReg != popCount)			return NO_INLINE_FLAG;		    checkThis = true;		    stackSize -= popCount;		} else { 		    stackSize -= popCount;		  		}		pc += 2;		continue;	    }	    case opc_return:	/* return void or value */		return makeReturnResult(checkThis, nextReg, REGSIZE(opPtr));	    case opc_iadd: {	/* any simple instruction */		int ilength = opcLengths[opcode];		int result;		opcode2 = code[pc + ilength] & 0xff;		if (!((opPtr.outStack > 0)			 ? isXreturn(opcode2)			 : (opcode2 == opc_return			    || opcode == opc_athrow)))		    return NO_INLINE_FLAG;		if ((opPtr.flags & OpcodeInfoType.NULL_CHECK) != 0		    && (stackBase == 0)) {		    /* We don't need to generate code to check for null, since		     * the instruction already does it.		     */		    checkThis = false;		}		switch (ilength) {		case 1:		    result =			makeOpcodeResult(checkThis, nextReg, opPtr.inStack,					 1, opcode, 0, 0);		    break;		case 2:

⌨️ 快捷键说明

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