feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
310
jdkSrc/jdk8/com/sun/tools/javac/jvm/ByteCodes.java
Normal file
310
jdkSrc/jdk8/com/sun/tools/javac/jvm/ByteCodes.java
Normal 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"
|
||||
};
|
||||
}
|
||||
55
jdkSrc/jdk8/com/sun/tools/javac/jvm/CRTFlags.java
Normal file
55
jdkSrc/jdk8/com/sun/tools/javac/jvm/CRTFlags.java
Normal 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;
|
||||
}
|
||||
621
jdkSrc/jdk8/com/sun/tools/javac/jvm/CRTable.java
Normal file
621
jdkSrc/jdk8/com/sun/tools/javac/jvm/CRTable.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
196
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassFile.java
Normal file
196
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassFile.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
2965
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassReader.java
Normal file
2965
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassReader.java
Normal file
File diff suppressed because it is too large
Load Diff
1805
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassWriter.java
Normal file
1805
jdkSrc/jdk8/com/sun/tools/javac/jvm/ClassWriter.java
Normal file
File diff suppressed because it is too large
Load Diff
2441
jdkSrc/jdk8/com/sun/tools/javac/jvm/Code.java
Normal file
2441
jdkSrc/jdk8/com/sun/tools/javac/jvm/Code.java
Normal file
File diff suppressed because it is too large
Load Diff
2547
jdkSrc/jdk8/com/sun/tools/javac/jvm/Gen.java
Normal file
2547
jdkSrc/jdk8/com/sun/tools/javac/jvm/Gen.java
Normal file
File diff suppressed because it is too large
Load Diff
830
jdkSrc/jdk8/com/sun/tools/javac/jvm/Items.java
Normal file
830
jdkSrc/jdk8/com/sun/tools/javac/jvm/Items.java
Normal 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) + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
856
jdkSrc/jdk8/com/sun/tools/javac/jvm/JNIWriter.java
Normal file
856
jdkSrc/jdk8/com/sun/tools/javac/jvm/JNIWriter.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
324
jdkSrc/jdk8/com/sun/tools/javac/jvm/Pool.java
Normal file
324
jdkSrc/jdk8/com/sun/tools/javac/jvm/Pool.java
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
105
jdkSrc/jdk8/com/sun/tools/javac/jvm/Profile.java
Normal file
105
jdkSrc/jdk8/com/sun/tools/javac/jvm/Profile.java
Normal 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);
|
||||
}
|
||||
}
|
||||
298
jdkSrc/jdk8/com/sun/tools/javac/jvm/Target.java
Normal file
298
jdkSrc/jdk8/com/sun/tools/javac/jvm/Target.java
Normal 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;
|
||||
}
|
||||
}
|
||||
60
jdkSrc/jdk8/com/sun/tools/javac/jvm/UninitializedType.java
Normal file
60
jdkSrc/jdk8/com/sun/tools/javac/jvm/UninitializedType.java
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user