📄 kvmstackmap.java
字号:
/* * KVMStackMap.java 1.4 01/02/02 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 runtime;import components.*;import jcc.Util;import vm.EVMMethodInfo;import util.*;import java.io.ByteArrayOutputStream;import vm.Const;/* * The CoreImageWriter for the Embedded VM */public class KVMStackMap implements Const { KVMWriter writer; KVMNameTable nameTable; public KVMStackMap(KVMWriter writer, KVMNameTable nameTable) { this.writer = writer; this.nameTable = nameTable; } private long frameToLong(MethodInfo mi, StackMapFrame frame) { boolean[] locals = frame.getLocalsBitmap(); boolean[] stack = frame.getStackBitmap(); int maxLocals = mi.locals; long stackMap = 0; // this gives us 64 bits for (int i = 0; i < locals.length; i++) { if (locals[i]) { stackMap |= 1L << i; } } for (int i = 0; i < stack.length; i++) { if (stack[i]) { stackMap |= 1L << (i + maxLocals); } } return stackMap; } private String frameToString(MethodInfo mi, StackMapFrame frame) { long stackMap = frameToLong(mi, frame); StringBuffer sb = new StringBuffer(); sb.append((char)frame.getStackSize()); while (stackMap != 0) { sb.append((char)(stackMap & 0xFF)); stackMap = stackMap >>> 8; } String result = sb.toString(); return result; } public void initialPass(EVMMethodInfo meth) { MethodInfo mi = meth.method; StackMapFrame frames[] = mi.stackMapTable; if (frames != null) { // removeExtraStackMaps(meth); if (!useShortStackMaps(meth)) { for (int i = 0; i < frames.length; i++) { nameTable.getKey(frameToString(mi, frames[i])); } } } } void showStatistics() { if (removeKeep + removeBut + removeSame > 0) { System.out.println("Total: " + (removeKeep + removeBut + removeSame)); System.out.println("Keep: " + (removeKeep)); System.out.println("Toss: " + (removeSame)); System.out.println("But: " + (removeBut)); System.out.println("Long stack maps: " + longStackMaps); } } void printDeclaration(CCodeWriter out, EVMMethodInfo meth, String prefix) { String methodNativeName = meth.getNativeName(); MethodInfo mi = meth.method; out.println(prefix + "struct { /* " + mi.parent.className + ": " + writer.prettyName(mi) + "*/"); out.println(prefix + "\tunsigned short length;"); if (useShortStackMaps(meth)) { out.println(prefix + "\tstruct { unsigned short offset; " + "unsigned char map[2]; } frame[" + mi.stackMapTable.length + "];"); } else { out.println(prefix + "\tstruct { unsigned short offset; " + "unsigned short info; } frame[" + mi.stackMapTable.length + "];"); } out.println(prefix + "} " + methodNativeName + ";"); } void printDefinition(CCodeWriter out, EVMMethodInfo meth, String prefix) { MethodInfo mi = meth.method; StackMapFrame frames[] = mi.stackMapTable; String pprefix = prefix + "\t"; out.println(prefix + "{ /* " + mi.parent.className + ": " + writer.prettyName(mi) + "*/"); boolean useShort = useShortStackMaps(meth); out.println(pprefix + frames.length + (useShort ? " | STACK_MAP_SHORT_ENTRY_FLAG" : "") + ","); out.println(pprefix + "{"); for (int i = 0; i < frames.length; i++) { StackMapFrame frame = frames[i]; int offset = frame.getOffset(); out.print(pprefix + "\t\t"); printComment(out, meth, frame); out.println(); if (useShort) { int map = (int)frameToLong(mi, frame); out.print(pprefix + "\t{" + offset + " + (" + frame.getStackSize() + " << 12), { "); out.printHexInt(map & 0xFF); out.print(", "); out.printHexInt((map >> 8) & 0xFF); out.print(" }"); } else { String string = frameToString(mi, frame); int key = nameTable.getKey(string); out.print(pprefix + "\t{" + offset + ", " ); out.printHexInt(key); } out.print("}"); if (i < frames.length - 1) { out.println(","); } else { out.println(); } } out.println(pprefix + "}"); out.println(prefix + "},"); } java.util.Hashtable useShortStackMapsCache = new java.util.Hashtable(); static int longStackMaps; public boolean useShortStackMaps(EVMMethodInfo meth) { Boolean value = (Boolean)useShortStackMapsCache.get(meth); if (value != null) { return value.booleanValue(); } else { boolean result = useShortStackMapsInternal(meth.method); if (result) { useShortStackMapsCache.put(meth, Boolean.TRUE); } else { useShortStackMapsCache.put(meth, Boolean.FALSE); longStackMaps++; } return result; } } boolean useShortStackMapsInternal(MethodInfo mi) { if (mi.code.length > 1023) { return false; } else if (mi.stack <= 15 && mi.locals + mi.stack <= 16) { /* This is almost always they case */ return true; } else { StackMapFrame frames[] = mi.stackMapTable; for (int i = 0; i < frames.length; i++) { if (frames[i].getStackSize() > 15) { return false; } if (frameToLong(mi, frames[i]) > 65535) { return false; } } return true; } } String frameToComment(MethodInfo mi, StackMapFrame frame) { StringBuffer sb = new StringBuffer(); boolean[] locals = frame.getLocalsBitmap(); boolean[] stack = frame.getStackBitmap(); int maxLocals = mi.locals; int maxStack = mi.stack; sb.append("Locals: "); for (int i = 0; i < locals.length; i++) { sb.append(locals[i] ? 'X' : '-'); } for (int i = locals.length; i < maxLocals; i++) { sb.append('.'); } sb.append("; Stack: "); for (int i = 0; i < stack.length; i++) { sb.append(stack[i] ? 'X' : '-'); } return sb.toString(); } private void printComment(CCodeWriter out, EVMMethodInfo meth, StackMapFrame frame) { MethodInfo mi = meth.method; boolean[] locals = frame.getLocalsBitmap(); boolean[] stack = frame.getStackBitmap(); int maxLocals = mi.locals; int maxStack = mi.stack; out.print("/* Locals: "); if (maxLocals == 0) { out.print("<None>"); } else { for (int i = 0; i < locals.length; i++) { out.write(locals[i] ? 'X' : '-'); } for (int i = locals.length; i < maxLocals; i++) { out.write('.'); } } out.print("; Stack: "); if (stack.length == 0) { out.print("<None>"); } else { for (int i = 0; i < stack.length; i++) { out.write(stack[i] ? 'X' : '-'); } } out.print(" */"); } /* This is some experimental code that we're not yet using. * It allows us to delete some unneeded stack maps from the code. */ private boolean removeVerbose = false; private int removeKeep, removeBut, removeSame; private void removeExtraStackMaps(EVMMethodInfo meth) { MethodInfo mi = meth.method; ClassInfo ci = mi.parent; ConstantObject cpool[] = ci.constants; StackMapFrame frames[] = mi.stackMapTable; boolean[] locals = new boolean[mi.locals]; boolean[] stack = new boolean[mi.stack]; boolean[] discardList = new boolean[frames.length]; int discardCount = 0; byte[] code = mi.code; int stackSize = 0; int thisIP = 0; boolean needStackmap = false; int currentFrameIndex = 0; if (removeVerbose) { System.out.println("Method: " + ci.className + "." + writer.prettyName(mi)); } initializeLocals(mi, locals); for (thisIP = 0; thisIP < code.length; ) { StackMapFrame currentFrame = null; boolean[] newStack = null; boolean[] newLocals = null; if (currentFrameIndex < frames.length) { if (frames[currentFrameIndex].getOffset() < thisIP) { throw new RuntimeException("Missed stack frame??"); } else if (frames[currentFrameIndex].getOffset() == thisIP) { currentFrame = frames[currentFrameIndex]; newStack = currentFrame.getStackBitmap(); boolean[] temp = currentFrame.getLocalsBitmap(); if (temp.length == locals.length) { newLocals = temp; } else { newLocals = new boolean[mi.locals]; System.arraycopy(temp, 0, newLocals, 0, temp.length); } } } if (removeVerbose) { if (currentFrame != null || thisIP == 0) { System.out.print(" Old: "); for (int i = 0; i < locals.length; i++) { System.out.print(locals[i] ? 'X' : '-'); } System.out.print(' '); for (int i = 0; i < stackSize; i++) { System.out.print(stack[i] ? 'X' : '-'); } System.out.println(); } if (currentFrame != null) { System.out.print(" New: "); for (int i = 0; i < newLocals.length; i++) { System.out.print(newLocals[i] ? 'X' : '-'); } System.out.print(' '); for (int i = 0; i < newStack.length; i++) { System.out.print(newStack[i] ? 'X' : '-'); } } } if (needStackmap) { if (currentFrame == null) { throw new RuntimeException("Expected stack map at " + thisIP); } } if (currentFrame != null) { if (!needStackmap && (newStack.length != stackSize)) { throw new RuntimeException("Inconsistent stack size at " + thisIP); } boolean same = sameStackMaps(locals, stack, stackSize, newLocals, newStack); if (!same) { removeKeep++; } else if (needStackmap) { removeBut++; } else { removeSame++; discardCount++; discardList[currentFrameIndex] = true; } if (removeVerbose) { System.out.print(same ? "=" : "#"); System.out.println(needStackmap ? "+" : "-"); } } if (currentFrame != null) { locals = newLocals; stackSize = newStack.length; System.arraycopy(newStack, 0, stack, 0, stackSize); currentFrameIndex++; } needStackmap = false; if (removeVerbose) { System.out.print(thisIP + ": " + mi.disassemble(thisIP, thisIP + 1)); /* Note, that the println is at the end */ } int token = code[thisIP++] & 0xFF; int index; switch(token) { /* Store a single non pointer from the stack to a register */ case opc_istore: case opc_fstore: index = code[thisIP++] & 0xFF; locals[index] = false; stackSize--; break; /* Store a single pointer from the stack to a register */ case opc_astore: index = code[thisIP++] & 0xFF; locals[index] = true; stackSize--; break; /* Store a double or long from the stack to a register */ case opc_lstore: case opc_dstore: index = code[thisIP++] & 0xFF; locals[index] = false; locals[index+1] = false; stackSize -= 2; break; case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3: index = token - opc_istore_0; locals[index] = false; stackSize--; break; case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3: index = token - opc_lstore_0; locals[index] = false; locals[index+1] = false; stackSize -= 2; break; case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3: index = (token - opc_fstore_0); locals[index] = false; stackSize--; break; case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3: index = (token - opc_dstore_0); locals[index] = false; locals[index+1] = false; stackSize -= 2; break; case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -