feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,310 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
/** Bytecode instruction codes, as well as typecodes used as
* instruction modifiers.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public interface ByteCodes {
/** Byte code instruction codes.
*/
int illegal = -1,
nop = 0,
aconst_null = 1,
iconst_m1 = 2,
iconst_0 = 3,
iconst_1 = 4,
iconst_2 = 5,
iconst_3 = 6,
iconst_4 = 7,
iconst_5 = 8,
lconst_0 = 9,
lconst_1 = 10,
fconst_0 = 11,
fconst_1 = 12,
fconst_2 = 13,
dconst_0 = 14,
dconst_1 = 15,
bipush = 16,
sipush = 17,
ldc1 = 18,
ldc2 = 19,
ldc2w = 20,
iload = 21,
lload = 22,
fload = 23,
dload = 24,
aload = 25,
iload_0 = 26,
iload_1 = 27,
iload_2 = 28,
iload_3 = 29,
lload_0 = 30,
lload_1 = 31,
lload_2 = 32,
lload_3 = 33,
fload_0 = 34,
fload_1 = 35,
fload_2 = 36,
fload_3 = 37,
dload_0 = 38,
dload_1 = 39,
dload_2 = 40,
dload_3 = 41,
aload_0 = 42,
aload_1 = 43,
aload_2 = 44,
aload_3 = 45,
iaload = 46,
laload = 47,
faload = 48,
daload = 49,
aaload = 50,
baload = 51,
caload = 52,
saload = 53,
istore = 54,
lstore = 55,
fstore = 56,
dstore = 57,
astore = 58,
istore_0 = 59,
istore_1 = 60,
istore_2 = 61,
istore_3 = 62,
lstore_0 = 63,
lstore_1 = 64,
lstore_2 = 65,
lstore_3 = 66,
fstore_0 = 67,
fstore_1 = 68,
fstore_2 = 69,
fstore_3 = 70,
dstore_0 = 71,
dstore_1 = 72,
dstore_2 = 73,
dstore_3 = 74,
astore_0 = 75,
astore_1 = 76,
astore_2 = 77,
astore_3 = 78,
iastore = 79,
lastore = 80,
fastore = 81,
dastore = 82,
aastore = 83,
bastore = 84,
castore = 85,
sastore = 86,
pop = 87,
pop2 = 88,
dup = 89,
dup_x1 = 90,
dup_x2 = 91,
dup2 = 92,
dup2_x1 = 93,
dup2_x2 = 94,
swap = 95,
iadd = 96,
ladd = 97,
fadd = 98,
dadd = 99,
isub = 100,
lsub = 101,
fsub = 102,
dsub = 103,
imul = 104,
lmul = 105,
fmul = 106,
dmul = 107,
idiv = 108,
ldiv = 109,
fdiv = 110,
ddiv = 111,
imod = 112,
lmod = 113,
fmod = 114,
dmod = 115,
ineg = 116,
lneg = 117,
fneg = 118,
dneg = 119,
ishl = 120,
lshl = 121,
ishr = 122,
lshr = 123,
iushr = 124,
lushr = 125,
iand = 126,
land = 127,
ior = 128,
lor = 129,
ixor = 130,
lxor = 131,
iinc = 132,
i2l = 133,
i2f = 134,
i2d = 135,
l2i = 136,
l2f = 137,
l2d = 138,
f2i = 139,
f2l = 140,
f2d = 141,
d2i = 142,
d2l = 143,
d2f = 144,
int2byte = 145,
int2char = 146,
int2short = 147,
lcmp = 148,
fcmpl = 149,
fcmpg = 150,
dcmpl = 151,
dcmpg = 152,
ifeq = 153,
ifne = 154,
iflt = 155,
ifge = 156,
ifgt = 157,
ifle = 158,
if_icmpeq = 159,
if_icmpne = 160,
if_icmplt = 161,
if_icmpge = 162,
if_icmpgt = 163,
if_icmple = 164,
if_acmpeq = 165,
if_acmpne = 166,
goto_ = 167,
jsr = 168,
ret = 169,
tableswitch = 170,
lookupswitch = 171,
ireturn = 172,
lreturn = 173,
freturn = 174,
dreturn = 175,
areturn = 176,
return_ = 177,
getstatic = 178,
putstatic = 179,
getfield = 180,
putfield = 181,
invokevirtual = 182,
invokespecial = 183,
invokestatic = 184,
invokeinterface = 185,
invokedynamic = 186,
new_ = 187,
newarray = 188,
anewarray = 189,
arraylength = 190,
athrow = 191,
checkcast = 192,
instanceof_ = 193,
monitorenter = 194,
monitorexit = 195,
wide = 196,
multianewarray = 197,
if_acmp_null = 198,
if_acmp_nonnull = 199,
goto_w = 200,
jsr_w = 201,
breakpoint = 202,
ByteCodeCount = 203;
/** Virtual instruction codes; used for constant folding.
*/
int string_add = 256, // string +
bool_not = 257, // boolean !
bool_and = 258, // boolean &&
bool_or = 259; // boolean ||
/** Virtual opcodes; used for shifts with long shiftcount
*/
int ishll = 270, // int shift left with long count
lshll = 271, // long shift left with long count
ishrl = 272, // int shift right with long count
lshrl = 273, // long shift right with long count
iushrl = 274, // int unsigned shift right with long count
lushrl = 275; // long unsigned shift right with long count
/** Virtual opcode for null reference checks
*/
int nullchk = 276; // return operand if non-null,
// otherwise throw NullPointerException.
/** Virtual opcode for disallowed operations.
*/
int error = 277;
/** All conditional jumps come in pairs. To streamline the
* treatment of jumps, we also introduce a negation of an
* unconditional jump. That opcode happens to be jsr.
*/
int dontgoto = jsr;
/** Shift and mask constants for shifting prefix instructions.
* a pair of instruction codes such as LCMP ; IFEQ is encoded
* in Symtab as {@literal (LCMP << preShift) + IFEQ }.
*/
int preShift = 9;
int preMask = (1 << preShift) - 1;
/** Type codes.
*/
int INTcode = 0,
LONGcode = 1,
FLOATcode = 2,
DOUBLEcode = 3,
OBJECTcode = 4,
BYTEcode = 5,
CHARcode = 6,
SHORTcode = 7,
VOIDcode = 8,
TypeCodeCount = 9;
static final String[] typecodeNames = {
"int",
"long",
"float",
"double",
"object",
"byte",
"char",
"short",
"void",
"oops"
};
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
/** The CharacterRangeTable flags indicating type of an entry.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public interface CRTFlags {
/** CRTEntry flags.
*/
public static final int CRT_STATEMENT = 0x0001;
public static final int CRT_BLOCK = 0x0002;
public static final int CRT_ASSIGNMENT = 0x0004;
public static final int CRT_FLOW_CONTROLLER = 0x0008;
public static final int CRT_FLOW_TARGET = 0x0010;
public static final int CRT_INVOKE = 0x0020;
public static final int CRT_CREATE = 0x0040;
public static final int CRT_BRANCH_TRUE = 0x0080;
public static final int CRT_BRANCH_FALSE = 0x0100;
/** The mask for valid flags
*/
public static final int CRT_VALID_FLAGS = CRT_STATEMENT | CRT_BLOCK | CRT_ASSIGNMENT |
CRT_FLOW_CONTROLLER | CRT_FLOW_TARGET | CRT_INVOKE |
CRT_CREATE | CRT_BRANCH_TRUE | CRT_BRANCH_FALSE;
}

View File

