169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode.stackmap; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Stack map maker. 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class MapMaker extends Tracer { 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void main(String[] args) throws Exception { 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean useMain2 = args[0].equals("0"); 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (useMain2 && args.length > 1) { 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal main2(args); 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < args.length; i++) 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal main1(args[i]); 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void main1(String className) throws Exception { 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool cp = ClassPool.getDefault(); 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal //javassist.CtClass cc = cp.get(className); 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal javassist.CtClass cc = cp.makeClass(new java.io.FileInputStream(className)); 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(className); 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassFile cf = cc.getClassFile(); 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal java.util.List minfos = cf.getMethods(); 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < minfos.size(); i++) { 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo minfo = (MethodInfo)minfos.get(i); 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = minfo.getCodeAttribute(); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ca != null) 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ca.setAttribute(make(cp, minfo)); 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cc.writeFile("tmp"); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void main2(String[] args) throws Exception { 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool cp = ClassPool.getDefault(); 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal //javassist.CtClass cc = cp.get(args[1]); 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal javassist.CtClass cc = cp.makeClass(new java.io.FileInputStream(args[1])); 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo minfo; 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (args[2].equals("_init_")) 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal minfo = cc.getDeclaredConstructors()[0].getMethodInfo(); 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // minfo = cc.getClassInitializer().getMethodInfo(); 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal minfo = cc.getDeclaredMethod(args[2]).getMethodInfo(); 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = minfo.getCodeAttribute(); 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ca == null) { 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println("abstarct method"); 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, false); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MapMaker mm = new MapMaker(cp, minfo, ca); 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mm.make(blocks, ca.getCode()); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < blocks.length; i++) 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(blocks[i]); 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Computes the stack map table of the given method and returns it. 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It returns null if the given method does not have to have a 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * stack map table. 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static StackMapTable make(ClassPool classes, MethodInfo minfo) 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = minfo.getCodeAttribute(); 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ca == null) 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, true); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (blocks == null) 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MapMaker mm = new MapMaker(classes, minfo, ca); 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mm.make(blocks, ca.getCode()); 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mm.toStackMap(blocks); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Computes the stack map table for J2ME. 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It returns null if the given method does not have to have a 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * stack map table. 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static StackMap make2(ClassPool classes, MethodInfo minfo) 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = minfo.getCodeAttribute(); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ca == null) 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, true); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (blocks == null) 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MapMaker mm = new MapMaker(classes, minfo, ca); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mm.make(blocks, ca.getCode()); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mm.toStackMap2(minfo.getConstPool(), blocks); 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public MapMaker(ClassPool classes, MethodInfo minfo, CodeAttribute ca) { 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(classes, minfo.getConstPool(), 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ca.getMaxStack(), ca.getMaxLocals(), 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock.getRetType(minfo.getDescriptor())); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected MapMaker(MapMaker old, boolean copyStack) { 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(old, copyStack); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Runs an analyzer (Phase 1 and 2). 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void make(TypedBlock[] blocks, byte[] code) 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock first = blocks[0]; 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fixParamTypes(first); 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] srcTypes = first.localsTypes; 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal copyFrom(srcTypes.length, srcTypes, this.localsTypes); 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal make(code, first); 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = blocks.length; 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal evalExpected(blocks[i]); 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If a parameter type is String but it is used only as Object 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * within the method body, this MapMaker class will report its type 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is Object. To avoid this, fixParamTypes calls TypeData.setType() 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * on each parameter type. 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void fixParamTypes(TypedBlock first) throws BadBytecode { 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] types = first.localsTypes; 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = types.length; 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) { 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData t = types[i]; 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t instanceof TypeData.ClassName) { 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Skip the following statement if t.isNullType() is true 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * although a parameter type is never null type. 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData.setType(t, t.getName(), classPool); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Phase 1 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void make(byte[] code, TypedBlock tb) 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal BasicBlock.Catch handlers = tb.toCatch; 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (handlers != null) { 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal traceException(code, handlers); 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal handlers = handlers.next; 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = tb.position; 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int end = pos + tb.length; 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (pos < end) 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += doOpcode(pos, code); 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tb.exit != null) { 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < tb.exit.length; i++) { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock e = (TypedBlock)tb.exit[i]; 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (e.alreadySet()) 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mergeMap(e, true); 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal recordStackMap(e); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MapMaker maker = new MapMaker(this, true); 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maker.make(code, e); 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void traceException(byte[] code, TypedBlock.Catch handler) 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock tb = (TypedBlock)handler.body; 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tb.alreadySet()) 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mergeMap(tb, false); 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal recordStackMap(tb, handler.typeIndex); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MapMaker maker = new MapMaker(this, false); 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* the following code is equivalent to maker.copyFrom(this) 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * except stackTypes are not copied. 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maker.stackTypes[0] = tb.stackTypes[0].getSelf(); 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maker.stackTop = 1; 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maker.make(code, tb); 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void mergeMap(TypedBlock dest, boolean mergeStack) { 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean[] inputs = dest.inputs; 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = inputs.length; 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (inputs[i]) 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal merge(localsTypes[i], dest.localsTypes[i]); 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mergeStack) { 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n = stackTop; 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal merge(stackTypes[i], dest.stackTypes[i]); 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void merge(TypeData td, TypeData target) { 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean tdIsObj = false; 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean targetIsObj = false; 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // td or target is null if it is TOP. 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td != TOP && td.isObjectType()) 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tdIsObj = true; 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (target != TOP && target.isObjectType()) 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal targetIsObj = true; 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tdIsObj && targetIsObj) 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal target.merge(td); 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void recordStackMap(TypedBlock target) 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] tStackTypes = new TypeData[stackTypes.length]; 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int st = stackTop; 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal copyFrom(st, stackTypes, tStackTypes); 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal recordStackMap0(target, st, tStackTypes); 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void recordStackMap(TypedBlock target, int exceptionType) 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String type; 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exceptionType == 0) 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = "java.lang.Throwable"; 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = cpool.getClassInfo(exceptionType); 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] tStackTypes = new TypeData[stackTypes.length]; 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tStackTypes[0] = new TypeData.ClassName(type); 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal recordStackMap0(target, 1, tStackTypes); 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void recordStackMap0(TypedBlock target, int st, TypeData[] tStackTypes) 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = localsTypes.length; 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] tLocalsTypes = new TypeData[n]; 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = copyFrom(n, localsTypes, tLocalsTypes); 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean[] inputs = target.inputs; 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!inputs[i]) 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tLocalsTypes[i] = TOP; 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal target.setStackMap(st, tStackTypes, k, tLocalsTypes); 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Phase 2 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void evalExpected(TypedBlock target) throws BadBytecode { 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool cp = classPool; 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal evalExpected(cp, target.stackTop, target.stackTypes); 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData[] types = target.localsTypes; 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (types != null) // unless this block is dead code 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal evalExpected(cp, types.length, types); 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void evalExpected(ClassPool cp, int n, TypeData[] types) 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) { 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = types[i]; 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td != null) 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal td.evalExpectedType(cp); 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Phase 3 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public StackMapTable toStackMap(TypedBlock[] blocks) { 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMapTable.Writer writer = new StackMapTable.Writer(32); 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = blocks.length; 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock prev = blocks[0]; 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offsetDelta = prev.length; 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (prev.incoming > 0) { // the first instruction is a branch target. 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameFrame(0); 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offsetDelta--; 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 1; i < n; i++) { 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock bb = blocks[i]; 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isTarget(bb, blocks[i - 1])) { 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bb.resetNumLocals(); 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int diffL = stackMapDiff(prev.numLocals, prev.localsTypes, 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bb.numLocals, bb.localsTypes); 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toStackMapBody(writer, bb, diffL, offsetDelta, prev); 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offsetDelta = bb.length - 1; 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal prev = bb; 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offsetDelta += bb.length; 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return writer.toStackMapTable(cpool); 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if cur is a branch target. 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean isTarget(TypedBlock cur, TypedBlock prev) { 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int in = cur.incoming; 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (in > 1) 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (in < 1) 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return prev.stop; 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void toStackMapBody(StackMapTable.Writer writer, TypedBlock bb, 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int diffL, int offsetDelta, TypedBlock prev) { 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // if diffL is -100, two TypeData arrays do not share 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // any elements. 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int stackTop = bb.stackTop; 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (stackTop == 0) { 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (diffL == 0) { 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameFrame(offsetDelta); 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (0 > diffL && diffL >= -3) { 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.chopFrame(offsetDelta, -diffL); 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (0 < diffL && diffL <= 3) { 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] data = new int[diffL]; 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] tags = fillStackMap(bb.numLocals - prev.numLocals, 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal prev.numLocals, data, 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bb.localsTypes); 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.appendFrame(offsetDelta, tags, data); 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (stackTop == 1 && diffL == 0) { 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = bb.stackTypes[0]; 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td == TOP) 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameLocals(offsetDelta, StackMapTable.TOP, 0); 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameLocals(offsetDelta, td.getTypeTag(), 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal td.getTypeData(cpool)); 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (stackTop == 2 && diffL == 0) { 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = bb.stackTypes[0]; 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td != TOP && td.is2WordType()) { 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // bb.stackTypes[1] must be TOP. 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameLocals(offsetDelta, td.getTypeTag(), 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal td.getTypeData(cpool)); 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] sdata = new int[stackTop]; 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stags = fillStackMap(stackTop, 0, sdata, bb.stackTypes); 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] ldata = new int[bb.numLocals]; 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] ltags = fillStackMap(bb.numLocals, 0, ldata, bb.localsTypes); 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.fullFrame(offsetDelta, ltags, ldata, stags, sdata); 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int[] fillStackMap(int num, int offset, int[] data, TypeData[] types) { 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int realNum = diffSize(types, offset, offset + num); 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool cp = cpool; 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] tags = new int[realNum]; 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int j = 0; 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < num; i++) { 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = types[offset + i]; 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td == TOP) { 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tags[j] = StackMapTable.TOP; 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data[j] = 0; 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tags[j] = td.getTypeTag(); 40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data[j] = td.getTypeData(cp); 41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td.is2WordType()) 41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i++; 41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal j++; 41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return tags; 41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static int stackMapDiff(int oldTdLen, TypeData[] oldTd, 42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int newTdLen, TypeData[] newTd) 42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int diff = newTdLen - oldTdLen; 42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len; 42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (diff > 0) 42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = oldTdLen; 42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = newTdLen; 42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (stackMapEq(oldTd, newTd, len)) 43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (diff > 0) 43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return diffSize(newTd, len, newTdLen); 43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -diffSize(oldTd, len, oldTdLen); 43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -100; 43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static boolean stackMapEq(TypeData[] oldTd, TypeData[] newTd, int len) { 44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < len; i++) { 44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = oldTd[i]; 44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td == TOP) { // the next element to LONG/DOUBLE is TOP. 44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (newTd[i] != TOP) 44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!oldTd[i].equals(newTd[i])) 44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static int diffSize(TypeData[] types, int offset, int len) { 45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int num = 0; 45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (offset < len) { 45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = types[offset++]; 45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal num++; 45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td != TOP && td.is2WordType()) 46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset++; 46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return num; 46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Phase 3 for J2ME 46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public StackMap toStackMap2(ConstPool cp, TypedBlock[] blocks) { 46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMap.Writer writer = new StackMap.Writer(); 47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = blocks.length; // should be > 0 47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean[] effective = new boolean[n]; 47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock prev = blocks[0]; 47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Is the first instruction a branch target? 47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal effective[0] = prev.incoming > 0; 47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int num = effective[0] ? 1 : 0; 47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 1; i < n; i++) { 47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypedBlock bb = blocks[i]; 48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (effective[i] = isTarget(bb, blocks[i - 1])) { 48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bb.resetNumLocals(); 48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal prev = bb; 48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal num++; 48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (num == 0) 48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.write16bit(num); 49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (effective[i]) 49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeStackFrame(writer, cp, blocks[i].position, blocks[i]); 49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return writer.toStackMap(cp); 49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void writeStackFrame(StackMap.Writer writer, ConstPool cp, int offset, TypedBlock tb) { 49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.write16bit(offset); 50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeVerifyTypeInfo(writer, cp, tb.localsTypes, tb.numLocals); 50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeVerifyTypeInfo(writer, cp, tb.stackTypes, tb.stackTop); 50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void writeVerifyTypeInfo(StackMap.Writer writer, ConstPool cp, TypeData[] types, int num) { 50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int numDWord = 0; 50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < num; i++) { 50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = types[i]; 50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td != null && td.is2WordType()) { 50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numDWord++; 51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i++; 51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.write16bit(num - numDWord); 51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < num; i++) { 51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal TypeData td = types[i]; 51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td == TOP) 51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.writeVerifyTypeInfo(StackMap.TOP, 0); 51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.writeVerifyTypeInfo(td.getTypeTag(), td.getTypeData(cp)); 52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (td.is2WordType()) 52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i++; 52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 527