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