@@ -0,0 +1,621 @@
/*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import java.util.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.EndPosTable;
/** This class contains the CharacterRangeTable for some method
* and the hashtable for mapping trees or lists of trees to their
* ending positions.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class CRTable
implements CRTFlags {
private final boolean crtDebug = false;
/** The list of CRTable entries.
*/
private ListBuffer<CRTEntry> entries = new ListBuffer<CRTEntry>();
/** The hashtable for source positions.
*/
private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
/** The object for ending positions stored in the parser.
*/
private EndPosTable endPosTable;
/** The tree of the method this table is intended for.
* We should traverse this tree to get source ranges.
*/
JCTree.JCMethodDecl methodTree;
/** Constructor
*/
public CRTable(JCTree.JCMethodDecl tree, EndPosTable endPosTable) {
this.methodTree = tree;
this.endPosTable = endPosTable;
}
/** Create a new CRTEntry and add it to the entries.
* @param tree The tree or the list of trees for which
* we are storing the code pointers.
* @param flags The set of flags designating type of the entry.
* @param startPc The starting code position.
* @param endPc The ending code position.
*/
public void put(Object tree, int flags, int startPc, int endPc) {
entries.append(new CRTEntry(tree, flags, startPc, endPc));
}
/** Compute source positions and write CRT to the databuf.
* @param databuf The buffer to write bytecodes to.
*/
public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) {
int crtEntries = 0;
// compute source positions for the method
new SourceComputer().csp(methodTree);
for (List<CRTEntry> l = entries.toList(); l.nonEmpty(); l = l.tail) {
CRTEntry entry = l.head;
// eliminate entries that do not produce bytecodes:
// for example, empty blocks and statements
if (entry.startPc == entry.endPc)
continue;
SourceRange pos = positions.get(entry.tree);
Assert.checkNonNull(pos, "CRT: tree source positions are undefined");
if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
continue;
if (crtDebug) {
System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags));
System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc);
}
// encode startPos into line/column representation
int startPos = encodePosition(pos.startPos, lineMap, log);
if (startPos == Position.NOPOS)
continue;
if (crtDebug) {
System.out.print("End: pos = " + pos.endPos + ", pc = " + (entry.endPc - 1));
}
// encode endPos into line/column representation
int endPos = encodePosition(pos.endPos, lineMap, log);
if (endPos == Position.NOPOS)
continue;
// write attribute
databuf.appendChar(entry.startPc);
// 'endPc - 1' because endPc actually points to start of the next command
databuf.appendChar(entry.endPc - 1);
databuf.appendInt(startPos);
databuf.appendInt(endPos);
databuf.appendChar(entry.flags);
crtEntries++;
}
return crtEntries;
}
/** Return the number of the entries.
*/
public int length() {
return entries.length();
}
/** Return string describing flags enabled.
*/
private String getTypes(int flags) {
String types = "";
if ((flags & CRT_STATEMENT) != 0) types += " CRT_STATEMENT";
if ((flags & CRT_BLOCK) != 0) types += " CRT_BLOCK";
if ((flags & CRT_ASSIGNMENT) != 0) types += " CRT_ASSIGNMENT";
if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER";
if ((flags & CRT_FLOW_TARGET) != 0) types += " CRT_FLOW_TARGET";
if ((flags & CRT_INVOKE) != 0) types += " CRT_INVOKE";
if ((flags & CRT_CREATE) != 0) types += " CRT_CREATE";
if ((flags & CRT_BRANCH_TRUE) != 0) types += " CRT_BRANCH_TRUE";
if ((flags & CRT_BRANCH_FALSE) != 0) types += " CRT_BRANCH_FALSE";
return types;
}
/** Source file positions in CRT are integers in the format:
* {@literal line-number << LINESHIFT + column-number }
*/
private int encodePosition(int pos, Position.LineMap lineMap, Log log) {
int line = lineMap.getLineNumber(pos);
int col = lineMap.getColumnNumber(pos);
int new_pos = Position.encodePosition(line, col);
if (crtDebug) {
System.out.println(", line = " + line + ", column = " + col +
", new_pos = " + new_pos);
}
if (new_pos == Position.NOPOS)
log.warning(pos, "position.overflow", line);
return new_pos;
}
/* ************************************************************************
* Traversal methods
*************************************************************************/
/**
* This class contains methods to compute source positions for trees.
* Extends Tree.Visitor to traverse the abstract syntax tree.
*/
class SourceComputer extends JCTree.Visitor {
/** The result of the tree traversal methods.
*/
SourceRange result;
/** Visitor method: compute source positions for a single node.
*/
public SourceRange csp(JCTree tree) {
if (tree == null) return null;
tree.accept(this);
if (result != null) {
positions.put(tree, result);
}
return result;
}
/** Visitor method: compute source positions for a list of nodes.
*/
public SourceRange csp(List<? extends JCTree> trees) {
if ((trees == null) || !(trees.nonEmpty())) return null;
SourceRange list_sr = new SourceRange();
for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
list_sr.mergeWith(csp(l.head));
}
positions.put(trees, list_sr);
return list_sr;
}
/** Visitor method: compute source positions for
* a list of case blocks of switch statements.
*/
public SourceRange cspCases(List<JCCase> trees) {
if ((trees == null) || !(trees.nonEmpty())) return null;
SourceRange list_sr = new SourceRange();
for (List<JCCase> l = trees; l.nonEmpty(); l = l.tail) {
list_sr.mergeWith(csp(l.head));
}
positions.put(trees, list_sr);
return list_sr;
}
/** Visitor method: compute source positions for
* a list of catch clauses in try statements.
*/
public SourceRange cspCatchers(List<JCCatch> trees) {
if ((trees == null) || !(trees.nonEmpty())) return null;
SourceRange list_sr = new SourceRange();
for (List<JCCatch> l = trees; l.nonEmpty(); l = l.tail) {
list_sr.mergeWith(csp(l.head));
}
positions.put(trees, list_sr);
return list_sr;
}
public void visitMethodDef(JCMethodDecl tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitVarDef(JCVariableDecl tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
csp(tree.vartype);
sr.mergeWith(csp(tree.init));
result = sr;
}
public void visitSkip(JCSkip tree) {
// endPos is the same as startPos for the empty statement
SourceRange sr = new SourceRange(startPos(tree), startPos(tree));
result = sr;
}
public void visitBlock(JCBlock tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
csp(tree.stats); // doesn't compare because block's ending position is defined
result = sr;
}
public void visitDoLoop(JCDoWhileLoop tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.body));
sr.mergeWith(csp(tree.cond));
result = sr;
}
public void visitWhileLoop(JCWhileLoop tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.cond));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitForLoop(JCForLoop tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.init));
sr.mergeWith(csp(tree.cond));
sr.mergeWith(csp(tree.step));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitForeachLoop(JCEnhancedForLoop tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.var));
sr.mergeWith(csp(tree.expr));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitLabelled(JCLabeledStatement tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitSwitch(JCSwitch tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.selector));
sr.mergeWith(cspCases(tree.cases));
result = sr;
}
public void visitCase(JCCase tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.pat));
sr.mergeWith(csp(tree.stats));
result = sr;
}
public void visitSynchronized(JCSynchronized tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.lock));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitTry(JCTry tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.resources));
sr.mergeWith(csp(tree.body));
sr.mergeWith(cspCatchers(tree.catchers));
sr.mergeWith(csp(tree.finalizer));
result = sr;
}
public void visitCatch(JCCatch tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.param));
sr.mergeWith(csp(tree.body));
result = sr;
}
public void visitConditional(JCConditional tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.cond));
sr.mergeWith(csp(tree.truepart));
sr.mergeWith(csp(tree.falsepart));
result = sr;
}
public void visitIf(JCIf tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.cond));
sr.mergeWith(csp(tree.thenpart));
sr.mergeWith(csp(tree.elsepart));
result = sr;
}
public void visitExec(JCExpressionStatement tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitBreak(JCBreak tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitContinue(JCContinue tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitReturn(JCReturn tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitThrow(JCThrow tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitAssert(JCAssert tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.cond));
sr.mergeWith(csp(tree.detail));
result = sr;
}
public void visitApply(JCMethodInvocation tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.meth));
sr.mergeWith(csp(tree.args));
result = sr;
}
public void visitNewClass(JCNewClass tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.encl));
sr.mergeWith(csp(tree.clazz));
sr.mergeWith(csp(tree.args));
sr.mergeWith(csp(tree.def));
result = sr;
}
public void visitNewArray(JCNewArray tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.elemtype));
sr.mergeWith(csp(tree.dims));
sr.mergeWith(csp(tree.elems));
result = sr;
}
public void visitParens(JCParens tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitAssign(JCAssign tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.lhs));
sr.mergeWith(csp(tree.rhs));
result = sr;
}
public void visitAssignop(JCAssignOp tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.lhs));
sr.mergeWith(csp(tree.rhs));
result = sr;
}
public void visitUnary(JCUnary tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.arg));
result = sr;
}
public void visitBinary(JCBinary tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.lhs));
sr.mergeWith(csp(tree.rhs));
result = sr;
}
public void visitTypeCast(JCTypeCast tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.clazz));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitTypeTest(JCInstanceOf tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.expr));
sr.mergeWith(csp(tree.clazz));
result = sr;
}
public void visitIndexed(JCArrayAccess tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.indexed));
sr.mergeWith(csp(tree.index));
result = sr;
}
public void visitSelect(JCFieldAccess tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.selected));
result = sr;
}
public void visitIdent(JCIdent tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitLiteral(JCLiteral tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitTypeIdent(JCPrimitiveTypeTree tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitTypeArray(JCArrayTypeTree tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.elemtype));
result = sr;
}
public void visitTypeApply(JCTypeApply tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.clazz));
sr.mergeWith(csp(tree.arguments));
result = sr;
}
@Override
public void visitLetExpr(LetExpr tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.defs));
sr.mergeWith(csp(tree.expr));
result = sr;
}
public void visitTypeParameter(JCTypeParameter tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.bounds));
result = sr;
}
public void visitWildcard(JCWildcard tree) {
result = null;
}
public void visitErroneous(JCErroneous tree) {
result = null;
}
public void visitTree(JCTree tree) {
Assert.error();
}
/** The start position of given tree.
*/
public int startPos(JCTree tree) {
if (tree == null) return Position.NOPOS;
return TreeInfo.getStartPos(tree);
}
/** The end position of given tree, if it has
* defined endpos, NOPOS otherwise.
*/
public int endPos(JCTree tree) {
if (tree == null) return Position.NOPOS;
return TreeInfo.getEndPos(tree, endPosTable);
}
}
/** This class contains a CharacterRangeTableEntry.
*/
static class CRTEntry {
/** A tree or a list of trees to obtain source positions.
*/
Object tree;
/** The flags described in the CharacterRangeTable spec.
*/
int flags;
/** The starting code position of this entry.
*/
int startPc;
/** The ending code position of this entry.
*/
int endPc;
/** Constructor */
CRTEntry(Object tree, int flags, int startPc, int endPc) {
this.tree = tree;
this.flags = flags;
this.startPc = startPc;
this.endPc = endPc;
}
}
/** This class contains source positions
* for some tree or list of trees.
*/
static class SourceRange {
/** The starting source position.
*/
int startPos;
/** The ending source position.
*/
int endPos;
/** Constructor */
SourceRange() {
startPos = Position.NOPOS;
endPos = Position.NOPOS;
}
/** Constructor */
SourceRange(int startPos, int endPos) {
this.startPos = startPos;
this.endPos = endPos;
}
/** Compare the starting and the ending positions
* of the source range and combines them assigning
* the widest range to this.
*/
SourceRange mergeWith(SourceRange sr) {
if (sr == null) return this;
if (startPos == Position.NOPOS)
startPos = sr.startPos;
else if (sr.startPos != Position.NOPOS)
startPos = (startPos < sr.startPos ? startPos : sr.startPos);
if (endPos == Position.NOPOS)
endPos = sr.endPos;
else if (sr.endPos != Position.NOPOS)
endPos = (endPos > sr.endPos ? endPos : sr.endPos);
return this;
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.Name;
/** A JVM class file.
*
* <p>Generic Java classfiles have one additional attribute for classes,
* methods and fields:
* <pre>
* "Signature" (u4 attr-length, u2 signature-index)
* </pre>
*
* <p>A signature gives the full Java type of a method or field. When
* used as a class attribute, it indicates type parameters, followed
* by supertype, followed by all interfaces.
* <pre>
* methodOrFieldSignature ::= type
* classSignature ::= [ typeparams ] supertype { interfacetype }
* </pre>
* <p>The type syntax in signatures is extended as follows:
* <pre>{@literal
* type ::= ... | classtype | methodtype | typevar
* classtype ::= classsig { '.' classsig }
* classig ::= 'L' name [typeargs] ';'
* methodtype ::= [ typeparams ] '(' { type } ')' type
* typevar ::= 'T' name ';'
* typeargs ::= '<' type { type } '>'
* typeparams ::= '<' typeparam { typeparam } '>'
* typeparam ::= name ':' type
* }</pre>
* <p>This class defines constants used in class files as well
* as routines to convert between internal ``.'' and external ``/''
* separators in class names.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b> */
public class ClassFile {
public final static int JAVA_MAGIC = 0xCAFEBABE;
// see Target
public final static int CONSTANT_Utf8 = 1;
public final static int CONSTANT_Unicode = 2;
public final static int CONSTANT_Integer = 3;
public final static int CONSTANT_Float = 4;
public final static int CONSTANT_Long = 5;
public final static int CONSTANT_Double = 6;
public final static int CONSTANT_Class = 7;
public final static int CONSTANT_String = 8;
public final static int CONSTANT_Fieldref = 9;
public final static int CONSTANT_Methodref = 10;
public final static int CONSTANT_InterfaceMethodref = 11;
public final static int CONSTANT_NameandType = 12;
public final static int CONSTANT_MethodHandle = 15;
public final static int CONSTANT_MethodType = 16;
public final static int CONSTANT_InvokeDynamic = 18;
public final static int REF_getField = 1;
public final static int REF_getStatic = 2;
public final static int REF_putField = 3;
public final static int REF_putStatic = 4;
public final static int REF_invokeVirtual = 5;
public final static int REF_invokeStatic = 6;
public final static int REF_invokeSpecial = 7;
public final static int REF_newInvokeSpecial = 8;
public final static int REF_invokeInterface = 9;
public final static int MAX_PARAMETERS = 0xff;
public final static int MAX_DIMENSIONS = 0xff;
public final static int MAX_CODE = 0xffff;
public final static int MAX_LOCALS = 0xffff;
public final static int MAX_STACK = 0xffff;
public enum Version {
V45_3(45, 3), // base level for all attributes
V49(49, 0), // JDK 1.5: enum, generics, annotations
V50(50, 0), // JDK 1.6: stackmaps
V51(51, 0), // JDK 1.7
V52(52, 0); // JDK 1.8: lambda, type annos, param names
Version(int major, int minor) {
this.major = major;
this.minor = minor;
}
public final int major, minor;
}
/************************************************************************
* String Translation Routines
***********************************************************************/
/** Return internal representation of buf[offset..offset+len-1],
* converting '/' to '.'.
*/
public static byte[] internalize(byte[] buf, int offset, int len) {
byte[] translated = new byte[len];
for (int j = 0; j < len; j++) {
byte b = buf[offset + j];
if (b == '/') translated[j] = (byte) '.';
else translated[j] = b;
}
return translated;
}
/** Return internal representation of given name,
* converting '/' to '.'.
*/
public static byte[] internalize(Name name) {
return internalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
}
/** Return external representation of buf[offset..offset+len-1],
* converting '.' to '/'.
*/
public static byte[] externalize(byte[] buf, int offset, int len) {
byte[] translated = new byte[len];
for (int j = 0; j < len; j++) {
byte b = buf[offset + j];
if (b == '.') translated[j] = (byte) '/';
else translated[j] = b;
}
return translated;
}
/** Return external representation of given name,
* converting '/' to '.'.
*/
public static byte[] externalize(Name name) {
return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
}
/************************************************************************
* Name-and-type
***********************************************************************/
/** A class for the name-and-type signature of a method or field.
*/
public static class NameAndType {
Name name;
UniqueType uniqueType;
Types types;
NameAndType(Name name, Type type, Types types) {
this.name = name;
this.uniqueType = new UniqueType(type, types);
this.types = types;
}
void setType(Type type) {
this.uniqueType = new UniqueType(type, types);
}
@Override
public boolean equals(Object other) {
return (other instanceof NameAndType &&
name == ((NameAndType) other).name &&
uniqueType.equals(((NameAndType) other).uniqueType));
}
@Override
public int hashCode() {
return name.hashCode() * uniqueType.hashCode();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,830 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.jvm.Code.*;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Assert;
import static com.sun.tools.javac.jvm.ByteCodes.*;
/** A helper class for code generation. Items are objects
* that stand for addressable entities in the bytecode. Each item
* supports a fixed protocol for loading the item on the stack, storing
* into it, converting it into a jump condition, and several others.
* There are many individual forms of items, such as local, static,
* indexed, or instance variables, values on the top of stack, the
* special values this or super, etc. Individual items are represented as
* inner classes in class Items.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Items {
/** The current constant pool.
*/
Pool pool;
/** The current code buffer.
*/
Code code;
/** The current symbol table.
*/
Symtab syms;
/** Type utilities. */
Types types;
/** Items that exist only once (flyweight pattern).
*/
private final Item voidItem;
private final Item thisItem;
private final Item superItem;
private final Item[] stackItem = new Item[TypeCodeCount];
public Items(Pool pool, Code code, Symtab syms, Types types) {
this.code = code;
this.pool = pool;
this.types = types;
voidItem = new Item(VOIDcode) {
public String toString() { return "void"; }
};
thisItem = new SelfItem(false);
superItem = new SelfItem(true);
for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
stackItem[VOIDcode] = voidItem;
this.syms = syms;
}
/** Make a void item
*/
Item makeVoidItem() {
return voidItem;
}
/** Make an item representing `this'.
*/
Item makeThisItem() {
return thisItem;
}
/** Make an item representing `super'.
*/
Item makeSuperItem() {
return superItem;
}
/** Make an item representing a value on stack.
* @param type The value's type.
*/
Item makeStackItem(Type type) {
return stackItem[Code.typecode(type)];
}
/** Make an item representing a dynamically invoked method.
* @param member The represented symbol.
*/
Item makeDynamicItem(Symbol member) {
return new DynamicItem(member);
}
/** Make an item representing an indexed expression.
* @param type The expression's type.
*/
Item makeIndexedItem(Type type) {
return new IndexedItem(type);
}
/** Make an item representing a local variable.
* @param v The represented variable.
*/
LocalItem makeLocalItem(VarSymbol v) {
return new LocalItem(v.erasure(types), v.adr);
}
/** Make an item representing a local anonymous variable.
* @param type The represented variable's type.
* @param reg The represented variable's register.
*/
private LocalItem makeLocalItem(Type type, int reg) {
return new LocalItem(type, reg);
}
/** Make an item representing a static variable or method.
* @param member The represented symbol.
*/
Item makeStaticItem(Symbol member) {
return new StaticItem(member);
}
/** Make an item representing an instance variable or method.
* @param member The represented symbol.
* @param nonvirtual Is the reference not virtual? (true for constructors
* and private members).
*/
Item makeMemberItem(Symbol member, boolean nonvirtual) {
return new MemberItem(member, nonvirtual);
}
/** Make an item representing a literal.
* @param type The literal's type.
* @param value The literal's value.
*/
Item makeImmediateItem(Type type, Object value) {
return new ImmediateItem(type, value);
}
/** Make an item representing an assignment expression.
* @param lhs The item representing the assignment's left hand side.
*/
Item makeAssignItem(Item lhs) {
return new AssignItem(lhs);
}
/** Make an item representing a conditional or unconditional jump.
* @param opcode The jump's opcode.
* @param trueJumps A chain encomassing all jumps that can be taken
* if the condition evaluates to true.
* @param falseJumps A chain encomassing all jumps that can be taken
* if the condition evaluates to false.
*/
CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
return new CondItem(opcode, trueJumps, falseJumps);
}
/** Make an item representing a conditional or unconditional jump.
* @param opcode The jump's opcode.
*/
CondItem makeCondItem(int opcode) {
return makeCondItem(opcode, null, null);
}
/** The base class of all items, which implements default behavior.
*/
abstract class Item {
/** The type code of values represented by this item.
*/
int typecode;
Item(int typecode) {
this.typecode = typecode;
}
/** Generate code to load this item onto stack.
*/
Item load() {
throw new AssertionError();
}
/** Generate code to store top of stack into this item.
*/
void store() {
throw new AssertionError("store unsupported: " + this);
}
/** Generate code to invoke method represented by this item.
*/
Item invoke() {
throw new AssertionError(this);
}
/** Generate code to use this item twice.
*/
void duplicate() {}
/** Generate code to avoid having to use this item.
*/
void drop() {}
/** Generate code to stash a copy of top of stack - of typecode toscode -
* under this item.
*/
void stash(int toscode) {
stackItem[toscode].duplicate();
}
/** Generate code to turn item into a testable condition.
*/
CondItem mkCond() {
load();
return makeCondItem(ifne);
}
/** Generate code to coerce item to given type code.
* @param targetcode The type code to coerce to.
*/
Item coerce(int targetcode) {
if (typecode == targetcode)
return this;
else {
load();
int typecode1 = Code.truncate(typecode);
int targetcode1 = Code.truncate(targetcode);
if (typecode1 != targetcode1) {
int offset = targetcode1 > typecode1 ? targetcode1 - 1
: targetcode1;
code.emitop0(i2l + typecode1 * 3 + offset);
}
if (targetcode != targetcode1) {
code.emitop0(int2byte + targetcode - BYTEcode);
}
return stackItem[targetcode];
}
}
/** Generate code to coerce item to given type.
* @param targettype The type to coerce to.
*/
Item coerce(Type targettype) {
return coerce(Code.typecode(targettype));
}
/** Return the width of this item on stack as a number of words.
*/
int width() {
return 0;
}
public abstract String toString();
}
/** An item representing a value on stack.
*/
class StackItem extends Item {
StackItem(int typecode) {
super(typecode);
}
Item load() {
return this;
}
void duplicate() {
code.emitop0(width() == 2 ? dup2 : dup);
}
void drop() {
code.emitop0(width() == 2 ? pop2 : pop);
}
void stash(int toscode) {
code.emitop0(
(width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
}
int width() {
return Code.width(typecode);
}
public String toString() {
return "stack(" + typecodeNames[typecode] + ")";
}
}
/** An item representing an indexed expression.
*/
class IndexedItem extends Item {
IndexedItem(Type type) {
super(Code.typecode(type));
}
Item load() {
code.emitop0(iaload + typecode);
return stackItem[typecode];
}
void store() {
code.emitop0(iastore + typecode);
}
void duplicate() {
code.emitop0(dup2);
}
void drop() {
code.emitop0(pop2);
}
void stash(int toscode) {
code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
}
int width() {
return 2;
}
public String toString() {
return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
}
}
/** An item representing `this' or `super'.
*/
class SelfItem extends Item {
/** Flag which determines whether this item represents `this' or `super'.
*/
boolean isSuper;
SelfItem(boolean isSuper) {
super(OBJECTcode);
this.isSuper = isSuper;
}
Item load() {
code.emitop0(aload_0);
return stackItem[typecode];
}
public String toString() {
return isSuper ? "super" : "this";
}
}
/** An item representing a local variable.
*/
class LocalItem extends Item {
/** The variable's register.
*/
int reg;
/** The variable's type.
*/
Type type;
LocalItem(Type type, int reg) {
super(Code.typecode(type));
Assert.check(reg >= 0);
this.type = type;
this.reg = reg;
}
Item load() {
if (reg <= 3)
code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
else
code.emitop1w(iload + Code.truncate(typecode), reg);
return stackItem[typecode];
}
void store() {
if (reg <= 3)
code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
else
code.emitop1w(istore + Code.truncate(typecode), reg);
code.setDefined(reg);
}
void incr(int x) {
if (typecode == INTcode && x >= -32768 && x <= 32767) {
code.emitop1w(iinc, reg, x);
} else {
load();
if (x >= 0) {
makeImmediateItem(syms.intType, x).load();
code.emitop0(iadd);
} else {
makeImmediateItem(syms.intType, -x).load();
code.emitop0(isub);
}
makeStackItem(syms.intType).coerce(typecode);
store();
}
}
public String toString() {
return "localItem(type=" + type + "; reg=" + reg + ")";
}
}
/** An item representing a static variable or method.
*/
class StaticItem extends Item {
/** The represented symbol.
*/
Symbol member;
StaticItem(Symbol member) {
super(Code.typecode(member.erasure(types)));
this.member = member;
}
Item load() {
code.emitop2(getstatic, pool.put(member));
return stackItem[typecode];
}
void store() {
code.emitop2(putstatic, pool.put(member));
}
Item invoke() {
MethodType mtype = (MethodType)member.erasure(types);
int rescode = Code.typecode(mtype.restype);
code.emitInvokestatic(pool.put(member), mtype);
return stackItem[rescode];
}
public String toString() {
return "static(" + member + ")";
}
}
/** An item representing a dynamic call site.
*/
class DynamicItem extends StaticItem {
DynamicItem(Symbol member) {
super(member);
}
Item load() {
assert false;
return null;
}
void store() {
assert false;
}
Item invoke() {
// assert target.hasNativeInvokeDynamic();
MethodType mtype = (MethodType)member.erasure(types);
int rescode = Code.typecode(mtype.restype);
code.emitInvokedynamic(pool.put(member), mtype);
return stackItem[rescode];
}
public String toString() {
return "dynamic(" + member + ")";
}
}
/** An item representing an instance variable or method.
*/
class MemberItem extends Item {
/** The represented symbol.
*/
Symbol member;
/** Flag that determines whether or not access is virtual.
*/
boolean nonvirtual;
MemberItem(Symbol member, boolean nonvirtual) {
super(Code.typecode(member.erasure(types)));
this.member = member;
this.nonvirtual = nonvirtual;
}
Item load() {
code.emitop2(getfield, pool.put(member));
return stackItem[typecode];
}
void store() {
code.emitop2(putfield, pool.put(member));
}
Item invoke() {
MethodType mtype = (MethodType)member.externalType(types);
int rescode = Code.typecode(mtype.restype);
if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
code.emitInvokeinterface(pool.put(member), mtype);
} else if (nonvirtual) {
code.emitInvokespecial(pool.put(member), mtype);
} else {
code.emitInvokevirtual(pool.put(member), mtype);
}
return stackItem[rescode];
}
void duplicate() {
stackItem[OBJECTcode].duplicate();
}
void drop() {
stackItem[OBJECTcode].drop();
}
void stash(int toscode) {
stackItem[OBJECTcode].stash(toscode);
}
int width() {
return 1;
}
public String toString() {
return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
}
}
/** An item representing a literal.
*/
class ImmediateItem extends Item {
/** The literal's value.
*/
Object value;
ImmediateItem(Type type, Object value) {
super(Code.typecode(type));
this.value = value;
}
private void ldc() {
int idx = pool.put(value);
if (typecode == LONGcode || typecode == DOUBLEcode) {
code.emitop2(ldc2w, idx);
} else {
code.emitLdc(idx);
}
}
Item load() {
switch (typecode) {
case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
int ival = ((Number)value).intValue();
if (-1 <= ival && ival <= 5)
code.emitop0(iconst_0 + ival);
else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
code.emitop1(bipush, ival);
else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
code.emitop2(sipush, ival);
else
ldc();
break;
case LONGcode:
long lval = ((Number)value).longValue();
if (lval == 0 || lval == 1)
code.emitop0(lconst_0 + (int)lval);
else
ldc();
break;
case FLOATcode:
float fval = ((Number)value).floatValue();
if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
code.emitop0(fconst_0 + (int)fval);
else {
ldc();
}
break;
case DOUBLEcode:
double dval = ((Number)value).doubleValue();
if (isPosZero(dval) || dval == 1.0)
code.emitop0(dconst_0 + (int)dval);
else
ldc();
break;
case OBJECTcode:
ldc();
break;
default:
Assert.error();
}
return stackItem[typecode];
}
//where
/** Return true iff float number is positive 0.
*/
private boolean isPosZero(float x) {
return x == 0.0f && 1.0f / x > 0.0f;
}
/** Return true iff double number is positive 0.
*/
private boolean isPosZero(double x) {
return x == 0.0d && 1.0d / x > 0.0d;
}
CondItem mkCond() {
int ival = ((Number)value).intValue();
return makeCondItem(ival != 0 ? goto_ : dontgoto);
}
Item coerce(int targetcode) {
if (typecode == targetcode) {
return this;
} else {
switch (targetcode) {
case INTcode:
if (Code.truncate(typecode) == INTcode)
return this;
else
return new ImmediateItem(
syms.intType,
((Number)value).intValue());
case LONGcode:
return new ImmediateItem(
syms.longType,
((Number)value).longValue());
case FLOATcode:
return new ImmediateItem(
syms.floatType,
((Number)value).floatValue());
case DOUBLEcode:
return new ImmediateItem(
syms.doubleType,
((Number)value).doubleValue());
case BYTEcode:
return new ImmediateItem(
syms.byteType,
(int)(byte)((Number)value).intValue());
case CHARcode:
return new ImmediateItem(
syms.charType,
(int)(char)((Number)value).intValue());
case SHORTcode:
return new ImmediateItem(
syms.shortType,
(int)(short)((Number)value).intValue());
default:
return super.coerce(targetcode);
}
}
}
public String toString() {
return "immediate(" + value + ")";
}
}
/** An item representing an assignment expressions.
*/
class AssignItem extends Item {
/** The item representing the assignment's left hand side.
*/
Item lhs;
AssignItem(Item lhs) {
super(lhs.typecode);
this.lhs = lhs;
}
Item load() {
lhs.stash(typecode);
lhs.store();
return stackItem[typecode];
}
void duplicate() {
load().duplicate();
}
void drop() {
lhs.store();
}
void stash(int toscode) {
Assert.error();
}
int width() {
return lhs.width() + Code.width(typecode);
}
public String toString() {
return "assign(lhs = " + lhs + ")";
}
}
/** An item representing a conditional or unconditional jump.
*/
class CondItem extends Item {
/** A chain encomassing all jumps that can be taken
* if the condition evaluates to true.
*/
Chain trueJumps;
/** A chain encomassing all jumps that can be taken
* if the condition evaluates to false.
*/
Chain falseJumps;
/** The jump's opcode.
*/
int opcode;
/*
* An abstract syntax tree of this item. It is needed
* for branch entries in 'CharacterRangeTable' attribute.
*/
JCTree tree;
CondItem(int opcode, Chain truejumps, Chain falsejumps) {
super(BYTEcode);
this.opcode = opcode;
this.trueJumps = truejumps;
this.falseJumps = falsejumps;
}
Item load() {
Chain trueChain = null;
Chain falseChain = jumpFalse();
if (!isFalse()) {
code.resolve(trueJumps);
code.emitop0(iconst_1);
trueChain = code.branch(goto_);
}
if (falseChain != null) {
code.resolve(falseChain);
code.emitop0(iconst_0);
}
code.resolve(trueChain);
return stackItem[typecode];
}
void duplicate() {
load().duplicate();
}
void drop() {
load().drop();
}
void stash(int toscode) {
Assert.error();
}
CondItem mkCond() {
return this;
}
Chain jumpTrue() {
if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
// we should proceed further in -Xjcov mode only
int startpc = code.curCP();
Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
return c;
}
Chain jumpFalse() {
if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
// we should proceed further in -Xjcov mode only
int startpc = code.curCP();
Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
return c;
}
CondItem negate() {
CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
c.tree = tree;
return c;
}
int width() {
// a CondItem doesn't have a size on the stack per se.
throw new AssertionError();
}
boolean isTrue() {
return falseJumps == null && opcode == goto_;
}
boolean isFalse() {
return trueJumps == null && opcode == dontgoto;
}
public String toString() {
return "cond(" + Code.mnem(opcode) + ")";
}
}
}

View File

@@ -0,0 +1,856 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor8;
import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import static com.sun.tools.javac.main.Option.*;
/** This class provides operations to write native header files for classes.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class JNIWriter {
protected static final Context.Key<JNIWriter> jniWriterKey =
new Context.Key<JNIWriter>();
/** Access to files. */
private final JavaFileManager fileManager;
JavacElements elements;
JavacTypes types;
/** The log to use for verbose output.
*/
private final Log log;
/** Switch: verbose output.
*/
private boolean verbose;
/** Switch: check all nested classes of top level class
*/
private boolean checkAll;
private Mangle mangler;
private Context context;
private Symtab syms;
private String lineSep;
private final boolean isWindows =
System.getProperty("os.name").startsWith("Windows");
/** Get the ClassWriter instance for this context. */
public static JNIWriter instance(Context context) {
JNIWriter instance = context.get(jniWriterKey);
if (instance == null)
instance = new JNIWriter(context);
return instance;
}
/** Construct a class writer, given an options table.
*/
private JNIWriter(Context context) {
context.put(jniWriterKey, this);
fileManager = context.get(JavaFileManager.class);
log = Log.instance(context);
Options options = Options.instance(context);
verbose = options.isSet(VERBOSE);
checkAll = options.isSet("javah:full");
this.context = context; // for lazyInit()
syms = Symtab.instance(context);
lineSep = System.getProperty("line.separator");
}
private void lazyInit() {
if (mangler == null) {
elements = JavacElements.instance(context);
types = JavacTypes.instance(context);
mangler = new Mangle(elements, types);
}
}
public boolean needsHeader(ClassSymbol c) {
if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
return false;
if (checkAll)
return needsHeader(c.outermostClass(), true);
else
return needsHeader(c, false);
}
private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
return false;
for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
return true;
for (Attribute.Compound a: i.sym.getDeclarationAttributes()) {
if (a.type.tsym == syms.nativeHeaderType.tsym)
return true;
}
}
if (checkNestedClasses) {
for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
return true;
}
}
return false;
}
/** Emit a class file for a given class.
* @param c The class from which a class file is generated.
*/
public FileObject write(ClassSymbol c)
throws IOException
{
String className = c.flatName().toString();
FileObject outFile
= fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
"", className.replaceAll("[.$]", "_") + ".h", null);
Writer out = outFile.openWriter();
try {
write(out, c);
if (verbose)
log.printVerbose("wrote.file", outFile);
out.close();
out = null;
} finally {
if (out != null) {
// if we are propogating an exception, delete the file
out.close();
outFile.delete();
outFile = null;
}
}
return outFile; // may be null if write failed
}
public void write(Writer out, ClassSymbol sym)
throws IOException {
lazyInit();
try {
String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
println(out, fileTop());
println(out, includes());
println(out, guardBegin(cname));
println(out, cppGuardBegin());
writeStatics(out, sym);
writeMethods(out, sym, cname);
println(out, cppGuardEnd());
println(out, guardEnd(cname));
} catch (TypeSignature.SignatureException e) {
throw new IOException(e);
}
}
protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
List<VariableElement> classfields = getAllFields(sym);
for (VariableElement v: classfields) {
if (!v.getModifiers().contains(Modifier.STATIC))
continue;
String s = null;
s = defineForStatic(sym, v);
if (s != null) {
println(out, s);
}
}
}
/**
* Including super class fields.
*/
List<VariableElement> getAllFields(TypeElement subclazz) {
List<VariableElement> fields = new ArrayList<VariableElement>();
TypeElement cd = null;
Stack<TypeElement> s = new Stack<TypeElement>();
cd = subclazz;
while (true) {
s.push(cd);
TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
if (c == null)
break;
cd = c;
}
while (!s.empty()) {
cd = s.pop();
fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
}
return fields;
}
protected String defineForStatic(TypeElement c, VariableElement f) {
CharSequence cnamedoc = c.getQualifiedName();
CharSequence fnamedoc = f.getSimpleName();
String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
Assert.check(f.getModifiers().contains(Modifier.STATIC));
if (f.getModifiers().contains(Modifier.FINAL)) {
Object value = null;
value = f.getConstantValue();
if (value != null) { /* so it is a ConstantExpression */
String constString = null;
if ((value instanceof Integer)
|| (value instanceof Byte)
|| (value instanceof Short)) {
/* covers byte, short, int */
constString = value.toString() + "L";
} else if (value instanceof Boolean) {
constString = ((Boolean) value) ? "1L" : "0L";
} else if (value instanceof Character) {
Character ch = (Character) value;
constString = String.valueOf(((int) ch) & 0xffff) + "L";
} else if (value instanceof Long) {
// Visual C++ supports the i64 suffix, not LL.
if (isWindows)
constString = value.toString() + "i64";
else
constString = value.toString() + "LL";
} else if (value instanceof Float) {
/* bug for bug */
float fv = ((Float)value).floatValue();
if (Float.isInfinite(fv))
constString = ((fv < 0) ? "-" : "") + "Inff";
else
constString = value.toString() + "f";
} else if (value instanceof Double) {
/* bug for bug */
double d = ((Double)value).doubleValue();
if (Double.isInfinite(d))
constString = ((d < 0) ? "-" : "") + "InfD";
else
constString = value.toString();
}
if (constString != null) {
StringBuilder s = new StringBuilder("#undef ");
s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
s.append("#define "); s.append(cname); s.append("_");
s.append(fname); s.append(" "); s.append(constString);
return s.toString();
}
}
}
return null;
}
protected void writeMethods(Writer out, ClassSymbol sym, String cname)
throws IOException, TypeSignature.SignatureException {
List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.getEnclosedElements());
for (ExecutableElement md: classmethods) {
if(md.getModifiers().contains(Modifier.NATIVE)){
TypeMirror mtr = types.erasure(md.getReturnType());
String sig = signature(md);
TypeSignature newtypesig = new TypeSignature(elements);
CharSequence methodName = md.getSimpleName();
boolean longName = false;
for (ExecutableElement md2: classmethods) {
if ((md2 != md)
&& (methodName.equals(md2.getSimpleName()))
&& (md2.getModifiers().contains(Modifier.NATIVE)))
longName = true;
}
println(out, "/*");
println(out, " * Class: " + cname);
println(out, " * Method: " +
mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
println(out, " */");
println(out, "JNIEXPORT " + jniType(mtr) +
" JNICALL " +
mangler.mangleMethod(md, sym,
(longName) ?
Mangle.Type.METHOD_JNI_LONG :
Mangle.Type.METHOD_JNI_SHORT));
print(out, " (JNIEnv *, ");
List<? extends VariableElement> paramargs = md.getParameters();
List<TypeMirror> args = new ArrayList<TypeMirror>();
for (VariableElement p: paramargs) {
args.add(types.erasure(p.asType()));
}
if (md.getModifiers().contains(Modifier.STATIC))
print(out, "jclass");
else
print(out, "jobject");
for (TypeMirror arg: args) {
print(out, ", ");
print(out, jniType(arg));
}
println(out, ");"
+ lineSep);
}
}
}
// c.f. MethodDoc.signature
String signature(ExecutableElement e) {
StringBuilder sb = new StringBuilder("(");
String sep = "";
for (VariableElement p: e.getParameters()) {
sb.append(sep);
sb.append(types.erasure(p.asType()).toString());
sep = ",";
}
sb.append(")");
return sb.toString();
}
protected final String jniType(TypeMirror t) {
TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
TypeElement jClass = elements.getTypeElement("java.lang.Class");
TypeElement jString = elements.getTypeElement("java.lang.String");
Element tclassDoc = types.asElement(t);
switch (t.getKind()) {
case ARRAY: {
TypeMirror ct = ((ArrayType) t).getComponentType();
switch (ct.getKind()) {
case BOOLEAN: return "jbooleanArray";
case BYTE: return "jbyteArray";
case CHAR: return "jcharArray";
case SHORT: return "jshortArray";
case INT: return "jintArray";
case LONG: return "jlongArray";
case FLOAT: return "jfloatArray";
case DOUBLE: return "jdoubleArray";
case ARRAY:
case DECLARED: return "jobjectArray";
default: throw new Error(ct.toString());
}
}
case VOID: return "void";
case BOOLEAN: return "jboolean";
case BYTE: return "jbyte";
case CHAR: return "jchar";
case SHORT: return "jshort";
case INT: return "jint";
case LONG: return "jlong";
case FLOAT: return "jfloat";
case DOUBLE: return "jdouble";
case DECLARED: {
if (tclassDoc.equals(jString))
return "jstring";
else if (types.isAssignable(t, throwable.asType()))
return "jthrowable";
else if (types.isAssignable(t, jClass.asType()))
return "jclass";
else
return "jobject";
}
}
Assert.check(false, "jni unknown type");
return null; /* dead code. */
}
protected String fileTop() {
return "/* DO NOT EDIT THIS FILE - it is machine generated */";
}
protected String includes() {
return "#include <jni.h>";
}
/*
* Deal with the C pre-processor.
*/
protected String cppGuardBegin() {
return "#ifdef __cplusplus" + lineSep
+ "extern \"C\" {" + lineSep
+ "#endif";
}
protected String cppGuardEnd() {
return "#ifdef __cplusplus" + lineSep
+ "}" + lineSep
+ "#endif";
}
protected String guardBegin(String cname) {
return "/* Header for class " + cname + " */" + lineSep
+ lineSep
+ "#ifndef _Included_" + cname + lineSep
+ "#define _Included_" + cname;
}
protected String guardEnd(String cname) {
return "#endif";
}
protected void print(Writer out, String text) throws IOException {
out.write(text);
}
protected void println(Writer out, String text) throws IOException {
out.write(text);
out.write(lineSep);
}
private static class Mangle {
public static class Type {
public static final int CLASS = 1;
public static final int FIELDSTUB = 2;
public static final int FIELD = 3;
public static final int JNI = 4;
public static final int SIGNATURE = 5;
public static final int METHOD_JDK_1 = 6;
public static final int METHOD_JNI_SHORT = 7;
public static final int METHOD_JNI_LONG = 8;
};
private Elements elems;
private Types types;
Mangle(Elements elems, Types types) {
this.elems = elems;
this.types = types;
}
public final String mangle(CharSequence name, int mtype) {
StringBuilder result = new StringBuilder(100);
int length = name.length();
for (int i = 0; i < length; i++) {
char ch = name.charAt(i);
if (isalnum(ch)) {
result.append(ch);
} else if ((ch == '.') &&
mtype == Mangle.Type.CLASS) {
result.append('_');
} else if (( ch == '$') &&
mtype == Mangle.Type.CLASS) {
result.append('_');
result.append('_');
} else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
result.append('_');
} else if (ch == '_' && mtype == Mangle.Type.CLASS) {
result.append('_');
} else if (mtype == Mangle.Type.JNI) {
String esc = null;
if (ch == '_')
esc = "_1";
else if (ch == '.')
esc = "_";
else if (ch == ';')
esc = "_2";
else if (ch == '[')
esc = "_3";
if (esc != null) {
result.append(esc);
} else {
result.append(mangleChar(ch));
}
} else if (mtype == Mangle.Type.SIGNATURE) {
if (isprint(ch)) {
result.append(ch);
} else {
result.append(mangleChar(ch));
}
} else {
result.append(mangleChar(ch));
}
}
return result.toString();
}
public String mangleMethod(ExecutableElement method, TypeElement clazz,
int mtype) throws TypeSignature.SignatureException {
StringBuilder result = new StringBuilder(100);
result.append("Java_");
if (mtype == Mangle.Type.METHOD_JDK_1) {
result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
result.append('_');
result.append(mangle(method.getSimpleName(),
Mangle.Type.FIELD));
result.append("_stub");
return result.toString();
}
/* JNI */
result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
result.append('_');
result.append(mangle(method.getSimpleName(),
Mangle.Type.JNI));
if (mtype == Mangle.Type.METHOD_JNI_LONG) {
result.append("__");
String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType());
sig = sig.substring(1);
sig = sig.substring(0, sig.lastIndexOf(')'));
sig = sig.replace('/', '.');
result.append(mangle(sig, Mangle.Type.JNI));
}
return result.toString();
}
//where
private String getInnerQualifiedName(TypeElement clazz) {
return elems.getBinaryName(clazz).toString();
}
public final String mangleChar(char ch) {
String s = Integer.toHexString(ch);
int nzeros = 5 - s.length();
char[] result = new char[6];
result[0] = '_';
for (int i = 1; i <= nzeros; i++)
result[i] = '0';
for (int i = nzeros+1, j = 0; i < 6; i++, j++)
result[i] = s.charAt(j);
return new String(result);
}
// Warning: duplicated in Gen
private String signature(ExecutableElement e) {
StringBuilder sb = new StringBuilder();
String sep = "(";
for (VariableElement p: e.getParameters()) {
sb.append(sep);
sb.append(types.erasure(p.asType()).toString());
sep = ",";
}
sb.append(")");
return sb.toString();
}
/* Warning: Intentional ASCII operation. */
private static boolean isalnum(char ch) {
return ch <= 0x7f && /* quick test */
((ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
(ch >= '0' && ch <= '9'));
}
/* Warning: Intentional ASCII operation. */
private static boolean isprint(char ch) {
return ch >= 32 && ch <= 126;
}
}
private static class TypeSignature {
static class SignatureException extends Exception {
private static final long serialVersionUID = 1L;
SignatureException(String reason) {
super(reason);
}
}
Elements elems;
/* Signature Characters */
private static final String SIG_VOID = "V";
private static final String SIG_BOOLEAN = "Z";
private static final String SIG_BYTE = "B";
private static final String SIG_CHAR = "C";
private static final String SIG_SHORT = "S";
private static final String SIG_INT = "I";
private static final String SIG_LONG = "J";
private static final String SIG_FLOAT = "F";
private static final String SIG_DOUBLE = "D";
private static final String SIG_ARRAY = "[";
private static final String SIG_CLASS = "L";
public TypeSignature(Elements elems){
this.elems = elems;
}
/*
* Returns the type signature of a field according to JVM specs
*/
public String getTypeSignature(String javasignature) throws SignatureException {
return getParamJVMSignature(javasignature);
}
/*
* Returns the type signature of a method according to JVM specs
*/
public String getTypeSignature(String javasignature, TypeMirror returnType)
throws SignatureException {
String signature = null; //Java type signature.
String typeSignature = null; //Internal type signature.
List<String> params = new ArrayList<String>(); //List of parameters.
String paramsig = null; //Java parameter signature.
String paramJVMSig = null; //Internal parameter signature.
String returnSig = null; //Java return type signature.
String returnJVMType = null; //Internal return type signature.
int dimensions = 0; //Array dimension.
int startIndex = -1;
int endIndex = -1;
StringTokenizer st = null;
int i = 0;
// Gets the actual java signature without parentheses.
if (javasignature != null) {
startIndex = javasignature.indexOf("(");
endIndex = javasignature.indexOf(")");
}
if (((startIndex != -1) && (endIndex != -1))
&&(startIndex+1 < javasignature.length())
&&(endIndex < javasignature.length())) {
signature = javasignature.substring(startIndex+1, endIndex);
}
// Separates parameters.
if (signature != null) {
if (signature.indexOf(",") != -1) {
st = new StringTokenizer(signature, ",");
if (st != null) {
while (st.hasMoreTokens()) {
params.add(st.nextToken());
}
}
} else {
params.add(signature);
}
}
/* JVM type signature. */
typeSignature = "(";
// Gets indivisual internal parameter signature.
while (params.isEmpty() != true) {
paramsig = params.remove(i).trim();
paramJVMSig = getParamJVMSignature(paramsig);
if (paramJVMSig != null) {
typeSignature += paramJVMSig;
}
}
typeSignature += ")";
// Get internal return type signature.
returnJVMType = "";
if (returnType != null) {
dimensions = dimensions(returnType);
}
//Gets array dimension of return type.
while (dimensions-- > 0) {
returnJVMType += "[";
}
if (returnType != null) {
returnSig = qualifiedTypeName(returnType);
returnJVMType += getComponentType(returnSig);
} else {
System.out.println("Invalid return type.");
}
typeSignature += returnJVMType;
return typeSignature;
}
/*
* Returns internal signature of a parameter.
*/
private String getParamJVMSignature(String paramsig) throws SignatureException {
String paramJVMSig = "";
String componentType ="";
if(paramsig != null){
if(paramsig.indexOf("[]") != -1) {
// Gets array dimension.
int endindex = paramsig.indexOf("[]");
componentType = paramsig.substring(0, endindex);
String dimensionString = paramsig.substring(endindex);
if(dimensionString != null){
while(dimensionString.indexOf("[]") != -1){
paramJVMSig += "[";
int beginindex = dimensionString.indexOf("]") + 1;
if(beginindex < dimensionString.length()){
dimensionString = dimensionString.substring(beginindex);
}else
dimensionString = "";
}
}
} else componentType = paramsig;
paramJVMSig += getComponentType(componentType);
}
return paramJVMSig;
}
/*
* Returns internal signature of a component.
*/
private String getComponentType(String componentType) throws SignatureException {
String JVMSig = "";
if(componentType != null){
if(componentType.equals("void")) JVMSig += SIG_VOID ;
else if(componentType.equals("boolean")) JVMSig += SIG_BOOLEAN ;
else if(componentType.equals("byte")) JVMSig += SIG_BYTE ;
else if(componentType.equals("char")) JVMSig += SIG_CHAR ;
else if(componentType.equals("short")) JVMSig += SIG_SHORT ;
else if(componentType.equals("int")) JVMSig += SIG_INT ;
else if(componentType.equals("long")) JVMSig += SIG_LONG ;
else if(componentType.equals("float")) JVMSig += SIG_FLOAT ;
else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ;
else {
if(!componentType.equals("")){
TypeElement classNameDoc = elems.getTypeElement(componentType);
if(classNameDoc == null){
throw new SignatureException(componentType);
}else {
String classname = classNameDoc.getQualifiedName().toString();
String newclassname = classname.replace('.', '/');
JVMSig += "L";
JVMSig += newclassname;
JVMSig += ";";
}
}
}
}
return JVMSig;
}
int dimensions(TypeMirror t) {
if (t.getKind() != TypeKind.ARRAY)
return 0;
return 1 + dimensions(((ArrayType) t).getComponentType());
}
String qualifiedTypeName(TypeMirror type) {
TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
@Override
public Name visitArray(ArrayType t, Void p) {
return t.getComponentType().accept(this, p);
}
@Override
public Name visitDeclared(DeclaredType t, Void p) {
return ((TypeElement) t.asElement()).getQualifiedName();
}
@Override
public Name visitPrimitive(PrimitiveType t, Void p) {
return elems.getName(t.toString());
}
@Override
public Name visitNoType(NoType t, Void p) {
if (t.getKind() == TypeKind.VOID)
return elems.getName("void");
return defaultAction(t, p);
}
@Override
public Name visitTypeVariable(TypeVariable t, Void p) {
return t.getUpperBound().accept(this, p);
}
};
return v.visit(type).toString();
}
}
}

