1 30 package org.objectweb.asm.attrs; 31 32 import java.util.ArrayList ; 33 import java.util.HashSet ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Set ; 37 38 import org.objectweb.asm.Attribute; 39 import org.objectweb.asm.ByteVector; 40 import org.objectweb.asm.ClassReader; 41 import org.objectweb.asm.ClassWriter; 42 import org.objectweb.asm.Label; 43 44 143 public class StackMapAttribute extends Attribute { 144 145 static final int MAX_SIZE = 65535; 146 147 150 public List frames = new ArrayList (); 151 152 public StackMapAttribute() { 153 super("StackMap"); 154 } 155 156 public StackMapAttribute(List frames) { 157 this(); 158 this.frames = frames; 159 } 160 161 public List getFrames() { 162 return frames; 163 } 164 165 public StackMapFrame getFrame(Label label) { 166 for (int i = 0; i < frames.size(); i++) { 167 StackMapFrame frame = (StackMapFrame) frames.get(i); 168 if (frame.label == label) { 169 return frame; 170 } 171 } 172 return null; 173 } 174 175 public boolean isUnknown() { 176 return false; 177 } 178 179 public boolean isCodeAttribute() { 180 return true; 181 } 182 183 protected Attribute read( 184 ClassReader cr, 185 int off, 186 int len, 187 char[] buf, 188 int codeOff, 189 Label[] labels) 190 { 191 StackMapAttribute attr = new StackMapAttribute(); 192 boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SIZE; 194 boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SIZE; 195 boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SIZE; 196 197 int size = 0; 198 if (isExtCodeSize) { 199 size = cr.readInt(off); 200 off += 4; 201 } else { 202 size = cr.readUnsignedShort(off); 203 off += 2; 204 } 205 for (int i = 0; i < size; i++) { 206 int offset; 207 if (isExtCodeSize) { 208 offset = cr.readInt(off); 209 off += 4; 210 } else { 211 offset = cr.readUnsignedShort(off); 212 off += 2; 213 } 214 215 Label label = getLabel(offset, labels); 216 List locals = new ArrayList (); 217 List stack = new ArrayList (); 218 219 off = readTypeInfo(cr, 220 off, 221 locals, 222 labels, 223 buf, 224 isExtLocals, 225 isExtCodeSize); 226 off = readTypeInfo(cr, 227 off, 228 stack, 229 labels, 230 buf, 231 isExtStack, 232 isExtCodeSize); 233 234 attr.frames.add(new StackMapFrame(label, locals, stack)); 235 } 236 return attr; 237 } 238 239 private int readTypeInfo( 240 ClassReader cr, 241 int off, 242 List info, 243 Label[] labels, 244 char[] buf, 245 boolean isExt, 246 boolean isExtCode) 247 { 248 int n = 0; 249 if (isExt) { 250 n = cr.readInt(off); 251 off += 4; 252 } else { 253 n = cr.readUnsignedShort(off); 254 off += 2; 255 } 256 for (int j = 0; j < n; j++) { 257 int itemType = cr.readByte(off++); 258 StackMapType typeInfo = StackMapType.getTypeInfo(itemType); 259 info.add(typeInfo); 260 switch (itemType) { 261 case StackMapType.ITEM_Object: typeInfo.setObject(cr.readClass(off, buf)); 263 off += 2; 264 break; 265 case StackMapType.ITEM_Uninitialized: int offset; 267 if (isExtCode) { 268 offset = cr.readInt(off); 269 off += 4; 270 } else { 271 offset = cr.readUnsignedShort(off); 272 off += 2; 273 } 274 typeInfo.setLabel(getLabel(offset, labels)); 275 break; 276 } 277 } 278 return off; 279 } 280 281 private void writeTypeInfo(ByteVector bv, ClassWriter cw, List info, int max) 282 { 283 if (max > StackMapAttribute.MAX_SIZE) { 284 bv.putInt(info.size()); 285 } else { 286 bv.putShort(info.size()); 287 } 288 for (int j = 0; j < info.size(); j++) { 289 StackMapType typeInfo = (StackMapType) info.get(j); 290 bv.putByte(typeInfo.getType()); 291 switch (typeInfo.getType()) { 292 case StackMapType.ITEM_Object: bv.putShort(cw.newClass(typeInfo.getObject())); 294 break; 295 296 case StackMapType.ITEM_Uninitialized: bv.putShort(typeInfo.getLabel().getOffset()); 298 break; 299 300 } 301 } 302 } 303 304 private Label getLabel(int offset, Label[] labels) { 305 Label l = labels[offset]; 306 if (l != null) { 307 return l; 308 } 309 return labels[offset] = new Label(); 310 } 311 312 protected ByteVector write( 313 ClassWriter cw, 314 byte[] code, 315 int len, 316 int maxStack, 317 int maxLocals) 318 { 319 ByteVector bv = new ByteVector(); 320 if (code != null && code.length > MAX_SIZE) { bv.putInt(frames.size()); 322 } else { 323 bv.putShort(frames.size()); 324 } 325 for (int i = 0; i < frames.size(); i++) { 326 writeFrame((StackMapFrame) frames.get(i), 327 cw, 328 maxStack, 329 maxLocals, 330 bv); 331 } 332 return bv; 333 } 334 335 protected Label[] getLabels() { 336 HashSet labels = new HashSet (); 337 for (int i = 0; i < frames.size(); i++) { 338 getFrameLabels((StackMapFrame) frames.get(i), labels); 339 } 340 return (Label[]) labels.toArray(new Label[labels.size()]); 341 } 342 343 private void writeFrame( 344 StackMapFrame frame, 345 ClassWriter cw, 346 int maxStack, 347 int maxLocals, 348 ByteVector bv) 349 { 350 bv.putShort(frame.label.getOffset()); 351 writeTypeInfo(bv, cw, frame.locals, maxLocals); 352 writeTypeInfo(bv, cw, frame.stack, maxStack); 353 } 354 355 private void getFrameLabels(StackMapFrame frame, Set labels) { 356 labels.add(frame.label); 357 getTypeInfoLabels(labels, frame.locals); 358 getTypeInfoLabels(labels, frame.stack); 359 } 360 361 private void getTypeInfoLabels(Set labels, List info) { 362 for (Iterator it = info.iterator(); it.hasNext();) { 363 StackMapType typeInfo = (StackMapType) it.next(); 364 if (typeInfo.getType() == StackMapType.ITEM_Uninitialized) { 365 labels.add(typeInfo.getLabel()); 366 } 367 } 368 } 369 370 public String toString() { 371 StringBuffer sb = new StringBuffer ("StackMap["); 372 for (int i = 0; i < frames.size(); i++) { 373 sb.append('\n').append('[').append(frames.get(i)).append(']'); 374 } 375 sb.append("\n]"); 376 return sb.toString(); 377 } 378 } 379 | Popular Tags |