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