View File

@@ -0,0 +1,324 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.ArrayUtils;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Filter;
import com.sun.tools.javac.util.Name;
import java.util.*;
/** An internal structure that corresponds to the constant pool of a classfile.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Pool {
public static final int MAX_ENTRIES = 0xFFFF;
public static final int MAX_STRING_LENGTH = 0xFFFF;
/** Index of next constant to be entered.
*/
int pp;
/** The initial pool buffer.
*/
Object[] pool;
/** A hashtable containing all constants in the pool.
*/
Map<Object,Integer> indices;
Types types;
/** Construct a pool with given number of elements and element array.
*/
public Pool(int pp, Object[] pool, Types types) {
this.pp = pp;
this.pool = pool;
this.types = types;
this.indices = new HashMap<Object,Integer>(pool.length);
for (int i = 1; i < pp; i++) {
if (pool[i] != null) indices.put(pool[i], i);
}
}
/** Construct an empty pool.
*/
public Pool(Types types) {
this(1, new Object[64], types);
}
/** Return the number of entries in the constant pool.
*/
public int numEntries() {
return pp;
}
/** Remove everything from this pool.
*/
public void reset() {
pp = 1;
indices.clear();
}
/** Place an object in the pool, unless it is already there.
* If object is a symbol also enter its owner unless the owner is a
* package. Return the object's index in the pool.
*/
public int put(Object value) {
value = makePoolValue(value);
// assert !(value instanceof Type.TypeVar);
Integer index = indices.get(value);
if (index == null) {
// System.err.println("put " + value + " " + value.getClass());//DEBUG
index = pp;
indices.put(value, index);
pool = ArrayUtils.ensureCapacity(pool, pp);
pool[pp++] = value;
if (value instanceof Long || value instanceof Double) {
pool = ArrayUtils.ensureCapacity(pool, pp);
pool[pp++] = null;
}
}
return index.intValue();
}
Object makePoolValue(Object o) {
if (o instanceof DynamicMethodSymbol) {
return new DynamicMethod((DynamicMethodSymbol)o, types);
} else if (o instanceof MethodSymbol) {
return new Method((MethodSymbol)o, types);
} else if (o instanceof VarSymbol) {
return new Variable((VarSymbol)o, types);
} else if (o instanceof Type) {
return new UniqueType((Type)o, types);
} else {
return o;
}
}
/** Return the given object's index in the pool,
* or -1 if object is not in there.
*/
public int get(Object o) {
Integer n = indices.get(o);
return n == null ? -1 : n.intValue();
}
static class Method extends DelegatedSymbol<MethodSymbol> {
UniqueType uniqueType;
Method(MethodSymbol m, Types types) {
super(m);
this.uniqueType = new UniqueType(m.type, types);
}
public boolean equals(Object any) {
if (!(any instanceof Method)) return false;
MethodSymbol o = ((Method)any).other;
MethodSymbol m = this.other;
return
o.name == m.name &&
o.owner == m.owner &&
((Method)any).uniqueType.equals(uniqueType);
}
public int hashCode() {
MethodSymbol m = this.other;
return
m.name.hashCode() * 33 +
m.owner.hashCode() * 9 +
uniqueType.hashCode();
}
}
static class DynamicMethod extends Method {
public Object[] uniqueStaticArgs;
DynamicMethod(DynamicMethodSymbol m, Types types) {
super(m, types);
uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
}
@Override
public boolean equals(Object any) {
if (!super.equals(any)) return false;
if (!(any instanceof DynamicMethod)) return false;
DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
return dm1.bsm == dm2.bsm &&
dm1.bsmKind == dm2.bsmKind &&
Arrays.equals(uniqueStaticArgs,
((DynamicMethod)any).uniqueStaticArgs);
}
@Override
public int hashCode() {
int hash = super.hashCode();
DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
hash += dm.bsmKind * 7 +
dm.bsm.hashCode() * 11;
for (int i = 0; i < dm.staticArgs.length; i++) {
hash += (uniqueStaticArgs[i].hashCode() * 23);
}
return hash;
}
private Object[] getUniqueTypeArray(Object[] objects, Types types) {
Object[] result = new Object[objects.length];
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof Type) {
result[i] = new UniqueType((Type)objects[i], types);
} else {
result[i] = objects[i];
}
}
return result;
}
}
static class Variable extends DelegatedSymbol<VarSymbol> {
UniqueType uniqueType;
Variable(VarSymbol v, Types types) {
super(v);
this.uniqueType = new UniqueType(v.type, types);
}
public boolean equals(Object any) {
if (!(any instanceof Variable)) return false;
VarSymbol o = ((Variable)any).other;
VarSymbol v = other;
return
o.name == v.name &&
o.owner == v.owner &&
((Variable)any).uniqueType.equals(uniqueType);
}
public int hashCode() {
VarSymbol v = other;
return
v.name.hashCode() * 33 +
v.owner.hashCode() * 9 +
uniqueType.hashCode();
}
}
public static class MethodHandle {
/** Reference kind - see ClassFile */
int refKind;
/** Reference symbol */
Symbol refSym;
UniqueType uniqueType;
public MethodHandle(int refKind, Symbol refSym, Types types) {
this.refKind = refKind;
this.refSym = refSym;
this.uniqueType = new UniqueType(this.refSym.type, types);
checkConsistent();
}
public boolean equals(Object other) {
if (!(other instanceof MethodHandle)) return false;
MethodHandle mr = (MethodHandle) other;
if (mr.refKind != refKind) return false;
Symbol o = mr.refSym;
return
o.name == refSym.name &&
o.owner == refSym.owner &&
((MethodHandle)other).uniqueType.equals(uniqueType);
}
public int hashCode() {
return
refKind * 65 +
refSym.name.hashCode() * 33 +
refSym.owner.hashCode() * 9 +
uniqueType.hashCode();
}
/**
* Check consistency of reference kind and symbol (see JVMS 4.4.8)
*/
@SuppressWarnings("fallthrough")
private void checkConsistent() {
boolean staticOk = false;
int expectedKind = -1;
Filter<Name> nameFilter = nonInitFilter;
boolean interfaceOwner = false;
switch (refKind) {
case ClassFile.REF_getStatic:
case ClassFile.REF_putStatic:
staticOk = true;
case ClassFile.REF_getField:
case ClassFile.REF_putField:
expectedKind = Kinds.VAR;
break;
case ClassFile.REF_newInvokeSpecial:
nameFilter = initFilter;
expectedKind = Kinds.MTH;
break;
case ClassFile.REF_invokeInterface:
interfaceOwner = true;
expectedKind = Kinds.MTH;
break;
case ClassFile.REF_invokeStatic:
interfaceOwner = true;
staticOk = true;
case ClassFile.REF_invokeVirtual:
expectedKind = Kinds.MTH;
break;
case ClassFile.REF_invokeSpecial:
interfaceOwner = true;
expectedKind = Kinds.MTH;
break;
}
Assert.check(!refSym.isStatic() || staticOk);
Assert.check(refSym.kind == expectedKind);
Assert.check(nameFilter.accepts(refSym.name));
Assert.check(!refSym.owner.isInterface() || interfaceOwner);
}
//where
Filter<Name> nonInitFilter = new Filter<Name>() {
public boolean accepts(Name n) {
return n != n.table.names.init && n != n.table.names.clinit;
}
};
Filter<Name> initFilter = new Filter<Name>() {
public boolean accepts(Name n) {
return n == n.table.names.init;
}
};
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Options;
import java.util.EnumSet;
import java.util.Set;
import static com.sun.tools.javac.main.Option.PROFILE;
/** The target profile.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public enum Profile {
COMPACT1("compact1", 1, Target.JDK1_8),
COMPACT2("compact2", 2, Target.JDK1_8),
COMPACT3("compact3", 3, Target.JDK1_8),
DEFAULT {
@Override
public boolean isValid(Target t) {
return true;
}
};
private static final Context.Key<Profile> profileKey =
new Context.Key<Profile>();
public static Profile instance(Context context) {
Profile instance = context.get(profileKey);
if (instance == null) {
Options options = Options.instance(context);
String profileString = options.get(PROFILE);
if (profileString != null) instance = lookup(profileString);
if (instance == null) instance = DEFAULT;
context.put(profileKey, instance);
}
return instance;
}
public final String name;
public final int value;
final Set<Target> targets;
Profile() {
name = null;
value = Integer.MAX_VALUE;
targets = null;
}
Profile(String name, int value, Target t, Target... targets) {
this.name = name;
this.value = value;
this.targets = EnumSet.of(t, targets);
}
public static Profile lookup(String name) {
// the set of values is small enough to do linear search
for (Profile p: values()) {
if (name.equals(p.name))
return p;
}
return null;
}
public static Profile lookup(int value) {
// the set of values is small enough to do linear search
for (Profile p: values()) {
if (value == p.value)
return p;
}
return null;
}
public boolean isValid(Target t) {
return targets.contains(t);
}
}

View File

@@ -0,0 +1,298 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import java.util.*;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.main.Option.TARGET;
/** The classfile version target.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public enum Target {
JDK1_1("1.1", 45, 3),
JDK1_2("1.2", 46, 0),
JDK1_3("1.3", 47, 0),
/** J2SE1.4 = Merlin. */
JDK1_4("1.4", 48, 0),
/** Tiger. */
JDK1_5("1.5", 49, 0),
/** JDK 6. */
JDK1_6("1.6", 50, 0),
/** JDK 7. */
JDK1_7("1.7", 51, 0),
/** JDK 8. */
JDK1_8("1.8", 52, 0);
private static final Context.Key<Target> targetKey =
new Context.Key<Target>();
public static Target instance(Context context) {
Target instance = context.get(targetKey);
if (instance == null) {
Options options = Options.instance(context);
String targetString = options.get(TARGET);
if (targetString != null) instance = lookup(targetString);
if (instance == null) instance = DEFAULT;
context.put(targetKey, instance);
}
return instance;
}
private static final Target MIN = values()[0];
public static Target MIN() { return MIN; }
private static final Target MAX = values()[values().length - 1];
public static Target MAX() { return MAX; }
private static final Map<String,Target> tab = new HashMap<String,Target>();
static {
for (Target t : values()) {
tab.put(t.name, t);
}
tab.put("5", JDK1_5);
tab.put("6", JDK1_6);
tab.put("7", JDK1_7);
tab.put("8", JDK1_8);
}
public final String name;
public final int majorVersion;
public final int minorVersion;
private Target(String name, int majorVersion, int minorVersion) {
this.name = name;
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
}
public static final Target DEFAULT = JDK1_8;
public static Target lookup(String name) {
return tab.get(name);
}
/** In -target 1.1 and earlier, the compiler is required to emit
* synthetic method definitions in abstract classes for interface
* methods that are not overridden. We call them "Miranda" methods.
*/
public boolean requiresIproxy() {
return compareTo(JDK1_1) <= 0;
}
/** Beginning in 1.4, we take advantage of the possibility of emitting
* code to initialize fields before calling the superclass constructor.
* This is allowed by the VM spec, but the verifier refused to allow
* it until 1.4. This is necesary to translate some code involving
* inner classes. See, for example, 4030374.
*/
public boolean initializeFieldsBeforeSuper() {
return compareTo(JDK1_4) >= 0;
}
/** Beginning with -target 1.2 we obey the JLS rules for binary
* compatibility, emitting as the qualifying type of a reference
* to a method or field the type of the qualifier. In earlier
* targets we use as the qualifying type the class in which the
* member was found. The following methods named
* *binaryCompatibility() indicate places where we vary from this
* general rule. */
public boolean obeyBinaryCompatibility() {
return compareTo(JDK1_2) >= 0;
}
/** Starting in 1.5, the compiler uses an array type as
* the qualifier for method calls (such as clone) where required by
* the language and VM spec. Earlier versions of the compiler
* qualified them by Object.
*/
public boolean arrayBinaryCompatibility() {
return compareTo(JDK1_5) >= 0;
}
/** Beginning after 1.2, we follow the binary compatibility rules for
* interface fields. The 1.2 VMs had bugs handling interface fields
* when compiled using binary compatibility (see 4400598), so this is
* an accommodation to them.
*/
public boolean interfaceFieldsBinaryCompatibility() {
return compareTo(JDK1_2) > 0;
}
/** Beginning in -target 1.5, we follow the binary compatibility
* rules for interface methods that redefine Object methods.
* Earlier VMs had bugs handling such methods compiled using binary
* compatibility (see 4392595, 4398791, 4392595, 4400415).
* The VMs were fixed during or soon after 1.4. See 4392595.
*/
public boolean interfaceObjectOverridesBinaryCompatibility() {
return compareTo(JDK1_5) >= 0;
}
/** Beginning in -target 1.5, we make synthetic variables
* package-private instead of private. This is to prevent the
* necessity of access methods, which effectively relax the
* protection of the field but bloat the class files and affect
* execution.
*/
public boolean usePrivateSyntheticFields() {
return compareTo(JDK1_5) < 0;
}
/** Sometimes we need to create a field to cache a value like a
* class literal of the assertions flag. In -target 1.5 and
* later we create a new synthetic class for this instead of
* using the outermost class. See 4401576.
*/
public boolean useInnerCacheClass() {
return compareTo(JDK1_5) >= 0;
}
/** Return true if cldc-style stack maps need to be generated. */
public boolean generateCLDCStackmap() {
return false;
}
/** Beginning in -target 6, we generate stackmap attribute in
* compact format. */
public boolean generateStackMapTable() {
return compareTo(JDK1_6) >= 0;
}
/** Beginning in -target 6, package-info classes are marked synthetic.
*/
public boolean isPackageInfoSynthetic() {
return compareTo(JDK1_6) >= 0;
}
/** Do we generate "empty" stackmap slots after double and long?
*/
public boolean generateEmptyAfterBig() {
return false;
}
/** Beginning in 1.5, we have an unsynchronized version of
* StringBuffer called StringBuilder that can be used by the
* compiler for string concatenation.
*/
public boolean useStringBuilder() {
return compareTo(JDK1_5) >= 0;
}
/** Beginning in 1.5, we have flag bits we can use instead of
* marker attributes.
*/
public boolean useSyntheticFlag() {
return compareTo(JDK1_5) >= 0;
}
public boolean useEnumFlag() {
return compareTo(JDK1_5) >= 0;
}
public boolean useAnnotationFlag() {
return compareTo(JDK1_5) >= 0;
}
public boolean useVarargsFlag() {
return compareTo(JDK1_5) >= 0;
}
public boolean useBridgeFlag() {
return compareTo(JDK1_5) >= 0;
}
/** Return the character to be used in constructing synthetic
* identifiers, where not specified by the JLS.
*/
public char syntheticNameChar() {
return '$';
}
/** Does the VM have direct support for class literals?
*/
public boolean hasClassLiterals() {
return compareTo(JDK1_5) >= 0;
}
/** Does the VM support an invokedynamic instruction?
*/
public boolean hasInvokedynamic() {
return compareTo(JDK1_7) >= 0;
}
/** Does the VM support polymorphic method handle invocation?
* Affects the linkage information output to the classfile.
* An alias for {@code hasInvokedynamic}, since all the JSR 292 features appear together.
*/
public boolean hasMethodHandles() {
return hasInvokedynamic();
}
/** Although we may not have support for class literals, should we
* avoid initializing the class that the literal refers to?
* See 4468823
*/
public boolean classLiteralsNoInit() {
return compareTo(JDK1_5) >= 0;
}
/** Although we may not have support for class literals, when we
* throw a NoClassDefFoundError, should we initialize its cause?
*/
public boolean hasInitCause() {
return compareTo(JDK1_4) >= 0;
}
/** For bootstrapping, we use J2SE1.4's wrapper class constructors
* to implement boxing.
*/
public boolean boxWithConstructors() {
return compareTo(JDK1_5) < 0;
}
/** For bootstrapping, we use J2SE1.4's java.util.Collection
* instead of java.lang.Iterable.
*/
public boolean hasIterable() {
return compareTo(JDK1_5) >= 0;
}
/** In J2SE1.5.0, we introduced the "EnclosingMethod" attribute
* for improved reflection support.
*/
public boolean hasEnclosingMethodAttribute() {
return compareTo(JDK1_5) >= 0;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*;
import static com.sun.tools.javac.code.TypeTag.UNINITIALIZED_OBJECT;
import static com.sun.tools.javac.code.TypeTag.UNINITIALIZED_THIS;
/** These pseudo-types appear in the generated verifier tables to
* indicate objects that have been allocated but not yet constructed.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
class UninitializedType extends Type.DelegatedType {
public static UninitializedType uninitializedThis(Type qtype) {
return new UninitializedType(UNINITIALIZED_THIS, qtype, -1);
}
public static UninitializedType uninitializedObject(Type qtype, int offset) {
return new UninitializedType(UNINITIALIZED_OBJECT, qtype, offset);
}
public final int offset; // PC where allocation took place
private UninitializedType(TypeTag tag, Type qtype, int offset) {
super(tag, qtype);
this.offset = offset;
}
Type initializedType() {
return qtype;
}
}