codehacker.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 498 行 · 第 1/2 页
JAVA
498 行
/* * @(#)CodeHacker.java 1.41 06/10/22 * * 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;import components.*;import java.io.PrintStream;import consts.Const;import consts.CVMConst;import util.DataFormatException;import util.Localizer;import util.SignatureIterator;/* * This class "quickens" Java bytecodes. * That is, it looks at the instructions having symbolic references, * such as get/putfield and methodcalls, attempts to resolve the references * and re-writes the instructions in their JVM-specific, quick form. * * Resolution failures are not (any longer) considered fatal errors, they * just result in code that cannot be considered as read-only, as more * resolution will be required at runtime, as we refuse to re-write any * instructions having unresolved references. * * The following is an exception to the above rule: * References to array classes (having names starting in "[") are * quickened anyway, as we have confidence that these classes, though not * instantiated when this code is run, will be instantiated in time. * (Perhaps this should be under control of a flag?) * */publicclass CodeHacker { boolean verbose; PrintStream log; boolean useLosslessOpcodes = false; boolean jitOn = false; ClassInfo java_lang_Object; private boolean success; private byte newopcode; public static int quickenings = 0; public static int checkinitQuickenings = 0; public CodeHacker( boolean lossless, boolean jitOn, boolean v ){ verbose = v; log = System.err; java_lang_Object = ClassTable.lookupClass("java/lang/Object"); if ( java_lang_Object == null ){ log.println(Localizer.getString( "codehacker.lookup_failed", "", "java.lang.Object")); } useLosslessOpcodes = lossless; this.jitOn = jitOn; } private void lookupFailed( ClassConstant me, FMIrefConstant target ){ log.println(Localizer.getString( "codehacker.lookup_failed", me.name, target)); success = false; } private static int getInt( byte code[], int w ){ return ( (int)code[w] << 24 ) | (( (int)code[w+1] &0xff ) << 16 ) | (( (int)code[w+2] &0xff ) << 8 ) | ( (int)code[w+3] &0xff ); } private static int getUnsignedShort( byte code[], int w ){ return (( (int)code[w] &0xff ) << 8 ) | ( (int)code[w+1] &0xff ); } private static void putShort( byte code[], int w, short v ){ code[w] = (byte)(v>>>8); code[w+1] = (byte)v; } /* * Returns true if the reference was fully quickened. * Returns false if the reference could not be deleted, either because * the lookup failed, or because we had to use the wide variant. * Sets this.success to false if the lookup failed or there was no * usable variant. */ private boolean quickenFieldAccess( MethodInfo m, ClassConstant me, byte code[], int loc, boolean isStatic, ConstantObject c[], int oneWord, int twoWords, int refReference, int wideReference, int oneWord_checkinit, int twoWords_checkinit, int refReference_checkinit ) { FieldConstant fc = (FieldConstant)c[ getUnsignedShort( code, loc+1 ) ]; FieldInfo fi = fc.find(); if ( fi == null ){ // // never even try to quicken anything we cannot resolve. // lookupFailed( me, fc ); return false; } byte newCode; boolean useCheckinit = (isStatic && fi.parent.vmClass.hasStaticInitializer); switch (fc.sig.type.string.charAt(0) ){ case '[': case 'L': newCode = (byte)((useCheckinit) ? (refReference_checkinit) : (refReference)); break; case 'D': case 'J': newCode = (byte)((useCheckinit) ? (twoWords_checkinit) : (twoWords)); break; default: newCode = (byte)((useCheckinit) ? (oneWord_checkinit) : (oneWord)); break; } if ( isStatic ) { if ( useCheckinit ) { CodeHacker.checkinitQuickenings++; m.hasCheckinits = true; } CodeHacker.quickenings++; code[loc] = newCode; return false; // still references constant pool! } else { int fieldOffset = fi.instanceOffset; // CVM wants field offset as actual WORD offset // from the start of the object. This requires // knowing the size of the header. // JVM just wanted a 0-based word index. // fieldOffset += CVMConst.ObjHeaderWords; if ( fieldOffset < 0 ){ lookupFailed( me, fc ); log.println(Localizer.getString( "codehacker.negative_field_offset")); return false; } // // Disallow lossy field access quickening if // 1 Non-lossy opcodes are requested // 2 The offset won't fit in a byte // 3 The JIT is on, and the field is volatile // if ( fieldOffset > 0xFF || useLosslessOpcodes || (jitOn && fi.isVolatile())) { if ( wideReference == 0 ){ lookupFailed( me, fc ); log.println(Localizer.getString( "codehacker.need_wide_op")); } code[loc] = (byte)wideReference; return false; // still references constant pool! } code[loc+1] = (byte)fieldOffset; code[loc+2] = 0; code[loc] = newCode; return true; } } /* * Should a call to the specified methodblock be turned into * an invokesuper_quick instead of a invokenonvirtual_quick? * * The four conditions that have to be satisfied: * The method isn't private * The method isn't an <init> method * The ACC_SUPER flag is set in the current class * The method's class is a superclass (and not equal) to * the current class. */ private boolean isSpecialSuperCall( MethodInfo me, MethodInfo callee ){ String name = callee.name.string; if ( (callee.access&Const.ACC_PRIVATE) != 0 ) return false; if ( name.equals("<init>") ) return false; ClassInfo myclass = me.parent; ClassInfo hisclass = callee.parent; if ( myclass == hisclass ) return false; // walk up my chain, looking for other's class while ( myclass != null ){ myclass = myclass.superClassInfo; if ( myclass == hisclass ) return true; } return false; } private boolean quickenMethod(MethodInfo m, ConstantObject c[]) throws DataFormatException { byte code[] = m.code; int list[] = m.getLdcInstructions(); ConstantObject constObj; FieldConstant fc; MethodConstant mc; NameAndTypeConstant nt; ClassConstant classConst; String t; ClassConstant me = m.parent.thisClass; MethodInfo mi; ClassInfo classInfo; success = true; if ( list != null ){ for ( int i = 0; i < list.length; i++ ){ int loc = list[i]; if ( loc < 0 ) continue; switch( (int)code[loc]&0xff ){ case Const.opc_ldc:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?