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

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