PageRenderTime 68ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/java-1.7.0-openjdk/openjdk/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java

#
Java | 1612 lines | 1268 code | 131 blank | 213 comment | 345 complexity | ee8eaf6e6b90f406fbe576a8b062d17a MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. package com.sun.tools.javac.jvm;
  26. import java.io.*;
  27. import java.util.Set;
  28. import java.util.HashSet;
  29. import javax.tools.JavaFileManager;
  30. import javax.tools.FileObject;
  31. import javax.tools.JavaFileObject;
  32. import com.sun.tools.javac.code.*;
  33. import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  34. import com.sun.tools.javac.code.Symbol.*;
  35. import com.sun.tools.javac.code.Type.*;
  36. import com.sun.tools.javac.file.BaseFileObject;
  37. import com.sun.tools.javac.util.*;
  38. import static com.sun.tools.javac.code.BoundKind.*;
  39. import static com.sun.tools.javac.code.Flags.*;
  40. import static com.sun.tools.javac.code.Kinds.*;
  41. import static com.sun.tools.javac.code.TypeTags.*;
  42. import static com.sun.tools.javac.jvm.UninitializedType.*;
  43. import static com.sun.tools.javac.main.OptionName.*;
  44. import static javax.tools.StandardLocation.CLASS_OUTPUT;
  45. /** This class provides operations to map an internal symbol table graph
  46. * rooted in a ClassSymbol into a classfile.
  47. *
  48. * <p><b>This is NOT part of any supported API.
  49. * If you write code that depends on this, you do so at your own risk.
  50. * This code and its internal interfaces are subject to change or
  51. * deletion without notice.</b>
  52. */
  53. public class ClassWriter extends ClassFile {
  54. protected static final Context.Key<ClassWriter> classWriterKey =
  55. new Context.Key<ClassWriter>();
  56. private final Symtab syms;
  57. private final Options options;
  58. /** Switch: verbose output.
  59. */
  60. private boolean verbose;
  61. /** Switch: scrable private names.
  62. */
  63. private boolean scramble;
  64. /** Switch: scrable private names.
  65. */
  66. private boolean scrambleAll;
  67. /** Switch: retrofit mode.
  68. */
  69. private boolean retrofit;
  70. /** Switch: emit source file attribute.
  71. */
  72. private boolean emitSourceFile;
  73. /** Switch: generate CharacterRangeTable attribute.
  74. */
  75. private boolean genCrt;
  76. /** Switch: describe the generated stackmap
  77. */
  78. boolean debugstackmap;
  79. /**
  80. * Target class version.
  81. */
  82. private Target target;
  83. /**
  84. * Source language version.
  85. */
  86. private Source source;
  87. /** Type utilities. */
  88. private Types types;
  89. /** The initial sizes of the data and constant pool buffers.
  90. * sizes are increased when buffers get full.
  91. */
  92. static final int DATA_BUF_SIZE = 0x0fff0;
  93. static final int POOL_BUF_SIZE = 0x1fff0;
  94. /** An output buffer for member info.
  95. */
  96. ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
  97. /** An output buffer for the constant pool.
  98. */
  99. ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
  100. /** An output buffer for type signatures.
  101. */
  102. ByteBuffer sigbuf = new ByteBuffer();
  103. /** The constant pool.
  104. */
  105. Pool pool;
  106. /** The inner classes to be written, as a set.
  107. */
  108. Set<ClassSymbol> innerClasses;
  109. /** The inner classes to be written, as a queue where
  110. * enclosing classes come first.
  111. */
  112. ListBuffer<ClassSymbol> innerClassesQueue;
  113. /** The log to use for verbose output.
  114. */
  115. private final Log log;
  116. /** The name table. */
  117. private final Names names;
  118. /** Access to files. */
  119. private final JavaFileManager fileManager;
  120. /** The tags and constants used in compressed stackmap. */
  121. static final int SAME_FRAME_SIZE = 64;
  122. static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
  123. static final int SAME_FRAME_EXTENDED = 251;
  124. static final int FULL_FRAME = 255;
  125. static final int MAX_LOCAL_LENGTH_DIFF = 4;
  126. /** Get the ClassWriter instance for this context. */
  127. public static ClassWriter instance(Context context) {
  128. ClassWriter instance = context.get(classWriterKey);
  129. if (instance == null)
  130. instance = new ClassWriter(context);
  131. return instance;
  132. }
  133. /** Construct a class writer, given an options table.
  134. */
  135. private ClassWriter(Context context) {
  136. context.put(classWriterKey, this);
  137. log = Log.instance(context);
  138. names = Names.instance(context);
  139. syms = Symtab.instance(context);
  140. options = Options.instance(context);
  141. target = Target.instance(context);
  142. source = Source.instance(context);
  143. types = Types.instance(context);
  144. fileManager = context.get(JavaFileManager.class);
  145. verbose = options.isSet(VERBOSE);
  146. scramble = options.isSet("-scramble");
  147. scrambleAll = options.isSet("-scrambleAll");
  148. retrofit = options.isSet("-retrofit");
  149. genCrt = options.isSet(XJCOV);
  150. debugstackmap = options.isSet("debugstackmap");
  151. emitSourceFile = options.isUnset(G_CUSTOM) ||
  152. options.isSet(G_CUSTOM, "source");
  153. String dumpModFlags = options.get("dumpmodifiers");
  154. dumpClassModifiers =
  155. (dumpModFlags != null && dumpModFlags.indexOf('c') != -1);
  156. dumpFieldModifiers =
  157. (dumpModFlags != null && dumpModFlags.indexOf('f') != -1);
  158. dumpInnerClassModifiers =
  159. (dumpModFlags != null && dumpModFlags.indexOf('i') != -1);
  160. dumpMethodModifiers =
  161. (dumpModFlags != null && dumpModFlags.indexOf('m') != -1);
  162. }
  163. /******************************************************************
  164. * Diagnostics: dump generated class names and modifiers
  165. ******************************************************************/
  166. /** Value of option 'dumpmodifiers' is a string
  167. * indicating which modifiers should be dumped for debugging:
  168. * 'c' -- classes
  169. * 'f' -- fields
  170. * 'i' -- innerclass attributes
  171. * 'm' -- methods
  172. * For example, to dump everything:
  173. * javac -XDdumpmodifiers=cifm MyProg.java
  174. */
  175. private final boolean dumpClassModifiers; // -XDdumpmodifiers=c
  176. private final boolean dumpFieldModifiers; // -XDdumpmodifiers=f
  177. private final boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i
  178. private final boolean dumpMethodModifiers; // -XDdumpmodifiers=m
  179. /** Return flags as a string, separated by " ".
  180. */
  181. public static String flagNames(long flags) {
  182. StringBuilder sbuf = new StringBuilder();
  183. int i = 0;
  184. long f = flags & StandardFlags;
  185. while (f != 0) {
  186. if ((f & 1) != 0) {
  187. sbuf.append(" ");
  188. sbuf.append(flagName[i]);
  189. }
  190. f = f >> 1;
  191. i++;
  192. }
  193. return sbuf.toString();
  194. }
  195. //where
  196. private final static String[] flagName = {
  197. "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
  198. "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE",
  199. "ABSTRACT", "STRICTFP"};
  200. /******************************************************************
  201. * Output routines
  202. ******************************************************************/
  203. /** Write a character into given byte buffer;
  204. * byte buffer will not be grown.
  205. */
  206. void putChar(ByteBuffer buf, int op, int x) {
  207. buf.elems[op ] = (byte)((x >> 8) & 0xFF);
  208. buf.elems[op+1] = (byte)((x ) & 0xFF);
  209. }
  210. /** Write an integer into given byte buffer;
  211. * byte buffer will not be grown.
  212. */
  213. void putInt(ByteBuffer buf, int adr, int x) {
  214. buf.elems[adr ] = (byte)((x >> 24) & 0xFF);
  215. buf.elems[adr+1] = (byte)((x >> 16) & 0xFF);
  216. buf.elems[adr+2] = (byte)((x >> 8) & 0xFF);
  217. buf.elems[adr+3] = (byte)((x ) & 0xFF);
  218. }
  219. /******************************************************************
  220. * Signature Generation
  221. ******************************************************************/
  222. /** Assemble signature of given type in string buffer.
  223. */
  224. void assembleSig(Type type) {
  225. switch (type.tag) {
  226. case BYTE:
  227. sigbuf.appendByte('B');
  228. break;
  229. case SHORT:
  230. sigbuf.appendByte('S');
  231. break;
  232. case CHAR:
  233. sigbuf.appendByte('C');
  234. break;
  235. case INT:
  236. sigbuf.appendByte('I');
  237. break;
  238. case LONG:
  239. sigbuf.appendByte('J');
  240. break;
  241. case FLOAT:
  242. sigbuf.appendByte('F');
  243. break;
  244. case DOUBLE:
  245. sigbuf.appendByte('D');
  246. break;
  247. case BOOLEAN:
  248. sigbuf.appendByte('Z');
  249. break;
  250. case VOID:
  251. sigbuf.appendByte('V');
  252. break;
  253. case CLASS:
  254. sigbuf.appendByte('L');
  255. assembleClassSig(type);
  256. sigbuf.appendByte(';');
  257. break;
  258. case ARRAY:
  259. ArrayType at = (ArrayType)type;
  260. sigbuf.appendByte('[');
  261. assembleSig(at.elemtype);
  262. break;
  263. case METHOD:
  264. MethodType mt = (MethodType)type;
  265. sigbuf.appendByte('(');
  266. assembleSig(mt.argtypes);
  267. sigbuf.appendByte(')');
  268. assembleSig(mt.restype);
  269. if (hasTypeVar(mt.thrown)) {
  270. for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
  271. sigbuf.appendByte('^');
  272. assembleSig(l.head);
  273. }
  274. }
  275. break;
  276. case WILDCARD: {
  277. WildcardType ta = (WildcardType) type;
  278. switch (ta.kind) {
  279. case SUPER:
  280. sigbuf.appendByte('-');
  281. assembleSig(ta.type);
  282. break;
  283. case EXTENDS:
  284. sigbuf.appendByte('+');
  285. assembleSig(ta.type);
  286. break;
  287. case UNBOUND:
  288. sigbuf.appendByte('*');
  289. break;
  290. default:
  291. throw new AssertionError(ta.kind);
  292. }
  293. break;
  294. }
  295. case TYPEVAR:
  296. sigbuf.appendByte('T');
  297. sigbuf.appendName(type.tsym.name);
  298. sigbuf.appendByte(';');
  299. break;
  300. case FORALL:
  301. ForAll ft = (ForAll)type;
  302. assembleParamsSig(ft.tvars);
  303. assembleSig(ft.qtype);
  304. break;
  305. case UNINITIALIZED_THIS:
  306. case UNINITIALIZED_OBJECT:
  307. // we don't yet have a spec for uninitialized types in the
  308. // local variable table
  309. assembleSig(types.erasure(((UninitializedType)type).qtype));
  310. break;
  311. default:
  312. throw new AssertionError("typeSig " + type.tag);
  313. }
  314. }
  315. boolean hasTypeVar(List<Type> l) {
  316. while (l.nonEmpty()) {
  317. if (l.head.tag == TypeTags.TYPEVAR) return true;
  318. l = l.tail;
  319. }
  320. return false;
  321. }
  322. void assembleClassSig(Type type) {
  323. ClassType ct = (ClassType)type;
  324. ClassSymbol c = (ClassSymbol)ct.tsym;
  325. enterInner(c);
  326. Type outer = ct.getEnclosingType();
  327. if (outer.allparams().nonEmpty()) {
  328. boolean rawOuter =
  329. c.owner.kind == MTH || // either a local class
  330. c.name == names.empty; // or anonymous
  331. assembleClassSig(rawOuter
  332. ? types.erasure(outer)
  333. : outer);
  334. sigbuf.appendByte('.');
  335. Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
  336. sigbuf.appendName(rawOuter
  337. ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength())
  338. : c.name);
  339. } else {
  340. sigbuf.appendBytes(externalize(c.flatname));
  341. }
  342. if (ct.getTypeArguments().nonEmpty()) {
  343. sigbuf.appendByte('<');
  344. assembleSig(ct.getTypeArguments());
  345. sigbuf.appendByte('>');
  346. }
  347. }
  348. void assembleSig(List<Type> types) {
  349. for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail)
  350. assembleSig(ts.head);
  351. }
  352. void assembleParamsSig(List<Type> typarams) {
  353. sigbuf.appendByte('<');
  354. for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
  355. TypeVar tvar = (TypeVar)ts.head;
  356. sigbuf.appendName(tvar.tsym.name);
  357. List<Type> bounds = types.getBounds(tvar);
  358. if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
  359. sigbuf.appendByte(':');
  360. }
  361. for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
  362. sigbuf.appendByte(':');
  363. assembleSig(l.head);
  364. }
  365. }
  366. sigbuf.appendByte('>');
  367. }
  368. /** Return signature of given type
  369. */
  370. Name typeSig(Type type) {
  371. Assert.check(sigbuf.length == 0);
  372. //- System.out.println(" ? " + type);
  373. assembleSig(type);
  374. Name n = sigbuf.toName(names);
  375. sigbuf.reset();
  376. //- System.out.println(" " + n);
  377. return n;
  378. }
  379. /** Given a type t, return the extended class name of its erasure in
  380. * external representation.
  381. */
  382. public Name xClassName(Type t) {
  383. if (t.tag == CLASS) {
  384. return names.fromUtf(externalize(t.tsym.flatName()));
  385. } else if (t.tag == ARRAY) {
  386. return typeSig(types.erasure(t));
  387. } else {
  388. throw new AssertionError("xClassName");
  389. }
  390. }
  391. /******************************************************************
  392. * Writing the Constant Pool
  393. ******************************************************************/
  394. /** Thrown when the constant pool is over full.
  395. */
  396. public static class PoolOverflow extends Exception {
  397. private static final long serialVersionUID = 0;
  398. public PoolOverflow() {}
  399. }
  400. public static class StringOverflow extends Exception {
  401. private static final long serialVersionUID = 0;
  402. public final String value;
  403. public StringOverflow(String s) {
  404. value = s;
  405. }
  406. }
  407. /** Write constant pool to pool buffer.
  408. * Note: during writing, constant pool
  409. * might grow since some parts of constants still need to be entered.
  410. */
  411. void writePool(Pool pool) throws PoolOverflow, StringOverflow {
  412. int poolCountIdx = poolbuf.length;
  413. poolbuf.appendChar(0);
  414. int i = 1;
  415. while (i < pool.pp) {
  416. Object value = pool.pool[i];
  417. Assert.checkNonNull(value);
  418. if (value instanceof Pool.Method)
  419. value = ((Pool.Method)value).m;
  420. else if (value instanceof Pool.Variable)
  421. value = ((Pool.Variable)value).v;
  422. if (value instanceof MethodSymbol) {
  423. MethodSymbol m = (MethodSymbol)value;
  424. poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
  425. ? CONSTANT_InterfaceMethodref
  426. : CONSTANT_Methodref);
  427. poolbuf.appendChar(pool.put(m.owner));
  428. poolbuf.appendChar(pool.put(nameType(m)));
  429. } else if (value instanceof VarSymbol) {
  430. VarSymbol v = (VarSymbol)value;
  431. poolbuf.appendByte(CONSTANT_Fieldref);
  432. poolbuf.appendChar(pool.put(v.owner));
  433. poolbuf.appendChar(pool.put(nameType(v)));
  434. } else if (value instanceof Name) {
  435. poolbuf.appendByte(CONSTANT_Utf8);
  436. byte[] bs = ((Name)value).toUtf();
  437. poolbuf.appendChar(bs.length);
  438. poolbuf.appendBytes(bs, 0, bs.length);
  439. if (bs.length > Pool.MAX_STRING_LENGTH)
  440. throw new StringOverflow(value.toString());
  441. } else if (value instanceof ClassSymbol) {
  442. ClassSymbol c = (ClassSymbol)value;
  443. if (c.owner.kind == TYP) pool.put(c.owner);
  444. poolbuf.appendByte(CONSTANT_Class);
  445. if (c.type.tag == ARRAY) {
  446. poolbuf.appendChar(pool.put(typeSig(c.type)));
  447. } else {
  448. poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
  449. enterInner(c);
  450. }
  451. } else if (value instanceof NameAndType) {
  452. NameAndType nt = (NameAndType)value;
  453. poolbuf.appendByte(CONSTANT_NameandType);
  454. poolbuf.appendChar(pool.put(nt.name));
  455. poolbuf.appendChar(pool.put(typeSig(nt.type)));
  456. } else if (value instanceof Integer) {
  457. poolbuf.appendByte(CONSTANT_Integer);
  458. poolbuf.appendInt(((Integer)value).intValue());
  459. } else if (value instanceof Long) {
  460. poolbuf.appendByte(CONSTANT_Long);
  461. poolbuf.appendLong(((Long)value).longValue());
  462. i++;
  463. } else if (value instanceof Float) {
  464. poolbuf.appendByte(CONSTANT_Float);
  465. poolbuf.appendFloat(((Float)value).floatValue());
  466. } else if (value instanceof Double) {
  467. poolbuf.appendByte(CONSTANT_Double);
  468. poolbuf.appendDouble(((Double)value).doubleValue());
  469. i++;
  470. } else if (value instanceof String) {
  471. poolbuf.appendByte(CONSTANT_String);
  472. poolbuf.appendChar(pool.put(names.fromString((String)value)));
  473. } else if (value instanceof Type) {
  474. Type type = (Type)value;
  475. if (type.tag == CLASS) enterInner((ClassSymbol)type.tsym);
  476. poolbuf.appendByte(CONSTANT_Class);
  477. poolbuf.appendChar(pool.put(xClassName(type)));
  478. } else {
  479. Assert.error("writePool " + value);
  480. }
  481. i++;
  482. }
  483. if (pool.pp > Pool.MAX_ENTRIES)
  484. throw new PoolOverflow();
  485. putChar(poolbuf, poolCountIdx, pool.pp);
  486. }
  487. /** Given a field, return its name.
  488. */
  489. Name fieldName(Symbol sym) {
  490. if (scramble && (sym.flags() & PRIVATE) != 0 ||
  491. scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0)
  492. return names.fromString("_$" + sym.name.getIndex());
  493. else
  494. return sym.name;
  495. }
  496. /** Given a symbol, return its name-and-type.
  497. */
  498. NameAndType nameType(Symbol sym) {
  499. return new NameAndType(fieldName(sym),
  500. retrofit
  501. ? sym.erasure(types)
  502. : sym.externalType(types));
  503. // if we retrofit, then the NameAndType has been read in as is
  504. // and no change is necessary. If we compile normally, the
  505. // NameAndType is generated from a symbol reference, and the
  506. // adjustment of adding an additional this$n parameter needs to be made.
  507. }
  508. /******************************************************************
  509. * Writing Attributes
  510. ******************************************************************/
  511. /** Write header for an attribute to data buffer and return
  512. * position past attribute length index.
  513. */
  514. int writeAttr(Name attrName) {
  515. databuf.appendChar(pool.put(attrName));
  516. databuf.appendInt(0);
  517. return databuf.length;
  518. }
  519. /** Fill in attribute length.
  520. */
  521. void endAttr(int index) {
  522. putInt(databuf, index - 4, databuf.length - index);
  523. }
  524. /** Leave space for attribute count and return index for
  525. * number of attributes field.
  526. */
  527. int beginAttrs() {
  528. databuf.appendChar(0);
  529. return databuf.length;
  530. }
  531. /** Fill in number of attributes.
  532. */
  533. void endAttrs(int index, int count) {
  534. putChar(databuf, index - 2, count);
  535. }
  536. /** Write the EnclosingMethod attribute if needed.
  537. * Returns the number of attributes written (0 or 1).
  538. */
  539. int writeEnclosingMethodAttribute(ClassSymbol c) {
  540. if (!target.hasEnclosingMethodAttribute() ||
  541. c.owner.kind != MTH && // neither a local class
  542. c.name != names.empty) // nor anonymous
  543. return 0;
  544. int alenIdx = writeAttr(names.EnclosingMethod);
  545. ClassSymbol enclClass = c.owner.enclClass();
  546. MethodSymbol enclMethod =
  547. (c.owner.type == null // local to init block
  548. || c.owner.kind != MTH) // or member init
  549. ? null
  550. : (MethodSymbol)c.owner;
  551. databuf.appendChar(pool.put(enclClass));
  552. databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner)));
  553. endAttr(alenIdx);
  554. return 1;
  555. }
  556. /** Write flag attributes; return number of attributes written.
  557. */
  558. int writeFlagAttrs(long flags) {
  559. int acount = 0;
  560. if ((flags & DEPRECATED) != 0) {
  561. int alenIdx = writeAttr(names.Deprecated);
  562. endAttr(alenIdx);
  563. acount++;
  564. }
  565. if ((flags & ENUM) != 0 && !target.useEnumFlag()) {
  566. int alenIdx = writeAttr(names.Enum);
  567. endAttr(alenIdx);
  568. acount++;
  569. }
  570. if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) {
  571. int alenIdx = writeAttr(names.Synthetic);
  572. endAttr(alenIdx);
  573. acount++;
  574. }
  575. if ((flags & BRIDGE) != 0 && !target.useBridgeFlag()) {
  576. int alenIdx = writeAttr(names.Bridge);
  577. endAttr(alenIdx);
  578. acount++;
  579. }
  580. if ((flags & VARARGS) != 0 && !target.useVarargsFlag()) {
  581. int alenIdx = writeAttr(names.Varargs);
  582. endAttr(alenIdx);
  583. acount++;
  584. }
  585. if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) {
  586. int alenIdx = writeAttr(names.Annotation);
  587. endAttr(alenIdx);
  588. acount++;
  589. }
  590. return acount;
  591. }
  592. /** Write member (field or method) attributes;
  593. * return number of attributes written.
  594. */
  595. int writeMemberAttrs(Symbol sym) {
  596. int acount = writeFlagAttrs(sym.flags());
  597. long flags = sym.flags();
  598. if (source.allowGenerics() &&
  599. (flags & (SYNTHETIC|BRIDGE)) != SYNTHETIC &&
  600. (flags & ANONCONSTR) == 0 &&
  601. (!types.isSameType(sym.type, sym.erasure(types)) ||
  602. hasTypeVar(sym.type.getThrownTypes()))) {
  603. // note that a local class with captured variables
  604. // will get a signature attribute
  605. int alenIdx = writeAttr(names.Signature);
  606. databuf.appendChar(pool.put(typeSig(sym.type)));
  607. endAttr(alenIdx);
  608. acount++;
  609. }
  610. acount += writeJavaAnnotations(sym.getAnnotationMirrors());
  611. return acount;
  612. }
  613. /** Write method parameter annotations;
  614. * return number of attributes written.
  615. */
  616. int writeParameterAttrs(MethodSymbol m) {
  617. boolean hasVisible = false;
  618. boolean hasInvisible = false;
  619. if (m.params != null) for (VarSymbol s : m.params) {
  620. for (Attribute.Compound a : s.getAnnotationMirrors()) {
  621. switch (types.getRetention(a)) {
  622. case SOURCE: break;
  623. case CLASS: hasInvisible = true; break;
  624. case RUNTIME: hasVisible = true; break;
  625. default: ;// /* fail soft */ throw new AssertionError(vis);
  626. }
  627. }
  628. }
  629. int attrCount = 0;
  630. if (hasVisible) {
  631. int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations);
  632. databuf.appendByte(m.params.length());
  633. for (VarSymbol s : m.params) {
  634. ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
  635. for (Attribute.Compound a : s.getAnnotationMirrors())
  636. if (types.getRetention(a) == RetentionPolicy.RUNTIME)
  637. buf.append(a);
  638. databuf.appendChar(buf.length());
  639. for (Attribute.Compound a : buf)
  640. writeCompoundAttribute(a);
  641. }
  642. endAttr(attrIndex);
  643. attrCount++;
  644. }
  645. if (hasInvisible) {
  646. int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations);
  647. databuf.appendByte(m.params.length());
  648. for (VarSymbol s : m.params) {
  649. ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
  650. for (Attribute.Compound a : s.getAnnotationMirrors())
  651. if (types.getRetention(a) == RetentionPolicy.CLASS)
  652. buf.append(a);
  653. databuf.appendChar(buf.length());
  654. for (Attribute.Compound a : buf)
  655. writeCompoundAttribute(a);
  656. }
  657. endAttr(attrIndex);
  658. attrCount++;
  659. }
  660. return attrCount;
  661. }
  662. /**********************************************************************
  663. * Writing Java-language annotations (aka metadata, attributes)
  664. **********************************************************************/
  665. /** Write Java-language annotations; return number of JVM
  666. * attributes written (zero or one).
  667. */
  668. int writeJavaAnnotations(List<Attribute.Compound> attrs) {
  669. if (attrs.isEmpty()) return 0;
  670. ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>();
  671. ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>();
  672. for (Attribute.Compound a : attrs) {
  673. switch (types.getRetention(a)) {
  674. case SOURCE: break;
  675. case CLASS: invisibles.append(a); break;
  676. case RUNTIME: visibles.append(a); break;
  677. default: ;// /* fail soft */ throw new AssertionError(vis);
  678. }
  679. }
  680. int attrCount = 0;
  681. if (visibles.length() != 0) {
  682. int attrIndex = writeAttr(names.RuntimeVisibleAnnotations);
  683. databuf.appendChar(visibles.length());
  684. for (Attribute.Compound a : visibles)
  685. writeCompoundAttribute(a);
  686. endAttr(attrIndex);
  687. attrCount++;
  688. }
  689. if (invisibles.length() != 0) {
  690. int attrIndex = writeAttr(names.RuntimeInvisibleAnnotations);
  691. databuf.appendChar(invisibles.length());
  692. for (Attribute.Compound a : invisibles)
  693. writeCompoundAttribute(a);
  694. endAttr(attrIndex);
  695. attrCount++;
  696. }
  697. return attrCount;
  698. }
  699. /** A visitor to write an attribute including its leading
  700. * single-character marker.
  701. */
  702. class AttributeWriter implements Attribute.Visitor {
  703. public void visitConstant(Attribute.Constant _value) {
  704. Object value = _value.value;
  705. switch (_value.type.tag) {
  706. case BYTE:
  707. databuf.appendByte('B');
  708. break;
  709. case CHAR:
  710. databuf.appendByte('C');
  711. break;
  712. case SHORT:
  713. databuf.appendByte('S');
  714. break;
  715. case INT:
  716. databuf.appendByte('I');
  717. break;
  718. case LONG:
  719. databuf.appendByte('J');
  720. break;
  721. case FLOAT:
  722. databuf.appendByte('F');
  723. break;
  724. case DOUBLE:
  725. databuf.appendByte('D');
  726. break;
  727. case BOOLEAN:
  728. databuf.appendByte('Z');
  729. break;
  730. case CLASS:
  731. Assert.check(value instanceof String);
  732. databuf.appendByte('s');
  733. value = names.fromString(value.toString()); // CONSTANT_Utf8
  734. break;
  735. default:
  736. throw new AssertionError(_value.type);
  737. }
  738. databuf.appendChar(pool.put(value));
  739. }
  740. public void visitEnum(Attribute.Enum e) {
  741. databuf.appendByte('e');
  742. databuf.appendChar(pool.put(typeSig(e.value.type)));
  743. databuf.appendChar(pool.put(e.value.name));
  744. }
  745. public void visitClass(Attribute.Class clazz) {
  746. databuf.appendByte('c');
  747. databuf.appendChar(pool.put(typeSig(clazz.type)));
  748. }
  749. public void visitCompound(Attribute.Compound compound) {
  750. databuf.appendByte('@');
  751. writeCompoundAttribute(compound);
  752. }
  753. public void visitError(Attribute.Error x) {
  754. throw new AssertionError(x);
  755. }
  756. public void visitArray(Attribute.Array array) {
  757. databuf.appendByte('[');
  758. databuf.appendChar(array.values.length);
  759. for (Attribute a : array.values) {
  760. a.accept(this);
  761. }
  762. }
  763. }
  764. AttributeWriter awriter = new AttributeWriter();
  765. /** Write a compound attribute excluding the '@' marker. */
  766. void writeCompoundAttribute(Attribute.Compound c) {
  767. databuf.appendChar(pool.put(typeSig(c.type)));
  768. databuf.appendChar(c.values.length());
  769. for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
  770. databuf.appendChar(pool.put(p.fst.name));
  771. p.snd.accept(awriter);
  772. }
  773. }
  774. /**********************************************************************
  775. * Writing Objects
  776. **********************************************************************/
  777. /** Enter an inner class into the `innerClasses' set/queue.
  778. */
  779. void enterInner(ClassSymbol c) {
  780. if (c.type.isCompound()) {
  781. throw new AssertionError("Unexpected intersection type: " + c.type);
  782. }
  783. try {
  784. c.complete();
  785. } catch (CompletionFailure ex) {
  786. System.err.println("error: " + c + ": " + ex.getMessage());
  787. throw ex;
  788. }
  789. if (c.type.tag != CLASS) return; // arrays
  790. if (pool != null && // pool might be null if called from xClassName
  791. c.owner.enclClass() != null &&
  792. (innerClasses == null || !innerClasses.contains(c))) {
  793. // log.errWriter.println("enter inner " + c);//DEBUG
  794. enterInner(c.owner.enclClass());
  795. pool.put(c);
  796. pool.put(c.name);
  797. if (innerClasses == null) {
  798. innerClasses = new HashSet<ClassSymbol>();
  799. innerClassesQueue = new ListBuffer<ClassSymbol>();
  800. pool.put(names.InnerClasses);
  801. }
  802. innerClasses.add(c);
  803. innerClassesQueue.append(c);
  804. }
  805. }
  806. /** Write "inner classes" attribute.
  807. */
  808. void writeInnerClasses() {
  809. int alenIdx = writeAttr(names.InnerClasses);
  810. databuf.appendChar(innerClassesQueue.length());
  811. for (List<ClassSymbol> l = innerClassesQueue.toList();
  812. l.nonEmpty();
  813. l = l.tail) {
  814. ClassSymbol inner = l.head;
  815. char flags = (char) adjustFlags(inner.flags_field);
  816. if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
  817. if (inner.name.isEmpty()) flags &= ~FINAL; // Anonymous class: unset FINAL flag
  818. if (dumpInnerClassModifiers) {
  819. log.errWriter.println("INNERCLASS " + inner.name);
  820. log.errWriter.println("---" + flagNames(flags));
  821. }
  822. databuf.appendChar(pool.get(inner));
  823. databuf.appendChar(
  824. inner.owner.kind == TYP ? pool.get(inner.owner) : 0);
  825. databuf.appendChar(
  826. !inner.name.isEmpty() ? pool.get(inner.name) : 0);
  827. databuf.appendChar(flags);
  828. }
  829. endAttr(alenIdx);
  830. }
  831. /** Write field symbol, entering all references into constant pool.
  832. */
  833. void writeField(VarSymbol v) {
  834. int flags = adjustFlags(v.flags());
  835. databuf.appendChar(flags);
  836. if (dumpFieldModifiers) {
  837. log.errWriter.println("FIELD " + fieldName(v));
  838. log.errWriter.println("---" + flagNames(v.flags()));
  839. }
  840. databuf.appendChar(pool.put(fieldName(v)));
  841. databuf.appendChar(pool.put(typeSig(v.erasure(types))));
  842. int acountIdx = beginAttrs();
  843. int acount = 0;
  844. if (v.getConstValue() != null) {
  845. int alenIdx = writeAttr(names.ConstantValue);
  846. databuf.appendChar(pool.put(v.getConstValue()));
  847. endAttr(alenIdx);
  848. acount++;
  849. }
  850. acount += writeMemberAttrs(v);
  851. endAttrs(acountIdx, acount);
  852. }
  853. /** Write method symbol, entering all references into constant pool.
  854. */
  855. void writeMethod(MethodSymbol m) {
  856. int flags = adjustFlags(m.flags());
  857. databuf.appendChar(flags);
  858. if (dumpMethodModifiers) {
  859. log.errWriter.println("METHOD " + fieldName(m));
  860. log.errWriter.println("---" + flagNames(m.flags()));
  861. }
  862. databuf.appendChar(pool.put(fieldName(m)));
  863. databuf.appendChar(pool.put(typeSig(m.externalType(types))));
  864. int acountIdx = beginAttrs();
  865. int acount = 0;
  866. if (m.code != null) {
  867. int alenIdx = writeAttr(names.Code);
  868. writeCode(m.code);
  869. m.code = null; // to conserve space
  870. endAttr(alenIdx);
  871. acount++;
  872. }
  873. List<Type> thrown = m.erasure(types).getThrownTypes();
  874. if (thrown.nonEmpty()) {
  875. int alenIdx = writeAttr(names.Exceptions);
  876. databuf.appendChar(thrown.length());
  877. for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
  878. databuf.appendChar(pool.put(l.head.tsym));
  879. endAttr(alenIdx);
  880. acount++;
  881. }
  882. if (m.defaultValue != null) {
  883. int alenIdx = writeAttr(names.AnnotationDefault);
  884. m.defaultValue.accept(awriter);
  885. endAttr(alenIdx);
  886. acount++;
  887. }
  888. acount += writeMemberAttrs(m);
  889. acount += writeParameterAttrs(m);
  890. endAttrs(acountIdx, acount);
  891. }
  892. /** Write code attribute of method.
  893. */
  894. void writeCode(Code code) {
  895. databuf.appendChar(code.max_stack);
  896. databuf.appendChar(code.max_locals);
  897. databuf.appendInt(code.cp);
  898. databuf.appendBytes(code.code, 0, code.cp);
  899. databuf.appendChar(code.catchInfo.length());
  900. for (List<char[]> l = code.catchInfo.toList();
  901. l.nonEmpty();
  902. l = l.tail) {
  903. for (int i = 0; i < l.head.length; i++)
  904. databuf.appendChar(l.head[i]);
  905. }
  906. int acountIdx = beginAttrs();
  907. int acount = 0;
  908. if (code.lineInfo.nonEmpty()) {
  909. int alenIdx = writeAttr(names.LineNumberTable);
  910. databuf.appendChar(code.lineInfo.length());
  911. for (List<char[]> l = code.lineInfo.reverse();
  912. l.nonEmpty();
  913. l = l.tail)
  914. for (int i = 0; i < l.head.length; i++)
  915. databuf.appendChar(l.head[i]);
  916. endAttr(alenIdx);
  917. acount++;
  918. }
  919. if (genCrt && (code.crt != null)) {
  920. CRTable crt = code.crt;
  921. int alenIdx = writeAttr(names.CharacterRangeTable);
  922. int crtIdx = beginAttrs();
  923. int crtEntries = crt.writeCRT(databuf, code.lineMap, log);
  924. endAttrs(crtIdx, crtEntries);
  925. endAttr(alenIdx);
  926. acount++;
  927. }
  928. // counter for number of generic local variables
  929. int nGenericVars = 0;
  930. if (code.varBufferSize > 0) {
  931. int alenIdx = writeAttr(names.LocalVariableTable);
  932. databuf.appendChar(code.varBufferSize);
  933. for (int i=0; i<code.varBufferSize; i++) {
  934. Code.LocalVar var = code.varBuffer[i];
  935. // write variable info
  936. Assert.check(var.start_pc >= 0
  937. && var.start_pc <= code.cp);
  938. databuf.appendChar(var.start_pc);
  939. Assert.check(var.length >= 0
  940. && (var.start_pc + var.length) <= code.cp);
  941. databuf.appendChar(var.length);
  942. VarSymbol sym = var.sym;
  943. databuf.appendChar(pool.put(sym.name));
  944. Type vartype = sym.erasure(types);
  945. if (needsLocalVariableTypeEntry(sym.type))
  946. nGenericVars++;
  947. databuf.appendChar(pool.put(typeSig(vartype)));
  948. databuf.appendChar(var.reg);
  949. }
  950. endAttr(alenIdx);
  951. acount++;
  952. }
  953. if (nGenericVars > 0) {
  954. int alenIdx = writeAttr(names.LocalVariableTypeTable);
  955. databuf.appendChar(nGenericVars);
  956. int count = 0;
  957. for (int i=0; i<code.varBufferSize; i++) {
  958. Code.LocalVar var = code.varBuffer[i];
  959. VarSymbol sym = var.sym;
  960. if (!needsLocalVariableTypeEntry(sym.type))
  961. continue;
  962. count++;
  963. // write variable info
  964. databuf.appendChar(var.start_pc);
  965. databuf.appendChar(var.length);
  966. databuf.appendChar(pool.put(sym.name));
  967. databuf.appendChar(pool.put(typeSig(sym.type)));
  968. databuf.appendChar(var.reg);
  969. }
  970. Assert.check(count == nGenericVars);
  971. endAttr(alenIdx);
  972. acount++;
  973. }
  974. if (code.stackMapBufferSize > 0) {
  975. if (debugstackmap) System.out.println("Stack map for " + code.meth);
  976. int alenIdx = writeAttr(code.stackMap.getAttributeName(names));
  977. writeStackMap(code);
  978. endAttr(alenIdx);
  979. acount++;
  980. }
  981. endAttrs(acountIdx, acount);
  982. }
  983. //where
  984. private boolean needsLocalVariableTypeEntry(Type t) {
  985. //a local variable needs a type-entry if its type T is generic
  986. //(i.e. |T| != T) and if it's not an intersection type (not supported
  987. //in signature attribute grammar)
  988. return (!types.isSameType(t, types.erasure(t)) &&
  989. !t.isCompound());
  990. }
  991. void writeStackMap(Code code) {
  992. int nframes = code.stackMapBufferSize;
  993. if (debugstackmap) System.out.println(" nframes = " + nframes);
  994. databuf.appendChar(nframes);
  995. switch (code.stackMap) {
  996. case CLDC:
  997. for (int i=0; i<nframes; i++) {
  998. if (debugstackmap) System.out.print(" " + i + ":");
  999. Code.StackMapFrame frame = code.stackMapBuffer[i];
  1000. // output PC
  1001. if (debugstackmap) System.out.print(" pc=" + frame.pc);
  1002. databuf.appendChar(frame.pc);
  1003. // output locals
  1004. int localCount = 0;
  1005. for (int j=0; j<frame.locals.length;
  1006. j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.locals[j]))) {
  1007. localCount++;
  1008. }
  1009. if (debugstackmap) System.out.print(" nlocals=" +
  1010. localCount);
  1011. databuf.appendChar(localCount);
  1012. for (int j=0; j<frame.locals.length;
  1013. j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.locals[j]))) {
  1014. if (debugstackmap) System.out.print(" local[" + j + "]=");
  1015. writeStackMapType(frame.locals[j]);
  1016. }
  1017. // output stack
  1018. int stackCount = 0;
  1019. for (int j=0; j<frame.stack.length;
  1020. j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.stack[j]))) {
  1021. stackCount++;
  1022. }
  1023. if (debugstackmap) System.out.print(" nstack=" +
  1024. stackCount);
  1025. databuf.appendChar(stackCount);
  1026. for (int j=0; j<frame.stack.length;
  1027. j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.stack[j]))) {
  1028. if (debugstackmap) System.out.print(" stack[" + j + "]=");
  1029. writeStackMapType(frame.stack[j]);
  1030. }
  1031. if (debugstackmap) System.out.println();
  1032. }
  1033. break;
  1034. case JSR202: {
  1035. Assert.checkNull(code.stackMapBuffer);
  1036. for (int i=0; i<nframes; i++) {
  1037. if (debugstackmap) System.out.print(" " + i + ":");
  1038. StackMapTableFrame frame = code.stackMapTableBuffer[i];
  1039. frame.write(this);
  1040. if (debugstackmap) System.out.println();
  1041. }
  1042. break;
  1043. }
  1044. default:
  1045. throw new AssertionError("Unexpected stackmap format value");
  1046. }
  1047. }
  1048. //where
  1049. void writeStackMapType(Type t) {
  1050. if (t == null) {
  1051. if (debugstackmap) System.out.print("empty");
  1052. databuf.appendByte(0);
  1053. }
  1054. else switch(t.tag) {
  1055. case BYTE:
  1056. case CHAR:
  1057. case SHORT:
  1058. case INT:
  1059. case BOOLEAN:
  1060. if (debugstackmap) System.out.print("int");
  1061. databuf.appendByte(1);
  1062. break;
  1063. case FLOAT:
  1064. if (debugstackmap) System.out.print("float");
  1065. databuf.appendByte(2);
  1066. break;
  1067. case DOUBLE:
  1068. if (debugstackmap) System.out.print("double");
  1069. databuf.appendByte(3);
  1070. break;
  1071. case LONG:
  1072. if (debugstackmap) System.out.print("long");
  1073. databuf.appendByte(4);
  1074. break;
  1075. case BOT: // null
  1076. if (debugstackmap) System.out.print("null");
  1077. databuf.appendByte(5);
  1078. break;
  1079. case CLASS:
  1080. case ARRAY:
  1081. if (debugstackmap) System.out.print("object(" + t + ")");
  1082. databuf.appendByte(7);
  1083. databuf.appendChar(pool.put(t));
  1084. break;
  1085. case TYPEVAR:
  1086. if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
  1087. databuf.appendByte(7);
  1088. databuf.appendChar(pool.put(types.erasure(t).tsym));
  1089. break;
  1090. case UNINITIALIZED_THIS:
  1091. if (debugstackmap) System.out.print("uninit_this");
  1092. databuf.appendByte(6);
  1093. break;
  1094. case UNINITIALIZED_OBJECT:
  1095. { UninitializedType uninitType = (UninitializedType)t;
  1096. databuf.appendByte(8);
  1097. if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
  1098. databuf.appendChar(uninitType.offset);
  1099. }
  1100. break;
  1101. default:
  1102. throw new AssertionError();
  1103. }
  1104. }
  1105. /** An entry in the JSR202 StackMapTable */
  1106. abstract static class StackMapTableFrame {
  1107. abstract int getFrameType();
  1108. void write(ClassWriter writer) {
  1109. int frameType = getFrameType();
  1110. writer.databuf.appendByte(frameType);
  1111. if (writer.debugstackmap) System.out.print(" frame_type=" + frameType);
  1112. }
  1113. static class SameFrame extends StackMapTableFrame {
  1114. final int offsetDelta;
  1115. SameFrame(int offsetDelta) {
  1116. this.offsetDelta = offsetDelta;
  1117. }
  1118. int getFrameType() {
  1119. return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED;
  1120. }
  1121. @Override
  1122. void write(ClassWriter writer) {
  1123. super.write(writer);
  1124. if (getFrameType() == SAME_FRAME_EXTENDED) {
  1125. writer.databuf.appendChar(offsetDelta);
  1126. if (writer.debugstackmap){
  1127. System.out.print(" offset_delta=" + offsetDelta);
  1128. }
  1129. }
  1130. }
  1131. }
  1132. static class SameLocals1StackItemFrame extends StackMapTableFrame {
  1133. final int offsetDelta;
  1134. final Type stack;
  1135. SameLocals1StackItemFrame(int offsetDelta, Type stack) {
  1136. this.offsetDelta = offsetDelta;
  1137. this.stack = stack;
  1138. }
  1139. int getFrameType() {
  1140. return (offsetDelta < SAME_FRAME_SIZE) ?
  1141. (SAME_FRAME_SIZE + offsetDelta) :
  1142. SAME_LOCALS_1_STACK_ITEM_EXTENDED;
  1143. }
  1144. @Override
  1145. void write(ClassWriter writer) {
  1146. super.write(writer);
  1147. if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
  1148. writer.databuf.appendChar(offsetDelta);
  1149. if (writer.debugstackmap) {
  1150. System.out.print(" offset_delta=" + offsetDelta);
  1151. }
  1152. }
  1153. if (writer.debugstackmap) {
  1154. System.out.print(" stack[" + 0 + "]=");
  1155. }
  1156. writer.writeStackMapType(stack);
  1157. }
  1158. }
  1159. static class ChopFrame extends StackMapTableFrame {
  1160. final int frameType;
  1161. final int offsetDelta;
  1162. ChopFrame(int frameType, int offsetDelta) {
  1163. this.frameType = frameType;
  1164. this.offsetDelta = offsetDelta;
  1165. }
  1166. int getFrameType() { return frameType; }
  1167. @Override
  1168. void write(ClassWriter writer) {
  1169. super.write(writer);
  1170. writer.databuf.appendChar(offsetDelta);
  1171. if (writer.debugstackmap) {
  1172. System.out.print(" offset_delta=" + offsetDelta);
  1173. }
  1174. }
  1175. }
  1176. static class AppendFrame extends StackMapTableFrame {
  1177. final int frameType;
  1178. final int offsetDelta;
  1179. final Type[] locals;
  1180. AppendFrame(int frameType, int offsetDelta, Type[] locals) {
  1181. this.frameType = frameType;
  1182. this.offsetDelta = offsetDelta;
  1183. this.locals = locals;
  1184. }
  1185. int getFrameType() { return frameType; }
  1186. @Override
  1187. void write(ClassWriter writer) {
  1188. super.write(writer);
  1189. writer.databuf.appendChar(offsetDelta);
  1190. if (writer.debugstackmap) {
  1191. System.out.print(" offset_delta=" + offsetDelta);
  1192. }
  1193. for (int i=0; i<locals.length; i++) {
  1194. if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
  1195. writer.writeStackMapType(locals[i]);
  1196. }
  1197. }
  1198. }
  1199. static class FullFrame extends StackMapTableFrame {
  1200. final int offsetDelta;
  1201. final Type[] locals;
  1202. final Type[] stack;
  1203. FullFrame(int offsetDelta, Type[] locals, Type[] stack) {
  1204. this.offsetDelta = offsetDelta;
  1205. this.locals = locals;
  1206. this.stack = stack;
  1207. }
  1208. int getFrameType() { return FULL_FRAME; }
  1209. @Override
  1210. void write(ClassWriter writer) {
  1211. super.write(writer);
  1212. writer.databuf.appendChar(offsetDelta);
  1213. writer.databuf.appendChar(locals.length);
  1214. if (writer.debugstackmap) {
  1215. System.out.print(" offset_delta=" + offsetDelta);
  1216. System.out.print(" nlocals=" + locals.length);
  1217. }
  1218. for (int i=0; i<locals.length; i++) {
  1219. if (writer.debugstackmap) System.out.print(" locals[" + i + "]=");
  1220. writer.writeStackMapType(locals[i]);
  1221. }
  1222. writer.databuf.appendChar(stack.length);
  1223. if (writer.debugstackmap) { System.out.print(" nstack=" + stack.length); }
  1224. for (int i=0; i<stack.length; i++) {
  1225. if (writer.debugstackmap) System.out.print(" stack[" + i + "]=");
  1226. writer.writeStackMapType(stack[i]);
  1227. }
  1228. }
  1229. }
  1230. /** Compare this frame with the previous frame and produce
  1231. * an entry of compressed stack map frame. */
  1232. static StackMapTableFrame getInstance(Code.StackMapFrame this_frame,
  1233. int prev_pc,
  1234. Type[] prev_locals,
  1235. Types types) {
  1236. Type[] locals = this_frame.locals;
  1237. Type[] stack = this_frame.stack;
  1238. int offset_delta = this_frame.pc - prev_pc - 1;
  1239. if (stack.length == 1) {
  1240. if (locals.length == prev_locals.length
  1241. && compare(prev_locals, locals, types) == 0) {
  1242. return new SameLocals1StackItemFrame(offset_delta, stack[0]);
  1243. }

Large files files are truncated, but you can click here to view the full file