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 org.drools.asm.util.attrs;
030:
031: import java.util.List;
032: import java.util.Map;
033:
034: import org.drools.asm.Attribute;
035: import org.drools.asm.ClassReader;
036: import org.drools.asm.Label;
037: import org.drools.asm.attrs.StackMapFrame;
038: import org.drools.asm.attrs.StackMapTableAttribute;
039: import org.drools.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(final List frames, final int len) {
058: super (frames);
059: this .len = len;
060: }
061:
062: protected Attribute read(final ClassReader cr, final int off,
063: final int len, final char[] buf, final int codeOff,
064: final Label[] labels) {
065: final StackMapTableAttribute attr = (StackMapTableAttribute) super
066: .read(cr, off, len, buf, codeOff, labels);
067:
068: return new ASMStackMapTableAttribute(attr.getFrames(), len);
069: }
070:
071: public void asmify(final StringBuffer buf, final String varName,
072: final Map labelNames) {
073: final List frames = getFrames();
074: if (frames.size() == 0) {
075: buf.append("List frames = Collections.EMPTY_LIST;\n");
076: } else {
077: buf.append("List frames = new ArrayList();\n");
078: for (int i = 0; i < frames.size(); i++) {
079: buf.append("{\n");
080: final StackMapFrame f = (StackMapFrame) frames.get(i);
081: declareLabel(buf, labelNames, f.label);
082:
083: final String frameVar = varName + "frame" + i;
084: asmifyTypeInfo(buf, frameVar, labelNames, f.locals,
085: "locals");
086: asmifyTypeInfo(buf, frameVar, labelNames, f.stack,
087: "stack");
088:
089: buf.append("StackMapFrame ").append(frameVar).append(
090: " = new StackMapFrame(").append(
091: labelNames.get(f.label)).append(
092: ", locals, stack);\n");
093: buf.append("frames.add(").append(frameVar).append(
094: ");\n");
095: buf.append("}\n");
096: }
097: }
098: buf.append("StackMapTableAttribute ").append(varName);
099: buf.append(" = new StackMapTableAttribute(frames);\n");
100: }
101:
102: void asmifyTypeInfo(final StringBuffer buf, final String varName,
103: final Map labelNames, final List infos, final String field) {
104: if (infos.size() == 0) {
105: buf.append("List ").append(field).append(
106: " = Collections.EMPTY_LIST;\n");
107: } else {
108: buf.append("List ").append(field).append(
109: " = new ArrayList();\n");
110: buf.append("{\n");
111: for (int i = 0; i < infos.size(); i++) {
112: final StackMapType typeInfo = (StackMapType) infos
113: .get(i);
114: final String localName = varName + "Info" + i;
115: final int type = typeInfo.getType();
116: buf
117: .append("StackMapType ")
118: .append(localName)
119: .append(
120: " = StackMapType.getTypeInfo( StackMapType.ITEM_")
121: .append(StackMapType.ITEM_NAMES[type]).append(
122: ");\n");
123:
124: switch (type) {
125: case StackMapType.ITEM_Object: //
126: buf.append(localName).append(".setObject(\"")
127: .append(typeInfo.getObject()).append(
128: "\");\n");
129: break;
130:
131: case StackMapType.ITEM_Uninitialized: //
132: declareLabel(buf, labelNames, typeInfo.getLabel());
133: buf.append(localName).append(".setLabel(").append(
134: labelNames.get(typeInfo.getLabel()))
135: .append(");\n");
136: break;
137: }
138: buf.append(field).append(".add(").append(localName)
139: .append(");\n");
140: }
141: buf.append("}\n");
142: }
143: }
144:
145: static void declareLabel(final StringBuffer buf,
146: final Map labelNames, final Label l) {
147: String name = (String) labelNames.get(l);
148: if (name == null) {
149: name = "l" + labelNames.size();
150: labelNames.put(l, name);
151: buf.append("Label ").append(name).append(
152: " = new Label();\n");
153: }
154: }
155:
156: public void trace(final StringBuffer buf, final Map labelNames) {
157: final List frames = getFrames();
158: buf.append("[\n");
159: for (int i = 0; i < frames.size(); i++) {
160: final StackMapFrame f = (StackMapFrame) frames.get(i);
161:
162: buf.append(" Frame:");
163: appendLabel(buf, labelNames, f.label);
164:
165: buf.append(" locals[");
166: traceTypeInfo(buf, labelNames, f.locals);
167: buf.append("]");
168: buf.append(" stack[");
169: traceTypeInfo(buf, labelNames, f.stack);
170: buf.append("]\n");
171: }
172: buf.append(" ] length:").append(this .len).append("\n");
173: }
174:
175: private void traceTypeInfo(final StringBuffer buf,
176: final Map labelNames, final List infos) {
177: String sep = "";
178: for (int i = 0; i < infos.size(); i++) {
179: final StackMapType t = (StackMapType) infos.get(i);
180:
181: buf.append(sep)
182: .append(StackMapType.ITEM_NAMES[t.getType()]);
183: sep = ", ";
184: if (t.getType() == StackMapType.ITEM_Object) {
185: buf.append(":").append(t.getObject());
186: }
187: if (t.getType() == StackMapType.ITEM_Uninitialized) {
188: buf.append(":");
189: appendLabel(buf, labelNames, t.getLabel());
190: }
191: }
192: }
193:
194: protected void appendLabel(final StringBuffer buf,
195: final Map labelNames, final Label l) {
196: String name = (String) labelNames.get(l);
197: if (name == null) {
198: name = "L" + labelNames.size();
199: labelNames.put(l, name);
200: }
201: buf.append(name);
202: }
203:
204: }
|