StackMapTableAttr.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // Copyright (c) 2008, 2010 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.bytecode;
  4. /** Represents a "StackMapTable" attribute, as added in Java 6. */
  5. public class StackMapTableAttr extends MiscAttr
  6. {
  7. public static boolean compressStackMapTable = true;
  8. int numEntries;
  9. int prevPosition = -1;
  10. int[] encodedLocals;
  11. int[] encodedStack;
  12. /** Length of in-use segments of encodedLocals and encodedStack.
  13. * In this case, Long and Double counts as one. */
  14. int countLocals, countStack;
  15. public StackMapTableAttr()
  16. {
  17. super("StackMapTable", null, 0, 0);
  18. put2(0); // numEntries
  19. }
  20. /** Add a new StackMapTableAttr to a CodeAttr. */
  21. public StackMapTableAttr(byte[] data, CodeAttr code)
  22. {
  23. super("StackMapTable", data, 0, data.length);
  24. addToFrontOf(code);
  25. this.numEntries = u2(0);
  26. }
  27. public Method getMethod() { return ((CodeAttr) container).getMethod(); }
  28. /** Write out the contents of the Attribute.
  29. * Does not write the 6-byte attribute header. */
  30. public void write (java.io.DataOutputStream dstr)
  31. throws java.io.IOException
  32. {
  33. put2(0, numEntries);
  34. super.write(dstr);
  35. }
  36. void emitVerificationType (int encoding)
  37. {
  38. int tag = encoding & 0xff;
  39. put1(tag);
  40. if (tag >= 7)
  41. put2(encoding >> 8);
  42. }
  43. /** Return {@code (offset<<8)|tag} for {@code type}. */
  44. int encodeVerificationType (Type type, CodeAttr code)
  45. {
  46. if (type == null)
  47. return 0; // ITEM_Top
  48. if (type instanceof UninitializedType)
  49. {
  50. UninitializedType utype = (UninitializedType) type;
  51. Label label = utype.label;
  52. if (label == null)
  53. return 6; // ITEM_UninitializedThis
  54. else
  55. return (label.position << 8) | 8; // ITEM_uninitialized
  56. }
  57. else if (type == Type.nullType)
  58. return 5; // ITEM_Null
  59. else
  60. {
  61. type = type.getRawType();
  62. if (type instanceof PrimType)
  63. {
  64. switch (type.signature.charAt(0))
  65. {
  66. case 'B': case 'S': case 'I': case 'C': case 'Z':
  67. return 1; // ITEM_Integer
  68. case 'J':
  69. return 4; // ITEM_Long
  70. case 'F':
  71. return 2; // ITEM_Float
  72. case 'D':
  73. return 3; // ITEM_Double
  74. default: // Should be: case 'V':
  75. return 0; // ITEM_Top
  76. }
  77. }
  78. else // ITEM_Object
  79. return ((code.getConstants().addClass((ObjectType) type).index) << 8) | 7;
  80. }
  81. }
  82. /** Emit type state for the given Label.
  83. * This must be called by strictly increasing position.
  84. * This is handled automatically by {@link CodeAttr#processFixups}.
  85. */
  86. public void emitStackMapEntry (Label label, CodeAttr code)
  87. {
  88. int offset_delta = label.position - prevPosition - 1;
  89. int matchingLocals = 0;
  90. int rawLocalsCount = label.localTypes.length;
  91. if (rawLocalsCount > encodedLocals.length)
  92. {
  93. int[] tmp = new int[rawLocalsCount + encodedLocals.length];
  94. System.arraycopy(encodedLocals, 0, tmp, 0, countLocals);
  95. encodedLocals = tmp;
  96. }
  97. int rawStackCount = label.stackTypes.length;
  98. if (rawStackCount > encodedStack.length)
  99. {
  100. int[] tmp = new int[rawStackCount + encodedStack.length];
  101. System.arraycopy(encodedStack, 0, tmp, 0, countStack);
  102. encodedStack = tmp;
  103. }
  104. int unchangedLocals = 0;
  105. int curLocalsCount = 0;
  106. for (int i = 0; i < rawLocalsCount; i++)
  107. {
  108. int prevType = encodedLocals[curLocalsCount];
  109. int nextType = encodeVerificationType(label.localTypes[i], code);
  110. if (prevType == nextType && unchangedLocals == curLocalsCount)
  111. unchangedLocals = curLocalsCount + 1;
  112. encodedLocals[curLocalsCount++] = nextType;
  113. if (nextType == 3 || nextType == 4) // Double or Long
  114. i++;
  115. }
  116. while (curLocalsCount > 0 && encodedLocals[curLocalsCount-1] == 0)
  117. curLocalsCount--;
  118. int curStackCount = 0;
  119. for (int i = 0; i < rawStackCount; i++)
  120. {
  121. int prevType = encodedStack[curStackCount];
  122. Type t = label.stackTypes[i];
  123. if (t == Type.voidType)
  124. t = label.stackTypes[++i]; // long or double
  125. int nextType = encodeVerificationType(t, code);
  126. encodedStack[curStackCount++] = nextType;
  127. }
  128. int localsDelta = curLocalsCount - countLocals;
  129. if (compressStackMapTable && localsDelta == 0
  130. && curLocalsCount == unchangedLocals && curStackCount <= 1)
  131. {
  132. if (curStackCount == 0)
  133. {
  134. if (offset_delta <= 63)
  135. put1(offset_delta); // same_frame
  136. else
  137. {
  138. put1(251); // same_frame_extended
  139. put2(offset_delta);
  140. }
  141. }
  142. else
  143. {
  144. if (offset_delta <= 63)
  145. put1(64 + offset_delta); // same_locals_1_stack_item_frame
  146. else
  147. {
  148. put1(247); // same_locals_1_stack_item_frame_extended
  149. put2(offset_delta);
  150. }
  151. emitVerificationType(encodedStack[0]);
  152. }
  153. }
  154. else if (compressStackMapTable && curStackCount == 0
  155. && curLocalsCount < countLocals
  156. && unchangedLocals == curLocalsCount
  157. && localsDelta >= -3)
  158. {
  159. put1(251 + localsDelta); // chop_frame
  160. put2(offset_delta);
  161. }
  162. else if (compressStackMapTable && curStackCount == 0
  163. && countLocals == unchangedLocals
  164. && localsDelta <= 3)
  165. {
  166. put1(251+localsDelta); // append_frame
  167. put2(offset_delta);
  168. for (int i = 0; i < localsDelta; i++)
  169. emitVerificationType(encodedLocals[unchangedLocals+i]);
  170. }
  171. else
  172. {
  173. put1(255); // full_frame
  174. put2(offset_delta);
  175. put2(curLocalsCount);
  176. for (int i = 0; i < curLocalsCount; i++)
  177. emitVerificationType(encodedLocals[i]);
  178. put2(curStackCount);
  179. for (int i = 0; i < curStackCount; i++)
  180. emitVerificationType(encodedStack[i]);
  181. }
  182. countLocals = curLocalsCount;
  183. countStack = curStackCount;
  184. prevPosition = label.position;
  185. numEntries++;
  186. }
  187. void printVerificationType (int encoding, ClassTypeWriter dst)
  188. {
  189. int tag = encoding & 0xff;
  190. switch (tag)
  191. {
  192. case 0: // ITEM_Top
  193. dst.print("top/unavailable");
  194. break;
  195. case 1: // ITEM_Integer
  196. dst.print("integer");
  197. break;
  198. case 2: // ITEM_Float
  199. dst.print("float");
  200. break;
  201. case 3: // ITEM_Double
  202. dst.print("double");
  203. break;
  204. case 4: // ITEM_Long
  205. dst.print("long");
  206. break;
  207. case 5: // ITEM_Null
  208. dst.print("null");
  209. break;
  210. case 6: // ITEM_UniniializedThis
  211. dst.print("uninitialized this");
  212. break;
  213. case 7: // ITEM_Object
  214. int index = encoding >> 8;
  215. dst.printOptionalIndex(index);
  216. dst.printConstantTersely(index, ConstantPool.CLASS);
  217. break;
  218. case 8: // ITEM_uninitialized
  219. int offset = encoding >> 8;
  220. dst.print("uninitialized object created at ");
  221. dst.print(offset);
  222. break;
  223. default:
  224. dst.print("<bad verification type tag "+tag+'>');
  225. }
  226. }
  227. /** Extract a single verification_type_info.
  228. * @param startOffset starting index in data
  229. * @return encoded verification type
  230. */
  231. int extractVerificationType (int startOffset, int tag)
  232. {
  233. if (tag == 7 || tag == 8)
  234. {
  235. int value = u2(startOffset+1);
  236. tag |= (value << 8);
  237. }
  238. return tag;
  239. }
  240. static int[] reallocBuffer (int[] buffer, int needed)
  241. {
  242. if (buffer == null)
  243. buffer = new int[needed+10];
  244. else if (needed > buffer.length)
  245. {
  246. int[] tmp = new int[needed+10];
  247. System.arraycopy(buffer, 0, tmp, 0, buffer.length);
  248. buffer = tmp;
  249. }
  250. return buffer;
  251. }
  252. int extractVerificationTypes (int startOffset, int count, int startIndex,
  253. int[] buffer)
  254. {
  255. int offset = startOffset;
  256. while (--count >= 0)
  257. {
  258. int encoding;
  259. if (offset >= dataLength)
  260. encoding = -1;
  261. else
  262. {
  263. int tag = data[offset];
  264. encoding = extractVerificationType(offset, tag);
  265. offset += (tag == 7 || tag == 8 ? 3 : 1);
  266. }
  267. buffer[startIndex++] = encoding;
  268. }
  269. return offset;
  270. }
  271. /** Print a sequence of encoded verification types.
  272. * @param startIndex index if of encodings of first type to print
  273. * @param count number of entries in encodings to print
  274. */
  275. void printVerificationTypes (int[] encodings, int startIndex, int count,
  276. ClassTypeWriter dst)
  277. {
  278. int regno = 0;
  279. for (int i = 0; i < startIndex + count; i++)
  280. {
  281. int encoding = encodings[i];
  282. int tag = encoding & 0xff;
  283. if (i >= startIndex)
  284. {
  285. dst.print(" ");
  286. if (regno >= 100)
  287. ;
  288. else
  289. {
  290. if (regno < 10)
  291. dst.print(' ');
  292. dst.print(' ');
  293. }
  294. dst.print(regno);
  295. dst.print(": ");
  296. printVerificationType(encoding, dst);
  297. dst.println();
  298. }
  299. regno++;
  300. if (tag == 3 || tag == 4)
  301. regno++;
  302. }
  303. }
  304. public void print (ClassTypeWriter dst)
  305. {
  306. dst.print("Attribute \"");
  307. dst.print(getName());
  308. dst.print("\", length:");
  309. dst.print(getLength());
  310. dst.print(", number of entries: ");
  311. dst.println(numEntries);
  312. int ipos = 2; // Start in the data array after the numEntries field.
  313. int pc_offset = -1;
  314. Method method = getMethod();
  315. int encodedTypes[] = null;
  316. int curLocals = (method.getStaticFlag() ? 0 : 1) + method.arg_types.length;
  317. int curStack = 0;
  318. for (int i = 0; i < numEntries; i++)
  319. {
  320. if (ipos >= dataLength)
  321. {
  322. i = -1;
  323. break;
  324. }
  325. int tag = u1(ipos++);
  326. pc_offset++;
  327. int delta = -1;
  328. if (tag <= 127)
  329. pc_offset += tag & 63;
  330. else if (ipos + 1 >= dataLength)
  331. {
  332. ipos = -1;
  333. break;
  334. }
  335. else
  336. {
  337. delta = u2(ipos);
  338. pc_offset += delta;
  339. ipos += 2;
  340. }
  341. dst.print(" offset: ");
  342. dst.print(pc_offset);
  343. if (tag <= 63)
  344. {
  345. dst.println(" - same_frame");
  346. curStack = 0;
  347. }
  348. else if (tag <= 127 || tag == 247)
  349. {
  350. dst.println(tag <= 127 ? " - same_locals_1_stack_item_frame"
  351. : " - same_locals_1_stack_item_frame_extended");
  352. encodedTypes = reallocBuffer(encodedTypes, 1);
  353. ipos = extractVerificationTypes(ipos, 1, 0, encodedTypes);
  354. printVerificationTypes(encodedTypes, 0, 1, dst);
  355. curStack = 1;
  356. }
  357. else if (tag <= 246)
  358. {
  359. dst.print(" - tag reserved for future use - ");
  360. dst.println(tag);
  361. break;
  362. }
  363. else if (tag <= 250)
  364. {
  365. int count = 251-tag;
  366. dst.print(" - chop_frame - undefine ");
  367. dst.print(count);
  368. dst.println(" locals");
  369. curLocals -= count;
  370. curStack = 0;
  371. }
  372. else if (tag == 251)
  373. {
  374. dst.println(" - same_frame_extended");
  375. curStack = 0;
  376. }
  377. else if (tag <= 254)
  378. {
  379. int count = tag - 251;
  380. dst.print(" - append_frame - define ");
  381. dst.print(count);
  382. dst.println(" more locals");
  383. encodedTypes = reallocBuffer(encodedTypes, curLocals+count);
  384. ipos = extractVerificationTypes(ipos, count, curLocals, encodedTypes);
  385. printVerificationTypes(encodedTypes, curLocals, count, dst);
  386. curLocals += count;
  387. curStack = 0;
  388. }
  389. else // tag == 255
  390. {
  391. if (ipos + 1 >= dataLength)
  392. {
  393. ipos = -1;
  394. break;
  395. }
  396. int num_locals = u2(ipos);
  397. ipos += 2;
  398. dst.print(" - full_frame. Locals count: ");
  399. dst.println(num_locals);
  400. encodedTypes = reallocBuffer(encodedTypes, num_locals);
  401. ipos = extractVerificationTypes(ipos, num_locals, 0, encodedTypes);
  402. printVerificationTypes(encodedTypes, 0, num_locals, dst);
  403. curLocals = num_locals;
  404. if (ipos + 1 >= dataLength)
  405. {
  406. ipos = -1;
  407. break;
  408. }
  409. int num_stack = u2(ipos);
  410. ipos += 2;
  411. dst.print(" (end of locals)");
  412. // Align "Locals count:" and "Stack count:":
  413. for (int nspaces = Integer.toString(pc_offset).length();
  414. --nspaces >= 0; )
  415. dst.print(' ');
  416. dst.print(" Stack count: ");
  417. dst.println(num_stack);
  418. encodedTypes = reallocBuffer(encodedTypes, num_stack);
  419. ipos = extractVerificationTypes(ipos, num_stack, 0, encodedTypes);
  420. printVerificationTypes(encodedTypes, 0, num_stack, dst);
  421. curStack = num_stack;
  422. }
  423. if (ipos < 0)
  424. {
  425. dst.println("<ERROR - missing data>");
  426. return;
  427. }
  428. }
  429. }
  430. }