This commit is contained in:
J. Duke 2017-07-05 17:02:54 +02:00
commit 9928bdac3a
141 changed files with 9366 additions and 1462 deletions

View File

@ -49,3 +49,4 @@ e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73
2c88089b6e1c053597418099a14232182c387edc jdk7-b74
d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75

View File

@ -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.

View File

@ -49,3 +49,4 @@ a12ea7c7b497b4ba7830550095ef633bd6f43971 jdk7-b67
c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73
5d0cf59a3203b9f57aceebc33ae656b884987955 jdk7-b74
0fb137085952c8e47878e240d1cb40f14de463c4 jdk7-b75

View File

@ -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)
#

View File

@ -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 )

View File

@ -49,3 +49,4 @@ d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68
a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73
f4b900403d6e4b0af51447bd13bbe23fe3a1dac7 jdk7-b74
d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75

View File

@ -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

View File

@ -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"

View File

@ -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) {

View File

@ -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) {

View File

@ -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)) {

View File

@ -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());
}

View File

@ -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&lt;MonitorValue&gt; */
/** Returns a List&lt;ObjectValue&gt; */
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 */

View File

@ -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();
}

View File

@ -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) {" +

View File

@ -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

View File

@ -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;
//

View File

@ -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"

View File

@ -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");

View File

@ -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);

View File

@ -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
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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) {

View File

@ -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.") \

View File

@ -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);
}

View File

@ -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.

View File

@ -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());
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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();
}

View File

@ -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;

View File

@ -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());
}

View File

@ -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;

View File

@ -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();

View File

@ -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); \

View File

@ -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
}

View File

@ -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

View File

@ -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) \
\
/***************************************************/ \

View File

@ -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 */);

View 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();
}
}

View File

@ -49,3 +49,4 @@ b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71
460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
8885b22565077236a927e824ef450742e434a230 jdk7-b75

View File

@ -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)
#

View File

@ -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

View File

@ -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)
#

View 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)
#

View File

@ -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)

View File

@ -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

View File

@ -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 \

View File

@ -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
#

View File

@ -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)

View File

@ -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)"'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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' \

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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=\

View File

@ -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"

View File

@ -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' $< > $@

View File

@ -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

View File

@ -38,7 +38,6 @@ SUBDIRS = \
compile_properties \
dir_diff \
dtdbuilder \
fontchecker \
freetypecheck \
generate_break_iterator \
GenerateCharacter \

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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;
}

View File

@ -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());
}
}
/**

View File

@ -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);
}
/**

View File

@ -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
*/

View File

@ -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);
}
/**

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,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;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,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