1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,1804 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.jvm; 1.30 + 1.31 +import java.io.*; 1.32 +import java.util.LinkedHashMap; 1.33 +import java.util.Map; 1.34 +import java.util.Set; 1.35 +import java.util.HashSet; 1.36 + 1.37 +import javax.tools.JavaFileManager; 1.38 +import javax.tools.FileObject; 1.39 +import javax.tools.JavaFileObject; 1.40 + 1.41 +import com.sun.tools.javac.code.*; 1.42 +import com.sun.tools.javac.code.Attribute.RetentionPolicy; 1.43 +import com.sun.tools.javac.code.Symbol.*; 1.44 +import com.sun.tools.javac.code.Type.*; 1.45 +import com.sun.tools.javac.code.Types.UniqueType; 1.46 +import com.sun.tools.javac.file.BaseFileObject; 1.47 +import com.sun.tools.javac.jvm.Pool.DynamicMethod; 1.48 +import com.sun.tools.javac.jvm.Pool.Method; 1.49 +import com.sun.tools.javac.jvm.Pool.MethodHandle; 1.50 +import com.sun.tools.javac.jvm.Pool.Variable; 1.51 +import com.sun.tools.javac.util.*; 1.52 + 1.53 +import static com.sun.tools.javac.code.Flags.*; 1.54 +import static com.sun.tools.javac.code.Kinds.*; 1.55 +import static com.sun.tools.javac.code.TypeTag.*; 1.56 +import static com.sun.tools.javac.jvm.UninitializedType.*; 1.57 +import static com.sun.tools.javac.main.Option.*; 1.58 +import static javax.tools.StandardLocation.CLASS_OUTPUT; 1.59 + 1.60 +/** This class provides operations to map an internal symbol table graph 1.61 + * rooted in a ClassSymbol into a classfile. 1.62 + * 1.63 + * <p><b>This is NOT part of any supported API. 1.64 + * If you write code that depends on this, you do so at your own risk. 1.65 + * This code and its internal interfaces are subject to change or 1.66 + * deletion without notice.</b> 1.67 + */ 1.68 +public class ClassWriter extends ClassFile { 1.69 + protected static final Context.Key<ClassWriter> classWriterKey = 1.70 + new Context.Key<ClassWriter>(); 1.71 + 1.72 + private final Options options; 1.73 + 1.74 + /** Switch: verbose output. 1.75 + */ 1.76 + private boolean verbose; 1.77 + 1.78 + /** Switch: scramble private field names. 1.79 + */ 1.80 + private boolean scramble; 1.81 + 1.82 + /** Switch: scramble all field names. 1.83 + */ 1.84 + private boolean scrambleAll; 1.85 + 1.86 + /** Switch: retrofit mode. 1.87 + */ 1.88 + private boolean retrofit; 1.89 + 1.90 + /** Switch: emit source file attribute. 1.91 + */ 1.92 + private boolean emitSourceFile; 1.93 + 1.94 + /** Switch: generate CharacterRangeTable attribute. 1.95 + */ 1.96 + private boolean genCrt; 1.97 + 1.98 + /** Switch: describe the generated stackmap. 1.99 + */ 1.100 + boolean debugstackmap; 1.101 + 1.102 + /** 1.103 + * Target class version. 1.104 + */ 1.105 + private Target target; 1.106 + 1.107 + /** 1.108 + * Source language version. 1.109 + */ 1.110 + private Source source; 1.111 + 1.112 + /** Type utilities. */ 1.113 + private Types types; 1.114 + 1.115 + /** The initial sizes of the data and constant pool buffers. 1.116 + * Sizes are increased when buffers get full. 1.117 + */ 1.118 + static final int DATA_BUF_SIZE = 0x0fff0; 1.119 + static final int POOL_BUF_SIZE = 0x1fff0; 1.120 + 1.121 + /** An output buffer for member info. 1.122 + */ 1.123 + ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE); 1.124 + 1.125 + /** An output buffer for the constant pool. 1.126 + */ 1.127 + ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE); 1.128 + 1.129 + /** The constant pool. 1.130 + */ 1.131 + Pool pool; 1.132 + 1.133 + /** The inner classes to be written, as a set. 1.134 + */ 1.135 + Set<ClassSymbol> innerClasses; 1.136 + 1.137 + /** The inner classes to be written, as a queue where 1.138 + * enclosing classes come first. 1.139 + */ 1.140 + ListBuffer<ClassSymbol> innerClassesQueue; 1.141 + 1.142 + /** The bootstrap methods to be written in the corresponding class attribute 1.143 + * (one for each invokedynamic) 1.144 + */ 1.145 + Map<DynamicMethod, MethodHandle> bootstrapMethods; 1.146 + 1.147 + /** The log to use for verbose output. 1.148 + */ 1.149 + private final Log log; 1.150 + 1.151 + /** The name table. */ 1.152 + private final Names names; 1.153 + 1.154 + /** Access to files. */ 1.155 + private final JavaFileManager fileManager; 1.156 + 1.157 + /** Sole signature generator */ 1.158 + private final CWSignatureGenerator signatureGen; 1.159 + 1.160 + /** The tags and constants used in compressed stackmap. */ 1.161 + static final int SAME_FRAME_SIZE = 64; 1.162 + static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; 1.163 + static final int SAME_FRAME_EXTENDED = 251; 1.164 + static final int FULL_FRAME = 255; 1.165 + static final int MAX_LOCAL_LENGTH_DIFF = 4; 1.166 + 1.167 + /** Get the ClassWriter instance for this context. */ 1.168 + public static ClassWriter instance(Context context) { 1.169 + ClassWriter instance = context.get(classWriterKey); 1.170 + if (instance == null) 1.171 + instance = new ClassWriter(context); 1.172 + return instance; 1.173 + } 1.174 + 1.175 + /** Construct a class writer, given an options table. 1.176 + */ 1.177 + protected ClassWriter(Context context) { 1.178 + context.put(classWriterKey, this); 1.179 + 1.180 + log = Log.instance(context); 1.181 + names = Names.instance(context); 1.182 + options = Options.instance(context); 1.183 + target = Target.instance(context); 1.184 + source = Source.instance(context); 1.185 + types = Types.instance(context); 1.186 + fileManager = context.get(JavaFileManager.class); 1.187 + signatureGen = new CWSignatureGenerator(types); 1.188 + 1.189 + verbose = options.isSet(VERBOSE); 1.190 + scramble = options.isSet("-scramble"); 1.191 + scrambleAll = options.isSet("-scrambleAll"); 1.192 + retrofit = options.isSet("-retrofit"); 1.193 + genCrt = options.isSet(XJCOV); 1.194 + debugstackmap = options.isSet("debugstackmap"); 1.195 + 1.196 + emitSourceFile = options.isUnset(G_CUSTOM) || 1.197 + options.isSet(G_CUSTOM, "source"); 1.198 + 1.199 + String dumpModFlags = options.get("dumpmodifiers"); 1.200 + dumpClassModifiers = 1.201 + (dumpModFlags != null && dumpModFlags.indexOf('c') != -1); 1.202 + dumpFieldModifiers = 1.203 + (dumpModFlags != null && dumpModFlags.indexOf('f') != -1); 1.204 + dumpInnerClassModifiers = 1.205 + (dumpModFlags != null && dumpModFlags.indexOf('i') != -1); 1.206 + dumpMethodModifiers = 1.207 + (dumpModFlags != null && dumpModFlags.indexOf('m') != -1); 1.208 + } 1.209 + 1.210 +/****************************************************************** 1.211 + * Diagnostics: dump generated class names and modifiers 1.212 + ******************************************************************/ 1.213 + 1.214 + /** Value of option 'dumpmodifiers' is a string 1.215 + * indicating which modifiers should be dumped for debugging: 1.216 + * 'c' -- classes 1.217 + * 'f' -- fields 1.218 + * 'i' -- innerclass attributes 1.219 + * 'm' -- methods 1.220 + * For example, to dump everything: 1.221 + * javac -XDdumpmodifiers=cifm MyProg.java 1.222 + */ 1.223 + private final boolean dumpClassModifiers; // -XDdumpmodifiers=c 1.224 + private final boolean dumpFieldModifiers; // -XDdumpmodifiers=f 1.225 + private final boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i 1.226 + private final boolean dumpMethodModifiers; // -XDdumpmodifiers=m 1.227 + 1.228 + 1.229 + /** Return flags as a string, separated by " ". 1.230 + */ 1.231 + public static String flagNames(long flags) { 1.232 + StringBuilder sbuf = new StringBuilder(); 1.233 + int i = 0; 1.234 + long f = flags & StandardFlags; 1.235 + while (f != 0) { 1.236 + if ((f & 1) != 0) { 1.237 + sbuf.append(" "); 1.238 + sbuf.append(flagName[i]); 1.239 + } 1.240 + f = f >> 1; 1.241 + i++; 1.242 + } 1.243 + return sbuf.toString(); 1.244 + } 1.245 + //where 1.246 + private final static String[] flagName = { 1.247 + "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL", 1.248 + "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE", 1.249 + "ABSTRACT", "STRICTFP"}; 1.250 + 1.251 +/****************************************************************** 1.252 + * Output routines 1.253 + ******************************************************************/ 1.254 + 1.255 + /** Write a character into given byte buffer; 1.256 + * byte buffer will not be grown. 1.257 + */ 1.258 + void putChar(ByteBuffer buf, int op, int x) { 1.259 + buf.elems[op ] = (byte)((x >> 8) & 0xFF); 1.260 + buf.elems[op+1] = (byte)((x ) & 0xFF); 1.261 + } 1.262 + 1.263 + /** Write an integer into given byte buffer; 1.264 + * byte buffer will not be grown. 1.265 + */ 1.266 + void putInt(ByteBuffer buf, int adr, int x) { 1.267 + buf.elems[adr ] = (byte)((x >> 24) & 0xFF); 1.268 + buf.elems[adr+1] = (byte)((x >> 16) & 0xFF); 1.269 + buf.elems[adr+2] = (byte)((x >> 8) & 0xFF); 1.270 + buf.elems[adr+3] = (byte)((x ) & 0xFF); 1.271 + } 1.272 + 1.273 + /** 1.274 + * Signature Generation 1.275 + */ 1.276 + private class CWSignatureGenerator extends Types.SignatureGenerator { 1.277 + 1.278 + /** 1.279 + * An output buffer for type signatures. 1.280 + */ 1.281 + ByteBuffer sigbuf = new ByteBuffer(); 1.282 + 1.283 + CWSignatureGenerator(Types types) { 1.284 + super(types); 1.285 + } 1.286 + 1.287 + /** 1.288 + * Assemble signature of given type in string buffer. 1.289 + * Check for uninitialized types before calling the general case. 1.290 + */ 1.291 + @Override 1.292 + public void assembleSig(Type type) { 1.293 + type = type.unannotatedType(); 1.294 + switch (type.getTag()) { 1.295 + case UNINITIALIZED_THIS: 1.296 + case UNINITIALIZED_OBJECT: 1.297 + // we don't yet have a spec for uninitialized types in the 1.298 + // local variable table 1.299 + assembleSig(types.erasure(((UninitializedType)type).qtype)); 1.300 + break; 1.301 + default: 1.302 + super.assembleSig(type); 1.303 + } 1.304 + } 1.305 + 1.306 + @Override 1.307 + protected void append(char ch) { 1.308 + sigbuf.appendByte(ch); 1.309 + } 1.310 + 1.311 + @Override 1.312 + protected void append(byte[] ba) { 1.313 + sigbuf.appendBytes(ba); 1.314 + } 1.315 + 1.316 + @Override 1.317 + protected void append(Name name) { 1.318 + sigbuf.appendName(name); 1.319 + } 1.320 + 1.321 + @Override 1.322 + protected void classReference(ClassSymbol c) { 1.323 + enterInner(c); 1.324 + } 1.325 + 1.326 + private void reset() { 1.327 + sigbuf.reset(); 1.328 + } 1.329 + 1.330 + private Name toName() { 1.331 + return sigbuf.toName(names); 1.332 + } 1.333 + 1.334 + private boolean isEmpty() { 1.335 + return sigbuf.length == 0; 1.336 + } 1.337 + } 1.338 + 1.339 + /** 1.340 + * Return signature of given type 1.341 + */ 1.342 + Name typeSig(Type type) { 1.343 + Assert.check(signatureGen.isEmpty()); 1.344 + //- System.out.println(" ? " + type); 1.345 + signatureGen.assembleSig(type); 1.346 + Name n = signatureGen.toName(); 1.347 + signatureGen.reset(); 1.348 + //- System.out.println(" " + n); 1.349 + return n; 1.350 + } 1.351 + 1.352 + /** Given a type t, return the extended class name of its erasure in 1.353 + * external representation. 1.354 + */ 1.355 + public Name xClassName(Type t) { 1.356 + if (t.hasTag(CLASS)) { 1.357 + return names.fromUtf(externalize(t.tsym.flatName())); 1.358 + } else if (t.hasTag(ARRAY)) { 1.359 + return typeSig(types.erasure(t)); 1.360 + } else { 1.361 + throw new AssertionError("xClassName"); 1.362 + } 1.363 + } 1.364 + 1.365 +/****************************************************************** 1.366 + * Writing the Constant Pool 1.367 + ******************************************************************/ 1.368 + 1.369 + /** Thrown when the constant pool is over full. 1.370 + */ 1.371 + public static class PoolOverflow extends Exception { 1.372 + private static final long serialVersionUID = 0; 1.373 + public PoolOverflow() {} 1.374 + } 1.375 + public static class StringOverflow extends Exception { 1.376 + private static final long serialVersionUID = 0; 1.377 + public final String value; 1.378 + public StringOverflow(String s) { 1.379 + value = s; 1.380 + } 1.381 + } 1.382 + 1.383 + /** Write constant pool to pool buffer. 1.384 + * Note: during writing, constant pool 1.385 + * might grow since some parts of constants still need to be entered. 1.386 + */ 1.387 + void writePool(Pool pool) throws PoolOverflow, StringOverflow { 1.388 + int poolCountIdx = poolbuf.length; 1.389 + poolbuf.appendChar(0); 1.390 + int i = 1; 1.391 + while (i < pool.pp) { 1.392 + Object value = pool.pool[i]; 1.393 + Assert.checkNonNull(value); 1.394 + if (value instanceof Method || value instanceof Variable) 1.395 + value = ((DelegatedSymbol)value).getUnderlyingSymbol(); 1.396 + 1.397 + if (value instanceof MethodSymbol) { 1.398 + MethodSymbol m = (MethodSymbol)value; 1.399 + if (!m.isDynamic()) { 1.400 + poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0 1.401 + ? CONSTANT_InterfaceMethodref 1.402 + : CONSTANT_Methodref); 1.403 + poolbuf.appendChar(pool.put(m.owner)); 1.404 + poolbuf.appendChar(pool.put(nameType(m))); 1.405 + } else { 1.406 + //invokedynamic 1.407 + DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m; 1.408 + MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types); 1.409 + DynamicMethod dynMeth = new DynamicMethod(dynSym, types); 1.410 + bootstrapMethods.put(dynMeth, handle); 1.411 + //init cp entries 1.412 + pool.put(names.BootstrapMethods); 1.413 + pool.put(handle); 1.414 + for (Object staticArg : dynSym.staticArgs) { 1.415 + pool.put(staticArg); 1.416 + } 1.417 + poolbuf.appendByte(CONSTANT_InvokeDynamic); 1.418 + poolbuf.appendChar(bootstrapMethods.size() - 1); 1.419 + poolbuf.appendChar(pool.put(nameType(dynSym))); 1.420 + } 1.421 + } else if (value instanceof VarSymbol) { 1.422 + VarSymbol v = (VarSymbol)value; 1.423 + poolbuf.appendByte(CONSTANT_Fieldref); 1.424 + poolbuf.appendChar(pool.put(v.owner)); 1.425 + poolbuf.appendChar(pool.put(nameType(v))); 1.426 + } else if (value instanceof Name) { 1.427 + poolbuf.appendByte(CONSTANT_Utf8); 1.428 + byte[] bs = ((Name)value).toUtf(); 1.429 + poolbuf.appendChar(bs.length); 1.430 + poolbuf.appendBytes(bs, 0, bs.length); 1.431 + if (bs.length > Pool.MAX_STRING_LENGTH) 1.432 + throw new StringOverflow(value.toString()); 1.433 + } else if (value instanceof ClassSymbol) { 1.434 + ClassSymbol c = (ClassSymbol)value; 1.435 + if (c.owner.kind == TYP) pool.put(c.owner); 1.436 + poolbuf.appendByte(CONSTANT_Class); 1.437 + if (c.type.hasTag(ARRAY)) { 1.438 + poolbuf.appendChar(pool.put(typeSig(c.type))); 1.439 + } else { 1.440 + poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname)))); 1.441 + enterInner(c); 1.442 + } 1.443 + } else if (value instanceof NameAndType) { 1.444 + NameAndType nt = (NameAndType)value; 1.445 + poolbuf.appendByte(CONSTANT_NameandType); 1.446 + poolbuf.appendChar(pool.put(nt.name)); 1.447 + poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type))); 1.448 + } else if (value instanceof Integer) { 1.449 + poolbuf.appendByte(CONSTANT_Integer); 1.450 + poolbuf.appendInt(((Integer)value).intValue()); 1.451 + } else if (value instanceof Long) { 1.452 + poolbuf.appendByte(CONSTANT_Long); 1.453 + poolbuf.appendLong(((Long)value).longValue()); 1.454 + i++; 1.455 + } else if (value instanceof Float) { 1.456 + poolbuf.appendByte(CONSTANT_Float); 1.457 + poolbuf.appendFloat(((Float)value).floatValue()); 1.458 + } else if (value instanceof Double) { 1.459 + poolbuf.appendByte(CONSTANT_Double); 1.460 + poolbuf.appendDouble(((Double)value).doubleValue()); 1.461 + i++; 1.462 + } else if (value instanceof String) { 1.463 + poolbuf.appendByte(CONSTANT_String); 1.464 + poolbuf.appendChar(pool.put(names.fromString((String)value))); 1.465 + } else if (value instanceof UniqueType) { 1.466 + Type type = ((UniqueType)value).type; 1.467 + if (type instanceof MethodType) { 1.468 + poolbuf.appendByte(CONSTANT_MethodType); 1.469 + poolbuf.appendChar(pool.put(typeSig((MethodType)type))); 1.470 + } else { 1.471 + if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym); 1.472 + poolbuf.appendByte(CONSTANT_Class); 1.473 + poolbuf.appendChar(pool.put(xClassName(type))); 1.474 + } 1.475 + } else if (value instanceof MethodHandle) { 1.476 + MethodHandle ref = (MethodHandle)value; 1.477 + poolbuf.appendByte(CONSTANT_MethodHandle); 1.478 + poolbuf.appendByte(ref.refKind); 1.479 + poolbuf.appendChar(pool.put(ref.refSym)); 1.480 + } else { 1.481 + Assert.error("writePool " + value); 1.482 + } 1.483 + i++; 1.484 + } 1.485 + if (pool.pp > Pool.MAX_ENTRIES) 1.486 + throw new PoolOverflow(); 1.487 + putChar(poolbuf, poolCountIdx, pool.pp); 1.488 + } 1.489 + 1.490 + /** Given a field, return its name. 1.491 + */ 1.492 + Name fieldName(Symbol sym) { 1.493 + if (scramble && (sym.flags() & PRIVATE) != 0 || 1.494 + scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0) 1.495 + return names.fromString("_$" + sym.name.getIndex()); 1.496 + else 1.497 + return sym.name; 1.498 + } 1.499 + 1.500 + /** Given a symbol, return its name-and-type. 1.501 + */ 1.502 + NameAndType nameType(Symbol sym) { 1.503 + return new NameAndType(fieldName(sym), 1.504 + retrofit 1.505 + ? sym.erasure(types) 1.506 + : sym.externalType(types), types); 1.507 + // if we retrofit, then the NameAndType has been read in as is 1.508 + // and no change is necessary. If we compile normally, the 1.509 + // NameAndType is generated from a symbol reference, and the 1.510 + // adjustment of adding an additional this$n parameter needs to be made. 1.511 + } 1.512 + 1.513 +/****************************************************************** 1.514 + * Writing Attributes 1.515 + ******************************************************************/ 1.516 + 1.517 + /** Write header for an attribute to data buffer and return 1.518 + * position past attribute length index. 1.519 + */ 1.520 + int writeAttr(Name attrName) { 1.521 + databuf.appendChar(pool.put(attrName)); 1.522 + databuf.appendInt(0); 1.523 + return databuf.length; 1.524 + } 1.525 + 1.526 + /** Fill in attribute length. 1.527 + */ 1.528 + void endAttr(int index) { 1.529 + putInt(databuf, index - 4, databuf.length - index); 1.530 + } 1.531 + 1.532 + /** Leave space for attribute count and return index for 1.533 + * number of attributes field. 1.534 + */ 1.535 + int beginAttrs() { 1.536 + databuf.appendChar(0); 1.537 + return databuf.length; 1.538 + } 1.539 + 1.540 + /** Fill in number of attributes. 1.541 + */ 1.542 + void endAttrs(int index, int count) { 1.543 + putChar(databuf, index - 2, count); 1.544 + } 1.545 + 1.546 + /** Write the EnclosingMethod attribute if needed. 1.547 + * Returns the number of attributes written (0 or 1). 1.548 + */ 1.549 + int writeEnclosingMethodAttribute(ClassSymbol c) { 1.550 + if (!target.hasEnclosingMethodAttribute()) 1.551 + return 0; 1.552 + return writeEnclosingMethodAttribute(names.EnclosingMethod, c); 1.553 + } 1.554 + 1.555 + /** Write the EnclosingMethod attribute with a specified name. 1.556 + * Returns the number of attributes written (0 or 1). 1.557 + */ 1.558 + protected int writeEnclosingMethodAttribute(Name attributeName, ClassSymbol c) { 1.559 + if (c.owner.kind != MTH && // neither a local class 1.560 + c.name != names.empty) // nor anonymous 1.561 + return 0; 1.562 + 1.563 + int alenIdx = writeAttr(attributeName); 1.564 + ClassSymbol enclClass = c.owner.enclClass(); 1.565 + MethodSymbol enclMethod = 1.566 + (c.owner.type == null // local to init block 1.567 + || c.owner.kind != MTH) // or member init 1.568 + ? null 1.569 + : (MethodSymbol)c.owner; 1.570 + databuf.appendChar(pool.put(enclClass)); 1.571 + databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner))); 1.572 + endAttr(alenIdx); 1.573 + return 1; 1.574 + } 1.575 + 1.576 + /** Write flag attributes; return number of attributes written. 1.577 + */ 1.578 + int writeFlagAttrs(long flags) { 1.579 + int acount = 0; 1.580 + if ((flags & DEPRECATED) != 0) { 1.581 + int alenIdx = writeAttr(names.Deprecated); 1.582 + endAttr(alenIdx); 1.583 + acount++; 1.584 + } 1.585 + if ((flags & ENUM) != 0 && !target.useEnumFlag()) { 1.586 + int alenIdx = writeAttr(names.Enum); 1.587 + endAttr(alenIdx); 1.588 + acount++; 1.589 + } 1.590 + if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) { 1.591 + int alenIdx = writeAttr(names.Synthetic); 1.592 + endAttr(alenIdx); 1.593 + acount++; 1.594 + } 1.595 + if ((flags & BRIDGE) != 0 && !target.useBridgeFlag()) { 1.596 + int alenIdx = writeAttr(names.Bridge); 1.597 + endAttr(alenIdx); 1.598 + acount++; 1.599 + } 1.600 + if ((flags & VARARGS) != 0 && !target.useVarargsFlag()) { 1.601 + int alenIdx = writeAttr(names.Varargs); 1.602 + endAttr(alenIdx); 1.603 + acount++; 1.604 + } 1.605 + if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) { 1.606 + int alenIdx = writeAttr(names.Annotation); 1.607 + endAttr(alenIdx); 1.608 + acount++; 1.609 + } 1.610 + return acount; 1.611 + } 1.612 + 1.613 + /** Write member (field or method) attributes; 1.614 + * return number of attributes written. 1.615 + */ 1.616 + int writeMemberAttrs(Symbol sym) { 1.617 + int acount = writeFlagAttrs(sym.flags()); 1.618 + long flags = sym.flags(); 1.619 + if (source.allowGenerics() && 1.620 + (flags & (SYNTHETIC|BRIDGE)) != SYNTHETIC && 1.621 + (flags & ANONCONSTR) == 0 && 1.622 + (!types.isSameType(sym.type, sym.erasure(types)) || 1.623 + signatureGen.hasTypeVar(sym.type.getThrownTypes()))) { 1.624 + // note that a local class with captured variables 1.625 + // will get a signature attribute 1.626 + int alenIdx = writeAttr(names.Signature); 1.627 + databuf.appendChar(pool.put(typeSig(sym.type))); 1.628 + endAttr(alenIdx); 1.629 + acount++; 1.630 + } 1.631 + acount += writeJavaAnnotations(sym.getRawAttributes()); 1.632 + acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false); 1.633 + return acount; 1.634 + } 1.635 + 1.636 + /** 1.637 + * Write method parameter names attribute. 1.638 + */ 1.639 + int writeMethodParametersAttr(MethodSymbol m) { 1.640 + MethodType ty = m.externalType(types).asMethodType(); 1.641 + final int allparams = ty.argtypes.size(); 1.642 + if (m.params != null && allparams != 0) { 1.643 + final int attrIndex = writeAttr(names.MethodParameters); 1.644 + databuf.appendByte(allparams); 1.645 + // Write extra parameters first 1.646 + for (VarSymbol s : m.extraParams) { 1.647 + final int flags = 1.648 + ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | 1.649 + ((int) m.flags() & SYNTHETIC); 1.650 + databuf.appendChar(pool.put(s.name)); 1.651 + databuf.appendChar(flags); 1.652 + } 1.653 + // Now write the real parameters 1.654 + for (VarSymbol s : m.params) { 1.655 + final int flags = 1.656 + ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | 1.657 + ((int) m.flags() & SYNTHETIC); 1.658 + databuf.appendChar(pool.put(s.name)); 1.659 + databuf.appendChar(flags); 1.660 + } 1.661 + // Now write the captured locals 1.662 + for (VarSymbol s : m.capturedLocals) { 1.663 + final int flags = 1.664 + ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | 1.665 + ((int) m.flags() & SYNTHETIC); 1.666 + databuf.appendChar(pool.put(s.name)); 1.667 + databuf.appendChar(flags); 1.668 + } 1.669 + endAttr(attrIndex); 1.670 + return 1; 1.671 + } else 1.672 + return 0; 1.673 + } 1.674 + 1.675 + 1.676 + /** Write method parameter annotations; 1.677 + * return number of attributes written. 1.678 + */ 1.679 + int writeParameterAttrs(MethodSymbol m) { 1.680 + boolean hasVisible = false; 1.681 + boolean hasInvisible = false; 1.682 + if (m.params != null) { 1.683 + for (VarSymbol s : m.params) { 1.684 + for (Attribute.Compound a : s.getRawAttributes()) { 1.685 + switch (types.getRetention(a)) { 1.686 + case SOURCE: break; 1.687 + case CLASS: hasInvisible = true; break; 1.688 + case RUNTIME: hasVisible = true; break; 1.689 + default: ;// /* fail soft */ throw new AssertionError(vis); 1.690 + } 1.691 + } 1.692 + } 1.693 + } 1.694 + 1.695 + int attrCount = 0; 1.696 + if (hasVisible) { 1.697 + int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations); 1.698 + databuf.appendByte(m.params.length()); 1.699 + for (VarSymbol s : m.params) { 1.700 + ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); 1.701 + for (Attribute.Compound a : s.getRawAttributes()) 1.702 + if (types.getRetention(a) == RetentionPolicy.RUNTIME) 1.703 + buf.append(a); 1.704 + databuf.appendChar(buf.length()); 1.705 + for (Attribute.Compound a : buf) 1.706 + writeCompoundAttribute(a); 1.707 + } 1.708 + endAttr(attrIndex); 1.709 + attrCount++; 1.710 + } 1.711 + if (hasInvisible) { 1.712 + int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations); 1.713 + databuf.appendByte(m.params.length()); 1.714 + for (VarSymbol s : m.params) { 1.715 + ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); 1.716 + for (Attribute.Compound a : s.getRawAttributes()) 1.717 + if (types.getRetention(a) == RetentionPolicy.CLASS) 1.718 + buf.append(a); 1.719 + databuf.appendChar(buf.length()); 1.720 + for (Attribute.Compound a : buf) 1.721 + writeCompoundAttribute(a); 1.722 + } 1.723 + endAttr(attrIndex); 1.724 + attrCount++; 1.725 + } 1.726 + return attrCount; 1.727 + } 1.728 + 1.729 +/********************************************************************** 1.730 + * Writing Java-language annotations (aka metadata, attributes) 1.731 + **********************************************************************/ 1.732 + 1.733 + /** Write Java-language annotations; return number of JVM 1.734 + * attributes written (zero or one). 1.735 + */ 1.736 + int writeJavaAnnotations(List<Attribute.Compound> attrs) { 1.737 + if (attrs.isEmpty()) return 0; 1.738 + ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>(); 1.739 + ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>(); 1.740 + for (Attribute.Compound a : attrs) { 1.741 + switch (types.getRetention(a)) { 1.742 + case SOURCE: break; 1.743 + case CLASS: invisibles.append(a); break; 1.744 + case RUNTIME: visibles.append(a); break; 1.745 + default: ;// /* fail soft */ throw new AssertionError(vis); 1.746 + } 1.747 + } 1.748 + 1.749 + int attrCount = 0; 1.750 + if (visibles.length() != 0) { 1.751 + int attrIndex = writeAttr(names.RuntimeVisibleAnnotations); 1.752 + databuf.appendChar(visibles.length()); 1.753 + for (Attribute.Compound a : visibles) 1.754 + writeCompoundAttribute(a); 1.755 + endAttr(attrIndex); 1.756 + attrCount++; 1.757 + } 1.758 + if (invisibles.length() != 0) { 1.759 + int attrIndex = writeAttr(names.RuntimeInvisibleAnnotations); 1.760 + databuf.appendChar(invisibles.length()); 1.761 + for (Attribute.Compound a : invisibles) 1.762 + writeCompoundAttribute(a); 1.763 + endAttr(attrIndex); 1.764 + attrCount++; 1.765 + } 1.766 + return attrCount; 1.767 + } 1.768 + 1.769 + int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos, boolean inCode) { 1.770 + if (typeAnnos.isEmpty()) return 0; 1.771 + 1.772 + ListBuffer<Attribute.TypeCompound> visibles = new ListBuffer<>(); 1.773 + ListBuffer<Attribute.TypeCompound> invisibles = new ListBuffer<>(); 1.774 + 1.775 + for (Attribute.TypeCompound tc : typeAnnos) { 1.776 + if (tc.hasUnknownPosition()) { 1.777 + boolean fixed = tc.tryFixPosition(); 1.778 + 1.779 + // Could we fix it? 1.780 + if (!fixed) { 1.781 + // This happens for nested types like @A Outer. @B Inner. 1.782 + // For method parameters we get the annotation twice! Once with 1.783 + // a valid position, once unknown. 1.784 + // TODO: find a cleaner solution. 1.785 + PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); 1.786 + pw.println("ClassWriter: Position UNKNOWN in type annotation: " + tc); 1.787 + continue; 1.788 + } 1.789 + } 1.790 + 1.791 + if (tc.position.type.isLocal() != inCode) 1.792 + continue; 1.793 + if (!tc.position.emitToClassfile()) 1.794 + continue; 1.795 + switch (types.getRetention(tc)) { 1.796 + case SOURCE: break; 1.797 + case CLASS: invisibles.append(tc); break; 1.798 + case RUNTIME: visibles.append(tc); break; 1.799 + default: ;// /* fail soft */ throw new AssertionError(vis); 1.800 + } 1.801 + } 1.802 + 1.803 + int attrCount = 0; 1.804 + if (visibles.length() != 0) { 1.805 + int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations); 1.806 + databuf.appendChar(visibles.length()); 1.807 + for (Attribute.TypeCompound p : visibles) 1.808 + writeTypeAnnotation(p); 1.809 + endAttr(attrIndex); 1.810 + attrCount++; 1.811 + } 1.812 + 1.813 + if (invisibles.length() != 0) { 1.814 + int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations); 1.815 + databuf.appendChar(invisibles.length()); 1.816 + for (Attribute.TypeCompound p : invisibles) 1.817 + writeTypeAnnotation(p); 1.818 + endAttr(attrIndex); 1.819 + attrCount++; 1.820 + } 1.821 + 1.822 + return attrCount; 1.823 + } 1.824 + 1.825 + /** A visitor to write an attribute including its leading 1.826 + * single-character marker. 1.827 + */ 1.828 + class AttributeWriter implements Attribute.Visitor { 1.829 + public void visitConstant(Attribute.Constant _value) { 1.830 + Object value = _value.value; 1.831 + switch (_value.type.getTag()) { 1.832 + case BYTE: 1.833 + databuf.appendByte('B'); 1.834 + break; 1.835 + case CHAR: 1.836 + databuf.appendByte('C'); 1.837 + break; 1.838 + case SHORT: 1.839 + databuf.appendByte('S'); 1.840 + break; 1.841 + case INT: 1.842 + databuf.appendByte('I'); 1.843 + break; 1.844 + case LONG: 1.845 + databuf.appendByte('J'); 1.846 + break; 1.847 + case FLOAT: 1.848 + databuf.appendByte('F'); 1.849 + break; 1.850 + case DOUBLE: 1.851 + databuf.appendByte('D'); 1.852 + break; 1.853 + case BOOLEAN: 1.854 + databuf.appendByte('Z'); 1.855 + break; 1.856 + case CLASS: 1.857 + Assert.check(value instanceof String); 1.858 + databuf.appendByte('s'); 1.859 + value = names.fromString(value.toString()); // CONSTANT_Utf8 1.860 + break; 1.861 + default: 1.862 + throw new AssertionError(_value.type); 1.863 + } 1.864 + databuf.appendChar(pool.put(value)); 1.865 + } 1.866 + public void visitEnum(Attribute.Enum e) { 1.867 + databuf.appendByte('e'); 1.868 + databuf.appendChar(pool.put(typeSig(e.value.type))); 1.869 + databuf.appendChar(pool.put(e.value.name)); 1.870 + } 1.871 + public void visitClass(Attribute.Class clazz) { 1.872 + databuf.appendByte('c'); 1.873 + databuf.appendChar(pool.put(typeSig(clazz.classType))); 1.874 + } 1.875 + public void visitCompound(Attribute.Compound compound) { 1.876 + databuf.appendByte('@'); 1.877 + writeCompoundAttribute(compound); 1.878 + } 1.879 + public void visitError(Attribute.Error x) { 1.880 + throw new AssertionError(x); 1.881 + } 1.882 + public void visitArray(Attribute.Array array) { 1.883 + databuf.appendByte('['); 1.884 + databuf.appendChar(array.values.length); 1.885 + for (Attribute a : array.values) { 1.886 + a.accept(this); 1.887 + } 1.888 + } 1.889 + } 1.890 + AttributeWriter awriter = new AttributeWriter(); 1.891 + 1.892 + /** Write a compound attribute excluding the '@' marker. */ 1.893 + void writeCompoundAttribute(Attribute.Compound c) { 1.894 + databuf.appendChar(pool.put(typeSig(c.type))); 1.895 + databuf.appendChar(c.values.length()); 1.896 + for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) { 1.897 + databuf.appendChar(pool.put(p.fst.name)); 1.898 + p.snd.accept(awriter); 1.899 + } 1.900 + } 1.901 + 1.902 + void writeTypeAnnotation(Attribute.TypeCompound c) { 1.903 + writePosition(c.position); 1.904 + writeCompoundAttribute(c); 1.905 + } 1.906 + 1.907 + void writePosition(TypeAnnotationPosition p) { 1.908 + databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte 1.909 + switch (p.type) { 1.910 + // instanceof 1.911 + case INSTANCEOF: 1.912 + // new expression 1.913 + case NEW: 1.914 + // constructor/method reference receiver 1.915 + case CONSTRUCTOR_REFERENCE: 1.916 + case METHOD_REFERENCE: 1.917 + databuf.appendChar(p.offset); 1.918 + break; 1.919 + // local variable 1.920 + case LOCAL_VARIABLE: 1.921 + // resource variable 1.922 + case RESOURCE_VARIABLE: 1.923 + databuf.appendChar(p.lvarOffset.length); // for table length 1.924 + for (int i = 0; i < p.lvarOffset.length; ++i) { 1.925 + databuf.appendChar(p.lvarOffset[i]); 1.926 + databuf.appendChar(p.lvarLength[i]); 1.927 + databuf.appendChar(p.lvarIndex[i]); 1.928 + } 1.929 + break; 1.930 + // exception parameter 1.931 + case EXCEPTION_PARAMETER: 1.932 + databuf.appendChar(p.exception_index); 1.933 + break; 1.934 + // method receiver 1.935 + case METHOD_RECEIVER: 1.936 + // Do nothing 1.937 + break; 1.938 + // type parameter 1.939 + case CLASS_TYPE_PARAMETER: 1.940 + case METHOD_TYPE_PARAMETER: 1.941 + databuf.appendByte(p.parameter_index); 1.942 + break; 1.943 + // type parameter bound 1.944 + case CLASS_TYPE_PARAMETER_BOUND: 1.945 + case METHOD_TYPE_PARAMETER_BOUND: 1.946 + databuf.appendByte(p.parameter_index); 1.947 + databuf.appendByte(p.bound_index); 1.948 + break; 1.949 + // class extends or implements clause 1.950 + case CLASS_EXTENDS: 1.951 + databuf.appendChar(p.type_index); 1.952 + break; 1.953 + // throws 1.954 + case THROWS: 1.955 + databuf.appendChar(p.type_index); 1.956 + break; 1.957 + // method parameter 1.958 + case METHOD_FORMAL_PARAMETER: 1.959 + databuf.appendByte(p.parameter_index); 1.960 + break; 1.961 + // type cast 1.962 + case CAST: 1.963 + // method/constructor/reference type argument 1.964 + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: 1.965 + case METHOD_INVOCATION_TYPE_ARGUMENT: 1.966 + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: 1.967 + case METHOD_REFERENCE_TYPE_ARGUMENT: 1.968 + databuf.appendChar(p.offset); 1.969 + databuf.appendByte(p.type_index); 1.970 + break; 1.971 + // We don't need to worry about these 1.972 + case METHOD_RETURN: 1.973 + case FIELD: 1.974 + break; 1.975 + case UNKNOWN: 1.976 + throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!"); 1.977 + default: 1.978 + throw new AssertionError("jvm.ClassWriter: Unknown target type for position: " + p); 1.979 + } 1.980 + 1.981 + { // Append location data for generics/arrays. 1.982 + databuf.appendByte(p.location.size()); 1.983 + java.util.List<Integer> loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location); 1.984 + for (int i : loc) 1.985 + databuf.appendByte((byte)i); 1.986 + } 1.987 + } 1.988 + 1.989 +/********************************************************************** 1.990 + * Writing Objects 1.991 + **********************************************************************/ 1.992 + 1.993 + /** Enter an inner class into the `innerClasses' set/queue. 1.994 + */ 1.995 + void enterInner(ClassSymbol c) { 1.996 + if (c.type.isCompound()) { 1.997 + throw new AssertionError("Unexpected intersection type: " + c.type); 1.998 + } 1.999 + try { 1.1000 + c.complete(); 1.1001 + } catch (CompletionFailure ex) { 1.1002 + System.err.println("error: " + c + ": " + ex.getMessage()); 1.1003 + throw ex; 1.1004 + } 1.1005 + if (!c.type.hasTag(CLASS)) return; // arrays 1.1006 + if (pool != null && // pool might be null if called from xClassName 1.1007 + c.owner.enclClass() != null && 1.1008 + (innerClasses == null || !innerClasses.contains(c))) { 1.1009 +// log.errWriter.println("enter inner " + c);//DEBUG 1.1010 + enterInner(c.owner.enclClass()); 1.1011 + pool.put(c); 1.1012 + if (c.name != names.empty) 1.1013 + pool.put(c.name); 1.1014 + if (innerClasses == null) { 1.1015 + innerClasses = new HashSet<ClassSymbol>(); 1.1016 + innerClassesQueue = new ListBuffer<ClassSymbol>(); 1.1017 + pool.put(names.InnerClasses); 1.1018 + } 1.1019 + innerClasses.add(c); 1.1020 + innerClassesQueue.append(c); 1.1021 + } 1.1022 + } 1.1023 + 1.1024 + /** Write "inner classes" attribute. 1.1025 + */ 1.1026 + void writeInnerClasses() { 1.1027 + int alenIdx = writeAttr(names.InnerClasses); 1.1028 + databuf.appendChar(innerClassesQueue.length()); 1.1029 + for (List<ClassSymbol> l = innerClassesQueue.toList(); 1.1030 + l.nonEmpty(); 1.1031 + l = l.tail) { 1.1032 + ClassSymbol inner = l.head; 1.1033 + char flags = (char) adjustFlags(inner.flags_field); 1.1034 + if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT 1.1035 + if (inner.name.isEmpty()) flags &= ~FINAL; // Anonymous class: unset FINAL flag 1.1036 + flags &= ~STRICTFP; //inner classes should not have the strictfp flag set. 1.1037 + if (dumpInnerClassModifiers) { 1.1038 + PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); 1.1039 + pw.println("INNERCLASS " + inner.name); 1.1040 + pw.println("---" + flagNames(flags)); 1.1041 + } 1.1042 + databuf.appendChar(pool.get(inner)); 1.1043 + databuf.appendChar( 1.1044 + inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0); 1.1045 + databuf.appendChar( 1.1046 + !inner.name.isEmpty() ? pool.get(inner.name) : 0); 1.1047 + databuf.appendChar(flags); 1.1048 + } 1.1049 + endAttr(alenIdx); 1.1050 + } 1.1051 + 1.1052 + /** Write "bootstrapMethods" attribute. 1.1053 + */ 1.1054 + void writeBootstrapMethods() { 1.1055 + int alenIdx = writeAttr(names.BootstrapMethods); 1.1056 + databuf.appendChar(bootstrapMethods.size()); 1.1057 + for (Map.Entry<DynamicMethod, MethodHandle> entry : bootstrapMethods.entrySet()) { 1.1058 + DynamicMethod dmeth = entry.getKey(); 1.1059 + DynamicMethodSymbol dsym = (DynamicMethodSymbol)dmeth.baseSymbol(); 1.1060 + //write BSM handle 1.1061 + databuf.appendChar(pool.get(entry.getValue())); 1.1062 + //write static args length 1.1063 + databuf.appendChar(dsym.staticArgs.length); 1.1064 + //write static args array 1.1065 + Object[] uniqueArgs = dmeth.uniqueStaticArgs; 1.1066 + for (Object o : uniqueArgs) { 1.1067 + databuf.appendChar(pool.get(o)); 1.1068 + } 1.1069 + } 1.1070 + endAttr(alenIdx); 1.1071 + } 1.1072 + 1.1073 + /** Write field symbol, entering all references into constant pool. 1.1074 + */ 1.1075 + void writeField(VarSymbol v) { 1.1076 + int flags = adjustFlags(v.flags()); 1.1077 + databuf.appendChar(flags); 1.1078 + if (dumpFieldModifiers) { 1.1079 + PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); 1.1080 + pw.println("FIELD " + fieldName(v)); 1.1081 + pw.println("---" + flagNames(v.flags())); 1.1082 + } 1.1083 + databuf.appendChar(pool.put(fieldName(v))); 1.1084 + databuf.appendChar(pool.put(typeSig(v.erasure(types)))); 1.1085 + int acountIdx = beginAttrs(); 1.1086 + int acount = 0; 1.1087 + if (v.getConstValue() != null) { 1.1088 + int alenIdx = writeAttr(names.ConstantValue); 1.1089 + databuf.appendChar(pool.put(v.getConstValue())); 1.1090 + endAttr(alenIdx); 1.1091 + acount++; 1.1092 + } 1.1093 + acount += writeMemberAttrs(v); 1.1094 + endAttrs(acountIdx, acount); 1.1095 + } 1.1096 + 1.1097 + /** Write method symbol, entering all references into constant pool. 1.1098 + */ 1.1099 + void writeMethod(MethodSymbol m) { 1.1100 + int flags = adjustFlags(m.flags()); 1.1101 + databuf.appendChar(flags); 1.1102 + if (dumpMethodModifiers) { 1.1103 + PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); 1.1104 + pw.println("METHOD " + fieldName(m)); 1.1105 + pw.println("---" + flagNames(m.flags())); 1.1106 + } 1.1107 + databuf.appendChar(pool.put(fieldName(m))); 1.1108 + databuf.appendChar(pool.put(typeSig(m.externalType(types)))); 1.1109 + int acountIdx = beginAttrs(); 1.1110 + int acount = 0; 1.1111 + if (m.code != null) { 1.1112 + int alenIdx = writeAttr(names.Code); 1.1113 + writeCode(m.code); 1.1114 + m.code = null; // to conserve space 1.1115 + endAttr(alenIdx); 1.1116 + acount++; 1.1117 + } 1.1118 + List<Type> thrown = m.erasure(types).getThrownTypes(); 1.1119 + if (thrown.nonEmpty()) { 1.1120 + int alenIdx = writeAttr(names.Exceptions); 1.1121 + databuf.appendChar(thrown.length()); 1.1122 + for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1.1123 + databuf.appendChar(pool.put(l.head.tsym)); 1.1124 + endAttr(alenIdx); 1.1125 + acount++; 1.1126 + } 1.1127 + if (m.defaultValue != null) { 1.1128 + int alenIdx = writeAttr(names.AnnotationDefault); 1.1129 + m.defaultValue.accept(awriter); 1.1130 + endAttr(alenIdx); 1.1131 + acount++; 1.1132 + } 1.1133 + if (options.isSet(PARAMETERS)) 1.1134 + acount += writeMethodParametersAttr(m); 1.1135 + acount += writeMemberAttrs(m); 1.1136 + acount += writeParameterAttrs(m); 1.1137 + endAttrs(acountIdx, acount); 1.1138 + } 1.1139 + 1.1140 + /** Write code attribute of method. 1.1141 + */ 1.1142 + void writeCode(Code code) { 1.1143 + databuf.appendChar(code.max_stack); 1.1144 + databuf.appendChar(code.max_locals); 1.1145 + databuf.appendInt(code.cp); 1.1146 + databuf.appendBytes(code.code, 0, code.cp); 1.1147 + databuf.appendChar(code.catchInfo.length()); 1.1148 + for (List<char[]> l = code.catchInfo.toList(); 1.1149 + l.nonEmpty(); 1.1150 + l = l.tail) { 1.1151 + for (int i = 0; i < l.head.length; i++) 1.1152 + databuf.appendChar(l.head[i]); 1.1153 + } 1.1154 + int acountIdx = beginAttrs(); 1.1155 + int acount = 0; 1.1156 + 1.1157 + if (code.lineInfo.nonEmpty()) { 1.1158 + int alenIdx = writeAttr(names.LineNumberTable); 1.1159 + databuf.appendChar(code.lineInfo.length()); 1.1160 + for (List<char[]> l = code.lineInfo.reverse(); 1.1161 + l.nonEmpty(); 1.1162 + l = l.tail) 1.1163 + for (int i = 0; i < l.head.length; i++) 1.1164 + databuf.appendChar(l.head[i]); 1.1165 + endAttr(alenIdx); 1.1166 + acount++; 1.1167 + } 1.1168 + 1.1169 + if (genCrt && (code.crt != null)) { 1.1170 + CRTable crt = code.crt; 1.1171 + int alenIdx = writeAttr(names.CharacterRangeTable); 1.1172 + int crtIdx = beginAttrs(); 1.1173 + int crtEntries = crt.writeCRT(databuf, code.lineMap, log); 1.1174 + endAttrs(crtIdx, crtEntries); 1.1175 + endAttr(alenIdx); 1.1176 + acount++; 1.1177 + } 1.1178 + 1.1179 + // counter for number of generic local variables 1.1180 + if (code.varDebugInfo && code.varBufferSize > 0) { 1.1181 + int nGenericVars = 0; 1.1182 + int alenIdx = writeAttr(names.LocalVariableTable); 1.1183 + databuf.appendChar(code.getLVTSize()); 1.1184 + for (int i=0; i<code.varBufferSize; i++) { 1.1185 + Code.LocalVar var = code.varBuffer[i]; 1.1186 + 1.1187 + for (Code.LocalVar.Range r: var.aliveRanges) { 1.1188 + // write variable info 1.1189 + Assert.check(r.start_pc >= 0 1.1190 + && r.start_pc <= code.cp); 1.1191 + databuf.appendChar(r.start_pc); 1.1192 + Assert.check(r.length >= 0 1.1193 + && (r.start_pc + r.length) <= code.cp); 1.1194 + databuf.appendChar(r.length); 1.1195 + VarSymbol sym = var.sym; 1.1196 + databuf.appendChar(pool.put(sym.name)); 1.1197 + Type vartype = sym.erasure(types); 1.1198 + databuf.appendChar(pool.put(typeSig(vartype))); 1.1199 + databuf.appendChar(var.reg); 1.1200 + if (needsLocalVariableTypeEntry(var.sym.type)) { 1.1201 + nGenericVars++; 1.1202 + } 1.1203 + } 1.1204 + } 1.1205 + endAttr(alenIdx); 1.1206 + acount++; 1.1207 + 1.1208 + if (nGenericVars > 0) { 1.1209 + alenIdx = writeAttr(names.LocalVariableTypeTable); 1.1210 + databuf.appendChar(nGenericVars); 1.1211 + int count = 0; 1.1212 + 1.1213 + for (int i=0; i<code.varBufferSize; i++) { 1.1214 + Code.LocalVar var = code.varBuffer[i]; 1.1215 + VarSymbol sym = var.sym; 1.1216 + if (!needsLocalVariableTypeEntry(sym.type)) 1.1217 + continue; 1.1218 + for (Code.LocalVar.Range r : var.aliveRanges) { 1.1219 + // write variable info 1.1220 + databuf.appendChar(r.start_pc); 1.1221 + databuf.appendChar(r.length); 1.1222 + databuf.appendChar(pool.put(sym.name)); 1.1223 + databuf.appendChar(pool.put(typeSig(sym.type))); 1.1224 + databuf.appendChar(var.reg); 1.1225 + count++; 1.1226 + } 1.1227 + } 1.1228 + Assert.check(count == nGenericVars); 1.1229 + endAttr(alenIdx); 1.1230 + acount++; 1.1231 + } 1.1232 + } 1.1233 + 1.1234 + if (code.stackMapBufferSize > 0) { 1.1235 + if (debugstackmap) System.out.println("Stack map for " + code.meth); 1.1236 + int alenIdx = writeAttr(code.stackMap.getAttributeName(names)); 1.1237 + writeStackMap(code); 1.1238 + endAttr(alenIdx); 1.1239 + acount++; 1.1240 + } 1.1241 + 1.1242 + acount += writeTypeAnnotations(code.meth.getRawTypeAttributes(), true); 1.1243 + 1.1244 + endAttrs(acountIdx, acount); 1.1245 + } 1.1246 + //where 1.1247 + private boolean needsLocalVariableTypeEntry(Type t) { 1.1248 + //a local variable needs a type-entry if its type T is generic 1.1249 + //(i.e. |T| != T) and if it's not an intersection type (not supported 1.1250 + //in signature attribute grammar) 1.1251 + return (!types.isSameType(t, types.erasure(t)) && 1.1252 + !t.isCompound()); 1.1253 + } 1.1254 + 1.1255 + void writeStackMap(Code code) { 1.1256 + int nframes = code.stackMapBufferSize; 1.1257 + if (debugstackmap) System.out.println(" nframes = " + nframes); 1.1258 + databuf.appendChar(nframes); 1.1259 + 1.1260 + switch (code.stackMap) { 1.1261 + case CLDC: 1.1262 + for (int i=0; i<nframes; i++) { 1.1263 + if (debugstackmap) System.out.print(" " + i + ":"); 1.1264 + Code.StackMapFrame frame = code.stackMapBuffer[i]; 1.1265 + 1.1266 + // output PC 1.1267 + if (debugstackmap) System.out.print(" pc=" + frame.pc); 1.1268 + databuf.appendChar(frame.pc); 1.1269 + 1.1270 + // output locals 1.1271 + int localCount = 0; 1.1272 + for (int j=0; j<frame.locals.length; 1.1273 + j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.locals[j]))) { 1.1274 + localCount++; 1.1275 + } 1.1276 + if (debugstackmap) System.out.print(" nlocals=" + 1.1277 + localCount); 1.1278 + databuf.appendChar(localCount); 1.1279 + for (int j=0; j<frame.locals.length; 1.1280 + j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.locals[j]))) { 1.1281 + if (debugstackmap) System.out.print(" local[" + j + "]="); 1.1282 + writeStackMapType(frame.locals[j]); 1.1283 + } 1.1284 + 1.1285 + // output stack 1.1286 + int stackCount = 0; 1.1287 + for (int j=0; j<frame.stack.length; 1.1288 + j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.stack[j]))) { 1.1289 + stackCount++; 1.1290 + } 1.1291 + if (debugstackmap) System.out.print(" nstack=" + 1.1292 + stackCount); 1.1293 + databuf.appendChar(stackCount); 1.1294 + for (int j=0; j<frame.stack.length; 1.1295 + j += (target.generateEmptyAfterBig() ? 1 : Code.width(frame.stack[j]))) { 1.1296 + if (debugstackmap) System.out.print(" stack[" + j + "]="); 1.1297 + writeStackMapType(frame.stack[j]); 1.1298 + } 1.1299 + if (debugstackmap) System.out.println(); 1.1300 + } 1.1301 + break; 1.1302 + case JSR202: { 1.1303 + Assert.checkNull(code.stackMapBuffer); 1.1304 + for (int i=0; i<nframes; i++) { 1.1305 + if (debugstackmap) System.out.print(" " + i + ":"); 1.1306 + StackMapTableFrame frame = code.stackMapTableBuffer[i]; 1.1307 + frame.write(this); 1.1308 + if (debugstackmap) System.out.println(); 1.1309 + } 1.1310 + break; 1.1311 + } 1.1312 + default: 1.1313 + throw new AssertionError("Unexpected stackmap format value"); 1.1314 + } 1.1315 + } 1.1316 + 1.1317 + //where 1.1318 + void writeStackMapType(Type t) { 1.1319 + if (t == null) { 1.1320 + if (debugstackmap) System.out.print("empty"); 1.1321 + databuf.appendByte(0); 1.1322 + } 1.1323 + else switch(t.getTag()) { 1.1324 + case BYTE: 1.1325 + case CHAR: 1.1326 + case SHORT: 1.1327 + case INT: 1.1328 + case BOOLEAN: 1.1329 + if (debugstackmap) System.out.print("int"); 1.1330 + databuf.appendByte(1); 1.1331 + break; 1.1332 + case FLOAT: 1.1333 + if (debugstackmap) System.out.print("float"); 1.1334 + databuf.appendByte(2); 1.1335 + break; 1.1336 + case DOUBLE: 1.1337 + if (debugstackmap) System.out.print("double"); 1.1338 + databuf.appendByte(3); 1.1339 + break; 1.1340 + case LONG: 1.1341 + if (debugstackmap) System.out.print("long"); 1.1342 + databuf.appendByte(4); 1.1343 + break; 1.1344 + case BOT: // null 1.1345 + if (debugstackmap) System.out.print("null"); 1.1346 + databuf.appendByte(5); 1.1347 + break; 1.1348 + case CLASS: 1.1349 + case ARRAY: 1.1350 + if (debugstackmap) System.out.print("object(" + t + ")"); 1.1351 + databuf.appendByte(7); 1.1352 + databuf.appendChar(pool.put(t)); 1.1353 + break; 1.1354 + case TYPEVAR: 1.1355 + if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")"); 1.1356 + databuf.appendByte(7); 1.1357 + databuf.appendChar(pool.put(types.erasure(t).tsym)); 1.1358 + break; 1.1359 + case UNINITIALIZED_THIS: 1.1360 + if (debugstackmap) System.out.print("uninit_this"); 1.1361 + databuf.appendByte(6); 1.1362 + break; 1.1363 + case UNINITIALIZED_OBJECT: 1.1364 + { UninitializedType uninitType = (UninitializedType)t; 1.1365 + databuf.appendByte(8); 1.1366 + if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset); 1.1367 + databuf.appendChar(uninitType.offset); 1.1368 + } 1.1369 + break; 1.1370 + default: 1.1371 + throw new AssertionError(); 1.1372 + } 1.1373 + } 1.1374 + 1.1375 + /** An entry in the JSR202 StackMapTable */ 1.1376 + abstract static class StackMapTableFrame { 1.1377 + abstract int getFrameType(); 1.1378 + 1.1379 + void write(ClassWriter writer) { 1.1380 + int frameType = getFrameType(); 1.1381 + writer.databuf.appendByte(frameType); 1.1382 + if (writer.debugstackmap) System.out.print(" frame_type=" + frameType); 1.1383 + } 1.1384 + 1.1385 + static class SameFrame extends StackMapTableFrame { 1.1386 + final int offsetDelta; 1.1387 + SameFrame(int offsetDelta) { 1.1388 + this.offsetDelta = offsetDelta; 1.1389 + } 1.1390 + int getFrameType() { 1.1391 + return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED; 1.1392 + } 1.1393 + @Override 1.1394 + void write(ClassWriter writer) { 1.1395 + super.write(writer); 1.1396 + if (getFrameType() == SAME_FRAME_EXTENDED) { 1.1397 + writer.databuf.appendChar(offsetDelta); 1.1398 + if (writer.debugstackmap){ 1.1399 + System.out.print(" offset_delta=" + offsetDelta); 1.1400 + } 1.1401 + } 1.1402 + } 1.1403 + } 1.1404 + 1.1405 + static class SameLocals1StackItemFrame extends StackMapTableFrame { 1.1406 + final int offsetDelta; 1.1407 + final Type stack; 1.1408 + SameLocals1StackItemFrame(int offsetDelta, Type stack) { 1.1409 + this.offsetDelta = offsetDelta; 1.1410 + this.stack = stack; 1.1411 + } 1.1412 + int getFrameType() { 1.1413 + return (offsetDelta < SAME_FRAME_SIZE) ? 1.1414 + (SAME_FRAME_SIZE + offsetDelta) : 1.1415 + SAME_LOCALS_1_STACK_ITEM_EXTENDED; 1.1416 + } 1.1417 + @Override 1.1418 + void write(ClassWriter writer) { 1.1419 + super.write(writer); 1.1420 + if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 1.1421 + writer.databuf.appendChar(offsetDelta); 1.1422 + if (writer.debugstackmap) { 1.1423 + System.out.print(" offset_delta=" + offsetDelta); 1.1424 + } 1.1425 + } 1.1426 + if (writer.debugstackmap) { 1.1427 + System.out.print(" stack[" + 0 + "]="); 1.1428 + } 1.1429 + writer.writeStackMapType(stack); 1.1430 + } 1.1431 + } 1.1432 + 1.1433 + static class ChopFrame extends StackMapTableFrame { 1.1434 + final int frameType; 1.1435 + final int offsetDelta; 1.1436 + ChopFrame(int frameType, int offsetDelta) { 1.1437 + this.frameType = frameType; 1.1438 + this.offsetDelta = offsetDelta; 1.1439 + } 1.1440 + int getFrameType() { return frameType; } 1.1441 + @Override 1.1442 + void write(ClassWriter writer) { 1.1443 + super.write(writer); 1.1444 + writer.databuf.appendChar(offsetDelta); 1.1445 + if (writer.debugstackmap) { 1.1446 + System.out.print(" offset_delta=" + offsetDelta); 1.1447 + } 1.1448 + } 1.1449 + } 1.1450 + 1.1451 + static class AppendFrame extends StackMapTableFrame { 1.1452 + final int frameType; 1.1453 + final int offsetDelta; 1.1454 + final Type[] locals; 1.1455 + AppendFrame(int frameType, int offsetDelta, Type[] locals) { 1.1456 + this.frameType = frameType; 1.1457 + this.offsetDelta = offsetDelta; 1.1458 + this.locals = locals; 1.1459 + } 1.1460 + int getFrameType() { return frameType; } 1.1461 + @Override 1.1462 + void write(ClassWriter writer) { 1.1463 + super.write(writer); 1.1464 + writer.databuf.appendChar(offsetDelta); 1.1465 + if (writer.debugstackmap) { 1.1466 + System.out.print(" offset_delta=" + offsetDelta); 1.1467 + } 1.1468 + for (int i=0; i<locals.length; i++) { 1.1469 + if (writer.debugstackmap) System.out.print(" locals[" + i + "]="); 1.1470 + writer.writeStackMapType(locals[i]); 1.1471 + } 1.1472 + } 1.1473 + } 1.1474 + 1.1475 + static class FullFrame extends StackMapTableFrame { 1.1476 + final int offsetDelta; 1.1477 + final Type[] locals; 1.1478 + final Type[] stack; 1.1479 + FullFrame(int offsetDelta, Type[] locals, Type[] stack) { 1.1480 + this.offsetDelta = offsetDelta; 1.1481 + this.locals = locals; 1.1482 + this.stack = stack; 1.1483 + } 1.1484 + int getFrameType() { return FULL_FRAME; } 1.1485 + @Override 1.1486 + void write(ClassWriter writer) { 1.1487 + super.write(writer); 1.1488 + writer.databuf.appendChar(offsetDelta); 1.1489 + writer.databuf.appendChar(locals.length); 1.1490 + if (writer.debugstackmap) { 1.1491 + System.out.print(" offset_delta=" + offsetDelta); 1.1492 + System.out.print(" nlocals=" + locals.length); 1.1493 + } 1.1494 + for (int i=0; i<locals.length; i++) { 1.1495 + if (writer.debugstackmap) System.out.print(" locals[" + i + "]="); 1.1496 + writer.writeStackMapType(locals[i]); 1.1497 + } 1.1498 + 1.1499 + writer.databuf.appendChar(stack.length); 1.1500 + if (writer.debugstackmap) { System.out.print(" nstack=" + stack.length); } 1.1501 + for (int i=0; i<stack.length; i++) { 1.1502 + if (writer.debugstackmap) System.out.print(" stack[" + i + "]="); 1.1503 + writer.writeStackMapType(stack[i]); 1.1504 + } 1.1505 + } 1.1506 + } 1.1507 + 1.1508 + /** Compare this frame with the previous frame and produce 1.1509 + * an entry of compressed stack map frame. */ 1.1510 + static StackMapTableFrame getInstance(Code.StackMapFrame this_frame, 1.1511 + int prev_pc, 1.1512 + Type[] prev_locals, 1.1513 + Types types) { 1.1514 + Type[] locals = this_frame.locals; 1.1515 + Type[] stack = this_frame.stack; 1.1516 + int offset_delta = this_frame.pc - prev_pc - 1; 1.1517 + if (stack.length == 1) { 1.1518 + if (locals.length == prev_locals.length 1.1519 + && compare(prev_locals, locals, types) == 0) { 1.1520 + return new SameLocals1StackItemFrame(offset_delta, stack[0]); 1.1521 + } 1.1522 + } else if (stack.length == 0) { 1.1523 + int diff_length = compare(prev_locals, locals, types); 1.1524 + if (diff_length == 0) { 1.1525 + return new SameFrame(offset_delta); 1.1526 + } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) { 1.1527 + // APPEND 1.1528 + Type[] local_diff = new Type[-diff_length]; 1.1529 + for (int i=prev_locals.length, j=0; i<locals.length; i++,j++) { 1.1530 + local_diff[j] = locals[i]; 1.1531 + } 1.1532 + return new AppendFrame(SAME_FRAME_EXTENDED - diff_length, 1.1533 + offset_delta, 1.1534 + local_diff); 1.1535 + } else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) { 1.1536 + // CHOP 1.1537 + return new ChopFrame(SAME_FRAME_EXTENDED - diff_length, 1.1538 + offset_delta); 1.1539 + } 1.1540 + } 1.1541 + // FULL_FRAME 1.1542 + return new FullFrame(offset_delta, locals, stack); 1.1543 + } 1.1544 + 1.1545 + static boolean isInt(Type t) { 1.1546 + return (t.getTag().isStrictSubRangeOf(INT) || t.hasTag(BOOLEAN)); 1.1547 + } 1.1548 + 1.1549 + static boolean isSameType(Type t1, Type t2, Types types) { 1.1550 + if (t1 == null) { return t2 == null; } 1.1551 + if (t2 == null) { return false; } 1.1552 + 1.1553 + if (isInt(t1) && isInt(t2)) { return true; } 1.1554 + 1.1555 + if (t1.hasTag(UNINITIALIZED_THIS)) { 1.1556 + return t2.hasTag(UNINITIALIZED_THIS); 1.1557 + } else if (t1.hasTag(UNINITIALIZED_OBJECT)) { 1.1558 + if (t2.hasTag(UNINITIALIZED_OBJECT)) { 1.1559 + return ((UninitializedType)t1).offset == ((UninitializedType)t2).offset; 1.1560 + } else { 1.1561 + return false; 1.1562 + } 1.1563 + } else if (t2.hasTag(UNINITIALIZED_THIS) || t2.hasTag(UNINITIALIZED_OBJECT)) { 1.1564 + return false; 1.1565 + } 1.1566 + 1.1567 + return types.isSameType(t1, t2); 1.1568 + } 1.1569 + 1.1570 + static int compare(Type[] arr1, Type[] arr2, Types types) { 1.1571 + int diff_length = arr1.length - arr2.length; 1.1572 + if (diff_length > MAX_LOCAL_LENGTH_DIFF || diff_length < -MAX_LOCAL_LENGTH_DIFF) { 1.1573 + return Integer.MAX_VALUE; 1.1574 + } 1.1575 + int len = (diff_length > 0) ? arr2.length : arr1.length; 1.1576 + for (int i=0; i<len; i++) { 1.1577 + if (!isSameType(arr1[i], arr2[i], types)) { 1.1578 + return Integer.MAX_VALUE; 1.1579 + } 1.1580 + } 1.1581 + return diff_length; 1.1582 + } 1.1583 + } 1.1584 + 1.1585 + void writeFields(Scope.Entry e) { 1.1586 + // process them in reverse sibling order; 1.1587 + // i.e., process them in declaration order. 1.1588 + List<VarSymbol> vars = List.nil(); 1.1589 + for (Scope.Entry i = e; i != null; i = i.sibling) { 1.1590 + if (i.sym.kind == VAR) vars = vars.prepend((VarSymbol)i.sym); 1.1591 + } 1.1592 + while (vars.nonEmpty()) { 1.1593 + writeField(vars.head); 1.1594 + vars = vars.tail; 1.1595 + } 1.1596 + } 1.1597 + 1.1598 + void writeMethods(Scope.Entry e) { 1.1599 + List<MethodSymbol> methods = List.nil(); 1.1600 + for (Scope.Entry i = e; i != null; i = i.sibling) { 1.1601 + if (i.sym.kind == MTH && (i.sym.flags() & HYPOTHETICAL) == 0) 1.1602 + methods = methods.prepend((MethodSymbol)i.sym); 1.1603 + } 1.1604 + while (methods.nonEmpty()) { 1.1605 + writeMethod(methods.head); 1.1606 + methods = methods.tail; 1.1607 + } 1.1608 + } 1.1609 + 1.1610 + /** Emit a class file for a given class. 1.1611 + * @param c The class from which a class file is generated. 1.1612 + */ 1.1613 + public JavaFileObject writeClass(ClassSymbol c) 1.1614 + throws IOException, PoolOverflow, StringOverflow 1.1615 + { 1.1616 + JavaFileObject outFile 1.1617 + = fileManager.getJavaFileForOutput(CLASS_OUTPUT, 1.1618 + c.flatname.toString(), 1.1619 + JavaFileObject.Kind.CLASS, 1.1620 + c.sourcefile); 1.1621 + OutputStream out = outFile.openOutputStream(); 1.1622 + try { 1.1623 + writeClassFile(out, c); 1.1624 + if (verbose) 1.1625 + log.printVerbose("wrote.file", outFile); 1.1626 + out.close(); 1.1627 + out = null; 1.1628 + } finally { 1.1629 + if (out != null) { 1.1630 + // if we are propagating an exception, delete the file 1.1631 + out.close(); 1.1632 + outFile.delete(); 1.1633 + outFile = null; 1.1634 + } 1.1635 + } 1.1636 + return outFile; // may be null if write failed 1.1637 + } 1.1638 + 1.1639 + /** Write class `c' to outstream `out'. 1.1640 + */ 1.1641 + public void writeClassFile(OutputStream out, ClassSymbol c) 1.1642 + throws IOException, PoolOverflow, StringOverflow { 1.1643 + Assert.check((c.flags() & COMPOUND) == 0); 1.1644 + databuf.reset(); 1.1645 + poolbuf.reset(); 1.1646 + signatureGen.reset(); 1.1647 + pool = c.pool; 1.1648 + innerClasses = null; 1.1649 + innerClassesQueue = null; 1.1650 + bootstrapMethods = new LinkedHashMap<DynamicMethod, MethodHandle>(); 1.1651 + 1.1652 + Type supertype = types.supertype(c.type); 1.1653 + List<Type> interfaces = types.interfaces(c.type); 1.1654 + List<Type> typarams = c.type.getTypeArguments(); 1.1655 + 1.1656 + int flags = adjustFlags(c.flags() & ~DEFAULT); 1.1657 + if ((flags & PROTECTED) != 0) flags |= PUBLIC; 1.1658 + flags = flags & ClassFlags & ~STRICTFP; 1.1659 + if ((flags & INTERFACE) == 0) flags |= ACC_SUPER; 1.1660 + if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL; 1.1661 + if (dumpClassModifiers) { 1.1662 + PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); 1.1663 + pw.println(); 1.1664 + pw.println("CLASSFILE " + c.getQualifiedName()); 1.1665 + pw.println("---" + flagNames(flags)); 1.1666 + } 1.1667 + databuf.appendChar(flags); 1.1668 + 1.1669 + databuf.appendChar(pool.put(c)); 1.1670 + databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0); 1.1671 + databuf.appendChar(interfaces.length()); 1.1672 + for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail) 1.1673 + databuf.appendChar(pool.put(l.head.tsym)); 1.1674 + int fieldsCount = 0; 1.1675 + int methodsCount = 0; 1.1676 + for (Scope.Entry e = c.members().elems; e != null; e = e.sibling) { 1.1677 + switch (e.sym.kind) { 1.1678 + case VAR: fieldsCount++; break; 1.1679 + case MTH: if ((e.sym.flags() & HYPOTHETICAL) == 0) methodsCount++; 1.1680 + break; 1.1681 + case TYP: enterInner((ClassSymbol)e.sym); break; 1.1682 + default : Assert.error(); 1.1683 + } 1.1684 + } 1.1685 + 1.1686 + if (c.trans_local != null) { 1.1687 + for (ClassSymbol local : c.trans_local) { 1.1688 + enterInner(local); 1.1689 + } 1.1690 + } 1.1691 + 1.1692 + databuf.appendChar(fieldsCount); 1.1693 + writeFields(c.members().elems); 1.1694 + databuf.appendChar(methodsCount); 1.1695 + writeMethods(c.members().elems); 1.1696 + 1.1697 + int acountIdx = beginAttrs(); 1.1698 + int acount = 0; 1.1699 + 1.1700 + boolean sigReq = 1.1701 + typarams.length() != 0 || supertype.allparams().length() != 0; 1.1702 + for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail) 1.1703 + sigReq = l.head.allparams().length() != 0; 1.1704 + if (sigReq) { 1.1705 + Assert.check(source.allowGenerics()); 1.1706 + int alenIdx = writeAttr(names.Signature); 1.1707 + if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams); 1.1708 + signatureGen.assembleSig(supertype); 1.1709 + for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail) 1.1710 + signatureGen.assembleSig(l.head); 1.1711 + databuf.appendChar(pool.put(signatureGen.toName())); 1.1712 + signatureGen.reset(); 1.1713 + endAttr(alenIdx); 1.1714 + acount++; 1.1715 + } 1.1716 + 1.1717 + if (c.sourcefile != null && emitSourceFile) { 1.1718 + int alenIdx = writeAttr(names.SourceFile); 1.1719 + // WHM 6/29/1999: Strip file path prefix. We do it here at 1.1720 + // the last possible moment because the sourcefile may be used 1.1721 + // elsewhere in error diagnostics. Fixes 4241573. 1.1722 + //databuf.appendChar(c.pool.put(c.sourcefile)); 1.1723 + String simpleName = BaseFileObject.getSimpleName(c.sourcefile); 1.1724 + databuf.appendChar(c.pool.put(names.fromString(simpleName))); 1.1725 + endAttr(alenIdx); 1.1726 + acount++; 1.1727 + } 1.1728 + 1.1729 + if (genCrt) { 1.1730 + // Append SourceID attribute 1.1731 + int alenIdx = writeAttr(names.SourceID); 1.1732 + databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile))))); 1.1733 + endAttr(alenIdx); 1.1734 + acount++; 1.1735 + // Append CompilationID attribute 1.1736 + alenIdx = writeAttr(names.CompilationID); 1.1737 + databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis())))); 1.1738 + endAttr(alenIdx); 1.1739 + acount++; 1.1740 + } 1.1741 + 1.1742 + acount += writeFlagAttrs(c.flags()); 1.1743 + acount += writeJavaAnnotations(c.getRawAttributes()); 1.1744 + acount += writeTypeAnnotations(c.getRawTypeAttributes(), false); 1.1745 + acount += writeEnclosingMethodAttribute(c); 1.1746 + acount += writeExtraClassAttributes(c); 1.1747 + 1.1748 + poolbuf.appendInt(JAVA_MAGIC); 1.1749 + poolbuf.appendChar(target.minorVersion); 1.1750 + poolbuf.appendChar(target.majorVersion); 1.1751 + 1.1752 + writePool(c.pool); 1.1753 + 1.1754 + if (innerClasses != null) { 1.1755 + writeInnerClasses(); 1.1756 + acount++; 1.1757 + } 1.1758 + 1.1759 + if (!bootstrapMethods.isEmpty()) { 1.1760 + writeBootstrapMethods(); 1.1761 + acount++; 1.1762 + } 1.1763 + 1.1764 + endAttrs(acountIdx, acount); 1.1765 + 1.1766 + poolbuf.appendBytes(databuf.elems, 0, databuf.length); 1.1767 + out.write(poolbuf.elems, 0, poolbuf.length); 1.1768 + 1.1769 + pool = c.pool = null; // to conserve space 1.1770 + } 1.1771 + 1.1772 + /**Allows subclasses to write additional class attributes 1.1773 + * 1.1774 + * @return the number of attributes written 1.1775 + */ 1.1776 + protected int writeExtraClassAttributes(ClassSymbol c) { 1.1777 + return 0; 1.1778 + } 1.1779 + 1.1780 + int adjustFlags(final long flags) { 1.1781 + int result = (int)flags; 1.1782 + if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) 1.1783 + result &= ~SYNTHETIC; 1.1784 + if ((flags & ENUM) != 0 && !target.useEnumFlag()) 1.1785 + result &= ~ENUM; 1.1786 + if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) 1.1787 + result &= ~ANNOTATION; 1.1788 + 1.1789 + if ((flags & BRIDGE) != 0 && target.useBridgeFlag()) 1.1790 + result |= ACC_BRIDGE; 1.1791 + if ((flags & VARARGS) != 0 && target.useVarargsFlag()) 1.1792 + result |= ACC_VARARGS; 1.1793 + if ((flags & DEFAULT) != 0) 1.1794 + result &= ~ABSTRACT; 1.1795 + return result; 1.1796 + } 1.1797 + 1.1798 + long getLastModified(FileObject filename) { 1.1799 + long mod = 0; 1.1800 + try { 1.1801 + mod = filename.getLastModified(); 1.1802 + } catch (SecurityException e) { 1.1803 + throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage()); 1.1804 + } 1.1805 + return mod; 1.1806 + } 1.1807 +}