1 /*
2  * Copyright (c) 2001, 2004, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package jdk.internal.reflect;
27 
28 class ClassFileAssembler implements ClassFileConstants {
29     private ByteVector vec;
30     private short cpIdx = 0;
31 
ClassFileAssembler()32     public ClassFileAssembler() {
33         this(ByteVectorFactory.create());
34     }
35 
ClassFileAssembler(ByteVector vec)36     public ClassFileAssembler(ByteVector vec) {
37         this.vec = vec;
38     }
39 
getData()40     public ByteVector getData() {
41         return vec;
42     }
43 
44     /** Length in bytes */
getLength()45     public short getLength() {
46         return (short) vec.getLength();
47     }
48 
emitMagicAndVersion()49     public void emitMagicAndVersion() {
50         emitInt(0xCAFEBABE);
51         emitShort((short) 0);
52         emitShort((short) 49);
53     }
54 
emitInt(int val)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 
emitShort(short val)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
emitShort(short bci, short val)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 
emitByte(byte val)73     public void emitByte(byte val) {
74         vec.add(val);
75     }
76 
append(ClassFileAssembler asm)77     public void append(ClassFileAssembler asm) {
78         append(asm.vec);
79     }
80 
append(ByteVector vec)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. */
cpi()93     public short cpi() {
94         if (cpIdx == 0) {
95             throw new RuntimeException("Illegal use of ClassFileAssembler");
96         }
97         return cpIdx;
98     }
99 
emitConstantPoolUTF8(String str)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 
emitConstantPoolClass(short index)112     public void emitConstantPoolClass(short index) {
113         emitByte(CONSTANT_Class);
114         emitShort(index);
115         cpIdx++;
116     }
117 
emitConstantPoolNameAndType(short nameIndex, short typeIndex)118     public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {
119         emitByte(CONSTANT_NameAndType);
120         emitShort(nameIndex);
121         emitShort(typeIndex);
122         cpIdx++;
123     }
124 
emitConstantPoolFieldref(short classIndex, short nameAndTypeIndex)125     public void emitConstantPoolFieldref
126         (short classIndex, short nameAndTypeIndex)
127     {
128         emitByte(CONSTANT_Fieldref);
129         emitShort(classIndex);
130         emitShort(nameAndTypeIndex);
131         cpIdx++;
132     }
133 
emitConstantPoolMethodref(short classIndex, short nameAndTypeIndex)134     public void emitConstantPoolMethodref
135         (short classIndex, short nameAndTypeIndex)
136     {
137         emitByte(CONSTANT_Methodref);
138         emitShort(classIndex);
139         emitShort(nameAndTypeIndex);
140         cpIdx++;
141     }
142 
emitConstantPoolInterfaceMethodref(short classIndex, short nameAndTypeIndex)143     public void emitConstantPoolInterfaceMethodref
144         (short classIndex, short nameAndTypeIndex)
145     {
146         emitByte(CONSTANT_InterfaceMethodref);
147         emitShort(classIndex);
148         emitShort(nameAndTypeIndex);
149         cpIdx++;
150     }
151 
emitConstantPoolString(short utf8Index)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 
incStack()168     private void incStack() {
169         setStack(stack + 1);
170     }
171 
decStack()172     private void decStack() {
173         --stack;
174     }
175 
getMaxStack()176     public short getMaxStack() {
177         return (short) maxStack;
178     }
179 
getMaxLocals()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) */
setMaxLocals(int maxLocals)187     public void setMaxLocals(int maxLocals) {
188         this.maxLocals = maxLocals;
189     }
190 
191     /** Needed to do flow control. Returns current stack depth. */
getStack()192     public int getStack() {
193         return stack;
194     }
195 
196     /** Needed to do flow control. */
setStack(int value)197     public void setStack(int value) {
198         stack = value;
199         if (stack > maxStack) {
200             maxStack = stack;
201         }
202     }
203 
204     ///////////////
205     // Constants //
206     ///////////////
207 
opc_aconst_null()208     public void opc_aconst_null() {
209         emitByte(opc_aconst_null);
210         incStack();
211     }
212 
opc_sipush(short constant)213     public void opc_sipush(short constant) {
214         emitByte(opc_sipush);
215         emitShort(constant);
216         incStack();
217     }
218 
opc_ldc(byte cpIdx)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 
opc_iload_0()229     public void opc_iload_0() {
230         emitByte(opc_iload_0);
231         if (maxLocals < 1) maxLocals = 1;
232         incStack();
233     }
234 
opc_iload_1()235     public void opc_iload_1() {
236         emitByte(opc_iload_1);
237         if (maxLocals < 2) maxLocals = 2;
238         incStack();
239     }
240 
opc_iload_2()241     public void opc_iload_2() {
242         emitByte(opc_iload_2);
243         if (maxLocals < 3) maxLocals = 3;
244         incStack();
245     }
246 
opc_iload_3()247     public void opc_iload_3() {
248         emitByte(opc_iload_3);
249         if (maxLocals < 4) maxLocals = 4;
250         incStack();
251     }
252 
opc_lload_0()253     public void opc_lload_0() {
254         emitByte(opc_lload_0);
255         if (maxLocals < 2) maxLocals = 2;
256         incStack();
257         incStack();
258     }
259 
opc_lload_1()260     public void opc_lload_1() {
261         emitByte(opc_lload_1);
262         if (maxLocals < 3) maxLocals = 3;
263         incStack();
264         incStack();
265     }
266 
opc_lload_2()267     public void opc_lload_2() {
268         emitByte(opc_lload_2);
269         if (maxLocals < 4) maxLocals = 4;
270         incStack();
271         incStack();
272     }
273 
opc_lload_3()274     public void opc_lload_3() {
275         emitByte(opc_lload_3);
276         if (maxLocals < 5) maxLocals = 5;
277         incStack();
278         incStack();
279     }
280 
opc_fload_0()281     public void opc_fload_0() {
282         emitByte(opc_fload_0);
283         if (maxLocals < 1) maxLocals = 1;
284         incStack();
285     }
286 
opc_fload_1()287     public void opc_fload_1() {
288         emitByte(opc_fload_1);
289         if (maxLocals < 2) maxLocals = 2;
290         incStack();
291     }
292 
opc_fload_2()293     public void opc_fload_2() {
294         emitByte(opc_fload_2);
295         if (maxLocals < 3) maxLocals = 3;
296         incStack();
297     }
298 
opc_fload_3()299     public void opc_fload_3() {
300         emitByte(opc_fload_3);
301         if (maxLocals < 4) maxLocals = 4;
302         incStack();
303     }
304 
opc_dload_0()305     public void opc_dload_0() {
306         emitByte(opc_dload_0);
307         if (maxLocals < 2) maxLocals = 2;
308         incStack();
309         incStack();
310     }
311 
opc_dload_1()312     public void opc_dload_1() {
313         emitByte(opc_dload_1);
314         if (maxLocals < 3) maxLocals = 3;
315         incStack();
316         incStack();
317     }
318 
opc_dload_2()319     public void opc_dload_2() {
320         emitByte(opc_dload_2);
321         if (maxLocals < 4) maxLocals = 4;
322         incStack();
323         incStack();
324     }
325 
opc_dload_3()326     public void opc_dload_3() {
327         emitByte(opc_dload_3);
328         if (maxLocals < 5) maxLocals = 5;
329         incStack();
330         incStack();
331     }
332 
opc_aload_0()333     public void opc_aload_0() {
334         emitByte(opc_aload_0);
335         if (maxLocals < 1) maxLocals = 1;
336         incStack();
337     }
338 
opc_aload_1()339     public void opc_aload_1() {
340         emitByte(opc_aload_1);
341         if (maxLocals < 2) maxLocals = 2;
342         incStack();
343     }
344 
opc_aload_2()345     public void opc_aload_2() {
346         emitByte(opc_aload_2);
347         if (maxLocals < 3) maxLocals = 3;
348         incStack();
349     }
350 
opc_aload_3()351     public void opc_aload_3() {
352         emitByte(opc_aload_3);
353         if (maxLocals < 4) maxLocals = 4;
354         incStack();
355     }
356 
opc_aaload()357     public void opc_aaload() {
358         emitByte(opc_aaload);
359         decStack();
360     }
361 
opc_astore_0()362     public void opc_astore_0() {
363         emitByte(opc_astore_0);
364         if (maxLocals < 1) maxLocals = 1;
365         decStack();
366     }
367 
opc_astore_1()368     public void opc_astore_1() {
369         emitByte(opc_astore_1);
370         if (maxLocals < 2) maxLocals = 2;
371         decStack();
372     }
373 
opc_astore_2()374     public void opc_astore_2() {
375         emitByte(opc_astore_2);
376         if (maxLocals < 3) maxLocals = 3;
377         decStack();
378     }
379 
opc_astore_3()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 
opc_pop()390     public void opc_pop() {
391         emitByte(opc_pop);
392         decStack();
393     }
394 
opc_dup()395     public void opc_dup() {
396         emitByte(opc_dup);
397         incStack();
398     }
399 
opc_dup_x1()400     public void opc_dup_x1() {
401         emitByte(opc_dup_x1);
402         incStack();
403     }
404 
opc_swap()405     public void opc_swap() {
406         emitByte(opc_swap);
407     }
408 
409     ///////////////////////////////
410     // Widening conversions only //
411     ///////////////////////////////
412 
opc_i2l()413     public void opc_i2l() {
414         emitByte(opc_i2l);
415     }
416 
opc_i2f()417     public void opc_i2f() {
418         emitByte(opc_i2f);
419     }
420 
opc_i2d()421     public void opc_i2d() {
422         emitByte(opc_i2d);
423     }
424 
opc_l2f()425     public void opc_l2f() {
426         emitByte(opc_l2f);
427     }
428 
opc_l2d()429     public void opc_l2d() {
430         emitByte(opc_l2d);
431     }
432 
opc_f2d()433     public void opc_f2d() {
434         emitByte(opc_f2d);
435     }
436 
437     //////////////////
438     // Control flow //
439     //////////////////
440 
opc_ifeq(short bciOffset)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. */
opc_ifeq(Label l)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 
opc_if_icmpeq(short bciOffset)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. */
opc_if_icmpeq(Label l)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 
opc_goto(short bciOffset)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. */
opc_goto(Label l)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 
opc_ifnull(short bciOffset)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. */
opc_ifnull(Label l)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 
opc_ifnonnull(short bciOffset)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. */
opc_ifnonnull(Label l)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 
opc_ireturn()521     public void opc_ireturn() {
522         emitByte(opc_ireturn);
523         setStack(0);
524     }
525 
opc_lreturn()526     public void opc_lreturn() {
527         emitByte(opc_lreturn);
528         setStack(0);
529     }
530 
opc_freturn()531     public void opc_freturn() {
532         emitByte(opc_freturn);
533         setStack(0);
534     }
535 
opc_dreturn()536     public void opc_dreturn() {
537         emitByte(opc_dreturn);
538         setStack(0);
539     }
540 
opc_areturn()541     public void opc_areturn() {
542         emitByte(opc_areturn);
543         setStack(0);
544     }
545 
opc_return()546     public void opc_return() {
547         emitByte(opc_return);
548         setStack(0);
549     }
550 
551     //////////////////////
552     // Field operations //
553     //////////////////////
554 
opc_getstatic(short fieldIndex, int fieldSizeInStackSlots)555     public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {
556         emitByte(opc_getstatic);
557         emitShort(fieldIndex);
558         setStack(getStack() + fieldSizeInStackSlots);
559     }
560 
opc_putstatic(short fieldIndex, int fieldSizeInStackSlots)561     public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {
562         emitByte(opc_putstatic);
563         emitShort(fieldIndex);
564         setStack(getStack() - fieldSizeInStackSlots);
565     }
566 
opc_getfield(short fieldIndex, int fieldSizeInStackSlots)567     public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
568         emitByte(opc_getfield);
569         emitShort(fieldIndex);
570         setStack(getStack() + fieldSizeInStackSlots - 1);
571     }
572 
opc_putfield(short fieldIndex, int fieldSizeInStackSlots)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. */
opc_invokevirtual(short methodIndex, int numArgs, int numReturnValues)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. */
opc_invokespecial(short methodIndex, int numArgs, int numReturnValues)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. */
opc_invokestatic(short methodIndex, int numArgs, int numReturnValues)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. */
opc_invokeinterface(short methodIndex, int numArgs, byte count, int numReturnValues)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 
opc_arraylength()634     public void opc_arraylength() {
635         emitByte(opc_arraylength);
636     }
637 
638     /////////
639     // New //
640     /////////
641 
opc_new(short classIndex)642     public void opc_new(short classIndex) {
643         emitByte(opc_new);
644         emitShort(classIndex);
645         incStack();
646     }
647 
648     ////////////
649     // Athrow //
650     ////////////
651 
opc_athrow()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 */
opc_checkcast(short classIndex)662     public void opc_checkcast(short classIndex) {
663         emitByte(opc_checkcast);
664         emitShort(classIndex);
665     }
666 
opc_instanceof(short classIndex)667     public void opc_instanceof(short classIndex) {
668         emitByte(opc_instanceof);
669         emitShort(classIndex);
670     }
671 }
672