You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Bytecode.java 36KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist.bytecode;
  16. import javassist.CtClass;
  17. import javassist.CtPrimitiveType;
  18. /**
  19. * A utility class for producing a bytecode sequence.
  20. *
  21. * <p>A <code>Bytecode</code> object is an unbounded array
  22. * containing bytecode. For example,
  23. *
  24. * <ul><pre>ConstPool cp = ...; // constant pool table
  25. * Bytecode b = new Bytecode(cp, 1, 0);
  26. * b.addIconst(3);
  27. * b.addReturn(CtClass.intType);
  28. * CodeAttribute ca = b.toCodeAttribute();</ul></pre>
  29. *
  30. * <p>This program produces a Code attribute including a bytecode
  31. * sequence:
  32. *
  33. * <ul><pre>iconst_3
  34. * ireturn</pre></ul>
  35. *
  36. * @see ConstPool
  37. * @see CodeAttribute
  38. */
  39. public class Bytecode implements Opcode {
  40. /**
  41. * Represents the <code>CtClass</code> file using the
  42. * constant pool table given to this <code>Bytecode</code> object.
  43. */
  44. public static final CtClass THIS = ConstPool.THIS;
  45. static final int bufsize = 64;
  46. ConstPool constPool;
  47. int maxStack, maxLocals;
  48. ExceptionTable tryblocks;
  49. Bytecode next;
  50. byte[] buffer;
  51. int num;
  52. private int stackDepth;
  53. /**
  54. * Constructs a <code>Bytecode</code> object with an empty bytecode
  55. * sequence.
  56. *
  57. * <p>The parameters <code>stacksize</code> and <code>localvars</code>
  58. * specify initial values
  59. * of <code>max_stack</code> and <code>max_locals</code>.
  60. * They can be changed later.
  61. *
  62. * @param cp constant pool table.
  63. * @param stacksize <code>max_stack</code>.
  64. * @param localvars <code>max_locals</code>.
  65. */
  66. public Bytecode(ConstPool cp, int stacksize, int localvars) {
  67. this();
  68. constPool = cp;
  69. maxStack = stacksize;
  70. maxLocals = localvars;
  71. tryblocks = new ExceptionTable(cp);
  72. stackDepth = 0;
  73. }
  74. /**
  75. * Constructs a <code>Bytecode</code> object with an empty bytecode
  76. * sequence. The initial values of <code>max_stack</code> and
  77. * <code>max_locals</code> are zero.
  78. *
  79. * @param cp constant pool table.
  80. * @see Bytecode#setMaxStack(int)
  81. * @see Bytecode#setMaxLocals(int)
  82. */
  83. public Bytecode(ConstPool cp) {
  84. this(cp, 0, 0);
  85. }
  86. /* used in add().
  87. */
  88. private Bytecode() {
  89. buffer = new byte[bufsize];
  90. num = 0;
  91. next = null;
  92. }
  93. /**
  94. * Gets a constant pool table.
  95. */
  96. public ConstPool getConstPool() { return constPool; }
  97. /**
  98. * Returns <code>exception_table</code>.
  99. */
  100. public ExceptionTable getExceptionTable() { return tryblocks; }
  101. /**
  102. * Converts to a <code>CodeAttribute</code>.
  103. */
  104. public CodeAttribute toCodeAttribute() {
  105. return new CodeAttribute(constPool, maxStack, maxLocals,
  106. get(), tryblocks);
  107. }
  108. /**
  109. * Returns the length of the bytecode sequence.
  110. */
  111. public int length() {
  112. int len = 0;
  113. Bytecode b = this;
  114. while (b != null) {
  115. len += b.num;
  116. b = b.next;
  117. }
  118. return len;
  119. }
  120. private void copy(byte[] dest, int index) {
  121. Bytecode b = this;
  122. while (b != null) {
  123. System.arraycopy(b.buffer, 0, dest, index, b.num);
  124. index += b.num;
  125. b = b.next;
  126. }
  127. }
  128. /**
  129. * Returns the produced bytecode sequence.
  130. */
  131. public byte[] get() {
  132. byte[] b = new byte[length()];
  133. copy(b, 0);
  134. return b;
  135. }
  136. /**
  137. * Gets <code>max_stack</code>.
  138. */
  139. public int getMaxStack() { return maxStack; }
  140. /**
  141. * Sets <code>max_stack</code>.
  142. *
  143. * <p>This value may be automatically updated when an instruction
  144. * is appended. A <code>Bytecode</code> object maintains the current
  145. * stack depth whenever an instruction is added
  146. * by <code>addOpcode()</code>. For example, if DUP is appended,
  147. * the current stack depth is increased by one. If the new stack
  148. * depth is more than <code>max_stack</code>, then it is assigned
  149. * to <code>max_stack</code>. However, if branch instructions are
  150. * appended, the current stack depth may not be correctly maintained.
  151. *
  152. * @see #addOpcode(int)
  153. */
  154. public void setMaxStack(int size) {
  155. maxStack = size;
  156. }
  157. /**
  158. * Gets <code>max_locals</code>.
  159. */
  160. public int getMaxLocals() { return maxLocals; }
  161. /**
  162. * Sets <code>max_locals</code>.
  163. */
  164. public void setMaxLocals(int size) {
  165. maxLocals = size;
  166. }
  167. /**
  168. * Sets <code>max_locals</code>.
  169. *
  170. * <p>This computes the number of local variables
  171. * used to pass method parameters and sets <code>max_locals</code>
  172. * to that number plus <code>locals</code>.
  173. *
  174. * @param isStatic true if <code>params</code> must be
  175. * interpreted as parameters to a static method.
  176. * @param params parameter types.
  177. * @param locals the number of local variables excluding
  178. * ones used to pass parameters.
  179. */
  180. public void setMaxLocals(boolean isStatic, CtClass[] params,
  181. int locals) {
  182. if (!isStatic)
  183. ++locals;
  184. if (params != null) {
  185. CtClass doubleType = CtClass.doubleType;
  186. CtClass longType = CtClass.longType;
  187. int n = params.length;
  188. for (int i = 0; i < n; ++i) {
  189. CtClass type = params[i];
  190. if (type == doubleType || type == longType)
  191. locals += 2;
  192. else
  193. ++locals;
  194. }
  195. }
  196. maxLocals = locals;
  197. }
  198. /**
  199. * Increments <code>max_locals</code>.
  200. */
  201. public void incMaxLocals(int diff) {
  202. maxLocals += diff;
  203. }
  204. /**
  205. * Adds a new entry of <code>exception_table</code>.
  206. */
  207. public void addExceptionHandler(int start, int end,
  208. int handler, CtClass type) {
  209. addExceptionHandler(start, end, handler,
  210. constPool.addClassInfo(type));
  211. }
  212. /**
  213. * Adds a new entry of <code>exception_table</code>.
  214. */
  215. public void addExceptionHandler(int start, int end,
  216. int handler, int type) {
  217. tryblocks.add(start, end, handler, type);
  218. }
  219. /**
  220. * Returns the length of bytecode sequence
  221. * that have been added so far.
  222. */
  223. public int currentPc() {
  224. int n = 0;
  225. Bytecode b = this;
  226. while (b != null) {
  227. n += b.num;
  228. b = b.next;
  229. }
  230. return n;
  231. }
  232. /**
  233. * Reads a signed 8bit value at the offset from the beginning of the
  234. * bytecode sequence.
  235. *
  236. * @throws ArrayIndexOutOfBoundsException if offset is invalid.
  237. */
  238. public int read(int offset) {
  239. if (offset < 0)
  240. return Opcode.NOP;
  241. else if (offset < num)
  242. return buffer[offset];
  243. else
  244. try {
  245. return next.read(offset - num);
  246. }
  247. catch (NullPointerException e) {
  248. throw new ArrayIndexOutOfBoundsException(offset);
  249. }
  250. }
  251. /**
  252. * Reads a signed 16bit value at the offset from the beginning of the
  253. * bytecode sequence.
  254. */
  255. public int read16bit(int offset) {
  256. int v1 = read(offset);
  257. int v2 = read(offset + 1);
  258. return (v1 << 8) + (v2 & 0xff);
  259. }
  260. /**
  261. * Writes an 8bit value at the offset from the beginning of the
  262. * bytecode sequence.
  263. *
  264. * @throws ArrayIndexOutOfBoundsException if offset is invalid.
  265. */
  266. public void write(int offset, int value) {
  267. if (offset < num)
  268. buffer[offset] = (byte)value;
  269. else
  270. try {
  271. next.write(offset - num, value);
  272. }
  273. catch (NullPointerException e) {
  274. throw new ArrayIndexOutOfBoundsException(offset);
  275. }
  276. }
  277. /**
  278. * Writes an 16bit value at the offset from the beginning of the
  279. * bytecode sequence.
  280. */
  281. public void write16bit(int offset, int value) {
  282. write(offset, value >>> 8);
  283. write(offset + 1, value);
  284. }
  285. /**
  286. * Appends an 8bit value to the end of the bytecode sequence.
  287. */
  288. public void add(int code) {
  289. if (num < bufsize)
  290. buffer[num++] = (byte)code;
  291. else {
  292. if (next == null)
  293. next = new Bytecode();
  294. next.add(code);
  295. }
  296. }
  297. /**
  298. * Appends an 8bit opcode to the end of the bytecode sequence.
  299. * The current stack depth is updated.
  300. * <code>max_stack</code> is updated if the current stack depth
  301. * is the deepest so far.
  302. *
  303. * <p>Note: some instructions such as INVOKEVIRTUAL does not
  304. * update the current stack depth since the increment depends
  305. * on the method signature.
  306. * <code>growStack()</code> must be explicitly called.
  307. */
  308. public void addOpcode(int code) {
  309. add(code);
  310. growStack(STACK_GROW[code]);
  311. }
  312. /**
  313. * Increases the current stack depth.
  314. * It also updates <code>max_stack</code> if the current stack depth
  315. * is the deepest so far.
  316. *
  317. * @param diff the number added to the current stack depth.
  318. */
  319. public void growStack(int diff) {
  320. setStackDepth(stackDepth + diff);
  321. }
  322. /**
  323. * Returns the current stack depth.
  324. */
  325. public int getStackDepth() { return stackDepth; }
  326. /**
  327. * Sets the current stack depth.
  328. * It also updates <code>max_stack</code> if the current stack depth
  329. * is the deepest so far.
  330. *
  331. * @param depth new value.
  332. */
  333. public void setStackDepth(int depth) {
  334. stackDepth = depth;
  335. if (stackDepth > maxStack)
  336. maxStack = stackDepth;
  337. }
  338. /**
  339. * Appends a 16bit value to the end of the bytecode sequence.
  340. * It never changes the current stack depth.
  341. */
  342. public void addIndex(int index) {
  343. add(index >> 8);
  344. add(index);
  345. }
  346. /**
  347. * Appends ALOAD or (WIDE) ALOAD_&lt;n&gt;
  348. *
  349. * @param n an index into the local variable array.
  350. */
  351. public void addAload(int n) {
  352. if (n < 4)
  353. addOpcode(42 + n); // aload_<n>
  354. else if (n < 0x100) {
  355. addOpcode(ALOAD); // aload
  356. add(n);
  357. }
  358. else {
  359. addOpcode(WIDE);
  360. addOpcode(ALOAD);
  361. addIndex(n);
  362. }
  363. }
  364. /**
  365. * Appends ASTORE or (WIDE) ASTORE_&lt;n&gt;
  366. *
  367. * @param n an index into the local variable array.
  368. */
  369. public void addAstore(int n) {
  370. if (n < 4)
  371. addOpcode(75 + n); // astore_<n>
  372. else if (n < 0x100) {
  373. addOpcode(ASTORE); // astore
  374. add(n);
  375. }
  376. else {
  377. addOpcode(WIDE);
  378. addOpcode(ASTORE);
  379. addIndex(n);
  380. }
  381. }
  382. /**
  383. * Appends ICONST or ICONST_&lt;n&gt;
  384. *
  385. * @param n the pushed integer constant.
  386. */
  387. public void addIconst(int n) {
  388. if (n < 6 && -2 < n)
  389. addOpcode(3 + n); // iconst_<i> -1..5
  390. else if (n <= 127 && -128 <= n) {
  391. addOpcode(16); // bipush
  392. add(n);
  393. }
  394. else if (n <= 32767 && -32768 <= n) {
  395. addOpcode(17); // sipush
  396. add(n >> 8);
  397. add(n);
  398. }
  399. else
  400. addLdc(constPool.addIntegerInfo(n));
  401. }
  402. /**
  403. * Appends ILOAD or (WIDE) ILOAD_&lt;n&gt;
  404. *
  405. * @param n an index into the local variable array.
  406. */
  407. public void addIload(int n) {
  408. if (n < 4)
  409. addOpcode(26 + n); // iload_<n>
  410. else if (n < 0x100) {
  411. addOpcode(ILOAD); // iload
  412. add(n);
  413. }
  414. else {
  415. addOpcode(WIDE);
  416. addOpcode(ILOAD);
  417. addIndex(n);
  418. }
  419. }
  420. /**
  421. * Appends ISTORE or (WIDE) ISTORE_&lt;n&gt;
  422. *
  423. * @param n an index into the local variable array.
  424. */
  425. public void addIstore(int n) {
  426. if (n < 4)
  427. addOpcode(59 + n); // istore_<n>
  428. else if (n < 0x100) {
  429. addOpcode(ISTORE); // istore
  430. add(n);
  431. }
  432. else {
  433. addOpcode(WIDE);
  434. addOpcode(ISTORE);
  435. addIndex(n);
  436. }
  437. }
  438. /**
  439. * Appends LCONST or LCONST_&lt;n&gt;
  440. *
  441. * @param n the pushed long integer constant.
  442. */
  443. public void addLconst(long n) {
  444. if (n == 0 || n == 1)
  445. addOpcode(9 + (int)n); // lconst_<n>
  446. else
  447. addLdc2w(n);
  448. }
  449. /**
  450. * Appends LLOAD or (WIDE) LLOAD_&lt;n&gt;
  451. *
  452. * @param n an index into the local variable array.
  453. */
  454. public void addLload(int n) {
  455. if (n < 4)
  456. addOpcode(30 + n); // lload_<n>
  457. else if (n < 0x100) {
  458. addOpcode(LLOAD); // lload
  459. add(n);
  460. }
  461. else {
  462. addOpcode(WIDE);
  463. addOpcode(LLOAD);
  464. addIndex(n);
  465. }
  466. }
  467. /**
  468. * Appends LSTORE or LSTORE_&lt;n&gt;
  469. *
  470. * @param n an index into the local variable array.
  471. */
  472. public void addLstore(int n) {
  473. if (n < 4)
  474. addOpcode(63 + n); // lstore_<n>
  475. else if (n < 0x100) {
  476. addOpcode(LSTORE); // lstore
  477. add(n);
  478. }
  479. else {
  480. addOpcode(WIDE);
  481. addOpcode(LSTORE);
  482. addIndex(n);
  483. }
  484. }
  485. /**
  486. * Appends DCONST or DCONST_&lt;n&gt;
  487. *
  488. * @param d the pushed double constant.
  489. */
  490. public void addDconst(double d) {
  491. if (d == 0.0 || d == 1.0)
  492. addOpcode(14 + (int)d); // dconst_<n>
  493. else
  494. addLdc2w(d);
  495. }
  496. /**
  497. * Appends DLOAD or (WIDE) DLOAD_&lt;n&gt;
  498. *
  499. * @param n an index into the local variable array.
  500. */
  501. public void addDload(int n) {
  502. if (n < 4)
  503. addOpcode(38 + n); // dload_<n>
  504. else if (n < 0x100) {
  505. addOpcode(DLOAD); // dload
  506. add(n);
  507. }
  508. else {
  509. addOpcode(WIDE);
  510. addOpcode(DLOAD);
  511. addIndex(n);
  512. }
  513. }
  514. /**
  515. * Appends DSTORE or (WIDE) DSTORE_&lt;n&gt;
  516. *
  517. * @param n an index into the local variable array.
  518. */
  519. public void addDstore(int n) {
  520. if (n < 4)
  521. addOpcode(71 + n); // dstore_<n>
  522. else if (n < 0x100) {
  523. addOpcode(DSTORE); // dstore
  524. add(n);
  525. }
  526. else {
  527. addOpcode(WIDE);
  528. addOpcode(DSTORE);
  529. addIndex(n);
  530. }
  531. }
  532. /**
  533. * Appends FCONST or FCONST_&lt;n&gt;
  534. *
  535. * @param f the pushed float constant.
  536. */
  537. public void addFconst(float f) {
  538. if (f == 0.0f || f == 1.0f || f == 2.0f)
  539. addOpcode(11 + (int)f); // fconst_<n>
  540. else
  541. addLdc(constPool.addFloatInfo(f));
  542. }
  543. /**
  544. * Appends FLOAD or (WIDE) FLOAD_&lt;n&gt;
  545. *
  546. * @param n an index into the local variable array.
  547. */
  548. public void addFload(int n) {
  549. if (n < 4)
  550. addOpcode(34 + n); // fload_<n>
  551. else if (n < 0x100) {
  552. addOpcode(FLOAD); // fload
  553. add(n);
  554. }
  555. else {
  556. addOpcode(WIDE);
  557. addOpcode(FLOAD);
  558. addIndex(n);
  559. }
  560. }
  561. /**
  562. * Appends FSTORE or FSTORE_&lt;n&gt;
  563. *
  564. * @param n an index into the local variable array.
  565. */
  566. public void addFstore(int n) {
  567. if (n < 4)
  568. addOpcode(67 + n); // fstore_<n>
  569. else if (n < 0x100) {
  570. addOpcode(FSTORE); // fstore
  571. add(n);
  572. }
  573. else {
  574. addOpcode(WIDE);
  575. addOpcode(FSTORE);
  576. addIndex(n);
  577. }
  578. }
  579. /**
  580. * Appends an instruction for loading a value from the
  581. * local variable at the index <code>n</code>.
  582. *
  583. * @param n the index.
  584. * @param type the type of the loaded value.
  585. * @return the size of the value (1 or 2 word).
  586. */
  587. public int addLoad(int n, CtClass type) {
  588. if (type.isPrimitive()) {
  589. if (type == CtClass.booleanType || type == CtClass.charType
  590. || type == CtClass.byteType || type == CtClass.shortType
  591. || type == CtClass.intType)
  592. addIload(n);
  593. else if (type == CtClass.longType) {
  594. addLload(n);
  595. return 2;
  596. }
  597. else if(type == CtClass.floatType)
  598. addFload(n);
  599. else if(type == CtClass.doubleType) {
  600. addDload(n);
  601. return 2;
  602. }
  603. else
  604. throw new RuntimeException("void type?");
  605. }
  606. else
  607. addAload(n);
  608. return 1;
  609. }
  610. /**
  611. * Appends an instruction for storing a value into the
  612. * local variable at the index <code>n</code>.
  613. *
  614. * @param n the index.
  615. * @param type the type of the stored value.
  616. * @return 2 if the type is long or double. Otherwise 1.
  617. */
  618. public int addStore(int n, CtClass type) {
  619. if (type.isPrimitive()) {
  620. if (type == CtClass.booleanType || type == CtClass.charType
  621. || type == CtClass.byteType || type == CtClass.shortType
  622. || type == CtClass.intType)
  623. addIstore(n);
  624. else if (type == CtClass.longType) {
  625. addLstore(n);
  626. return 2;
  627. }
  628. else if(type == CtClass.floatType)
  629. addFstore(n);
  630. else if(type == CtClass.doubleType) {
  631. addDstore(n);
  632. return 2;
  633. }
  634. else
  635. throw new RuntimeException("void type?");
  636. }
  637. else
  638. addAstore(n);
  639. return 1;
  640. }
  641. /**
  642. * Appends instructions for loading all the parameters onto the
  643. * operand stack.
  644. *
  645. * @param offset the index of the first parameter. It is 0
  646. * if the method is static. Otherwise, it is 1.
  647. */
  648. public int addLoadParameters(CtClass[] params, int offset) {
  649. int stacksize = 0;
  650. if (params != null) {
  651. int n = params.length;
  652. for (int i = 0; i < n; ++i)
  653. stacksize += addLoad(stacksize + offset, params[i]);
  654. }
  655. return stacksize;
  656. }
  657. /**
  658. * Appends CHECKCAST.
  659. *
  660. * @param c the type.
  661. */
  662. public void addCheckcast(CtClass c) {
  663. addOpcode(CHECKCAST);
  664. addIndex(constPool.addClassInfo(c));
  665. }
  666. /**
  667. * Appends CHECKCAST.
  668. *
  669. * @param classname a fully-qualified class name.
  670. */
  671. public void addCheckcast(String classname) {
  672. addOpcode(CHECKCAST);
  673. addIndex(constPool.addClassInfo(classname));
  674. }
  675. /**
  676. * Appends INSTANCEOF.
  677. *
  678. * @param classname the class name.
  679. */
  680. public void addInstanceof(String classname) {
  681. addOpcode(INSTANCEOF);
  682. addIndex(constPool.addClassInfo(classname));
  683. }
  684. /**
  685. * Appends GETFIELD.
  686. *
  687. * @param c the class
  688. * @param name the field name
  689. * @param type the descriptor of the field type.
  690. *
  691. * @see Descriptor#of(CtClass)
  692. */
  693. public void addGetfield(CtClass c, String name, String type) {
  694. add(GETFIELD);
  695. int ci = constPool.addClassInfo(c);
  696. addIndex(constPool.addFieldrefInfo(ci, name, type));
  697. growStack(Descriptor.dataSize(type) - 1);
  698. }
  699. /**
  700. * Appends GETSTATIC.
  701. *
  702. * @param c the class
  703. * @param name the field name
  704. * @param type the descriptor of the field type.
  705. *
  706. * @see Descriptor#of(CtClass)
  707. */
  708. public void addGetstatic(CtClass c, String name, String type) {
  709. add(GETSTATIC);
  710. int ci = constPool.addClassInfo(c);
  711. addIndex(constPool.addFieldrefInfo(ci, name, type));
  712. growStack(Descriptor.dataSize(type));
  713. }
  714. /**
  715. * Appends GETSTATIC.
  716. *
  717. * @param c the fully-qualified class name
  718. * @param name the field name
  719. * @param type the descriptor of the field type.
  720. *
  721. * @see Descriptor#of(CtClass)
  722. */
  723. public void addGetstatic(String c, String name, String type) {
  724. add(GETSTATIC);
  725. int ci = constPool.addClassInfo(c);
  726. addIndex(constPool.addFieldrefInfo(ci, name, type));
  727. growStack(Descriptor.dataSize(type));
  728. }
  729. /**
  730. * Appends INVOKESPECIAL.
  731. *
  732. * @param clazz the target class.
  733. * @param name the method name.
  734. * @param returnType the return type.
  735. * @param paramTypes the parameter types.
  736. */
  737. public void addInvokespecial(CtClass clazz, String name,
  738. CtClass returnType, CtClass[] paramTypes) {
  739. String desc = Descriptor.ofMethod(returnType, paramTypes);
  740. addInvokespecial(clazz, name, desc);
  741. }
  742. /**
  743. * Appends INVOKESPECIAL.
  744. *
  745. * @param clazz the target class.
  746. * @param name the method name
  747. * @param desc the descriptor of the method signature.
  748. *
  749. * @see Descriptor#ofMethod(CtClass,CtClass[])
  750. * @see Descriptor#ofConstructor(CtClass[])
  751. */
  752. public void addInvokespecial(CtClass clazz, String name, String desc) {
  753. addInvokespecial(constPool.addClassInfo(clazz), name, desc);
  754. }
  755. /**
  756. * Appends INVOKESPECIAL.
  757. *
  758. * @param clazz the fully-qualified class name.
  759. * @param name the method name
  760. * @param desc the descriptor of the method signature.
  761. *
  762. * @see Descriptor#ofMethod(CtClass,CtClass[])
  763. * @see Descriptor#ofConstructor(CtClass[])
  764. */
  765. public void addInvokespecial(String clazz, String name, String desc) {
  766. addInvokespecial(constPool.addClassInfo(clazz), name, desc);
  767. }
  768. /**
  769. * Appends INVOKESPECIAL.
  770. *
  771. * @param clazz the index of <code>CONSTANT_Class_info</code>
  772. * structure.
  773. * @param name the method name
  774. * @param desc the descriptor of the method signature.
  775. *
  776. * @see Descriptor#ofMethod(CtClass,CtClass[])
  777. * @see Descriptor#ofConstructor(CtClass[])
  778. */
  779. public void addInvokespecial(int clazz, String name, String desc) {
  780. add(INVOKESPECIAL);
  781. addIndex(constPool.addMethodrefInfo(clazz, name, desc));
  782. growStack(Descriptor.dataSize(desc) - 1);
  783. }
  784. /**
  785. * Appends INVOKESTATIC.
  786. *
  787. * @param clazz the target class.
  788. * @param name the method name
  789. * @param returnType the return type.
  790. * @param paramTypes the parameter types.
  791. */
  792. public void addInvokestatic(CtClass clazz, String name,
  793. CtClass returnType, CtClass[] paramTypes) {
  794. String desc = Descriptor.ofMethod(returnType, paramTypes);
  795. addInvokestatic(clazz, name, desc);
  796. }
  797. /**
  798. * Appends INVOKESTATIC.
  799. *
  800. * @param clazz the target class.
  801. * @param name the method name
  802. * @param desc the descriptor of the method signature.
  803. *
  804. * @see Descriptor#ofMethod(CtClass,CtClass[])
  805. */
  806. public void addInvokestatic(CtClass clazz, String name, String desc) {
  807. addInvokestatic(constPool.addClassInfo(clazz), name, desc);
  808. }
  809. /**
  810. * Appends INVOKESTATIC.
  811. *
  812. * @param classname the fully-qualified class name.
  813. * @param name the method name
  814. * @param desc the descriptor of the method signature.
  815. *
  816. * @see Descriptor#ofMethod(CtClass,CtClass[])
  817. */
  818. public void addInvokestatic(String classname, String name, String desc) {
  819. addInvokestatic(constPool.addClassInfo(classname), name, desc);
  820. }
  821. /**
  822. * Appends INVOKESTATIC.
  823. *
  824. * @param clazz the index of <code>CONSTANT_Class_info</code>
  825. * structure.
  826. * @param name the method name
  827. * @param desc the descriptor of the method signature.
  828. *
  829. * @see Descriptor#ofMethod(CtClass,CtClass[])
  830. */
  831. public void addInvokestatic(int clazz, String name, String desc) {
  832. add(INVOKESTATIC);
  833. addIndex(constPool.addMethodrefInfo(clazz, name, desc));
  834. growStack(Descriptor.dataSize(desc));
  835. }
  836. /**
  837. * Appends INVOKEVIRTUAL.
  838. *
  839. * <p>The specified method must not be an inherited method.
  840. * It must be directly declared in the class specified
  841. * in <code>clazz</code>.
  842. *
  843. * @param clazz the target class.
  844. * @param name the method name
  845. * @param returnType the return type.
  846. * @param paramTypes the parameter types.
  847. */
  848. public void addInvokevirtual(CtClass clazz, String name,
  849. CtClass returnType, CtClass[] paramTypes) {
  850. String desc = Descriptor.ofMethod(returnType, paramTypes);
  851. addInvokevirtual(clazz, name, desc);
  852. }
  853. /**
  854. * Appends INVOKEVIRTUAL.
  855. *
  856. * <p>The specified method must not be an inherited method.
  857. * It must be directly declared in the class specified
  858. * in <code>clazz</code>.
  859. *
  860. * @param clazz the target class.
  861. * @param name the method name
  862. * @param desc the descriptor of the method signature.
  863. *
  864. * @see Descriptor#ofMethod(CtClass,CtClass[])
  865. */
  866. public void addInvokevirtual(CtClass clazz, String name, String desc) {
  867. addInvokevirtual(constPool.addClassInfo(clazz), name, desc);
  868. }
  869. /**
  870. * Appends INVOKEVIRTUAL.
  871. *
  872. * <p>The specified method must not be an inherited method.
  873. * It must be directly declared in the class specified
  874. * in <code>classname</code>.
  875. *
  876. * @param classname the fully-qualified class name.
  877. * @param name the method name
  878. * @param desc the descriptor of the method signature.
  879. *
  880. * @see Descriptor#ofMethod(CtClass,CtClass[])
  881. */
  882. public void addInvokevirtual(String classname, String name, String desc) {
  883. addInvokevirtual(constPool.addClassInfo(classname), name, desc);
  884. }
  885. /**
  886. * Appends INVOKEVIRTUAL.
  887. *
  888. * <p>The specified method must not be an inherited method.
  889. * It must be directly declared in the class specified
  890. * by <code>clazz</code>.
  891. *
  892. * @param clazz the index of <code>CONSTANT_Class_info</code>
  893. * structure.
  894. * @param name the method name
  895. * @param desc the descriptor of the method signature.
  896. *
  897. * @see Descriptor#ofMethod(CtClass,CtClass[])
  898. */
  899. public void addInvokevirtual(int clazz, String name, String desc) {
  900. add(INVOKEVIRTUAL);
  901. addIndex(constPool.addMethodrefInfo(clazz, name, desc));
  902. growStack(Descriptor.dataSize(desc) - 1);
  903. }
  904. /**
  905. * Appends INVOKEINTERFACE.
  906. *
  907. * @param clazz the target class.
  908. * @param name the method name
  909. * @param returnType the return type.
  910. * @param paramTypes the parameter types.
  911. * @param count the count operand of the instruction.
  912. */
  913. public void addInvokeinterface(CtClass clazz, String name,
  914. CtClass returnType, CtClass[] paramTypes,
  915. int count) {
  916. String desc = Descriptor.ofMethod(returnType, paramTypes);
  917. addInvokeinterface(clazz, name, desc, count);
  918. }
  919. /**
  920. * Appends INVOKEINTERFACE.
  921. *
  922. * @param clazz the target class.
  923. * @param name the method name
  924. * @param desc the descriptor of the method signature.
  925. * @param count the count operand of the instruction.
  926. *
  927. * @see Descriptor#ofMethod(CtClass,CtClass[])
  928. */
  929. public void addInvokeinterface(CtClass clazz, String name,
  930. String desc, int count) {
  931. addInvokeinterface(constPool.addClassInfo(clazz), name, desc,
  932. count);
  933. }
  934. /**
  935. * Appends INVOKEINTERFACE.
  936. *
  937. * @param classname the fully-qualified class name.
  938. * @param name the method name
  939. * @param desc the descriptor of the method signature.
  940. * @param count the count operand of the instruction.
  941. *
  942. * @see Descriptor#ofMethod(CtClass,CtClass[])
  943. */
  944. public void addInvokeinterface(String classname, String name,
  945. String desc, int count) {
  946. addInvokeinterface(constPool.addClassInfo(classname), name, desc,
  947. count);
  948. }
  949. /**
  950. * Appends INVOKEINTERFACE.
  951. *
  952. * @param clazz the index of <code>CONSTANT_Class_info</code>
  953. * structure.
  954. * @param name the method name
  955. * @param desc the descriptor of the method signature.
  956. * @param count the count operand of the instruction.
  957. *
  958. * @see Descriptor#ofMethod(CtClass,CtClass[])
  959. */
  960. public void addInvokeinterface(int clazz, String name,
  961. String desc, int count) {
  962. add(INVOKEINTERFACE);
  963. addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
  964. add(count);
  965. add(0);
  966. growStack(Descriptor.dataSize(desc) - 1);
  967. }
  968. /**
  969. * Appends LDC or LDC_W. The pushed item is a <code>String</code>
  970. * object.
  971. *
  972. * @param s the character string pushed by LDC or LDC_W.
  973. */
  974. public void addLdc(String s) {
  975. addLdc(constPool.addStringInfo(s));
  976. }
  977. /**
  978. * Appends LDC or LDC_W.
  979. *
  980. * @param i index into the constant pool.
  981. */
  982. public void addLdc(int i) {
  983. if (i > 0xFF) {
  984. addOpcode(LDC_W);
  985. addIndex(i);
  986. }
  987. else {
  988. addOpcode(LDC);
  989. add(i);
  990. }
  991. }
  992. /**
  993. * Appends LDC2_W. The pushed item is a long value.
  994. */
  995. public void addLdc2w(long l) {
  996. addOpcode(LDC2_W);
  997. addIndex(constPool.addLongInfo(l));
  998. }
  999. /**
  1000. * Appends LDC2_W. The pushed item is a double value.
  1001. */
  1002. public void addLdc2w(double d) {
  1003. addOpcode(LDC2_W);
  1004. addIndex(constPool.addDoubleInfo(d));
  1005. }
  1006. /**
  1007. * Appends NEW.
  1008. *
  1009. * @param clazz the class of the created instance.
  1010. */
  1011. public void addNew(CtClass clazz) {
  1012. addOpcode(NEW);
  1013. addIndex(constPool.addClassInfo(clazz));
  1014. }
  1015. /**
  1016. * Appends NEW.
  1017. *
  1018. * @param classname the fully-qualified class name.
  1019. */
  1020. public void addNew(String classname) {
  1021. addOpcode(NEW);
  1022. addIndex(constPool.addClassInfo(classname));
  1023. }
  1024. /**
  1025. * Appends ANEWARRAY.
  1026. *
  1027. * @param classname the qualified class name of the element type.
  1028. */
  1029. public void addAnewarray(String classname) {
  1030. addOpcode(ANEWARRAY);
  1031. addIndex(constPool.addClassInfo(classname));
  1032. }
  1033. /**
  1034. * Appends ICONST and ANEWARRAY.
  1035. *
  1036. * @param clazz the elememnt type.
  1037. * @param length the array length.
  1038. */
  1039. public void addAnewarray(CtClass clazz, int length) {
  1040. addIconst(length);
  1041. addOpcode(ANEWARRAY);
  1042. addIndex(constPool.addClassInfo(clazz));
  1043. }
  1044. /**
  1045. * Appends NEWARRAY for primitive types.
  1046. *
  1047. * @param atype <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
  1048. * @see Opcode
  1049. */
  1050. public void addNewarray(int atype, int length) {
  1051. addIconst(length);
  1052. addOpcode(NEWARRAY);
  1053. add(atype);
  1054. }
  1055. /**
  1056. * Appends MULTINEWARRAY.
  1057. *
  1058. * @param clazz the array type.
  1059. * @param dimensions the sizes of all dimensions.
  1060. * @return the length of <code>dimensions</code>.
  1061. */
  1062. public int addMultiNewarray(CtClass clazz, int[] dimensions) {
  1063. int len = dimensions.length;
  1064. for (int i = 0; i < len; ++i)
  1065. addIconst(dimensions[i]);
  1066. growStack(len);
  1067. return addMultiNewarray(clazz, len);
  1068. }
  1069. /**
  1070. * Appends MULTINEWARRAY. The size of every dimension must have been
  1071. * already pushed on the stack.
  1072. *
  1073. * @param clazz the array type.
  1074. * @param dim the number of the dimensions.
  1075. * @return the value of <code>dim</code>.
  1076. */
  1077. public int addMultiNewarray(CtClass clazz, int dim) {
  1078. add(MULTIANEWARRAY);
  1079. addIndex(constPool.addClassInfo(clazz));
  1080. add(dim);
  1081. growStack(1 - dim);
  1082. return dim;
  1083. }
  1084. /**
  1085. * Appends MULTINEWARRAY.
  1086. *
  1087. * @param desc the type descriptor of the created array.
  1088. * @param dim dimensions.
  1089. * @return the value of <code>dim</code>.
  1090. */
  1091. public int addMultiNewarray(String desc, int dim) {
  1092. add(MULTIANEWARRAY);
  1093. addIndex(constPool.addClassInfo(desc));
  1094. add(dim);
  1095. growStack(1 - dim);
  1096. return dim;
  1097. }
  1098. /**
  1099. * Appends PUTFIELD.
  1100. *
  1101. * @param c the target class.
  1102. * @param name the field name.
  1103. * @param desc the descriptor of the field type.
  1104. */
  1105. public void addPutfield(CtClass c, String name, String desc) {
  1106. add(PUTFIELD);
  1107. int ci = constPool.addClassInfo(c);
  1108. addIndex(constPool.addFieldrefInfo(ci, name, desc));
  1109. growStack(-1 - Descriptor.dataSize(desc));
  1110. }
  1111. /**
  1112. * Appends PUTSTATIC.
  1113. *
  1114. * @param c the target class.
  1115. * @param name the field name.
  1116. * @param desc the descriptor of the field type.
  1117. */
  1118. public void addPutstatic(CtClass c, String name, String desc) {
  1119. add(PUTSTATIC);
  1120. int ci = constPool.addClassInfo(c);
  1121. addIndex(constPool.addFieldrefInfo(ci, name, desc));
  1122. growStack(-Descriptor.dataSize(desc));
  1123. }
  1124. /**
  1125. * Appends ARETURN, IRETURN, .., or RETURN.
  1126. *
  1127. * @param type the return type.
  1128. */
  1129. public void addReturn(CtClass type) {
  1130. if (type == null)
  1131. addOpcode(RETURN);
  1132. else if (type.isPrimitive()) {
  1133. CtPrimitiveType ptype = (CtPrimitiveType)type;
  1134. addOpcode(ptype.getReturnOp());
  1135. }
  1136. else
  1137. addOpcode(ARETURN);
  1138. }
  1139. /**
  1140. * Appends RET.
  1141. *
  1142. * @param var local variable
  1143. */
  1144. public void addRet(int var) {
  1145. if (var < 0x100) {
  1146. addOpcode(RET);
  1147. add(var);
  1148. }
  1149. else {
  1150. addOpcode(WIDE);
  1151. addOpcode(RET);
  1152. addIndex(var);
  1153. }
  1154. }
  1155. /**
  1156. * Appends instructions for executing
  1157. * <code>java.lang.System.println(<i>message</i>)</code>.
  1158. *
  1159. * @param message printed message.
  1160. */
  1161. public void addPrintln(String message) {
  1162. addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
  1163. addLdc(message);
  1164. addInvokevirtual("java.io.PrintStream",
  1165. "println", "(Ljava/lang/String;)V");
  1166. }
  1167. }