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