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 41KB

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