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.

CodeIterator.java 55KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647
  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 java.util.ArrayList;
  18. import java.util.List;
  19. /**
  20. * An iterator for editing a code attribute.
  21. *
  22. * <p>To directly read or edit a bytecode sequence, call {@link #byteAt(int)}, {@link #s16bitAt(int)},
  23. * {@link #writeByte(int, int)}, {@link #write16bit(int, int)}, and other methods.
  24. * For example, if <code>method</code> refers to a <code>CtMethod</code> object,
  25. * the following code substitutes the <code>NOP</code> instruction for the first
  26. * instruction of the method:
  27. *
  28. * <pre>
  29. * CodeAttribute ca = method.getMethodInfo().getCodeAttribute();
  30. * CodeIterator ci = ca.iterator();
  31. * ci.writeByte(Opcode.NOP, 0);</pre>
  32. *
  33. * <p>To visit every instruction, call {@link #next()} on a <code>CodeIterator</code>.
  34. * It returns the index of the first byte of the next instruction.
  35. *
  36. * <p>If there are multiple <code>CodeIterator</code>s referring to the
  37. * same <code>Code_attribute</code>, then inserting a gap by one
  38. * <code>CodeIterator</code> will break the other
  39. * <code>CodeIterator</code>.
  40. *
  41. * <p>This iterator does not provide <code>remove()</code>.
  42. * If a piece of code in a <code>Code_attribute</code> is unnecessary,
  43. * it should be overwritten with <code>NOP</code>.
  44. *
  45. * @see CodeAttribute#iterator()
  46. */
  47. public class CodeIterator implements Opcode {
  48. protected CodeAttribute codeAttr;
  49. protected byte[] bytecode;
  50. protected int endPos;
  51. protected int currentPos;
  52. protected int mark, mark2;
  53. protected CodeIterator(CodeAttribute ca) {
  54. codeAttr = ca;
  55. bytecode = ca.getCode();
  56. begin();
  57. }
  58. /**
  59. * Moves to the first instruction.
  60. */
  61. public void begin() {
  62. currentPos = mark = mark2 = 0;
  63. endPos = getCodeLength();
  64. }
  65. /**
  66. * Moves to the given index.
  67. *
  68. * <p>The index of the next instruction is set to the given index.
  69. * The successive call to <code>next()</code>
  70. * returns the index that has been given to <code>move()</code>.
  71. *
  72. * <p>Note that the index is into the byte array returned by
  73. * <code>get().getCode()</code>.
  74. *
  75. * @see CodeAttribute#getCode()
  76. */
  77. public void move(int index) {
  78. currentPos = index;
  79. }
  80. /**
  81. * Sets a mark to the bytecode at the given index.
  82. * The mark can be used to track the position of that bytecode
  83. * when code blocks are inserted.
  84. * If a code block is inclusively inserted at the position of the
  85. * bytecode, the mark is set to the inserted code block.
  86. *
  87. * @see #getMark()
  88. * @since 3.11
  89. */
  90. public void setMark(int index) {
  91. mark = index;
  92. }
  93. /**
  94. * Sets a mark to the bytecode at the given index.
  95. * The mark can be used to track the position of that bytecode
  96. * when code blocks are inserted.
  97. * If a code block is inclusively inserted at the position of the
  98. * bytecode, the mark is set to the inserted code block.
  99. *
  100. * @see #getMark2()
  101. * @since 3.26
  102. */
  103. public void setMark2(int index) {
  104. mark2 = index;
  105. }
  106. /**
  107. * Gets the index of the position of the mark set by
  108. * <code>setMark</code>.
  109. *
  110. * @return the index of the position.
  111. * @see #setMark(int)
  112. * @since 3.11
  113. */
  114. public int getMark() { return mark; }
  115. /**
  116. * Gets the index of the position of the mark set by
  117. * <code>setMark2</code>.
  118. *
  119. * @return the index of the position.
  120. * @see #setMark2(int)
  121. * @since 3.26
  122. */
  123. public int getMark2() { return mark2; }
  124. /**
  125. * Returns a Code attribute read with this iterator.
  126. */
  127. public CodeAttribute get() {
  128. return codeAttr;
  129. }
  130. /**
  131. * Returns <code>code_length</code> of <code>Code_attribute</code>.
  132. */
  133. public int getCodeLength() {
  134. return bytecode.length;
  135. }
  136. /**
  137. * Returns the unsigned 8bit value at the given index.
  138. */
  139. public int byteAt(int index) { return bytecode[index] & 0xff; }
  140. /**
  141. * Returns the signed 8bit value at the given index.
  142. */
  143. public int signedByteAt(int index) { return bytecode[index]; }
  144. /**
  145. * Writes an 8bit value at the given index.
  146. */
  147. public void writeByte(int value, int index) {
  148. bytecode[index] = (byte)value;
  149. }
  150. /**
  151. * Returns the unsigned 16bit value at the given index.
  152. */
  153. public int u16bitAt(int index) {
  154. return ByteArray.readU16bit(bytecode, index);
  155. }
  156. /**
  157. * Returns the signed 16bit value at the given index.
  158. */
  159. public int s16bitAt(int index) {
  160. return ByteArray.readS16bit(bytecode, index);
  161. }
  162. /**
  163. * Writes a 16 bit integer at the index.
  164. */
  165. public void write16bit(int value, int index) {
  166. ByteArray.write16bit(value, bytecode, index);
  167. }
  168. /**
  169. * Returns the signed 32bit value at the given index.
  170. */
  171. public int s32bitAt(int index) {
  172. return ByteArray.read32bit(bytecode, index);
  173. }
  174. /**
  175. * Writes a 32bit integer at the index.
  176. */
  177. public void write32bit(int value, int index) {
  178. ByteArray.write32bit(value, bytecode, index);
  179. }
  180. /**
  181. * Writes a byte array at the index.
  182. *
  183. * @param code may be a zero-length array.
  184. */
  185. public void write(byte[] code, int index) {
  186. int len = code.length;
  187. for (int j = 0; j < len; ++j)
  188. bytecode[index++] = code[j];
  189. }
  190. /**
  191. * Returns true if there is more instructions.
  192. */
  193. public boolean hasNext() { return currentPos < endPos; }
  194. /**
  195. * Returns the index of the next instruction
  196. * (not the operand following the current opcode).
  197. *
  198. * <p>Note that the index is into the byte array returned by
  199. * <code>get().getCode()</code>.
  200. *
  201. * @see CodeAttribute#getCode()
  202. * @see CodeIterator#byteAt(int)
  203. */
  204. public int next() throws BadBytecode {
  205. int pos = currentPos;
  206. currentPos = nextOpcode(bytecode, pos);
  207. return pos;
  208. }
  209. /**
  210. * Obtains the value that the next call
  211. * to <code>next()</code> will return.
  212. *
  213. * <p>This method is side-effects free.
  214. * Successive calls to <code>lookAhead()</code> return the
  215. * same value until <code>next()</code> is called.
  216. */
  217. public int lookAhead() {
  218. return currentPos;
  219. }
  220. /**
  221. * Moves to the instruction for
  222. * either <code>super()</code> or <code>this()</code>.
  223. *
  224. * <p>This method skips all the instructions for computing arguments
  225. * to <code>super()</code> or <code>this()</code>, which should be
  226. * placed at the beginning of a constructor body.
  227. *
  228. * <p>This method returns the index of INVOKESPECIAL instruction
  229. * executing <code>super()</code> or <code>this()</code>.
  230. * A successive call to <code>next()</code> returns the
  231. * index of the next instruction following that INVOKESPECIAL.
  232. *
  233. * <p>This method works only for a constructor.
  234. *
  235. * @return the index of the INVOKESPECIAL instruction, or -1
  236. * if a constructor invocation is not found.
  237. */
  238. public int skipConstructor() throws BadBytecode {
  239. return skipSuperConstructor0(-1);
  240. }
  241. /**
  242. * Moves to the instruction for <code>super()</code>.
  243. *
  244. * <p>This method skips all the instructions for computing arguments to
  245. * <code>super()</code>, which should be
  246. * placed at the beginning of a constructor body.
  247. *
  248. * <p>This method returns the index of INVOKESPECIAL instruction
  249. * executing <code>super()</code>.
  250. * A successive call to <code>next()</code> returns the
  251. * index of the next instruction following that INVOKESPECIAL.
  252. *
  253. * <p>This method works only for a constructor.
  254. *
  255. * @return the index of the INVOKESPECIAL instruction, or -1
  256. * if a super constructor invocation is not found
  257. * but <code>this()</code> is found.
  258. */
  259. public int skipSuperConstructor() throws BadBytecode {
  260. return skipSuperConstructor0(0);
  261. }
  262. /**
  263. * Moves to the instruction for <code>this()</code>.
  264. *
  265. * <p>This method skips all the instructions for computing arguments to
  266. * <code>this()</code>, which should be
  267. * placed at the beginning of a constructor body.
  268. *
  269. * <p>This method returns the index of INVOKESPECIAL instruction
  270. * executing <code>this()</code>.
  271. * A successive call to <code>next()</code> returns the
  272. * index of the next instruction following that INVOKESPECIAL.
  273. *
  274. * <p>This method works only for a constructor.
  275. *
  276. * @return the index of the INVOKESPECIAL instruction, or -1
  277. * if a explicit constructor invocation is not found
  278. * but <code>super()</code> is found.
  279. */
  280. public int skipThisConstructor() throws BadBytecode {
  281. return skipSuperConstructor0(1);
  282. }
  283. /* skipSuper 1: this(), 0: super(), -1: both.
  284. */
  285. private int skipSuperConstructor0(int skipThis) throws BadBytecode {
  286. begin();
  287. ConstPool cp = codeAttr.getConstPool();
  288. String thisClassName = codeAttr.getDeclaringClass();
  289. int nested = 0;
  290. while (hasNext()) {
  291. int index = next();
  292. int c = byteAt(index);
  293. if (c == NEW)
  294. ++nested;
  295. else if (c == INVOKESPECIAL) {
  296. int mref = ByteArray.readU16bit(bytecode, index + 1);
  297. if (cp.getMethodrefName(mref).equals(MethodInfo.nameInit))
  298. if (--nested < 0) {
  299. if (skipThis < 0)
  300. return index;
  301. String cname = cp.getMethodrefClassName(mref);
  302. if (cname.equals(thisClassName) == (skipThis > 0))
  303. return index;
  304. break;
  305. }
  306. }
  307. }
  308. begin();
  309. return -1;
  310. }
  311. /**
  312. * Inserts the given bytecode sequence
  313. * before the next instruction that would be returned by
  314. * <code>next()</code> (not before the instruction returned
  315. * by the last call to <code>next()</code>).
  316. * Branch offsets and the exception table are also updated.
  317. *
  318. * <p>If the next instruction is at the beginning of a block statement,
  319. * then the bytecode is inserted within that block.
  320. *
  321. * <p>An extra gap may be inserted at the end of the inserted
  322. * bytecode sequence for adjusting alignment if the code attribute
  323. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  324. *
  325. * @param code inserted bytecode sequence.
  326. * @return the index indicating the first byte of the
  327. * inserted byte sequence.
  328. */
  329. public int insert(byte[] code)
  330. throws BadBytecode
  331. {
  332. return insert0(currentPos, code, false);
  333. }
  334. /**
  335. * Inserts the given bytecode sequence
  336. * before the instruction at the given index <code>pos</code>.
  337. * Branch offsets and the exception table are also updated.
  338. *
  339. * <p>If the instruction at the given index is at the beginning
  340. * of a block statement,
  341. * then the bytecode is inserted within that block.
  342. *
  343. * <p>An extra gap may be inserted at the end of the inserted
  344. * bytecode sequence for adjusting alignment if the code attribute
  345. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  346. *
  347. * <p>The index at which the byte sequence is actually inserted
  348. * might be different from pos since some other bytes might be
  349. * inserted at other positions (e.g. to change <code>GOTO</code>
  350. * to <code>GOTO_W</code>).
  351. *
  352. * @param pos the index at which a byte sequence is inserted.
  353. * @param code inserted bytecode sequence.
  354. */
  355. public void insert(int pos, byte[] code) throws BadBytecode {
  356. insert0(pos, code, false);
  357. }
  358. /**
  359. * Inserts the given bytecode sequence
  360. * before the instruction at the given index <code>pos</code>.
  361. * Branch offsets and the exception table are also updated.
  362. *
  363. * <p>If the instruction at the given index is at the beginning
  364. * of a block statement,
  365. * then the bytecode is inserted within that block.
  366. *
  367. * <p>An extra gap may be inserted at the end of the inserted
  368. * bytecode sequence for adjusting alignment if the code attribute
  369. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  370. *
  371. * @param pos the index at which a byte sequence is inserted.
  372. * @param code inserted bytecode sequence.
  373. * @return the index indicating the first byte of the
  374. * inserted byte sequence, which might be
  375. * different from pos.
  376. * @since 3.11
  377. */
  378. public int insertAt(int pos, byte[] code) throws BadBytecode {
  379. return insert0(pos, code, false);
  380. }
  381. /**
  382. * Inserts the given bytecode sequence exclusively
  383. * before the next instruction that would be returned by
  384. * <code>next()</code> (not before the instruction returned
  385. * by tha last call to <code>next()</code>).
  386. * Branch offsets and the exception table are also updated.
  387. *
  388. * <p>If the next instruction is at the beginning of a block statement,
  389. * then the bytecode is excluded from that block.
  390. *
  391. * <p>An extra gap may be inserted at the end of the inserted
  392. * bytecode sequence for adjusting alignment if the code attribute
  393. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  394. *
  395. * @param code inserted bytecode sequence.
  396. * @return the index indicating the first byte of the
  397. * inserted byte sequence.
  398. */
  399. public int insertEx(byte[] code)
  400. throws BadBytecode
  401. {
  402. return insert0(currentPos, code, true);
  403. }
  404. /**
  405. * Inserts the given bytecode sequence exclusively
  406. * before the instruction at the given index <code>pos</code>.
  407. * Branch offsets and the exception table are also updated.
  408. *
  409. * <p>If the instruction at the given index is at the beginning
  410. * of a block statement,
  411. * then the bytecode is excluded from that block.
  412. *
  413. * <p>An extra gap may be inserted at the end of the inserted
  414. * bytecode sequence for adjusting alignment if the code attribute
  415. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  416. *
  417. * <p>The index at which the byte sequence is actually inserted
  418. * might be different from pos since some other bytes might be
  419. * inserted at other positions (e.g. to change <code>GOTO</code>
  420. * to <code>GOTO_W</code>).
  421. *
  422. * @param pos the index at which a byte sequence is inserted.
  423. * @param code inserted bytecode sequence.
  424. */
  425. public void insertEx(int pos, byte[] code) throws BadBytecode {
  426. insert0(pos, code, true);
  427. }
  428. /**
  429. * Inserts the given bytecode sequence exclusively
  430. * before the instruction at the given index <code>pos</code>.
  431. * Branch offsets and the exception table are also updated.
  432. *
  433. * <p>If the instruction at the given index is at the beginning
  434. * of a block statement,
  435. * then the bytecode is excluded from that block.
  436. *
  437. * <p>An extra gap may be inserted at the end of the inserted
  438. * bytecode sequence for adjusting alignment if the code attribute
  439. * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
  440. *
  441. * @param pos the index at which a byte sequence is inserted.
  442. * @param code inserted bytecode sequence.
  443. * @return the index indicating the first byte of the
  444. * inserted byte sequence, which might be
  445. * different from pos.
  446. * @since 3.11
  447. */
  448. public int insertExAt(int pos, byte[] code) throws BadBytecode {
  449. return insert0(pos, code, true);
  450. }
  451. /**
  452. * @return the index indicating the first byte of the
  453. * inserted byte sequence.
  454. */
  455. private int insert0(int pos, byte[] code, boolean exclusive)
  456. throws BadBytecode
  457. {
  458. int len = code.length;
  459. if (len <= 0)
  460. return pos;
  461. // currentPos will change.
  462. pos = insertGapAt(pos, len, exclusive).position;
  463. int p = pos;
  464. for (int j = 0; j < len; ++j)
  465. bytecode[p++] = code[j];
  466. return pos;
  467. }
  468. /**
  469. * Inserts a gap
  470. * before the next instruction that would be returned by
  471. * <code>next()</code> (not before the instruction returned
  472. * by the last call to <code>next()</code>).
  473. * Branch offsets and the exception table are also updated.
  474. * The inserted gap is filled with NOP. The gap length may be
  475. * extended to a multiple of 4.
  476. *
  477. * <p>If the next instruction is at the beginning of a block statement,
  478. * then the gap is inserted within that block.
  479. *
  480. * @param length gap length
  481. * @return the index indicating the first byte of the inserted gap.
  482. */
  483. public int insertGap(int length) throws BadBytecode {
  484. return insertGapAt(currentPos, length, false).position;
  485. }
  486. /**
  487. * Inserts a gap in front of the instruction at the given
  488. * index <code>pos</code>.
  489. * Branch offsets and the exception table are also updated.
  490. * The inserted gap is filled with NOP. The gap length may be
  491. * extended to a multiple of 4.
  492. *
  493. * <p>If the instruction at the given index is at the beginning
  494. * of a block statement,
  495. * then the gap is inserted within that block.
  496. *
  497. * @param pos the index at which a gap is inserted.
  498. * @param length gap length.
  499. * @return the length of the inserted gap.
  500. * It might be bigger than <code>length</code>.
  501. */
  502. public int insertGap(int pos, int length) throws BadBytecode {
  503. return insertGapAt(pos, length, false).length;
  504. }
  505. /**
  506. * Inserts an exclusive gap
  507. * before the next instruction that would be returned by
  508. * <code>next()</code> (not before the instruction returned
  509. * by the last call to <code>next()</code>).
  510. * Branch offsets and the exception table are also updated.
  511. * The inserted gap is filled with NOP. The gap length may be
  512. * extended to a multiple of 4.
  513. *
  514. * <p>If the next instruction is at the beginning of a block statement,
  515. * then the gap is excluded from that block.
  516. *
  517. * @param length gap length
  518. * @return the index indicating the first byte of the inserted gap.
  519. */
  520. public int insertExGap(int length) throws BadBytecode {
  521. return insertGapAt(currentPos, length, true).position;
  522. }
  523. /**
  524. * Inserts an exclusive gap in front of the instruction at the given
  525. * index <code>pos</code>.
  526. * Branch offsets and the exception table are also updated.
  527. * The inserted gap is filled with NOP. The gap length may be
  528. * extended to a multiple of 4.
  529. *
  530. * <p>If the instruction at the given index is at the beginning
  531. * of a block statement,
  532. * then the gap is excluded from that block.
  533. *
  534. * @param pos the index at which a gap is inserted.
  535. * @param length gap length.
  536. * @return the length of the inserted gap.
  537. * It might be bigger than <code>length</code>.
  538. */
  539. public int insertExGap(int pos, int length) throws BadBytecode {
  540. return insertGapAt(pos, length, true).length;
  541. }
  542. /**
  543. * An inserted gap.
  544. *
  545. * @since 3.11
  546. */
  547. public static class Gap {
  548. /**
  549. * The position of the gap.
  550. */
  551. public int position;
  552. /**
  553. * The length of the gap.
  554. */
  555. public int length;
  556. }
  557. /**
  558. * Inserts an inclusive or exclusive gap in front of the instruction
  559. * at the given index <code>pos</code>.
  560. * Branch offsets and the exception table in the method body
  561. * are also updated. The inserted gap is filled with NOP.
  562. * The gap length may be extended to a multiple of 4.
  563. *
  564. * <p>Suppose that the instruction at the given index is at the
  565. * beginning of a block statement. If the gap is inclusive,
  566. * then it is included within that block. If the gap is exclusive,
  567. * then it is excluded from that block.
  568. *
  569. * <p>The index at which the gap is actually inserted
  570. * might be different from pos since some other bytes might be
  571. * inserted at other positions (e.g. to change <code>GOTO</code>
  572. * to <code>GOTO_W</code>). The index is available from the <code>Gap</code>
  573. * object returned by this method.
  574. *
  575. * <p>Suppose that the gap is inserted at the position of
  576. * the next instruction that would be returned by
  577. * <code>next()</code> (not the last instruction returned
  578. * by the last call to <code>next()</code>). The next
  579. * instruction returned by <code>next()</code> after the gap is
  580. * inserted is still the same instruction. It is not <code>NOP</code>
  581. * at the first byte of the inserted gap.
  582. *
  583. * @param pos the index at which a gap is inserted.
  584. * @param length gap length.
  585. * @param exclusive true if exclusive, otherwise false.
  586. * @return the position and the length of the inserted gap.
  587. * @since 3.11
  588. */
  589. public Gap insertGapAt(int pos, int length, boolean exclusive)
  590. throws BadBytecode
  591. {
  592. /**
  593. * cursorPos indicates the next bytecode whichever exclusive is
  594. * true or false.
  595. */
  596. Gap gap = new Gap();
  597. if (length <= 0) {
  598. gap.position = pos;
  599. gap.length = 0;
  600. return gap;
  601. }
  602. byte[] c;
  603. int length2;
  604. if (bytecode.length + length > Short.MAX_VALUE) {
  605. // currentPos might change after calling insertGapCore0w().
  606. c = insertGapCore0w(bytecode, pos, length, exclusive,
  607. get().getExceptionTable(), codeAttr, gap);
  608. pos = gap.position;
  609. length2 = length; // == gap.length
  610. }
  611. else {
  612. int cur = currentPos;
  613. c = insertGapCore0(bytecode, pos, length, exclusive,
  614. get().getExceptionTable(), codeAttr);
  615. // insertGapCore0() never changes pos.
  616. length2 = c.length - bytecode.length;
  617. gap.position = pos;
  618. gap.length = length2;
  619. if (cur >= pos)
  620. currentPos = cur + length2;
  621. if (mark > pos || (mark == pos && exclusive))
  622. mark += length2;
  623. if (mark2 > pos || (mark2 == pos && exclusive))
  624. mark2 += length2;
  625. }
  626. codeAttr.setCode(c);
  627. bytecode = c;
  628. endPos = getCodeLength();
  629. updateCursors(pos, length2);
  630. return gap;
  631. }
  632. /**
  633. * Is called when a gap is inserted. The default implementation is empty.
  634. * A subclass can override this method so that cursors will be updated.
  635. *
  636. * @param pos the position where a gap is inserted.
  637. * @param length the length of the gap.
  638. */
  639. protected void updateCursors(int pos, int length) {
  640. // empty
  641. }
  642. /**
  643. * Copies and inserts the entries in the given exception table
  644. * at the beginning of the exception table in the code attribute
  645. * edited by this object.
  646. *
  647. * @param offset the value added to the code positions included
  648. * in the entries.
  649. */
  650. public void insert(ExceptionTable et, int offset) {
  651. codeAttr.getExceptionTable().add(0, et, offset);
  652. }
  653. /**
  654. * Appends the given bytecode sequence at the end.
  655. *
  656. * @param code the bytecode appended.
  657. * @return the position of the first byte of the appended bytecode.
  658. */
  659. public int append(byte[] code) {
  660. int size = getCodeLength();
  661. int len = code.length;
  662. if (len <= 0)
  663. return size;
  664. appendGap(len);
  665. byte[] dest = bytecode;
  666. for (int i = 0; i < len; ++i)
  667. dest[i + size] = code[i];
  668. return size;
  669. }
  670. /**
  671. * Appends a gap at the end of the bytecode sequence.
  672. *
  673. * @param gapLength gap length
  674. */
  675. public void appendGap(int gapLength) {
  676. byte[] code = bytecode;
  677. int codeLength = code.length;
  678. byte[] newcode = new byte[codeLength + gapLength];
  679. int i;
  680. for (i = 0; i < codeLength; ++i)
  681. newcode[i] = code[i];
  682. for (i = codeLength; i < codeLength + gapLength; ++i)
  683. newcode[i] = NOP;
  684. codeAttr.setCode(newcode);
  685. bytecode = newcode;
  686. endPos = getCodeLength();
  687. }
  688. /**
  689. * Copies and appends the entries in the given exception table
  690. * at the end of the exception table in the code attribute
  691. * edited by this object.
  692. *
  693. * @param offset the value added to the code positions included
  694. * in the entries.
  695. */
  696. public void append(ExceptionTable et, int offset) {
  697. ExceptionTable table = codeAttr.getExceptionTable();
  698. table.add(table.size(), et, offset);
  699. }
  700. /* opcodeLegth is used for implementing nextOpcode().
  701. */
  702. private static final int opcodeLength[] = {
  703. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3,
  704. 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  705. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1,
  706. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  707. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  708. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  709. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1,
  710. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3,
  711. 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3,
  712. 3, 3, 3, 3, 3, 5, 5, 3, 2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3,
  713. 5, 5
  714. };
  715. // 0 .. LOOKUPSWITCH, TABLESWITCH, WIDE
  716. /**
  717. * Calculates the index of the next opcode.
  718. */
  719. static int nextOpcode(byte[] code, int index)
  720. throws BadBytecode
  721. {
  722. int opcode;
  723. try {
  724. opcode = code[index] & 0xff;
  725. }
  726. catch (IndexOutOfBoundsException e) {
  727. throw new BadBytecode("invalid opcode address");
  728. }
  729. try {
  730. int len = opcodeLength[opcode];
  731. if (len > 0)
  732. return index + len;
  733. else if (opcode == WIDE)
  734. if (code[index + 1] == (byte)IINC) // WIDE IINC
  735. return index + 6;
  736. else
  737. return index + 4; // WIDE ...
  738. int index2 = (index & ~3) + 8;
  739. if (opcode == LOOKUPSWITCH) {
  740. int npairs = ByteArray.read32bit(code, index2);
  741. return index2 + npairs * 8 + 4;
  742. }
  743. else if (opcode == TABLESWITCH) {
  744. int low = ByteArray.read32bit(code, index2);
  745. int high = ByteArray.read32bit(code, index2 + 4);
  746. return index2 + (high - low + 1) * 4 + 8;
  747. }
  748. }
  749. catch (IndexOutOfBoundsException e) {
  750. }
  751. // opcode is UNUSED or an IndexOutOfBoundsException was thrown.
  752. throw new BadBytecode(opcode);
  753. }
  754. // methods for implementing insertGap().
  755. static class AlignmentException extends Exception {
  756. /** default serialVersionUID */
  757. private static final long serialVersionUID = 1L;}
  758. /**
  759. * insertGapCore0() inserts a gap (some NOPs).
  760. * It cannot handle a long code sequence more than 32K. All branch offsets must be
  761. * signed 16bits.
  762. *
  763. * If "where" is the beginning of a block statement and exclusive is false,
  764. * then the inserted gap is also included in the block statement.
  765. * "where" must indicate the first byte of an opcode.
  766. * The inserted gap is filled with NOP. gapLength may be extended to
  767. * a multiple of 4.
  768. *
  769. * This method was also called from CodeAttribute.LdcEntry.doit().
  770. *
  771. * @param where It must indicate the first byte of an opcode.
  772. */
  773. static byte[] insertGapCore0(byte[] code, int where, int gapLength,
  774. boolean exclusive, ExceptionTable etable, CodeAttribute ca)
  775. throws BadBytecode
  776. {
  777. if (gapLength <= 0)
  778. return code;
  779. try {
  780. return insertGapCore1(code, where, gapLength, exclusive, etable, ca);
  781. }
  782. catch (AlignmentException e) {
  783. try {
  784. return insertGapCore1(code, where, (gapLength + 3) & ~3,
  785. exclusive, etable, ca);
  786. }
  787. catch (AlignmentException e2) {
  788. throw new RuntimeException("fatal error?");
  789. }
  790. }
  791. }
  792. private static byte[] insertGapCore1(byte[] code, int where, int gapLength,
  793. boolean exclusive, ExceptionTable etable,
  794. CodeAttribute ca)
  795. throws BadBytecode, AlignmentException
  796. {
  797. int codeLength = code.length;
  798. byte[] newcode = new byte[codeLength + gapLength];
  799. insertGap2(code, where, gapLength, codeLength, newcode, exclusive);
  800. etable.shiftPc(where, gapLength, exclusive);
  801. LineNumberAttribute na
  802. = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
  803. if (na != null)
  804. na.shiftPc(where, gapLength, exclusive);
  805. LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
  806. LocalVariableAttribute.tag);
  807. if (va != null)
  808. va.shiftPc(where, gapLength, exclusive);
  809. LocalVariableAttribute vta
  810. = (LocalVariableAttribute)ca.getAttribute(
  811. LocalVariableAttribute.typeTag);
  812. if (vta != null)
  813. vta.shiftPc(where, gapLength, exclusive);
  814. StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
  815. if (smt != null)
  816. smt.shiftPc(where, gapLength, exclusive);
  817. StackMap sm = (StackMap)ca.getAttribute(StackMap.tag);
  818. if (sm != null)
  819. sm.shiftPc(where, gapLength, exclusive);
  820. return newcode;
  821. }
  822. private static void insertGap2(byte[] code, int where, int gapLength,
  823. int endPos, byte[] newcode, boolean exclusive)
  824. throws BadBytecode, AlignmentException
  825. {
  826. int nextPos;
  827. int i = 0;
  828. int j = 0;
  829. for (; i < endPos; i = nextPos) {
  830. if (i == where) {
  831. int j2 = j + gapLength;
  832. while (j < j2)
  833. newcode[j++] = NOP;
  834. }
  835. nextPos = nextOpcode(code, i);
  836. int inst = code[i] & 0xff;
  837. // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr
  838. if ((153 <= inst && inst <= 168)
  839. || inst == IFNULL || inst == IFNONNULL) {
  840. /* 2bytes *signed* offset */
  841. int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff);
  842. offset = newOffset(i, offset, where, gapLength, exclusive);
  843. newcode[j] = code[i];
  844. ByteArray.write16bit(offset, newcode, j + 1);
  845. j += 3;
  846. }
  847. else if (inst == GOTO_W || inst == JSR_W) {
  848. /* 4bytes offset */
  849. int offset = ByteArray.read32bit(code, i + 1);
  850. offset = newOffset(i, offset, where, gapLength, exclusive);
  851. newcode[j++] = code[i];
  852. ByteArray.write32bit(offset, newcode, j);
  853. j += 4;
  854. }
  855. else if (inst == TABLESWITCH) {
  856. if (i != j && (gapLength & 3) != 0)
  857. throw new AlignmentException();
  858. int i2 = (i & ~3) + 4; // 0-3 byte padding
  859. // IBM JVM 1.4.2 cannot run the following code:
  860. // int i0 = i;
  861. // while (i0 < i2)
  862. // newcode[j++] = code[i0++];
  863. // So extracting this code into an external method.
  864. // see JIRA JASSIST-74.
  865. j = copyGapBytes(newcode, j, code, i, i2);
  866. int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2),
  867. where, gapLength, exclusive);
  868. ByteArray.write32bit(defaultbyte, newcode, j);
  869. int lowbyte = ByteArray.read32bit(code, i2 + 4);
  870. ByteArray.write32bit(lowbyte, newcode, j + 4);
  871. int highbyte = ByteArray.read32bit(code, i2 + 8);
  872. ByteArray.write32bit(highbyte, newcode, j + 8);
  873. j += 12;
  874. int i0 = i2 + 12;
  875. i2 = i0 + (highbyte - lowbyte + 1) * 4;
  876. while (i0 < i2) {
  877. int offset = newOffset(i, ByteArray.read32bit(code, i0),
  878. where, gapLength, exclusive);
  879. ByteArray.write32bit(offset, newcode, j);
  880. j += 4;
  881. i0 += 4;
  882. }
  883. }
  884. else if (inst == LOOKUPSWITCH) {
  885. if (i != j && (gapLength & 3) != 0)
  886. throw new AlignmentException();
  887. int i2 = (i & ~3) + 4; // 0-3 byte padding
  888. // IBM JVM 1.4.2 cannot run the following code:
  889. // int i0 = i;
  890. // while (i0 < i2)
  891. // newcode[j++] = code[i0++];
  892. // So extracting this code into an external method.
  893. // see JIRA JASSIST-74.
  894. j = copyGapBytes(newcode, j, code, i, i2);
  895. int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2),
  896. where, gapLength, exclusive);
  897. ByteArray.write32bit(defaultbyte, newcode, j);
  898. int npairs = ByteArray.read32bit(code, i2 + 4);
  899. ByteArray.write32bit(npairs, newcode, j + 4);
  900. j += 8;
  901. int i0 = i2 + 8;
  902. i2 = i0 + npairs * 8;
  903. while (i0 < i2) {
  904. ByteArray.copy32bit(code, i0, newcode, j);
  905. int offset = newOffset(i,
  906. ByteArray.read32bit(code, i0 + 4),
  907. where, gapLength, exclusive);
  908. ByteArray.write32bit(offset, newcode, j + 4);
  909. j += 8;
  910. i0 += 8;
  911. }
  912. }
  913. else
  914. while (i < nextPos)
  915. newcode[j++] = code[i++];
  916. }
  917. }
  918. private static int copyGapBytes(byte[] newcode, int j, byte[] code, int i, int iEnd) {
  919. switch (iEnd - i) {
  920. case 4:
  921. newcode[j++] = code[i++];
  922. case 3:
  923. newcode[j++] = code[i++];
  924. case 2:
  925. newcode[j++] = code[i++];
  926. case 1:
  927. newcode[j++] = code[i++];
  928. default:
  929. }
  930. return j;
  931. }
  932. private static int newOffset(int i, int offset, int where,
  933. int gapLength, boolean exclusive) {
  934. int target = i + offset;
  935. if (i < where) {
  936. if (where < target || (exclusive && where == target))
  937. offset += gapLength;
  938. }
  939. else if (i == where) {
  940. // This code is different from the code in Branch#shiftOffset().
  941. // see JASSIST-124.
  942. if (target < where)
  943. offset -= gapLength;
  944. }
  945. else
  946. if (target < where || (!exclusive && where == target))
  947. offset -= gapLength;
  948. return offset;
  949. }
  950. static class Pointers {
  951. int cursor;
  952. int mark0, mark, mark2;
  953. ExceptionTable etable;
  954. LineNumberAttribute line;
  955. LocalVariableAttribute vars, types;
  956. StackMapTable stack;
  957. StackMap stack2;
  958. Pointers(int cur, int m, int m2, int m0, ExceptionTable et, CodeAttribute ca) {
  959. cursor = cur;
  960. mark = m;
  961. mark2 = m2;
  962. mark0 = m0;
  963. etable = et; // non null
  964. line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
  965. vars = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.tag);
  966. types = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.typeTag);
  967. stack = (StackMapTable)ca.getAttribute(StackMapTable.tag);
  968. stack2 = (StackMap)ca.getAttribute(StackMap.tag);
  969. }
  970. void shiftPc(int where, int gapLength, boolean exclusive) throws BadBytecode {
  971. if (where < cursor || (where == cursor && exclusive))
  972. cursor += gapLength;
  973. if (where < mark || (where == mark && exclusive))
  974. mark += gapLength;
  975. if (where < mark2 || (where == mark2 && exclusive))
  976. mark2 += gapLength;
  977. if (where < mark0 || (where == mark0 && exclusive))
  978. mark0 += gapLength;
  979. etable.shiftPc(where, gapLength, exclusive);
  980. if (line != null)
  981. line.shiftPc(where, gapLength, exclusive);
  982. if (vars != null)
  983. vars.shiftPc(where, gapLength, exclusive);
  984. if (types != null)
  985. types.shiftPc(where, gapLength, exclusive);
  986. if (stack != null)
  987. stack.shiftPc(where, gapLength, exclusive);
  988. if (stack2 != null)
  989. stack2.shiftPc(where, gapLength, exclusive);
  990. }
  991. void shiftForSwitch(int where, int gapLength) throws BadBytecode {
  992. if (stack != null)
  993. stack.shiftForSwitch(where, gapLength);
  994. if (stack2 != null)
  995. stack2.shiftForSwitch(where, gapLength);
  996. }
  997. }
  998. /*
  999. * This method is called from CodeAttribute.LdcEntry.doit().
  1000. */
  1001. static byte[] changeLdcToLdcW(byte[] code, ExceptionTable etable,
  1002. CodeAttribute ca, CodeAttribute.LdcEntry ldcs)
  1003. throws BadBytecode
  1004. {
  1005. Pointers pointers = new Pointers(0, 0, 0, 0, etable, ca);
  1006. List<Branch> jumps = makeJumpList(code, code.length, pointers);
  1007. while (ldcs != null) {
  1008. addLdcW(ldcs, jumps);
  1009. ldcs = ldcs.next;
  1010. }
  1011. byte[] r = insertGap2w(code, 0, 0, false, jumps, pointers);
  1012. return r;
  1013. }
  1014. private static void addLdcW(CodeAttribute.LdcEntry ldcs, List<Branch> jumps) {
  1015. int where = ldcs.where;
  1016. LdcW ldcw = new LdcW(where, ldcs.index);
  1017. int s = jumps.size();
  1018. for (int i = 0; i < s; i++)
  1019. if (where < jumps.get(i).orgPos) {
  1020. jumps.add(i, ldcw);
  1021. return;
  1022. }
  1023. jumps.add(ldcw);
  1024. }
  1025. /*
  1026. * insertGapCore0w() can handle a long code sequence more than 32K.
  1027. * It guarantees that the length of the inserted gap (NOPs) is equal to
  1028. * gapLength. No other NOPs except some NOPs following TABLESWITCH or
  1029. * LOOKUPSWITCH will not be inserted.
  1030. *
  1031. * Note: currentPos might be moved.
  1032. *
  1033. * @param where It must indicate the first byte of an opcode.
  1034. * @param newWhere It contains the updated index of the position where a gap
  1035. * is inserted and the length of the gap.
  1036. * It must not be null.
  1037. */
  1038. private byte[] insertGapCore0w(byte[] code, int where, int gapLength, boolean exclusive,
  1039. ExceptionTable etable, CodeAttribute ca, Gap newWhere)
  1040. throws BadBytecode
  1041. {
  1042. if (gapLength <= 0)
  1043. return code;
  1044. Pointers pointers = new Pointers(currentPos, mark, mark2, where, etable, ca);
  1045. List<Branch> jumps = makeJumpList(code, code.length, pointers);
  1046. byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers);
  1047. currentPos = pointers.cursor;
  1048. mark = pointers.mark;
  1049. mark2 = pointers.mark2;
  1050. int where2 = pointers.mark0;
  1051. if (where2 == currentPos && !exclusive)
  1052. currentPos += gapLength;
  1053. if (exclusive)
  1054. where2 -= gapLength;
  1055. newWhere.position = where2;
  1056. newWhere.length = gapLength;
  1057. return r;
  1058. }
  1059. private static byte[] insertGap2w(byte[] code, int where, int gapLength,
  1060. boolean exclusive, List<Branch> jumps, Pointers ptrs)
  1061. throws BadBytecode
  1062. {
  1063. if (gapLength > 0) {
  1064. ptrs.shiftPc(where, gapLength, exclusive);
  1065. for (Branch b:jumps)
  1066. b.shift(where, gapLength, exclusive);
  1067. }
  1068. boolean unstable = true;
  1069. do {
  1070. while (unstable) {
  1071. unstable = false;
  1072. for (Branch b:jumps) {
  1073. if (b.expanded()) {
  1074. unstable = true;
  1075. int p = b.pos;
  1076. int delta = b.deltaSize();
  1077. ptrs.shiftPc(p, delta, false);
  1078. for (Branch bb:jumps)
  1079. bb.shift(p, delta, false);
  1080. }
  1081. }
  1082. }
  1083. for (Branch b:jumps) {
  1084. int diff = b.gapChanged();
  1085. if (diff > 0) {
  1086. unstable = true;
  1087. int p = b.pos;
  1088. ptrs.shiftPc(p, diff, false);
  1089. for (Branch bb:jumps)
  1090. bb.shift(p, diff, false);
  1091. }
  1092. }
  1093. } while (unstable);
  1094. return makeExapndedCode(code, jumps, where, gapLength);
  1095. }
  1096. private static List<Branch> makeJumpList(byte[] code, int endPos, Pointers ptrs)
  1097. throws BadBytecode
  1098. {
  1099. List<Branch> jumps = new ArrayList<Branch>();
  1100. int nextPos;
  1101. for (int i = 0; i < endPos; i = nextPos) {
  1102. nextPos = nextOpcode(code, i);
  1103. int inst = code[i] & 0xff;
  1104. // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr
  1105. if ((153 <= inst && inst <= 168)
  1106. || inst == IFNULL || inst == IFNONNULL) {
  1107. /* 2bytes *signed* offset */
  1108. int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff);
  1109. Branch b;
  1110. if (inst == GOTO || inst == JSR)
  1111. b = new Jump16(i, offset);
  1112. else
  1113. b = new If16(i, offset);
  1114. jumps.add(b);
  1115. }
  1116. else if (inst == GOTO_W || inst == JSR_W) {
  1117. /* 4bytes offset */
  1118. int offset = ByteArray.read32bit(code, i + 1);
  1119. jumps.add(new Jump32(i, offset));
  1120. }
  1121. else if (inst == TABLESWITCH) {
  1122. int i2 = (i & ~3) + 4; // 0-3 byte padding
  1123. int defaultbyte = ByteArray.read32bit(code, i2);
  1124. int lowbyte = ByteArray.read32bit(code, i2 + 4);
  1125. int highbyte = ByteArray.read32bit(code, i2 + 8);
  1126. int i0 = i2 + 12;
  1127. int size = highbyte - lowbyte + 1;
  1128. int[] offsets = new int[size];
  1129. for (int j = 0; j < size; j++) {
  1130. offsets[j] = ByteArray.read32bit(code, i0);
  1131. i0 += 4;
  1132. }
  1133. jumps.add(new Table(i, defaultbyte, lowbyte, highbyte, offsets, ptrs));
  1134. }
  1135. else if (inst == LOOKUPSWITCH) {
  1136. int i2 = (i & ~3) + 4; // 0-3 byte padding
  1137. int defaultbyte = ByteArray.read32bit(code, i2);
  1138. int npairs = ByteArray.read32bit(code, i2 + 4);
  1139. int i0 = i2 + 8;
  1140. int[] matches = new int[npairs];
  1141. int[] offsets = new int[npairs];
  1142. for (int j = 0; j < npairs; j++) {
  1143. matches[j] = ByteArray.read32bit(code, i0);
  1144. offsets[j] = ByteArray.read32bit(code, i0 + 4);
  1145. i0 += 8;
  1146. }
  1147. jumps.add(new Lookup(i, defaultbyte, matches, offsets, ptrs));
  1148. }
  1149. }
  1150. return jumps;
  1151. }
  1152. private static byte[] makeExapndedCode(byte[] code, List<Branch> jumps,
  1153. int where, int gapLength)
  1154. throws BadBytecode
  1155. {
  1156. int n = jumps.size();
  1157. int size = code.length + gapLength;
  1158. for (Branch b:jumps)
  1159. size += b.deltaSize();
  1160. byte[] newcode = new byte[size];
  1161. int src = 0, dest = 0, bindex = 0;
  1162. int len = code.length;
  1163. Branch b;
  1164. int bpos;
  1165. if (0 < n) {
  1166. b = jumps.get(0);
  1167. bpos = b.orgPos;
  1168. }
  1169. else {
  1170. b = null;
  1171. bpos = len; // src will be never equal to bpos
  1172. }
  1173. while (src < len) {
  1174. if (src == where) {
  1175. int pos2 = dest + gapLength;
  1176. while (dest < pos2)
  1177. newcode[dest++] = NOP;
  1178. }
  1179. if (src != bpos)
  1180. newcode[dest++] = code[src++];
  1181. else {
  1182. int s = b.write(src, code, dest, newcode);
  1183. src += s;
  1184. dest += s + b.deltaSize();
  1185. if (++bindex < n) {
  1186. b = jumps.get(bindex);
  1187. bpos = b.orgPos;
  1188. }
  1189. else {
  1190. b = null;
  1191. bpos = len;
  1192. }
  1193. }
  1194. }
  1195. return newcode;
  1196. }
  1197. static abstract class Branch {
  1198. int pos, orgPos;
  1199. Branch(int p) { pos = orgPos = p; }
  1200. void shift(int where, int gapLength, boolean exclusive) {
  1201. if (where < pos || (where == pos && exclusive))
  1202. pos += gapLength;
  1203. }
  1204. static int shiftOffset(int i, int offset, int where,
  1205. int gapLength, boolean exclusive) {
  1206. int target = i + offset;
  1207. if (i < where) {
  1208. if (where < target || (exclusive && where == target))
  1209. offset += gapLength;
  1210. }
  1211. else if (i == where) {
  1212. // This code is different from the code in CodeIterator#newOffset().
  1213. // see JASSIST-124.
  1214. if (target < where && exclusive)
  1215. offset -= gapLength;
  1216. else if (where < target && !exclusive)
  1217. offset += gapLength;
  1218. }
  1219. else
  1220. if (target < where || (!exclusive && where == target))
  1221. offset -= gapLength;
  1222. return offset;
  1223. }
  1224. boolean expanded() { return false; }
  1225. int gapChanged() { return 0; }
  1226. int deltaSize() { return 0; } // newSize - oldSize
  1227. // This returns the original instruction size.
  1228. abstract int write(int srcPos, byte[] code, int destPos, byte[] newcode) throws BadBytecode;
  1229. }
  1230. /* used by changeLdcToLdcW() and CodeAttribute.LdcEntry.
  1231. */
  1232. static class LdcW extends Branch {
  1233. int index;
  1234. boolean state;
  1235. LdcW(int p, int i) {
  1236. super(p);
  1237. index = i;
  1238. state = true;
  1239. }
  1240. @Override
  1241. boolean expanded() {
  1242. if (state) {
  1243. state = false;
  1244. return true;
  1245. }
  1246. return false;
  1247. }
  1248. @Override
  1249. int deltaSize() { return 1; }
  1250. @Override
  1251. int write(int srcPos, byte[] code, int destPos, byte[] newcode) {
  1252. newcode[destPos] = LDC_W;
  1253. ByteArray.write16bit(index, newcode, destPos + 1);
  1254. return 2;
  1255. }
  1256. }
  1257. static abstract class Branch16 extends Branch {
  1258. int offset;
  1259. int state;
  1260. static final int BIT16 = 0;
  1261. static final int EXPAND = 1;
  1262. static final int BIT32 = 2;
  1263. Branch16(int p, int off) {
  1264. super(p);
  1265. offset = off;
  1266. state = BIT16;
  1267. }
  1268. @Override
  1269. void shift(int where, int gapLength, boolean exclusive) {
  1270. offset = shiftOffset(pos, offset, where, gapLength, exclusive);
  1271. super.shift(where, gapLength, exclusive);
  1272. if (state == BIT16)
  1273. if (offset < Short.MIN_VALUE || Short.MAX_VALUE < offset)
  1274. state = EXPAND;
  1275. }
  1276. @Override
  1277. boolean expanded() {
  1278. if (state == EXPAND) {
  1279. state = BIT32;
  1280. return true;
  1281. }
  1282. return false;
  1283. }
  1284. @Override
  1285. abstract int deltaSize();
  1286. abstract void write32(int src, byte[] code, int dest, byte[] newcode);
  1287. @Override
  1288. int write(int src, byte[] code, int dest, byte[] newcode) {
  1289. if (state == BIT32)
  1290. write32(src, code, dest, newcode);
  1291. else {
  1292. newcode[dest] = code[src];
  1293. ByteArray.write16bit(offset, newcode, dest + 1);
  1294. }
  1295. return 3;
  1296. }
  1297. }
  1298. // GOTO or JSR
  1299. static class Jump16 extends Branch16 {
  1300. Jump16(int p, int off) {
  1301. super(p, off);
  1302. }
  1303. @Override
  1304. int deltaSize() {
  1305. return state == BIT32 ? 2 : 0;
  1306. }
  1307. @Override
  1308. void write32(int src, byte[] code, int dest, byte[] newcode) {
  1309. newcode[dest] = (byte)(((code[src] & 0xff) == GOTO) ? GOTO_W : JSR_W);
  1310. ByteArray.write32bit(offset, newcode, dest + 1);
  1311. }
  1312. }
  1313. // if<cond>, if_icmp<cond>, or if_acmp<cond>
  1314. static class If16 extends Branch16 {
  1315. If16(int p, int off) {
  1316. super(p, off);
  1317. }
  1318. @Override
  1319. int deltaSize() {
  1320. return state == BIT32 ? 5 : 0;
  1321. }
  1322. @Override
  1323. void write32(int src, byte[] code, int dest, byte[] newcode) {
  1324. newcode[dest] = (byte)opcode(code[src] & 0xff);
  1325. newcode[dest + 1] = 0;
  1326. newcode[dest + 2] = 8; // branch_offset = 8
  1327. newcode[dest + 3] = (byte)GOTO_W;
  1328. ByteArray.write32bit(offset - 3, newcode, dest + 4);
  1329. }
  1330. int opcode(int op) {
  1331. if (op == IFNULL)
  1332. return IFNONNULL;
  1333. else if (op == IFNONNULL)
  1334. return IFNULL;
  1335. if (((op - IFEQ) & 1) == 0)
  1336. return op + 1;
  1337. return op - 1;
  1338. }
  1339. }
  1340. static class Jump32 extends Branch {
  1341. int offset;
  1342. Jump32(int p, int off) {
  1343. super(p);
  1344. offset = off;
  1345. }
  1346. @Override
  1347. void shift(int where, int gapLength, boolean exclusive) {
  1348. offset = shiftOffset(pos, offset, where, gapLength, exclusive);
  1349. super.shift(where, gapLength, exclusive);
  1350. }
  1351. @Override
  1352. int write(int src, byte[] code, int dest, byte[] newcode) {
  1353. newcode[dest] = code[src];
  1354. ByteArray.write32bit(offset, newcode, dest + 1);
  1355. return 5;
  1356. }
  1357. }
  1358. static abstract class Switcher extends Branch {
  1359. int gap, defaultByte;
  1360. int[] offsets;
  1361. Pointers pointers;
  1362. Switcher(int pos, int defaultByte, int[] offsets, Pointers ptrs) {
  1363. super(pos);
  1364. this.gap = 3 - (pos & 3);
  1365. this.defaultByte = defaultByte;
  1366. this.offsets = offsets;
  1367. this.pointers = ptrs;
  1368. }
  1369. @Override
  1370. void shift(int where, int gapLength, boolean exclusive) {
  1371. int p = pos;
  1372. defaultByte = shiftOffset(p, defaultByte, where, gapLength, exclusive);
  1373. int num = offsets.length;
  1374. for (int i = 0; i < num; i++)
  1375. offsets[i] = shiftOffset(p, offsets[i], where, gapLength, exclusive);
  1376. super.shift(where, gapLength, exclusive);
  1377. }
  1378. @Override
  1379. int gapChanged() {
  1380. int newGap = 3 - (pos & 3);
  1381. if (newGap > gap) {
  1382. int diff = newGap - gap;
  1383. gap = newGap;
  1384. return diff;
  1385. }
  1386. return 0;
  1387. }
  1388. @Override
  1389. int deltaSize() {
  1390. return gap - (3 - (orgPos & 3));
  1391. }
  1392. @Override
  1393. int write(int src, byte[] code, int dest, byte[] newcode) throws BadBytecode {
  1394. int padding = 3 - (pos & 3);
  1395. int nops = gap - padding;
  1396. int bytecodeSize = 5 + (3 - (orgPos & 3)) + tableSize();
  1397. if (nops > 0)
  1398. adjustOffsets(bytecodeSize, nops);
  1399. newcode[dest++] = code[src];
  1400. while (padding-- > 0)
  1401. newcode[dest++] = 0;
  1402. ByteArray.write32bit(defaultByte, newcode, dest);
  1403. int size = write2(dest + 4, newcode);
  1404. dest += size + 4;
  1405. while (nops-- > 0)
  1406. newcode[dest++] = NOP;
  1407. return 5 + (3 - (orgPos & 3)) + size;
  1408. }
  1409. abstract int write2(int dest, byte[] newcode);
  1410. abstract int tableSize();
  1411. /* If the new bytecode size is shorter than the original, some NOPs
  1412. * are appended after this branch instruction (tableswitch or
  1413. * lookupswitch) to fill the gap.
  1414. * This method changes a branch offset to point to the first NOP
  1415. * if the offset originally points to the bytecode next to this
  1416. * branch instruction. Otherwise, the bytecode would contain
  1417. * dead code. It complicates the generation of StackMap and
  1418. * StackMapTable.
  1419. */
  1420. void adjustOffsets(int size, int nops) throws BadBytecode {
  1421. pointers.shiftForSwitch(pos + size, nops);
  1422. if (defaultByte == size)
  1423. defaultByte -= nops;
  1424. for (int i = 0; i < offsets.length; i++)
  1425. if (offsets[i] == size)
  1426. offsets[i] -= nops;
  1427. }
  1428. }
  1429. static class Table extends Switcher {
  1430. int low, high;
  1431. Table(int pos, int defaultByte, int low, int high, int[] offsets, Pointers ptrs) {
  1432. super(pos, defaultByte, offsets, ptrs);
  1433. this.low = low;
  1434. this.high = high;
  1435. }
  1436. @Override
  1437. int write2(int dest, byte[] newcode) {
  1438. ByteArray.write32bit(low, newcode, dest);
  1439. ByteArray.write32bit(high, newcode, dest + 4);
  1440. int n = offsets.length;
  1441. dest += 8;
  1442. for (int i = 0; i < n; i++) {
  1443. ByteArray.write32bit(offsets[i], newcode, dest);
  1444. dest += 4;
  1445. }
  1446. return 8 + 4 * n;
  1447. }
  1448. @Override
  1449. int tableSize() { return 8 + 4 * offsets.length; }
  1450. }
  1451. static class Lookup extends Switcher {
  1452. int[] matches;
  1453. Lookup(int pos, int defaultByte, int[] matches, int[] offsets, Pointers ptrs) {
  1454. super(pos, defaultByte, offsets, ptrs);
  1455. this.matches = matches;
  1456. }
  1457. @Override
  1458. int write2(int dest, byte[] newcode) {
  1459. int n = matches.length;
  1460. ByteArray.write32bit(n, newcode, dest);
  1461. dest += 4;
  1462. for (int i = 0; i < n; i++) {
  1463. ByteArray.write32bit(matches[i], newcode, dest);
  1464. ByteArray.write32bit(offsets[i], newcode, dest + 4);
  1465. dest += 8;
  1466. }
  1467. return 4 + 8 * n;
  1468. }
  1469. @Override
  1470. int tableSize() { return 4 + 8 * matches.length; }
  1471. }
  1472. }