src/share/classes/com/sun/tools/javap/StackMapWriter.java

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 581
f2fdd52e4e87
child 1339
0e5899f09dab
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

jjg@283 1 /*
ohair@554 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
jjg@283 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@283 4 *
jjg@283 5 * This code is free software; you can redistribute it and/or modify it
jjg@283 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
jjg@283 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@283 10 *
jjg@283 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@283 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@283 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@283 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@283 15 * accompanied this code).
jjg@283 16 *
jjg@283 17 * You should have received a copy of the GNU General Public License version
jjg@283 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@283 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@283 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
jjg@283 24 */
jjg@283 25
jjg@283 26 package com.sun.tools.javap;
jjg@283 27
jjg@283 28 import com.sun.tools.classfile.AccessFlags;
jjg@283 29 import java.util.HashMap;
jjg@283 30 import java.util.Map;
jjg@283 31
jjg@283 32 import com.sun.tools.classfile.Attribute;
jjg@283 33 import com.sun.tools.classfile.Code_attribute;
jjg@283 34 import com.sun.tools.classfile.ConstantPool;
jjg@283 35 import com.sun.tools.classfile.ConstantPoolException;
jjg@283 36 import com.sun.tools.classfile.Descriptor;
jjg@283 37 import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
jjg@283 38 import com.sun.tools.classfile.Instruction;
jjg@283 39 import com.sun.tools.classfile.Method;
jjg@283 40 import com.sun.tools.classfile.StackMapTable_attribute;
jjg@283 41 import com.sun.tools.classfile.StackMapTable_attribute.*;
jjg@283 42
jjg@283 43 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
jjg@283 44
jjg@283 45 /**
jjg@283 46 * Annotate instructions with stack map.
jjg@283 47 *
jjg@581 48 * <p><b>This is NOT part of any supported API.
jjg@581 49 * If you write code that depends on this, you do so at your own risk.
jjg@283 50 * This code and its internal interfaces are subject to change or
jjg@283 51 * deletion without notice.</b>
jjg@283 52 */
jjg@283 53 public class StackMapWriter extends InstructionDetailWriter {
jjg@283 54 static StackMapWriter instance(Context context) {
jjg@283 55 StackMapWriter instance = context.get(StackMapWriter.class);
jjg@283 56 if (instance == null)
jjg@283 57 instance = new StackMapWriter(context);
jjg@283 58 return instance;
jjg@283 59 }
jjg@283 60
jjg@283 61 protected StackMapWriter(Context context) {
jjg@283 62 super(context);
jjg@283 63 context.put(StackMapWriter.class, this);
jjg@283 64 classWriter = ClassWriter.instance(context);
jjg@283 65 }
jjg@283 66
jjg@283 67 public void reset(Code_attribute attr) {
jjg@283 68 setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
jjg@283 69 }
jjg@283 70
jjg@283 71 void setStackMap(StackMapTable_attribute attr) {
jjg@283 72 if (attr == null) {
jjg@283 73 map = null;
jjg@283 74 return;
jjg@283 75 }
jjg@283 76
jjg@283 77 Method m = classWriter.getMethod();
jjg@283 78 Descriptor d = m.descriptor;
jjg@283 79 String[] args;
jjg@283 80 try {
jjg@283 81 ConstantPool cp = classWriter.getClassFile().constant_pool;
jjg@283 82 String argString = d.getParameterTypes(cp);
jjg@283 83 args = argString.substring(1, argString.length() - 1).split("[, ]+");
jjg@283 84 } catch (ConstantPoolException e) {
jjg@283 85 return;
jjg@283 86 } catch (InvalidDescriptor e) {
jjg@283 87 return;
jjg@283 88 }
jjg@283 89 boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
jjg@283 90
jjg@283 91 verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
jjg@283 92 if (!isStatic)
jjg@283 93 initialLocals[0] = new CustomVerificationTypeInfo("this");
jjg@283 94 for (int i = 0; i < args.length; i++) {
jjg@283 95 initialLocals[(isStatic ? 0 : 1) + i] =
jjg@283 96 new CustomVerificationTypeInfo(args[i].replace(".", "/"));
jjg@283 97 }
jjg@283 98
jjg@283 99 map = new HashMap<Integer, StackMap>();
jjg@283 100 StackMapBuilder builder = new StackMapBuilder();
jjg@283 101
jjg@283 102 // using -1 as the pc for the initial frame effectively compensates for
jjg@283 103 // the difference in behavior for the first stack map frame (where the
jjg@283 104 // pc offset is just offset_delta) compared to subsequent frames (where
jjg@283 105 // the pc offset is always offset_delta+1).
jjg@283 106 int pc = -1;
jjg@283 107
jjg@283 108 map.put(pc, new StackMap(initialLocals, empty));
jjg@283 109
jjg@283 110 for (int i = 0; i < attr.entries.length; i++)
jjg@283 111 pc = attr.entries[i].accept(builder, pc);
jjg@283 112 }
jjg@283 113
jjg@283 114 public void writeInitialDetails() {
jjg@283 115 writeDetails(-1);
jjg@283 116 }
jjg@283 117
jjg@283 118 public void writeDetails(Instruction instr) {
jjg@283 119 writeDetails(instr.getPC());
jjg@283 120 }
jjg@283 121
jjg@283 122 private void writeDetails(int pc) {
jjg@283 123 if (map == null)
jjg@283 124 return;
jjg@283 125
jjg@283 126 StackMap m = map.get(pc);
jjg@283 127 if (m != null) {
jjg@283 128 print("StackMap locals: ", m.locals);
jjg@283 129 print("StackMap stack: ", m.stack);
jjg@283 130 }
jjg@283 131
jjg@283 132 }
jjg@283 133
jjg@283 134 void print(String label, verification_type_info[] entries) {
jjg@283 135 print(label);
jjg@283 136 for (int i = 0; i < entries.length; i++) {
jjg@283 137 print(" ");
jjg@283 138 print(entries[i]);
jjg@283 139 }
jjg@283 140 println();
jjg@283 141 }
jjg@283 142
jjg@283 143 void print(verification_type_info entry) {
jjg@283 144 if (entry == null) {
jjg@283 145 print("ERROR");
jjg@283 146 return;
jjg@283 147 }
jjg@283 148
jjg@283 149 switch (entry.tag) {
jjg@283 150 case -1:
jjg@283 151 print(((CustomVerificationTypeInfo) entry).text);
jjg@283 152 break;
jjg@283 153
jjg@283 154 case ITEM_Top:
jjg@283 155 print("top");
jjg@283 156 break;
jjg@283 157
jjg@283 158 case ITEM_Integer:
jjg@283 159 print("int");
jjg@283 160 break;
jjg@283 161
jjg@283 162 case ITEM_Float:
jjg@283 163 print("float");
jjg@283 164 break;
jjg@283 165
jjg@283 166 case ITEM_Long:
jjg@283 167 print("long");
jjg@283 168 break;
jjg@283 169
jjg@283 170 case ITEM_Double:
jjg@283 171 print("double");
jjg@283 172 break;
jjg@283 173
jjg@283 174 case ITEM_Null:
jjg@283 175 print("null");
jjg@283 176 break;
jjg@283 177
jjg@283 178 case ITEM_UninitializedThis:
jjg@283 179 print("uninit_this");
jjg@283 180 break;
jjg@283 181
jjg@283 182 case ITEM_Object:
jjg@283 183 try {
jjg@283 184 ConstantPool cp = classWriter.getClassFile().constant_pool;
jjg@283 185 ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
jjg@283 186 print(cp.getUTF8Value(class_info.name_index));
jjg@283 187 } catch (ConstantPoolException e) {
jjg@283 188 print("??");
jjg@283 189 }
jjg@283 190 break;
jjg@283 191
jjg@283 192 case ITEM_Uninitialized:
jjg@283 193 print(((Uninitialized_variable_info) entry).offset);
jjg@283 194 break;
jjg@283 195 }
jjg@283 196
jjg@283 197 }
jjg@283 198
jjg@283 199 private Map<Integer, StackMap> map;
jjg@283 200 private ClassWriter classWriter;
jjg@283 201
jjg@283 202 class StackMapBuilder
jjg@283 203 implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
jjg@283 204
jjg@283 205 public Integer visit_same_frame(same_frame frame, Integer pc) {
jjg@283 206 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 207 StackMap m = map.get(pc);
jjg@283 208 assert (m != null);
jjg@283 209 map.put(new_pc, m);
jjg@283 210 return new_pc;
jjg@283 211 }
jjg@283 212
jjg@283 213 public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
jjg@283 214 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 215 StackMap prev = map.get(pc);
jjg@283 216 assert (prev != null);
jjg@283 217 StackMap m = new StackMap(prev.locals, frame.stack);
jjg@283 218 map.put(new_pc, m);
jjg@283 219 return new_pc;
jjg@283 220 }
jjg@283 221
jjg@283 222 public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
jjg@283 223 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 224 StackMap prev = map.get(pc);
jjg@283 225 assert (prev != null);
jjg@283 226 StackMap m = new StackMap(prev.locals, frame.stack);
jjg@283 227 map.put(new_pc, m);
jjg@283 228 return new_pc;
jjg@283 229 }
jjg@283 230
jjg@283 231 public Integer visit_chop_frame(chop_frame frame, Integer pc) {
jjg@283 232 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 233 StackMap prev = map.get(pc);
jjg@283 234 assert (prev != null);
jjg@283 235 int k = 251 - frame.frame_type;
jjg@283 236 verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
jjg@283 237 System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
jjg@283 238 StackMap m = new StackMap(new_locals, empty);
jjg@283 239 map.put(new_pc, m);
jjg@283 240 return new_pc;
jjg@283 241 }
jjg@283 242
jjg@283 243 public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {
jjg@283 244 int new_pc = pc + frame.getOffsetDelta();
jjg@283 245 StackMap m = map.get(pc);
jjg@283 246 assert (m != null);
jjg@283 247 map.put(new_pc, m);
jjg@283 248 return new_pc;
jjg@283 249 }
jjg@283 250
jjg@283 251 public Integer visit_append_frame(append_frame frame, Integer pc) {
jjg@283 252 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 253 StackMap prev = map.get(pc);
jjg@283 254 assert (prev != null);
jjg@283 255 verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];
jjg@283 256 System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
jjg@283 257 System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);
jjg@283 258 StackMap m = new StackMap(new_locals, empty);
jjg@283 259 map.put(new_pc, m);
jjg@283 260 return new_pc;
jjg@283 261 }
jjg@283 262
jjg@283 263 public Integer visit_full_frame(full_frame frame, Integer pc) {
jjg@283 264 int new_pc = pc + frame.getOffsetDelta() + 1;
jjg@283 265 StackMap m = new StackMap(frame.locals, frame.stack);
jjg@283 266 map.put(new_pc, m);
jjg@283 267 return new_pc;
jjg@283 268 }
jjg@283 269
jjg@283 270 }
jjg@283 271
jjg@283 272 class StackMap {
jjg@283 273 StackMap(verification_type_info[] locals, verification_type_info[] stack) {
jjg@283 274 this.locals = locals;
jjg@283 275 this.stack = stack;
jjg@283 276 }
jjg@283 277
jjg@283 278 private final verification_type_info[] locals;
jjg@283 279 private final verification_type_info[] stack;
jjg@283 280 }
jjg@283 281
jjg@283 282 class CustomVerificationTypeInfo extends verification_type_info {
jjg@283 283 public CustomVerificationTypeInfo(String text) {
jjg@283 284 super(-1);
jjg@283 285 this.text = text;
jjg@283 286 }
jjg@283 287 private String text;
jjg@283 288 }
jjg@283 289
jjg@283 290 private final verification_type_info[] empty = { };
jjg@283 291 }

mercurial