1 /** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2005 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.objectweb.asm.util.attrs; 31 32 import java.util.List; 33 import java.util.Map; 34 35 import org.objectweb.asm.Attribute; 36 import org.objectweb.asm.ClassReader; 37 import org.objectweb.asm.Label; 38 import org.objectweb.asm.attrs.StackMapTableAttribute; 39 import org.objectweb.asm.attrs.StackMapFrame; 40 import org.objectweb.asm.attrs.StackMapType; 41 42 /** 43 * An {@link ASMifiable} {@link StackMapTableAttribute} sub class. 44 * 45 * @author Eugene Kuleshov 46 */ 47 public class ASMStackMapTableAttribute extends StackMapTableAttribute implements 48 ASMifiable, 49 Traceable 50 { 51 /** 52 * Length of the attribute used for comparison 53 */ 54 private int len; 55 ASMStackMapTableAttribute()56 public ASMStackMapTableAttribute() { 57 super(); 58 } 59 ASMStackMapTableAttribute(List frames, int len)60 public ASMStackMapTableAttribute(List frames, int len) { 61 super(frames); 62 this.len = len; 63 } 64 read( ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels)65 protected Attribute read( 66 ClassReader cr, 67 int off, 68 int len, 69 char[] buf, 70 int codeOff, 71 Label[] labels) 72 { 73 StackMapTableAttribute attr = (StackMapTableAttribute) super.read(cr, 74 off, 75 len, 76 buf, 77 codeOff, 78 labels); 79 80 return new ASMStackMapTableAttribute(attr.getFrames(), len); 81 } 82 asmify(StringBuffer buf, String varName, Map labelNames)83 public void asmify(StringBuffer buf, String varName, Map labelNames) { 84 List frames = getFrames(); 85 if (frames.size() == 0) { 86 buf.append("List frames = Collections.EMPTY_LIST;\n"); 87 } else { 88 buf.append("List frames = new ArrayList();\n"); 89 for (int i = 0; i < frames.size(); i++) { 90 buf.append("{\n"); 91 StackMapFrame f = (StackMapFrame) frames.get(i); 92 declareLabel(buf, labelNames, f.label); 93 94 String frameVar = varName + "frame" + i; 95 asmifyTypeInfo(buf, frameVar, labelNames, f.locals, "locals"); 96 asmifyTypeInfo(buf, frameVar, labelNames, f.stack, "stack"); 97 98 buf.append("StackMapFrame ") 99 .append(frameVar) 100 .append(" = new StackMapFrame(") 101 .append(labelNames.get(f.label)) 102 .append(", locals, stack);\n"); 103 buf.append("frames.add(").append(frameVar).append(");\n"); 104 buf.append("}\n"); 105 } 106 } 107 buf.append("StackMapTableAttribute ").append(varName); 108 buf.append(" = new StackMapTableAttribute(frames);\n"); 109 } 110 asmifyTypeInfo( StringBuffer buf, String varName, Map labelNames, List infos, String field)111 void asmifyTypeInfo( 112 StringBuffer buf, 113 String varName, 114 Map labelNames, 115 List infos, 116 String field) 117 { 118 if (infos.size() == 0) { 119 buf.append("List ") 120 .append(field) 121 .append(" = Collections.EMPTY_LIST;\n"); 122 } else { 123 buf.append("List ").append(field).append(" = new ArrayList();\n"); 124 buf.append("{\n"); 125 for (int i = 0; i < infos.size(); i++) { 126 StackMapType typeInfo = (StackMapType) infos.get(i); 127 String localName = varName + "Info" + i; 128 int type = typeInfo.getType(); 129 buf.append("StackMapType ") 130 .append(localName) 131 .append(" = StackMapType.getTypeInfo( StackMapType.ITEM_") 132 .append(StackMapType.ITEM_NAMES[type]) 133 .append(");\n"); 134 135 switch (type) { 136 case StackMapType.ITEM_Object: // 137 buf.append(localName) 138 .append(".setObject(\"") 139 .append(typeInfo.getObject()) 140 .append("\");\n"); 141 break; 142 143 case StackMapType.ITEM_Uninitialized: // 144 declareLabel(buf, labelNames, typeInfo.getLabel()); 145 buf.append(localName) 146 .append(".setLabel(") 147 .append(labelNames.get(typeInfo.getLabel())) 148 .append(");\n"); 149 break; 150 } 151 buf.append(field) 152 .append(".add(") 153 .append(localName) 154 .append(");\n"); 155 } 156 buf.append("}\n"); 157 } 158 } 159 declareLabel(StringBuffer buf, Map labelNames, Label l)160 static void declareLabel(StringBuffer buf, Map labelNames, Label l) { 161 String name = (String) labelNames.get(l); 162 if (name == null) { 163 name = "l" + labelNames.size(); 164 labelNames.put(l, name); 165 buf.append("Label ").append(name).append(" = new Label();\n"); 166 } 167 } 168 trace(StringBuffer buf, Map labelNames)169 public void trace(StringBuffer buf, Map labelNames) { 170 List frames = getFrames(); 171 buf.append("[\n"); 172 for (int i = 0; i < frames.size(); i++) { 173 StackMapFrame f = (StackMapFrame) frames.get(i); 174 175 buf.append(" Frame:"); 176 appendLabel(buf, labelNames, f.label); 177 178 buf.append(" locals["); 179 traceTypeInfo(buf, labelNames, f.locals); 180 buf.append("]"); 181 buf.append(" stack["); 182 traceTypeInfo(buf, labelNames, f.stack); 183 buf.append("]\n"); 184 } 185 buf.append(" ] length:").append(len).append("\n"); 186 } 187 traceTypeInfo(StringBuffer buf, Map labelNames, List infos)188 private void traceTypeInfo(StringBuffer buf, Map labelNames, List infos) { 189 String sep = ""; 190 for (int i = 0; i < infos.size(); i++) { 191 StackMapType t = (StackMapType) infos.get(i); 192 193 buf.append(sep).append(StackMapType.ITEM_NAMES[t.getType()]); 194 sep = ", "; 195 if (t.getType() == StackMapType.ITEM_Object) { 196 buf.append(":").append(t.getObject()); 197 } 198 if (t.getType() == StackMapType.ITEM_Uninitialized) { 199 buf.append(":"); 200 appendLabel(buf, labelNames, t.getLabel()); 201 } 202 } 203 } 204 appendLabel(StringBuffer buf, Map labelNames, Label l)205 protected void appendLabel(StringBuffer buf, Map labelNames, Label l) { 206 String name = (String) labelNames.get(l); 207 if (name == null) { 208 name = "L" + labelNames.size(); 209 labelNames.put(l, name); 210 } 211 buf.append(name); 212 } 213 214 } 215