001: /**
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package com.uwyn.rife.asm.util.attrs;
030:
031: import java.util.List;
032: import java.util.Map;
033:
034: import com.uwyn.rife.asm.Attribute;
035: import com.uwyn.rife.asm.ClassReader;
036: import com.uwyn.rife.asm.Label;
037: import com.uwyn.rife.asm.attrs.StackMapTableAttribute;
038: import com.uwyn.rife.asm.attrs.StackMapFrame;
039: import com.uwyn.rife.asm.attrs.StackMapType;
040:
041: /**
042: * An {@link ASMifiable} {@link StackMapTableAttribute} sub class.
043: *
044: * @author Eugene Kuleshov
045: */
046: public class ASMStackMapTableAttribute extends StackMapTableAttribute
047: implements ASMifiable, Traceable {
048: /**
049: * Length of the attribute used for comparison
050: */
051: private int len;
052:
053: public ASMStackMapTableAttribute() {
054: super ();
055: }
056:
057: public ASMStackMapTableAttribute(List frames, int len) {
058: super (frames);
059: this .len = len;
060: }
061:
062: protected Attribute read(ClassReader cr, int off, int len,
063: char[] buf, int codeOff, Label[] labels) {
064: StackMapTableAttribute attr = (StackMapTableAttribute) super
065: .read(cr, off, len, buf, codeOff, labels);
066:
067: return new ASMStackMapTableAttribute(attr.getFrames(), len);
068: }
069:
070: public void asmify(StringBuffer buf, String varName, Map labelNames) {
071: List frames = getFrames();
072: if (frames.size() == 0) {
073: buf.append("List frames = Collections.EMPTY_LIST;\n");
074: } else {
075: buf.append("List frames = new ArrayList();\n");
076: for (int i = 0; i < frames.size(); i++) {
077: buf.append("{\n");
078: StackMapFrame f = (StackMapFrame) frames.get(i);
079: declareLabel(buf, labelNames, f.label);
080:
081: String frameVar = varName + "frame" + i;
082: asmifyTypeInfo(buf, frameVar, labelNames, f.locals,
083: "locals");
084: asmifyTypeInfo(buf, frameVar, labelNames, f.stack,
085: "stack");
086:
087: buf.append("StackMapFrame ").append(frameVar).append(
088: " = new StackMapFrame(").append(
089: labelNames.get(f.label)).append(
090: ", locals, stack);\n");
091: buf.append("frames.add(").append(frameVar).append(
092: ");\n");
093: buf.append("}\n");
094: }
095: }
096: buf.append("StackMapTableAttribute ").append(varName);
097: buf.append(" = new StackMapTableAttribute(frames);\n");
098: }
099:
100: void asmifyTypeInfo(StringBuffer buf, String varName,
101: Map labelNames, List infos, String field) {
102: if (infos.size() == 0) {
103: buf.append("List ").append(field).append(
104: " = Collections.EMPTY_LIST;\n");
105: } else {
106: buf.append("List ").append(field).append(
107: " = new ArrayList();\n");
108: buf.append("{\n");
109: for (int i = 0; i < infos.size(); i++) {
110: StackMapType typeInfo = (StackMapType) infos.get(i);
111: String localName = varName + "Info" + i;
112: int type = typeInfo.getType();
113: buf
114: .append("StackMapType ")
115: .append(localName)
116: .append(
117: " = StackMapType.getTypeInfo( StackMapType.ITEM_")
118: .append(StackMapType.ITEM_NAMES[type]).append(
119: ");\n");
120:
121: switch (type) {
122: case StackMapType.ITEM_Object: //
123: buf.append(localName).append(".setObject(\"")
124: .append(typeInfo.getObject()).append(
125: "\");\n");
126: break;
127:
128: case StackMapType.ITEM_Uninitialized: //
129: declareLabel(buf, labelNames, typeInfo.getLabel());
130: buf.append(localName).append(".setLabel(").append(
131: labelNames.get(typeInfo.getLabel()))
132: .append(");\n");
133: break;
134: }
135: buf.append(field).append(".add(").append(localName)
136: .append(");\n");
137: }
138: buf.append("}\n");
139: }
140: }
141:
142: static void declareLabel(StringBuffer buf, Map labelNames, Label l) {
143: String name = (String) labelNames.get(l);
144: if (name == null) {
145: name = "l" + labelNames.size();
146: labelNames.put(l, name);
147: buf.append("Label ").append(name).append(
148: " = new Label();\n");
149: }
150: }
151:
152: public void trace(StringBuffer buf, Map labelNames) {
153: List frames = getFrames();
154: buf.append("[\n");
155: for (int i = 0; i < frames.size(); i++) {
156: StackMapFrame f = (StackMapFrame) frames.get(i);
157:
158: buf.append(" Frame:");
159: appendLabel(buf, labelNames, f.label);
160:
161: buf.append(" locals[");
162: traceTypeInfo(buf, labelNames, f.locals);
163: buf.append("]");
164: buf.append(" stack[");
165: traceTypeInfo(buf, labelNames, f.stack);
166: buf.append("]\n");
167: }
168: buf.append(" ] length:").append(len).append("\n");
169: }
170:
171: private void traceTypeInfo(StringBuffer buf, Map labelNames,
172: List infos) {
173: String sep = "";
174: for (int i = 0; i < infos.size(); i++) {
175: StackMapType t = (StackMapType) infos.get(i);
176:
177: buf.append(sep)
178: .append(StackMapType.ITEM_NAMES[t.getType()]);
179: sep = ", ";
180: if (t.getType() == StackMapType.ITEM_Object) {
181: buf.append(":").append(t.getObject());
182: }
183: if (t.getType() == StackMapType.ITEM_Uninitialized) {
184: buf.append(":");
185: appendLabel(buf, labelNames, t.getLabel());
186: }
187: }
188: }
189:
190: protected void appendLabel(StringBuffer buf, Map labelNames, Label l) {
191: String name = (String) labelNames.get(l);
192: if (name == null) {
193: name = "L" + labelNames.size();
194: labelNames.put(l, name);
195: }
196: buf.append(name);
197: }
198:
199: }
|