001: /*
002: * Copyright 2001-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.reflect;
027:
028: class ClassFileAssembler implements ClassFileConstants {
029: private ByteVector vec;
030: private short cpIdx = 0;
031:
032: public ClassFileAssembler() {
033: this (ByteVectorFactory.create());
034: }
035:
036: public ClassFileAssembler(ByteVector vec) {
037: this .vec = vec;
038: }
039:
040: public ByteVector getData() {
041: return vec;
042: }
043:
044: /** Length in bytes */
045: public short getLength() {
046: return (short) vec.getLength();
047: }
048:
049: public void emitMagicAndVersion() {
050: emitInt(0xCAFEBABE);
051: emitShort((short) 0);
052: emitShort((short) 49);
053: }
054:
055: public void emitInt(int val) {
056: emitByte((byte) (val >> 24));
057: emitByte((byte) ((val >> 16) & 0xFF));
058: emitByte((byte) ((val >> 8) & 0xFF));
059: emitByte((byte) (val & 0xFF));
060: }
061:
062: public void emitShort(short val) {
063: emitByte((byte) ((val >> 8) & 0xFF));
064: emitByte((byte) (val & 0xFF));
065: }
066:
067: // Support for labels; package-private
068: void emitShort(short bci, short val) {
069: vec.put(bci, (byte) ((val >> 8) & 0xFF));
070: vec.put(bci + 1, (byte) (val & 0xFF));
071: }
072:
073: public void emitByte(byte val) {
074: vec.add(val);
075: }
076:
077: public void append(ClassFileAssembler asm) {
078: append(asm.vec);
079: }
080:
081: public void append(ByteVector vec) {
082: for (int i = 0; i < vec.getLength(); i++) {
083: emitByte(vec.get(i));
084: }
085: }
086:
087: /** Keeps track of the current (one-based) constant pool index;
088: incremented after emitting one of the following constant pool
089: entries. Can fetch the current constant pool index for use in
090: later entries. Index points at the last valid constant pool
091: entry; initially invalid. It is illegal to fetch the constant
092: pool index before emitting at least one constant pool entry. */
093: public short cpi() {
094: if (cpIdx == 0) {
095: throw new RuntimeException(
096: "Illegal use of ClassFileAssembler");
097: }
098: return cpIdx;
099: }
100:
101: public void emitConstantPoolUTF8(String str) {
102: // NOTE: can not use str.getBytes("UTF-8") here because of
103: // bootstrapping issues with the character set converters.
104: byte[] bytes = UTF8.encode(str);
105: emitByte(CONSTANT_Utf8);
106: emitShort((short) bytes.length);
107: for (int i = 0; i < bytes.length; i++) {
108: emitByte(bytes[i]);
109: }
110: cpIdx++;
111: }
112:
113: public void emitConstantPoolClass(short index) {
114: emitByte(CONSTANT_Class);
115: emitShort(index);
116: cpIdx++;
117: }
118:
119: public void emitConstantPoolNameAndType(short nameIndex,
120: short typeIndex) {
121: emitByte(CONSTANT_NameAndType);
122: emitShort(nameIndex);
123: emitShort(typeIndex);
124: cpIdx++;
125: }
126:
127: public void emitConstantPoolFieldref(short classIndex,
128: short nameAndTypeIndex) {
129: emitByte(CONSTANT_Fieldref);
130: emitShort(classIndex);
131: emitShort(nameAndTypeIndex);
132: cpIdx++;
133: }
134:
135: public void emitConstantPoolMethodref(short classIndex,
136: short nameAndTypeIndex) {
137: emitByte(CONSTANT_Methodref);
138: emitShort(classIndex);
139: emitShort(nameAndTypeIndex);
140: cpIdx++;
141: }
142:
143: public void emitConstantPoolInterfaceMethodref(short classIndex,
144: short nameAndTypeIndex) {
145: emitByte(CONSTANT_InterfaceMethodref);
146: emitShort(classIndex);
147: emitShort(nameAndTypeIndex);
148: cpIdx++;
149: }
150:
151: public void emitConstantPoolString(short utf8Index) {
152: emitByte(CONSTANT_String);
153: emitShort(utf8Index);
154: cpIdx++;
155: }
156:
157: //----------------------------------------------------------------------
158: // Opcodes. Keeps track of maximum stack and locals. Make a new
159: // assembler for each piece of assembled code, then append the
160: // result to the previous assembler's class file.
161: //
162:
163: private int stack = 0;
164: private int maxStack = 0;
165: private int maxLocals = 0;
166:
167: private void incStack() {
168: setStack(stack + 1);
169: }
170:
171: private void decStack() {
172: --stack;
173: }
174:
175: public short getMaxStack() {
176: return (short) maxStack;
177: }
178:
179: public short getMaxLocals() {
180: return (short) maxLocals;
181: }
182:
183: /** It's necessary to be able to specify the number of arguments at
184: the beginning of the method (which translates to the initial
185: value of max locals) */
186: public void setMaxLocals(int maxLocals) {
187: this .maxLocals = maxLocals;
188: }
189:
190: /** Needed to do flow control. Returns current stack depth. */
191: public int getStack() {
192: return stack;
193: }
194:
195: /** Needed to do flow control. */
196: public void setStack(int value) {
197: stack = value;
198: if (stack > maxStack) {
199: maxStack = stack;
200: }
201: }
202:
203: ///////////////
204: // Constants //
205: ///////////////
206:
207: public void opc_aconst_null() {
208: emitByte(opc_aconst_null);
209: incStack();
210: }
211:
212: public void opc_sipush(short constant) {
213: emitByte(opc_sipush);
214: emitShort(constant);
215: incStack();
216: }
217:
218: public void opc_ldc(byte cpIdx) {
219: emitByte(opc_ldc);
220: emitByte(cpIdx);
221: incStack();
222: }
223:
224: /////////////////////////////////////
225: // Local variable loads and stores //
226: /////////////////////////////////////
227:
228: public void opc_iload_0() {
229: emitByte(opc_iload_0);
230: if (maxLocals < 1)
231: maxLocals = 1;
232: incStack();
233: }
234:
235: public void opc_iload_1() {
236: emitByte(opc_iload_1);
237: if (maxLocals < 2)
238: maxLocals = 2;
239: incStack();
240: }
241:
242: public void opc_iload_2() {
243: emitByte(opc_iload_2);
244: if (maxLocals < 3)
245: maxLocals = 3;
246: incStack();
247: }
248:
249: public void opc_iload_3() {
250: emitByte(opc_iload_3);
251: if (maxLocals < 4)
252: maxLocals = 4;
253: incStack();
254: }
255:
256: public void opc_lload_0() {
257: emitByte(opc_lload_0);
258: if (maxLocals < 2)
259: maxLocals = 2;
260: incStack();
261: incStack();
262: }
263:
264: public void opc_lload_1() {
265: emitByte(opc_lload_1);
266: if (maxLocals < 3)
267: maxLocals = 3;
268: incStack();
269: incStack();
270: }
271:
272: public void opc_lload_2() {
273: emitByte(opc_lload_2);
274: if (maxLocals < 4)
275: maxLocals = 4;
276: incStack();
277: incStack();
278: }
279:
280: public void opc_lload_3() {
281: emitByte(opc_lload_3);
282: if (maxLocals < 5)
283: maxLocals = 5;
284: incStack();
285: incStack();
286: }
287:
288: public void opc_fload_0() {
289: emitByte(opc_fload_0);
290: if (maxLocals < 1)
291: maxLocals = 1;
292: incStack();
293: }
294:
295: public void opc_fload_1() {
296: emitByte(opc_fload_1);
297: if (maxLocals < 2)
298: maxLocals = 2;
299: incStack();
300: }
301:
302: public void opc_fload_2() {
303: emitByte(opc_fload_2);
304: if (maxLocals < 3)
305: maxLocals = 3;
306: incStack();
307: }
308:
309: public void opc_fload_3() {
310: emitByte(opc_fload_3);
311: if (maxLocals < 4)
312: maxLocals = 4;
313: incStack();
314: }
315:
316: public void opc_dload_0() {
317: emitByte(opc_dload_0);
318: if (maxLocals < 2)
319: maxLocals = 2;
320: incStack();
321: incStack();
322: }
323:
324: public void opc_dload_1() {
325: emitByte(opc_dload_1);
326: if (maxLocals < 3)
327: maxLocals = 3;
328: incStack();
329: incStack();
330: }
331:
332: public void opc_dload_2() {
333: emitByte(opc_dload_2);
334: if (maxLocals < 4)
335: maxLocals = 4;
336: incStack();
337: incStack();
338: }
339:
340: public void opc_dload_3() {
341: emitByte(opc_dload_3);
342: if (maxLocals < 5)
343: maxLocals = 5;
344: incStack();
345: incStack();
346: }
347:
348: public void opc_aload_0() {
349: emitByte(opc_aload_0);
350: if (maxLocals < 1)
351: maxLocals = 1;
352: incStack();
353: }
354:
355: public void opc_aload_1() {
356: emitByte(opc_aload_1);
357: if (maxLocals < 2)
358: maxLocals = 2;
359: incStack();
360: }
361:
362: public void opc_aload_2() {
363: emitByte(opc_aload_2);
364: if (maxLocals < 3)
365: maxLocals = 3;
366: incStack();
367: }
368:
369: public void opc_aload_3() {
370: emitByte(opc_aload_3);
371: if (maxLocals < 4)
372: maxLocals = 4;
373: incStack();
374: }
375:
376: public void opc_aaload() {
377: emitByte(opc_aaload);
378: decStack();
379: }
380:
381: public void opc_astore_0() {
382: emitByte(opc_astore_0);
383: if (maxLocals < 1)
384: maxLocals = 1;
385: decStack();
386: }
387:
388: public void opc_astore_1() {
389: emitByte(opc_astore_1);
390: if (maxLocals < 2)
391: maxLocals = 2;
392: decStack();
393: }
394:
395: public void opc_astore_2() {
396: emitByte(opc_astore_2);
397: if (maxLocals < 3)
398: maxLocals = 3;
399: decStack();
400: }
401:
402: public void opc_astore_3() {
403: emitByte(opc_astore_3);
404: if (maxLocals < 4)
405: maxLocals = 4;
406: decStack();
407: }
408:
409: ////////////////////////
410: // Stack manipulation //
411: ////////////////////////
412:
413: public void opc_pop() {
414: emitByte(opc_pop);
415: decStack();
416: }
417:
418: public void opc_dup() {
419: emitByte(opc_dup);
420: incStack();
421: }
422:
423: public void opc_dup_x1() {
424: emitByte(opc_dup_x1);
425: incStack();
426: }
427:
428: public void opc_swap() {
429: emitByte(opc_swap);
430: }
431:
432: ///////////////////////////////
433: // Widening conversions only //
434: ///////////////////////////////
435:
436: public void opc_i2l() {
437: emitByte(opc_i2l);
438: }
439:
440: public void opc_i2f() {
441: emitByte(opc_i2f);
442: }
443:
444: public void opc_i2d() {
445: emitByte(opc_i2d);
446: }
447:
448: public void opc_l2f() {
449: emitByte(opc_l2f);
450: }
451:
452: public void opc_l2d() {
453: emitByte(opc_l2d);
454: }
455:
456: public void opc_f2d() {
457: emitByte(opc_f2d);
458: }
459:
460: //////////////////
461: // Control flow //
462: //////////////////
463:
464: public void opc_ifeq(short bciOffset) {
465: emitByte(opc_ifeq);
466: emitShort(bciOffset);
467: decStack();
468: }
469:
470: /** Control flow with forward-reference BCI. Stack assumes
471: straight-through control flow. */
472: public void opc_ifeq(Label l) {
473: short instrBCI = getLength();
474: emitByte(opc_ifeq);
475: l.add(this , instrBCI, getLength(), getStack() - 1);
476: emitShort((short) -1); // Must be patched later
477: }
478:
479: public void opc_if_icmpeq(short bciOffset) {
480: emitByte(opc_if_icmpeq);
481: emitShort(bciOffset);
482: setStack(getStack() - 2);
483: }
484:
485: /** Control flow with forward-reference BCI. Stack assumes straight
486: control flow. */
487: public void opc_if_icmpeq(Label l) {
488: short instrBCI = getLength();
489: emitByte(opc_if_icmpeq);
490: l.add(this , instrBCI, getLength(), getStack() - 2);
491: emitShort((short) -1); // Must be patched later
492: }
493:
494: public void opc_goto(short bciOffset) {
495: emitByte(opc_goto);
496: emitShort(bciOffset);
497: }
498:
499: /** Control flow with forward-reference BCI. Stack assumes straight
500: control flow. */
501: public void opc_goto(Label l) {
502: short instrBCI = getLength();
503: emitByte(opc_goto);
504: l.add(this , instrBCI, getLength(), getStack());
505: emitShort((short) -1); // Must be patched later
506: }
507:
508: public void opc_ifnull(short bciOffset) {
509: emitByte(opc_ifnull);
510: emitShort(bciOffset);
511: decStack();
512: }
513:
514: /** Control flow with forward-reference BCI. Stack assumes straight
515: control flow. */
516: public void opc_ifnull(Label l) {
517: short instrBCI = getLength();
518: emitByte(opc_ifnull);
519: l.add(this , instrBCI, getLength(), getStack() - 1);
520: emitShort((short) -1); // Must be patched later
521: decStack();
522: }
523:
524: public void opc_ifnonnull(short bciOffset) {
525: emitByte(opc_ifnonnull);
526: emitShort(bciOffset);
527: decStack();
528: }
529:
530: /** Control flow with forward-reference BCI. Stack assumes straight
531: control flow. */
532: public void opc_ifnonnull(Label l) {
533: short instrBCI = getLength();
534: emitByte(opc_ifnonnull);
535: l.add(this , instrBCI, getLength(), getStack() - 1);
536: emitShort((short) -1); // Must be patched later
537: decStack();
538: }
539:
540: /////////////////////////
541: // Return instructions //
542: /////////////////////////
543:
544: public void opc_ireturn() {
545: emitByte(opc_ireturn);
546: setStack(0);
547: }
548:
549: public void opc_lreturn() {
550: emitByte(opc_lreturn);
551: setStack(0);
552: }
553:
554: public void opc_freturn() {
555: emitByte(opc_freturn);
556: setStack(0);
557: }
558:
559: public void opc_dreturn() {
560: emitByte(opc_dreturn);
561: setStack(0);
562: }
563:
564: public void opc_areturn() {
565: emitByte(opc_areturn);
566: setStack(0);
567: }
568:
569: public void opc_return() {
570: emitByte(opc_return);
571: setStack(0);
572: }
573:
574: //////////////////////
575: // Field operations //
576: //////////////////////
577:
578: public void opc_getstatic(short fieldIndex,
579: int fieldSizeInStackSlots) {
580: emitByte(opc_getstatic);
581: emitShort(fieldIndex);
582: setStack(getStack() + fieldSizeInStackSlots);
583: }
584:
585: public void opc_putstatic(short fieldIndex,
586: int fieldSizeInStackSlots) {
587: emitByte(opc_putstatic);
588: emitShort(fieldIndex);
589: setStack(getStack() - fieldSizeInStackSlots);
590: }
591:
592: public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
593: emitByte(opc_getfield);
594: emitShort(fieldIndex);
595: setStack(getStack() + fieldSizeInStackSlots - 1);
596: }
597:
598: public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {
599: emitByte(opc_putfield);
600: emitShort(fieldIndex);
601: setStack(getStack() - fieldSizeInStackSlots - 1);
602: }
603:
604: ////////////////////////
605: // Method invocations //
606: ////////////////////////
607:
608: /** Long and double arguments and return types count as 2 arguments;
609: other values count as 1. */
610: public void opc_invokevirtual(short methodIndex, int numArgs,
611: int numReturnValues) {
612: emitByte(opc_invokevirtual);
613: emitShort(methodIndex);
614: setStack(getStack() - numArgs - 1 + numReturnValues);
615: }
616:
617: /** Long and double arguments and return types count as 2 arguments;
618: other values count as 1. */
619: public void opc_invokespecial(short methodIndex, int numArgs,
620: int numReturnValues) {
621: emitByte(opc_invokespecial);
622: emitShort(methodIndex);
623: setStack(getStack() - numArgs - 1 + numReturnValues);
624: }
625:
626: /** Long and double arguments and return types count as 2 arguments;
627: other values count as 1. */
628: public void opc_invokestatic(short methodIndex, int numArgs,
629: int numReturnValues) {
630: emitByte(opc_invokestatic);
631: emitShort(methodIndex);
632: setStack(getStack() - numArgs + numReturnValues);
633: }
634:
635: /** Long and double arguments and return types count as 2 arguments;
636: other values count as 1. */
637: public void opc_invokeinterface(short methodIndex, int numArgs,
638: byte count, int numReturnValues) {
639: emitByte(opc_invokeinterface);
640: emitShort(methodIndex);
641: emitByte(count);
642: emitByte((byte) 0);
643: setStack(getStack() - numArgs - 1 + numReturnValues);
644: }
645:
646: //////////////////
647: // Array length //
648: //////////////////
649:
650: public void opc_arraylength() {
651: emitByte(opc_arraylength);
652: }
653:
654: /////////
655: // New //
656: /////////
657:
658: public void opc_new(short classIndex) {
659: emitByte(opc_new);
660: emitShort(classIndex);
661: incStack();
662: }
663:
664: ////////////
665: // Athrow //
666: ////////////
667:
668: public void opc_athrow() {
669: emitByte(opc_athrow);
670: setStack(1);
671: }
672:
673: //////////////////////////////
674: // Checkcast and instanceof //
675: //////////////////////////////
676:
677: /** Assumes the checkcast succeeds */
678: public void opc_checkcast(short classIndex) {
679: emitByte(opc_checkcast);
680: emitShort(classIndex);
681: }
682:
683: public void opc_instanceof (short classIndex) {
684: emitByte(opc_instanceof);
685: emitShort(classIndex);
686: }
687: }
|