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 + -
显示快捷键?