Merge
This commit is contained in:
commit
9928bdac3a
@ -49,3 +49,4 @@ e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
|
||||
0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
|
||||
3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73
|
||||
2c88089b6e1c053597418099a14232182c387edc jdk7-b74
|
||||
d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
|
||||
|
@ -545,7 +545,11 @@
|
||||
</li>
|
||||
<li>
|
||||
<strong>Windows:</strong>
|
||||
Make sure you start your build inside a bash/sh/ksh shell.
|
||||
Make sure you start your build inside a bash/sh/ksh shell
|
||||
and are using a <tt>make.exe</tt> utility built for that
|
||||
environment (a cygwin <tt>make.exe</tt> is not the same
|
||||
as a <tt>make.exe</tt> built for something like
|
||||
<a href="http://www.mkssoftware.com/">MKS</a>).
|
||||
<br>
|
||||
<b>WARNING:</b> Watch out for make version 3.81, it may
|
||||
not work due to a lack of support for MS-DOS drive letter paths
|
||||
@ -826,7 +830,8 @@
|
||||
All OpenJDK builds require access to the previously released
|
||||
JDK 6, this is often called a bootstrap JDK.
|
||||
The JDK 6 binaries can be downloaded from Sun's
|
||||
<a href="http://java.sun.com/javase/1.6.0/download.html" target="_blank">JDK 6 download site</a>.
|
||||
<a href="http://java.sun.com/javase/downloads/index.jsp"
|
||||
target="_blank">JDK 6 download site</a>.
|
||||
For build performance reasons
|
||||
is very important that this bootstrap JDK be made available on the
|
||||
local disk of the machine doing the build.
|
||||
|
@ -49,3 +49,4 @@ a12ea7c7b497b4ba7830550095ef633bd6f43971 jdk7-b67
|
||||
c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
|
||||
b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73
|
||||
5d0cf59a3203b9f57aceebc33ae656b884987955 jdk7-b74
|
||||
0fb137085952c8e47878e240d1cb40f14de463c4 jdk7-b75
|
||||
|
@ -99,8 +99,16 @@ CFLAGS_REQUIRED_sparcv9 += -m64 -mcpu=v9
|
||||
LDFLAGS_COMMON_sparcv9 += -m64 -mcpu=v9
|
||||
CFLAGS_REQUIRED_sparc += -m32 -mcpu=v9
|
||||
LDFLAGS_COMMON_sparc += -m32 -mcpu=v9
|
||||
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
|
||||
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
CFLAGS_REQUIRED = $(ZERO_ARCHFLAG)
|
||||
ifeq ($(ZERO_ENDIANNESS), little)
|
||||
CFLAGS_REQUIRED += -D_LITTLE_ENDIAN
|
||||
endif
|
||||
LDFLAGS_COMMON += $(ZERO_ARCHFLAG)
|
||||
else
|
||||
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
|
||||
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
|
||||
endif
|
||||
|
||||
# Add in platform specific optimizations for all opt levels
|
||||
CC_HIGHEST_OPT += $(_OPT_$(ARCH))
|
||||
@ -196,7 +204,7 @@ endif
|
||||
|
||||
EXTRA_LIBS += -lc
|
||||
|
||||
LDFLAGS_DEFS_OPTION = -z defs
|
||||
LDFLAGS_DEFS_OPTION = -Xlinker -z -Xlinker defs
|
||||
LDFLAGS_COMMON += $(LDFLAGS_DEFS_OPTION)
|
||||
|
||||
#
|
||||
|
@ -70,6 +70,11 @@ ifeq ($(PLATFORM), linux)
|
||||
else
|
||||
CXX = $(COMPILER_PATH)g++
|
||||
endif
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
# zero
|
||||
REQUIRED_CC_VER = 3.2
|
||||
REQUIRED_GCC_VER = 3.2.*
|
||||
else
|
||||
ifneq ("$(findstring sparc,$(ARCH))", "")
|
||||
# sparc or sparcv9
|
||||
REQUIRED_CC_VER = 4.0
|
||||
@ -88,6 +93,7 @@ ifeq ($(PLATFORM), linux)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
# Option used to create a shared library
|
||||
SHARED_LIBRARY_FLAG = -shared -mimpure-text
|
||||
SUN_COMP_VER := $(shell $(CC) --verbose 2>&1 )
|
||||
|
@ -49,3 +49,4 @@ d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68
|
||||
a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
|
||||
faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73
|
||||
f4b900403d6e4b0af51447bd13bbe23fe3a1dac7 jdk7-b74
|
||||
d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
|
||||
|
@ -48,8 +48,16 @@ if [ "$OS" = "Linux" ]; then
|
||||
CPU=i386
|
||||
fi
|
||||
else
|
||||
LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so
|
||||
export LD_AUDIT_32
|
||||
# configure audit helper library if SA_ALTROOT is set
|
||||
if [ -n "$SA_ALTROOT" ]; then
|
||||
LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so
|
||||
export LD_AUDIT_32
|
||||
if [ ! -f $LD_AUDIT_32 ]; then
|
||||
echo "SA_ALTROOT is set and can't find libsaproc_audit.so."
|
||||
echo "Make sure to build it with 'make natives'."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/solaris/`uname -p`
|
||||
OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
|
||||
CPU=sparc
|
||||
|
@ -43,8 +43,16 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so
|
||||
export LD_AUDIT_64
|
||||
# configure audit helper library if SA_ALTROOT is set
|
||||
if [ -n "$SA_ALTROOT" ]; then
|
||||
LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so
|
||||
export LD_AUDIT_64
|
||||
if [ ! -f $LD_AUDIT_64 ]; then
|
||||
echo "SA_ALTROOT is set and can't find libsaproc_audit.so."
|
||||
echo "Make sure to build it with 'make natives'."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/$CPU:$STARTDIR/solaris/$CPU
|
||||
|
||||
OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
|
||||
|
@ -926,6 +926,28 @@ public class CommandProcessor {
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("dumpcodecache", "dumpcodecache", false) {
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 0) {
|
||||
usage();
|
||||
} else {
|
||||
final PrintStream fout = out;
|
||||
final HTMLGenerator gen = new HTMLGenerator(false);
|
||||
CodeCacheVisitor v = new CodeCacheVisitor() {
|
||||
public void prologue(Address start, Address end) {
|
||||
}
|
||||
public void visit(CodeBlob blob) {
|
||||
fout.println(gen.genHTML(blob.instructionsBegin()));
|
||||
}
|
||||
public void epilogue() {
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
VM.getVM().getCodeCache().iterate(v);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("where", "where { -a | id }", false) {
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 1) {
|
||||
|
@ -173,7 +173,8 @@ public class CodeCache {
|
||||
CodeBlob lastBlob = null;
|
||||
while (ptr != null && ptr.lessThan(end)) {
|
||||
try {
|
||||
CodeBlob blob = findBlobUnsafe(ptr);
|
||||
// Use findStart to get a pointer inside blob other findBlob asserts
|
||||
CodeBlob blob = findBlobUnsafe(heap.findStart(ptr));
|
||||
if (blob != null) {
|
||||
visitor.visit(blob);
|
||||
if (blob == lastBlob) {
|
||||
|
@ -42,7 +42,7 @@ public class NMethod extends CodeBlob {
|
||||
/** To support simple linked-list chaining of nmethods */
|
||||
private static AddressField osrLinkField;
|
||||
private static AddressField scavengeRootLinkField;
|
||||
private static CIntegerField scavengeRootStateField;
|
||||
private static JByteField scavengeRootStateField;
|
||||
|
||||
/** Offsets for different nmethod parts */
|
||||
private static CIntegerField exceptionOffsetField;
|
||||
@ -92,7 +92,7 @@ public class NMethod extends CodeBlob {
|
||||
entryBCIField = type.getCIntegerField("_entry_bci");
|
||||
osrLinkField = type.getAddressField("_osr_link");
|
||||
scavengeRootLinkField = type.getAddressField("_scavenge_root_link");
|
||||
scavengeRootStateField = type.getCIntegerField("_scavenge_root_state");
|
||||
scavengeRootStateField = type.getJByteField("_scavenge_root_state");
|
||||
|
||||
exceptionOffsetField = type.getCIntegerField("_exception_offset");
|
||||
deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
|
||||
@ -274,7 +274,7 @@ public class NMethod extends CodeBlob {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(pd != null, "scope must be present");
|
||||
}
|
||||
return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
|
||||
return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
|
||||
}
|
||||
|
||||
/** This is only for use by the debugging system, and is only
|
||||
@ -306,11 +306,11 @@ public class NMethod extends CodeBlob {
|
||||
public ScopeDesc getScopeDescNearDbg(Address pc) {
|
||||
PCDesc pd = getPCDescNearDbg(pc);
|
||||
if (pd == null) return null;
|
||||
return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
|
||||
return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
|
||||
}
|
||||
|
||||
public Map/*<Address, PcDesc>*/ getSafepoints() {
|
||||
Map safepoints = new HashMap(); // Map<Address, PcDesc>
|
||||
public Map/*<Address, PCDesc>*/ getSafepoints() {
|
||||
Map safepoints = new HashMap(); // Map<Address, PCDesc>
|
||||
sun.jvm.hotspot.debugger.Address p = null;
|
||||
for (p = scopesPCsBegin(); p.lessThan(scopesPCsEnd());
|
||||
p = p.addOffsetTo(pcDescSize)) {
|
||||
|
@ -36,6 +36,7 @@ import sun.jvm.hotspot.types.*;
|
||||
public class PCDesc extends VMObject {
|
||||
private static CIntegerField pcOffsetField;
|
||||
private static CIntegerField scopeDecodeOffsetField;
|
||||
private static CIntegerField objDecodeOffsetField;
|
||||
private static CIntegerField pcFlagsField;
|
||||
|
||||
static {
|
||||
@ -51,6 +52,7 @@ public class PCDesc extends VMObject {
|
||||
|
||||
pcOffsetField = type.getCIntegerField("_pc_offset");
|
||||
scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset");
|
||||
objDecodeOffsetField = type.getCIntegerField("_obj_decode_offset");
|
||||
pcFlagsField = type.getCIntegerField("_flags");
|
||||
}
|
||||
|
||||
@ -68,6 +70,10 @@ public class PCDesc extends VMObject {
|
||||
return ((int) scopeDecodeOffsetField.getValue(addr));
|
||||
}
|
||||
|
||||
public int getObjDecodeOffset() {
|
||||
return ((int) objDecodeOffsetField.getValue(addr));
|
||||
}
|
||||
|
||||
public Address getRealPC(NMethod code) {
|
||||
return code.instructionsBegin().addOffsetTo(getPCOffset());
|
||||
}
|
||||
|
@ -51,11 +51,10 @@ public class ScopeDesc {
|
||||
/** Scalar replaced bjects pool */
|
||||
private List objects; // ArrayList<ScopeValue>
|
||||
|
||||
|
||||
public ScopeDesc(NMethod code, int decodeOffset, boolean reexecute) {
|
||||
private ScopeDesc(NMethod code, int decodeOffset, List objects, boolean reexecute) {
|
||||
this.code = code;
|
||||
this.decodeOffset = decodeOffset;
|
||||
this.objects = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL);
|
||||
this.objects = objects;
|
||||
this.reexecute = reexecute;
|
||||
|
||||
// Decode header
|
||||
@ -108,7 +107,7 @@ public class ScopeDesc {
|
||||
return decodeMonitorValues(monitorsDecodeOffset);
|
||||
}
|
||||
|
||||
/** Returns a List<MonitorValue> */
|
||||
/** Returns a List<ObjectValue> */
|
||||
public List getObjects() {
|
||||
return objects;
|
||||
}
|
||||
@ -119,7 +118,7 @@ public class ScopeDesc {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ScopeDesc(code, senderDecodeOffset, false);
|
||||
return new ScopeDesc(code, senderDecodeOffset, objects, false);
|
||||
}
|
||||
|
||||
/** Returns where the scope was decoded */
|
||||
|
@ -807,6 +807,9 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
Interpreter interp = VM.getVM().getInterpreter();
|
||||
if (interp.contains(pc)) {
|
||||
InterpreterCodelet codelet = interp.getCodeletContaining(pc);
|
||||
if (codelet == null) {
|
||||
return "Unknown location in the Interpreter: " + pc;
|
||||
}
|
||||
return genHTML(codelet);
|
||||
}
|
||||
return genHTML(blob);
|
||||
@ -969,16 +972,24 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
}
|
||||
|
||||
protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) {
|
||||
ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm));
|
||||
Formatter buf = new Formatter(genHTML);
|
||||
Formatter tabs = new Formatter(genHTML);
|
||||
ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm));
|
||||
Formatter buf = new Formatter(genHTML);
|
||||
Formatter tabs = new Formatter(genHTML);
|
||||
tabs.append(tab + tab + tab); // Initial indent for debug info
|
||||
|
||||
buf.beginTag("pre");
|
||||
genScope(buf, tabs, sd);
|
||||
buf.endTag("pre");
|
||||
buf.append(genOopMapInfo(nm, pcDesc));
|
||||
buf.beginTag("pre");
|
||||
genScope(buf, tabs, sd);
|
||||
|
||||
return buf.toString();
|
||||
// Reset indent for scalar replaced objects
|
||||
tabs = new Formatter(genHTML);
|
||||
tabs.append(tab + tab + tab); // Initial indent for debug info
|
||||
|
||||
genScObjInfo(buf, tabs, sd);
|
||||
buf.endTag("pre");
|
||||
|
||||
buf.append(genOopMapInfo(nm, pcDesc));
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) {
|
||||
@ -1022,8 +1033,95 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
buf.append(genHTMLForMonitors(sd, monitors));
|
||||
}
|
||||
|
||||
tabs.append(tab);
|
||||
buf.br();
|
||||
tabs.append(tab);
|
||||
}
|
||||
|
||||
protected void genScObjInfo(Formatter buf, Formatter tabs, ScopeDesc sd) {
|
||||
if (sd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List objects = sd.getObjects();
|
||||
if (objects == null) {
|
||||
return;
|
||||
}
|
||||
int length = objects.size();
|
||||
for (int i = 0; i < length; i++) {
|
||||
buf.append(tabs);
|
||||
ObjectValue ov = (ObjectValue)objects.get(i);
|
||||
buf.append("ScObj" + i);
|
||||
ScopeValue sv = ov.getKlass();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(sv.isConstantOop(), "scalar replaced object klass must be constant oop");
|
||||
}
|
||||
ConstantOopReadValue klv = (ConstantOopReadValue)sv;
|
||||
OopHandle klHandle = klv.getValue();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(klHandle != null, "scalar replaced object klass must be not NULL");
|
||||
}
|
||||
Oop obj = VM.getVM().getObjectHeap().newOop(klHandle);
|
||||
if (obj instanceof InstanceKlass) {
|
||||
InstanceKlass kls = (InstanceKlass) obj;
|
||||
buf.append(" " + kls.getName().asString() + "={");
|
||||
int flen = ov.fieldsSize();
|
||||
|
||||
TypeArray klfields = kls.getFields();
|
||||
int klen = (int) klfields.getLength();
|
||||
|
||||
ConstantPool cp = kls.getConstants();
|
||||
int findex = 0;
|
||||
for (int index = 0; index < klen; index += kls.NEXT_OFFSET) {
|
||||
int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET);
|
||||
int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET);
|
||||
AccessFlags access = new AccessFlags(accsFlags);
|
||||
if (!access.isStatic()) {
|
||||
ScopeValue svf = ov.getFieldAt(findex++);
|
||||
String fstr = scopeValueAsString(sd, svf);
|
||||
Symbol f_name = cp.getSymbolAt(nameIndex);
|
||||
buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")");
|
||||
}
|
||||
}
|
||||
buf.append(" }");
|
||||
} else {
|
||||
buf.append(" ");
|
||||
int flen = ov.fieldsSize();
|
||||
if (obj instanceof TypeArrayKlass) {
|
||||
TypeArrayKlass kls = (TypeArrayKlass) obj;
|
||||
buf.append(kls.getElementTypeName() + "[" + flen + "]");
|
||||
} else if (obj instanceof ObjArrayKlass) {
|
||||
ObjArrayKlass kls = (ObjArrayKlass) obj;
|
||||
Klass elobj = kls.getBottomKlass();
|
||||
if (elobj instanceof InstanceKlass) {
|
||||
buf.append(elobj.getName().asString());
|
||||
} else if (elobj instanceof TypeArrayKlass) {
|
||||
TypeArrayKlass elkls = (TypeArrayKlass) elobj;
|
||||
buf.append(elkls.getElementTypeName());
|
||||
} else {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(false, "unknown scalar replaced object klass!");
|
||||
}
|
||||
}
|
||||
buf.append("[" + flen + "]");
|
||||
int ndim = (int) kls.getDimension();
|
||||
while (--ndim > 0) {
|
||||
buf.append("[]");
|
||||
}
|
||||
} else {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(false, "unknown scalar replaced object klass!");
|
||||
}
|
||||
}
|
||||
buf.append("={");
|
||||
for (int findex = 0; findex < flen; findex++) {
|
||||
ScopeValue svf = ov.getFieldAt(findex);
|
||||
String fstr = scopeValueAsString(sd, svf);
|
||||
buf.append(" [" + findex + "]=(#" + fstr + ")");
|
||||
}
|
||||
buf.append(" }");
|
||||
}
|
||||
buf.br();
|
||||
}
|
||||
}
|
||||
|
||||
protected String genHTMLForOopMap(OopMap map) {
|
||||
@ -1037,8 +1135,6 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
tmpBuf.beginTag("tr");
|
||||
tmpBuf.beginTag("td");
|
||||
tmpBuf.append(type);
|
||||
tmpBuf.endTag("td");
|
||||
tmpBuf.endTag("tr");
|
||||
for (; ! oms.isDone(); oms.next()) {
|
||||
OopMapValue omv = oms.getCurrent();
|
||||
if (omv == null) {
|
||||
@ -1048,7 +1144,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
VMReg vmReg = omv.getReg();
|
||||
int reg = vmReg.getValue();
|
||||
if (reg < stack0) {
|
||||
tmpBuf.append(VMRegImpl.getRegisterName(vmReg.getValue()));
|
||||
tmpBuf.append(VMRegImpl.getRegisterName(reg));
|
||||
} else {
|
||||
tmpBuf.append('[');
|
||||
tmpBuf.append(Integer.toString((reg - stack0) * 4));
|
||||
@ -1058,7 +1154,13 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
tmpBuf.append(" = ");
|
||||
VMReg vmContentReg = omv.getContentReg();
|
||||
int contentReg = vmContentReg.getValue();
|
||||
tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue()));
|
||||
if (contentReg < stack0) {
|
||||
tmpBuf.append(VMRegImpl.getRegisterName(contentReg));
|
||||
} else {
|
||||
tmpBuf.append('[');
|
||||
tmpBuf.append(Integer.toString((contentReg - stack0) * 4));
|
||||
tmpBuf.append(']');
|
||||
}
|
||||
}
|
||||
tmpBuf.append(spaces);
|
||||
}
|
||||
@ -1072,19 +1174,19 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
|
||||
OopMapValueIterator omvIterator = new OopMapValueIterator();
|
||||
OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Oop:", false));
|
||||
|
||||
oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Value:", false));
|
||||
buf.append(omvIterator.iterate(oms, "Oops:", false));
|
||||
|
||||
oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Oop:", false));
|
||||
buf.append(omvIterator.iterate(oms, "narrowOops:", false));
|
||||
|
||||
oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Values:", false));
|
||||
|
||||
oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Callee saved:", true));
|
||||
|
||||
oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE);
|
||||
buf.append(omvIterator.iterate(oms, "Derived oop:", true));
|
||||
buf.append(omvIterator.iterate(oms, "Derived oops:", true));
|
||||
|
||||
buf.endTag("table");
|
||||
return buf.toString();
|
||||
@ -1093,6 +1195,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
|
||||
protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
|
||||
OopMapSet mapSet = nmethod.getOopMaps();
|
||||
if (mapSet == null || (mapSet.getSize() <= 0))
|
||||
return "";
|
||||
int pcOffset = pcDesc.getPCOffset();
|
||||
OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
|
||||
if (map == null) {
|
||||
@ -1106,6 +1210,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
Formatter buf = new Formatter(genHTML);
|
||||
buf.beginTag("pre");
|
||||
buf.append("OopMap: ");
|
||||
buf.br();
|
||||
buf.append(genHTMLForOopMap(map));
|
||||
buf.endTag("pre");
|
||||
|
||||
@ -1154,7 +1259,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String scopeValueAsString(ScopeValue sv) {
|
||||
private String scopeValueAsString(ScopeDesc sd, ScopeValue sv) {
|
||||
Formatter buf = new Formatter(genHTML);
|
||||
if (sv.isConstantInt()) {
|
||||
buf.append("int ");
|
||||
@ -1187,6 +1292,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
} else {
|
||||
buf.append("null");
|
||||
}
|
||||
} else if (sv.isObject()) {
|
||||
ObjectValue ov = (ObjectValue)sv;
|
||||
buf.append("#ScObj" + sd.getObjects().indexOf(ov));
|
||||
} else {
|
||||
buf.append("unknown scope value " + sv);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
@ -1219,7 +1329,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
}
|
||||
|
||||
buf.append(", ");
|
||||
buf.append(scopeValueAsString(sv));
|
||||
buf.append(scopeValueAsString(sd, sv));
|
||||
buf.append(") ");
|
||||
}
|
||||
|
||||
@ -1246,7 +1356,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
buf.append("(owner = ");
|
||||
ScopeValue owner = mv.owner();
|
||||
if (owner != null) {
|
||||
buf.append(scopeValueAsString(owner));
|
||||
buf.append(scopeValueAsString(sd, owner));
|
||||
} else {
|
||||
buf.append("null");
|
||||
}
|
||||
@ -1324,11 +1434,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||
buf.append(instr.asString(currentPc, symFinder));
|
||||
}
|
||||
|
||||
buf.br();
|
||||
if (isSafepoint && !prevWasCall) {
|
||||
buf.append(genSafepointInfo(nmethod, pcDesc));
|
||||
buf.append(genSafepointInfo(nmethod, pcDesc));
|
||||
}
|
||||
|
||||
buf.br();
|
||||
prevWasCall = instr.isCall();
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1047,7 @@ while (tmp.itr.hasNext()) {
|
||||
} else {
|
||||
// some type names have ':'. replace to make it as a
|
||||
// JavaScript identifier
|
||||
tmp.name = tmp.name.replace(':', '_');
|
||||
tmp.name = tmp.name.replace(':', '_').replace('<', '_').replace('>', '_').replace('*', '_').replace(' ', '_');
|
||||
eval("function read" + tmp.name + "(addr) {" +
|
||||
" return readVMType('" + tmp.name + "', addr);}");
|
||||
eval("function print" + tmp.name + "(addr) {" +
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||
|
||||
HS_MAJOR_VER=17
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=04
|
||||
HS_BUILD_NUMBER=05
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=7
|
||||
|
@ -3213,9 +3213,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
Register Oreturn0 = O0;
|
||||
Register Oreturn1 = O1;
|
||||
Register O2UnrollBlock = O2;
|
||||
Register O3tmp = O3;
|
||||
Register I5exception_tmp = I5;
|
||||
Register G4exception_tmp = G4_scratch;
|
||||
Register L0deopt_mode = L0;
|
||||
Register G4deopt_mode = G4_scratch;
|
||||
int frame_size_words;
|
||||
Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS);
|
||||
#if !defined(_LP64) && defined(COMPILER2)
|
||||
@ -3265,7 +3264,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
|
||||
map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
|
||||
__ ba(false, cont);
|
||||
__ delayed()->mov(Deoptimization::Unpack_deopt, I5exception_tmp);
|
||||
__ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
|
||||
|
||||
int exception_offset = __ offset() - start;
|
||||
|
||||
@ -3316,7 +3315,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
#endif
|
||||
|
||||
__ ba(false, cont);
|
||||
__ delayed()->mov(Deoptimization::Unpack_exception, I5exception_tmp);;
|
||||
__ delayed()->mov(Deoptimization::Unpack_exception, L0deopt_mode);;
|
||||
|
||||
//
|
||||
// Reexecute entry, similar to c2 uncommon trap
|
||||
@ -3326,7 +3325,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// No need to update oop_map as each call to save_live_registers will produce identical oopmap
|
||||
(void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
|
||||
|
||||
__ mov(Deoptimization::Unpack_reexecute, I5exception_tmp);
|
||||
__ mov(Deoptimization::Unpack_reexecute, L0deopt_mode);
|
||||
|
||||
__ bind(cont);
|
||||
|
||||
@ -3349,14 +3348,14 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
|
||||
// so this move will survive
|
||||
|
||||
__ mov(I5exception_tmp, G4exception_tmp);
|
||||
__ mov(L0deopt_mode, G4deopt_mode);
|
||||
|
||||
__ mov(O0, O2UnrollBlock->after_save());
|
||||
|
||||
RegisterSaver::restore_result_registers(masm);
|
||||
|
||||
Label noException;
|
||||
__ cmp(G4exception_tmp, Deoptimization::Unpack_exception); // Was exception pending?
|
||||
__ cmp(G4deopt_mode, Deoptimization::Unpack_exception); // Was exception pending?
|
||||
__ br(Assembler::notEqual, false, Assembler::pt, noException);
|
||||
__ delayed()->nop();
|
||||
|
||||
@ -3390,10 +3389,10 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
}
|
||||
#endif
|
||||
__ set_last_Java_frame(SP, noreg);
|
||||
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4exception_tmp);
|
||||
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode);
|
||||
#else
|
||||
// LP64 uses g4 in set_last_Java_frame
|
||||
__ mov(G4exception_tmp, O1);
|
||||
__ mov(G4deopt_mode, O1);
|
||||
__ set_last_Java_frame(SP, G0);
|
||||
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1);
|
||||
#endif
|
||||
@ -3446,7 +3445,6 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
#endif
|
||||
MacroAssembler* masm = new MacroAssembler(&buffer);
|
||||
Register O2UnrollBlock = O2;
|
||||
Register O3tmp = O3;
|
||||
Register O2klass_index = O2;
|
||||
|
||||
//
|
||||
|
@ -9419,8 +9419,9 @@ instruct countLeadingZerosI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{
|
||||
// x |= (x >> 8);
|
||||
// x |= (x >> 16);
|
||||
// return (WORDBITS - popc(x));
|
||||
format %{ "SRL $src,1,$dst\t! count leading zeros (int)\n\t"
|
||||
"OR $src,$tmp,$dst\n\t"
|
||||
format %{ "SRL $src,1,$tmp\t! count leading zeros (int)\n\t"
|
||||
"SRL $src,0,$dst\t! 32-bit zero extend\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRL $dst,2,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRL $dst,4,$tmp\n\t"
|
||||
@ -9437,7 +9438,8 @@ instruct countLeadingZerosI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{
|
||||
Register Rsrc = $src$$Register;
|
||||
Register Rtmp = $tmp$$Register;
|
||||
__ srl(Rsrc, 1, Rtmp);
|
||||
__ or3(Rsrc, Rtmp, Rdst);
|
||||
__ srl(Rsrc, 0, Rdst);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srl(Rdst, 2, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srl(Rdst, 4, Rtmp);
|
||||
@ -9465,7 +9467,7 @@ instruct countLeadingZerosL(iRegI dst, iRegL src, iRegL tmp, flagsReg cr) %{
|
||||
// x |= (x >> 16);
|
||||
// x |= (x >> 32);
|
||||
// return (WORDBITS - popc(x));
|
||||
format %{ "SRLX $src,1,$dst\t! count leading zeros (long)\n\t"
|
||||
format %{ "SRLX $src,1,$tmp\t! count leading zeros (long)\n\t"
|
||||
"OR $src,$tmp,$dst\n\t"
|
||||
"SRLX $dst,2,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
|
@ -8214,6 +8214,15 @@ void MacroAssembler::store_heap_oop(Address dst, Register src) {
|
||||
}
|
||||
}
|
||||
|
||||
// Used for storing NULLs.
|
||||
void MacroAssembler::store_heap_oop_null(Address dst) {
|
||||
if (UseCompressedOops) {
|
||||
movl(dst, (int32_t)NULL_WORD);
|
||||
} else {
|
||||
movslq(dst, (int32_t)NULL_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
// Algorithm must match oop.inline.hpp encode_heap_oop.
|
||||
void MacroAssembler::encode_heap_oop(Register r) {
|
||||
assert (UseCompressedOops, "should be compressed");
|
||||
|
@ -1682,6 +1682,17 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
void load_heap_oop(Register dst, Address src);
|
||||
void store_heap_oop(Address dst, Register src);
|
||||
|
||||
// This dummy is to prevent a call to store_heap_oop from
|
||||
// converting a zero (like NULL) into a Register by giving
|
||||
// the compiler two choices it can't resolve
|
||||
|
||||
void store_heap_oop(Address dst, void* dummy);
|
||||
|
||||
// Used for storing NULL. All other oop constants should be
|
||||
// stored using routines that take a jobject.
|
||||
void store_heap_oop_null(Address dst);
|
||||
|
||||
void encode_heap_oop(Register r);
|
||||
void decode_heap_oop(Register r);
|
||||
void encode_heap_oop_not_null(Register r);
|
||||
|
@ -271,9 +271,15 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||
void trace_method_handle_stub(const char* adaptername,
|
||||
oopDesc* mh,
|
||||
intptr_t* entry_sp,
|
||||
intptr_t* saved_sp) {
|
||||
intptr_t* saved_sp,
|
||||
intptr_t* saved_bp) {
|
||||
// called as a leaf from native code: do not block the JVM!
|
||||
printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp);
|
||||
intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
|
||||
intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
|
||||
printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
|
||||
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
|
||||
if (last_sp != saved_sp)
|
||||
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
@ -293,6 +299,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
Register rbx_temp = rbx;
|
||||
Register rdx_temp = rdx;
|
||||
|
||||
// This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls)
|
||||
// and gen_c2i_adapter (from compiled calls):
|
||||
Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi);
|
||||
|
||||
guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
|
||||
|
||||
// some handy addresses
|
||||
@ -315,6 +325,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
assert(tag_offset = wordSize, "stack grows as expected");
|
||||
}
|
||||
|
||||
const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
|
||||
|
||||
if (have_entry(ek)) {
|
||||
__ nop(); // empty stubs make SG sick
|
||||
return;
|
||||
@ -328,45 +340,65 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
|
||||
__ lea(rax, Address(rsp, wordSize*6)); // entry_sp
|
||||
// arguments:
|
||||
__ push(rbp); // interpreter frame pointer
|
||||
__ push(rsi); // saved_sp
|
||||
__ push(rax); // entry_sp
|
||||
__ push(rcx); // mh
|
||||
__ push(rcx);
|
||||
__ movptr(Address(rsp, 0), (intptr_t)entry_name(ek));
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5);
|
||||
__ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
switch ((int) ek) {
|
||||
case _check_mtype:
|
||||
case _raise_exception:
|
||||
{
|
||||
// this stub is special, because it requires a live mtype argument
|
||||
Register rax_mtype = rax;
|
||||
// Not a real MH entry, but rather shared code for raising an exception.
|
||||
// Extra local arguments are pushed on stack, as required type at TOS+8,
|
||||
// failing object (or NULL) at TOS+4, failing bytecode type at TOS.
|
||||
// Beyond those local arguments are the PC, of course.
|
||||
Register rdx_code = rdx_temp;
|
||||
Register rcx_fail = rcx_recv;
|
||||
Register rax_want = rax_argslot;
|
||||
Register rdi_pc = rdi;
|
||||
__ pop(rdx_code); // TOS+0
|
||||
__ pop(rcx_fail); // TOS+4
|
||||
__ pop(rax_want); // TOS+8
|
||||
__ pop(rdi_pc); // caller PC
|
||||
|
||||
// emit WrongMethodType path first, to enable jccb back-branch
|
||||
Label wrong_method_type;
|
||||
__ bind(wrong_method_type);
|
||||
__ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type]));
|
||||
__ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
|
||||
__ hlt();
|
||||
__ mov(rsp, rsi); // cut the stack back to where the caller started
|
||||
|
||||
interp_entry = __ pc();
|
||||
__ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
|
||||
// now rax_mtype is dead; subsequent stubs will use it as a temp
|
||||
// Repush the arguments as if coming from the interpreter.
|
||||
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT));
|
||||
__ push(rdx_code);
|
||||
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
|
||||
__ push(rcx_fail);
|
||||
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
|
||||
__ push(rax_want);
|
||||
|
||||
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
||||
}
|
||||
break;
|
||||
Register rbx_method = rbx_temp;
|
||||
Label no_method;
|
||||
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
|
||||
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
|
||||
__ testptr(rbx_method, rbx_method);
|
||||
__ jcc(Assembler::zero, no_method);
|
||||
int jobject_oop_offset = 0;
|
||||
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
|
||||
__ testptr(rbx_method, rbx_method);
|
||||
__ jcc(Assembler::zero, no_method);
|
||||
__ verify_oop(rbx_method);
|
||||
__ push(rdi_pc); // and restore caller PC
|
||||
__ jmp(rbx_method_fie);
|
||||
|
||||
case _wrong_method_type:
|
||||
{
|
||||
// this stub is special, because it requires a live mtype argument
|
||||
Register rax_mtype = rax;
|
||||
|
||||
interp_entry = __ pc();
|
||||
__ push(rax_mtype); // required mtype
|
||||
__ push(rcx_recv); // random mh (1st stacked argument)
|
||||
// If we get here, the Java runtime did not do its job of creating the exception.
|
||||
// Do something that is at least causes a valid throw from the interpreter.
|
||||
__ bind(no_method);
|
||||
__ pop(rax_want);
|
||||
if (TaggedStackInterpreter) __ pop(rcx_fail);
|
||||
__ pop(rcx_fail);
|
||||
__ push(rax_want);
|
||||
__ push(rcx_fail);
|
||||
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
|
||||
}
|
||||
break;
|
||||
@ -442,7 +474,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ load_klass(rax_klass, rcx_recv);
|
||||
__ verify_oop(rax_klass);
|
||||
|
||||
Register rcx_temp = rcx_recv;
|
||||
Register rdi_temp = rdi;
|
||||
Register rbx_method = rbx_index;
|
||||
|
||||
// get interface klass
|
||||
@ -451,7 +483,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ lookup_interface_method(rax_klass, rdx_intf,
|
||||
// note: next two args must be the same:
|
||||
rbx_index, rbx_method,
|
||||
rcx_temp,
|
||||
rdi_temp,
|
||||
no_such_interface);
|
||||
|
||||
__ verify_oop(rbx_method);
|
||||
@ -461,7 +493,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ bind(no_such_interface);
|
||||
// Throw an exception.
|
||||
// For historical reasons, it will be IncompatibleClassChangeError.
|
||||
__ should_not_reach_here(); // %%% FIXME NYI
|
||||
__ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface
|
||||
__ push(rcx_recv); // bad receiver
|
||||
__ push((int)Bytecodes::_invokeinterface); // who is complaining?
|
||||
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -524,6 +559,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
break;
|
||||
|
||||
case _adapter_retype_only:
|
||||
case _adapter_retype_raw:
|
||||
// immediately jump to the next MH layer:
|
||||
__ movptr(rcx_recv, rcx_mh_vmtarget);
|
||||
__ verify_oop(rcx_recv);
|
||||
@ -545,10 +581,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
|
||||
__ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
|
||||
|
||||
// get the new MH:
|
||||
__ movptr(rcx_recv, rcx_mh_vmtarget);
|
||||
// (now we are done with the old MH)
|
||||
|
||||
Label done;
|
||||
__ movptr(rdx_temp, vmarg);
|
||||
__ testl(rdx_temp, rdx_temp);
|
||||
@ -558,17 +590,23 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
// live at this point:
|
||||
// - rbx_klass: klass required by the target method
|
||||
// - rdx_temp: argument klass to test
|
||||
// - rcx_recv: method handle to invoke (after cast succeeds)
|
||||
// - rcx_recv: adapter method handle
|
||||
__ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
|
||||
|
||||
// If we get here, the type check failed!
|
||||
// Call the wrong_method_type stub, passing the failing argument type in rax.
|
||||
Register rax_mtype = rax_argslot;
|
||||
__ push(rbx_klass); // missed klass (required type)
|
||||
__ push(rdx_temp); // bad actual type (1st stacked argument)
|
||||
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
|
||||
__ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field
|
||||
__ movptr(rdx_temp, vmarg);
|
||||
|
||||
__ pushptr(rcx_amh_argument); // required class
|
||||
__ push(rdx_temp); // bad object
|
||||
__ push((int)Bytecodes::_checkcast); // who is complaining?
|
||||
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
|
||||
|
||||
__ bind(done);
|
||||
// get the new MH:
|
||||
__ movptr(rcx_recv, rcx_mh_vmtarget);
|
||||
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
||||
}
|
||||
break;
|
||||
@ -1107,11 +1145,17 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
|
||||
__ bind(bad_array_klass);
|
||||
UNPUSH_RSI_RDI;
|
||||
__ stop("bad array klass NYI");
|
||||
__ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type
|
||||
__ pushptr(vmarg); // bad array
|
||||
__ push((int)Bytecodes::_aaload); // who is complaining?
|
||||
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
|
||||
|
||||
__ bind(bad_array_length);
|
||||
UNPUSH_RSI_RDI;
|
||||
__ stop("bad array length NYI");
|
||||
__ push(rcx_recv); // AMH requiring a certain length
|
||||
__ pushptr(vmarg); // bad array
|
||||
__ push((int)Bytecodes::_arraylength); // who is complaining?
|
||||
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
|
||||
|
||||
#undef UNPUSH_RSI_RDI
|
||||
}
|
||||
|
@ -92,8 +92,7 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
|
||||
// pc at TOS (just for debugging)
|
||||
// Arguments are: required type at TOS+4, failing object (or NULL) at TOS.
|
||||
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||
address entry = __ pc();
|
||||
|
||||
|
@ -139,7 +139,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm,
|
||||
}
|
||||
__ g1_write_barrier_pre(rdx, r8, rbx, val != noreg);
|
||||
if (val == noreg) {
|
||||
__ store_heap_oop(Address(rdx, 0), NULL_WORD);
|
||||
__ store_heap_oop_null(Address(rdx, 0));
|
||||
} else {
|
||||
__ store_heap_oop(Address(rdx, 0), val);
|
||||
__ g1_write_barrier_post(rdx, val, r8, rbx);
|
||||
@ -152,7 +152,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm,
|
||||
case BarrierSet::CardTableExtension:
|
||||
{
|
||||
if (val == noreg) {
|
||||
__ store_heap_oop(obj, NULL_WORD);
|
||||
__ store_heap_oop_null(obj);
|
||||
} else {
|
||||
__ store_heap_oop(obj, val);
|
||||
// flatten object address if needed
|
||||
@ -168,7 +168,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm,
|
||||
case BarrierSet::ModRef:
|
||||
case BarrierSet::Other:
|
||||
if (val == noreg) {
|
||||
__ store_heap_oop(obj, NULL_WORD);
|
||||
__ store_heap_oop_null(obj);
|
||||
} else {
|
||||
__ store_heap_oop(obj, val);
|
||||
}
|
||||
|
@ -903,19 +903,20 @@ class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle {
|
||||
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
|
||||
enum {
|
||||
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
|
||||
OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument
|
||||
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another
|
||||
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive
|
||||
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI)
|
||||
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg)
|
||||
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg)
|
||||
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS)
|
||||
OP_DROP_ARGS = 0x8, // remove one or more argument slots
|
||||
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI)
|
||||
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size)
|
||||
OP_FLYBY = 0xB, // operate first on reified argument list (NYI)
|
||||
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI)
|
||||
CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration
|
||||
OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T)
|
||||
OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
|
||||
OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
|
||||
OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
|
||||
OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI)
|
||||
OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
|
||||
OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
|
||||
OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
|
||||
OP_DROP_ARGS = 0x9, // remove one or more argument slots
|
||||
OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI)
|
||||
OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
|
||||
OP_FLYBY = 0xC, // operate first on reified argument list (NYI)
|
||||
OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI)
|
||||
CONV_OP_LIMIT = 0xE, // limit of CONV_OP enumeration
|
||||
|
||||
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
|
||||
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
|
||||
|
@ -1963,7 +1963,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
||||
initialize_wk_klasses_until(meth_group_start, scan, CHECK);
|
||||
if (EnableMethodHandles) {
|
||||
initialize_wk_klasses_through(meth_group_start, scan, CHECK);
|
||||
initialize_wk_klasses_through(meth_group_end, scan, CHECK);
|
||||
}
|
||||
if (_well_known_klasses[meth_group_start] == NULL) {
|
||||
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
|
||||
|
@ -667,39 +667,6 @@ ConcurrentMark::~ConcurrentMark() {
|
||||
// Called at the first checkpoint.
|
||||
//
|
||||
|
||||
#define PRINT_REACHABLE_AT_INITIAL_MARK 0
|
||||
#if PRINT_REACHABLE_AT_INITIAL_MARK
|
||||
static FILE* reachable_file = NULL;
|
||||
|
||||
class PrintReachableClosure: public OopsInGenClosure {
|
||||
CMBitMap* _bm;
|
||||
int _level;
|
||||
public:
|
||||
PrintReachableClosure(CMBitMap* bm) :
|
||||
_bm(bm), _level(0) {
|
||||
guarantee(reachable_file != NULL, "pre-condition");
|
||||
}
|
||||
void do_oop(oop* p) {
|
||||
oop obj = *p;
|
||||
HeapWord* obj_addr = (HeapWord*)obj;
|
||||
if (obj == NULL) return;
|
||||
fprintf(reachable_file, "%d: "PTR_FORMAT" -> "PTR_FORMAT" (%d)\n",
|
||||
_level, p, (void*) obj, _bm->isMarked(obj_addr));
|
||||
if (!_bm->isMarked(obj_addr)) {
|
||||
_bm->mark(obj_addr);
|
||||
_level++;
|
||||
obj->oop_iterate(this);
|
||||
_level--;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // PRINT_REACHABLE_AT_INITIAL_MARK
|
||||
|
||||
#define SEND_HEAP_DUMP_TO_FILE 0
|
||||
#if SEND_HEAP_DUMP_TO_FILE
|
||||
static FILE* heap_dump_file = NULL;
|
||||
#endif // SEND_HEAP_DUMP_TO_FILE
|
||||
|
||||
void ConcurrentMark::clearNextBitmap() {
|
||||
guarantee(!G1CollectedHeap::heap()->mark_in_progress(), "Precondition.");
|
||||
|
||||
@ -737,32 +704,9 @@ void ConcurrentMark::checkpointRootsInitialPre() {
|
||||
|
||||
_has_aborted = false;
|
||||
|
||||
// Find all the reachable objects...
|
||||
#if PRINT_REACHABLE_AT_INITIAL_MARK
|
||||
guarantee(reachable_file == NULL, "Protocol");
|
||||
char fn_buf[100];
|
||||
sprintf(fn_buf, "/tmp/reachable.txt.%d", os::current_process_id());
|
||||
reachable_file = fopen(fn_buf, "w");
|
||||
// clear the mark bitmap (no grey objects to start with)
|
||||
_nextMarkBitMap->clearAll();
|
||||
PrintReachableClosure prcl(_nextMarkBitMap);
|
||||
g1h->process_strong_roots(true, // activate StrongRootsScope
|
||||
false, // fake perm gen collection
|
||||
SharedHeap::SO_AllClasses,
|
||||
&prcl, // Regular roots
|
||||
NULL, // do not visit active blobs
|
||||
&prcl // Perm Gen Roots
|
||||
);
|
||||
// The root iteration above "consumed" dirty cards in the perm gen.
|
||||
// Therefore, as a shortcut, we dirty all such cards.
|
||||
g1h->rem_set()->invalidate(g1h->perm_gen()->used_region(), false);
|
||||
fclose(reachable_file);
|
||||
reachable_file = NULL;
|
||||
// clear the mark bitmap again.
|
||||
_nextMarkBitMap->clearAll();
|
||||
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
#endif // PRINT_REACHABLE_AT_INITIAL_MARK
|
||||
if (G1PrintReachableAtInitialMark) {
|
||||
print_reachable(true, "before");
|
||||
}
|
||||
|
||||
// Initialise marking structures. This has to be done in a STW phase.
|
||||
reset();
|
||||
@ -1965,15 +1909,21 @@ void ConcurrentMark::checkpointRootsFinalWork() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
class ReachablePrinterOopClosure: public OopClosure {
|
||||
private:
|
||||
G1CollectedHeap* _g1h;
|
||||
CMBitMapRO* _bitmap;
|
||||
outputStream* _out;
|
||||
bool _use_prev_marking;
|
||||
|
||||
public:
|
||||
ReachablePrinterOopClosure(CMBitMapRO* bitmap, outputStream* out) :
|
||||
_bitmap(bitmap), _g1h(G1CollectedHeap::heap()), _out(out) { }
|
||||
ReachablePrinterOopClosure(CMBitMapRO* bitmap,
|
||||
outputStream* out,
|
||||
bool use_prev_marking) :
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
|
||||
|
||||
void do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
void do_oop( oop* p) { do_oop_work(p); }
|
||||
@ -1988,14 +1938,23 @@ public:
|
||||
else {
|
||||
HeapRegion* hr = _g1h->heap_region_containing(obj);
|
||||
guarantee(hr != NULL, "invariant");
|
||||
if (hr->obj_allocated_since_prev_marking(obj)) {
|
||||
bool over_tams = false;
|
||||
if (_use_prev_marking) {
|
||||
over_tams = hr->obj_allocated_since_prev_marking(obj);
|
||||
} else {
|
||||
over_tams = hr->obj_allocated_since_next_marking(obj);
|
||||
}
|
||||
|
||||
if (over_tams) {
|
||||
str = "over TAMS";
|
||||
if (_bitmap->isMarked((HeapWord*) obj))
|
||||
if (_bitmap->isMarked((HeapWord*) obj)) {
|
||||
str2 = " AND MARKED";
|
||||
} else if (_bitmap->isMarked((HeapWord*) obj))
|
||||
}
|
||||
} else if (_bitmap->isMarked((HeapWord*) obj)) {
|
||||
str = "marked";
|
||||
else
|
||||
} else {
|
||||
str = "#### NOT MARKED ####";
|
||||
}
|
||||
}
|
||||
|
||||
_out->print_cr(" "PTR_FORMAT" contains "PTR_FORMAT" %s%s",
|
||||
@ -2005,16 +1964,19 @@ public:
|
||||
|
||||
class ReachablePrinterClosure: public BitMapClosure {
|
||||
private:
|
||||
CMBitMapRO* _bitmap;
|
||||
CMBitMapRO* _bitmap;
|
||||
outputStream* _out;
|
||||
bool _use_prev_marking;
|
||||
|
||||
public:
|
||||
ReachablePrinterClosure(CMBitMapRO* bitmap, outputStream* out) :
|
||||
_bitmap(bitmap), _out(out) { }
|
||||
ReachablePrinterClosure(CMBitMapRO* bitmap,
|
||||
outputStream* out,
|
||||
bool use_prev_marking) :
|
||||
_bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
|
||||
|
||||
bool do_bit(size_t offset) {
|
||||
HeapWord* addr = _bitmap->offsetToHeapWord(offset);
|
||||
ReachablePrinterOopClosure oopCl(_bitmap, _out);
|
||||
ReachablePrinterOopClosure oopCl(_bitmap, _out, _use_prev_marking);
|
||||
|
||||
_out->print_cr(" obj "PTR_FORMAT", offset %10d (marked)", addr, offset);
|
||||
oop(addr)->oop_iterate(&oopCl);
|
||||
@ -2026,76 +1988,111 @@ public:
|
||||
|
||||
class ObjInRegionReachablePrinterClosure : public ObjectClosure {
|
||||
private:
|
||||
CMBitMapRO* _bitmap;
|
||||
CMBitMapRO* _bitmap;
|
||||
outputStream* _out;
|
||||
bool _use_prev_marking;
|
||||
|
||||
public:
|
||||
ObjInRegionReachablePrinterClosure(CMBitMapRO* bitmap,
|
||||
outputStream* out,
|
||||
bool use_prev_marking) :
|
||||
_bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
|
||||
|
||||
void do_object(oop o) {
|
||||
ReachablePrinterOopClosure oopCl(_bitmap, _out);
|
||||
ReachablePrinterOopClosure oopCl(_bitmap, _out, _use_prev_marking);
|
||||
|
||||
_out->print_cr(" obj "PTR_FORMAT" (over TAMS)", (void*) o);
|
||||
o->oop_iterate(&oopCl);
|
||||
_out->print_cr("");
|
||||
}
|
||||
|
||||
ObjInRegionReachablePrinterClosure(CMBitMapRO* bitmap, outputStream* out) :
|
||||
_bitmap(bitmap), _out(out) { }
|
||||
};
|
||||
|
||||
class RegionReachablePrinterClosure : public HeapRegionClosure {
|
||||
private:
|
||||
CMBitMapRO* _bitmap;
|
||||
CMBitMapRO* _bitmap;
|
||||
outputStream* _out;
|
||||
bool _use_prev_marking;
|
||||
|
||||
public:
|
||||
bool doHeapRegion(HeapRegion* hr) {
|
||||
HeapWord* b = hr->bottom();
|
||||
HeapWord* e = hr->end();
|
||||
HeapWord* t = hr->top();
|
||||
HeapWord* p = hr->prev_top_at_mark_start();
|
||||
HeapWord* p = NULL;
|
||||
if (_use_prev_marking) {
|
||||
p = hr->prev_top_at_mark_start();
|
||||
} else {
|
||||
p = hr->next_top_at_mark_start();
|
||||
}
|
||||
_out->print_cr("** ["PTR_FORMAT", "PTR_FORMAT"] top: "PTR_FORMAT" "
|
||||
"PTAMS: "PTR_FORMAT, b, e, t, p);
|
||||
"TAMS: "PTR_FORMAT, b, e, t, p);
|
||||
_out->print_cr("");
|
||||
|
||||
ObjInRegionReachablePrinterClosure ocl(_bitmap, _out);
|
||||
ObjInRegionReachablePrinterClosure ocl(_bitmap, _out, _use_prev_marking);
|
||||
hr->object_iterate_mem_careful(MemRegion(p, t), &ocl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RegionReachablePrinterClosure(CMBitMapRO* bitmap,
|
||||
outputStream* out) :
|
||||
_bitmap(bitmap), _out(out) { }
|
||||
RegionReachablePrinterClosure(CMBitMapRO* bitmap,
|
||||
outputStream* out,
|
||||
bool use_prev_marking) :
|
||||
_bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
|
||||
};
|
||||
|
||||
void ConcurrentMark::print_prev_bitmap_reachable() {
|
||||
outputStream* out = gclog_or_tty;
|
||||
void ConcurrentMark::print_reachable(bool use_prev_marking, const char* str) {
|
||||
gclog_or_tty->print_cr("== Doing reachable object dump... ");
|
||||
|
||||
#if SEND_HEAP_DUMP_TO_FILE
|
||||
guarantee(heap_dump_file == NULL, "Protocol");
|
||||
char fn_buf[100];
|
||||
sprintf(fn_buf, "/tmp/dump.txt.%d", os::current_process_id());
|
||||
heap_dump_file = fopen(fn_buf, "w");
|
||||
fileStream fstream(heap_dump_file);
|
||||
out = &fstream;
|
||||
#endif // SEND_HEAP_DUMP_TO_FILE
|
||||
if (G1PrintReachableBaseFile == NULL) {
|
||||
gclog_or_tty->print_cr(" #### error: no base file defined");
|
||||
return;
|
||||
}
|
||||
|
||||
RegionReachablePrinterClosure rcl(_prevMarkBitMap, out);
|
||||
out->print_cr("--- ITERATING OVER REGIONS WITH PTAMS < TOP");
|
||||
if (strlen(G1PrintReachableBaseFile) + 1 + strlen(str) >
|
||||
(JVM_MAXPATHLEN - 1)) {
|
||||
gclog_or_tty->print_cr(" #### error: file name too long");
|
||||
return;
|
||||
}
|
||||
|
||||
char file_name[JVM_MAXPATHLEN];
|
||||
sprintf(file_name, "%s.%s", G1PrintReachableBaseFile, str);
|
||||
gclog_or_tty->print_cr(" dumping to file %s", file_name);
|
||||
|
||||
fileStream fout(file_name);
|
||||
if (!fout.is_open()) {
|
||||
gclog_or_tty->print_cr(" #### error: could not open file");
|
||||
return;
|
||||
}
|
||||
|
||||
outputStream* out = &fout;
|
||||
|
||||
CMBitMapRO* bitmap = NULL;
|
||||
if (use_prev_marking) {
|
||||
bitmap = _prevMarkBitMap;
|
||||
} else {
|
||||
bitmap = _nextMarkBitMap;
|
||||
}
|
||||
|
||||
out->print_cr("-- USING %s", (use_prev_marking) ? "PTAMS" : "NTAMS");
|
||||
out->cr();
|
||||
|
||||
RegionReachablePrinterClosure rcl(bitmap, out, use_prev_marking);
|
||||
out->print_cr("--- ITERATING OVER REGIONS WITH TAMS < TOP");
|
||||
out->cr();
|
||||
_g1h->heap_region_iterate(&rcl);
|
||||
out->print_cr("");
|
||||
out->cr();
|
||||
|
||||
ReachablePrinterClosure cl(_prevMarkBitMap, out);
|
||||
out->print_cr("--- REACHABLE OBJECTS ON THE BITMAP");
|
||||
_prevMarkBitMap->iterate(&cl);
|
||||
out->print_cr("");
|
||||
ReachablePrinterClosure cl(bitmap, out, use_prev_marking);
|
||||
out->print_cr("--- ITERATING OVER MARKED OBJECTS ON THE BITMAP");
|
||||
out->cr();
|
||||
bitmap->iterate(&cl);
|
||||
out->cr();
|
||||
|
||||
#if SEND_HEAP_DUMP_TO_FILE
|
||||
fclose(heap_dump_file);
|
||||
heap_dump_file = NULL;
|
||||
#endif // SEND_HEAP_DUMP_TO_FILE
|
||||
gclog_or_tty->print_cr(" done");
|
||||
}
|
||||
|
||||
#endif // PRODUCT
|
||||
|
||||
// This note is for drainAllSATBBuffers and the code in between.
|
||||
// In the future we could reuse a task to do this work during an
|
||||
// evacuation pause (since now tasks are not active and can be claimed
|
||||
|
@ -612,10 +612,11 @@ public:
|
||||
// we do nothing.
|
||||
void markAndGrayObjectIfNecessary(oop p);
|
||||
|
||||
// This iterates over the bitmap of the previous marking and prints
|
||||
// out all objects that are marked on the bitmap and indicates
|
||||
// whether what they point to is also marked or not.
|
||||
void print_prev_bitmap_reachable();
|
||||
// This iterates over the marking bitmap (either prev or next) and
|
||||
// prints out all objects that are marked on the bitmap and indicates
|
||||
// whether what they point to is also marked or not. It also iterates
|
||||
// the objects over TAMS (either prev or next).
|
||||
void print_reachable(bool use_prev_marking, const char* str);
|
||||
|
||||
// Clear the next marking bitmap (will be called concurrently).
|
||||
void clearNextBitmap();
|
||||
|
@ -2371,8 +2371,9 @@ void G1CollectedHeap::verify(bool allow_dirty,
|
||||
gclog_or_tty->print_cr("Heap:");
|
||||
print_on(gclog_or_tty, true /* extended */);
|
||||
gclog_or_tty->print_cr("");
|
||||
if (VerifyDuringGC && G1VerifyConcMarkPrintReachable) {
|
||||
concurrent_mark()->print_prev_bitmap_reachable();
|
||||
if (VerifyDuringGC && G1VerifyDuringGCPrintReachable) {
|
||||
concurrent_mark()->print_reachable(use_prev_marking,
|
||||
"failed-verification");
|
||||
}
|
||||
gclog_or_tty->flush();
|
||||
}
|
||||
@ -3135,7 +3136,7 @@ void G1CollectedHeap::finalize_for_evac_failure() {
|
||||
_evac_failure_scan_stack->length() == 0,
|
||||
"Postcondition");
|
||||
assert(!_drain_in_progress, "Postcondition");
|
||||
// Don't have to delete, since the scan stack is a resource object.
|
||||
delete _evac_failure_scan_stack;
|
||||
_evac_failure_scan_stack = NULL;
|
||||
}
|
||||
|
||||
|
@ -1516,7 +1516,8 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
||||
(end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
|
||||
update_recent_gc_times(end_time_sec, elapsed_ms);
|
||||
_recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms;
|
||||
assert(recent_avg_pause_time_ratio() < 1.00, "All GC?");
|
||||
// using 1.01 to account for floating point inaccuracies
|
||||
assert(recent_avg_pause_time_ratio() < 1.01, "All GC?");
|
||||
}
|
||||
|
||||
if (G1PolicyVerbose > 1) {
|
||||
|
@ -55,8 +55,14 @@
|
||||
develop(intx, G1MarkingVerboseLevel, 0, \
|
||||
"Level (0-4) of verboseness of the marking code") \
|
||||
\
|
||||
develop(bool, G1VerifyConcMarkPrintReachable, false, \
|
||||
"If conc mark verification fails, print reachable objects") \
|
||||
develop(bool, G1PrintReachableAtInitialMark, false, \
|
||||
"Reachable object dump at the initial mark pause") \
|
||||
\
|
||||
develop(bool, G1VerifyDuringGCPrintReachable, false, \
|
||||
"If conc mark verification fails, dump reachable objects") \
|
||||
\
|
||||
develop(ccstr, G1PrintReachableBaseFile, NULL, \
|
||||
"The base file name for the reachable object dumps") \
|
||||
\
|
||||
develop(bool, G1TraceMarkStackOverflow, false, \
|
||||
"If true, extra debugging code for CM restart for ovflw.") \
|
||||
|
@ -135,7 +135,6 @@ RSHashTable::RSHashTable(size_t capacity) :
|
||||
_occupied_entries(0), _occupied_cards(0),
|
||||
_entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)),
|
||||
_buckets(NEW_C_HEAP_ARRAY(int, capacity)),
|
||||
_next_deleted(NULL), _deleted(false),
|
||||
_free_list(NullEntry), _free_region(0)
|
||||
{
|
||||
clear();
|
||||
@ -296,40 +295,6 @@ void RSHashTable::add_entry(SparsePRTEntry* e) {
|
||||
assert(e2->num_valid_cards() > 0, "Postcondition.");
|
||||
}
|
||||
|
||||
RSHashTable* RSHashTable::_head_deleted_list = NULL;
|
||||
|
||||
void RSHashTable::add_to_deleted_list(RSHashTable* rsht) {
|
||||
assert(!rsht->deleted(), "Should delete only once.");
|
||||
rsht->set_deleted(true);
|
||||
RSHashTable* hd = _head_deleted_list;
|
||||
while (true) {
|
||||
rsht->_next_deleted = hd;
|
||||
RSHashTable* res =
|
||||
(RSHashTable*)
|
||||
Atomic::cmpxchg_ptr(rsht, &_head_deleted_list, hd);
|
||||
if (res == hd) return;
|
||||
else hd = res;
|
||||
}
|
||||
}
|
||||
|
||||
RSHashTable* RSHashTable::get_from_deleted_list() {
|
||||
RSHashTable* hd = _head_deleted_list;
|
||||
while (hd != NULL) {
|
||||
RSHashTable* next = hd->next_deleted();
|
||||
RSHashTable* res =
|
||||
(RSHashTable*)
|
||||
Atomic::cmpxchg_ptr(next, &_head_deleted_list, hd);
|
||||
if (res == hd) {
|
||||
hd->set_next_deleted(NULL);
|
||||
hd->set_deleted(false);
|
||||
return hd;
|
||||
} else {
|
||||
hd = res;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
|
||||
CardIdx_t res;
|
||||
while (_bl_ind != RSHashTable::NullEntry) {
|
||||
@ -442,15 +407,6 @@ void SparsePRT::cleanup_all() {
|
||||
sprt->cleanup();
|
||||
sprt = get_from_expanded_list();
|
||||
}
|
||||
// Now delete all deleted RSHashTables.
|
||||
RSHashTable* rsht = RSHashTable::get_from_deleted_list();
|
||||
while (rsht != NULL) {
|
||||
#if SPARSE_PRT_VERBOSE
|
||||
gclog_or_tty->print_cr("About to delete RSHT " PTR_FORMAT ".", rsht);
|
||||
#endif
|
||||
delete rsht;
|
||||
rsht = RSHashTable::get_from_deleted_list();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -511,8 +467,10 @@ void SparsePRT::clear() {
|
||||
}
|
||||
|
||||
void SparsePRT::cleanup() {
|
||||
// Make sure that the current and next tables agree. (Another mechanism
|
||||
// takes care of deleting now-unused tables.)
|
||||
// Make sure that the current and next tables agree.
|
||||
if (_cur != _next) {
|
||||
delete _cur;
|
||||
}
|
||||
_cur = _next;
|
||||
set_expanded(false);
|
||||
}
|
||||
@ -535,7 +493,8 @@ void SparsePRT::expand() {
|
||||
_next->add_entry(e);
|
||||
}
|
||||
}
|
||||
if (last != _cur)
|
||||
RSHashTable::add_to_deleted_list(last);
|
||||
if (last != _cur) {
|
||||
delete last;
|
||||
}
|
||||
add_to_expanded_list(this);
|
||||
}
|
||||
|
@ -102,13 +102,6 @@ class RSHashTable : public CHeapObj {
|
||||
int _free_region;
|
||||
int _free_list;
|
||||
|
||||
static RSHashTable* _head_deleted_list;
|
||||
RSHashTable* _next_deleted;
|
||||
RSHashTable* next_deleted() { return _next_deleted; }
|
||||
void set_next_deleted(RSHashTable* rsht) { _next_deleted = rsht; }
|
||||
bool _deleted;
|
||||
void set_deleted(bool b) { _deleted = b; }
|
||||
|
||||
// Requires that the caller hold a lock preventing parallel modifying
|
||||
// operations, and that the the table be less than completely full. If
|
||||
// an entry for "region_ind" is already in the table, finds it and
|
||||
@ -154,14 +147,10 @@ public:
|
||||
size_t occupied_entries() const { return _occupied_entries; }
|
||||
size_t occupied_cards() const { return _occupied_cards; }
|
||||
size_t mem_size() const;
|
||||
bool deleted() { return _deleted; }
|
||||
|
||||
SparsePRTEntry* entry(int i) const { return &_entries[i]; }
|
||||
|
||||
void print();
|
||||
|
||||
static void add_to_deleted_list(RSHashTable* rsht);
|
||||
static RSHashTable* get_from_deleted_list();
|
||||
};
|
||||
|
||||
// ValueObj because will be embedded in HRRS iterator.
|
||||
|
@ -352,15 +352,19 @@ void CompactingPermGenGen::post_compact() {
|
||||
}
|
||||
|
||||
|
||||
// Do not use in time-critical operations due to the possibility of paging
|
||||
// in otherwise untouched or previously unread portions of the perm gen,
|
||||
// for instance, the shared spaces. NOTE: Because CompactingPermGenGen
|
||||
// derives from OneContigSpaceCardGeneration which is supposed to have a
|
||||
// single space, and does not override its object_iterate() method,
|
||||
// object iteration via that interface does not look at the objects in
|
||||
// the shared spaces when using CDS. This should be fixed; see CR 6897798.
|
||||
void CompactingPermGenGen::space_iterate(SpaceClosure* blk, bool usedOnly) {
|
||||
OneContigSpaceCardGeneration::space_iterate(blk, usedOnly);
|
||||
if (spec()->enable_shared_spaces()) {
|
||||
#ifdef PRODUCT
|
||||
// Making the rw_space walkable will page in the entire space, and
|
||||
// is to be avoided. However, this is required for Verify options.
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
|
||||
// is to be avoided in the case of time-critical operations.
|
||||
// However, this is required for Verify and heap dump operations.
|
||||
blk->do_space(ro_space());
|
||||
blk->do_space(rw_space());
|
||||
}
|
||||
|
@ -29,6 +29,9 @@
|
||||
class PermanentGenerationSpec;
|
||||
|
||||
// This is the "generation" view of a CompactingPermGen.
|
||||
// NOTE: the shared spaces used for CDS are here handled in
|
||||
// a somewhat awkward and potentially buggy fashion, see CR 6801625.
|
||||
// This infelicity should be fixed, see CR 6897789.
|
||||
class CompactingPermGenGen: public OneContigSpaceCardGeneration {
|
||||
friend class VMStructs;
|
||||
// Abstractly, this is a subtype that gets access to protected fields.
|
||||
@ -47,7 +50,7 @@ private:
|
||||
OffsetTableContigSpace* _ro_space;
|
||||
OffsetTableContigSpace* _rw_space;
|
||||
|
||||
// With shared spaces there is a dicotomy in the use of the
|
||||
// With shared spaces there is a dichotomy in the use of the
|
||||
// _virtual_space of the generation. There is a portion of the
|
||||
// _virtual_space that is used for the unshared part of the
|
||||
// permanent generation and a portion that is reserved for the shared part.
|
||||
|
@ -606,6 +606,13 @@ void OneContigSpaceCardGeneration::shrink_by(size_t bytes) {
|
||||
void OneContigSpaceCardGeneration::prepare_for_verify() {}
|
||||
|
||||
|
||||
// Override for a card-table generation with one contiguous
|
||||
// space. NOTE: For reasons that are lost in the fog of history,
|
||||
// this code is used when you iterate over perm gen objects,
|
||||
// even when one uses CDS, where the perm gen has a couple of
|
||||
// other spaces; this is because CompactingPermGenGen derives
|
||||
// from OneContigSpaceCardGeneration. This should be cleaned up,
|
||||
// see CR 6897789..
|
||||
void OneContigSpaceCardGeneration::object_iterate(ObjectClosure* blk) {
|
||||
_the_space->object_iterate(blk);
|
||||
}
|
||||
|
@ -1900,7 +1900,7 @@ void instanceKlass::release_C_heap_structures() {
|
||||
}
|
||||
}
|
||||
|
||||
char* instanceKlass::signature_name() const {
|
||||
const char* instanceKlass::signature_name() const {
|
||||
const char* src = (const char*) (name()->as_C_string());
|
||||
const int src_length = (int)strlen(src);
|
||||
char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3);
|
||||
@ -2259,6 +2259,10 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
st->print(BULLET"fake entry for array: ");
|
||||
array_klass->print_value_on(st);
|
||||
st->cr();
|
||||
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
|
||||
st->print(BULLET"signature: ");
|
||||
java_dyn_MethodType::print_signature(obj, st);
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2284,6 +2288,9 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) {
|
||||
const char* tname = type2name(java_lang_Class::primitive_type(obj));
|
||||
st->print("%s", tname ? tname : "type?");
|
||||
}
|
||||
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
|
||||
st->print(" = ");
|
||||
java_dyn_MethodType::print_signature(obj, st);
|
||||
} else if (java_lang_boxing_object::is_instance(obj)) {
|
||||
st->print(" = ");
|
||||
java_lang_boxing_object::print(obj, st);
|
||||
|
@ -722,7 +722,7 @@ class instanceKlass: public Klass {
|
||||
#endif // SERIALGC
|
||||
|
||||
// Naming
|
||||
char* signature_name() const;
|
||||
const char* signature_name() const;
|
||||
|
||||
// Iterators
|
||||
int oop_oop_iterate(oop obj, OopClosure* blk) {
|
||||
|
@ -496,11 +496,13 @@ const char* Klass::external_name() const {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (name() == NULL) return "<unknown>";
|
||||
return name()->as_klass_external_name();
|
||||
}
|
||||
|
||||
|
||||
char* Klass::signature_name() const {
|
||||
const char* Klass::signature_name() const {
|
||||
if (name() == NULL) return "<unknown>";
|
||||
return name()->as_C_string();
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ class Klass : public Klass_vtbl {
|
||||
// For arrays, this returns the name of the element with a leading '['.
|
||||
// For classes, this returns the name with a leading 'L' and a trailing ';'
|
||||
// and the package separators as '/'.
|
||||
virtual char* signature_name() const;
|
||||
virtual const char* signature_name() const;
|
||||
|
||||
// garbage collection support
|
||||
virtual void oop_follow_contents(oop obj) = 0;
|
||||
|
@ -31,8 +31,9 @@ void markOopDesc::print_on(outputStream* st) const {
|
||||
st->print("locked(0x%lx)->", value());
|
||||
markOop(*(markOop*)value())->print_on(st);
|
||||
} else {
|
||||
assert(is_unlocked(), "just checking");
|
||||
assert(is_unlocked() || has_bias_pattern(), "just checking");
|
||||
st->print("mark(");
|
||||
if (has_bias_pattern()) st->print("biased,");
|
||||
st->print("hash %#lx,", hash());
|
||||
st->print("age %d)", age());
|
||||
}
|
||||
|
@ -881,7 +881,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||
assert((oop)p == method_type(), "pointer chase is correct");
|
||||
#endif
|
||||
|
||||
if (TraceMethodHandles)
|
||||
if (TraceMethodHandles && (Verbose || WizardMode))
|
||||
m->print_on(tty);
|
||||
|
||||
return m;
|
||||
|
@ -421,21 +421,23 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
|
||||
iklass = cik->as_instance_klass();
|
||||
} else if (cik->is_type_array_klass()) {
|
||||
cik->as_array_klass()->base_element_type()->print_name_on(st);
|
||||
st->print("[%d]=", spobj->n_fields());
|
||||
st->print("[%d]", spobj->n_fields());
|
||||
} else if (cik->is_obj_array_klass()) {
|
||||
ciType* cie = cik->as_array_klass()->base_element_type();
|
||||
int ndim = 1;
|
||||
while (cie->is_obj_array_klass()) {
|
||||
ndim += 1;
|
||||
cie = cie->as_array_klass()->base_element_type();
|
||||
ciKlass* cie = cik->as_obj_array_klass()->base_element_klass();
|
||||
if (cie->is_instance_klass()) {
|
||||
cie->print_name_on(st);
|
||||
} else if (cie->is_type_array_klass()) {
|
||||
cie->as_array_klass()->base_element_type()->print_name_on(st);
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
cie->print_name_on(st);
|
||||
st->print("[%d]", spobj->n_fields());
|
||||
int ndim = cik->as_array_klass()->dimension() - 1;
|
||||
while (ndim-- > 0) {
|
||||
st->print("[]");
|
||||
}
|
||||
st->print("[%d]=", spobj->n_fields());
|
||||
}
|
||||
st->print("{");
|
||||
st->print("={");
|
||||
uint nf = spobj->n_fields();
|
||||
if (nf > 0) {
|
||||
uint first_ind = spobj->first_index();
|
||||
|
@ -2116,7 +2116,7 @@ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, js
|
||||
DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
|
||||
objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
|
||||
if (a->is_within_bounds(index)) {
|
||||
jobject ret = JNIHandles::make_local(env, a->obj_at(index));
|
||||
ret = JNIHandles::make_local(env, a->obj_at(index));
|
||||
return ret;
|
||||
} else {
|
||||
char buf[jintAsStringSize];
|
||||
@ -2150,14 +2150,14 @@ JNI_END
|
||||
|
||||
#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \
|
||||
\
|
||||
DT_RETURN_MARK_DECL_FOR(Result, New##Result##Array, Return);\
|
||||
DT_RETURN_MARK_DECL(New##Result##Array, Return);\
|
||||
\
|
||||
JNI_ENTRY(Return, \
|
||||
jni_New##Result##Array(JNIEnv *env, jsize len)) \
|
||||
JNIWrapper("New" XSTR(Result) "Array"); \
|
||||
DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\
|
||||
Return ret = NULL;\
|
||||
DT_RETURN_MARK_FOR(Result, New##Result##Array, Return, (const Return&)ret);\
|
||||
DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
|
||||
\
|
||||
oop obj= oopFactory::Allocator(len, CHECK_0); \
|
||||
ret = (Return) JNIHandles::make_local(env, obj); \
|
||||
|
@ -33,8 +33,7 @@ bool MethodHandles::_enabled = false; // set true after successful native linkag
|
||||
|
||||
MethodHandleEntry* MethodHandles::_entries[MethodHandles::_EK_LIMIT] = {NULL};
|
||||
const char* MethodHandles::_entry_names[_EK_LIMIT+1] = {
|
||||
"check_mtype",
|
||||
"wrong_method_type", // what happens when there is a type mismatch
|
||||
"raise_exception",
|
||||
"invokestatic", // how a MH emulates invokestatic
|
||||
"invokespecial", // ditto for the other invokes...
|
||||
"invokevirtual",
|
||||
@ -48,6 +47,7 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = {
|
||||
|
||||
// starting at _adapter_mh_first:
|
||||
"adapter_retype_only", // these are for AMH...
|
||||
"adapter_retype_raw",
|
||||
"adapter_check_cast",
|
||||
"adapter_prim_to_prim",
|
||||
"adapter_ref_to_prim",
|
||||
@ -82,6 +82,8 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
jobject MethodHandles::_raise_exception_method;
|
||||
|
||||
#ifdef ASSERT
|
||||
bool MethodHandles::spot_check_entry_names() {
|
||||
assert(!strcmp(entry_name(_invokestatic_mh), "invokestatic"), "");
|
||||
@ -157,7 +159,8 @@ methodOop MethodHandles::decode_DirectMethodHandle(oop mh, klassOop& receiver_li
|
||||
}
|
||||
|
||||
methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
|
||||
assert(mh->klass() == SystemDictionary::BoundMethodHandle_klass(), "");
|
||||
assert(sun_dyn_BoundMethodHandle::is_instance(mh), "");
|
||||
assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), "");
|
||||
for (oop bmh = mh;;) {
|
||||
// Bound MHs can be stacked to bind several arguments.
|
||||
oop target = java_dyn_MethodHandle::vmtarget(bmh);
|
||||
@ -174,10 +177,9 @@ methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_lim
|
||||
} else {
|
||||
// Optimized case: binding a receiver to a non-dispatched DMH
|
||||
// short-circuits directly to the methodOop.
|
||||
// (It might be another argument besides a receiver also.)
|
||||
assert(target->is_method(), "must be a simple method");
|
||||
methodOop m = (methodOop) target;
|
||||
DEBUG_ONLY(int argslot = sun_dyn_BoundMethodHandle::vmargslot(bmh));
|
||||
assert(argslot == m->size_of_parameters() - 1, "must be initial argument (receiver)");
|
||||
decode_flags_result |= MethodHandles::_dmf_binds_method;
|
||||
return m;
|
||||
}
|
||||
@ -214,6 +216,9 @@ methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_re
|
||||
return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
|
||||
} else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) {
|
||||
return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result);
|
||||
} else if (sun_dyn_BoundMethodHandle::is_subclass(mhk)) {
|
||||
// could be a JavaMethodHandle (but not an adapter MH)
|
||||
return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
|
||||
} else {
|
||||
assert(false, "cannot parse this MH");
|
||||
return NULL; // random MH?
|
||||
@ -366,7 +371,13 @@ methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_r
|
||||
oop vmtarget = sun_dyn_MemberName::vmtarget(mname);
|
||||
int vmindex = sun_dyn_MemberName::vmindex(mname);
|
||||
if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved
|
||||
return decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
|
||||
methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
|
||||
oop clazz = sun_dyn_MemberName::clazz(mname);
|
||||
if (clazz != NULL && java_lang_Class::is_instance(clazz)) {
|
||||
klassOop klass = java_lang_Class::as_klassOop(clazz);
|
||||
if (klass != NULL) receiver_limit_result = klass;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
// An unresolved member name is a mere symbolic reference.
|
||||
@ -789,6 +800,30 @@ oop MethodHandles::encode_target(Handle mh, int format, TRAPS) {
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), msg);
|
||||
}
|
||||
|
||||
static const char* always_null_names[] = {
|
||||
"java/lang/Void",
|
||||
"java/lang/Null",
|
||||
//"java/lang/Nothing",
|
||||
"sun/dyn/empty/Empty",
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool is_always_null_type(klassOop klass) {
|
||||
if (!Klass::cast(klass)->oop_is_instance()) return false;
|
||||
instanceKlass* ik = instanceKlass::cast(klass);
|
||||
// Must be on the boot class path:
|
||||
if (ik->class_loader() != NULL) return false;
|
||||
// Check the name.
|
||||
symbolOop name = ik->name();
|
||||
for (int i = 0; ; i++) {
|
||||
const char* test_name = always_null_names[i];
|
||||
if (test_name == NULL) break;
|
||||
if (name->equals(test_name, (int) strlen(test_name)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) {
|
||||
if (src == dst || dst == SystemDictionary::object_klass())
|
||||
return false; // quickest checks
|
||||
@ -805,6 +840,12 @@ bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) {
|
||||
//srck = Klass::cast(SystemDictionary::object_klass());
|
||||
return true;
|
||||
}
|
||||
if (is_always_null_type(src)) {
|
||||
// some source types are known to be never instantiated;
|
||||
// they represent references which are always null
|
||||
// such null references never fail to convert safely
|
||||
return false;
|
||||
}
|
||||
return !srck->is_subclass_of(dstk->as_klassOop());
|
||||
}
|
||||
|
||||
@ -814,9 +855,15 @@ static oop object_java_mirror() {
|
||||
|
||||
bool MethodHandles::same_basic_type_for_arguments(BasicType src,
|
||||
BasicType dst,
|
||||
bool raw,
|
||||
bool for_return) {
|
||||
// return values can always be forgotten:
|
||||
if (for_return && dst == T_VOID) return true;
|
||||
if (for_return) {
|
||||
// return values can always be forgotten:
|
||||
if (dst == T_VOID) return true;
|
||||
if (src == T_VOID) return raw && (dst == T_INT);
|
||||
// We allow caller to receive a garbage int, which is harmless.
|
||||
// This trick is pulled by trusted code (see VerifyType.canPassRaw).
|
||||
}
|
||||
assert(src != T_VOID && dst != T_VOID, "should not be here");
|
||||
if (src == dst) return true;
|
||||
if (type2size[src] != type2size[dst]) return false;
|
||||
@ -929,8 +976,8 @@ void MethodHandles::verify_method_type(methodHandle m,
|
||||
const char* err = NULL;
|
||||
|
||||
int first_ptype_pos = m_needs_receiver ? 1 : 0;
|
||||
if (has_bound_recv && err == NULL) {
|
||||
first_ptype_pos -= 1;
|
||||
if (has_bound_recv) {
|
||||
first_ptype_pos -= 1; // ptypes do not include the bound argument; start earlier in them
|
||||
if (m_needs_receiver && bound_recv_type.is_null())
|
||||
{ err = "bound receiver is not an object"; goto die; }
|
||||
}
|
||||
@ -939,10 +986,10 @@ void MethodHandles::verify_method_type(methodHandle m,
|
||||
objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype());
|
||||
if (ptypes->length() < first_ptype_pos)
|
||||
{ err = "receiver argument is missing"; goto die; }
|
||||
if (first_ptype_pos == -1)
|
||||
if (has_bound_recv)
|
||||
err = check_method_receiver(m(), bound_recv_type->as_klassOop());
|
||||
else
|
||||
err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(0)));
|
||||
err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(first_ptype_pos-1)));
|
||||
if (err != NULL) goto die;
|
||||
}
|
||||
|
||||
@ -983,7 +1030,8 @@ const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg,
|
||||
int insert_argnum, oop insert_type,
|
||||
int change_argnum, oop change_type,
|
||||
int delete_argnum,
|
||||
oop dst_mtype, int dst_beg, int dst_end) {
|
||||
oop dst_mtype, int dst_beg, int dst_end,
|
||||
bool raw) {
|
||||
objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype);
|
||||
objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype);
|
||||
|
||||
@ -1042,7 +1090,7 @@ const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg,
|
||||
if (src_type != dst_type) {
|
||||
if (src_type == NULL) return "not enough arguments";
|
||||
if (dst_type == NULL) return "too many arguments";
|
||||
err = check_argument_type_change(src_type, dst_type, dst_idx);
|
||||
err = check_argument_type_change(src_type, dst_type, dst_idx, raw);
|
||||
if (err != NULL) return err;
|
||||
}
|
||||
}
|
||||
@ -1051,7 +1099,7 @@ const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg,
|
||||
oop src_rtype = java_dyn_MethodType::rtype(src_mtype);
|
||||
oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype);
|
||||
if (src_rtype != dst_rtype) {
|
||||
err = check_return_type_change(dst_rtype, src_rtype); // note reversal!
|
||||
err = check_return_type_change(dst_rtype, src_rtype, raw); // note reversal!
|
||||
if (err != NULL) return err;
|
||||
}
|
||||
|
||||
@ -1061,38 +1109,45 @@ const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg,
|
||||
|
||||
|
||||
const char* MethodHandles::check_argument_type_change(BasicType src_type,
|
||||
klassOop src_klass,
|
||||
BasicType dst_type,
|
||||
klassOop dst_klass,
|
||||
int argnum) {
|
||||
klassOop src_klass,
|
||||
BasicType dst_type,
|
||||
klassOop dst_klass,
|
||||
int argnum,
|
||||
bool raw) {
|
||||
const char* err = NULL;
|
||||
bool for_return = (argnum < 0);
|
||||
|
||||
// just in case:
|
||||
if (src_type == T_ARRAY) src_type = T_OBJECT;
|
||||
if (dst_type == T_ARRAY) dst_type = T_OBJECT;
|
||||
|
||||
// Produce some nice messages if VerifyMethodHandles is turned on:
|
||||
if (!same_basic_type_for_arguments(src_type, dst_type, (argnum < 0))) {
|
||||
if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) {
|
||||
if (src_type == T_OBJECT) {
|
||||
if (raw && dst_type == T_INT && is_always_null_type(src_klass))
|
||||
return NULL; // OK to convert a null pointer to a garbage int
|
||||
err = ((argnum >= 0)
|
||||
? "type mismatch: passing a %s for method argument #%d, which expects primitive %s"
|
||||
: "type mismatch: returning a %s, but caller expects primitive %s");
|
||||
} else if (dst_type == T_OBJECT) {
|
||||
err = ((argnum < 0)
|
||||
err = ((argnum >= 0)
|
||||
? "type mismatch: passing a primitive %s for method argument #%d, which expects %s"
|
||||
: "type mismatch: returning a primitive %s, but caller expects %s");
|
||||
} else {
|
||||
err = ((argnum < 0)
|
||||
err = ((argnum >= 0)
|
||||
? "type mismatch: passing a %s for method argument #%d, which expects %s"
|
||||
: "type mismatch: returning a %s, but caller expects %s");
|
||||
}
|
||||
} else if (src_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) {
|
||||
} else if (src_type == T_OBJECT && dst_type == T_OBJECT &&
|
||||
class_cast_needed(src_klass, dst_klass)) {
|
||||
if (!class_cast_needed(dst_klass, src_klass)) {
|
||||
err = ((argnum < 0)
|
||||
if (raw)
|
||||
return NULL; // reverse cast is OK; the MH target is trusted to enforce it
|
||||
err = ((argnum >= 0)
|
||||
? "cast required: passing a %s for method argument #%d, which expects %s"
|
||||
: "cast required: returning a %s, but caller expects %s");
|
||||
} else {
|
||||
err = ((argnum < 0)
|
||||
err = ((argnum >= 0)
|
||||
? "reference mismatch: passing a %s for method argument #%d, which expects %s"
|
||||
: "reference mismatch: returning a %s, but caller expects %s");
|
||||
}
|
||||
@ -1429,10 +1484,10 @@ void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnu
|
||||
assert(this_pushes == slots_pushed, "BMH pushes one or two stack slots");
|
||||
assert(slots_pushed <= MethodHandlePushLimit, "");
|
||||
} else {
|
||||
int prev_pushes = decode_MethodHandle_stack_pushes(target());
|
||||
assert(this_pushes == slots_pushed + prev_pushes, "BMH stack motion must be correct");
|
||||
int target_pushes = decode_MethodHandle_stack_pushes(target());
|
||||
assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct");
|
||||
// do not blow the stack; use a Java-based adapter if this limit is exceeded
|
||||
if (slots_pushed + prev_pushes > MethodHandlePushLimit)
|
||||
if (slots_pushed + target_pushes > MethodHandlePushLimit)
|
||||
err = "too many bound parameters";
|
||||
}
|
||||
}
|
||||
@ -1588,6 +1643,11 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
||||
if (err == NULL) {
|
||||
// Check that the src/dest types are supplied if needed.
|
||||
switch (ek) {
|
||||
case _adapter_check_cast:
|
||||
if (src != T_OBJECT || dest != T_OBJECT) {
|
||||
err = "adapter requires object src/dest conversion subfields";
|
||||
}
|
||||
break;
|
||||
case _adapter_prim_to_prim:
|
||||
if (!is_java_primitive(src) || !is_java_primitive(dest) || src == dest) {
|
||||
err = "adapter requires primitive src/dest conversion subfields"; break;
|
||||
@ -1616,9 +1676,9 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
||||
err = "adapter requires src/dest conversion subfields for swap"; break;
|
||||
}
|
||||
int swap_size = type2size[src];
|
||||
oop src_mtype = sun_dyn_AdapterMethodHandle::type(target());
|
||||
oop dest_mtype = sun_dyn_AdapterMethodHandle::type(mh());
|
||||
int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(src_mtype);
|
||||
oop src_mtype = sun_dyn_AdapterMethodHandle::type(mh());
|
||||
oop dest_mtype = sun_dyn_AdapterMethodHandle::type(target());
|
||||
int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(target());
|
||||
int src_slot = argslot;
|
||||
int dest_slot = vminfo;
|
||||
bool rotate_up = (src_slot > dest_slot); // upward rotation
|
||||
@ -1729,22 +1789,22 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
||||
// Make sure this adapter does not push too deeply.
|
||||
int slots_pushed = stack_move / stack_move_unit();
|
||||
int this_vmslots = java_dyn_MethodHandle::vmslots(mh());
|
||||
int prev_vmslots = java_dyn_MethodHandle::vmslots(target());
|
||||
if (slots_pushed != (this_vmslots - prev_vmslots)) {
|
||||
int target_vmslots = java_dyn_MethodHandle::vmslots(target());
|
||||
if (slots_pushed != (target_vmslots - this_vmslots)) {
|
||||
err = "stack_move inconsistent with previous and current MethodType vmslots";
|
||||
} else if (slots_pushed > 0) {
|
||||
// verify stack_move against MethodHandlePushLimit
|
||||
int prev_pushes = decode_MethodHandle_stack_pushes(target());
|
||||
int target_pushes = decode_MethodHandle_stack_pushes(target());
|
||||
// do not blow the stack; use a Java-based adapter if this limit is exceeded
|
||||
if (slots_pushed + prev_pushes > MethodHandlePushLimit) {
|
||||
if (slots_pushed + target_pushes > MethodHandlePushLimit) {
|
||||
err = "adapter pushes too many parameters";
|
||||
}
|
||||
}
|
||||
|
||||
// While we're at it, check that the stack motion decoder works:
|
||||
DEBUG_ONLY(int prev_pushes = decode_MethodHandle_stack_pushes(target()));
|
||||
DEBUG_ONLY(int target_pushes = decode_MethodHandle_stack_pushes(target()));
|
||||
DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh()));
|
||||
assert(this_pushes == slots_pushed + prev_pushes, "AMH stack motion must be correct");
|
||||
assert(this_pushes == slots_pushed + target_pushes, "AMH stack motion must be correct");
|
||||
}
|
||||
|
||||
if (err == NULL && vminfo != 0) {
|
||||
@ -1761,7 +1821,11 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
||||
if (err == NULL) {
|
||||
switch (ek) {
|
||||
case _adapter_retype_only:
|
||||
err = check_method_type_passthrough(src_mtype(), dst_mtype());
|
||||
err = check_method_type_passthrough(src_mtype(), dst_mtype(), false);
|
||||
break;
|
||||
|
||||
case _adapter_retype_raw:
|
||||
err = check_method_type_passthrough(src_mtype(), dst_mtype(), true);
|
||||
break;
|
||||
|
||||
case _adapter_check_cast:
|
||||
@ -1821,6 +1885,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
// Now it's time to finish the case analysis and pick a MethodHandleEntry.
|
||||
switch (ek_orig) {
|
||||
case _adapter_retype_only:
|
||||
case _adapter_retype_raw:
|
||||
case _adapter_check_cast:
|
||||
case _adapter_dup_args:
|
||||
case _adapter_drop_args:
|
||||
@ -1888,8 +1953,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
|
||||
case _adapter_rot_args:
|
||||
{
|
||||
int swap_slots = type2size[src];
|
||||
oop mtype = sun_dyn_AdapterMethodHandle::type(mh());
|
||||
int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mtype);
|
||||
int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mh());
|
||||
int src_slot = argslot;
|
||||
int dest_slot = vminfo;
|
||||
int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1;
|
||||
@ -2133,7 +2197,7 @@ JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) {
|
||||
guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF,
|
||||
"MethodHandlePushLimit parameter must be in valid range");
|
||||
return MethodHandlePushLimit;
|
||||
case MethodHandles::GC_JVM_STACK_MOVE_LIMIT:
|
||||
case MethodHandles::GC_JVM_STACK_MOVE_UNIT:
|
||||
// return number of words per slot, signed according to stack direction
|
||||
return MethodHandles::stack_move_unit();
|
||||
}
|
||||
@ -2144,7 +2208,7 @@ JVM_END
|
||||
#ifndef PRODUCT
|
||||
#define EACH_NAMED_CON(template) \
|
||||
template(MethodHandles,GC_JVM_PUSH_LIMIT) \
|
||||
template(MethodHandles,GC_JVM_STACK_MOVE_LIMIT) \
|
||||
template(MethodHandles,GC_JVM_STACK_MOVE_UNIT) \
|
||||
template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \
|
||||
template(MethodHandles,ETF_DIRECT_HANDLE) \
|
||||
template(MethodHandles,ETF_METHOD_NAME) \
|
||||
@ -2157,6 +2221,7 @@ JVM_END
|
||||
template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \
|
||||
template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \
|
||||
template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \
|
||||
template(sun_dyn_AdapterMethodHandle,OP_RETYPE_RAW) \
|
||||
template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \
|
||||
template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \
|
||||
template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \
|
||||
@ -2345,10 +2410,12 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
|
||||
// note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes
|
||||
|
||||
if (!EnableMethodHandles) {
|
||||
warning("JSR 292 method handles are disabled in this JVM. Use -XX:+EnableMethodHandles to enable.");
|
||||
warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable.");
|
||||
return; // bind nothing
|
||||
}
|
||||
|
||||
bool enable_MH = true;
|
||||
|
||||
{
|
||||
ThreadToNativeFromVM ttnfv(thread);
|
||||
|
||||
@ -2356,14 +2423,33 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
|
||||
if (env->ExceptionOccurred()) {
|
||||
MethodHandles::set_enabled(false);
|
||||
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
|
||||
enable_MH = false;
|
||||
env->ExceptionClear();
|
||||
} else {
|
||||
MethodHandles::set_enabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_MH) {
|
||||
KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass();
|
||||
if (MHI_klass.not_null()) {
|
||||
symbolHandle raiseException_name = oopFactory::new_symbol_handle("raiseException", CHECK);
|
||||
symbolHandle raiseException_sig = oopFactory::new_symbol_handle("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
|
||||
methodOop raiseException_method = instanceKlass::cast(MHI_klass->as_klassOop())
|
||||
->find_method(raiseException_name(), raiseException_sig());
|
||||
if (raiseException_method != NULL && raiseException_method->is_static()) {
|
||||
MethodHandles::set_raise_exception_method(raiseException_method);
|
||||
} else {
|
||||
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
|
||||
enable_MH = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_MH) {
|
||||
MethodHandles::set_enabled(true);
|
||||
}
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+EnableInvokeDynamic to enable.");
|
||||
warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable.");
|
||||
return; // bind nothing
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,7 @@ class MethodHandles: AllStatic {
|
||||
// See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}.
|
||||
public:
|
||||
enum EntryKind {
|
||||
_check_mtype, // how a caller calls a MH
|
||||
_wrong_method_type, // what happens when there is a type mismatch
|
||||
_raise_exception, // stub for error generation from other stubs
|
||||
_invokestatic_mh, // how a MH emulates invokestatic
|
||||
_invokespecial_mh, // ditto for the other invokes...
|
||||
_invokevirtual_mh,
|
||||
@ -47,6 +46,7 @@ class MethodHandles: AllStatic {
|
||||
|
||||
_adapter_mh_first, // adapter sequence goes here...
|
||||
_adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY,
|
||||
_adapter_retype_raw = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW,
|
||||
_adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST,
|
||||
_adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM,
|
||||
_adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM,
|
||||
@ -113,6 +113,8 @@ class MethodHandles: AllStatic {
|
||||
static bool _enabled;
|
||||
static MethodHandleEntry* _entries[_EK_LIMIT];
|
||||
static const char* _entry_names[_EK_LIMIT+1];
|
||||
static jobject _raise_exception_method;
|
||||
|
||||
static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; }
|
||||
static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; }
|
||||
|
||||
@ -131,6 +133,16 @@ class MethodHandles: AllStatic {
|
||||
_entries[ek] = me;
|
||||
}
|
||||
|
||||
static methodOop raise_exception_method() {
|
||||
oop rem = JNIHandles::resolve(_raise_exception_method);
|
||||
assert(rem == NULL || rem->is_method(), "");
|
||||
return (methodOop) rem;
|
||||
}
|
||||
static void set_raise_exception_method(methodOop rem) {
|
||||
assert(_raise_exception_method == NULL, "");
|
||||
_raise_exception_method = JNIHandles::make_global(Handle(rem));
|
||||
}
|
||||
|
||||
static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
|
||||
int stack_move = 0, int vminfo = 0) {
|
||||
assert(conv_op_valid(conv_op), "oob");
|
||||
@ -243,7 +255,7 @@ class MethodHandles: AllStatic {
|
||||
enum {
|
||||
// format of query to getConstant:
|
||||
GC_JVM_PUSH_LIMIT = 0,
|
||||
GC_JVM_STACK_MOVE_LIMIT = 1,
|
||||
GC_JVM_STACK_MOVE_UNIT = 1,
|
||||
|
||||
// format of result from getTarget / encode_target:
|
||||
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
|
||||
@ -261,7 +273,8 @@ class MethodHandles: AllStatic {
|
||||
int insert_argnum, oop insert_type,
|
||||
int change_argnum, oop change_type,
|
||||
int delete_argnum,
|
||||
oop dst_mtype, int dst_beg, int dst_end);
|
||||
oop dst_mtype, int dst_beg, int dst_end,
|
||||
bool raw = false);
|
||||
static const char* check_method_type_insertion(oop src_mtype,
|
||||
int insert_argnum, oop insert_type,
|
||||
oop dst_mtype) {
|
||||
@ -278,29 +291,29 @@ class MethodHandles: AllStatic {
|
||||
change_argnum, change_type,
|
||||
-1, dst_mtype, 0, -1);
|
||||
}
|
||||
static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) {
|
||||
static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype, bool raw) {
|
||||
oop no_ref = NULL;
|
||||
return check_method_type_change(src_mtype, 0, -1,
|
||||
-1, no_ref, -1, no_ref, -1,
|
||||
dst_mtype, 0, -1);
|
||||
dst_mtype, 0, -1, raw);
|
||||
}
|
||||
|
||||
// These checkers operate on pairs of argument or return types:
|
||||
static const char* check_argument_type_change(BasicType src_type, klassOop src_klass,
|
||||
BasicType dst_type, klassOop dst_klass,
|
||||
int argnum);
|
||||
int argnum, bool raw = false);
|
||||
|
||||
static const char* check_argument_type_change(oop src_type, oop dst_type,
|
||||
int argnum) {
|
||||
int argnum, bool raw = false) {
|
||||
klassOop src_klass = NULL, dst_klass = NULL;
|
||||
BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass);
|
||||
BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass);
|
||||
return check_argument_type_change(src_bt, src_klass,
|
||||
dst_bt, dst_klass, argnum);
|
||||
dst_bt, dst_klass, argnum, raw);
|
||||
}
|
||||
|
||||
static const char* check_return_type_change(oop src_type, oop dst_type) {
|
||||
return check_argument_type_change(src_type, dst_type, -1);
|
||||
static const char* check_return_type_change(oop src_type, oop dst_type, bool raw = false) {
|
||||
return check_argument_type_change(src_type, dst_type, -1, raw);
|
||||
}
|
||||
|
||||
static const char* check_return_type_change(BasicType src_type, klassOop src_klass,
|
||||
@ -357,9 +370,10 @@ class MethodHandles: AllStatic {
|
||||
TRAPS);
|
||||
|
||||
static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
|
||||
bool raw = false,
|
||||
bool for_return = false);
|
||||
static bool same_basic_type_for_returns(BasicType src, BasicType dst) {
|
||||
return same_basic_type_for_arguments(src, dst, true);
|
||||
static bool same_basic_type_for_returns(BasicType src, BasicType dst, bool raw = false) {
|
||||
return same_basic_type_for_arguments(src, dst, raw, true);
|
||||
}
|
||||
|
||||
enum { // arg_mask values
|
||||
|
@ -594,6 +594,7 @@ static inline uint64_t cast_uint64_t(size_t x)
|
||||
\
|
||||
nonstatic_field(PcDesc, _pc_offset, int) \
|
||||
nonstatic_field(PcDesc, _scope_decode_offset, int) \
|
||||
nonstatic_field(PcDesc, _obj_decode_offset, int) \
|
||||
nonstatic_field(PcDesc, _flags, PcDesc::PcDescFlags) \
|
||||
\
|
||||
/***************************************************/ \
|
||||
|
@ -1913,8 +1913,9 @@ void HeapDumper::dump_heap() {
|
||||
if (use_default_filename) {
|
||||
char fn[32];
|
||||
sprintf(fn, "java_pid%d", os::current_process_id());
|
||||
assert(strlen(base_path) + strlen(fn) < sizeof(base_path), "HeapDumpPath too long");
|
||||
assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long");
|
||||
strcat(base_path, fn);
|
||||
strcat(base_path, ".hprof");
|
||||
}
|
||||
assert(strlen(base_path) < sizeof(my_path), "Buffer too small");
|
||||
strcpy(my_path, base_path);
|
||||
@ -1927,8 +1928,6 @@ void HeapDumper::dump_heap() {
|
||||
strcat(my_path, fn);
|
||||
}
|
||||
dump_file_seq++; // increment seq number for next time we dump
|
||||
assert(strlen(".hprof") + strlen(my_path) < sizeof(my_path), "HeapDumpPath too long");
|
||||
strcat(my_path, ".hprof");
|
||||
|
||||
HeapDumper dumper(false /* no GC before heap dump */,
|
||||
true /* send to tty */);
|
||||
|
108
hotspot/test/compiler/6891750/Test6891750.java
Normal file
108
hotspot/test/compiler/6891750/Test6891750.java
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6891750
|
||||
* @summary deopt blob kills values in O5
|
||||
*
|
||||
* @run main Test6891750
|
||||
*/
|
||||
|
||||
abstract class Base6891750 extends Thread {
|
||||
abstract public long m();
|
||||
}
|
||||
class Other6891750 extends Base6891750 {
|
||||
public long m() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class Test6891750 extends Base6891750 {
|
||||
Base6891750 d;
|
||||
volatile long value = 9;
|
||||
|
||||
static int limit = 400000;
|
||||
|
||||
Test6891750() {
|
||||
d = this;
|
||||
|
||||
}
|
||||
public long m() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public long test(boolean doit) {
|
||||
if (doit) {
|
||||
long total0 = 0;
|
||||
long total1 = 0;
|
||||
long total2 = 0;
|
||||
long total3 = 0;
|
||||
long total4 = 0;
|
||||
long total5 = 0;
|
||||
long total6 = 0;
|
||||
long total7 = 0;
|
||||
long total8 = 0;
|
||||
long total9 = 0;
|
||||
for (int i = 0; i < limit; i++) {
|
||||
total0 += d.m();
|
||||
total1 += d.m();
|
||||
total2 += d.m();
|
||||
total3 += d.m();
|
||||
total4 += d.m();
|
||||
total5 += d.m();
|
||||
total6 += d.m();
|
||||
total7 += d.m();
|
||||
total8 += d.m();
|
||||
total9 += d.m();
|
||||
}
|
||||
return total0 + total1 + total2 + total3 + total4 + total5 + total6 + total7 + total8 + total9;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
long result = test(true);
|
||||
for (int i = 0; i < 300; i++) {
|
||||
long result2 = test(true);
|
||||
if (result != result2) {
|
||||
throw new InternalError(result + " != " + result2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Test6891750 Test6891750 = new Test6891750();
|
||||
// warm it up
|
||||
for (int i = 0; i < 200000; i++) {
|
||||
Test6891750.test(false);
|
||||
}
|
||||
// set in off running
|
||||
Test6891750.start();
|
||||
Thread.sleep(2000);
|
||||
|
||||
// Load a class to invalidate CHA
|
||||
new Other6891750();
|
||||
}
|
||||
}
|
@ -49,3 +49,4 @@ b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71
|
||||
460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
|
||||
f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
|
||||
eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
|
||||
8885b22565077236a927e824ef450742e434a230 jdk7-b75
|
||||
|
@ -116,8 +116,16 @@ CFLAGS_REQUIRED_sparcv9 += -m64 -mcpu=v9
|
||||
LDFLAGS_COMMON_sparcv9 += -m64 -mcpu=v9
|
||||
CFLAGS_REQUIRED_sparc += -m32 -mcpu=v9
|
||||
LDFLAGS_COMMON_sparc += -m32 -mcpu=v9
|
||||
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
|
||||
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
CFLAGS_REQUIRED = $(ZERO_ARCHFLAG)
|
||||
ifeq ($(ZERO_ENDIANNESS), little)
|
||||
CFLAGS_REQUIRED += -D_LITTLE_ENDIAN
|
||||
endif
|
||||
LDFLAGS_COMMON += $(ZERO_ARCHFLAG)
|
||||
else
|
||||
CFLAGS_REQUIRED = $(CFLAGS_REQUIRED_$(ARCH))
|
||||
LDFLAGS_COMMON += $(LDFLAGS_COMMON_$(ARCH))
|
||||
endif
|
||||
|
||||
# If this is a --hash-style=gnu system, use --hash-style=both
|
||||
# The gnu .hash section won't work on some Linux systems like SuSE 10.
|
||||
@ -217,7 +225,7 @@ endif
|
||||
|
||||
EXTRA_LIBS += -lc
|
||||
|
||||
LDFLAGS_DEFS_OPTION = -z defs
|
||||
LDFLAGS_DEFS_OPTION = -Xlinker -z -Xlinker defs
|
||||
LDFLAGS_COMMON += $(LDFLAGS_DEFS_OPTION)
|
||||
|
||||
#
|
||||
|
@ -667,12 +667,7 @@ LDLIBS = $(OTHER_LDLIBS) $(LDLIBS_$(VARIANT)) $(LDLIBS_COMMON)
|
||||
LINTFLAGS = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \
|
||||
$(OTHER_LINTFLAGS)
|
||||
|
||||
# this should be moved into Defs-<platform>.gmk.....
|
||||
ifeq ($(PLATFORM), windows)
|
||||
VERSION_DEFINES = -DRELEASE="\"$(RELEASE)\""
|
||||
else
|
||||
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
|
||||
endif
|
||||
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
|
||||
|
||||
# Note: As a rule, GNU Make rules should not appear in any of the
|
||||
# Defs*.gmk files. These were added for Kestrel-Solaris and do address
|
||||
|
@ -85,7 +85,7 @@ ifneq (,$(findstring $(PLATFORM), linux solaris)) # UNIX systems
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM), linux)
|
||||
LDFLAGS += -z origin
|
||||
LDFLAGS += -Wl,-z -Wl,origin
|
||||
LDFLAGS += -Wl,--allow-shlib-undefined
|
||||
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../lib/$(LIBARCH)/jli
|
||||
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../jre/lib/$(LIBARCH)/jli
|
||||
@ -236,13 +236,13 @@ endif # files
|
||||
endif # INCREMENTAL_BUILD
|
||||
|
||||
ifdef JAVA_ARGS
|
||||
OTHER_CPPFLAGS += -DJAVA_ARGS=$(JAVA_ARGS)
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
|
||||
OTHER_CPPFLAGS += -DJAVA_ARGS='$(JAVA_ARGS)'
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), windows)
|
||||
ifdef RELEASE
|
||||
OTHER_CPPFLAGS += -DVERSION="$(RELEASE)"
|
||||
OTHER_CPPFLAGS += -DVERSION='"$(RELEASE)"'
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -258,14 +258,8 @@ endif
|
||||
OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)/bin -I$(LAUNCHER_PLATFORM_SRC)/bin
|
||||
OTHER_INCLUDES += -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
|
||||
|
||||
# this may not be necessary...
|
||||
ifeq ($(PLATFORM), windows)
|
||||
OTHER_CPPFLAGS += -DPROGNAME="\"$(PROGRAM)\""
|
||||
VERSION_DEFINES += -DFULL_VERSION="\"$(FULL_VERSION)\""
|
||||
else
|
||||
OTHER_CPPFLAGS += -DPROGNAME='"$(PROGRAM)"'
|
||||
VERSION_DEFINES += -DFULL_VERSION='"$(FULL_VERSION)"'
|
||||
endif
|
||||
|
||||
VERSION_DEFINES += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
|
||||
-DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"'
|
||||
@ -279,8 +273,14 @@ $(OBJDIR)/main.$(OBJECT_SUFFIX): $(LAUNCHER_SHARE_SRC)/bin/main.c
|
||||
|
||||
#
|
||||
# How to install jvm.cfg.
|
||||
#
|
||||
$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(ARCH)/jvm.cfg
|
||||
#
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
JVMCFG_ARCH = zero
|
||||
else
|
||||
JVMCFG_ARCH = $(ARCH)
|
||||
endif
|
||||
|
||||
$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(JVMCFG_ARCH)/jvm.cfg
|
||||
$(install-file)
|
||||
|
||||
#
|
||||
|
@ -330,7 +330,7 @@ endif
|
||||
#
|
||||
# Specific files and directories that will be filtered out from above areas.
|
||||
#
|
||||
SOURCE_FILTERs = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
|
||||
SOURCE_FILTERs = $(SCM_DIRs) ',*'
|
||||
SOURCE_FILES_filter = $(SOURCE_FILTERs:%=-name % -prune -o)
|
||||
|
||||
#
|
||||
|
@ -63,7 +63,7 @@ endif
|
||||
# If AUTO_FILES_PROPERTIES_DIRS used, automatically find properties files
|
||||
#
|
||||
ifdef AUTO_FILES_PROPERTIES_DIRS
|
||||
AUTO_FILES_PROPERTIES_FILTERS1 = $(SCM_DIRs) 'X-*' '*-X-*' ',*'
|
||||
AUTO_FILES_PROPERTIES_FILTERS1 = $(SCM_DIRs) ',*'
|
||||
AUTO_FILES_PROPERTIES_FILTERS1 += $(AUTO_PROPERTIES_PRUNE)
|
||||
FILES_properties_find_filters1 = $(AUTO_FILES_PROPERTIES_FILTERS1:%=-name % -prune -o)
|
||||
FILES_properties_auto1 := \
|
||||
@ -111,7 +111,7 @@ include $(JDK_TOPDIR)/make/common/internal/Resources.gmk
|
||||
|
||||
ifdef AUTO_FILES_JAVA_DIRS
|
||||
# Filter out these files or directories
|
||||
AUTO_FILES_JAVA_SOURCE_FILTERS1 = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
|
||||
AUTO_FILES_JAVA_SOURCE_FILTERS1 = $(SCM_DIRs) ',*'
|
||||
AUTO_FILES_JAVA_SOURCE_FILTERS2 =
|
||||
AUTO_FILES_JAVA_SOURCE_FILTERS1 += $(AUTO_JAVA_PRUNE)
|
||||
AUTO_FILES_JAVA_SOURCE_FILTERS2 += $(AUTO_JAVA_PRUNE)
|
||||
|
@ -109,7 +109,7 @@ else
|
||||
LDFLAGS += -R \$$ORIGIN/jli
|
||||
endif
|
||||
ifeq ($(PLATFORM), linux)
|
||||
LDFLAGS += -z origin
|
||||
LDFLAGS += -Wl,-z -Wl,origin
|
||||
LDFLAGS += -Wl,--allow-shlib-undefined
|
||||
LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/jli
|
||||
endif
|
||||
|
@ -286,11 +286,18 @@ JAVA_JAVA_java = \
|
||||
java/util/concurrent/ExecutorService.java \
|
||||
java/util/concurrent/ExecutorCompletionService.java \
|
||||
java/util/concurrent/Executors.java \
|
||||
java/util/concurrent/ForkJoinPool.java \
|
||||
java/util/concurrent/ForkJoinTask.java \
|
||||
java/util/concurrent/ForkJoinWorkerThread.java \
|
||||
java/util/concurrent/Future.java \
|
||||
java/util/concurrent/FutureTask.java \
|
||||
java/util/concurrent/LinkedBlockingDeque.java \
|
||||
java/util/concurrent/LinkedBlockingQueue.java \
|
||||
java/util/concurrent/LinkedTransferQueue.java \
|
||||
java/util/concurrent/Phaser.java \
|
||||
java/util/concurrent/PriorityBlockingQueue.java \
|
||||
java/util/concurrent/RecursiveAction.java \
|
||||
java/util/concurrent/RecursiveTask.java \
|
||||
java/util/concurrent/RejectedExecutionException.java \
|
||||
java/util/concurrent/RejectedExecutionHandler.java \
|
||||
java/util/concurrent/RunnableFuture.java \
|
||||
@ -301,9 +308,11 @@ JAVA_JAVA_java = \
|
||||
java/util/concurrent/Semaphore.java \
|
||||
java/util/concurrent/SynchronousQueue.java \
|
||||
java/util/concurrent/ThreadFactory.java \
|
||||
java/util/concurrent/ThreadLocalRandom.java \
|
||||
java/util/concurrent/ThreadPoolExecutor.java \
|
||||
java/util/concurrent/TimeUnit.java \
|
||||
java/util/concurrent/TimeoutException.java \
|
||||
java/util/concurrent/TransferQueue.java \
|
||||
java/util/concurrent/atomic/AtomicBoolean.java \
|
||||
java/util/concurrent/atomic/AtomicInteger.java \
|
||||
java/util/concurrent/atomic/AtomicIntegerArray.java \
|
||||
|
@ -48,11 +48,15 @@ ZIP_SRC = $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
|
||||
LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
|
||||
LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
|
||||
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
ERGO_FAMILY=zero
|
||||
else
|
||||
ifeq ($(ARCH_FAMILY), amd64)
|
||||
ERGO_FAMILY=i586
|
||||
else
|
||||
ERGO_FAMILY=$(ARCH_FAMILY)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
|
@ -57,7 +57,7 @@ endif
|
||||
#
|
||||
include $(BUILDDIR)/common/Program.gmk
|
||||
OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
|
||||
|
||||
ifeq ($(PLATFORM), solaris)
|
||||
LDFLAGS += -R$(OPENWIN_LIB)
|
||||
|
@ -62,4 +62,5 @@ endif
|
||||
#
|
||||
include $(BUILDDIR)/common/Program.gmk
|
||||
OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
|
||||
OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
|
||||
|
||||
|
@ -335,6 +335,15 @@ SCH_SRC=$(SNIO_SRC)/ch
|
||||
SCS_SRC=$(SNIO_SRC)/cs
|
||||
SFS_SRC=$(SNIO_SRC)/fs
|
||||
|
||||
# Template files
|
||||
HEAP_X_BUF_TEMPLATE=$(BUF_SRC)/Heap-X-Buffer.java.template
|
||||
BYTE_X_BUF_TEMPLATE=$(BUF_SRC)/ByteBufferAs-X-Buffer.java.template
|
||||
X_BUF_TEMPLATE=$(BUF_SRC)/X-Buffer.java.template
|
||||
X_BUF_BIN_TEMPLATE=$(BUF_SRC)/X-Buffer-bin.java.template
|
||||
DIRECT_X_BUF_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer.java.template
|
||||
DIRECT_X_BUF_BIN_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer-bin.java.template
|
||||
CHARSET_X_CODER_TEMPLATE=$(CS_SRC)/Charset-X-Coder.java.template
|
||||
|
||||
BUF_GEN=$(NIO_GEN)
|
||||
CH_GEN=$(NIO_GEN)/channels
|
||||
CS_GEN=$(NIO_GEN)/charset
|
||||
@ -357,39 +366,39 @@ GEN_BUFFER_CMD = SPP="$(SPP_CMD)" NAWK="$(NAWK)" SED="$(SED)" SH="$(SH)" \
|
||||
|
||||
# Public abstract buffer classes
|
||||
#
|
||||
$(BUF_GEN)/ByteBuffer.java: $(BUF_SRC)/X-Buffer.java \
|
||||
$(BUF_SRC)/X-Buffer-bin.java \
|
||||
$(BUF_GEN)/ByteBuffer.java: $(X_BUF_TEMPLATE) \
|
||||
$(X_BUF_BIN_TEMPLATE) \
|
||||
$(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/CharBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/CharBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ShortBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ShortBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/IntBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/IntBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/LongBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/LongBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/FloatBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/FloatBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DoubleBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DoubleBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -397,72 +406,72 @@ $(BUF_GEN)/DoubleBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
|
||||
|
||||
# Buffers whose contents are heap-allocated
|
||||
#
|
||||
$(BUF_GEN)/HeapByteBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapByteBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=byte SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapByteBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapByteBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=byte RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapCharBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapCharBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapCharBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapCharBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapShortBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapShortBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapShortBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapShortBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapIntBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapIntBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapIntBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapIntBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapLongBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapLongBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapLongBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapLongBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapFloatBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapFloatBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapFloatBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapFloatBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapDoubleBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapDoubleBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/HeapDoubleBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/HeapDoubleBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -470,15 +479,15 @@ $(BUF_GEN)/HeapDoubleBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH
|
||||
|
||||
# Direct byte buffer
|
||||
#
|
||||
$(BUF_GEN)/DirectByteBuffer.java: $(BUF_SRC)/Direct-X-Buffer.java \
|
||||
$(BUF_SRC)/Direct-X-Buffer.java \
|
||||
$(BUF_GEN)/DirectByteBuffer.java: $(DIRECT_X_BUF_TEMPLATE) \
|
||||
$(DIRECT_X_BUF_TEMPLATE) \
|
||||
$(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectByteBuffer%.java: $(BUF_SRC)/Direct-X-Buffer.java \
|
||||
$(BUF_SRC)/Direct-X-Buffer.java \
|
||||
$(BUF_GEN)/DirectByteBuffer%.java: $(DIRECT_X_BUF_TEMPLATE) \
|
||||
$(DIRECT_X_BUF_TEMPLATE) \
|
||||
$(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
@ -487,62 +496,62 @@ $(BUF_GEN)/DirectByteBuffer%.java: $(BUF_SRC)/Direct-X-Buffer.java \
|
||||
|
||||
# Unswapped views of direct byte buffers
|
||||
#
|
||||
$(BUF_GEN)/DirectCharBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectCharBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectCharBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectCharBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectShortBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectShortBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectShortBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectShortBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectIntBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectIntBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectIntBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectIntBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectLongBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectLongBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectLongBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectLongBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectFloatBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectFloatBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectFloatBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectFloatBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectDoubleBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectDoubleBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectDoubleBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectDoubleBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -550,62 +559,62 @@ $(BUF_GEN)/DirectDoubleBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFF
|
||||
|
||||
# Swapped views of direct byte buffers
|
||||
#
|
||||
$(BUF_GEN)/DirectCharBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectCharBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectCharBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectCharBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectShortBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectShortBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectShortBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectShortBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectIntBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectIntBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectIntBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectIntBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectLongBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectLongBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectLongBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectLongBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectFloatBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectFloatBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectFloatBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectFloatBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectDoubleBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectDoubleBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/DirectDoubleBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/DirectDoubleBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -613,62 +622,62 @@ $(BUF_GEN)/DirectDoubleBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFF
|
||||
|
||||
# Big-endian views of byte buffers
|
||||
#
|
||||
$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -676,62 +685,62 @@ $(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.jav
|
||||
|
||||
# Little-endian views of byte buffers
|
||||
#
|
||||
$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=char RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=short RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=int RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=long RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=float RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
$(MV) $@.temp $@
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
|
||||
$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
TYPE=double RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
|
||||
@ -745,13 +754,13 @@ GEN_CODER_SH = genCoder.sh
|
||||
|
||||
GEN_CODER_CMD = SPP="$(SPP_CMD)" SED="$(SED)" NAWK="$(NAWK)" SH="$(SH)" $(SH) $(GEN_CODER_SH)
|
||||
|
||||
$(CS_GEN)/CharsetDecoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
|
||||
$(CS_GEN)/CharsetDecoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
$(GEN_CODER_CMD) decoder $< $@.temp
|
||||
$(MV) $@.temp $@
|
||||
|
||||
$(CS_GEN)/CharsetEncoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
|
||||
$(CS_GEN)/CharsetEncoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
|
||||
$(prep-target)
|
||||
@$(RM) $@.temp
|
||||
$(GEN_CODER_CMD) encoder $< $@.temp
|
||||
|
@ -154,7 +154,7 @@ if [ $BIN ]; then
|
||||
mv $DST $DST.tmp
|
||||
sed -e '/#BIN/,$d' <$DST.tmp >$DST
|
||||
rm -f $DST.tmp
|
||||
binops=`dirname $SRC`/`basename $SRC .java`-bin.java
|
||||
binops=`dirname $SRC`/`basename $SRC .java.template`-bin.java.template
|
||||
genBinOps char character 1 two one $binops >>$DST
|
||||
genBinOps short short 1 two one $binops >>$DST
|
||||
genBinOps int integer 2 four three $binops >>$DST
|
||||
|
@ -94,11 +94,13 @@ ifeq ($(INCLUDE_SA), true)
|
||||
endif
|
||||
endif # INCLUDE_SA
|
||||
|
||||
# Hotspot client is only available on 32-bit builds
|
||||
# Hotspot client is only available on 32-bit non-Zero builds
|
||||
ifneq ($(ZERO_BUILD), true)
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME) \
|
||||
$(LIB_LOCATION)/$(CLIENT_LOCATION)/Xusage.txt
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), windows)
|
||||
# Windows vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Windows
|
||||
@ -171,6 +173,7 @@ ifeq ($(PLATFORM), solaris)
|
||||
IMPORT_LIST += $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME)
|
||||
endif
|
||||
|
||||
ifneq ($(ZERO_BUILD), true)
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
|
||||
IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME)
|
||||
@ -201,6 +204,8 @@ endif # 32bit solaris
|
||||
|
||||
endif # 32bit
|
||||
|
||||
endif # ZERO_BUILD
|
||||
|
||||
# NOT Windows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ NOT Windows
|
||||
|
||||
endif # PLATFORM
|
||||
|
@ -33,7 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk
|
||||
all build: $(GENSRCDIR)/sun/misc/Version.java
|
||||
|
||||
$(GENSRCDIR)/sun/misc/Version.java: \
|
||||
$(SHARE_SRC)/classes/sun/misc/Version-template.java
|
||||
$(SHARE_SRC)/classes/sun/misc/Version.java.template
|
||||
$(prep-target)
|
||||
$(RM) $@.temp
|
||||
$(SED) -e 's/@@launcher_name@@/$(LAUNCHER_NAME)/g' \
|
||||
|
@ -128,7 +128,7 @@ endif # PLATFORM solaris
|
||||
|
||||
# for dynamic inclusion of extra sound libs: these
|
||||
# JNI libs will be loaded from Platform.java
|
||||
CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS="\"$(EXTRA_SOUND_JNI_LIBS)\""
|
||||
CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
|
||||
|
||||
# integrate MIDI i/o in jsound lib
|
||||
ifeq ($(INCLUDE_MIDI),TRUE)
|
||||
|
@ -55,21 +55,25 @@ ifeq ($(PLATFORM), solaris)
|
||||
|
||||
endif # PLATFORM solaris
|
||||
|
||||
ifeq ($(ARCH), i586)
|
||||
CPPFLAGS += -DX_ARCH=X_I586
|
||||
endif # ARCH i586
|
||||
ifeq ($(ZERO_BUILD), true)
|
||||
CPPFLAGS += -DX_ARCH=X_ZERO
|
||||
else
|
||||
ifeq ($(ARCH), i586)
|
||||
CPPFLAGS += -DX_ARCH=X_I586
|
||||
endif # ARCH i586
|
||||
|
||||
ifeq ($(ARCH), sparc)
|
||||
CPPFLAGS += -DX_ARCH=X_SPARC
|
||||
endif # ARCH sparc
|
||||
ifeq ($(ARCH), sparc)
|
||||
CPPFLAGS += -DX_ARCH=X_SPARC
|
||||
endif # ARCH sparc
|
||||
|
||||
ifeq ($(ARCH), sparcv9)
|
||||
CPPFLAGS += -DX_ARCH=X_SPARCV9
|
||||
endif # ARCH sparcv9
|
||||
ifeq ($(ARCH), sparcv9)
|
||||
CPPFLAGS += -DX_ARCH=X_SPARCV9
|
||||
endif # ARCH sparcv9
|
||||
|
||||
ifeq ($(ARCH), amd64)
|
||||
CPPFLAGS += -DX_ARCH=X_AMD64
|
||||
endif # ARCH amd64
|
||||
ifeq ($(ARCH), amd64)
|
||||
CPPFLAGS += -DX_ARCH=X_AMD64
|
||||
endif # ARCH amd64
|
||||
endif
|
||||
|
||||
|
||||
# files needed for MIDI i/o
|
||||
|
@ -339,3 +339,82 @@ fi
|
||||
PATH="${path4sdk}"
|
||||
export PATH
|
||||
|
||||
# Export variables required for Zero
|
||||
if [ "${ZERO_BUILD}" = true ] ; then
|
||||
# ZERO_LIBARCH is the name of the architecture-specific
|
||||
# subdirectory under $JAVA_HOME/jre/lib
|
||||
arch=$(uname -m)
|
||||
case "${arch}" in
|
||||
x86_64) ZERO_LIBARCH=amd64 ;;
|
||||
i?86) ZERO_LIBARCH=i386 ;;
|
||||
sparc64) ZERO_LIBARCH=sparcv9 ;;
|
||||
arm*) ZERO_LIBARCH=arm ;;
|
||||
*) ZERO_LIBARCH="$(arch)"
|
||||
esac
|
||||
export ZERO_LIBARCH
|
||||
|
||||
# ARCH_DATA_MODEL is the number of bits in a pointer
|
||||
case "${ZERO_LIBARCH}" in
|
||||
i386|ppc|s390|sparc|arm)
|
||||
ARCH_DATA_MODEL=32
|
||||
;;
|
||||
amd64|ppc64|s390x|sparcv9|ia64|alpha)
|
||||
ARCH_DATA_MODEL=64
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unable to determine ARCH_DATA_MODEL for ${ZERO_LIBARCH}"
|
||||
exit 1
|
||||
esac
|
||||
export ARCH_DATA_MODEL
|
||||
|
||||
# ZERO_ENDIANNESS is the endianness of the processor
|
||||
case "${ZERO_LIBARCH}" in
|
||||
i386|amd64|ia64)
|
||||
ZERO_ENDIANNESS=little
|
||||
;;
|
||||
ppc*|s390*|sparc*|alpha)
|
||||
ZERO_ENDIANNESS=big
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unable to determine ZERO_ENDIANNESS for ${ZERO_LIBARCH}"
|
||||
exit 1
|
||||
esac
|
||||
export ZERO_ENDIANNESS
|
||||
|
||||
# ZERO_ARCHDEF is used to enable architecture-specific code
|
||||
case "${ZERO_LIBARCH}" in
|
||||
i386) ZERO_ARCHDEF=IA32 ;;
|
||||
ppc*) ZERO_ARCHDEF=PPC ;;
|
||||
s390*) ZERO_ARCHDEF=S390 ;;
|
||||
sparc*) ZERO_ARCHDEF=SPARC ;;
|
||||
*) ZERO_ARCHDEF=$(echo "${ZERO_LIBARCH}" | tr a-z A-Z)
|
||||
esac
|
||||
export ZERO_ARCHDEF
|
||||
|
||||
# ZERO_ARCHFLAG tells the compiler which mode to build for
|
||||
case "${ZERO_LIBARCH}" in
|
||||
s390)
|
||||
ZERO_ARCHFLAG="-m31"
|
||||
;;
|
||||
*)
|
||||
ZERO_ARCHFLAG="-m${ARCH_DATA_MODEL}"
|
||||
esac
|
||||
export ZERO_ARCHFLAG
|
||||
|
||||
# LIBFFI_CFLAGS and LIBFFI_LIBS tell the compiler how to compile and
|
||||
# link against libffi
|
||||
pkgconfig=$(which pkg-config 2>/dev/null)
|
||||
if [ -x "${pkgconfig}" ] ; then
|
||||
if [ "${LIBFFI_CFLAGS}" = "" ] ; then
|
||||
LIBFFI_CFLAGS=$("${pkgconfig}" --cflags libffi)
|
||||
fi
|
||||
if [ "${LIBFFI_LIBS}" = "" ] ; then
|
||||
LIBFFI_LIBS=$("${pkgconfig}" --libs libffi)
|
||||
fi
|
||||
fi
|
||||
if [ "${LIBFFI_LIBS}" = "" ] ; then
|
||||
LIBFFI_LIBS="-lffi"
|
||||
fi
|
||||
export LIBFFI_CFLAGS
|
||||
export LIBFFI_LIBS
|
||||
fi
|
||||
|
@ -137,15 +137,15 @@ ifeq ($(PROGRAM),jdb)
|
||||
# PROGRAM, JAVA_ARGS, and APP_CLASSPATH are used in src/share/bin/java.c
|
||||
# SA is currently not available on windows (for any ARCH), or linux-ia64:
|
||||
ifneq ($(ARCH), ia64)
|
||||
JDB_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\" }"
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JDB_CLASSPATH)
|
||||
JDB_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JDB_CLASSPATH)'
|
||||
endif
|
||||
endif
|
||||
|
||||
# jconsole only
|
||||
ifeq ($(PROGRAM),jconsole)
|
||||
JCONSOLE_CLASSPATH = "{ \"/lib/jconsole.jar\", \"/lib/tools.jar\", \"/classes\" }"
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JCONSOLE_CLASSPATH)
|
||||
JCONSOLE_CLASSPATH = { "/lib/jconsole.jar", "/lib/tools.jar", "/classes" }
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JCONSOLE_CLASSPATH)'
|
||||
ifeq ($(PLATFORM), windows)
|
||||
OTHER_CPPFLAGS += -DJAVAW
|
||||
LDLIBS_COMMON += user32.lib
|
||||
@ -163,8 +163,8 @@ endif
|
||||
|
||||
# SA tools need special app classpath
|
||||
ifeq ($(SA_TOOL),true)
|
||||
SA_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\"}"
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(SA_CLASSPATH)
|
||||
SA_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
|
||||
OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(SA_CLASSPATH)'
|
||||
endif
|
||||
|
||||
# Wildcards
|
||||
@ -173,11 +173,11 @@ ifeq ($(WILDCARDS),true)
|
||||
endif
|
||||
|
||||
# Always tell native code what the main class is
|
||||
OTHER_CPPFLAGS += -DMAIN_CLASS=\"$(MAIN_CLASS)\"
|
||||
OTHER_CPPFLAGS += -DMAIN_CLASS='"$(MAIN_CLASS)"'
|
||||
|
||||
# Construct initializer for initial arguments to java
|
||||
ALL_ARGS = -J-ms8m $(MAIN_JAVA_ARGS) $(MAIN_CLASS) $(MAIN_ARGS)
|
||||
JAVA_ARGS = "{ $(ALL_ARGS:%=\"%\",) }"
|
||||
JAVA_ARGS = { $(ALL_ARGS:%="%",) }
|
||||
|
||||
# Always report launcher info
|
||||
build: launcher_info
|
||||
|
@ -33,7 +33,7 @@ includes=\
|
||||
com/sun/tools/jconsole/ \
|
||||
sun/tools/jconsole/
|
||||
excludes=\
|
||||
sun/tools/jconsole/Version-template.java
|
||||
sun/tools/jconsole/Version.java.template
|
||||
jtreg.tests=\
|
||||
sun/tools/jconsole/
|
||||
javadoc.packagenames=\
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
<target name="-pre-compile">
|
||||
<copy
|
||||
file="${root}/src/share/classes/sun/tools/jconsole/Version-template.java"
|
||||
file="${root}/src/share/classes/sun/tools/jconsole/Version.java.template"
|
||||
tofile="${gensrc.dir}/sun/tools/jconsole/Version.java"/>
|
||||
<replace
|
||||
file="${gensrc.dir}/sun/tools/jconsole/Version.java"
|
||||
|
@ -70,7 +70,7 @@ include $(BUILDDIR)/common/Classes.gmk
|
||||
build: $(FILES_png) $(FILES_gif) $(TEMPDIR)/manifest $(JARFILE)
|
||||
|
||||
$(GENSRCDIR)/sun/tools/jconsole/Version.java: \
|
||||
$(SHARE_SRC)/classes/sun/tools/jconsole/Version-template.java
|
||||
$(SHARE_SRC)/classes/sun/tools/jconsole/Version.java.template
|
||||
$(MKDIR) -p $(@D)
|
||||
$(SED) -e 's/@@jconsole_version@@/$(FULL_VERSION)/g' $< > $@
|
||||
|
||||
|
@ -44,14 +44,6 @@ include $(BUILDDIR)/common/Defs.gmk
|
||||
include FILES_java.gmk
|
||||
AUTO_FILES_JAVA_DIRS = sun/nio/cs/ext
|
||||
|
||||
# Exclude a few sources on windows
|
||||
ifeq ($(PLATFORM), windows)
|
||||
AUTO_JAVA_PRUNE = sun/nio/cs/ext/COMPOUND_TEXT.java \
|
||||
sun/nio/cs/ext/COMPOUND_TEXT_Decoder.java \
|
||||
sun/nio/cs/ext/COMPOUND_TEXT_Encoder.java \
|
||||
sun/nio/cs/ext/CompoundTextSupport.java
|
||||
endif # PLATFORM
|
||||
|
||||
# For Cygwin, command line arguments that are paths must be converted to
|
||||
# windows style paths. These paths cannot be used as targets, however, because
|
||||
# the ":" in them will interfere with GNU Make rules, generating "multiple
|
||||
|
@ -38,7 +38,6 @@ SUBDIRS = \
|
||||
compile_properties \
|
||||
dir_diff \
|
||||
dtdbuilder \
|
||||
fontchecker \
|
||||
freetypecheck \
|
||||
generate_break_iterator \
|
||||
GenerateCharacter \
|
||||
|
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2004 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package build.tools.fontchecker;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* FontCheckDummy (not unlike Crash Test Dummy).
|
||||
*
|
||||
* <PRE>
|
||||
* FontCheckDummy is the "child" process. Its task is to verify
|
||||
* integrity of system fonts. Since unexpected crashes are known
|
||||
* to occur when certain fonts are manipulated, the process is
|
||||
* "monitored" by the parent process, which might have to restart
|
||||
* the "child" if it crashes.
|
||||
* </PRE>
|
||||
*
|
||||
* @author Ilya Bagrak
|
||||
*/
|
||||
public class FontCheckDummy implements FontCheckerConstants {
|
||||
|
||||
/**
|
||||
* Input stream from parent process.
|
||||
*/
|
||||
private BufferedReader is;
|
||||
|
||||
/**
|
||||
* Output stream to parent process.
|
||||
*/
|
||||
private BufferedOutputStream os;
|
||||
|
||||
/**
|
||||
* Image on which font characters will be drawn.
|
||||
*/
|
||||
private BufferedImage bi;
|
||||
|
||||
/**
|
||||
* graphics object on which characters will be drawn.
|
||||
*/
|
||||
private Graphics graphics;
|
||||
|
||||
/**
|
||||
* This constructor wraps the process's standard output and input streams
|
||||
* to enable easier communication with parent process. It also initializes
|
||||
* the graphics object used for drawing font characters.
|
||||
* <BR><BR>
|
||||
* @see FontCheckerConstants
|
||||
*/
|
||||
public FontCheckDummy() {
|
||||
is = new BufferedReader(new InputStreamReader(System.in));
|
||||
os = new BufferedOutputStream(System.out);
|
||||
/* make suffficient space for 12 point font */
|
||||
bi = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
|
||||
graphics = bi.getGraphics();
|
||||
try {
|
||||
os.write(CHILD_STARTED_OK);
|
||||
os.flush();
|
||||
} catch (IOException e) {
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an instance of Font from given font path.
|
||||
* <BR>
|
||||
* This methods attempts to create an instance of font from
|
||||
* a string that represents path to the font file.
|
||||
* <BR><BR>
|
||||
* @param fontPath string representing path to font file
|
||||
* @param flag indicating whether or not checking of non-TrueType fonts
|
||||
* is necessary
|
||||
*/
|
||||
private void testFont(String fontPath, boolean checkNonTTF) {
|
||||
|
||||
FontFileFilter fff = new FontFileFilter(checkNonTTF);
|
||||
File fontFile = new File(fontPath);
|
||||
if (!fontFile.canRead()) {
|
||||
try {
|
||||
os.write(ERR_FONT_NOT_FOUND);
|
||||
os.flush();
|
||||
} catch (IOException e) {
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
Font font = null;
|
||||
try {
|
||||
File file = new File(fontPath);
|
||||
font = Font.createFont(fff.getFontType(fontPath), file);
|
||||
} catch (FontFormatException e1) {
|
||||
} catch (IOException e2) {
|
||||
}
|
||||
if (font == null) {
|
||||
return;
|
||||
}
|
||||
font = font.deriveFont(Font.PLAIN, 12);
|
||||
String name = font.getFontName();
|
||||
String family = font.getFamily();
|
||||
|
||||
char[] testChars = { '0' };
|
||||
if (font.canDisplay(testChars[0])) {
|
||||
graphics.setFont(font);
|
||||
graphics.drawChars(testChars, 0, 1, 20, 20);
|
||||
}
|
||||
try {
|
||||
os.write(ERR_FONT_OK);
|
||||
os.flush();
|
||||
} catch (IOException e) {
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins synchronous communication betweeen parent and child processes.
|
||||
* <BR>
|
||||
* This method begins communication between parent and child processes.
|
||||
* FontCheckDummy reads a line of text from input stream (@see #is).
|
||||
*/
|
||||
public void run() {
|
||||
String command = null;
|
||||
while (true) {
|
||||
try {
|
||||
command = is.readLine();
|
||||
} catch (IOException e) {
|
||||
System.exit(-1);
|
||||
}
|
||||
if (command != null && command.length() >= 1) {
|
||||
int cmd = Integer.parseInt(command.substring(0,1));
|
||||
if (cmd == EXITCOMMAND) {
|
||||
return;
|
||||
}
|
||||
boolean checkNonTTF = ((cmd == 1) ? true : false);
|
||||
String fontPath = command.substring(1);
|
||||
testFont(fontPath, checkNonTTF);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
/* Background app. */
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
System.setProperty("sun.java2d.noddraw", "true");
|
||||
new FontCheckDummy().run();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
@ -1,452 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2004 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package build.tools.fontchecker;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.awt.event.*;
|
||||
import sun.font.FontManager;
|
||||
|
||||
/**
|
||||
* FontChecker.
|
||||
*
|
||||
* <PRE>
|
||||
* This is a FontChecker program. This class is a "parent" process
|
||||
* which invokes a "child" process. The child process will test
|
||||
* series of fonts and may crash as it encounters invalid fonts.
|
||||
* The "parent" process must then interpret error codes passed to it
|
||||
* by the "child" process and restart the "child" process if necessary.
|
||||
*
|
||||
* usage: java FontChecker [-v] -o outputfile
|
||||
*
|
||||
* -o is the name of the file to contains canonical path names of
|
||||
* bad fonts that are identified. This file is not created if
|
||||
* no bad fonts are found.
|
||||
* -v verbose: prints progress messages.
|
||||
*
|
||||
* </PRE>
|
||||
*
|
||||
* @author Ilya Bagrak
|
||||
*/
|
||||
public class FontChecker implements ActionListener, FontCheckerConstants {
|
||||
|
||||
/**
|
||||
* Output stream to subprocess.
|
||||
* Corresponds to the subprocess's System.in".
|
||||
*/
|
||||
private PrintWriter procPipeOut;
|
||||
|
||||
/**
|
||||
* Input stream from subprocess.
|
||||
* Corresponds to the subprocess's System.out".
|
||||
*/
|
||||
private BufferedInputStream procPipeIn;
|
||||
|
||||
/**
|
||||
* Child process.
|
||||
*/
|
||||
private Process childProc;
|
||||
|
||||
/**
|
||||
* Name of output file to write file names of bad fonts
|
||||
*/
|
||||
private String outputFile;
|
||||
|
||||
/**
|
||||
* Reference to currently executing thread.
|
||||
*/
|
||||
private Thread currThread;
|
||||
|
||||
/**
|
||||
* Timeout timer for a single font check
|
||||
*/
|
||||
private javax.swing.Timer timeOne;
|
||||
|
||||
/**
|
||||
* Timeout timer for all font checks
|
||||
*/
|
||||
private javax.swing.Timer timeAll;
|
||||
|
||||
/**
|
||||
* max time (in milliseconds) allowed for checking a single font.
|
||||
*/
|
||||
private static int timeoutOne = 10000;
|
||||
|
||||
/**
|
||||
* max time (in milliseconds) allowed for checking all fonts.
|
||||
*/
|
||||
private static int timeoutAll = 120000;
|
||||
|
||||
/**
|
||||
* Boolean flag indicating whether FontChecker is required to
|
||||
* check non-TrueType fonts.
|
||||
*/
|
||||
private boolean checkNonTTF = false;
|
||||
|
||||
/**
|
||||
* List of bad fonts found in the system.
|
||||
*/
|
||||
private Vector badFonts = new Vector();
|
||||
|
||||
/**
|
||||
* whether to print warnings messges etc to stdout/err
|
||||
* default is false
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/* Command to use to exec sub-process. */
|
||||
private static String javaCmd = "java";
|
||||
|
||||
static void printlnMessage(String s) {
|
||||
if (verbose) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for timer event.
|
||||
* <BR>
|
||||
* Stops the timer and interrupts the current thread which is
|
||||
* still waiting on I/O from the child process.
|
||||
* <BR><BR>
|
||||
* @param evt timer event
|
||||
*/
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
if (evt.getSource() == timeOne) {
|
||||
timeOne.stop();
|
||||
printlnMessage("Child timed out: killing");
|
||||
childProc.destroy();
|
||||
} else {
|
||||
doExit(); // went on too long (ie timeAll timed out).
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a FontChecker.
|
||||
* <BR>
|
||||
* This method is usually called after an unrecoverable error has
|
||||
* been detected and a child process has either crashed or is in bad
|
||||
* state. The method creates a new child process from
|
||||
* scratch and initializes it's input/output streams.
|
||||
*/
|
||||
public void initialize() {
|
||||
try {
|
||||
if (childProc != null) {
|
||||
childProc.destroy();
|
||||
}
|
||||
String fileSeparator = System.getProperty("file.separator");
|
||||
String javaHome = System.getProperty("java.home");
|
||||
String classPath = System.getProperty("java.class.path");
|
||||
classPath = "\"" + classPath + "\"";
|
||||
String opt = "-cp " + classPath + " -Dsun.java2d.fontpath=\"" +
|
||||
javaHome + fileSeparator + "lib" + fileSeparator + "fonts\"";
|
||||
|
||||
/* command to exec the child process with the same JRE */
|
||||
String cmd =
|
||||
new String(javaHome + fileSeparator + "bin" +
|
||||
fileSeparator + javaCmd +
|
||||
" -XXsuppressExitMessage " + opt +
|
||||
" com.sun.java2d.fontchecker.FontCheckDummy");
|
||||
printlnMessage("cmd="+cmd);
|
||||
childProc = Runtime.getRuntime().exec(cmd);
|
||||
|
||||
} catch (IOException e) {
|
||||
printlnMessage("can't execute child process");
|
||||
System.exit(0);
|
||||
} catch (SecurityException e) {
|
||||
printlnMessage("Error: access denied");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/* initialize input/output streams to/from child process */
|
||||
procPipeOut = new PrintWriter(childProc.getOutputStream());
|
||||
procPipeIn = new BufferedInputStream(childProc.getInputStream());
|
||||
|
||||
try {
|
||||
int code = procPipeIn.read();
|
||||
if (code != CHILD_STARTED_OK) {
|
||||
printlnMessage("bad child process start status="+code);
|
||||
doExit();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
printlnMessage("can't read child process start status unknown");
|
||||
doExit();
|
||||
}
|
||||
}
|
||||
|
||||
private void doExit() {
|
||||
try {
|
||||
if (procPipeOut != null) {
|
||||
/* Tell the child to exit */
|
||||
procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
|
||||
procPipeOut.flush();
|
||||
procPipeOut.close();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to verify integrity of a font specified by a path.
|
||||
* <BR>
|
||||
* This method is used to test whether a font specified by the given
|
||||
* path is valid and does not crash the system.
|
||||
* <BR><BR>
|
||||
* @param fontPath a string representation of font path
|
||||
* to standard out during while this font is tried
|
||||
* @return returns <code>true</code> if font is OK, and
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean tryFont(File fontFile) {
|
||||
int bytesRead = 0;
|
||||
String fontPath = fontFile.getAbsolutePath();
|
||||
|
||||
printlnMessage("Checking font "+fontPath);
|
||||
|
||||
/* store reference to the current thread, so that when the timer
|
||||
* fires it can be interrupted
|
||||
*/
|
||||
currThread = Thread.currentThread();
|
||||
timeOne.restart();
|
||||
|
||||
/* write a string command out to child process
|
||||
* The command is formed by appending whether to test non-TT fonts
|
||||
* and font path to be tested
|
||||
*/
|
||||
String command = Integer.toString(checkNonTTF ? 1 : 0) +
|
||||
fontPath +
|
||||
System.getProperty("line.separator");
|
||||
procPipeOut.write(command);
|
||||
procPipeOut.flush();
|
||||
|
||||
/* check if underlying stream has encountered an error after
|
||||
* command has been issued
|
||||
*/
|
||||
if (procPipeOut.checkError()){
|
||||
printlnMessage("Error: font crashed");
|
||||
initialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* trying reading error code back from child process */
|
||||
try {
|
||||
bytesRead = procPipeIn.read();
|
||||
} catch(InterruptedIOException e) {
|
||||
/* A timeout timer fired before the operation completed */
|
||||
printlnMessage("Error: timeout occured");
|
||||
initialize();
|
||||
return false;
|
||||
} catch(IOException e) {
|
||||
/* there was an error reading from the stream */
|
||||
timeOne.stop();
|
||||
printlnMessage("Error: font crashed");
|
||||
initialize();
|
||||
return false;
|
||||
} catch (Throwable t) {
|
||||
bytesRead = ERR_FONT_READ_EXCPT;
|
||||
} finally {
|
||||
timeOne.stop();
|
||||
}
|
||||
|
||||
if (bytesRead == ERR_FONT_OK) {
|
||||
printlnMessage("Font integrity verified");
|
||||
return true;
|
||||
} else if (bytesRead > 0) {
|
||||
|
||||
switch(bytesRead){
|
||||
case ERR_FONT_NOT_FOUND:
|
||||
printlnMessage("Error: font not found!");
|
||||
break;
|
||||
case ERR_FONT_BAD_FORMAT:
|
||||
printlnMessage("Error: incorrect font format");
|
||||
break;
|
||||
case ERR_FONT_READ_EXCPT:
|
||||
printlnMessage("Error: exception reading font");
|
||||
break;
|
||||
case ERR_FONT_DISPLAY:
|
||||
printlnMessage("Error: can't display characters");
|
||||
break;
|
||||
case ERR_FONT_CRASH:
|
||||
printlnMessage("Error: font crashed");
|
||||
break;
|
||||
default:
|
||||
printlnMessage("Error: invalid error code:"+bytesRead);
|
||||
break;
|
||||
|
||||
}
|
||||
} else if (bytesRead == ERR_FONT_EOS) {
|
||||
printlnMessage("Error: end of stream marker encountered");
|
||||
} else {
|
||||
printlnMessage("Error: invalid error code:"+bytesRead);
|
||||
}
|
||||
|
||||
/* if we still haven't returned from this method, some error
|
||||
* condition has occured and it is safer to re-initialize
|
||||
*/
|
||||
initialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the integrity of all system fonts.
|
||||
* <BR>
|
||||
* This method goes through every font in system's font path and verifies
|
||||
* its integrity via the tryFont method.
|
||||
* <BR><BR>
|
||||
* @param restart <code>true</code> if checking of fonts should continue
|
||||
* after the first bad font is found, and <code>false</code> otherwise
|
||||
* @return returns <code>true</code> if all fonts are valid,
|
||||
* <code>false</code> otherwise
|
||||
* @see #tryFont(String, boolean, boolean)
|
||||
*/
|
||||
public boolean checkFonts(boolean restart) {
|
||||
|
||||
/* file filter to filter out none-truetype font files */
|
||||
FontFileFilter fff = new FontFileFilter(checkNonTTF);
|
||||
boolean checkOk = true;
|
||||
|
||||
/* get platform-independent font path. Note that this bypasses
|
||||
* the normal GraphicsEnvironment initialisation. In conjunction with
|
||||
* the headless setting above, so we want to add
|
||||
* java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
* to trigger a more normal initialisation.
|
||||
*/
|
||||
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
String fontPath = FontManager.getFontPath(true);
|
||||
StringTokenizer st =
|
||||
new StringTokenizer(fontPath,
|
||||
System.getProperty("path.separator"));
|
||||
|
||||
/* some systems may have multiple font paths separated by
|
||||
* platform-dependent characters, so fontPath string needs to be
|
||||
* parsed
|
||||
*/
|
||||
timeOne = new javax.swing.Timer(timeoutOne, this);
|
||||
timeAll = new javax.swing.Timer(timeoutAll, this);
|
||||
timeAll.restart();
|
||||
while (st.hasMoreTokens()) {
|
||||
File fontRoot = new File(st.nextToken());
|
||||
File[] fontFiles = fontRoot.listFiles(fff);
|
||||
|
||||
for (int i = 0; i < fontFiles.length; i++) {
|
||||
/* for each font file that is not a directory and passes
|
||||
* through the font filter run the test
|
||||
*/
|
||||
if (!fontFiles[i].isDirectory() &&
|
||||
!tryFont(fontFiles[i])) {
|
||||
|
||||
checkOk = false;
|
||||
badFonts.add(fontFiles[i].getAbsolutePath());
|
||||
if (!restart) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the child to exit */
|
||||
procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
|
||||
procPipeOut.flush();
|
||||
procPipeOut.close();
|
||||
|
||||
return checkOk;
|
||||
}
|
||||
|
||||
public static void main(String args[]){
|
||||
try {
|
||||
/* Background app. */
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
System.setProperty("sun.java2d.noddraw", "true");
|
||||
|
||||
boolean restart = true;
|
||||
boolean errorFlag = false;
|
||||
|
||||
FontChecker fc = new FontChecker();
|
||||
int arg = 0;
|
||||
|
||||
while (arg < args.length && errorFlag == false) {
|
||||
if (args[arg].equals("-v")) {
|
||||
verbose = true;
|
||||
}
|
||||
else if (args[arg].equals("-w") &&
|
||||
System.getProperty("os.name", "unknown").
|
||||
startsWith("Windows")) {
|
||||
javaCmd = "javaw";
|
||||
}
|
||||
else if (args[arg].equals("-o")) {
|
||||
/* set output file */
|
||||
if (++arg < args.length)
|
||||
fc.outputFile = args[arg];
|
||||
else {
|
||||
/* invalid argument format */
|
||||
printlnMessage("Error: invalid argument format");
|
||||
errorFlag = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* invalid command line argument */
|
||||
printlnMessage("Error: invalid argument value");
|
||||
errorFlag = true;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (errorFlag || fc.outputFile == null) {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
File outfile = new File(fc.outputFile);
|
||||
if (outfile.exists()) {
|
||||
outfile.delete();
|
||||
}
|
||||
|
||||
fc.initialize();
|
||||
|
||||
if (!fc.checkFonts(restart)) {
|
||||
String[] badFonts = (String[])fc.badFonts.toArray(new String[0]);
|
||||
if (badFonts.length > 0) {
|
||||
printlnMessage("Bad Fonts:");
|
||||
try {
|
||||
FileOutputStream fos =
|
||||
new FileOutputStream(fc.outputFile);
|
||||
PrintStream ps = new PrintStream(fos);
|
||||
for (int i = 0; i < badFonts.length; i++) {
|
||||
ps.println(badFonts[i]);
|
||||
printlnMessage(badFonts[i]);
|
||||
}
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printlnMessage("No bad fonts found.");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2004 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package build.tools.fontchecker;
|
||||
|
||||
public interface FontCheckerConstants {
|
||||
|
||||
/* code sent to indicate child process started OK */
|
||||
public static final int CHILD_STARTED_OK = 100;
|
||||
|
||||
/* error codes returned from child process */
|
||||
public static final int ERR_FONT_OK = 65;
|
||||
public static final int ERR_FONT_NOT_FOUND = 60;
|
||||
public static final int ERR_FONT_BAD_FORMAT = 61;
|
||||
public static final int ERR_FONT_READ_EXCPT = 62;
|
||||
public static final int ERR_FONT_DISPLAY = 64;
|
||||
public static final int ERR_FONT_EOS = -1;
|
||||
/* nl char sent after child crashes */
|
||||
public static final int ERR_FONT_CRASH = 10;
|
||||
|
||||
/* 0 and 1 are reserved, and commands can only be a single digit integer */
|
||||
public static final int EXITCOMMAND = 2;
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2003 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* <PRE>
|
||||
* This class filters TrueType font files from other file
|
||||
* found in the font path.
|
||||
*
|
||||
* </PRE>
|
||||
*
|
||||
* @author Ilya Bagrak
|
||||
*/
|
||||
|
||||
package build.tools.fontchecker;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
|
||||
public class FontFileFilter implements java.io.FileFilter, FontCheckerConstants {
|
||||
|
||||
/**
|
||||
* Boolean flag indicating whether this filter filters out
|
||||
* non-TrueType fonts.
|
||||
*/
|
||||
private boolean checkNonTTF;
|
||||
|
||||
public FontFileFilter() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public FontFileFilter(boolean checkNonTTF) {
|
||||
super();
|
||||
this.checkNonTTF = checkNonTTF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file is accepted by this filter.
|
||||
* <BR>
|
||||
* This method checks whehter a file is accepted by this filter.
|
||||
* This filter is made to accept all the file whose extension is
|
||||
* either .ttf or .TTF. These files are assumed to be TrueType fonts.
|
||||
* <BR><BR>
|
||||
* @return returns a boolean value indicating whether or not a file is
|
||||
* accepted
|
||||
*/
|
||||
public boolean accept(File pathname) {
|
||||
|
||||
String name = pathname.getName();
|
||||
return (name.endsWith(".ttf") ||
|
||||
name.endsWith(".TTF") ||
|
||||
name.endsWith(".ttc") ||
|
||||
name.endsWith(".TTC")) ||
|
||||
(name.endsWith(".pfb") ||
|
||||
name.endsWith(".PFB") ||
|
||||
name.endsWith(".pfa") ||
|
||||
name.endsWith(".PFA") &&
|
||||
checkNonTTF == true);
|
||||
}
|
||||
|
||||
public static int getFontType(String filename) {
|
||||
if (filename.endsWith(".ttf") ||
|
||||
filename.endsWith(".TTF") ||
|
||||
filename.endsWith(".ttc") ||
|
||||
filename.endsWith(".TTC"))
|
||||
return Font.TRUETYPE_FONT;
|
||||
else if (filename.endsWith(".pfb") ||
|
||||
filename.endsWith(".PFB") ||
|
||||
filename.endsWith(".pfa") ||
|
||||
filename.endsWith(".PFA"))
|
||||
return Font.TYPE1_FONT;
|
||||
else
|
||||
return 999;
|
||||
}
|
||||
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2003 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
Instructions for running FontChecker
|
||||
------------------------------------
|
||||
|
||||
FontChecker is a program designed to identify fonts that may cause JRE
|
||||
crashes. Such fonts may be corrupted files, or badly constructed fonts.
|
||||
Some crashes may also be due to bugs in the JRE's font code.
|
||||
This test is designed to run quickly and silently as part of the JRE
|
||||
installation process. It will only benefit users who install the JRE
|
||||
via that mechanism. It cannot guarantee to identify all "bad fonts" because
|
||||
the tests are minimal. Nor can it prevent problems due to fonts installed
|
||||
subsequently to the JRE's installation. However it does ensure that the
|
||||
vast majority of problem fonts are identified. This is important
|
||||
"RAS" functionality. It is targeted at the consumer/plugin market where
|
||||
there is substantial likelihood of end-users having installed software
|
||||
packages which may be delivered with fonts that are not up to commercial
|
||||
standards.
|
||||
|
||||
The test is designed to be "fail safe". If the program fails to run
|
||||
properly it has no impact on the installer or on JRE execution.
|
||||
Thus there is no need to monitor successful execution of the test.
|
||||
|
||||
The test is not a new "tool" in the sense of "javah" etc.
|
||||
The test is not designed to be user executable or visible, and should
|
||||
be unpacked by the installer into a temporary location, and executed
|
||||
once the rest of the JRE is installed (ie as a postinstall step), and
|
||||
can then be deleted from the temporary location once installation is
|
||||
complete. Not deleting the jar file before execution is complete is
|
||||
probably the sole reason that the installer may want to wait for
|
||||
the program to complete.
|
||||
|
||||
The FontChecker application can be run directly from the jar
|
||||
file with this command:
|
||||
%java -jar fontchecker.jar -o <file>
|
||||
|
||||
The output file is a required parameter in this version of the application.
|
||||
The JRE installer should use the above form, and use it to create an
|
||||
output file which must be named "badfonts.txt" and be placed into
|
||||
the JRE's lib\fonts directory eg:-
|
||||
|
||||
java -jar fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
|
||||
|
||||
Note the lower case "badfonts.txt", and the string quotes because of the spaces
|
||||
in the path name.
|
||||
The location given here is an example and needs to be calculated at install
|
||||
time as $JREHOME\lib\fonts\badfonts.txt
|
||||
The location and name are important, because the JRE at runtime will
|
||||
look for this exactly located name and file.
|
||||
This location is private to that JRE instance. It will not affect
|
||||
any other JRE installed on the system.
|
||||
|
||||
If running from a different directory than that containing the jar file,
|
||||
use the form containing the full path to the jar file, eg :
|
||||
|
||||
java -jar C:\fc\fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
|
||||
|
||||
FontChecker application accepts following command line flags.
|
||||
usage: java -jar fontchecker.jar -o outputfile
|
||||
-v
|
||||
|
||||
-o is the name of the file to contains canonical path names of
|
||||
bad fonts that are identified. This file is not created if
|
||||
no bad fonts are found.
|
||||
|
||||
-v verbose mode: print progress/warning messages. Not recommended
|
||||
for installer use.
|
||||
|
||||
-w if running on Windows, use "javaw" to exec the sub-process.
|
@ -256,9 +256,8 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements L
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
rangeCheckForAdd(index);
|
||||
boolean modified = false;
|
||||
Iterator<? extends E> e = c.iterator();
|
||||
while (e.hasNext()) {
|
||||
add(index++, e.next());
|
||||
for (E e : c) {
|
||||
add(index++, e);
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
|
@ -183,11 +183,9 @@ public abstract class AbstractQueue<E>
|
||||
if (c == this)
|
||||
throw new IllegalArgumentException();
|
||||
boolean modified = false;
|
||||
Iterator<? extends E> e = c.iterator();
|
||||
while (e.hasNext()) {
|
||||
if (add(e.next()))
|
||||
for (E e : c)
|
||||
if (add(e))
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
@ -448,10 +448,8 @@ public class HashMap<K,V>
|
||||
}
|
||||
|
||||
private void putAllForCreate(Map<? extends K, ? extends V> m) {
|
||||
for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
|
||||
Map.Entry<? extends K, ? extends V> e = i.next();
|
||||
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
|
||||
putForCreate(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -536,10 +534,8 @@ public class HashMap<K,V>
|
||||
resize(newCapacity);
|
||||
}
|
||||
|
||||
for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
|
||||
Map.Entry<? extends K, ? extends V> e = i.next();
|
||||
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
|
||||
put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -280,8 +280,8 @@ public class HashSet<E>
|
||||
s.writeInt(map.size());
|
||||
|
||||
// Write out all elements in the proper order.
|
||||
for (Iterator i=map.keySet().iterator(); i.hasNext(); )
|
||||
s.writeObject(i.next());
|
||||
for (E e : map.keySet())
|
||||
s.writeObject(e);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,6 +50,18 @@ import sun.misc.Unsafe;
|
||||
* <p>
|
||||
* Many applications will find the method {@link Math#random} simpler to use.
|
||||
*
|
||||
* <p>Instances of {@code java.util.Random} are threadsafe.
|
||||
* However, the concurrent use of the same {@code java.util.Random}
|
||||
* instance across threads may encounter contention and consequent
|
||||
* poor performance. Consider instead using
|
||||
* {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
|
||||
* designs.
|
||||
*
|
||||
* <p>Instances of {@code java.util.Random} are not cryptographically
|
||||
* secure. Consider instead using {@link java.security.SecureRandom} to
|
||||
* get a cryptographically secure pseudo-random number generator for use
|
||||
* by security-sensitive applications.
|
||||
*
|
||||
* @author Frank Yellin
|
||||
* @since 1.0
|
||||
*/
|
||||
|
@ -218,8 +218,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
|
||||
if (capacity < c.size())
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
|
||||
add(it.next());
|
||||
for (E e : c)
|
||||
add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -250,8 +250,8 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
* of its elements are null
|
||||
*/
|
||||
public ConcurrentLinkedQueue(Collection<? extends E> c) {
|
||||
for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
|
||||
add(it.next());
|
||||
for (E e : c)
|
||||
add(e);
|
||||
}
|
||||
|
||||
// Have to override just to update the javadoc
|
||||
|
@ -895,7 +895,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
if (n != null) {
|
||||
Node<K,V> f = n.next;
|
||||
if (n != b.next) // inconsistent read
|
||||
break;;
|
||||
break;
|
||||
Object v = n.value;
|
||||
if (v == null) { // n is deleted
|
||||
n.helpDelete(b, f);
|
||||
|
@ -148,7 +148,8 @@ import java.util.concurrent.atomic.*;
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to calling
|
||||
* <p>Memory consistency effects: Until the count reaches
|
||||
* zero, actions in a thread prior to calling
|
||||
* {@code countDown()}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions following a successful return from a corresponding
|
||||
|
@ -332,8 +332,8 @@ public interface ExecutorService extends Executor {
|
||||
* @param tasks the collection of tasks
|
||||
* @return the result returned by one of the tasks
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws NullPointerException if tasks or any of its elements
|
||||
* are <tt>null</tt>
|
||||
* @throws NullPointerException if tasks or any element task
|
||||
* subject to execution is <tt>null</tt>
|
||||
* @throws IllegalArgumentException if tasks is empty
|
||||
* @throws ExecutionException if no task successfully completes
|
||||
* @throws RejectedExecutionException if tasks cannot be scheduled
|
||||
@ -356,8 +356,8 @@ public interface ExecutorService extends Executor {
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @return the result returned by one of the tasks.
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws NullPointerException if tasks, any of its elements, or
|
||||
* unit are <tt>null</tt>
|
||||
* @throws NullPointerException if tasks, or unit, or any element
|
||||
* task subject to execution is <tt>null</tt>
|
||||
* @throws TimeoutException if the given timeout elapses before
|
||||
* any task successfully completes
|
||||
* @throws ExecutionException if no task successfully completes
|
||||
|
1988
jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
Normal file
1988
jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
Normal file
File diff suppressed because it is too large
Load Diff
1292
jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
Normal file
1292
jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,827 @@
|
||||
/*
|
||||
* 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/licenses/publicdomain
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A thread managed by a {@link ForkJoinPool}. This class is
|
||||
* subclassable solely for the sake of adding functionality -- there
|
||||
* are no overridable methods dealing with scheduling or execution.
|
||||
* However, you can override initialization and termination methods
|
||||
* surrounding the main task processing loop. If you do create such a
|
||||
* subclass, you will also need to supply a custom {@link
|
||||
* ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code
|
||||
* ForkJoinPool}.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class ForkJoinWorkerThread extends Thread {
|
||||
/*
|
||||
* Algorithm overview:
|
||||
*
|
||||
* 1. Work-Stealing: Work-stealing queues are special forms of
|
||||
* Deques that support only three of the four possible
|
||||
* end-operations -- push, pop, and deq (aka steal), and only do
|
||||
* so under the constraints that push and pop are called only from
|
||||
* the owning thread, while deq may be called from other threads.
|
||||
* (If you are unfamiliar with them, you probably want to read
|
||||
* Herlihy and Shavit's book "The Art of Multiprocessor
|
||||
* programming", chapter 16 describing these in more detail before
|
||||
* proceeding.) The main work-stealing queue design is roughly
|
||||
* similar to "Dynamic Circular Work-Stealing Deque" by David
|
||||
* Chase and Yossi Lev, SPAA 2005
|
||||
* (http://research.sun.com/scalable/pubs/index.html). The main
|
||||
* difference ultimately stems from gc requirements that we null
|
||||
* out taken slots as soon as we can, to maintain as small a
|
||||
* footprint as possible even in programs generating huge numbers
|
||||
* of tasks. To accomplish this, we shift the CAS arbitrating pop
|
||||
* vs deq (steal) from being on the indices ("base" and "sp") to
|
||||
* the slots themselves (mainly via method "casSlotNull()"). So,
|
||||
* both a successful pop and deq mainly entail CAS'ing a non-null
|
||||
* slot to null. Because we rely on CASes of references, we do
|
||||
* not need tag bits on base or sp. They are simple ints as used
|
||||
* in any circular array-based queue (see for example ArrayDeque).
|
||||
* Updates to the indices must still be ordered in a way that
|
||||
* guarantees that (sp - base) > 0 means the queue is empty, but
|
||||
* otherwise may err on the side of possibly making the queue
|
||||
* appear nonempty when a push, pop, or deq have not fully
|
||||
* committed. Note that this means that the deq operation,
|
||||
* considered individually, is not wait-free. One thief cannot
|
||||
* successfully continue until another in-progress one (or, if
|
||||
* previously empty, a push) completes. However, in the
|
||||
* aggregate, we ensure at least probabilistic
|
||||
* non-blockingness. If an attempted steal fails, a thief always
|
||||
* chooses a different random victim target to try next. So, in
|
||||
* order for one thief to progress, it suffices for any
|
||||
* in-progress deq or new push on any empty queue to complete. One
|
||||
* reason this works well here is that apparently-nonempty often
|
||||
* means soon-to-be-stealable, which gives threads a chance to
|
||||
* activate if necessary before stealing (see below).
|
||||
*
|
||||
* This approach also enables support for "async mode" where local
|
||||
* task processing is in FIFO, not LIFO order; simply by using a
|
||||
* version of deq rather than pop when locallyFifo is true (as set
|
||||
* by the ForkJoinPool). This allows use in message-passing
|
||||
* frameworks in which tasks are never joined.
|
||||
*
|
||||
* Efficient implementation of this approach currently relies on
|
||||
* an uncomfortable amount of "Unsafe" mechanics. To maintain
|
||||
* correct orderings, reads and writes of variable base require
|
||||
* volatile ordering. Variable sp does not require volatile write
|
||||
* but needs cheaper store-ordering on writes. Because they are
|
||||
* protected by volatile base reads, reads of the queue array and
|
||||
* its slots do not need volatile load semantics, but writes (in
|
||||
* push) require store order and CASes (in pop and deq) require
|
||||
* (volatile) CAS semantics. (See "Idempotent work stealing" by
|
||||
* Michael, Saraswat, and Vechev, PPoPP 2009
|
||||
* http://portal.acm.org/citation.cfm?id=1504186 for an algorithm
|
||||
* with similar properties, but without support for nulling
|
||||
* slots.) Since these combinations aren't supported using
|
||||
* ordinary volatiles, the only way to accomplish these
|
||||
* efficiently is to use direct Unsafe calls. (Using external
|
||||
* AtomicIntegers and AtomicReferenceArrays for the indices and
|
||||
* array is significantly slower because of memory locality and
|
||||
* indirection effects.)
|
||||
*
|
||||
* Further, performance on most platforms is very sensitive to
|
||||
* placement and sizing of the (resizable) queue array. Even
|
||||
* though these queues don't usually become all that big, the
|
||||
* initial size must be large enough to counteract cache
|
||||
* contention effects across multiple queues (especially in the
|
||||
* presence of GC cardmarking). Also, to improve thread-locality,
|
||||
* queues are currently initialized immediately after the thread
|
||||
* gets the initial signal to start processing tasks. However,
|
||||
* all queue-related methods except pushTask are written in a way
|
||||
* that allows them to instead be lazily allocated and/or disposed
|
||||
* of when empty. All together, these low-level implementation
|
||||
* choices produce as much as a factor of 4 performance
|
||||
* improvement compared to naive implementations, and enable the
|
||||
* processing of billions of tasks per second, sometimes at the
|
||||
* expense of ugliness.
|
||||
*
|
||||
* 2. Run control: The primary run control is based on a global
|
||||
* counter (activeCount) held by the pool. It uses an algorithm
|
||||
* similar to that in Herlihy and Shavit section 17.6 to cause
|
||||
* threads to eventually block when all threads declare they are
|
||||
* inactive. For this to work, threads must be declared active
|
||||
* when executing tasks, and before stealing a task. They must be
|
||||
* inactive before blocking on the Pool Barrier (awaiting a new
|
||||
* submission or other Pool event). In between, there is some free
|
||||
* play which we take advantage of to avoid contention and rapid
|
||||
* flickering of the global activeCount: If inactive, we activate
|
||||
* only if a victim queue appears to be nonempty (see above).
|
||||
* Similarly, a thread tries to inactivate only after a full scan
|
||||
* of other threads. The net effect is that contention on
|
||||
* activeCount is rarely a measurable performance issue. (There
|
||||
* are also a few other cases where we scan for work rather than
|
||||
* retry/block upon contention.)
|
||||
*
|
||||
* 3. Selection control. We maintain policy of always choosing to
|
||||
* run local tasks rather than stealing, and always trying to
|
||||
* steal tasks before trying to run a new submission. All steals
|
||||
* are currently performed in randomly-chosen deq-order. It may be
|
||||
* worthwhile to bias these with locality / anti-locality
|
||||
* information, but doing this well probably requires more
|
||||
* lower-level information from JVMs than currently provided.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Capacity of work-stealing queue array upon initialization.
|
||||
* Must be a power of two. Initial size must be at least 2, but is
|
||||
* padded to minimize cache effects.
|
||||
*/
|
||||
private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
|
||||
|
||||
/**
|
||||
* Maximum work-stealing queue array size. Must be less than or
|
||||
* equal to 1 << 28 to ensure lack of index wraparound. (This
|
||||
* is less than usual bounds, because we need leftshift by 3
|
||||
* to be in int range).
|
||||
*/
|
||||
private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 28;
|
||||
|
||||
/**
|
||||
* The pool this thread works in. Accessed directly by ForkJoinTask.
|
||||
*/
|
||||
final ForkJoinPool pool;
|
||||
|
||||
/**
|
||||
* The work-stealing queue array. Size must be a power of two.
|
||||
* Initialized when thread starts, to improve memory locality.
|
||||
*/
|
||||
private ForkJoinTask<?>[] queue;
|
||||
|
||||
/**
|
||||
* Index (mod queue.length) of next queue slot to push to or pop
|
||||
* from. It is written only by owner thread, via ordered store.
|
||||
* Both sp and base are allowed to wrap around on overflow, but
|
||||
* (sp - base) still estimates size.
|
||||
*/
|
||||
private volatile int sp;
|
||||
|
||||
/**
|
||||
* Index (mod queue.length) of least valid queue slot, which is
|
||||
* always the next position to steal from if nonempty.
|
||||
*/
|
||||
private volatile int base;
|
||||
|
||||
/**
|
||||
* Activity status. When true, this worker is considered active.
|
||||
* Must be false upon construction. It must be true when executing
|
||||
* tasks, and BEFORE stealing a task. It must be false before
|
||||
* calling pool.sync.
|
||||
*/
|
||||
private boolean active;
|
||||
|
||||
/**
|
||||
* Run state of this worker. Supports simple versions of the usual
|
||||
* shutdown/shutdownNow control.
|
||||
*/
|
||||
private volatile int runState;
|
||||
|
||||
/**
|
||||
* Seed for random number generator for choosing steal victims.
|
||||
* Uses Marsaglia xorshift. Must be nonzero upon initialization.
|
||||
*/
|
||||
private int seed;
|
||||
|
||||
/**
|
||||
* Number of steals, transferred to pool when idle
|
||||
*/
|
||||
private int stealCount;
|
||||
|
||||
/**
|
||||
* Index of this worker in pool array. Set once by pool before
|
||||
* running, and accessed directly by pool during cleanup etc.
|
||||
*/
|
||||
int poolIndex;
|
||||
|
||||
/**
|
||||
* The last barrier event waited for. Accessed in pool callback
|
||||
* methods, but only by current thread.
|
||||
*/
|
||||
long lastEventCount;
|
||||
|
||||
/**
|
||||
* True if use local fifo, not default lifo, for local polling
|
||||
*/
|
||||
private boolean locallyFifo;
|
||||
|
||||
/**
|
||||
* Creates a ForkJoinWorkerThread operating in the given pool.
|
||||
*
|
||||
* @param pool the pool this thread works in
|
||||
* @throws NullPointerException if pool is null
|
||||
*/
|
||||
protected ForkJoinWorkerThread(ForkJoinPool pool) {
|
||||
if (pool == null) throw new NullPointerException();
|
||||
this.pool = pool;
|
||||
// Note: poolIndex is set by pool during construction
|
||||
// Remaining initialization is deferred to onStart
|
||||
}
|
||||
|
||||
// Public access methods
|
||||
|
||||
/**
|
||||
* Returns the pool hosting this thread.
|
||||
*
|
||||
* @return the pool
|
||||
*/
|
||||
public ForkJoinPool getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index number of this thread in its pool. The
|
||||
* returned value ranges from zero to the maximum number of
|
||||
* threads (minus one) that have ever been created in the pool.
|
||||
* This method may be useful for applications that track status or
|
||||
* collect results per-worker rather than per-task.
|
||||
*
|
||||
* @return the index number
|
||||
*/
|
||||
public int getPoolIndex() {
|
||||
return poolIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes local first-in-first-out scheduling mode for forked
|
||||
* tasks that are never joined.
|
||||
*
|
||||
* @param async if true, use locally FIFO scheduling
|
||||
*/
|
||||
void setAsyncMode(boolean async) {
|
||||
locallyFifo = async;
|
||||
}
|
||||
|
||||
// Runstate management
|
||||
|
||||
// Runstate values. Order matters
|
||||
private static final int RUNNING = 0;
|
||||
private static final int SHUTDOWN = 1;
|
||||
private static final int TERMINATING = 2;
|
||||
private static final int TERMINATED = 3;
|
||||
|
||||
final boolean isShutdown() { return runState >= SHUTDOWN; }
|
||||
final boolean isTerminating() { return runState >= TERMINATING; }
|
||||
final boolean isTerminated() { return runState == TERMINATED; }
|
||||
final boolean shutdown() { return transitionRunStateTo(SHUTDOWN); }
|
||||
final boolean shutdownNow() { return transitionRunStateTo(TERMINATING); }
|
||||
|
||||
/**
|
||||
* Transitions to at least the given state.
|
||||
*
|
||||
* @return {@code true} if not already at least at given state
|
||||
*/
|
||||
private boolean transitionRunStateTo(int state) {
|
||||
for (;;) {
|
||||
int s = runState;
|
||||
if (s >= state)
|
||||
return false;
|
||||
if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, state))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to set status to active; fails on contention.
|
||||
*/
|
||||
private boolean tryActivate() {
|
||||
if (!active) {
|
||||
if (!pool.tryIncrementActiveCount())
|
||||
return false;
|
||||
active = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to set status to inactive; fails on contention.
|
||||
*/
|
||||
private boolean tryInactivate() {
|
||||
if (active) {
|
||||
if (!pool.tryDecrementActiveCount())
|
||||
return false;
|
||||
active = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes next value for random victim probe. Scans don't
|
||||
* require a very high quality generator, but also not a crummy
|
||||
* one. Marsaglia xor-shift is cheap and works well.
|
||||
*/
|
||||
private static int xorShift(int r) {
|
||||
r ^= (r << 13);
|
||||
r ^= (r >>> 17);
|
||||
return r ^ (r << 5);
|
||||
}
|
||||
|
||||
// Lifecycle methods
|
||||
|
||||
/**
|
||||
* This method is required to be public, but should never be
|
||||
* called explicitly. It performs the main run loop to execute
|
||||
* ForkJoinTasks.
|
||||
*/
|
||||
public void run() {
|
||||
Throwable exception = null;
|
||||
try {
|
||||
onStart();
|
||||
pool.sync(this); // await first pool event
|
||||
mainLoop();
|
||||
} catch (Throwable ex) {
|
||||
exception = ex;
|
||||
} finally {
|
||||
onTermination(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes tasks until shut down.
|
||||
*/
|
||||
private void mainLoop() {
|
||||
while (!isShutdown()) {
|
||||
ForkJoinTask<?> t = pollTask();
|
||||
if (t != null || (t = pollSubmission()) != null)
|
||||
t.quietlyExec();
|
||||
else if (tryInactivate())
|
||||
pool.sync(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes internal state after construction but before
|
||||
* processing any tasks. If you override this method, you must
|
||||
* invoke super.onStart() at the beginning of the method.
|
||||
* Initialization requires care: Most fields must have legal
|
||||
* default values, to ensure that attempted accesses from other
|
||||
* threads work correctly even before this thread starts
|
||||
* processing tasks.
|
||||
*/
|
||||
protected void onStart() {
|
||||
// Allocate while starting to improve chances of thread-local
|
||||
// isolation
|
||||
queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
|
||||
// Initial value of seed need not be especially random but
|
||||
// should differ across workers and must be nonzero
|
||||
int p = poolIndex + 1;
|
||||
seed = p + (p << 8) + (p << 16) + (p << 24); // spread bits
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs cleanup associated with termination of this worker
|
||||
* thread. If you override this method, you must invoke
|
||||
* {@code super.onTermination} at the end of the overridden method.
|
||||
*
|
||||
* @param exception the exception causing this thread to abort due
|
||||
* to an unrecoverable error, or {@code null} if completed normally
|
||||
*/
|
||||
protected void onTermination(Throwable exception) {
|
||||
// Execute remaining local tasks unless aborting or terminating
|
||||
while (exception == null && pool.isProcessingTasks() && base != sp) {
|
||||
try {
|
||||
ForkJoinTask<?> t = popTask();
|
||||
if (t != null)
|
||||
t.quietlyExec();
|
||||
} catch (Throwable ex) {
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
// Cancel other tasks, transition status, notify pool, and
|
||||
// propagate exception to uncaught exception handler
|
||||
try {
|
||||
do {} while (!tryInactivate()); // ensure inactive
|
||||
cancelTasks();
|
||||
runState = TERMINATED;
|
||||
pool.workerTerminated(this);
|
||||
} catch (Throwable ex) { // Shouldn't ever happen
|
||||
if (exception == null) // but if so, at least rethrown
|
||||
exception = ex;
|
||||
} finally {
|
||||
if (exception != null)
|
||||
ForkJoinTask.rethrowException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
// Intrinsics-based support for queue operations.
|
||||
|
||||
private static long slotOffset(int i) {
|
||||
return ((long) i << qShift) + qBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds in store-order the given task at given slot of q to null.
|
||||
* Caller must ensure q is non-null and index is in range.
|
||||
*/
|
||||
private static void setSlot(ForkJoinTask<?>[] q, int i,
|
||||
ForkJoinTask<?> t) {
|
||||
UNSAFE.putOrderedObject(q, slotOffset(i), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* CAS given slot of q to null. Caller must ensure q is non-null
|
||||
* and index is in range.
|
||||
*/
|
||||
private static boolean casSlotNull(ForkJoinTask<?>[] q, int i,
|
||||
ForkJoinTask<?> t) {
|
||||
return UNSAFE.compareAndSwapObject(q, slotOffset(i), t, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets sp in store-order.
|
||||
*/
|
||||
private void storeSp(int s) {
|
||||
UNSAFE.putOrderedInt(this, spOffset, s);
|
||||
}
|
||||
|
||||
// Main queue methods
|
||||
|
||||
/**
|
||||
* Pushes a task. Called only by current thread.
|
||||
*
|
||||
* @param t the task. Caller must ensure non-null.
|
||||
*/
|
||||
final void pushTask(ForkJoinTask<?> t) {
|
||||
ForkJoinTask<?>[] q = queue;
|
||||
int mask = q.length - 1;
|
||||
int s = sp;
|
||||
setSlot(q, s & mask, t);
|
||||
storeSp(++s);
|
||||
if ((s -= base) == 1)
|
||||
pool.signalWork();
|
||||
else if (s >= mask)
|
||||
growQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to take a task from the base of the queue, failing if
|
||||
* either empty or contended.
|
||||
*
|
||||
* @return a task, or null if none or contended
|
||||
*/
|
||||
final ForkJoinTask<?> deqTask() {
|
||||
ForkJoinTask<?> t;
|
||||
ForkJoinTask<?>[] q;
|
||||
int i;
|
||||
int b;
|
||||
if (sp != (b = base) &&
|
||||
(q = queue) != null && // must read q after b
|
||||
(t = q[i = (q.length - 1) & b]) != null &&
|
||||
casSlotNull(q, i, t)) {
|
||||
base = b + 1;
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to take a task from the base of own queue, activating if
|
||||
* necessary, failing only if empty. Called only by current thread.
|
||||
*
|
||||
* @return a task, or null if none
|
||||
*/
|
||||
final ForkJoinTask<?> locallyDeqTask() {
|
||||
int b;
|
||||
while (sp != (b = base)) {
|
||||
if (tryActivate()) {
|
||||
ForkJoinTask<?>[] q = queue;
|
||||
int i = (q.length - 1) & b;
|
||||
ForkJoinTask<?> t = q[i];
|
||||
if (t != null && casSlotNull(q, i, t)) {
|
||||
base = b + 1;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a popped task, or null if empty. Ensures active status
|
||||
* if non-null. Called only by current thread.
|
||||
*/
|
||||
final ForkJoinTask<?> popTask() {
|
||||
int s = sp;
|
||||
while (s != base) {
|
||||
if (tryActivate()) {
|
||||
ForkJoinTask<?>[] q = queue;
|
||||
int mask = q.length - 1;
|
||||
int i = (s - 1) & mask;
|
||||
ForkJoinTask<?> t = q[i];
|
||||
if (t == null || !casSlotNull(q, i, t))
|
||||
break;
|
||||
storeSp(s - 1);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized version of popTask to pop only if
|
||||
* topmost element is the given task. Called only
|
||||
* by current thread while active.
|
||||
*
|
||||
* @param t the task. Caller must ensure non-null.
|
||||
*/
|
||||
final boolean unpushTask(ForkJoinTask<?> t) {
|
||||
ForkJoinTask<?>[] q = queue;
|
||||
int mask = q.length - 1;
|
||||
int s = sp - 1;
|
||||
if (casSlotNull(q, s & mask, t)) {
|
||||
storeSp(s);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next task or null if empty or contended
|
||||
*/
|
||||
final ForkJoinTask<?> peekTask() {
|
||||
ForkJoinTask<?>[] q = queue;
|
||||
if (q == null)
|
||||
return null;
|
||||
int mask = q.length - 1;
|
||||
int i = locallyFifo ? base : (sp - 1);
|
||||
return q[i & mask];
|
||||
}
|
||||
|
||||
/**
|
||||
* Doubles queue array size. Transfers elements by emulating
|
||||
* steals (deqs) from old array and placing, oldest first, into
|
||||
* new array.
|
||||
*/
|
||||
private void growQueue() {
|
||||
ForkJoinTask<?>[] oldQ = queue;
|
||||
int oldSize = oldQ.length;
|
||||
int newSize = oldSize << 1;
|
||||
if (newSize > MAXIMUM_QUEUE_CAPACITY)
|
||||
throw new RejectedExecutionException("Queue capacity exceeded");
|
||||
ForkJoinTask<?>[] newQ = queue = new ForkJoinTask<?>[newSize];
|
||||
|
||||
int b = base;
|
||||
int bf = b + oldSize;
|
||||
int oldMask = oldSize - 1;
|
||||
int newMask = newSize - 1;
|
||||
do {
|
||||
int oldIndex = b & oldMask;
|
||||
ForkJoinTask<?> t = oldQ[oldIndex];
|
||||
if (t != null && !casSlotNull(oldQ, oldIndex, t))
|
||||
t = null;
|
||||
setSlot(newQ, b & newMask, t);
|
||||
} while (++b != bf);
|
||||
pool.signalWork();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to steal a task from another worker. Starts at a random
|
||||
* index of workers array, and probes workers until finding one
|
||||
* with non-empty queue or finding that all are empty. It
|
||||
* randomly selects the first n probes. If these are empty, it
|
||||
* resorts to a full circular traversal, which is necessary to
|
||||
* accurately set active status by caller. Also restarts if pool
|
||||
* events occurred since last scan, which forces refresh of
|
||||
* workers array, in case barrier was associated with resize.
|
||||
*
|
||||
* This method must be both fast and quiet -- usually avoiding
|
||||
* memory accesses that could disrupt cache sharing etc other than
|
||||
* those needed to check for and take tasks. This accounts for,
|
||||
* among other things, updating random seed in place without
|
||||
* storing it until exit.
|
||||
*
|
||||
* @return a task, or null if none found
|
||||
*/
|
||||
private ForkJoinTask<?> scan() {
|
||||
ForkJoinTask<?> t = null;
|
||||
int r = seed; // extract once to keep scan quiet
|
||||
ForkJoinWorkerThread[] ws; // refreshed on outer loop
|
||||
int mask; // must be power 2 minus 1 and > 0
|
||||
outer:do {
|
||||
if ((ws = pool.workers) != null && (mask = ws.length - 1) > 0) {
|
||||
int idx = r;
|
||||
int probes = ~mask; // use random index while negative
|
||||
for (;;) {
|
||||
r = xorShift(r); // update random seed
|
||||
ForkJoinWorkerThread v = ws[mask & idx];
|
||||
if (v == null || v.sp == v.base) {
|
||||
if (probes <= mask)
|
||||
idx = (probes++ < 0) ? r : (idx + 1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if (!tryActivate() || (t = v.deqTask()) == null)
|
||||
continue outer; // restart on contention
|
||||
else
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
} while (pool.hasNewSyncEvent(this)); // retry on pool events
|
||||
seed = r;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and removes a local or stolen task.
|
||||
*
|
||||
* @return a task, if available
|
||||
*/
|
||||
final ForkJoinTask<?> pollTask() {
|
||||
ForkJoinTask<?> t = locallyFifo ? locallyDeqTask() : popTask();
|
||||
if (t == null && (t = scan()) != null)
|
||||
++stealCount;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a local task.
|
||||
*
|
||||
* @return a task, if available
|
||||
*/
|
||||
final ForkJoinTask<?> pollLocalTask() {
|
||||
return locallyFifo ? locallyDeqTask() : popTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pool submission, if one exists, activating first.
|
||||
*
|
||||
* @return a submission, if available
|
||||
*/
|
||||
private ForkJoinTask<?> pollSubmission() {
|
||||
ForkJoinPool p = pool;
|
||||
while (p.hasQueuedSubmissions()) {
|
||||
ForkJoinTask<?> t;
|
||||
if (tryActivate() && (t = p.pollSubmission()) != null)
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Methods accessed only by Pool
|
||||
|
||||
/**
|
||||
* Removes and cancels all tasks in queue. Can be called from any
|
||||
* thread.
|
||||
*/
|
||||
final void cancelTasks() {
|
||||
ForkJoinTask<?> t;
|
||||
while (base != sp && (t = deqTask()) != null)
|
||||
t.cancelIgnoringExceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drains tasks to given collection c.
|
||||
*
|
||||
* @return the number of tasks drained
|
||||
*/
|
||||
final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
|
||||
int n = 0;
|
||||
ForkJoinTask<?> t;
|
||||
while (base != sp && (t = deqTask()) != null) {
|
||||
c.add(t);
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and clears steal count for accumulation by pool. Called
|
||||
* only when known to be idle (in pool.sync and termination).
|
||||
*/
|
||||
final int getAndClearStealCount() {
|
||||
int sc = stealCount;
|
||||
stealCount = 0;
|
||||
return sc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if at least one worker in the given array
|
||||
* appears to have at least one queued task.
|
||||
*
|
||||
* @param ws array of workers
|
||||
*/
|
||||
static boolean hasQueuedTasks(ForkJoinWorkerThread[] ws) {
|
||||
if (ws != null) {
|
||||
int len = ws.length;
|
||||
for (int j = 0; j < 2; ++j) { // need two passes for clean sweep
|
||||
for (int i = 0; i < len; ++i) {
|
||||
ForkJoinWorkerThread w = ws[i];
|
||||
if (w != null && w.sp != w.base)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Support methods for ForkJoinTask
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of tasks in the queue.
|
||||
*/
|
||||
final int getQueueSize() {
|
||||
// suppress momentarily negative values
|
||||
return Math.max(0, sp - base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of tasks, offset by a
|
||||
* function of number of idle workers.
|
||||
*/
|
||||
final int getEstimatedSurplusTaskCount() {
|
||||
// The halving approximates weighting idle vs non-idle workers
|
||||
return (sp - base) - (pool.getIdleThreadCount() >>> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans, returning early if joinMe done.
|
||||
*/
|
||||
final ForkJoinTask<?> scanWhileJoining(ForkJoinTask<?> joinMe) {
|
||||
ForkJoinTask<?> t = pollTask();
|
||||
if (t != null && joinMe.status < 0 && sp == base) {
|
||||
pushTask(t); // unsteal if done and this task would be stealable
|
||||
t = null;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks until {@code pool.isQuiescent()}.
|
||||
*/
|
||||
final void helpQuiescePool() {
|
||||
for (;;) {
|
||||
ForkJoinTask<?> t = pollTask();
|
||||
if (t != null)
|
||||
t.quietlyExec();
|
||||
else if (tryInactivate() && pool.isQuiescent())
|
||||
break;
|
||||
}
|
||||
do {} while (!tryActivate()); // re-activate on exit
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long spOffset =
|
||||
objectFieldOffset("sp", ForkJoinWorkerThread.class);
|
||||
private static final long runStateOffset =
|
||||
objectFieldOffset("runState", ForkJoinWorkerThread.class);
|
||||
private static final long qBase;
|
||||
private static final int qShift;
|
||||
|
||||
static {
|
||||
qBase = UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
|
||||
int s = UNSAFE.arrayIndexScale(ForkJoinTask[].class);
|
||||
if ((s & (s-1)) != 0)
|
||||
throw new Error("data type scale not a power of two");
|
||||
qShift = 31 - Integer.numberOfLeadingZeros(s);
|
||||
}
|
||||
|
||||
private static long objectFieldOffset(String field, Class<?> klazz) {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
1270
jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java
Normal file
1270
jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
1042
jdk/src/share/classes/java/util/concurrent/Phaser.java
Normal file
1042
jdk/src/share/classes/java/util/concurrent/Phaser.java
Normal file
File diff suppressed because it is too large
Load Diff
179
jdk/src/share/classes/java/util/concurrent/RecursiveAction.java
Normal file
179
jdk/src/share/classes/java/util/concurrent/RecursiveAction.java
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/licenses/publicdomain
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A recursive resultless {@link ForkJoinTask}. This class
|
||||
* establishes conventions to parameterize resultless actions as
|
||||
* {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
|
||||
* only valid value of type {@code Void}, methods such as join always
|
||||
* return {@code null} upon completion.
|
||||
*
|
||||
* <p><b>Sample Usages.</b> Here is a sketch of a ForkJoin sort that
|
||||
* sorts a given {@code long[]} array:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class SortTask extends RecursiveAction {
|
||||
* final long[] array; final int lo; final int hi;
|
||||
* SortTask(long[] array, int lo, int hi) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* protected void compute() {
|
||||
* if (hi - lo < THRESHOLD)
|
||||
* sequentiallySort(array, lo, hi);
|
||||
* else {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* invokeAll(new SortTask(array, lo, mid),
|
||||
* new SortTask(array, mid, hi));
|
||||
* merge(array, lo, hi);
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* You could then sort {@code anArray} by creating {@code new
|
||||
* SortTask(anArray, 0, anArray.length-1) } and invoking it in a
|
||||
* ForkJoinPool. As a more concrete simple example, the following
|
||||
* task increments each element of an array:
|
||||
* <pre> {@code
|
||||
* class IncrementTask extends RecursiveAction {
|
||||
* final long[] array; final int lo; final int hi;
|
||||
* IncrementTask(long[] array, int lo, int hi) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* protected void compute() {
|
||||
* if (hi - lo < THRESHOLD) {
|
||||
* for (int i = lo; i < hi; ++i)
|
||||
* array[i]++;
|
||||
* }
|
||||
* else {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* invokeAll(new IncrementTask(array, lo, mid),
|
||||
* new IncrementTask(array, mid, hi));
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>The following example illustrates some refinements and idioms
|
||||
* that may lead to better performance: RecursiveActions need not be
|
||||
* fully recursive, so long as they maintain the basic
|
||||
* divide-and-conquer approach. Here is a class that sums the squares
|
||||
* of each element of a double array, by subdividing out only the
|
||||
* right-hand-sides of repeated divisions by two, and keeping track of
|
||||
* them with a chain of {@code next} references. It uses a dynamic
|
||||
* threshold based on method {@code getSurplusQueuedTaskCount}, but
|
||||
* counterbalances potential excess partitioning by directly
|
||||
* performing leaf actions on unstolen tasks rather than further
|
||||
* subdividing.
|
||||
*
|
||||
* <pre> {@code
|
||||
* double sumOfSquares(ForkJoinPool pool, double[] array) {
|
||||
* int n = array.length;
|
||||
* Applyer a = new Applyer(array, 0, n, null);
|
||||
* pool.invoke(a);
|
||||
* return a.result;
|
||||
* }
|
||||
*
|
||||
* class Applyer extends RecursiveAction {
|
||||
* final double[] array;
|
||||
* final int lo, hi;
|
||||
* double result;
|
||||
* Applyer next; // keeps track of right-hand-side tasks
|
||||
* Applyer(double[] array, int lo, int hi, Applyer next) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* this.next = next;
|
||||
* }
|
||||
*
|
||||
* double atLeaf(int l, int h) {
|
||||
* double sum = 0;
|
||||
* for (int i = l; i < h; ++i) // perform leftmost base step
|
||||
* sum += array[i] * array[i];
|
||||
* return sum;
|
||||
* }
|
||||
*
|
||||
* protected void compute() {
|
||||
* int l = lo;
|
||||
* int h = hi;
|
||||
* Applyer right = null;
|
||||
* while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
|
||||
* int mid = (l + h) >>> 1;
|
||||
* right = new Applyer(array, mid, h, right);
|
||||
* right.fork();
|
||||
* h = mid;
|
||||
* }
|
||||
* double sum = atLeaf(l, h);
|
||||
* while (right != null) {
|
||||
* if (right.tryUnfork()) // directly calculate if not stolen
|
||||
* sum += right.atLeaf(right.lo, right.hi);
|
||||
* else {
|
||||
* right.helpJoin();
|
||||
* sum += right.result;
|
||||
* }
|
||||
* right = right.next;
|
||||
* }
|
||||
* result = sum;
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class RecursiveAction extends ForkJoinTask<Void> {
|
||||
private static final long serialVersionUID = 5232453952276485070L;
|
||||
|
||||
/**
|
||||
* The main computation performed by this task.
|
||||
*/
|
||||
protected abstract void compute();
|
||||
|
||||
/**
|
||||
* Always returns null.
|
||||
*/
|
||||
public final Void getRawResult() { return null; }
|
||||
|
||||
/**
|
||||
* Requires null completion value.
|
||||
*/
|
||||
protected final void setRawResult(Void mustBeNull) { }
|
||||
|
||||
/**
|
||||
* Implements execution conventions for RecursiveActions.
|
||||
*/
|
||||
protected final boolean exec() {
|
||||
compute();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user