001: // Copyright (c) Corporation for National Research Initiatives
002:
003: package org.python.compiler;
004:
005: import java.io.*;
006: import java.util.Vector;
007:
008: class ExceptionLabel {
009: public Label start, end, handler;
010: public int exc;
011:
012: public ExceptionLabel(Label start, Label end, Label handler, int exc) {
013: this .start = start;
014: this .end = end;
015: this .handler = handler;
016: this .exc = exc;
017: }
018: }
019:
020: public class Code extends Attribute {
021: ConstantPool pool;
022: public int stack;
023: int max_stack;
024: public DataOutputStream code;
025: ByteArrayOutputStream stream;
026: String sig;
027: String locals[];
028: int nlocals;
029: int argcount;
030: int att_name;
031: Vector labels, exceptions;
032: LineNumberTable linenumbers;
033: int returnLocal;
034:
035: public Label getLabel() {
036: Label l = new Label(this );
037: addLabel(l);
038: return l;
039: }
040:
041: public Label getLabelAtPosition() {
042: Label l = getLabel();
043: l.setPosition();
044: return l;
045: }
046:
047: public void addLabel(Label l) {
048: labels.addElement(l);
049: }
050:
051: public int size() {
052: return stream.size();
053: }
054:
055: public Code(String sig, ConstantPool pool, boolean isStatic) {
056: this .sig = sig;
057: max_stack = 2;
058: stack = 0;
059: this .pool = pool;
060: stream = new ByteArrayOutputStream();
061: code = new DataOutputStream(stream);
062: nlocals = -ConstantPool.sigSize(sig, false);
063: if (!isStatic)
064: nlocals = nlocals + 1;
065: argcount = nlocals;
066: locals = new String[nlocals + 128];
067: labels = new Vector();
068: exceptions = new Vector();
069: try {
070: att_name = pool.UTF8("Code");
071: } catch (IOException e) {
072: att_name = 0;
073: }
074: }
075:
076: public int getLocal(String type) {
077: //Could optimize this to skip arguments?
078: for (int l = argcount; l < nlocals; l++) {
079: if (locals[l] == null) {
080: locals[l] = type;
081: return l;
082: }
083: }
084: if (nlocals >= locals.length) {
085: String[] new_locals = new String[locals.length * 2];
086: System.arraycopy(locals, 0, new_locals, 0, locals.length);
087: locals = new_locals;
088: }
089: locals[nlocals] = type;
090: nlocals += 1;
091: return nlocals - 1;
092: }
093:
094: public void freeLocal(int l) {
095: if (locals[l] == null)
096: System.out.println("Double free:" + l);
097: locals[l] = null;
098: }
099:
100: java.util.BitSet finallyLocals = new java.util.BitSet();
101:
102: public int getFinallyLocal(String type) {
103: int l = getLocal(type);
104: finallyLocals.set(l);
105: return l;
106: }
107:
108: public void freeFinallyLocal(int l) {
109: finallyLocals.clear(l);
110: freeLocal(l);
111: }
112:
113: public int getReturnLocal() {
114: if (returnLocal == 0)
115: returnLocal = getLocal("return");
116: return returnLocal;
117: }
118:
119: public Vector getActiveLocals() {
120: Vector ret = new Vector();
121: ret.setSize(nlocals);
122: for (int l = argcount; l < nlocals; l++) {
123: if (l == returnLocal || finallyLocals.get(l))
124: continue;
125: ret.setElementAt(locals[l], l);
126: }
127: return ret;
128: }
129:
130: public void addExceptionHandler(Label begin, Label end,
131: Label handler, int exc) {
132: exceptions.addElement(new ExceptionLabel(begin, end, handler,
133: exc));
134: }
135:
136: /*
137: cl = self.code_length()
138: self.length = cl+12+8*len(self.exc_table)
139: cw.put2(self.name)
140: cw.put4(self.length)
141: cw.put2(self.max_stack)
142: cw.put2(len(self.locals))
143: cw.put4(cl)
144: self.dump_code(cw)
145: cw.put2(len(self.exc_table))
146: for start, end, handler, exc in self.exc_table:
147: cw.put2(self.labels[start])
148: cw.put2(self.labels[end])
149: cw.put2(self.labels[handler])
150: cw.put2(exc)
151: cw.dump_attributes(self.attributes)
152: */
153:
154: public void fixLabels(byte[] bytes) throws IOException {
155: for (int i = 0; i < labels.size(); i++) {
156: ((Label) labels.elementAt(i)).fix(bytes);
157: }
158: }
159:
160: public void write(DataOutputStream stream) throws IOException {
161: byte[] bytes = this .stream.toByteArray();
162:
163: fixLabels(bytes);
164:
165: int n = exceptions.size();
166: int length = bytes.length + 12 + 8 * n;
167: ;
168: if (linenumbers != null)
169: length += linenumbers.length();
170: stream.writeShort(att_name);
171: stream.writeInt(length);
172: stream.writeShort(max_stack);
173: stream.writeShort(nlocals);
174: stream.writeInt(bytes.length);
175: stream.write(bytes);
176:
177: //No Exceptions for now
178: stream.writeShort(n);
179: for (int i = 0; i < n; i++) {
180: ExceptionLabel e = (ExceptionLabel) exceptions.elementAt(i);
181: stream.writeShort(e.start.getPosition());
182: stream.writeShort(e.end.getPosition());
183: stream.writeShort(e.handler.getPosition());
184: stream.writeShort(e.exc);
185: }
186: if (linenumbers != null)
187: ClassFile.writeAttributes(stream,
188: new Attribute[] { linenumbers });
189: else
190: ClassFile.writeAttributes(stream, new Attribute[0]);
191: }
192:
193: public void push(int i) {
194: //System.out.println("push: "+i+" : "+stack);
195: stack = stack + i;
196: if (stack > max_stack)
197: max_stack = stack;
198: if (stack < 0)
199: throw new InternalError("stack < 0: " + stack);
200: }
201:
202: public void branch(int b, Label label) throws IOException {
203: int offset = size();
204: code.writeByte(b);
205: label.setBranch(offset, 2);
206: label.setStack(stack);
207: }
208:
209: public void print(String s) throws IOException {
210: getstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
211: ldc(s);
212: invokevirtual("java/io/PrintStream", "println",
213: "(Ljava/lang/String;)V");
214: }
215:
216: public void aaload() throws IOException {
217: code.writeByte(50);
218: push(-1);
219: }
220:
221: public void aastore() throws IOException {
222: code.writeByte(83);
223: push(-3);
224: }
225:
226: public void aconst_null() throws IOException {
227: code.writeByte(1);
228: push(1);
229: }
230:
231: public void aload(int i) throws IOException {
232: if (i >= 0 && i < 4) {
233: code.writeByte(42 + i);
234: } else {
235: code.writeByte(25);
236: code.writeByte(i);
237: }
238: push(1);
239: }
240:
241: public void anewarray(int c) throws IOException {
242: code.writeByte(189);
243: code.writeShort(c);
244: //push(-1); push(1);
245: }
246:
247: public void areturn() throws IOException {
248: code.writeByte(176);
249: push(-1);
250: }
251:
252: public void arraylength() throws IOException {
253: code.writeByte(190);
254: //push(-1); push(1);
255: }
256:
257: public void astore(int i) throws IOException {
258: if (i >= 0 && i < 4) {
259: code.writeByte(75 + i);
260: } else {
261: code.writeByte(58);
262: code.writeByte(i);
263: }
264: push(-1);
265: }
266:
267: public void athrow() throws IOException {
268: code.writeByte(191);
269: push(-1);
270: }
271:
272: public void checkcast(int c) throws IOException {
273: code.writeByte(192);
274: code.writeShort(c);
275: }
276:
277: public void dload(int i) throws IOException {
278: if (i >= 0 && i < 4) {
279: code.writeByte(38 + i);
280: } else {
281: code.writeByte(24);
282: code.writeByte(i);
283: }
284: push(2);
285: }
286:
287: public void dreturn() throws IOException {
288: code.writeByte(175);
289: push(-2);
290: }
291:
292: public void dup() throws IOException {
293: code.writeByte(89);
294: push(1);
295: }
296:
297: public void dup_x1() throws IOException {
298: code.writeByte(90);
299: push(1);
300: }
301:
302: public void fload(int i) throws IOException {
303: if (i >= 0 && i < 4) {
304: code.writeByte(34 + i);
305: } else {
306: code.writeByte(23);
307: code.writeByte(i);
308: }
309: push(1);
310: }
311:
312: public void freturn() throws IOException {
313: code.writeByte(174);
314: push(-1);
315: }
316:
317: public void getfield(int c) throws IOException {
318: code.writeByte(180);
319: code.writeShort(c);
320: push(pool.sizes[c] - 1);
321: }
322:
323: public void getfield(String c, String name, String type)
324: throws IOException {
325: getfield(pool.Fieldref(c, name, type));
326: }
327:
328: public void getstatic(int c) throws IOException {
329: code.writeByte(178);
330: code.writeShort(c);
331: push(pool.sizes[c]);
332: }
333:
334: public void getstatic(String c, String name, String type)
335: throws IOException {
336: getstatic(pool.Fieldref(c, name, type));
337: }
338:
339: public void goto_(Label label) throws IOException {
340: branch(167, label);
341: }
342:
343: public void iconst(int i) throws IOException {
344: if (i >= -1 && i <= 5) {
345: code.writeByte(3 + i);
346: } else {
347: if (i > -127 && i < 128) {
348: code.writeByte(16);
349: if (i < 0)
350: i = 256 + i;
351: code.writeByte(i);
352: } else {
353: if (i > -32767 && i < 32768) {
354: code.writeByte(17);
355: if (i < 0)
356: i = i + 65536;
357: code.writeShort(i);
358: } else {
359: ldc(pool.Integer(i));
360: }
361: }
362: }
363: push(1);
364: }
365:
366: public void if_icmpne(Label label) throws IOException {
367: push(-2);
368: branch(160, label);
369: }
370:
371: public void ifeq(Label label) throws IOException {
372: push(-1);
373: branch(153, label);
374: }
375:
376: public void ifne(Label label) throws IOException {
377: push(-1);
378: branch(154, label);
379: }
380:
381: public void ifnonnull(Label label) throws IOException {
382: push(-1);
383: branch(199, label);
384: }
385:
386: public void ifnull(Label label) throws IOException {
387: push(-1);
388: branch(198, label);
389: }
390:
391: public void iinc(int i, int increment) throws IOException {
392: code.writeByte(132);
393: code.writeByte(i);
394: code.writeByte(increment);
395: }
396:
397: public void iinc(int i) throws IOException {
398: iinc(i, 1);
399: }
400:
401: public void iload(int i) throws IOException {
402: if (i >= 0 && i < 4) {
403: code.writeByte(26 + i);
404: } else {
405: code.writeByte(21);
406: code.writeByte(i);
407: }
408: push(1);
409: }
410:
411: public void invokespecial(int c) throws IOException {
412: code.writeByte(183);
413: code.writeShort(c);
414: push(pool.sizes[c] - 1);
415: }
416:
417: public void invokestatic(int c) throws IOException {
418: code.writeByte(184);
419: code.writeShort(c);
420: push(pool.sizes[c]);
421: }
422:
423: public void invokevirtual(int c) throws IOException {
424: code.writeByte(182);
425: code.writeShort(c);
426: push(pool.sizes[c] - 1);
427: }
428:
429: public void invokevirtual(String c, String name, String type)
430: throws IOException {
431: invokevirtual(pool.Methodref(c, name, type));
432: }
433:
434: public void ireturn() throws IOException {
435: code.writeByte(172);
436: push(-1);
437: }
438:
439: public void istore(int i) throws IOException {
440: if (i >= 0 && i < 4) {
441: code.writeByte(59 + i);
442: } else {
443: code.writeByte(54);
444: code.writeByte(i);
445: }
446: push(-1);
447: }
448:
449: public void jsr(Label label) throws IOException {
450: //push(-1);
451: int offset = size();
452: code.writeByte(168);
453: label.setBranch(offset, 2);
454: label.setStack(stack + 1);
455: }
456:
457: public void ldc(int c) throws IOException {
458: int size = pool.sizes[c];
459: if (size == 1) {
460: if (c < 256) {
461: code.writeByte(18);
462: code.writeByte(c);
463: } else {
464: code.writeByte(19);
465: code.writeShort(c);
466: }
467: } else {
468: code.writeByte(20);
469: code.writeShort(c);
470: }
471:
472: push(pool.sizes[c]);
473: }
474:
475: public void ldc(String s) throws IOException {
476: ldc(pool.String(s));
477: }
478:
479: public void lload(int i) throws IOException {
480: if (i >= 0 && i < 4) {
481: code.writeByte(30 + i);
482: } else {
483: code.writeByte(22);
484: code.writeByte(i);
485: }
486: push(2);
487: }
488:
489: public void lreturn() throws IOException {
490: code.writeByte(173);
491: push(-2);
492: }
493:
494: public void new_(int c) throws IOException {
495: code.writeByte(187);
496: code.writeShort(c);
497: push(1);
498: }
499:
500: public void pop() throws IOException {
501: code.writeByte(87);
502: push(-1);
503: }
504:
505: public void putfield(int c) throws IOException {
506: code.writeByte(181);
507: code.writeShort(c);
508: push(-pool.sizes[c] - 1);
509: }
510:
511: public void putfield(String c, String name, String type)
512: throws IOException {
513: putfield(pool.Fieldref(c, name, type));
514: }
515:
516: public void putstatic(int c) throws IOException {
517: code.writeByte(179);
518: code.writeShort(c);
519: push(-pool.sizes[c]);
520: }
521:
522: public void putstatic(String c, String name, String type)
523: throws IOException {
524: putstatic(pool.Fieldref(c, name, type));
525: }
526:
527: public void return_() throws IOException {
528: code.writeByte(177);
529: }
530:
531: public void ret(int index) throws IOException {
532: code.writeByte(169);
533: code.writeByte(index);
534: }
535:
536: public void swap() throws IOException {
537: code.writeByte(95);
538: }
539:
540: public void tableswitch(Label def, int low, Label[] labels)
541: throws IOException {
542: int position = size();
543: push(-1);
544: code.writeByte(170);
545: for (int j = 0; j < 3 - (position % 4); j++)
546: code.writeByte(0);
547: def.setBranch(position, 4);
548: code.writeInt(low);
549: code.writeInt(labels.length - 1);
550: for (int i = 0; i < labels.length; i++) {
551: labels[i].setBranch(position, 4);
552: }
553: }
554:
555: public void setline(int line) throws IOException {
556: if (linenumbers == null)
557: linenumbers = new LineNumberTable(pool);
558: linenumbers.addLine(size(), line);
559: }
560: }
|