--- a/.hgtags-top-repo Tue Jul 20 22:17:33 2010 -0700
+++ b/.hgtags-top-repo Wed Jul 05 17:18:01 2017 +0200
@@ -75,3 +75,4 @@
6cea9984d73d74de0cd01f30d07ac0a1ed196117 jdk7-b98
e7f18db469a3e947b7096bfd12e87380e5a042cd jdk7-b99
b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100
+4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101
--- a/corba/.hgtags Tue Jul 20 22:17:33 2010 -0700
+++ b/corba/.hgtags Wed Jul 05 17:18:01 2017 +0200
@@ -75,3 +75,4 @@
3b99409057e4c255da946f9f540d051a5ef4ab23 jdk7-b98
95db968660e7d87c345d5cf3dc2e3db037fb7220 jdk7-b99
a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
+86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101
--- a/hotspot/.hgtags Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/.hgtags Wed Jul 05 17:18:01 2017 +0200
@@ -104,3 +104,5 @@
8a045b3f5c13eaad92ff4baf15ca671845fcad1a jdk7-b98
6a236384a379642b5a2398e2819db9ab4e711e9b jdk7-b99
ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100
+6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101
+ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,7 +35,6 @@
public class NMethod extends CodeBlob {
private static long pcDescSize;
- private static CIntegerField zombieInstructionSizeField;
private static sun.jvm.hotspot.types.OopField methodField;
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
private static CIntegerField entryBCIField;
@@ -88,7 +87,6 @@
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("nmethod");
- zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
methodField = type.getOopField("_method");
entryBCIField = type.getCIntegerField("_entry_bci");
osrLinkField = type.getAddressField("_osr_link");
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java Wed Jul 05 17:18:01 2017 +0200
@@ -72,6 +72,7 @@
addBytecodeClass(Bytecodes._invokestatic, BytecodeInvoke.class);
addBytecodeClass(Bytecodes._invokespecial, BytecodeInvoke.class);
addBytecodeClass(Bytecodes._invokeinterface, BytecodeInvoke.class);
+ addBytecodeClass(Bytecodes._invokedynamic, BytecodeInvoke.class);
addBytecodeClass(Bytecodes._jsr, BytecodeJsr.class);
addBytecodeClass(Bytecodes._jsr_w, BytecodeJsrW.class);
addBytecodeClass(Bytecodes._iload, BytecodeLoad.class);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java Wed Jul 05 17:18:01 2017 +0200
@@ -54,15 +54,31 @@
// returns the name of the invoked method
public Symbol name() {
ConstantPool cp = method().getConstants();
+ if (isInvokedynamic()) {
+ int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
+ return cp.getSymbolAt(nt[0]);
+ }
return cp.getNameRefAt(index());
}
// returns the signature of the invoked method
public Symbol signature() {
ConstantPool cp = method().getConstants();
+ if (isInvokedynamic()) {
+ int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
+ return cp.getSymbolAt(nt[1]);
+ }
return cp.getSignatureRefAt(index());
}
+ public int getSecondaryIndex() {
+ if (isInvokedynamic()) {
+ // change byte-ordering of 4-byte integer
+ return VM.getVM().getBytes().swapInt(javaSignedWordAt(1));
+ }
+ return super.getSecondaryIndex(); // throw an error
+ }
+
public Method getInvokedMethod() {
return method().getConstants().getMethodRefAt(index());
}
@@ -87,6 +103,7 @@
public boolean isInvokevirtual() { return adjustedInvokeCode() == Bytecodes._invokevirtual; }
public boolean isInvokestatic() { return adjustedInvokeCode() == Bytecodes._invokestatic; }
public boolean isInvokespecial() { return adjustedInvokeCode() == Bytecodes._invokespecial; }
+ public boolean isInvokedynamic() { return adjustedInvokeCode() == Bytecodes._invokedynamic; }
public boolean isValid() { return isInvokeinterface() ||
isInvokevirtual() ||
@@ -104,6 +121,11 @@
buf.append(spaces);
buf.append('#');
buf.append(Integer.toString(indexForFieldOrMethod()));
+ if (isInvokedynamic()) {
+ buf.append('(');
+ buf.append(Integer.toString(getSecondaryIndex()));
+ buf.append(')');
+ }
buf.append(" [Method ");
StringBuffer sigBuf = new StringBuffer();
new SignatureConverter(signature(), sigBuf).iterateReturntype();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,7 @@
package sun.jvm.hotspot.interpreter;
import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
public class BytecodeLoadConstant extends BytecodeWithCPIndex {
@@ -32,10 +33,47 @@
super(method, bci);
}
+ public boolean hasCacheIndex() {
+ // normal ldc uses CP index, but fast_aldc uses swapped CP cache index
+ return javaCode() != code();
+ }
+
public int index() {
- return javaCode() == Bytecodes._ldc ?
+ int i = javaCode() == Bytecodes._ldc ?
(int) (0xFF & javaByteAt(1))
: (int) (0xFFFF & javaShortAt(1));
+ if (hasCacheIndex()) {
+ return (0xFFFF & VM.getVM().getBytes().swapShort((short) i));
+ } else {
+ return i;
+ }
+ }
+
+ public int poolIndex() {
+ int i = index();
+ if (hasCacheIndex()) {
+ ConstantPoolCache cpCache = method().getConstants().getCache();
+ return cpCache.getEntryAt(i).getConstantPoolIndex();
+ } else {
+ return i;
+ }
+ }
+
+ public int cacheIndex() {
+ if (hasCacheIndex()) {
+ return index();
+ } else {
+ return -1; // no cache index
+ }
+ }
+
+ private Oop getCachedConstant() {
+ int i = cacheIndex();
+ if (i >= 0) {
+ ConstantPoolCache cpCache = method().getConstants().getCache();
+ return cpCache.getEntryAt(i).getF1();
+ }
+ return null;
}
public void verify() {
@@ -58,6 +96,7 @@
// has to be int or float or String or Klass
return (ctag.isUnresolvedString() || ctag.isString()
|| ctag.isUnresolvedKlass() || ctag.isKlass()
+ || ctag.isMethodHandle() || ctag.isMethodType()
|| ctag.isInt() || ctag.isFloat())? true: false;
}
}
@@ -112,7 +151,7 @@
public String getConstantValue() {
ConstantPool cpool = method().getConstants();
- int cpIndex = index();
+ int cpIndex = poolIndex();
ConstantTag ctag = cpool.getTagAt(cpIndex);
if (ctag.isInt()) {
return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">";
@@ -149,6 +188,18 @@
} else {
throw new RuntimeException("should not reach here");
}
+ } else if (ctag.isMethodHandle() || ctag.isMethodType()) {
+ Oop x = getCachedConstant();
+ int refidx = cpool.getMethodHandleIndexAt(cpIndex);
+ int refkind = cpool.getMethodHandleRefKindAt(cpIndex);
+ return "<MethodHandle kind=" + Integer.toString(refkind) +
+ " ref=" + Integer.toString(refidx)
+ + (x == null ? "" : " @" + x.getHandle()) + ">";
+ } else if (ctag.isMethodType()) {
+ Oop x = getCachedConstant();
+ int refidx = cpool.getMethodTypeIndexAt(cpIndex);
+ return "<MethodType " + cpool.getSymbolAt(refidx).asString()
+ + (x == null ? "" : " @" + x.getHandle()) + ">";
} else {
if (Assert.ASSERTS_ENABLED) {
Assert.that(false, "invalid load constant type");
@@ -162,7 +213,12 @@
buf.append(getJavaBytecodeName());
buf.append(spaces);
buf.append('#');
- buf.append(Integer.toString(index()));
+ buf.append(Integer.toString(poolIndex()));
+ if (hasCacheIndex()) {
+ buf.append('(');
+ buf.append(Integer.toString(cacheIndex()));
+ buf.append(')');
+ }
buf.append(spaces);
buf.append(getConstantValue());
if (code() != javaCode()) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Wed Jul 05 17:18:01 2017 +0200
@@ -37,12 +37,19 @@
// the constant pool index for this bytecode
public int index() { return 0xFFFF & javaShortAt(1); }
+ public int getSecondaryIndex() {
+ throw new IllegalArgumentException("must be invokedynamic");
+ }
+
protected int indexForFieldOrMethod() {
ConstantPoolCache cpCache = method().getConstants().getCache();
// get ConstantPool index from ConstantPoolCacheIndex at given bci
int cpCacheIndex = index();
if (cpCache == null) {
return cpCacheIndex;
+ } else if (code() == Bytecodes._invokedynamic) {
+ int secondaryIndex = getSecondaryIndex();
+ return cpCache.getMainEntryAt(secondaryIndex).getConstantPoolIndex();
} else {
// change byte-ordering and go via cache
return cpCache.getEntryAt((int) (0xFFFF & VM.getVM().getBytes().swapShort((short) cpCacheIndex))).getConstantPoolIndex();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Wed Jul 05 17:18:01 2017 +0200
@@ -222,7 +222,7 @@
public static final int _invokespecial = 183; // 0xb7
public static final int _invokestatic = 184; // 0xb8
public static final int _invokeinterface = 185; // 0xb9
- public static final int _xxxunusedxxx = 186; // 0xba
+ public static final int _invokedynamic = 186; // 0xba
public static final int _new = 187; // 0xbb
public static final int _newarray = 188; // 0xbc
public static final int _anewarray = 189; // 0xbd
@@ -269,9 +269,12 @@
public static final int _fast_invokevfinal = 226;
public static final int _fast_linearswitch = 227;
public static final int _fast_binaryswitch = 228;
- public static final int _shouldnotreachhere = 229; // For debugging
+ public static final int _fast_aldc = 229;
+ public static final int _fast_aldc_w = 230;
+ public static final int _return_register_finalizer = 231;
+ public static final int _shouldnotreachhere = 232; // For debugging
- public static final int number_of_codes = 230;
+ public static final int number_of_codes = 233;
public static int specialLengthAt(Method method, int bci) {
int code = codeAt(method, bci);
@@ -458,9 +461,9 @@
def(_dconst_1 , "dconst_1" , "b" , null , BasicType.getTDouble() , 2, false);
def(_bipush , "bipush" , "bc" , null , BasicType.getTInt() , 1, false);
def(_sipush , "sipush" , "bcc" , null , BasicType.getTInt() , 1, false);
- def(_ldc , "ldc" , "bi" , null , BasicType.getTIllegal(), 1, true );
- def(_ldc_w , "ldc_w" , "bii" , null , BasicType.getTIllegal(), 1, true );
- def(_ldc2_w , "ldc2_w" , "bii" , null , BasicType.getTIllegal(), 2, true );
+ def(_ldc , "ldc" , "bk" , null , BasicType.getTIllegal(), 1, true );
+ def(_ldc_w , "ldc_w" , "bkk" , null , BasicType.getTIllegal(), 1, true );
+ def(_ldc2_w , "ldc2_w" , "bkk" , null , BasicType.getTIllegal(), 2, true );
def(_iload , "iload" , "bi" , "wbii" , BasicType.getTInt() , 1, false);
def(_lload , "lload" , "bi" , "wbii" , BasicType.getTLong() , 2, false);
def(_fload , "fload" , "bi" , "wbii" , BasicType.getTFloat() , 1, false);
@@ -618,26 +621,26 @@
def(_dreturn , "dreturn" , "b" , null , BasicType.getTDouble() , -2, true );
def(_areturn , "areturn" , "b" , null , BasicType.getTObject() , -1, true );
def(_return , "return" , "b" , null , BasicType.getTVoid() , 0, true );
- def(_getstatic , "getstatic" , "bjj" , null , BasicType.getTIllegal(), 1, true );
- def(_putstatic , "putstatic" , "bjj" , null , BasicType.getTIllegal(), -1, true );
- def(_getfield , "getfield" , "bjj" , null , BasicType.getTIllegal(), 0, true );
- def(_putfield , "putfield" , "bjj" , null , BasicType.getTIllegal(), -2, true );
- def(_invokevirtual , "invokevirtual" , "bjj" , null , BasicType.getTIllegal(), -1, true );
- def(_invokespecial , "invokespecial" , "bjj" , null , BasicType.getTIllegal(), -1, true );
- def(_invokestatic , "invokestatic" , "bjj" , null , BasicType.getTIllegal(), 0, true );
- def(_invokeinterface , "invokeinterface" , "bjj__", null , BasicType.getTIllegal(), -1, true );
- def(_xxxunusedxxx , "xxxunusedxxx" , null , null , BasicType.getTVoid() , 0, false);
- def(_new , "new" , "bii" , null , BasicType.getTObject() , 1, true );
+ def(_getstatic , "getstatic" , "bJJ" , null , BasicType.getTIllegal(), 1, true );
+ def(_putstatic , "putstatic" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
+ def(_getfield , "getfield" , "bJJ" , null , BasicType.getTIllegal(), 0, true );
+ def(_putfield , "putfield" , "bJJ" , null , BasicType.getTIllegal(), -2, true );
+ def(_invokevirtual , "invokevirtual" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
+ def(_invokespecial , "invokespecial" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
+ def(_invokestatic , "invokestatic" , "bJJ" , null , BasicType.getTIllegal(), 0, true );
+ def(_invokeinterface , "invokeinterface" , "bJJ__", null , BasicType.getTIllegal(), -1, true );
+ def(_invokedynamic , "invokedynamic" , "bJJJJ", null , BasicType.getTIllegal(), -1, true );
+ def(_new , "new" , "bkk" , null , BasicType.getTObject() , 1, true );
def(_newarray , "newarray" , "bc" , null , BasicType.getTObject() , 0, true );
- def(_anewarray , "anewarray" , "bii" , null , BasicType.getTObject() , 0, true );
+ def(_anewarray , "anewarray" , "bkk" , null , BasicType.getTObject() , 0, true );
def(_arraylength , "arraylength" , "b" , null , BasicType.getTVoid() , 0, true );
def(_athrow , "athrow" , "b" , null , BasicType.getTVoid() , -1, true );
- def(_checkcast , "checkcast" , "bii" , null , BasicType.getTObject() , 0, true );
- def(_instanceof , "instanceof" , "bii" , null , BasicType.getTInt() , 0, true );
+ def(_checkcast , "checkcast" , "bkk" , null , BasicType.getTObject() , 0, true );
+ def(_instanceof , "instanceof" , "bkk" , null , BasicType.getTInt() , 0, true );
def(_monitorenter , "monitorenter" , "b" , null , BasicType.getTVoid() , -1, true );
def(_monitorexit , "monitorexit" , "b" , null , BasicType.getTVoid() , -1, true );
def(_wide , "wide" , "" , null , BasicType.getTVoid() , 0, false);
- def(_multianewarray , "multianewarray" , "biic" , null , BasicType.getTObject() , 1, true );
+ def(_multianewarray , "multianewarray" , "bkkc" , null , BasicType.getTObject() , 1, true );
def(_ifnull , "ifnull" , "boo" , null , BasicType.getTVoid() , -1, false);
def(_ifnonnull , "ifnonnull" , "boo" , null , BasicType.getTVoid() , -1, false);
def(_goto_w , "goto_w" , "boooo", null , BasicType.getTVoid() , 0, false);
@@ -646,38 +649,44 @@
// JVM bytecodes
// bytecode bytecode name format wide f. result tp stk traps std code
- def(_fast_agetfield , "fast_agetfield" , "bjj" , null , BasicType.getTObject() , 0, true , _getfield );
- def(_fast_bgetfield , "fast_bgetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield );
- def(_fast_cgetfield , "fast_cgetfield" , "bjj" , null , BasicType.getTChar() , 0, true , _getfield );
- def(_fast_dgetfield , "fast_dgetfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _getfield );
- def(_fast_fgetfield , "fast_fgetfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _getfield );
- def(_fast_igetfield , "fast_igetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield );
- def(_fast_lgetfield , "fast_lgetfield" , "bjj" , null , BasicType.getTLong() , 0, true , _getfield );
- def(_fast_sgetfield , "fast_sgetfield" , "bjj" , null , BasicType.getTShort() , 0, true , _getfield );
+ def(_fast_agetfield , "fast_agetfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _getfield );
+ def(_fast_bgetfield , "fast_bgetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield );
+ def(_fast_cgetfield , "fast_cgetfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _getfield );
+ def(_fast_dgetfield , "fast_dgetfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _getfield );
+ def(_fast_fgetfield , "fast_fgetfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _getfield );
+ def(_fast_igetfield , "fast_igetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield );
+ def(_fast_lgetfield , "fast_lgetfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _getfield );
+ def(_fast_sgetfield , "fast_sgetfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _getfield );
- def(_fast_aputfield , "fast_aputfield" , "bjj" , null , BasicType.getTObject() , 0, true , _putfield );
- def(_fast_bputfield , "fast_bputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield );
- def(_fast_cputfield , "fast_cputfield" , "bjj" , null , BasicType.getTChar() , 0, true , _putfield );
- def(_fast_dputfield , "fast_dputfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _putfield );
- def(_fast_fputfield , "fast_fputfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _putfield );
- def(_fast_iputfield , "fast_iputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield );
- def(_fast_lputfield , "fast_lputfield" , "bjj" , null , BasicType.getTLong() , 0, true , _putfield );
- def(_fast_sputfield , "fast_sputfield" , "bjj" , null , BasicType.getTShort() , 0, true , _putfield );
+ def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield );
+ def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield );
+ def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield );
+ def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield );
+ def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield );
+ def(_fast_iputfield , "fast_iputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield );
+ def(_fast_lputfield , "fast_lputfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _putfield );
+ def(_fast_sputfield , "fast_sputfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _putfield );
def(_fast_aload_0 , "fast_aload_0" , "b" , null , BasicType.getTObject() , 1, true , _aload_0 );
- def(_fast_iaccess_0 , "fast_iaccess_0" , "b_jj" , null , BasicType.getTInt() , 1, true , _aload_0 );
- def(_fast_aaccess_0 , "fast_aaccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 );
- def(_fast_faccess_0 , "fast_faccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 );
+ def(_fast_iaccess_0 , "fast_iaccess_0" , "b_JJ" , null , BasicType.getTInt() , 1, true , _aload_0 );
+ def(_fast_aaccess_0 , "fast_aaccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 );
+ def(_fast_faccess_0 , "fast_faccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 );
def(_fast_iload , "fast_iload" , "bi" , null , BasicType.getTInt() , 1, false, _iload);
def(_fast_iload2 , "fast_iload2" , "bi_i" , null , BasicType.getTInt() , 2, false, _iload);
def(_fast_icaload , "fast_icaload" , "bi_" , null , BasicType.getTInt() , 0, false, _iload);
// Faster method invocation.
- def(_fast_invokevfinal , "fast_invokevfinal" , "bjj" , null , BasicType.getTIllegal(), -1, true, _invokevirtual);
+ def(_fast_invokevfinal , "fast_invokevfinal" , "bJJ" , null , BasicType.getTIllegal(), -1, true, _invokevirtual);
def(_fast_linearswitch , "fast_linearswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
def(_fast_binaryswitch , "fast_binaryswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
+
+ def(_return_register_finalizer, "return_register_finalizer", "b" , null , BasicType.getTVoid() , 0, true, _return );
+
+ def(_fast_aldc , "fast_aldc" , "bj" , null , BasicType.getTObject(), 1, true, _ldc );
+ def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , null , BasicType.getTObject(), 1, true, _ldc_w );
+
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , null , BasicType.getTVoid() , 0, false);
if (Assert.ASSERTS_ENABLED) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed Jul 05 17:18:01 2017 +0200
@@ -152,7 +152,7 @@
return res;
}
- public int getNameAndTypeAt(int which) {
+ public int[] getNameAndTypeAt(int which) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool");
}
@@ -160,18 +160,16 @@
if (DEBUG) {
System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i);
}
- return i;
+ return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) };
}
public Symbol getNameRefAt(int which) {
- int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
- int nameIndex = extractLowShortFromInt(refIndex);
+ int nameIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[0];
return getSymbolAt(nameIndex);
}
public Symbol getSignatureRefAt(int which) {
- int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
- int sigIndex = extractHighShortFromInt(refIndex);
+ int sigIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[1];
return getSymbolAt(sigIndex);
}
@@ -220,11 +218,11 @@
/** Lookup for entries consisting of (name_index, signature_index) */
public int getNameRefIndexAt(int index) {
- int refIndex = getNameAndTypeAt(index);
+ int[] refIndex = getNameAndTypeAt(index);
if (DEBUG) {
- System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex);
+ System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
}
- int i = extractLowShortFromInt(refIndex);
+ int i = refIndex[0];
if (DEBUG) {
System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i);
}
@@ -233,17 +231,53 @@
/** Lookup for entries consisting of (name_index, signature_index) */
public int getSignatureRefIndexAt(int index) {
- int refIndex = getNameAndTypeAt(index);
+ int[] refIndex = getNameAndTypeAt(index);
if (DEBUG) {
- System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex);
+ System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
}
- int i = extractHighShortFromInt(refIndex);
+ int i = refIndex[1];
if (DEBUG) {
System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i);
}
return i;
}
+ /** Lookup for MethodHandle entries. */
+ public int getMethodHandleIndexAt(int i) {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
+ }
+ int res = extractHighShortFromInt(getIntAt(i));
+ if (DEBUG) {
+ System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res);
+ }
+ return res;
+ }
+
+ /** Lookup for MethodHandle entries. */
+ public int getMethodHandleRefKindAt(int i) {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
+ }
+ int res = extractLowShortFromInt(getIntAt(i));
+ if (DEBUG) {
+ System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res);
+ }
+ return res;
+ }
+
+ /** Lookup for MethodType entries. */
+ public int getMethodTypeIndexAt(int i) {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool");
+ }
+ int res = getIntAt(i);
+ if (DEBUG) {
+ System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res);
+ }
+ return res;
+ }
+
final private static String[] nameForTag = new String[] {
};
@@ -261,6 +295,8 @@
case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref";
case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref";
case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";
+ case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
+ case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
@@ -317,6 +353,8 @@
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_NameAndType:
+ case JVM_CONSTANT_MethodHandle:
+ case JVM_CONSTANT_MethodType:
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
break;
}
@@ -467,6 +505,18 @@
+ ", type = " + signatureIndex);
break;
}
+
+ case JVM_CONSTANT_MethodHandle: {
+ dos.writeByte(cpConstType);
+ int value = getIntAt(ci);
+ short nameIndex = (short) extractLowShortFromInt(value);
+ short signatureIndex = (short) extractHighShortFromInt(value);
+ dos.writeShort(nameIndex);
+ dos.writeShort(signatureIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex
+ + ", type = " + signatureIndex);
+ break;
+ }
default:
throw new InternalError("unknown tag: " + cpConstType);
} // switch
@@ -488,10 +538,12 @@
//
private static int extractHighShortFromInt(int val) {
+ // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
return (val >> 16) & 0xFFFF;
}
private static int extractLowShortFromInt(int val) {
+ // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
return val & 0xFFFF;
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Wed Jul 05 17:18:01 2017 +0200
@@ -78,6 +78,31 @@
return new ConstantPoolCacheEntry(this, i);
}
+ public static boolean isSecondaryIndex(int i) { return (i < 0); }
+ public static int decodeSecondaryIndex(int i) { return isSecondaryIndex(i) ? ~i : i; }
+ public static int encodeSecondaryIndex(int i) { return !isSecondaryIndex(i) ? ~i : i; }
+
+ // secondary entries hold invokedynamic call site bindings
+ public ConstantPoolCacheEntry getSecondaryEntryAt(int i) {
+ ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, decodeSecondaryIndex(i));
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(e.isSecondaryEntry(), "must be a secondary entry");
+ }
+ return e;
+ }
+
+ public ConstantPoolCacheEntry getMainEntryAt(int i) {
+ if (isSecondaryIndex(i)) {
+ // run through an extra level of indirection:
+ i = getSecondaryEntryAt(i).getMainEntryIndex();
+ }
+ ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, i);
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry");
+ }
+ return e;
+ }
+
public int getIntAt(int entry, int fld) {
//alignObjectSize ?
long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld* getHeap().getIntSize();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java Wed Jul 05 17:18:01 2017 +0200
@@ -28,6 +28,7 @@
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
public class ConstantPoolCacheEntry {
private static long size;
@@ -67,9 +68,23 @@
}
public int getConstantPoolIndex() {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(!isSecondaryEntry(), "must not be a secondary CP entry");
+ }
return (int) (getIndices() & 0xFFFF);
}
+ public boolean isSecondaryEntry() {
+ return (getIndices() & 0xFFFF) == 0;
+ }
+
+ public int getMainEntryIndex() {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(isSecondaryEntry(), "must be a secondary CP entry");
+ }
+ return (int) (getIndices() >>> 16);
+ }
+
private long getIndices() {
return cp.getHandle().getCIntegerAt(indices.getOffset() + offset, indices.getSize(), indices.isUnsigned());
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Wed Jul 05 17:18:01 2017 +0200
@@ -566,6 +566,7 @@
case Bytecodes._invokespecial:
case Bytecodes._invokestatic:
case Bytecodes._invokeinterface:
+ case Bytecodes._invokedynamic:
// FIXME: print signature of referenced method (need more
// accessors in ConstantPool and ConstantPoolCache)
int idx = currentBC.getIndexBig();
@@ -605,6 +606,7 @@
case Bytecodes._invokespecial:
case Bytecodes._invokestatic:
case Bytecodes._invokeinterface:
+ case Bytecodes._invokedynamic:
// FIXME: print signature of referenced method (need more
// accessors in ConstantPool and ConstantPoolCache)
int idx = currentBC.getIndexBig();
@@ -1134,6 +1136,7 @@
case Bytecodes._invokespecial:
case Bytecodes._invokestatic:
case Bytecodes._invokeinterface:
+ case Bytecodes._invokedynamic:
_itr_send = itr;
_report_result_for_send = true;
break;
@@ -1379,6 +1382,7 @@
case Bytecodes._invokevirtual:
case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
case Bytecodes._invokestatic: doMethod(true, false, itr.getIndexBig(), itr.bci()); break;
+ case Bytecodes._invokedynamic: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
case Bytecodes._invokeinterface: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
case Bytecodes._newarray:
case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break;
@@ -1725,7 +1729,7 @@
void doMethod (boolean is_static, boolean is_interface, int idx, int bci) {
// Dig up signature for field in constant pool
ConstantPool cp = _method.getConstants();
- int nameAndTypeIdx = cp.getNameAndTypeRefIndexAt(idx);
+ int nameAndTypeIdx = cp.getTagAt(idx).isNameAndType() ? idx : cp.getNameAndTypeRefIndexAt(idx);
int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
Symbol signature = cp.getSymbolAt(signatureIdx);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Wed Jul 05 17:18:01 2017 +0200
@@ -40,6 +40,19 @@
public static final int JVM_CONSTANT_Methodref = 10;
public static final int JVM_CONSTANT_InterfaceMethodref = 11;
public static final int JVM_CONSTANT_NameAndType = 12;
+ public static final int JVM_CONSTANT_MethodHandle = 15;
+ public static final int JVM_CONSTANT_MethodType = 16;
+
+ // JVM_CONSTANT_MethodHandle subtypes
+ public static final int JVM_REF_getField = 1;
+ public static final int JVM_REF_getStatic = 2;
+ public static final int JVM_REF_putField = 3;
+ public static final int JVM_REF_putStatic = 4;
+ public static final int JVM_REF_invokeVirtual = 5;
+ public static final int JVM_REF_invokeStatic = 6;
+ public static final int JVM_REF_invokeSpecial = 7;
+ public static final int JVM_REF_newInvokeSpecial = 8;
+ public static final int JVM_REF_invokeInterface = 9;
// HotSpot specific constant pool constant types.
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Wed Jul 05 17:18:01 2017 +0200
@@ -54,14 +54,34 @@
}
- protected short getConstantPoolIndex(int bci) {
+ protected short getConstantPoolIndex(int rawcode, int bci) {
// get ConstantPool index from ConstantPoolCacheIndex at given bci
- short cpCacheIndex = method.getBytecodeShortArg(bci);
+ String fmt = Bytecodes.format(rawcode);
+ int cpCacheIndex;
+ switch (fmt.length()) {
+ case 2: cpCacheIndex = method.getBytecodeByteArg(bci); break;
+ case 3: cpCacheIndex = method.getBytecodeShortArg(bci); break;
+ case 5:
+ if (fmt.indexOf("__") >= 0)
+ cpCacheIndex = method.getBytecodeShortArg(bci);
+ else
+ cpCacheIndex = method.getBytecodeIntArg(bci);
+ break;
+ default: throw new IllegalArgumentException();
+ }
if (cpCache == null) {
- return cpCacheIndex;
+ return (short) cpCacheIndex;
+ } else if (fmt.indexOf("JJJJ") >= 0) {
+ // change byte-ordering and go via secondary cache entry
+ return (short) cpCache.getMainEntryAt(bytes.swapInt(cpCacheIndex)).getConstantPoolIndex();
+ } else if (fmt.indexOf("JJ") >= 0) {
+ // change byte-ordering and go via cache
+ return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort((short)cpCacheIndex))).getConstantPoolIndex();
+ } else if (fmt.indexOf("j") >= 0) {
+ // go via cache
+ return (short) cpCache.getEntryAt((int) (0xFF & cpCacheIndex)).getConstantPoolIndex();
} else {
- // change byte-ordering and go via cache
- return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort(cpCacheIndex))).getConstantPoolIndex();
+ return (short) cpCacheIndex;
}
}
@@ -100,10 +120,31 @@
case Bytecodes._invokespecial:
case Bytecodes._invokestatic:
case Bytecodes._invokeinterface: {
- cpoolIndex = getConstantPoolIndex(bci + 1);
+ cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
writeShort(code, bci + 1, cpoolIndex);
break;
}
+
+ case Bytecodes._invokedynamic:
+ cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+ writeShort(code, bci + 1, cpoolIndex);
+ writeShort(code, bci + 3, (short)0); // clear out trailing bytes
+ break;
+
+ case Bytecodes._ldc_w:
+ if (hotspotcode != bytecode) {
+ // fast_aldc_w puts constant in CP cache
+ cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+ writeShort(code, bci + 1, cpoolIndex);
+ }
+ break;
+ case Bytecodes._ldc:
+ if (hotspotcode != bytecode) {
+ // fast_aldc puts constant in CP cache
+ cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+ code[bci + 1] = (byte)(cpoolIndex);
+ }
+ break;
}
len = Bytecodes.lengthFor(bytecode);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Wed Jul 05 17:18:01 2017 +0200
@@ -61,10 +61,12 @@
protected short _signatureIndex;
protected static int extractHighShortFromInt(int val) {
+ // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
return (val >> 16) & 0xFFFF;
}
protected static int extractLowShortFromInt(int val) {
+ // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
return val & 0xFFFF;
}
@@ -297,6 +299,28 @@
+ ", type = " + signatureIndex);
break;
}
+
+ case JVM_CONSTANT_MethodHandle: {
+ dos.writeByte(cpConstType);
+ int value = cpool.getIntAt(ci);
+ short refIndex = (short) extractHighShortFromInt(value);
+ byte refKind = (byte) extractLowShortFromInt(value);
+ dos.writeByte(refKind);
+ dos.writeShort(refIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = MH index = " + refIndex
+ + ", kind = " + refKind);
+ break;
+ }
+
+ case JVM_CONSTANT_MethodType: {
+ dos.writeByte(cpConstType);
+ int value = cpool.getIntAt(ci);
+ short refIndex = (short) value;
+ dos.writeShort(refIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);
+ break;
+ }
+
default:
throw new InternalError("Unknown tag: " + cpConstType);
} // switch
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Jul 05 17:18:01 2017 +0200
@@ -572,6 +572,16 @@
buf.cell(Integer.toString(cpool.getIntAt(index)));
break;
+ case JVM_CONSTANT_MethodHandle:
+ buf.cell("JVM_CONSTANT_MethodHandle");
+ buf.cell(genLowHighShort(cpool.getIntAt(index)));
+ break;
+
+ case JVM_CONSTANT_MethodType:
+ buf.cell("JVM_CONSTANT_MethodType");
+ buf.cell(Integer.toString(cpool.getIntAt(index)));
+ break;
+
default:
throw new InternalError("unknown tag: " + ctag);
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Wed Jul 05 17:18:01 2017 +0200
@@ -38,12 +38,26 @@
private static int JVM_CONSTANT_Methodref = 10;
private static int JVM_CONSTANT_InterfaceMethodref = 11;
private static int JVM_CONSTANT_NameAndType = 12;
+ private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
+ private static int JVM_CONSTANT_MethodType = 16; // JSR 292
private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use
private static int JVM_CONSTANT_ClassIndex = 101; // Temporary tag while constructing constant pool
private static int JVM_CONSTANT_UnresolvedString = 102; // Temporary tag until actual use
private static int JVM_CONSTANT_StringIndex = 103; // Temporary tag while constructing constant pool
private static int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed
+ private static int JVM_CONSTANT_Object = 105; // Required for BoundMethodHandle arguments.
+
+ // JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
+ private static int JVM_REF_getField = 1;
+ private static int JVM_REF_getStatic = 2;
+ private static int JVM_REF_putField = 3;
+ private static int JVM_REF_putStatic = 4;
+ private static int JVM_REF_invokeVirtual = 5;
+ private static int JVM_REF_invokeStatic = 6;
+ private static int JVM_REF_invokeSpecial = 7;
+ private static int JVM_REF_newInvokeSpecial = 8;
+ private static int JVM_REF_invokeInterface = 9;
private byte tag;
@@ -62,6 +76,8 @@
public boolean isDouble() { return tag == JVM_CONSTANT_Double; }
public boolean isNameAndType() { return tag == JVM_CONSTANT_NameAndType; }
public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; }
+ public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
+ public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
@@ -73,6 +89,8 @@
public boolean isUnresolvedString() { return tag == JVM_CONSTANT_UnresolvedString; }
public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; }
+ public boolean isObject() { return tag == JVM_CONSTANT_Object; }
+
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
public boolean isSymbol() { return isUtf8(); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Wed Jul 05 17:18:01 2017 +0200
@@ -825,6 +825,8 @@
}
writeln("");
disAsm.decode(new sapkg.interpreter.BytecodeVisitor() {
+ prologue: function(method) { },
+ epilogue: function() { },
visit: function(bytecode) {
if (hasLines) {
var line = method.getLineNumberFromBCI(bci);
--- a/hotspot/make/hotspot_version Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/make/hotspot_version Wed Jul 05 17:18:01 2017 +0200
@@ -35,7 +35,7 @@
HS_MAJOR_VER=19
HS_MINOR_VER=0
-HS_BUILD_NUMBER=03
+HS_BUILD_NUMBER=04
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
--- a/hotspot/make/linux/makefiles/adlc.make Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/make/linux/makefiles/adlc.make Wed Jul 05 17:18:01 2017 +0200
@@ -138,7 +138,11 @@
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
# But -g will put #line directives in those files pointing back to <arch>.ad.
+# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives
+# so skip it for 3.2 and ealier.
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
ADLCFLAGS += -g
+endif
ifdef LP64
ADLCFLAGS += -D_LP64
--- a/hotspot/make/linux/makefiles/sa.make Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/make/linux/makefiles/sa.make Wed Jul 05 17:18:01 2017 +0200
@@ -40,6 +40,9 @@
# tools.jar is needed by the JDI - SA binding
SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
# gnumake 3.78.1 does not accept the *s that
# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -65,7 +68,7 @@
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
exit 1; \
fi
- $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+ $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
echo ""; \
exit 1; \
--- a/hotspot/make/solaris/makefiles/sa.make Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/make/solaris/makefiles/sa.make Wed Jul 05 17:18:01 2017 +0200
@@ -36,6 +36,9 @@
# tools.jar is needed by the JDI - SA binding
SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
# gnumake 3.78.1 does not accept the *s that
# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -59,7 +62,7 @@
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
exit 1; \
fi
- $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+ $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
echo ""; \
exit 1; \
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -318,6 +318,31 @@
__ bind(exit);
}
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+ transition(vtos, atos);
+
+ if (!EnableMethodHandles) {
+ // We should not encounter this bytecode if !EnableMethodHandles.
+ // The verifier will stop it. However, if we get past the verifier,
+ // this will stop the thread in a reasonable way, without crashing the JVM.
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_IncompatibleClassChangeError));
+ // the call_VM checks for exception, so we should never return here.
+ __ should_not_reach_here();
+ return;
+ }
+
+ Register Rcache = G3_scratch;
+ Register Rscratch = G4_scratch;
+
+ resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
+
+ __ verify_oop(Otos_i);
+}
+
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
Label retry, resolved, Long, exit;
@@ -1994,6 +2019,8 @@
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
+ case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
+ case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
default : ShouldNotReachHere(); break;
}
// first time invocation - must resolve first
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -375,6 +375,32 @@
__ bind(Done);
}
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+ transition(vtos, atos);
+
+ if (!EnableMethodHandles) {
+ // We should not encounter this bytecode if !EnableMethodHandles.
+ // The verifier will stop it. However, if we get past the verifier,
+ // this will stop the thread in a reasonable way, without crashing the JVM.
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_IncompatibleClassChangeError));
+ // the call_VM checks for exception, so we should never return here.
+ __ should_not_reach_here();
+ return;
+ }
+
+ const Register cache = rcx;
+ const Register index = rdx;
+
+ resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
+ if (VerifyOops) {
+ __ verify_oop(rax);
+ }
+}
+
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
Label Long, Done;
@@ -2055,6 +2081,8 @@
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
+ case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
+ case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
default : ShouldNotReachHere(); break;
}
__ movl(temp, (int)bytecode());
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -389,6 +389,32 @@
__ bind(Done);
}
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+ transition(vtos, atos);
+
+ if (!EnableMethodHandles) {
+ // We should not encounter this bytecode if !EnableMethodHandles.
+ // The verifier will stop it. However, if we get past the verifier,
+ // this will stop the thread in a reasonable way, without crashing the JVM.
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_IncompatibleClassChangeError));
+ // the call_VM checks for exception, so we should never return here.
+ __ should_not_reach_here();
+ return;
+ }
+
+ const Register cache = rcx;
+ const Register index = rdx;
+
+ resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
+ if (VerifyOops) {
+ __ verify_oop(rax);
+ }
+}
+
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
Label Long, Done;
@@ -2063,6 +2089,12 @@
case Bytecodes::_invokedynamic:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
break;
+ case Bytecodes::_fast_aldc:
+ entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+ break;
+ case Bytecodes::_fast_aldc_w:
+ entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+ break;
default:
ShouldNotReachHere();
break;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
static BufferBlob* stub_blob;
-static const int stub_size = 300;
+static const int stub_size = 400;
extern "C" {
typedef void (*getPsrInfo_stub_t)(void*);
@@ -56,7 +56,7 @@
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
- Label detect_486, cpu486, detect_586, std_cpuid1;
+ Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
Label ext_cpuid1, ext_cpuid5, done;
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
@@ -131,13 +131,62 @@
__ movl(Address(rsi, 8), rcx);
__ movl(Address(rsi,12), rdx);
- __ cmpl(rax, 3); // Is cpuid(0x4) supported?
- __ jccb(Assembler::belowEqual, std_cpuid1);
+ __ cmpl(rax, 0xa); // Is cpuid(0xB) supported?
+ __ jccb(Assembler::belowEqual, std_cpuid4);
+
+ //
+ // cpuid(0xB) Processor Topology
+ //
+ __ movl(rax, 0xb);
+ __ xorl(rcx, rcx); // Threads level
+ __ cpuid();
+
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset())));
+ __ movl(Address(rsi, 0), rax);
+ __ movl(Address(rsi, 4), rbx);
+ __ movl(Address(rsi, 8), rcx);
+ __ movl(Address(rsi,12), rdx);
+
+ __ movl(rax, 0xb);
+ __ movl(rcx, 1); // Cores level
+ __ cpuid();
+ __ push(rax);
+ __ andl(rax, 0x1f); // Determine if valid topology level
+ __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level
+ __ andl(rax, 0xffff);
+ __ pop(rax);
+ __ jccb(Assembler::equal, std_cpuid4);
+
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset())));
+ __ movl(Address(rsi, 0), rax);
+ __ movl(Address(rsi, 4), rbx);
+ __ movl(Address(rsi, 8), rcx);
+ __ movl(Address(rsi,12), rdx);
+
+ __ movl(rax, 0xb);
+ __ movl(rcx, 2); // Packages level
+ __ cpuid();
+ __ push(rax);
+ __ andl(rax, 0x1f); // Determine if valid topology level
+ __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level
+ __ andl(rax, 0xffff);
+ __ pop(rax);
+ __ jccb(Assembler::equal, std_cpuid4);
+
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset())));
+ __ movl(Address(rsi, 0), rax);
+ __ movl(Address(rsi, 4), rbx);
+ __ movl(Address(rsi, 8), rcx);
+ __ movl(Address(rsi,12), rdx);
//
// cpuid(0x4) Deterministic cache params
//
+ __ bind(std_cpuid4);
__ movl(rax, 4);
+ __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported?
+ __ jccb(Assembler::greater, std_cpuid1);
+
__ xorl(rcx, rcx); // L1 cache
__ cpuid();
__ push(rax);
@@ -460,13 +509,18 @@
AllocatePrefetchDistance = allocate_prefetch_distance();
AllocatePrefetchStyle = allocate_prefetch_style();
- if( AllocatePrefetchStyle == 2 && is_intel() &&
- cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
+ if( is_intel() && cpu_family() == 6 && supports_sse3() ) {
+ if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core
#ifdef _LP64
- AllocatePrefetchDistance = 384;
+ AllocatePrefetchDistance = 384;
#else
- AllocatePrefetchDistance = 320;
+ AllocatePrefetchDistance = 320;
#endif
+ }
+ if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus
+ AllocatePrefetchDistance = 192;
+ AllocatePrefetchLines = 4;
+ }
}
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,6 +114,14 @@
} bits;
};
+ union TplCpuidBEbx {
+ uint32_t value;
+ struct {
+ uint32_t logical_cpus : 16,
+ : 16;
+ } bits;
+ };
+
union ExtCpuid1Ecx {
uint32_t value;
struct {
@@ -211,6 +219,25 @@
uint32_t dcp_cpuid4_ecx; // unused currently
uint32_t dcp_cpuid4_edx; // unused currently
+ // cpuid function 0xB (processor topology)
+ // ecx = 0
+ uint32_t tpl_cpuidB0_eax;
+ TplCpuidBEbx tpl_cpuidB0_ebx;
+ uint32_t tpl_cpuidB0_ecx; // unused currently
+ uint32_t tpl_cpuidB0_edx; // unused currently
+
+ // ecx = 1
+ uint32_t tpl_cpuidB1_eax;
+ TplCpuidBEbx tpl_cpuidB1_ebx;
+ uint32_t tpl_cpuidB1_ecx; // unused currently
+ uint32_t tpl_cpuidB1_edx; // unused currently
+
+ // ecx = 2
+ uint32_t tpl_cpuidB2_eax;
+ TplCpuidBEbx tpl_cpuidB2_ebx;
+ uint32_t tpl_cpuidB2_ecx; // unused currently
+ uint32_t tpl_cpuidB2_edx; // unused currently
+
// cpuid function 0x80000000 // example, unused
uint32_t ext_max_function;
uint32_t ext_vendor_name_0;
@@ -316,6 +343,9 @@
static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
+ static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
+ static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
+ static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
// Initialization
static void initialize();
@@ -346,10 +376,22 @@
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
+ static bool supports_processor_topology() {
+ return (_cpuid_info.std_max_function >= 0xB) &&
+ // eax[4:0] | ebx[0:15] == 0 indicates invalid topology level.
+ // Some cpus have max cpuid >= 0xB but do not support processor topology.
+ ((_cpuid_info.tpl_cpuidB0_eax & 0x1f | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
+ }
+
static uint cores_per_cpu() {
uint result = 1;
if (is_intel()) {
- result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
+ if (supports_processor_topology()) {
+ result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
+ _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
+ } else {
+ result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
+ }
} else if (is_amd()) {
result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
}
@@ -358,7 +400,9 @@
static uint threads_per_core() {
uint result = 1;
- if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
+ if (is_intel() && supports_processor_topology()) {
+ result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
+ } else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
cores_per_cpu();
}
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -820,7 +820,7 @@
bool is_top_frame) {
assert(popframe_extra_args == 0, "what to do?");
assert(!is_top_frame || (!callee_locals && !callee_param_count),
- "top frame should have no caller")
+ "top frame should have no caller");
// This code must exactly match what InterpreterFrame::build
// does (the full InterpreterFrame::build, that is, not the
--- a/hotspot/src/os/linux/vm/os_linux.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -2079,9 +2079,9 @@
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm.so or libjvm_g.so
-void os::jvm_path(char *buf, jint len) {
+void os::jvm_path(char *buf, jint buflen) {
// Error checking.
- if (len < MAXPATHLEN) {
+ if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
@@ -2117,6 +2117,9 @@
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != NULL && java_home_var[0] != 0) {
+ char* jrelib_p;
+ int len;
+
// Check the current module name "libjvm.so" or "libjvm_g.so".
p = strrchr(buf, '/');
assert(strstr(p, "/libjvm") == p, "invalid library name");
@@ -2124,14 +2127,24 @@
if (realpath(java_home_var, buf) == NULL)
return;
- sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+
+ // determine if this is a legacy image or modules image
+ // modules image doesn't have "jre" subdirectory
+ len = strlen(buf);
+ jrelib_p = buf + len;
+ snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+ if (0 != access(buf, F_OK)) {
+ snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+ }
+
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm[_g].so" instead of
// "libjvm"debug_only("_g")".so" since for fastdebug version
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
// It is used when we are choosing the HPI library's name
// "libhpi[_g].so" in hpi::initialize_get_interface().
- sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+ len = strlen(buf);
+ snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
} else {
// Go back to path of .so
if (realpath(dli_fname, buf) == NULL)
--- a/hotspot/src/os/linux/vm/vtune_linux.cpp Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_linux.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
-
-
-// Reconciliation History
-// vtune_solaris.cpp 1.8 99/07/12 23:54:21
-// End
--- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -123,7 +123,7 @@
int set_interrupt_callback (Sync_Interrupt_Callback * cb);
void remove_interrupt_callback(Sync_Interrupt_Callback * cb);
- void OSThread::do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
+ void do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
// ***************************************************************
// java.lang.Thread.interrupt state.
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -2435,6 +2435,8 @@
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != NULL && java_home_var[0] != 0) {
char cpu_arch[12];
+ char* jrelib_p;
+ int len;
sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch));
#ifdef _LP64
// If we are on sparc running a 64-bit vm, look in jre/lib/sparcv9.
@@ -2450,14 +2452,23 @@
p = strstr(p, "_g") ? "_g" : "";
realpath(java_home_var, buf);
- sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+ // determine if this is a legacy image or modules image
+ // modules image doesn't have "jre" subdirectory
+ len = strlen(buf);
+ jrelib_p = buf + len;
+ snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+ if (0 != access(buf, F_OK)) {
+ snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+ }
+
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm[_g].so" instead of
// "libjvm"debug_only("_g")".so" since for fastdebug version
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
// It is used when we are choosing the HPI library's name
// "libhpi[_g].so" in hpi::initialize_get_interface().
- sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+ len = strlen(buf);
+ snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
} else {
// Go back to path of .so
realpath((char *)dlinfo.dli_fname, buf);
--- a/hotspot/src/os/solaris/vm/vtune_solaris.cpp Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_solaris.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
--- a/hotspot/src/os/windows/vm/vtune_windows.cpp Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_windows.cpp.incl"
-
-static int current_method_ID = 0;
-
-// ------------- iJITProf.h -------------------
-// defined by Intel -- do not change
-
-#include "windows.h"
-
-extern "C" {
- enum iJITP_Event {
- ExceptionOccurred_S, // Java exception
- ExceptionOccurred_IDS,
-
- Shutdown, // VM exit
-
- ThreadCreate, // threads
- ThreadDestroy,
- ThreadSwitch,
-
- ClassLoadStart, // class loading
- ClassLoadEnd,
-
- GCStart, // GC
- GCEnd,
-
- NMethodCreate = 13, // nmethod creation
- NMethodDelete
-
- // rest of event types omitted (call profiling not supported yet)
- };
-
- // version number -- 0 if VTune not installed
- int WINAPI iJitP_VersionNumber();
-
- enum iJITP_ModeFlags {
- NoNotification = 0x0, // don't call vtune
- NotifyNMethodCreate = 0x1, // notify NMethod_Create
- NotifyNMethodDelete = 0x2, // notify NMethod_Create
- NotifyMethodEnter = 0x4, // method entry
- NotifyMethodExit = 0x8, // method exit
- NotifyShutdown = 0x10, // VM exit
- NotifyGC = 0x20, // GC
- };
-
- // call back function type
- typedef void (WINAPI *ModeChangedFn)(iJITP_ModeFlags flags);
-
- // ------------- VTune method interfaces ----------------------
- typedef void (WINAPI *RegisterCallbackFn)(ModeChangedFn fn); // register callback
- typedef int (WINAPI *NotifyEventFn)(iJITP_Event, void* event_data);
-
- // specific event data structures
-
- // data for NMethodCreate
-
- struct VTuneObj { // base class for allocation
- // (can't use CHeapObj -- has vtable ptr)
- void* operator new(size_t size) { return os::malloc(size); }
- void operator delete(void* p) { fatal("never delete VTune data"); }
- };
-
- struct LineNumberInfo : VTuneObj { // PC-to-line number mapping
- unsigned long offset; // byte offset from start of method
- unsigned long line_num; // corresponding line number
- };
-
- struct MethodLoadInfo : VTuneObj {
- unsigned long methodID; // unique method ID
- const char* name; // method name
- unsigned long instr_start; // start address
- unsigned long instr_size; // length in bytes
- unsigned long line_number_size; // size of line number table
- LineNumberInfo* line_number_table; // line number mapping
- unsigned long classID; // unique class ID
- char* class_file_name; // fully qualified class file name
- char* source_file_name; // fully qualified source file name
-
- MethodLoadInfo(nmethod* nm); // for real nmethods
- MethodLoadInfo(const char* vm_name, address start, address end);
- // for "nmethods" like stubs, interpreter, etc
-
- };
-
- // data for NMethodDelete
- struct MethodInfo : VTuneObj {
- unsigned long methodID; // unique method ID
- unsigned long classID; // (added for convenience -- not part of Intel interface)
-
- MethodInfo(methodOop m);
- };
-};
-
-MethodInfo::MethodInfo(methodOop m) {
- // just give it a new ID -- we're not compiling methods twice (usually)
- // (and even if we did, one might want to see the two versions separately)
- methodID = ++current_method_ID;
-}
-
-MethodLoadInfo::MethodLoadInfo(const char* vm_name, address start, address end) {
- classID = 0;
- methodID = ++current_method_ID;
- name = vm_name;
- instr_start = (unsigned long)start;
- instr_size = end - start;
- line_number_size = 0;
- line_number_table = NULL;
- class_file_name = source_file_name = "HotSpot JVM";
-}
-
-MethodLoadInfo::MethodLoadInfo(nmethod* nm) {
- methodOop m = nm->method();
- MethodInfo info(m);
- classID = info.classID;
- methodID = info.methodID;
- name = strdup(m->name()->as_C_string());
- instr_start = (unsigned long)nm->instructions_begin();
- instr_size = nm->code_size();
- line_number_size = 0;
- line_number_table = NULL;
- klassOop kl = m->method_holder();
- char* class_name = Klass::cast(kl)->name()->as_C_string();
- char* file_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + 1);
- strcpy(file_name, class_name);
- class_file_name = file_name;
- char* src_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + strlen(".java") + 1);
- strcpy(src_name, class_name);
- strcat(src_name, ".java");
- source_file_name = src_name;
-}
-
-// --------------------- DLL loading functions ------------------------
-
-#define DLLNAME "iJitProf.dll"
-
-static HINSTANCE load_lib(char* name) {
- HINSTANCE lib = NULL;
- HKEY hk;
-
- // try to get VTune directory from the registry
- if (RegOpenKey(HKEY_CURRENT_USER, "Software\\VB and VBA Program Settings\\VTune\\StartUp", &hk) == ERROR_SUCCESS) {
- for (int i = 0; true; i++) {
- char szName[MAX_PATH + 1];
- char szVal [MAX_PATH + 1];
- DWORD cbName, cbVal;
-
- cbName = cbVal = MAX_PATH + 1;
- if (RegEnumValue(hk, i, szName, &cbName, NULL, NULL, (LPBYTE)szVal, &cbVal) == ERROR_SUCCESS) {
- // get VTune directory
- if (!strcmp(szName, name)) {
- char*p = szVal;
- while (*p == ' ') p++; // trim
- char* q = p + strlen(p) - 1;
- while (*q == ' ') *(q--) = '\0';
-
- // chdir to the VTune dir
- GetCurrentDirectory(MAX_PATH + 1, szName);
- SetCurrentDirectory(p);
- // load lib
- lib = LoadLibrary(strcat(strcat(p, "\\"), DLLNAME));
- if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s", p);
- // restore current dir
- SetCurrentDirectory(szName);
- break;
- }
- } else {
- break;
- }
- }
- }
- return lib;
-}
-
-static RegisterCallbackFn iJIT_RegisterCallback = NULL;
-static NotifyEventFn iJIT_NotifyEvent = NULL;
-
-static bool load_iJIT_funcs() {
- // first try to load from PATH
- HINSTANCE lib = LoadLibrary(DLLNAME);
- if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s via PATH", DLLNAME);
-
- // if not successful, try to look in the VTUNE directory
- if (lib == NULL) lib = load_lib("VTUNEDIR30");
- if (lib == NULL) lib = load_lib("VTUNEDIR25");
- if (lib == NULL) lib = load_lib("VTUNEDIR");
-
- if (lib == NULL) return false; // unsuccessful
-
- // try to load the functions
- iJIT_RegisterCallback = (RegisterCallbackFn)GetProcAddress(lib, "iJIT_RegisterCallback");
- iJIT_NotifyEvent = (NotifyEventFn) GetProcAddress(lib, "iJIT_NotifyEvent");
-
- if (!iJIT_RegisterCallback) tty->print_cr("*couldn't find VTune entry point iJIT_RegisterCallback");
- if (!iJIT_NotifyEvent) tty->print_cr("*couldn't find VTune entry point iJIT_NotifyEvent");
- return iJIT_RegisterCallback != NULL && iJIT_NotifyEvent != NULL;
-}
-
-// --------------------- VTune class ------------------------
-
-static bool active = false;
-static int flags = 0;
-
-void VTune::start_GC() {
- if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCStart, NULL);
-}
-
-void VTune::end_GC() {
- if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCEnd, NULL);
-}
-
-void VTune::start_class_load() {
- // not yet implemented in VTune
-}
-
-void VTune::end_class_load() {
- // not yet implemented in VTune
-}
-
-void VTune::exit() {
- if (active && (flags & NotifyShutdown)) iJIT_NotifyEvent(Shutdown, NULL);
-}
-
-void VTune::register_stub(const char* name, address start, address end) {
- if (flags & NotifyNMethodCreate) {
- MethodLoadInfo* info = new MethodLoadInfo(name, start, end);
- if (PrintMiscellaneous && WizardMode && Verbose) {
- tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
- info->instr_start, info->instr_start + info->instr_size);
- }
- iJIT_NotifyEvent(NMethodCreate, info);
- }
-}
-
-void VTune::create_nmethod(nmethod* nm) {
- if (flags & NotifyNMethodCreate) {
- MethodLoadInfo* info = new MethodLoadInfo(nm);
- if (PrintMiscellaneous && WizardMode && Verbose) {
- tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
- info->instr_start, info->instr_start + info->instr_size);
- }
- iJIT_NotifyEvent(NMethodCreate, info);
- }
-}
-
-void VTune::delete_nmethod(nmethod* nm) {
- if (flags & NotifyNMethodDelete) {
- MethodInfo* info = new MethodInfo(nm->method());
- iJIT_NotifyEvent(NMethodDelete, info);
- }
-}
-
-static void set_flags(int new_flags) {
- flags = new_flags;
- // if (WizardMode) tty->print_cr("*new VTune flags: %#x", flags);
-}
-
-void vtune_init() {
- if (!UseVTune) return;
- active = load_iJIT_funcs();
- if (active) {
- iJIT_RegisterCallback((ModeChangedFn)set_flags);
- } else {
- assert(flags == 0, "flags shouldn't be set");
- }
-}
--- a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -26,7 +26,7 @@
#ifdef AMD64
(void)memmove(to, from, count * HeapWordSize);
#else
- // Same as pd_aligned_conjoint_words, except includes a zero-count check.
+ // Includes a zero-count check.
intx temp;
__asm__ volatile(" testl %6,%6 ;"
" jz 7f ;"
@@ -84,7 +84,7 @@
break;
}
#else
- // Same as pd_aligned_disjoint_words, except includes a zero-count check.
+ // Includes a zero-count check.
intx temp;
__asm__ volatile(" testl %6,%6 ;"
" jz 3f ;"
@@ -130,75 +130,18 @@
}
static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
-#ifdef AMD64
- (void)memmove(to, from, count * HeapWordSize);
-#else
- // Same as pd_conjoint_words, except no zero-count check.
- intx temp;
- __asm__ volatile(" cmpl %4,%5 ;"
- " leal -4(%4,%6,4),%3;"
- " jbe 1f ;"
- " cmpl %7,%5 ;"
- " jbe 4f ;"
- "1: cmpl $32,%6 ;"
- " ja 3f ;"
- " subl %4,%1 ;"
- "2: movl (%4),%3 ;"
- " movl %7,(%5,%4,1) ;"
- " addl $4,%0 ;"
- " subl $1,%2 ;"
- " jnz 2b ;"
- " jmp 7f ;"
- "3: rep; smovl ;"
- " jmp 7f ;"
- "4: cmpl $32,%2 ;"
- " movl %7,%0 ;"
- " leal -4(%5,%6,4),%1;"
- " ja 6f ;"
- " subl %4,%1 ;"
- "5: movl (%4),%3 ;"
- " movl %7,(%5,%4,1) ;"
- " subl $4,%0 ;"
- " subl $1,%2 ;"
- " jnz 5b ;"
- " jmp 7f ;"
- "6: std ;"
- " rep; smovl ;"
- " cld ;"
- "7: nop "
- : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
- : "0" (from), "1" (to), "2" (count), "3" (temp)
- : "memory", "flags");
-#endif // AMD64
+ pd_conjoint_words(from, to, count);
}
static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
-#ifdef AMD64
pd_disjoint_words(from, to, count);
-#else
- // Same as pd_disjoint_words, except no zero-count check.
- intx temp;
- __asm__ volatile(" cmpl $32,%6 ;"
- " ja 2f ;"
- " subl %4,%1 ;"
- "1: movl (%4),%3 ;"
- " movl %7,(%5,%4,1);"
- " addl $4,%0 ;"
- " subl $1,%2 ;"
- " jnz 1b ;"
- " jmp 3f ;"
- "2: rep; smovl ;"
- "3: nop "
- : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
- : "0" (from), "1" (to), "2" (count), "3" (temp)
- : "memory", "cc");
-#endif // AMD64
}
static void pd_conjoint_bytes(void* from, void* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count);
#else
+ // Includes a zero-count check.
intx temp;
__asm__ volatile(" testl %6,%6 ;"
" jz 13f ;"
--- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Wed Jul 05 17:18:01 2017 +0200
@@ -121,10 +121,10 @@
jnz 3b
addl %esi,%edi
4: movl %eax,%ecx # byte count less prefix
- andl $3,%ecx # suffix byte count
+5: andl $3,%ecx # suffix byte count
jz 7f # no suffix
# copy suffix
-5: xorl %eax,%eax
+ xorl %eax,%eax
6: movb (%esi,%eax,1),%dl
movb %dl,(%edi,%eax,1)
addl $1,%eax
@@ -159,10 +159,10 @@
# copy dwords, aligned or not
3: rep; smovl
4: movl %eax,%ecx # byte count
- andl $3,%ecx # suffix byte count
+5: andl $3,%ecx # suffix byte count
jz 7f # no suffix
# copy suffix
-5: subl %esi,%edi
+ subl %esi,%edi
addl $3,%esi
6: movb (%esi),%dl
movb %dl,(%edi,%esi,1)
@@ -214,10 +214,10 @@
# copy aligned dwords
3: rep; smovl
4: movl %eax,%ecx
- andl $3,%ecx
+5: andl $3,%ecx
jz 7f
# copy suffix
-5: xorl %eax,%eax
+ xorl %eax,%eax
6: movb (%esi,%eax,1),%dl
movb %dl,(%edi,%eax,1)
addl $1,%eax
@@ -250,9 +250,9 @@
jnz 3b
addl %esi,%edi
4: movl %eax,%ecx
- andl $3,%ecx
+5: andl $3,%ecx
jz 7f
-5: subl %esi,%edi
+ subl %esi,%edi
addl $3,%esi
6: movb (%esi),%dl
movb %dl,(%edi,%esi,1)
@@ -287,11 +287,12 @@
andl $3,%eax # either 0 or 2
jz 1f # no prefix
# copy prefix
+ subl $1,%ecx
+ jl 5f # zero count
movw (%esi),%dx
movw %dx,(%edi)
addl %eax,%esi # %eax == 2
addl %eax,%edi
- subl $1,%ecx
1: movl %ecx,%eax # word count less prefix
sarl %ecx # dword count
jz 4f # no dwords to move
@@ -454,12 +455,13 @@
ret
.=.+10
2: subl %esi,%edi
+ jmp 4f
.p2align 4,,15
3: movl (%esi),%edx
movl %edx,(%edi,%esi,1)
addl $4,%esi
- subl $1,%ecx
- jnz 3b
+4: subl $1,%ecx
+ jge 3b
popl %edi
popl %esi
ret
@@ -467,19 +469,20 @@
std
leal -4(%edi,%ecx,4),%edi # to + count*4 - 4
cmpl $32,%ecx
- ja 3f # > 32 dwords
+ ja 4f # > 32 dwords
subl %eax,%edi # eax == from + count*4 - 4
+ jmp 3f
.p2align 4,,15
2: movl (%eax),%edx
movl %edx,(%edi,%eax,1)
subl $4,%eax
- subl $1,%ecx
- jnz 2b
+3: subl $1,%ecx
+ jge 2b
cld
popl %edi
popl %esi
ret
-3: movl %eax,%esi # from + count*4 - 4
+4: movl %eax,%esi # from + count*4 - 4
rep; smovl
cld
popl %edi
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -861,7 +861,7 @@
cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
-extern "C" _solaris_raw_setup_fpu(address ptr);
+extern "C" void _solaris_raw_setup_fpu(address ptr);
void os::setup_fpu() {
address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
_solaris_raw_setup_fpu(fpu_cntrl);
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Wed Jul 05 17:18:01 2017 +0200
@@ -154,10 +154,10 @@
jnz 3b
addl %esi,%edi
4: movl %eax,%ecx / byte count less prefix
- andl $3,%ecx / suffix byte count
+5: andl $3,%ecx / suffix byte count
jz 7f / no suffix
/ copy suffix
-5: xorl %eax,%eax
+ xorl %eax,%eax
6: movb (%esi,%eax,1),%dl
movb %dl,(%edi,%eax,1)
addl $1,%eax
@@ -192,10 +192,10 @@
/ copy dwords, aligned or not
3: rep; smovl
4: movl %eax,%ecx / byte count
- andl $3,%ecx / suffix byte count
+5: andl $3,%ecx / suffix byte count
jz 7f / no suffix
/ copy suffix
-5: subl %esi,%edi
+ subl %esi,%edi
addl $3,%esi
6: movb (%esi),%dl
movb %dl,(%edi,%esi,1)
@@ -246,10 +246,10 @@
/ copy aligned dwords
3: rep; smovl
4: movl %eax,%ecx
- andl $3,%ecx
+5: andl $3,%ecx
jz 7f
/ copy suffix
-5: xorl %eax,%eax
+ xorl %eax,%eax
6: movb (%esi,%eax,1),%dl
movb %dl,(%edi,%eax,1)
addl $1,%eax
@@ -282,9 +282,9 @@
jnz 3b
addl %esi,%edi
4: movl %eax,%ecx
- andl $3,%ecx
+5: andl $3,%ecx
jz 7f
-5: subl %esi,%edi
+ subl %esi,%edi
addl $3,%esi
6: movb (%esi),%dl
movb %dl,(%edi,%esi,1)
@@ -318,11 +318,12 @@
andl $3,%eax / either 0 or 2
jz 1f / no prefix
/ copy prefix
+ subl $1,%ecx
+ jl 5f / zero count
movw (%esi),%dx
movw %dx,(%edi)
addl %eax,%esi / %eax == 2
addl %eax,%edi
- subl $1,%ecx
1: movl %ecx,%eax / word count less prefix
sarl %ecx / dword count
jz 4f / no dwords to move
@@ -482,12 +483,13 @@
ret
.=.+10
2: subl %esi,%edi
+ jmp 4f
.align 16
3: movl (%esi),%edx
movl %edx,(%edi,%esi,1)
addl $4,%esi
- subl $1,%ecx
- jnz 3b
+4: subl $1,%ecx
+ jge 3b
popl %edi
popl %esi
ret
@@ -495,19 +497,20 @@
std
leal -4(%edi,%ecx,4),%edi / to + count*4 - 4
cmpl $32,%ecx
- ja 3f / > 32 dwords
+ ja 4f / > 32 dwords
subl %eax,%edi / eax == from + count*4 - 4
+ jmp 3f
.align 16
2: movl (%eax),%edx
movl %edx,(%edi,%eax,1)
subl $4,%eax
- subl $1,%ecx
- jnz 2b
+3: subl $1,%ecx
+ jge 2b
cld
popl %edi
popl %esi
ret
-3: movl %eax,%esi / from + count*4 - 4
+4: movl %eax,%esi / from + count*4 - 4
rep; smovl
cld
popl %edi
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -404,7 +404,7 @@
locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
} else {
locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
- Copy::conjoint_bytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
+ Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
_locs_own = true;
}
_locs_start = locs_start;
@@ -581,7 +581,7 @@
(HeapWord*)(buf+buf_offset),
(lsize + HeapWordSize-1) / HeapWordSize);
} else {
- Copy::conjoint_bytes(lstart, buf+buf_offset, lsize);
+ Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize);
}
}
buf_offset += lsize;
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -242,10 +242,10 @@
code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
locs_buffer_size / sizeof(relocInfo));
code->initialize_consts_size(Compilation::desired_max_constant_size());
- // Call stubs + deopt/exception handler
+ // Call stubs + two deopt handlers (regular and MH) + exception handler
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
LIR_Assembler::exception_handler_size +
- LIR_Assembler::deopt_handler_size);
+ 2 * LIR_Assembler::deopt_handler_size);
}
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -878,15 +878,12 @@
case T_OBJECT :
{
ciObject* obj = con.as_object();
- if (obj->is_klass()) {
- ciKlass* klass = obj->as_klass();
- if (!klass->is_loaded() || PatchALot) {
- patch_state = state()->copy();
- t = new ObjectConstant(obj);
- } else {
- t = new InstanceConstant(klass->java_mirror());
- }
+ if (!obj->is_loaded()
+ || (PatchALot && obj->klass() != ciEnv::current()->String_klass())) {
+ patch_state = state()->copy();
+ t = new ObjectConstant(obj);
} else {
+ assert(!obj->is_klass(), "must be java_mirror of klass");
t = new InstanceConstant(obj->as_instance());
}
break;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -601,7 +601,7 @@
static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
- Bytecode_field* field_access = Bytecode_field_at(caller(), caller->bcp_from(bci));
+ Bytecode_field* field_access = Bytecode_field_at(caller, bci);
// This can be static or non-static field access
Bytecodes::Code code = field_access->code();
@@ -721,7 +721,7 @@
Handle load_klass(THREAD, NULL); // oop needed by load_klass_patching code
if (stub_id == Runtime1::access_field_patching_id) {
- Bytecode_field* field_access = Bytecode_field_at(caller_method(), caller_method->bcp_from(bci));
+ Bytecode_field* field_access = Bytecode_field_at(caller_method, bci);
FieldAccessInfo result; // initialize class if needed
Bytecodes::Code code = field_access->code();
constantPoolHandle constants(THREAD, caller_method->constants());
@@ -781,11 +781,9 @@
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
{
- Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method(),
- caller_method->bcp_from(bci));
- klassOop resolved = caller_method->constants()->klass_at(cc->index(), CHECK);
- // ldc wants the java mirror.
- k = resolved->klass_part()->java_mirror();
+ Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci);
+ k = cc->resolve_constant(CHECK);
+ assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
}
break;
default: Unimplemented();
@@ -816,6 +814,15 @@
// Return to the now deoptimized frame.
}
+ // If we are patching in a non-perm oop, make sure the nmethod
+ // is on the right list.
+ if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) {
+ MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
+ guarantee(nm != NULL, "only nmethods can contain non-perm oops");
+ if (!nm->on_scavenge_root_list())
+ CodeCache::add_scavenge_root_nmethod(nm);
+ }
// Now copy code back
@@ -1115,7 +1122,7 @@
if (length == 0) return;
// Not guaranteed to be word atomic, but that doesn't matter
// for anything but an oop array, which is covered by oop_arraycopy.
- Copy::conjoint_bytes(src, dst, length);
+ Copy::conjoint_jbytes(src, dst, length);
JRT_END
JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -106,7 +106,7 @@
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i))
- _arg_returned.set_bit(i);
+ _arg_returned.set(i);
}
_return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
@@ -126,16 +126,16 @@
if (_conservative)
return true;
for (int i = 0; i < _arg_size; i++) {
- if (vars.contains(i) && _arg_stack.at(i))
+ if (vars.contains(i) && _arg_stack.test(i))
return true;
}
return false;
}
-void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
+void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
- bm.clear_bit(i);
+ bm >>= i;
}
}
}
@@ -1157,15 +1157,15 @@
ciSignature* sig = method()->signature();
int j = 0;
if (!method()->is_static()) {
- _arg_local.set_bit(0);
- _arg_stack.set_bit(0);
+ _arg_local.set(0);
+ _arg_stack.set(0);
j++;
}
for (i = 0; i < sig->count(); i++) {
ciType* t = sig->type_at(i);
if (!t->is_primitive_type()) {
- _arg_local.set_bit(j);
- _arg_stack.set_bit(j);
+ _arg_local.set(j);
+ _arg_stack.set(j);
}
j += t->size();
}
@@ -1198,9 +1198,9 @@
set_modified(var, OFFSET_ANY, 4);
set_global_escape(var);
}
- _arg_local.clear();
- _arg_stack.clear();
- _arg_returned.clear();
+ _arg_local.Clear();
+ _arg_stack.Clear();
+ _arg_returned.Clear();
_return_local = false;
_return_allocated = false;
_allocated_escapes = true;
@@ -1254,7 +1254,7 @@
// Do not scan method if it has no object parameters and
// does not returns an object (_return_allocated is set in initialize()).
- if (_arg_local.is_empty() && !_return_allocated) {
+ if (_arg_local.Size() == 0 && !_return_allocated) {
// Clear all info since method's bytecode was not analysed and
// set pessimistic escape information.
clear_escape_info();
@@ -1275,14 +1275,14 @@
//
if (!has_dependencies() && !methodData()->is_empty()) {
for (i = 0; i < _arg_size; i++) {
- if (_arg_local.at(i)) {
- assert(_arg_stack.at(i), "inconsistent escape info");
+ if (_arg_local.test(i)) {
+ assert(_arg_stack.test(i), "inconsistent escape info");
methodData()->set_arg_local(i);
methodData()->set_arg_stack(i);
- } else if (_arg_stack.at(i)) {
+ } else if (_arg_stack.test(i)) {
methodData()->set_arg_stack(i);
}
- if (_arg_returned.at(i)) {
+ if (_arg_returned.test(i)) {
methodData()->set_arg_returned(i);
}
methodData()->set_arg_modified(i, _arg_modified[i]);
@@ -1308,9 +1308,12 @@
// read escape information from method descriptor
for (int i = 0; i < _arg_size; i++) {
- _arg_local.at_put(i, methodData()->is_arg_local(i));
- _arg_stack.at_put(i, methodData()->is_arg_stack(i));
- _arg_returned.at_put(i, methodData()->is_arg_returned(i));
+ if (methodData()->is_arg_local(i))
+ _arg_local.set(i);
+ if (methodData()->is_arg_stack(i))
+ _arg_stack.set(i);
+ if (methodData()->is_arg_returned(i))
+ _arg_returned.set(i);
_arg_modified[i] = methodData()->arg_modified(i);
}
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
@@ -1358,26 +1361,26 @@
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
: _conservative(method == NULL || !EstimateArgEscape)
+ , _arena(CURRENT_ENV->arena())
, _method(method)
, _methodData(method ? method->method_data() : NULL)
, _arg_size(method ? method->arg_size() : 0)
- , _stack()
- , _arg_local(_arg_size)
- , _arg_stack(_arg_size)
- , _arg_returned(_arg_size)
- , _dirty(_arg_size)
+ , _arg_local(_arena)
+ , _arg_stack(_arena)
+ , _arg_returned(_arena)
+ , _dirty(_arena)
, _return_local(false)
, _return_allocated(false)
, _allocated_escapes(false)
, _unknown_modified(false)
- , _dependencies()
+ , _dependencies(_arena, 4, 0, NULL)
, _parent(parent)
, _level(parent == NULL ? 0 : parent->level() + 1) {
if (!_conservative) {
- _arg_local.clear();
- _arg_stack.clear();
- _arg_returned.clear();
- _dirty.clear();
+ _arg_local.Clear();
+ _arg_stack.Clear();
+ _arg_returned.Clear();
+ _dirty.Clear();
Arena* arena = CURRENT_ENV->arena();
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
@@ -1414,8 +1417,8 @@
deps->assert_evol_method(method());
}
for (int i = 0; i < _dependencies.length(); i+=2) {
- ciKlass *k = _dependencies[i]->as_klass();
- ciMethod *m = _dependencies[i+1]->as_method();
+ ciKlass *k = _dependencies.at(i)->as_klass();
+ ciMethod *m = _dependencies.at(i+1)->as_method();
deps->assert_unique_concrete_method(k, m);
}
}
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -22,9 +22,6 @@
*
*/
-define_array(ciObjectArray, ciObject*);
-define_stack(ciObjectList, ciObjectArray);
-
// This class implements a fast, conservative analysis of effect of methods
// on the escape state of their arguments. The analysis is at the bytecode
// level.
@@ -34,18 +31,17 @@
class BCEscapeAnalyzer : public ResourceObj {
private:
+ Arena* _arena; // ciEnv arena
+
bool _conservative; // If true, return maximally
// conservative results.
ciMethod* _method;
ciMethodData* _methodData;
int _arg_size;
-
- intStack _stack;
-
- BitMap _arg_local;
- BitMap _arg_stack;
- BitMap _arg_returned;
- BitMap _dirty;
+ VectorSet _arg_local;
+ VectorSet _arg_stack;
+ VectorSet _arg_returned;
+ VectorSet _dirty;
enum{ ARG_OFFSET_MAX = 31};
uint *_arg_modified;
@@ -54,7 +50,7 @@
bool _allocated_escapes;
bool _unknown_modified;
- ciObjectList _dependencies;
+ GrowableArray<ciObject *> _dependencies;
ciMethodBlocks *_methodBlocks;
@@ -68,20 +64,10 @@
private:
// helper functions
bool is_argument(int i) { return i >= 0 && i < _arg_size; }
-
- void raw_push(int i) { _stack.push(i); }
- int raw_pop() { return _stack.is_empty() ? -1 : _stack.pop(); }
- void apush(int i) { raw_push(i); }
- void spush() { raw_push(-1); }
- void lpush() { spush(); spush(); }
- int apop() { return raw_pop(); }
- void spop() { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); }
- void lpop() { spop(); spop(); }
-
void set_returned(ArgumentMap vars);
bool is_argument(ArgumentMap vars);
bool is_arg_stack(ArgumentMap vars);
- void clear_bits(ArgumentMap vars, BitMap &bs);
+ void clear_bits(ArgumentMap vars, VectorSet &bs);
void set_method_escape(ArgumentMap vars);
void set_global_escape(ArgumentMap vars);
void set_dirty(ArgumentMap vars);
@@ -116,25 +102,25 @@
ciMethodData* methodData() const { return _methodData; }
BCEscapeAnalyzer* parent() const { return _parent; }
int level() const { return _level; }
- ciObjectList* dependencies() { return &_dependencies; }
+ GrowableArray<ciObject *>* dependencies() { return &_dependencies; }
bool has_dependencies() const { return !_dependencies.is_empty(); }
// retrieval of interprocedural escape information
// The given argument does not escape the callee.
bool is_arg_local(int i) const {
- return !_conservative && _arg_local.at(i);
+ return !_conservative && _arg_local.test(i);
}
// The given argument escapes the callee, but does not become globally
// reachable.
bool is_arg_stack(int i) const {
- return !_conservative && _arg_stack.at(i);
+ return !_conservative && _arg_stack.test(i);
}
// The given argument does not escape globally, and may be returned.
bool is_arg_returned(int i) const {
- return !_conservative && _arg_returned.at(i); }
+ return !_conservative && _arg_returned.test(i); }
// True iff only input arguments are returned.
bool is_return_local() const {
--- a/hotspot/src/share/vm/ci/ciCPCache.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciCPCache.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -44,13 +44,23 @@
// ciCPCache::is_f1_null_at
bool ciCPCache::is_f1_null_at(int index) {
VM_ENTRY_MARK;
- constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop();
- oop f1 = cpcache->secondary_entry_at(index)->f1();
+ oop f1 = entry_at(index)->f1();
return (f1 == NULL);
}
// ------------------------------------------------------------------
+// ciCPCache::get_pool_index
+int ciCPCache::get_pool_index(int index) {
+ VM_ENTRY_MARK;
+ ConstantPoolCacheEntry* e = entry_at(index);
+ if (e->is_secondary_entry())
+ e = entry_at(e->main_entry_index());
+ return e->constant_pool_index();
+}
+
+
+// ------------------------------------------------------------------
// ciCPCache::print
//
// Print debugging information about the cache.
--- a/hotspot/src/share/vm/ci/ciCPCache.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciCPCache.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -29,6 +29,18 @@
// Note: This class is called ciCPCache as ciConstantPoolCache is used
// for something different.
class ciCPCache : public ciObject {
+private:
+ constantPoolCacheOop get_cpCacheOop() { // must be called inside a VM_ENTRY_MARK
+ return (constantPoolCacheOop) get_oop();
+ }
+
+ ConstantPoolCacheEntry* entry_at(int i) {
+ int raw_index = i;
+ if (constantPoolCacheOopDesc::is_secondary_index(i))
+ raw_index = constantPoolCacheOopDesc::decode_secondary_index(i);
+ return get_cpCacheOop()->entry_at(raw_index);
+ }
+
public:
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
@@ -41,5 +53,7 @@
bool is_f1_null_at(int index);
+ int get_pool_index(int index);
+
void print();
};
--- a/hotspot/src/share/vm/ci/ciClassList.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciClassList.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -85,6 +85,7 @@
friend class ciConstantPoolCache; \
friend class ciField; \
friend class ciConstant; \
+friend class ciCPCache; \
friend class ciFlags; \
friend class ciExceptionHandler; \
friend class ciCallProfile; \
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -511,9 +511,22 @@
//
// Implementation of get_constant_by_index().
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
- int index,
+ int pool_index, int cache_index,
ciInstanceKlass* accessor) {
+ bool ignore_will_link;
EXCEPTION_CONTEXT;
+ int index = pool_index;
+ if (cache_index >= 0) {
+ assert(index < 0, "only one kind of index at a time");
+ ConstantPoolCacheEntry* cpc_entry = cpool->cache()->entry_at(cache_index);
+ index = cpc_entry->constant_pool_index();
+ oop obj = cpc_entry->f1();
+ if (obj != NULL) {
+ assert(obj->is_instance(), "must be an instance");
+ ciObject* ciobj = get_object(obj);
+ return ciConstant(T_OBJECT, ciobj);
+ }
+ }
constantTag tag = cpool->tag_at(index);
if (tag.is_int()) {
return ciConstant(T_INT, (jint)cpool->int_at(index));
@@ -540,8 +553,7 @@
return ciConstant(T_OBJECT, constant);
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
// 4881222: allow ldc to take a class type
- bool ignore;
- ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
+ ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
record_out_of_memory_failure();
@@ -549,12 +561,26 @@
}
assert (klass->is_instance_klass() || klass->is_array_klass(),
"must be an instance or array klass ");
- return ciConstant(T_OBJECT, klass);
+ return ciConstant(T_OBJECT, klass->java_mirror());
} else if (tag.is_object()) {
oop obj = cpool->object_at(index);
assert(obj->is_instance(), "must be an instance");
ciObject* ciobj = get_object(obj);
return ciConstant(T_OBJECT, ciobj);
+ } else if (tag.is_method_type()) {
+ // must execute Java code to link this CP entry into cache[i].f1
+ ciSymbol* signature = get_object(cpool->method_type_signature_at(index))->as_symbol();
+ ciObject* ciobj = get_unloaded_method_type_constant(signature);
+ return ciConstant(T_OBJECT, ciobj);
+ } else if (tag.is_method_handle()) {
+ // must execute Java code to link this CP entry into cache[i].f1
+ int ref_kind = cpool->method_handle_ref_kind_at(index);
+ int callee_index = cpool->method_handle_klass_index_at(index);
+ ciKlass* callee = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
+ ciSymbol* name = get_object(cpool->method_handle_name_ref_at(index))->as_symbol();
+ ciSymbol* signature = get_object(cpool->method_handle_signature_ref_at(index))->as_symbol();
+ ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
+ return ciConstant(T_OBJECT, ciobj);
} else {
ShouldNotReachHere();
return ciConstant();
@@ -562,61 +588,15 @@
}
// ------------------------------------------------------------------
-// ciEnv::is_unresolved_string_impl
-//
-// Implementation of is_unresolved_string().
-bool ciEnv::is_unresolved_string_impl(instanceKlass* accessor, int index) const {
- EXCEPTION_CONTEXT;
- assert(accessor->is_linked(), "must be linked before accessing constant pool");
- constantPoolOop cpool = accessor->constants();
- constantTag tag = cpool->tag_at(index);
- return tag.is_unresolved_string();
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_klass_impl
-//
-// Implementation of is_unresolved_klass().
-bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
- EXCEPTION_CONTEXT;
- assert(accessor->is_linked(), "must be linked before accessing constant pool");
- constantPoolOop cpool = accessor->constants();
- constantTag tag = cpool->tag_at(index);
- return tag.is_unresolved_klass();
-}
-
-// ------------------------------------------------------------------
// ciEnv::get_constant_by_index
//
// Pull a constant out of the constant pool. How appropriate.
//
// Implementation note: this query is currently in no way cached.
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
- int index,
+ int pool_index, int cache_index,
ciInstanceKlass* accessor) {
- GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_string
-//
-// Check constant pool
-//
-// Implementation note: this query is currently in no way cached.
-bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
- int index) const {
- GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); )
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_klass
-//
-// Check constant pool
-//
-// Implementation note: this query is currently in no way cached.
-bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor,
- int index) const {
- GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); )
+ GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);)
}
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -116,12 +116,8 @@
bool& is_accessible,
ciInstanceKlass* loading_klass);
ciConstant get_constant_by_index(constantPoolHandle cpool,
- int constant_index,
+ int pool_index, int cache_index,
ciInstanceKlass* accessor);
- bool is_unresolved_string(ciInstanceKlass* loading_klass,
- int constant_index) const;
- bool is_unresolved_klass(ciInstanceKlass* loading_klass,
- int constant_index) const;
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
int field_index);
ciMethod* get_method_by_index(constantPoolHandle cpool,
@@ -137,12 +133,8 @@
bool& is_accessible,
ciInstanceKlass* loading_klass);
ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
- int constant_index,
+ int pool_index, int cache_index,
ciInstanceKlass* loading_klass);
- bool is_unresolved_string_impl (instanceKlass* loading_klass,
- int constant_index) const;
- bool is_unresolved_klass_impl (instanceKlass* loading_klass,
- int constant_index) const;
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
int field_index);
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
@@ -190,6 +182,25 @@
return _factory->get_unloaded_klass(accessing_klass, name, true);
}
+ // Get a ciKlass representing an unloaded klass mirror.
+ // Result is not necessarily unique, but will be unloaded.
+ ciInstance* get_unloaded_klass_mirror(ciKlass* type) {
+ return _factory->get_unloaded_klass_mirror(type);
+ }
+
+ // Get a ciInstance representing an unresolved method handle constant.
+ ciInstance* get_unloaded_method_handle_constant(ciKlass* holder,
+ ciSymbol* name,
+ ciSymbol* signature,
+ int ref_kind) {
+ return _factory->get_unloaded_method_handle_constant(holder, name, signature, ref_kind);
+ }
+
+ // Get a ciInstance representing an unresolved method type constant.
+ ciInstance* get_unloaded_method_type_constant(ciSymbol* signature) {
+ return _factory->get_unloaded_method_type_constant(signature);
+ }
+
// See if we already have an unloaded klass for the given name
// or return NULL if not.
ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,9 +44,7 @@
_flags = ciFlags(access_flags);
_has_finalizer = access_flags.has_finalizer();
_has_subklass = ik->subklass() != NULL;
- _is_initialized = ik->is_initialized();
- // Next line must follow and use the result of the previous line:
- _is_linked = _is_initialized || ik->is_linked();
+ _init_state = (instanceKlass::ClassState)ik->get_init_state();
_nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
@@ -91,8 +89,7 @@
: ciKlass(name, ciInstanceKlassKlass::make())
{
assert(name->byte_at(0) != '[', "not an instance klass");
- _is_initialized = false;
- _is_linked = false;
+ _init_state = (instanceKlass::ClassState)0;
_nonstatic_field_size = -1;
_has_nonstatic_fields = false;
_nonstatic_fields = NULL;
@@ -109,21 +106,10 @@
// ------------------------------------------------------------------
// ciInstanceKlass::compute_shared_is_initialized
-bool ciInstanceKlass::compute_shared_is_initialized() {
+void ciInstanceKlass::compute_shared_init_state() {
GUARDED_VM_ENTRY(
instanceKlass* ik = get_instanceKlass();
- _is_initialized = ik->is_initialized();
- return _is_initialized;
- )
-}
-
-// ------------------------------------------------------------------
-// ciInstanceKlass::compute_shared_is_linked
-bool ciInstanceKlass::compute_shared_is_linked() {
- GUARDED_VM_ENTRY(
- instanceKlass* ik = get_instanceKlass();
- _is_linked = ik->is_linked();
- return _is_linked;
+ _init_state = (instanceKlass::ClassState)ik->get_init_state();
)
}
@@ -323,8 +309,8 @@
// ciInstanceKlass::java_mirror
//
// Get the instance of java.lang.Class corresponding to this klass.
+// Cache it on this->_java_mirror.
ciInstance* ciInstanceKlass::java_mirror() {
- assert(is_loaded(), "must be loaded");
if (_java_mirror == NULL) {
_java_mirror = ciKlass::java_mirror();
}
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,9 +39,8 @@
jobject _loader;
jobject _protection_domain;
+ instanceKlass::ClassState _init_state; // state of class
bool _is_shared;
- bool _is_initialized;
- bool _is_linked;
bool _has_finalizer;
bool _has_subklass;
bool _has_nonstatic_fields;
@@ -87,27 +86,34 @@
bool is_shared() { return _is_shared; }
- bool compute_shared_is_initialized();
- bool compute_shared_is_linked();
+ void compute_shared_init_state();
bool compute_shared_has_subklass();
int compute_shared_nof_implementors();
int compute_nonstatic_fields();
GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
+ // Update the init_state for shared klasses
+ void update_if_shared(instanceKlass::ClassState expected) {
+ if (_is_shared && _init_state != expected) {
+ if (is_loaded()) compute_shared_init_state();
+ }
+ }
+
public:
// Has this klass been initialized?
bool is_initialized() {
- if (_is_shared && !_is_initialized) {
- return is_loaded() && compute_shared_is_initialized();
- }
- return _is_initialized;
+ update_if_shared(instanceKlass::fully_initialized);
+ return _init_state == instanceKlass::fully_initialized;
+ }
+ // Is this klass being initialized?
+ bool is_being_initialized() {
+ update_if_shared(instanceKlass::being_initialized);
+ return _init_state == instanceKlass::being_initialized;
}
// Has this klass been linked?
bool is_linked() {
- if (_is_shared && !_is_linked) {
- return is_loaded() && compute_shared_is_linked();
- }
- return _is_linked;
+ update_if_shared(instanceKlass::linked);
+ return _init_state >= instanceKlass::linked;
}
// General klass information.
--- a/hotspot/src/share/vm/ci/ciKlass.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciKlass.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -192,8 +192,14 @@
// ------------------------------------------------------------------
// ciKlass::java_mirror
+//
+// Get the instance of java.lang.Class corresponding to this klass.
+// If it is an unloaded instance or array klass, return an unloaded
+// mirror object of type Class.
ciInstance* ciKlass::java_mirror() {
GUARDED_VM_ENTRY(
+ if (!is_loaded())
+ return ciEnv::current()->get_unloaded_klass_mirror(this);
oop java_mirror = get_Klass()->java_mirror();
return CURRENT_ENV->get_object(java_mirror)->as_instance();
)
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -54,10 +54,10 @@
_code = NULL;
_exception_handlers = NULL;
_liveness = NULL;
- _bcea = NULL;
_method_blocks = NULL;
#ifdef COMPILER2
_flow = NULL;
+ _bcea = NULL;
#endif // COMPILER2
ciEnv *env = CURRENT_ENV;
@@ -121,11 +121,11 @@
_intrinsic_id = vmIntrinsics::_none;
_liveness = NULL;
_can_be_statically_bound = false;
- _bcea = NULL;
_method_blocks = NULL;
_method_data = NULL;
#ifdef COMPILER2
_flow = NULL;
+ _bcea = NULL;
#endif // COMPILER2
}
@@ -1033,10 +1033,15 @@
bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); }
BCEscapeAnalyzer *ciMethod::get_bcea() {
+#ifdef COMPILER2
if (_bcea == NULL) {
_bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
}
return _bcea;
+#else // COMPILER2
+ ShouldNotReachHere();
+ return NULL;
+#endif // COMPILER2
}
ciMethodBlocks *ciMethod::get_method_blocks() {
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -48,7 +48,6 @@
ciInstanceKlass* _holder;
ciSignature* _signature;
ciMethodData* _method_data;
- BCEscapeAnalyzer* _bcea;
ciMethodBlocks* _method_blocks;
// Code attributes.
@@ -72,7 +71,8 @@
// Optional liveness analyzer.
MethodLiveness* _liveness;
#ifdef COMPILER2
- ciTypeFlow* _flow;
+ ciTypeFlow* _flow;
+ BCEscapeAnalyzer* _bcea;
#endif
ciMethod(methodHandle h_m);
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -70,6 +70,7 @@
_unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL);
_unloaded_klasses = new (arena) GrowableArray<ciKlass*>(arena, 8, 0, NULL);
+ _unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL);
_return_addresses =
new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL);
}
@@ -443,6 +444,74 @@
return new_klass;
}
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_instance
+//
+// Get a ciInstance representing an as-yet undetermined instance of a given class.
+//
+ciInstance* ciObjectFactory::get_unloaded_instance(ciInstanceKlass* instance_klass) {
+ for (int i=0; i<_unloaded_instances->length(); i++) {
+ ciInstance* entry = _unloaded_instances->at(i);
+ if (entry->klass()->equals(instance_klass)) {
+ // We've found a match.
+ return entry;
+ }
+ }
+
+ // This is a new unloaded instance. Create it and stick it in
+ // the cache.
+ ciInstance* new_instance = new (arena()) ciInstance(instance_klass);
+
+ init_ident_of(new_instance);
+ _unloaded_instances->append(new_instance);
+
+ // make sure it looks the way we want:
+ assert(!new_instance->is_loaded(), "");
+ assert(new_instance->klass() == instance_klass, "");
+
+ return new_instance;
+}
+
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_klass_mirror
+//
+// Get a ciInstance representing an unresolved klass mirror.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_klass_mirror(ciKlass* type) {
+ assert(ciEnv::_Class_klass != NULL, "");
+ return get_unloaded_instance(ciEnv::_Class_klass->as_instance_klass());
+}
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_method_handle_constant
+//
+// Get a ciInstance representing an unresolved method handle constant.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_method_handle_constant(ciKlass* holder,
+ ciSymbol* name,
+ ciSymbol* signature,
+ int ref_kind) {
+ if (ciEnv::_MethodHandle_klass == NULL) return NULL;
+ return get_unloaded_instance(ciEnv::_MethodHandle_klass->as_instance_klass());
+}
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_method_type_constant
+//
+// Get a ciInstance representing an unresolved method type constant.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_method_type_constant(ciSymbol* signature) {
+ if (ciEnv::_MethodType_klass == NULL) return NULL;
+ return get_unloaded_instance(ciEnv::_MethodType_klass->as_instance_klass());
+}
+
+
+
//------------------------------------------------------------------
// ciObjectFactory::get_empty_methodData
//
@@ -637,7 +706,8 @@
//
// Print debugging information about the object factory
void ciObjectFactory::print() {
- tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_klasses=%d>",
+ tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>",
_ci_objects->length(), _unloaded_methods->length(),
+ _unloaded_instances->length(),
_unloaded_klasses->length());
}
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -39,6 +39,7 @@
GrowableArray<ciObject*>* _ci_objects;
GrowableArray<ciMethod*>* _unloaded_methods;
GrowableArray<ciKlass*>* _unloaded_klasses;
+ GrowableArray<ciInstance*>* _unloaded_instances;
GrowableArray<ciReturnAddress*>* _return_addresses;
int _next_ident;
@@ -73,6 +74,8 @@
void print_contents_impl();
+ ciInstance* get_unloaded_instance(ciInstanceKlass* klass);
+
public:
static bool is_initialized() { return _initialized; }
@@ -98,6 +101,18 @@
ciSymbol* name,
bool create_if_not_found);
+ // Get a ciInstance representing an unresolved klass mirror.
+ ciInstance* get_unloaded_klass_mirror(ciKlass* type);
+
+ // Get a ciInstance representing an unresolved method handle constant.
+ ciInstance* get_unloaded_method_handle_constant(ciKlass* holder,
+ ciSymbol* name,
+ ciSymbol* signature,
+ int ref_kind);
+
+ // Get a ciInstance representing an unresolved method type constant.
+ ciInstance* get_unloaded_method_type_constant(ciSymbol* signature);
+
// Get the ciMethodData representing the methodData for a method
// with none.
--- a/hotspot/src/share/vm/ci/ciStreams.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -186,12 +186,13 @@
}
// ------------------------------------------------------------------
-// ciBytecodeStream::get_constant_index
+// ciBytecodeStream::get_constant_raw_index
//
// If this bytecode is one of the ldc variants, get the index of the
// referenced constant.
-int ciBytecodeStream::get_constant_index() const {
- switch(cur_bc()) {
+int ciBytecodeStream::get_constant_raw_index() const {
+ // work-alike for Bytecode_loadconstant::raw_index()
+ switch (cur_bc()) {
case Bytecodes::_ldc:
return get_index_u1();
case Bytecodes::_ldc_w:
@@ -202,25 +203,52 @@
return 0;
}
}
+
+// ------------------------------------------------------------------
+// ciBytecodeStream::get_constant_pool_index
+// Decode any CP cache index into a regular pool index.
+int ciBytecodeStream::get_constant_pool_index() const {
+ // work-alike for Bytecode_loadconstant::pool_index()
+ int index = get_constant_raw_index();
+ if (has_cache_index()) {
+ return get_cpcache()->get_pool_index(index);
+ }
+ return index;
+}
+
+// ------------------------------------------------------------------
+// ciBytecodeStream::get_constant_cache_index
+// Return the CP cache index, or -1 if there isn't any.
+int ciBytecodeStream::get_constant_cache_index() const {
+ // work-alike for Bytecode_loadconstant::cache_index()
+ return has_cache_index() ? get_constant_raw_index() : -1;
+}
+
// ------------------------------------------------------------------
// ciBytecodeStream::get_constant
//
// If this bytecode is one of the ldc variants, get the referenced
// constant.
ciConstant ciBytecodeStream::get_constant() {
+ int pool_index = get_constant_raw_index();
+ int cache_index = -1;
+ if (has_cache_index()) {
+ cache_index = pool_index;
+ pool_index = -1;
+ }
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
- return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
+ return CURRENT_ENV->get_constant_by_index(cpool, pool_index, cache_index, _holder);
}
// ------------------------------------------------------------------
-bool ciBytecodeStream::is_unresolved_string() const {
- return CURRENT_ENV->is_unresolved_string(_holder, get_constant_index());
-}
-
-// ------------------------------------------------------------------
-bool ciBytecodeStream::is_unresolved_klass() const {
- return CURRENT_ENV->is_unresolved_klass(_holder, get_klass_index());
+// ciBytecodeStream::get_constant_pool_tag
+//
+// If this bytecode is one of the ldc variants, get the referenced
+// constant.
+constantTag ciBytecodeStream::get_constant_pool_tag(int index) const {
+ VM_ENTRY_MARK;
+ return _method->get_methodOop()->constants()->tag_at(index);
}
// ------------------------------------------------------------------
@@ -378,13 +406,16 @@
// ------------------------------------------------------------------
// ciBytecodeStream::get_cpcache
-ciCPCache* ciBytecodeStream::get_cpcache() {
- VM_ENTRY_MARK;
- // Get the constant pool.
- constantPoolOop cpool = _holder->get_instanceKlass()->constants();
- constantPoolCacheOop cpcache = cpool->cache();
+ciCPCache* ciBytecodeStream::get_cpcache() const {
+ if (_cpcache == NULL) {
+ VM_ENTRY_MARK;
+ // Get the constant pool.
+ constantPoolOop cpool = _holder->get_instanceKlass()->constants();
+ constantPoolCacheOop cpcache = cpool->cache();
- return CURRENT_ENV->get_object(cpcache)->as_cpcache();
+ *(ciCPCache**)&_cpcache = CURRENT_ENV->get_object(cpcache)->as_cpcache();
+ }
+ return _cpcache;
}
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciStreams.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -46,6 +46,7 @@
ciMethod* _method; // the method
ciInstanceKlass* _holder;
+ ciCPCache* _cpcache;
address _bc_start; // Start of current bytecode for table
address _was_wide; // Address past last wide bytecode
jint* _table_base; // Aligned start of last table or switch
@@ -58,7 +59,9 @@
void reset( address base, unsigned int size ) {
_bc_start =_was_wide = 0;
- _start = _pc = base; _end = base + size; }
+ _start = _pc = base; _end = base + size;
+ _cpcache = NULL;
+ }
void assert_wide(bool require_wide) const {
if (require_wide)
@@ -136,15 +139,20 @@
bool is_wide() const { return ( _pc == _was_wide ); }
// Does this instruction contain an index which refes into the CP cache?
- bool uses_cp_cache() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
+ bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
int get_index_u1() const {
return bytecode()->get_index_u1(cur_bc_raw());
}
+ int get_index_u1_cpcache() const {
+ return bytecode()->get_index_u1_cpcache(cur_bc_raw());
+ }
+
// Get a byte index following this bytecode.
// If prefixed with a wide bytecode, get a wide index.
int get_index() const {
+ assert(!has_cache_index(), "else use cpcache variant");
return (_pc == _was_wide) // was widened?
? get_index_u2(true) // yes, return wide index
: get_index_u1(); // no, return narrow index
@@ -207,7 +215,9 @@
return cur_bci() + get_int_table(index); }
// --- Constant pool access ---
- int get_constant_index() const;
+ int get_constant_raw_index() const;
+ int get_constant_pool_index() const;
+ int get_constant_cache_index() const;
int get_field_index();
int get_method_index();
@@ -217,12 +227,17 @@
int get_klass_index() const;
// If this bytecode is one of the ldc variants, get the referenced
- // constant
+ // constant. Do not attempt to resolve it, since that would require
+ // execution of Java code. If it is not resolved, return an unloaded
+ // object (ciConstant.as_object()->is_loaded() == false).
ciConstant get_constant();
- // True if the ldc variant points to an unresolved string
- bool is_unresolved_string() const;
- // True if the ldc variant points to an unresolved klass
- bool is_unresolved_klass() const;
+ constantTag get_constant_pool_tag(int index) const;
+
+ // True if the klass-using bytecode points to an unresolved klass
+ bool is_unresolved_klass() const {
+ constantTag tag = get_constant_pool_tag(get_klass_index());
+ return tag.is_unresolved_klass();
+ }
// If this bytecode is one of get_field, get_static, put_field,
// or put_static, get the referenced field.
@@ -238,7 +253,7 @@
int get_method_holder_index();
int get_method_signature_index();
- ciCPCache* get_cpcache();
+ ciCPCache* get_cpcache() const;
ciCallSite* get_call_site();
};
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -712,10 +712,8 @@
ciObject* obj = con.as_object();
if (obj->is_null_object()) {
push_null();
- } else if (obj->is_klass()) {
- // The type of ldc <class> is java.lang.Class
- push_object(outer()->env()->Class_klass());
} else {
+ assert(!obj->is_klass(), "must be java_mirror of klass");
push_object(obj->klass());
}
} else {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -117,6 +117,29 @@
cp->string_index_at_put(index, string_index);
}
break;
+ case JVM_CONSTANT_MethodHandle :
+ case JVM_CONSTANT_MethodType :
+ if (!EnableMethodHandles ||
+ _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
+ classfile_parse_error(
+ (!EnableInvokeDynamic ?
+ "This JVM does not support constant tag %u in class file %s" :
+ "Class file version does not support constant tag %u in class file %s"),
+ tag, CHECK);
+ }
+ if (tag == JVM_CONSTANT_MethodHandle) {
+ cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags
+ u1 ref_kind = cfs->get_u1_fast();
+ u2 method_index = cfs->get_u2_fast();
+ cp->method_handle_index_at_put(index, ref_kind, method_index);
+ } else if (tag == JVM_CONSTANT_MethodType) {
+ cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags
+ u2 signature_index = cfs->get_u2_fast();
+ cp->method_type_index_at_put(index, signature_index);
+ } else {
+ ShouldNotReachHere();
+ }
+ break;
case JVM_CONSTANT_Integer :
{
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
@@ -337,6 +360,60 @@
cp->unresolved_string_at_put(index, sym);
}
break;
+ case JVM_CONSTANT_MethodHandle :
+ {
+ int ref_index = cp->method_handle_index_at(index);
+ check_property(
+ valid_cp_range(ref_index, length) &&
+ EnableMethodHandles,
+ "Invalid constant pool index %u in class file %s",
+ ref_index, CHECK_(nullHandle));
+ constantTag tag = cp->tag_at(ref_index);
+ int ref_kind = cp->method_handle_ref_kind_at(index);
+ switch (ref_kind) {
+ case JVM_REF_getField:
+ case JVM_REF_getStatic:
+ case JVM_REF_putField:
+ case JVM_REF_putStatic:
+ check_property(
+ tag.is_field(),
+ "Invalid constant pool index %u in class file %s (not a field)",
+ ref_index, CHECK_(nullHandle));
+ break;
+ case JVM_REF_invokeVirtual:
+ case JVM_REF_invokeStatic:
+ case JVM_REF_invokeSpecial:
+ case JVM_REF_newInvokeSpecial:
+ check_property(
+ tag.is_method(),
+ "Invalid constant pool index %u in class file %s (not a method)",
+ ref_index, CHECK_(nullHandle));
+ break;
+ case JVM_REF_invokeInterface:
+ check_property(
+ tag.is_interface_method(),
+ "Invalid constant pool index %u in class file %s (not an interface method)",
+ ref_index, CHECK_(nullHandle));
+ break;
+ default:
+ classfile_parse_error(
+ "Bad method handle kind at constant pool index %u in class file %s",
+ index, CHECK_(nullHandle));
+ }
+ // Keep the ref_index unchanged. It will be indirected at link-time.
+ }
+ break;
+ case JVM_CONSTANT_MethodType :
+ {
+ int ref_index = cp->method_type_index_at(index);
+ check_property(
+ valid_cp_range(ref_index, length) &&
+ cp->tag_at(ref_index).is_utf8() &&
+ EnableMethodHandles,
+ "Invalid constant pool index %u in class file %s",
+ ref_index, CHECK_(nullHandle));
+ }
+ break;
default:
fatal(err_msg("bad constant pool tag value %u",
cp->tag_at(index).value()));
@@ -452,6 +529,43 @@
}
break;
}
+ case JVM_CONSTANT_MethodHandle: {
+ int ref_index = cp->method_handle_index_at(index);
+ int ref_kind = cp->method_handle_ref_kind_at(index);
+ switch (ref_kind) {
+ case JVM_REF_invokeVirtual:
+ case JVM_REF_invokeStatic:
+ case JVM_REF_invokeSpecial:
+ case JVM_REF_newInvokeSpecial:
+ {
+ int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index);
+ int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
+ symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
+ if (ref_kind == JVM_REF_newInvokeSpecial) {
+ if (name() != vmSymbols::object_initializer_name()) {
+ classfile_parse_error(
+ "Bad constructor name at constant pool index %u in class file %s",
+ name_ref_index, CHECK_(nullHandle));
+ }
+ } else {
+ if (name() == vmSymbols::object_initializer_name()) {
+ classfile_parse_error(
+ "Bad method name at constant pool index %u in class file %s",
+ name_ref_index, CHECK_(nullHandle));
+ }
+ }
+ }
+ break;
+ // Other ref_kinds are already fully checked in previous pass.
+ }
+ break;
+ }
+ case JVM_CONSTANT_MethodType: {
+ symbolHandle no_name = vmSymbolHandles::type_name(); // place holder
+ symbolHandle signature(THREAD, cp->method_type_signature_at(index));
+ verify_legal_method_signature(no_name, signature, CHECK_(nullHandle));
+ break;
+ }
} // end of switch
} // end of for
@@ -467,7 +581,7 @@
case JVM_CONSTANT_UnresolvedClass :
// Patching a class means pre-resolving it.
// The name in the constant pool is ignored.
- if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance
+ if (java_lang_Class::is_instance(patch())) {
guarantee_property(!java_lang_Class::is_primitive(patch()),
"Illegal class patch at %d in class file %s",
index, CHECK);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -832,7 +832,6 @@
instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
- VTuneClassLoadMarker clm;
ResourceMark rm(THREAD);
EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -2454,6 +2454,48 @@
return Handle(THREAD, (oop) result.get_jobject());
}
+// Ask Java code to find or construct a method handle constant.
+Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
+ int ref_kind, //e.g., JVM_REF_invokeVirtual
+ KlassHandle callee,
+ symbolHandle name_sym,
+ symbolHandle signature,
+ TRAPS) {
+ Handle empty;
+ Handle name = java_lang_String::create_from_symbol(name_sym(), CHECK_(empty));
+ Handle type;
+ if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
+ bool ignore_is_on_bcp = false;
+ type = find_method_handle_type(signature, caller, ignore_is_on_bcp, CHECK_(empty));
+ } else {
+ SignatureStream ss(signature(), false);
+ if (!ss.is_done()) {
+ oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(),
+ SignatureStream::NCDFError, CHECK_(empty));
+ type = Handle(THREAD, mirror);
+ ss.next();
+ if (!ss.is_done()) type = Handle(); // error!
+ }
+ }
+ if (type.is_null()) {
+ THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty);
+ }
+
+ // call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle
+ JavaCallArguments args;
+ args.push_oop(caller->java_mirror()); // the referring class
+ args.push_int(ref_kind);
+ args.push_oop(callee->java_mirror()); // the target class
+ args.push_oop(name());
+ args.push_oop(type());
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_static(&result,
+ SystemDictionary::MethodHandleNatives_klass(),
+ vmSymbols::linkMethodHandleConstant_name(),
+ vmSymbols::linkMethodHandleConstant_signature(),
+ &args, CHECK_(empty));
+ return Handle(THREAD, (oop) result.get_jobject());
+}
// Ask Java code to find or construct a java.dyn.CallSite for the given
// name and signature, as interpreted relative to the given class loader.
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -473,6 +473,13 @@
KlassHandle accessing_klass,
bool& return_bcp_flag,
TRAPS);
+ // ask Java to compute a java.dyn.MethodHandle object for a given CP entry
+ static Handle link_method_handle_constant(KlassHandle caller,
+ int ref_kind, //e.g., JVM_REF_invokeVirtual
+ KlassHandle callee,
+ symbolHandle name,
+ symbolHandle signature,
+ TRAPS);
// ask Java to create a dynamic call site, while linking an invokedynamic op
static Handle make_dynamic_call_site(Handle bootstrap_method,
// Callee information:
--- a/hotspot/src/share/vm/classfile/verifier.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1598,7 +1598,10 @@
if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) {
types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
- | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class);
+ | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class)
+ | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
+ // Note: The class file parser already verified the legality of
+ // MethodHandle and MethodType constants.
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
}
} else {
@@ -1632,6 +1635,14 @@
current_frame->push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
+ } else if (tag.is_method_handle()) {
+ current_frame->push_stack(
+ VerificationType::reference_type(
+ vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this));
+ } else if (tag.is_method_type()) {
+ current_frame->push_stack(
+ VerificationType::reference_type(
+ vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this));
} else {
verify_error(bci, "Invalid index in ldc");
return;
@@ -1920,9 +1931,12 @@
// Get referenced class type
VerificationType ref_class_type;
if (opcode == Bytecodes::_invokedynamic) {
- if (!EnableInvokeDynamic) {
+ if (!EnableInvokeDynamic ||
+ _klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
class_format_error(
- "invokedynamic instructions not enabled on this JVM",
+ (!EnableInvokeDynamic ?
+ "invokedynamic instructions not enabled in this JVM" :
+ "invokedynamic instructions not supported by this class file version"),
_klass->external_name());
return;
}
--- a/hotspot/src/share/vm/classfile/verifier.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -25,7 +25,10 @@
// The verifier class
class Verifier : AllStatic {
public:
- enum { STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50 };
+ enum {
+ STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50,
+ INVOKEDYNAMIC_MAJOR_VERSION = 51
+ };
typedef enum { ThrowException, NoException } Mode;
/**
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -246,6 +246,8 @@
/* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
+ template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
+ template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
--- a/hotspot/src/share/vm/code/codeBlob.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -210,6 +210,7 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) AdapterBlob(size, cb);
+ CodeCache::commit(blob);
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
@@ -281,7 +282,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
Disassembler::decode(stub->instructions_begin(), stub->instructions_end());
}
- VTune::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -356,7 +356,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -414,7 +413,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -474,7 +472,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -533,7 +530,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/code/codeCache.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -93,6 +93,8 @@
CodeHeap * CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
+int CodeCache::_number_of_adapters = 0;
+int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
@@ -176,8 +178,14 @@
verify_if_often();
print_trace("free", cb);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies--;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods--;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies--;
+ }
+ }
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters--;
}
_number_of_blobs--;
@@ -191,9 +199,16 @@
void CodeCache::commit(CodeBlob* cb) {
// this is called by nmethod::nmethod, which must already own CodeCache_lock
assert_locked_or_safepoint(CodeCache_lock);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies++;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods++;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies++;
+ }
}
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters++;
+ }
+
// flush the hardware I-cache
ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
}
--- a/hotspot/src/share/vm/code/codeCache.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,8 @@
// 4422213 or 4436291 for details.
static CodeHeap * _heap;
static int _number_of_blobs;
+ static int _number_of_adapters;
+ static int _number_of_nmethods;
static int _number_of_nmethods_with_dependencies;
static bool _needs_cache_clean;
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
@@ -105,6 +107,8 @@
static nmethod* first_nmethod();
static nmethod* next_nmethod (CodeBlob* cb);
static int nof_blobs() { return _number_of_blobs; }
+ static int nof_adapters() { return _number_of_adapters; }
+ static int nof_nmethods() { return _number_of_nmethods; }
// GC support
static void gc_epilogue();
--- a/hotspot/src/share/vm/code/nmethod.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -397,11 +397,6 @@
//-------------end of code for ExceptionCache--------------
-void nmFlags::clear() {
- assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags");
- *(jint*)this = 0;
-}
-
int nmethod::total_size() const {
return
code_size() +
@@ -419,8 +414,32 @@
return NULL;
}
-// %%% This variable is no longer used?
-int nmethod::_zombie_instruction_size = NativeJump::instruction_size;
+// Fill in default values for various flag fields
+void nmethod::init_defaults() {
+ _state = alive;
+ _marked_for_reclamation = 0;
+ _has_flushed_dependencies = 0;
+ _speculatively_disconnected = 0;
+ _has_unsafe_access = 0;
+ _has_method_handle_invokes = 0;
+ _marked_for_deoptimization = 0;
+ _lock_count = 0;
+ _stack_traversal_mark = 0;
+ _unload_reported = false; // jvmti state
+
+ NOT_PRODUCT(_has_debug_info = false);
+ _oops_do_mark_link = NULL;
+ _jmethod_id = NULL;
+ _osr_link = NULL;
+ _scavenge_root_link = NULL;
+ _scavenge_root_state = 0;
+ _saved_nmethod_link = NULL;
+ _compiler = NULL;
+
+#ifdef HAVE_DTRACE_H
+ _trap_offset = 0;
+#endif // def HAVE_DTRACE_H
+}
nmethod* nmethod::new_native_nmethod(methodHandle method,
@@ -580,24 +599,16 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _saved_nmethod_link = NULL;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
_deoptimize_offset = 0;
_deoptimize_mh_offset = 0;
_orig_pc_offset = 0;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
+
_stub_offset = data_offset();
_consts_offset = data_offset();
_oops_offset = data_offset();
@@ -615,17 +626,9 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -673,14 +676,9 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
@@ -706,17 +704,9 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -781,20 +771,13 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
+ _entry_bci = entry_bci;
_compile_id = compile_id;
_comp_level = comp_level;
- _entry_bci = entry_bci;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
_compiler = compiler;
_orig_pc_offset = orig_pc_offset;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
_stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
// Exception handler and deopt handler are in the stub section
@@ -821,15 +804,6 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(scopes_pcs_begin());
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _unload_reported = false; // jvmti state
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
// Copy contents of ScopeDescRecorder to nmethod
code_buffer->copy_oops_to(this);
debug_info->copy_to(this);
@@ -841,8 +815,6 @@
CodeCache::commit(this);
- VTune::create_nmethod(this);
-
// Copy contents of ExceptionHandlerTable to nmethod
handler_table->copy_to(this);
nul_chk_table->copy_to(this);
@@ -988,11 +960,6 @@
}
-void nmethod::set_version(int v) {
- flags.version = v;
-}
-
-
// Promote one word from an assembly-time handle to a live embedded oop.
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
if (handle == NULL ||
@@ -1139,6 +1106,8 @@
// This is a private interface with the sweeper.
void nmethod::mark_as_seen_on_stack() {
assert(is_not_entrant(), "must be a non-entrant method");
+ // Set the traversal mark to ensure that the sweeper does 2
+ // cleaning passes before moving to zombie.
set_stack_traversal_mark(NMethodSweeper::traversal_count());
}
@@ -1207,7 +1176,7 @@
// for later on.
CodeCache::set_needs_cache_clean(true);
}
- flags.state = unloaded;
+ _state = unloaded;
// Log the unloading.
log_state_change();
@@ -1233,21 +1202,21 @@
if (LogCompilation) {
if (xtty != NULL) {
ttyLocker ttyl; // keep the following output all in one block
- if (flags.state == unloaded) {
+ if (_state == unloaded) {
xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
os::current_thread_id());
} else {
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
os::current_thread_id(),
- (flags.state == zombie ? " zombie='1'" : ""));
+ (_state == zombie ? " zombie='1'" : ""));
}
log_identity(xtty);
xtty->stamp();
xtty->end_elem();
}
}
- if (PrintCompilation && flags.state != unloaded) {
- print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
+ if (PrintCompilation && _state != unloaded) {
+ print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
tty->cr();
}
}
@@ -1258,8 +1227,9 @@
bool was_alive = false;
- // Make sure the nmethod is not flushed in case of a safepoint in code below.
+ // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this);
+ methodHandle the_method(method());
{
// If the method is already zombie there is nothing to do
@@ -1279,7 +1249,7 @@
// Enter critical section. Does not block for safepoint.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
- if (flags.state == state) {
+ if (_state == state) {
// another thread already performed this transition so nothing
// to do, but return false to indicate this.
return false;
@@ -1290,17 +1260,37 @@
if (!is_osr_method() && !is_not_entrant()) {
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
SharedRuntime::get_handle_wrong_method_stub());
- assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
}
- was_alive = is_in_use(); // Read state under lock
+ if (is_in_use()) {
+ // It's a true state change, so mark the method as decompiled.
+ // Do it only for transition from alive.
+ inc_decompile_count();
+ }
// Change state
- flags.state = state;
+ _state = state;
// Log the transition once
log_state_change();
+ // Remove nmethod from method.
+ // We need to check if both the _code and _from_compiled_code_entry_point
+ // refer to this nmethod because there is a race in setting these two fields
+ // in methodOop as seen in bugid 4947125.
+ // If the vep() points to the zombie nmethod, the memory for the nmethod
+ // could be flushed and the compiler and vtable stubs could still call
+ // through it.
+ if (method() != NULL && (method()->code() == this ||
+ method()->from_compiled_entry() == verified_entry_point())) {
+ HandleMark hm;
+ method()->clear_code();
+ }
+
+ if (state == not_entrant) {
+ mark_as_seen_on_stack();
+ }
+
} // leave critical region under Patching_lock
// When the nmethod becomes zombie it is no longer alive so the
@@ -1308,18 +1298,17 @@
// state will be flushed later when the transition to zombie
// happens or they get unloaded.
if (state == zombie) {
+ // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
+ // and it hasn't already been reported for this nmethod then report it now.
+ // (the event may have been reported earilier if the GC marked it for unloading).
+ post_compiled_method_unload();
+
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
flush_dependencies(NULL);
} else {
assert(state == not_entrant, "other cases may need to be handled differently");
}
- if (state == not_entrant) {
- Events::log("Make nmethod not entrant " INTPTR_FORMAT, this);
- } else {
- Events::log("Make nmethod zombie " INTPTR_FORMAT, this);
- }
-
if (TraceCreateZombies) {
tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
}
@@ -1327,47 +1316,6 @@
// Make sweeper aware that there is a zombie method that needs to be removed
NMethodSweeper::notify(this);
- // not_entrant only stuff
- if (state == not_entrant) {
- mark_as_seen_on_stack();
- }
-
- if (was_alive) {
- // It's a true state change, so mark the method as decompiled.
- // Do it only for transition from alive.
- inc_decompile_count();
- }
-
- // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
- // and it hasn't already been reported for this nmethod then report it now.
- // (the event may have been reported earilier if the GC marked it for unloading).
- if (state == zombie) {
- post_compiled_method_unload();
- }
-
-
- // Zombie only stuff
- if (state == zombie) {
- VTune::delete_nmethod(this);
- }
-
- // Check whether method got unloaded at a safepoint before this,
- // if so we can skip the flushing steps below
- if (method() == NULL) return true;
-
- // Remove nmethod from method.
- // We need to check if both the _code and _from_compiled_code_entry_point
- // refer to this nmethod because there is a race in setting these two fields
- // in methodOop as seen in bugid 4947125.
- // If the vep() points to the zombie nmethod, the memory for the nmethod
- // could be flushed and the compiler and vtable stubs could still call
- // through it.
- if (method()->code() == this ||
- method()->from_compiled_entry() == verified_entry_point()) {
- HandleMark hm;
- method()->clear_code();
- }
-
return true;
}
@@ -1488,11 +1436,25 @@
moop->signature()->utf8_length(),
code_begin(), code_size());
+ if (JvmtiExport::should_post_compiled_method_load() ||
+ JvmtiExport::should_post_compiled_method_unload()) {
+ get_and_cache_jmethod_id();
+ }
+
if (JvmtiExport::should_post_compiled_method_load()) {
JvmtiExport::post_compiled_method_load(this);
}
}
+jmethodID nmethod::get_and_cache_jmethod_id() {
+ if (_jmethod_id == NULL) {
+ // Cache the jmethod_id since it can no longer be looked up once the
+ // method itself has been marked for unloading.
+ _jmethod_id = method()->jmethod_id();
+ }
+ return _jmethod_id;
+}
+
void nmethod::post_compiled_method_unload() {
if (unload_reported()) {
// During unloading we transition to unloaded and then to zombie
@@ -1504,12 +1466,17 @@
DTRACE_METHOD_UNLOAD_PROBE(method());
// If a JVMTI agent has enabled the CompiledMethodUnload event then
- // post the event. Sometime later this nmethod will be made a zombie by
- // the sweeper but the methodOop will not be valid at that point.
- if (JvmtiExport::should_post_compiled_method_unload()) {
+ // post the event. Sometime later this nmethod will be made a zombie
+ // by the sweeper but the methodOop will not be valid at that point.
+ // If the _jmethod_id is null then no load event was ever requested
+ // so don't bother posting the unload. The main reason for this is
+ // that the jmethodID is a weak reference to the methodOop so if
+ // it's being unloaded there's no way to look it up since the weak
+ // ref will have been cleared.
+ if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) {
assert(!unload_reported(), "already unloaded");
HandleMark hm;
- JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
+ JvmtiExport::post_compiled_method_unload(_jmethod_id, code_begin());
}
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
@@ -2087,7 +2054,6 @@
void nmethod_init() {
// make sure you didn't forget to adjust the filler fields
- assert(sizeof(nmFlags) <= 4, "nmFlags occupies more than a word");
assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
}
@@ -2323,7 +2289,6 @@
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
tty->print(" for method " INTPTR_FORMAT , (address)method());
tty->print(" { ");
- if (version()) tty->print("v%d ", version());
if (is_in_use()) tty->print("in_use ");
if (is_not_entrant()) tty->print("not_entrant ");
if (is_zombie()) tty->print("zombie ");
@@ -2659,13 +2624,10 @@
case Bytecodes::_getstatic:
case Bytecodes::_putstatic:
{
- methodHandle sdm = sd->method();
- Bytecode_field* field = Bytecode_field_at(sdm(), sdm->bcp_from(sd->bci()));
- constantPoolOop sdmc = sdm->constants();
- symbolOop name = sdmc->name_ref_at(field->index());
+ Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci());
st->print(" ");
- if (name != NULL)
- name->print_symbol_on(st);
+ if (field->name() != NULL)
+ field->name()->print_symbol_on(st);
else
st->print("<UNKNOWN>");
}
--- a/hotspot/src/share/vm/code/nmethod.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -78,29 +78,8 @@
// nmethods (native methods) are the compiled code versions of Java methods.
-
-struct nmFlags {
- friend class VMStructs;
- unsigned int version:8; // version number (0 = first version)
- unsigned int age:4; // age (in # of sweep steps)
-
- unsigned int state:2; // {alive, zombie, unloaded)
-
- unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
- unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
- unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
- unsigned int markedForReclamation:1; // Used by NMethodSweeper
-
- unsigned int has_unsafe_access:1; // May fault due to unsafe access.
- unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
-
- unsigned int speculatively_disconnected:1; // Marked for potential unload
-
- void clear();
-};
-
-
-// A nmethod contains:
+//
+// An nmethod contains:
// - header (the nmethod structure)
// [Relocation]
// - relocation information
@@ -131,10 +110,9 @@
friend class CodeCache; // non-perm oops
private:
// Shared fields for all nmethod's
- static int _zombie_instruction_size;
-
methodOop _method;
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
+ jmethodID _jmethod_id; // Cache of method()->jmethod_id()
// To support simple linked-list chaining of nmethods:
nmethod* _osr_link; // from instanceKlass::osr_nmethods_head
@@ -146,6 +124,11 @@
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
+ // offsets for entry points
+ address _entry_point; // entry point with class check
+ address _verified_entry_point; // entry point without class check
+ address _osr_entry_point; // entry point for on stack replacement
+
// Offsets for different nmethod parts
int _exception_offset;
// All deoptee's will resume execution at this location described by
@@ -174,23 +157,31 @@
// pc during a deopt.
int _orig_pc_offset;
- int _compile_id; // which compilation made this nmethod
- int _comp_level; // compilation level
+ int _compile_id; // which compilation made this nmethod
+ int _comp_level; // compilation level
+
+ // protected by CodeCache_lock
+ bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
+ bool _speculatively_disconnected; // Marked for potential unload
+
+ bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
+ bool _marked_for_deoptimization; // Used for stack deoptimization
- // offsets for entry points
- address _entry_point; // entry point with class check
- address _verified_entry_point; // entry point without class check
- address _osr_entry_point; // entry point for on stack replacement
+ // used by jvmti to track if an unload event has been posted for this nmethod.
+ bool _unload_reported;
- nmFlags flags; // various flags to keep track of nmethod state
- bool _markedForDeoptimization; // Used for stack deoptimization
+ // set during construction
+ unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
+ unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
+
+ // Protected by Patching_lock
+ unsigned char _state; // {alive, not_entrant, zombie, unloaded)
+
enum { alive = 0,
not_entrant = 1, // uncommon trap has happened but activations may still exist
zombie = 2,
unloaded = 3 };
- // used by jvmti to track if an unload event has been posted for this nmethod.
- bool _unload_reported;
jbyte _scavenge_root_state;
@@ -269,15 +260,15 @@
bool make_not_entrant_or_zombie(unsigned int state);
void inc_decompile_count();
- // used to check that writes to nmFlags are done consistently.
- static void check_safepoint() PRODUCT_RETURN;
-
// Used to manipulate the exception cache
void add_exception_cache_entry(ExceptionCache* new_entry);
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
// Inform external interfaces that a compiled method has been unloaded
- inline void post_compiled_method_unload();
+ void post_compiled_method_unload();
+
+ // Initailize fields to their default values
+ void init_defaults();
public:
// create nmethod with entry_bci
@@ -392,11 +383,11 @@
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
// flag accessing and manipulation
- bool is_in_use() const { return flags.state == alive; }
- bool is_alive() const { return flags.state == alive || flags.state == not_entrant; }
- bool is_not_entrant() const { return flags.state == not_entrant; }
- bool is_zombie() const { return flags.state == zombie; }
- bool is_unloaded() const { return flags.state == unloaded; }
+ bool is_in_use() const { return _state == alive; }
+ bool is_alive() const { return _state == alive || _state == not_entrant; }
+ bool is_not_entrant() const { return _state == not_entrant; }
+ bool is_zombie() const { return _state == zombie; }
+ bool is_unloaded() const { return _state == unloaded; }
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
@@ -409,37 +400,33 @@
bool unload_reported() { return _unload_reported; }
void set_unload_reported() { _unload_reported = true; }
- bool is_marked_for_deoptimization() const { return _markedForDeoptimization; }
- void mark_for_deoptimization() { _markedForDeoptimization = true; }
+ bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
+ void mark_for_deoptimization() { _marked_for_deoptimization = true; }
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
bool has_dependencies() { return dependencies_size() != 0; }
void flush_dependencies(BoolObjectClosure* is_alive);
- bool has_flushed_dependencies() { return flags.hasFlushedDependencies; }
- void set_has_flushed_dependencies() {
+ bool has_flushed_dependencies() { return _has_flushed_dependencies; }
+ void set_has_flushed_dependencies() {
assert(!has_flushed_dependencies(), "should only happen once");
- flags.hasFlushedDependencies = 1;
+ _has_flushed_dependencies = 1;
}
- bool is_marked_for_reclamation() const { return flags.markedForReclamation; }
- void mark_for_reclamation() { flags.markedForReclamation = 1; }
- void unmark_for_reclamation() { flags.markedForReclamation = 0; }
+ bool is_marked_for_reclamation() const { return _marked_for_reclamation; }
+ void mark_for_reclamation() { _marked_for_reclamation = 1; }
+
+ bool has_unsafe_access() const { return _has_unsafe_access; }
+ void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }
- bool has_unsafe_access() const { return flags.has_unsafe_access; }
- void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
+ bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
+ void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
- bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
- void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
-
- bool is_speculatively_disconnected() const { return flags.speculatively_disconnected; }
- void set_speculatively_disconnected(bool z) { flags.speculatively_disconnected = z; }
+ bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
+ void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
int comp_level() const { return _comp_level; }
- int version() const { return flags.version; }
- void set_version(int v);
-
// Support for oops in scopes and relocs:
// Note: index 0 is reserved for null.
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
@@ -599,6 +586,7 @@
// jvmti support:
void post_compiled_method_load_event();
+ jmethodID get_and_cache_jmethod_id();
// verify operations
void verify();
--- a/hotspot/src/share/vm/code/vtableStubs.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/code/vtableStubs.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,6 @@
}
_chunk = blob->instructions_begin();
_chunk_end = _chunk + bytes;
- VTune::register_stub("vtable stub", _chunk, _chunk_end);
Forte::register_stub("vtable stub", _chunk, _chunk_end);
// Notify JVMTI about this stub. The event will be recorded by the enclosing
// JvmtiDynamicCodeEventCollector and posted when this thread has released
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -3972,6 +3972,10 @@
void work(int i) {
if (i >= _n_workers) return; // no work needed this round
+
+ double start_time_ms = os::elapsedTime() * 1000.0;
+ _g1h->g1_policy()->record_gc_worker_start_time(i, start_time_ms);
+
ResourceMark rm;
HandleMark hm;
@@ -4019,7 +4023,7 @@
double elapsed_ms = (os::elapsedTime()-start)*1000.0;
double term_ms = pss.term_time()*1000.0;
_g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
- _g1h->g1_policy()->record_termination_time(i, term_ms);
+ _g1h->g1_policy()->record_termination(i, term_ms, pss.term_attempts());
}
_g1h->g1_policy()->record_thread_age_table(pss.age_table());
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
@@ -4043,7 +4047,8 @@
double term = pss.term_time();
gclog_or_tty->print(" Elapsed: %7.2f ms.\n"
" Strong roots: %7.2f ms (%6.2f%%)\n"
- " Termination: %7.2f ms (%6.2f%%) (in %d entries)\n",
+ " Termination: %7.2f ms (%6.2f%%) "
+ "(in "SIZE_FORMAT" entries)\n",
elapsed * 1000.0,
strong_roots * 1000.0, (strong_roots*100.0/elapsed),
term * 1000.0, (term*100.0/elapsed),
@@ -4059,6 +4064,8 @@
assert(pss.refs_to_scan() == 0, "Task queue should be empty");
assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
+ double end_time_ms = os::elapsedTime() * 1000.0;
+ _g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
}
};
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1549,7 +1549,7 @@
int _hash_seed;
int _queue_num;
- int _term_attempts;
+ size_t _term_attempts;
#if G1_DETAILED_STATS
int _pushes, _pops, _steals, _steal_attempts;
int _overflow_pushes;
@@ -1727,8 +1727,8 @@
int* hash_seed() { return &_hash_seed; }
int queue_num() { return _queue_num; }
- int term_attempts() { return _term_attempts; }
- void note_term_attempt() { _term_attempts++; }
+ size_t term_attempts() { return _term_attempts; }
+ void note_term_attempt() { _term_attempts++; }
#if G1_DETAILED_STATS
int pushes() { return _pushes; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -231,20 +231,21 @@
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
+ _par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads];
_par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
_par_last_mark_stack_scan_times_ms = new double[_parallel_gc_threads];
- _par_last_update_rs_start_times_ms = new double[_parallel_gc_threads];
_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
- _par_last_scan_rs_start_times_ms = new double[_parallel_gc_threads];
_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
_par_last_scan_new_refs_times_ms = new double[_parallel_gc_threads];
_par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
_par_last_termination_times_ms = new double[_parallel_gc_threads];
+ _par_last_termination_attempts = new double[_parallel_gc_threads];
+ _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
// start conservatively
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
@@ -274,10 +275,64 @@
// </NEW PREDICTION>
- double time_slice = (double) GCPauseIntervalMillis / 1000.0;
+ // Below, we might need to calculate the pause time target based on
+ // the pause interval. When we do so we are going to give G1 maximum
+ // flexibility and allow it to do pauses when it needs to. So, we'll
+ // arrange that the pause interval to be pause time target + 1 to
+ // ensure that a) the pause time target is maximized with respect to
+ // the pause interval and b) we maintain the invariant that pause
+ // time target < pause interval. If the user does not want this
+ // maximum flexibility, they will have to set the pause interval
+ // explicitly.
+
+ // First make sure that, if either parameter is set, its value is
+ // reasonable.
+ if (!FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
+ if (MaxGCPauseMillis < 1) {
+ vm_exit_during_initialization("MaxGCPauseMillis should be "
+ "greater than 0");
+ }
+ }
+ if (!FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+ if (GCPauseIntervalMillis < 1) {
+ vm_exit_during_initialization("GCPauseIntervalMillis should be "
+ "greater than 0");
+ }
+ }
+
+ // Then, if the pause time target parameter was not set, set it to
+ // the default value.
+ if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
+ if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+ // The default pause time target in G1 is 200ms
+ FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
+ } else {
+ // We do not allow the pause interval to be set without the
+ // pause time target
+ vm_exit_during_initialization("GCPauseIntervalMillis cannot be set "
+ "without setting MaxGCPauseMillis");
+ }
+ }
+
+ // Then, if the interval parameter was not set, set it according to
+ // the pause time target (this will also deal with the case when the
+ // pause time target is the default value).
+ if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+ FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
+ }
+
+ // Finally, make sure that the two parameters are consistent.
+ if (MaxGCPauseMillis >= GCPauseIntervalMillis) {
+ char buffer[256];
+ jio_snprintf(buffer, 256,
+ "MaxGCPauseMillis (%u) should be less than "
+ "GCPauseIntervalMillis (%u)",
+ MaxGCPauseMillis, GCPauseIntervalMillis);
+ vm_exit_during_initialization(buffer);
+ }
+
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
- guarantee(max_gc_time < time_slice,
- "Max GC time should not be greater than the time slice");
+ double time_slice = (double) GCPauseIntervalMillis / 1000.0;
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
_sigma = (double) G1ConfidencePercent / 100.0;
@@ -782,16 +837,17 @@
// if they are not set properly
for (int i = 0; i < _parallel_gc_threads; ++i) {
- _par_last_ext_root_scan_times_ms[i] = -666.0;
- _par_last_mark_stack_scan_times_ms[i] = -666.0;
- _par_last_update_rs_start_times_ms[i] = -666.0;
- _par_last_update_rs_times_ms[i] = -666.0;
- _par_last_update_rs_processed_buffers[i] = -666.0;
- _par_last_scan_rs_start_times_ms[i] = -666.0;
- _par_last_scan_rs_times_ms[i] = -666.0;
- _par_last_scan_new_refs_times_ms[i] = -666.0;
- _par_last_obj_copy_times_ms[i] = -666.0;
- _par_last_termination_times_ms[i] = -666.0;
+ _par_last_gc_worker_start_times_ms[i] = -1234.0;
+ _par_last_ext_root_scan_times_ms[i] = -1234.0;
+ _par_last_mark_stack_scan_times_ms[i] = -1234.0;
+ _par_last_update_rs_times_ms[i] = -1234.0;
+ _par_last_update_rs_processed_buffers[i] = -1234.0;
+ _par_last_scan_rs_times_ms[i] = -1234.0;
+ _par_last_scan_new_refs_times_ms[i] = -1234.0;
+ _par_last_obj_copy_times_ms[i] = -1234.0;
+ _par_last_termination_times_ms[i] = -1234.0;
+ _par_last_termination_attempts[i] = -1234.0;
+ _par_last_gc_worker_end_times_ms[i] = -1234.0;
}
#endif
@@ -942,9 +998,9 @@
return sum;
}
-void G1CollectorPolicy::print_par_stats (int level,
- const char* str,
- double* data,
+void G1CollectorPolicy::print_par_stats(int level,
+ const char* str,
+ double* data,
bool summary) {
double min = data[0], max = data[0];
double total = 0.0;
@@ -973,10 +1029,10 @@
gclog_or_tty->print_cr("]");
}
-void G1CollectorPolicy::print_par_buffers (int level,
- const char* str,
- double* data,
- bool summary) {
+void G1CollectorPolicy::print_par_sizes(int level,
+ const char* str,
+ double* data,
+ bool summary) {
double min = data[0], max = data[0];
double total = 0.0;
int j;
@@ -1321,15 +1377,22 @@
}
if (parallel) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
- print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
+ print_par_stats(2, "GC Worker Start Time",
+ _par_last_gc_worker_start_times_ms, false);
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
- print_par_buffers(3, "Processed Buffers",
- _par_last_update_rs_processed_buffers, true);
- print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
- print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
+ print_par_sizes(3, "Processed Buffers",
+ _par_last_update_rs_processed_buffers, true);
+ print_par_stats(2, "Ext Root Scanning",
+ _par_last_ext_root_scan_times_ms);
+ print_par_stats(2, "Mark Stack Scanning",
+ _par_last_mark_stack_scan_times_ms);
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
+ print_par_sizes(3, "Termination Attempts",
+ _par_last_termination_attempts, true);
+ print_par_stats(2, "GC Worker End Time",
+ _par_last_gc_worker_end_times_ms, false);
print_stats(2, "Other", parallel_other_time);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
} else {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -171,16 +171,17 @@
double* _cur_aux_times_ms;
bool* _cur_aux_times_set;
+ double* _par_last_gc_worker_start_times_ms;
double* _par_last_ext_root_scan_times_ms;
double* _par_last_mark_stack_scan_times_ms;
- double* _par_last_update_rs_start_times_ms;
double* _par_last_update_rs_times_ms;
double* _par_last_update_rs_processed_buffers;
- double* _par_last_scan_rs_start_times_ms;
double* _par_last_scan_rs_times_ms;
double* _par_last_scan_new_refs_times_ms;
double* _par_last_obj_copy_times_ms;
double* _par_last_termination_times_ms;
+ double* _par_last_termination_attempts;
+ double* _par_last_gc_worker_end_times_ms;
// indicates that we are in young GC mode
bool _in_young_gc_mode;
@@ -559,13 +560,14 @@
}
protected:
- void print_stats (int level, const char* str, double value);
- void print_stats (int level, const char* str, int value);
- void print_par_stats (int level, const char* str, double* data) {
+ void print_stats(int level, const char* str, double value);
+ void print_stats(int level, const char* str, int value);
+
+ void print_par_stats(int level, const char* str, double* data) {
print_par_stats(level, str, data, true);
}
- void print_par_stats (int level, const char* str, double* data, bool summary);
- void print_par_buffers (int level, const char* str, double* data, bool summary);
+ void print_par_stats(int level, const char* str, double* data, bool summary);
+ void print_par_sizes(int level, const char* str, double* data, bool summary);
void check_other_times(int level,
NumberSeq* other_times_ms,
@@ -891,6 +893,10 @@
virtual void record_full_collection_start();
virtual void record_full_collection_end();
+ void record_gc_worker_start_time(int worker_i, double ms) {
+ _par_last_gc_worker_start_times_ms[worker_i] = ms;
+ }
+
void record_ext_root_scan_time(int worker_i, double ms) {
_par_last_ext_root_scan_times_ms[worker_i] = ms;
}
@@ -912,10 +918,6 @@
_all_mod_union_times_ms->add(ms);
}
- void record_update_rs_start_time(int thread, double ms) {
- _par_last_update_rs_start_times_ms[thread] = ms;
- }
-
void record_update_rs_time(int thread, double ms) {
_par_last_update_rs_times_ms[thread] = ms;
}
@@ -925,10 +927,6 @@
_par_last_update_rs_processed_buffers[thread] = processed_buffers;
}
- void record_scan_rs_start_time(int thread, double ms) {
- _par_last_scan_rs_start_times_ms[thread] = ms;
- }
-
void record_scan_rs_time(int thread, double ms) {
_par_last_scan_rs_times_ms[thread] = ms;
}
@@ -953,16 +951,13 @@
_par_last_obj_copy_times_ms[thread] += ms;
}
- void record_obj_copy_time(double ms) {
- record_obj_copy_time(0, ms);
+ void record_termination(int thread, double ms, size_t attempts) {
+ _par_last_termination_times_ms[thread] = ms;
+ _par_last_termination_attempts[thread] = (double) attempts;
}
- void record_termination_time(int thread, double ms) {
- _par_last_termination_times_ms[thread] = ms;
- }
-
- void record_termination_time(double ms) {
- record_termination_time(0, ms);
+ void record_gc_worker_end_time(int worker_i, double ms) {
+ _par_last_gc_worker_end_times_ms[worker_i] = ms;
}
void record_pause_time_ms(double ms) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -303,7 +303,6 @@
assert( _cards_scanned != NULL, "invariant" );
_cards_scanned[worker_i] = scanRScl.cards_done();
- _g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0);
_g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
}
@@ -311,8 +310,6 @@
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
double start = os::elapsedTime();
- _g1p->record_update_rs_start_time(worker_i, start * 1000.0);
-
// Apply the appropriate closure to all remaining log entries.
_g1->iterate_dirty_card_closure(false, worker_i);
// Now there should be no dirty cards.
@@ -471,7 +468,6 @@
updateRS(worker_i);
scanNewRefsRS(oc, worker_i);
} else {
- _g1p->record_update_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
_g1p->record_update_rs_processed_buffers(worker_i, 0.0);
_g1p->record_update_rs_time(worker_i, 0.0);
_g1p->record_scan_new_refs_time(worker_i, 0.0);
@@ -479,7 +475,6 @@
if (G1UseParallelRSetScanning || (worker_i == 0)) {
scanRS(oc, worker_i);
} else {
- _g1p->record_scan_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
_g1p->record_scan_rs_time(worker_i, 0.0);
}
} else {
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Wed Jul 05 17:18:01 2017 +0200
@@ -270,7 +270,7 @@
psParallelCompact.cpp pcTasks.hpp
psParallelCompact.cpp psMarkSweep.hpp
psParallelCompact.cpp psMarkSweepDecorator.hpp
-psParallelCompact.cpp psCompactionManager.hpp
+psParallelCompact.cpp psCompactionManager.inline.hpp
psParallelCompact.cpp psPromotionManager.inline.hpp
psParallelCompact.cpp psOldGen.hpp
psParallelCompact.cpp psParallelCompact.hpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -566,14 +566,14 @@
#endif
// Commit new or uncommit old pages, if necessary.
- resize_commit_uncommit(changed_region, new_region);
+ if (resize_commit_uncommit(changed_region, new_region)) {
+ // Set the new start of the committed region
+ resize_update_committed_table(changed_region, new_region);
+ }
// Update card table entries
resize_update_card_table_entries(changed_region, new_region);
- // Set the new start of the committed region
- resize_update_committed_table(changed_region, new_region);
-
// Update the covered region
resize_update_covered_table(changed_region, new_region);
@@ -604,8 +604,9 @@
debug_only(verify_guard();)
}
-void CardTableExtension::resize_commit_uncommit(int changed_region,
+bool CardTableExtension::resize_commit_uncommit(int changed_region,
MemRegion new_region) {
+ bool result = false;
// Commit new or uncommit old pages, if necessary.
MemRegion cur_committed = _committed[changed_region];
assert(_covered[changed_region].end() == new_region.end(),
@@ -675,20 +676,31 @@
"card table expansion");
}
}
+ result = true;
} else if (new_start_aligned > cur_committed.start()) {
// Shrink the committed region
+#if 0 // uncommitting space is currently unsafe because of the interactions
+ // of growing and shrinking regions. One region A can uncommit space
+ // that it owns but which is being used by another region B (maybe).
+ // Region B has not committed the space because it was already
+ // committed by region A.
MemRegion uncommit_region = committed_unique_to_self(changed_region,
MemRegion(cur_committed.start(), new_start_aligned));
if (!uncommit_region.is_empty()) {
if (!os::uncommit_memory((char*)uncommit_region.start(),
uncommit_region.byte_size())) {
- vm_exit_out_of_memory(uncommit_region.byte_size(),
- "card table contraction");
+ // If the uncommit fails, ignore it. Let the
+ // committed table resizing go even though the committed
+ // table will over state the committed space.
}
}
+#else
+ assert(!result, "Should be false with current workaround");
+#endif
}
assert(_committed[changed_region].end() == cur_committed.end(),
"end should not change");
+ return result;
}
void CardTableExtension::resize_update_committed_table(int changed_region,
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,9 @@
class CardTableExtension : public CardTableModRefBS {
private:
// Support methods for resizing the card table.
- void resize_commit_uncommit(int changed_region, MemRegion new_region);
+ // resize_commit_uncommit() returns true if the pages were committed or
+ // uncommitted
+ bool resize_commit_uncommit(int changed_region, MemRegion new_region);
void resize_update_card_table_entries(int changed_region,
MemRegion new_region);
void resize_update_committed_table(int changed_region, MemRegion new_region);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
ParCompactionManager::_objarray_queues = NULL;
ObjectStartArray* ParCompactionManager::_start_array = NULL;
ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL;
-RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;
+RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;
ParCompactionManager::ParCompactionManager() :
_action(CopyAndUpdate) {
@@ -43,25 +43,9 @@
_old_gen = heap->old_gen();
_start_array = old_gen()->start_array();
-
marking_stack()->initialize();
-
- // We want the overflow stack to be permanent
- _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
-
- _objarray_queue.initialize();
- _objarray_overflow_stack =
- new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true);
-
-#ifdef USE_RegionTaskQueueWithOverflow
+ _objarray_stack.initialize();
region_stack()->initialize();
-#else
- region_stack()->initialize();
-
- // We want the overflow stack to be permanent
- _region_overflow_stack =
- new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true);
-#endif
// Note that _revisit_klass_stack is allocated out of the
// C heap (as opposed to out of ResourceArena).
@@ -71,12 +55,9 @@
// From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
// have to do for now until we are able to investigate a more optimal setting.
_revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
-
}
ParCompactionManager::~ParCompactionManager() {
- delete _overflow_stack;
- delete _objarray_overflow_stack;
delete _revisit_klass_stack;
delete _revisit_mdo_stack;
// _manager_array and _stack_array are statics
@@ -108,12 +89,8 @@
_manager_array[i] = new ParCompactionManager();
guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
stack_array()->register_queue(i, _manager_array[i]->marking_stack());
- _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue);
-#ifdef USE_RegionTaskQueueWithOverflow
- region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
-#else
+ _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);
region_array()->register_queue(i, _manager_array[i]->region_stack());
-#endif
}
// The VMThread gets its own ParCompactionManager, which is not available
@@ -149,57 +126,6 @@
return action() == ParCompactionManager::ResetObjects;
}
-// For now save on a stack
-void ParCompactionManager::save_for_scanning(oop m) {
- stack_push(m);
-}
-
-void ParCompactionManager::stack_push(oop obj) {
-
- if(!marking_stack()->push(obj)) {
- overflow_stack()->push(obj);
- }
-}
-
-oop ParCompactionManager::retrieve_for_scanning() {
-
- // Should not be used in the parallel case
- ShouldNotReachHere();
- return NULL;
-}
-
-// Save region on a stack
-void ParCompactionManager::save_for_processing(size_t region_index) {
-#ifdef ASSERT
- const ParallelCompactData& sd = PSParallelCompact::summary_data();
- ParallelCompactData::RegionData* const region_ptr = sd.region(region_index);
- assert(region_ptr->claimed(), "must be claimed");
- assert(region_ptr->_pushed++ == 0, "should only be pushed once");
-#endif
- region_stack_push(region_index);
-}
-
-void ParCompactionManager::region_stack_push(size_t region_index) {
-
-#ifdef USE_RegionTaskQueueWithOverflow
- region_stack()->save(region_index);
-#else
- if(!region_stack()->push(region_index)) {
- region_overflow_stack()->push(region_index);
- }
-#endif
-}
-
-bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
-#ifdef USE_RegionTaskQueueWithOverflow
- return region_stack()->retrieve(region_index);
-#else
- // Should not be used in the parallel case
- ShouldNotReachHere();
- return false;
-#endif
-}
-
ParCompactionManager*
ParCompactionManager::gc_thread_compaction_manager(int index) {
assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
@@ -218,8 +144,8 @@
do {
// Drain the overflow stack first, to allow stealing from the marking stack.
oop obj;
- while (!overflow_stack()->is_empty()) {
- overflow_stack()->pop()->follow_contents(this);
+ while (marking_stack()->pop_overflow(obj)) {
+ obj->follow_contents(this);
}
while (marking_stack()->pop_local(obj)) {
obj->follow_contents(this);
@@ -227,11 +153,10 @@
// Process ObjArrays one at a time to avoid marking stack bloat.
ObjArrayTask task;
- if (!_objarray_overflow_stack->is_empty()) {
- task = _objarray_overflow_stack->pop();
+ if (_objarray_stack.pop_overflow(task)) {
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
k->oop_follow_contents(this, task.obj(), task.index());
- } else if (_objarray_queue.pop_local(task)) {
+ } else if (_objarray_stack.pop_local(task)) {
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
k->oop_follow_contents(this, task.obj(), task.index());
}
@@ -240,68 +165,18 @@
assert(marking_stacks_empty(), "Sanity");
}
-void ParCompactionManager::drain_region_overflow_stack() {
- size_t region_index = (size_t) -1;
- while(region_stack()->retrieve_from_overflow(region_index)) {
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
-}
-
void ParCompactionManager::drain_region_stacks() {
-#ifdef ASSERT
- ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
- MutableSpace* to_space = heap->young_gen()->to_space();
- MutableSpace* old_space = heap->old_gen()->object_space();
- MutableSpace* perm_space = heap->perm_gen()->object_space();
-#endif /* ASSERT */
-
-#if 1 // def DO_PARALLEL - the serial code hasn't been updated
do {
-
-#ifdef USE_RegionTaskQueueWithOverflow
- // Drain overflow stack first, so other threads can steal from
- // claimed stack while we work.
- size_t region_index = (size_t) -1;
- while(region_stack()->retrieve_from_overflow(region_index)) {
+ // Drain overflow stack first so other threads can steal.
+ size_t region_index;
+ while (region_stack()->pop_overflow(region_index)) {
PSParallelCompact::fill_and_update_region(this, region_index);
}
- while (region_stack()->retrieve_from_stealable_queue(region_index)) {
+ while (region_stack()->pop_local(region_index)) {
PSParallelCompact::fill_and_update_region(this, region_index);
}
} while (!region_stack()->is_empty());
-#else
- // Drain overflow stack first, so other threads can steal from
- // claimed stack while we work.
- while(!region_overflow_stack()->is_empty()) {
- size_t region_index = region_overflow_stack()->pop();
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
-
- size_t region_index = -1;
- // obj is a reference!!!
- while (region_stack()->pop_local(region_index)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
- } while((region_stack()->size() != 0) ||
- (region_overflow_stack()->length() != 0));
-#endif
-
-#ifdef USE_RegionTaskQueueWithOverflow
- assert(region_stack()->is_empty(), "Sanity");
-#else
- assert(region_stack()->size() == 0, "Sanity");
- assert(region_overflow_stack()->length() == 0, "Sanity");
-#endif
-#else
- oop obj;
- while (obj = retrieve_for_scanning()) {
- obj->follow_contents(this);
- }
-#endif
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,10 +59,10 @@
private:
// 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB
- #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
- typedef GenericTaskQueue<ObjArrayTask, OBJARRAY_QUEUE_SIZE> ObjArrayTaskQueue;
- typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
- #undef OBJARRAY_QUEUE_SIZE
+ #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
+ typedef OverflowTaskQueue<ObjArrayTask, QUEUE_SIZE> ObjArrayTaskQueue;
+ typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
+ #undef QUEUE_SIZE
static ParCompactionManager** _manager_array;
static OopTaskQueueSet* _stack_array;
@@ -72,23 +72,13 @@
static PSOldGen* _old_gen;
private:
- OopTaskQueue _marking_stack;
- GrowableArray<oop>* _overflow_stack;
-
- typedef GrowableArray<ObjArrayTask> ObjArrayOverflowStack;
- ObjArrayTaskQueue _objarray_queue;
- ObjArrayOverflowStack* _objarray_overflow_stack;
+ OverflowTaskQueue<oop> _marking_stack;
+ ObjArrayTaskQueue _objarray_stack;
// Is there a way to reuse the _marking_stack for the
// saving empty regions? For now just create a different
// type of TaskQueue.
-
-#ifdef USE_RegionTaskQueueWithOverflow
- RegionTaskQueueWithOverflow _region_stack;
-#else
RegionTaskQueue _region_stack;
- GrowableArray<size_t>* _region_overflow_stack;
-#endif
#if 1 // does this happen enough to need a per thread stack?
GrowableArray<Klass*>* _revisit_klass_stack;
@@ -107,16 +97,8 @@
protected:
// Array of tasks. Needed by the ParallelTaskTerminator.
static RegionTaskQueueSet* region_array() { return _region_array; }
- OopTaskQueue* marking_stack() { return &_marking_stack; }
- GrowableArray<oop>* overflow_stack() { return _overflow_stack; }
-#ifdef USE_RegionTaskQueueWithOverflow
- RegionTaskQueueWithOverflow* region_stack() { return &_region_stack; }
-#else
- RegionTaskQueue* region_stack() { return &_region_stack; }
- GrowableArray<size_t>* region_overflow_stack() {
- return _region_overflow_stack;
- }
-#endif
+ OverflowTaskQueue<oop>* marking_stack() { return &_marking_stack; }
+ RegionTaskQueue* region_stack() { return &_region_stack; }
// Pushes onto the marking stack. If the marking stack is full,
// pushes onto the overflow stack.
@@ -124,11 +106,7 @@
// Do not implement an equivalent stack_pop. Deal with the
// marking stack and overflow stack directly.
- // Pushes onto the region stack. If the region stack is full,
- // pushes onto the region overflow stack.
- void region_stack_push(size_t region_index);
-
-public:
+ public:
Action action() { return _action; }
void set_action(Action v) { _action = v; }
@@ -157,22 +135,15 @@
GrowableArray<DataLayout*>* revisit_mdo_stack() { return _revisit_mdo_stack; }
#endif
- // Save oop for later processing. Must not fail.
- void save_for_scanning(oop m);
- // Get a oop for scanning. If returns null, no oop were found.
- oop retrieve_for_scanning();
-
- inline void push_objarray(oop obj, size_t index);
-
- // Save region for later processing. Must not fail.
- void save_for_processing(size_t region_index);
- // Get a region for processing. If returns null, no region were found.
- bool retrieve_for_processing(size_t& region_index);
+ // Save for later processing. Must not fail.
+ inline void push(oop obj) { _marking_stack.push(obj); }
+ inline void push_objarray(oop objarray, size_t index);
+ inline void push_region(size_t index);
// Access function for compaction managers
static ParCompactionManager* gc_thread_compaction_manager(int index);
- static bool steal(int queue_num, int* seed, Task& t) {
+ static bool steal(int queue_num, int* seed, oop& t) {
return stack_array()->steal(queue_num, seed, t);
}
@@ -180,8 +151,8 @@
return _objarray_queues->steal(queue_num, seed, t);
}
- static bool steal(int queue_num, int* seed, RegionTask& t) {
- return region_array()->steal(queue_num, seed, t);
+ static bool steal(int queue_num, int* seed, size_t& region) {
+ return region_array()->steal(queue_num, seed, region);
}
// Process tasks remaining on any marking stack
@@ -191,9 +162,6 @@
// Process tasks remaining on any stack
void drain_region_stacks();
- // Process tasks remaining on any stack
- void drain_region_overflow_stack();
-
// Debugging support
#ifdef ASSERT
bool stacks_have_been_allocated();
@@ -208,6 +176,5 @@
}
bool ParCompactionManager::marking_stacks_empty() const {
- return _marking_stack.size() == 0 && _overflow_stack->is_empty() &&
- _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty();
+ return _marking_stack.is_empty() && _objarray_stack.is_empty();
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -26,7 +26,16 @@
{
ObjArrayTask task(obj, index);
assert(task.is_valid(), "bad ObjArrayTask");
- if (!_objarray_queue.push(task)) {
- _objarray_overflow_stack->push(task);
- }
+ _objarray_stack.push(task);
}
+
+void ParCompactionManager::push_region(size_t index)
+{
+#ifdef ASSERT
+ const ParallelCompactData& sd = PSParallelCompact::summary_data();
+ ParallelCompactData::RegionData* const region_ptr = sd.region(index);
+ assert(region_ptr->claimed(), "must be claimed");
+ assert(region_ptr->_pushed++ == 0, "should only be pushed once");
+#endif
+ region_stack()->push(index);
+}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -2474,7 +2474,7 @@
for (size_t cur = end_region - 1; cur >= beg_region; --cur) {
if (sd.region(cur)->claim_unsafe()) {
ParCompactionManager* cm = ParCompactionManager::manager_array(which);
- cm->save_for_processing(cur);
+ cm->push_region(cur);
if (TraceParallelOldGCCompactionPhase && Verbose) {
const size_t count_mod_8 = fillable_regions & 7;
@@ -3138,7 +3138,7 @@
assert(cur->data_size() > 0, "region must have live data");
cur->decrement_destination_count();
if (cur < enqueue_end && cur->available() && cur->claim()) {
- cm->save_for_processing(sd.region(cur));
+ cm->push_region(sd.region(cur));
}
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1297,11 +1297,8 @@
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (mark_bitmap()->is_unmarked(obj)) {
- if (mark_obj(obj)) {
- // This thread marked the object and owns the subsequent processing of it.
- cm->save_for_scanning(obj);
- }
+ if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
+ cm->push(obj);
}
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,45 +94,13 @@
print_stats();
#endif // PS_PM_STATS
- for(uint i=0; i<ParallelGCThreads+1; i++) {
+ for (uint i = 0; i < ParallelGCThreads + 1; i++) {
PSPromotionManager* manager = manager_array(i);
-
- // the guarantees are a bit gratuitous but, if one fires, we'll
- // have a better idea of what went wrong
- if (i < ParallelGCThreads) {
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->overflow_stack_depth()->length() <= 0),
- "promotion manager overflow stack must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->overflow_stack_breadth()->length() <= 0),
- "promotion manager overflow stack must be empty");
-
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->claimed_stack_depth()->size() <= 0),
- "promotion manager claimed stack must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->claimed_stack_breadth()->size() <= 0),
- "promotion manager claimed stack must be empty");
+ if (UseDepthFirstScavengeOrder) {
+ assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
} else {
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->overflow_stack_depth()->length() <= 0),
- "VM Thread promotion manager overflow stack "
- "must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->overflow_stack_breadth()->length() <= 0),
- "VM Thread promotion manager overflow stack "
- "must be empty");
-
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->claimed_stack_depth()->size() <= 0),
- "VM Thread promotion manager claimed stack "
- "must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->claimed_stack_breadth()->size() <= 0),
- "VM Thread promotion manager claimed stack "
- "must be empty");
+ assert(manager->claimed_stack_breadth()->is_empty(), "should be empty");
}
-
manager->flush_labs();
}
}
@@ -181,15 +149,9 @@
if (depth_first()) {
claimed_stack_depth()->initialize();
queue_size = claimed_stack_depth()->max_elems();
- // We want the overflow stack to be permanent
- _overflow_stack_depth = new (ResourceObj::C_HEAP) GrowableArray<StarTask>(10, true);
- _overflow_stack_breadth = NULL;
} else {
claimed_stack_breadth()->initialize();
queue_size = claimed_stack_breadth()->max_elems();
- // We want the overflow stack to be permanent
- _overflow_stack_breadth = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
- _overflow_stack_depth = NULL;
}
_totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
@@ -209,8 +171,7 @@
}
void PSPromotionManager::reset() {
- assert(claimed_stack_empty(), "reset of non-empty claimed stack");
- assert(overflow_stack_empty(), "reset of non-empty overflow stack");
+ assert(stacks_empty(), "reset of non-empty stack");
// We need to get an assert in here to make sure the labs are always flushed.
@@ -243,7 +204,7 @@
void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
assert(depth_first(), "invariant");
- assert(overflow_stack_depth() != NULL, "invariant");
+ assert(claimed_stack_depth()->overflow_stack() != NULL, "invariant");
totally_drain = totally_drain || _totally_drain;
#ifdef ASSERT
@@ -254,41 +215,35 @@
MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */
+ OopStarTaskQueue* const tq = claimed_stack_depth();
do {
StarTask p;
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
- while(!overflow_stack_depth()->is_empty()) {
- // linux compiler wants different overloaded operator= in taskqueue to
- // assign to p that the other compilers don't like.
- StarTask ptr = overflow_stack_depth()->pop();
- process_popped_location_depth(ptr);
+ while (tq->pop_overflow(p)) {
+ process_popped_location_depth(p);
}
if (totally_drain) {
- while (claimed_stack_depth()->pop_local(p)) {
+ while (tq->pop_local(p)) {
process_popped_location_depth(p);
}
} else {
- while (claimed_stack_depth()->size() > _target_stack_size &&
- claimed_stack_depth()->pop_local(p)) {
+ while (tq->size() > _target_stack_size && tq->pop_local(p)) {
process_popped_location_depth(p);
}
}
- } while( (totally_drain && claimed_stack_depth()->size() > 0) ||
- (overflow_stack_depth()->length() > 0) );
+ } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
- assert(!totally_drain || claimed_stack_empty(), "Sanity");
- assert(totally_drain ||
- claimed_stack_depth()->size() <= _target_stack_size,
- "Sanity");
- assert(overflow_stack_empty(), "Sanity");
+ assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+ assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+ assert(tq->overflow_empty(), "Sanity");
}
void PSPromotionManager::drain_stacks_breadth(bool totally_drain) {
assert(!depth_first(), "invariant");
- assert(overflow_stack_breadth() != NULL, "invariant");
+ assert(claimed_stack_breadth()->overflow_stack() != NULL, "invariant");
totally_drain = totally_drain || _totally_drain;
#ifdef ASSERT
@@ -299,51 +254,39 @@
MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */
+ OverflowTaskQueue<oop>* const tq = claimed_stack_breadth();
do {
oop obj;
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
- while(!overflow_stack_breadth()->is_empty()) {
- obj = overflow_stack_breadth()->pop();
+ while (tq->pop_overflow(obj)) {
obj->copy_contents(this);
}
if (totally_drain) {
- // obj is a reference!!!
- while (claimed_stack_breadth()->pop_local(obj)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
+ while (tq->pop_local(obj)) {
obj->copy_contents(this);
}
} else {
- // obj is a reference!!!
- while (claimed_stack_breadth()->size() > _target_stack_size &&
- claimed_stack_breadth()->pop_local(obj)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
+ while (tq->size() > _target_stack_size && tq->pop_local(obj)) {
obj->copy_contents(this);
}
}
// If we could not find any other work, flush the prefetch queue
- if (claimed_stack_breadth()->size() == 0 &&
- (overflow_stack_breadth()->length() == 0)) {
+ if (tq->is_empty()) {
flush_prefetch_queue();
}
- } while((totally_drain && claimed_stack_breadth()->size() > 0) ||
- (overflow_stack_breadth()->length() > 0));
+ } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
- assert(!totally_drain || claimed_stack_empty(), "Sanity");
- assert(totally_drain ||
- claimed_stack_breadth()->size() <= _target_stack_size,
- "Sanity");
- assert(overflow_stack_empty(), "Sanity");
+ assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+ assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+ assert(tq->overflow_empty(), "Sanity");
}
void PSPromotionManager::flush_labs() {
- assert(claimed_stack_empty(), "Attempt to flush lab with live stack");
- assert(overflow_stack_empty(), "Attempt to flush lab with live overflow stack");
+ assert(stacks_empty(), "Attempt to flush lab with live stack");
// If either promotion lab fills up, we can flush the
// lab but not refill it, so check first.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -78,9 +78,7 @@
PrefetchQueue _prefetch_queue;
OopStarTaskQueue _claimed_stack_depth;
- GrowableArray<StarTask>* _overflow_stack_depth;
- OopTaskQueue _claimed_stack_breadth;
- GrowableArray<oop>* _overflow_stack_breadth;
+ OverflowTaskQueue<oop> _claimed_stack_breadth;
bool _depth_first;
bool _totally_drain;
@@ -97,9 +95,6 @@
template <class T> inline void claim_or_forward_internal_depth(T* p);
template <class T> inline void claim_or_forward_internal_breadth(T* p);
- GrowableArray<StarTask>* overflow_stack_depth() { return _overflow_stack_depth; }
- GrowableArray<oop>* overflow_stack_breadth() { return _overflow_stack_breadth; }
-
// On the task queues we push reference locations as well as
// partially-scanned arrays (in the latter case, we push an oop to
// the from-space image of the array and the length on the
@@ -151,18 +146,19 @@
#if PS_PM_STATS
++_total_pushes;
+ int stack_length = claimed_stack_depth()->overflow_stack()->length();
#endif // PS_PM_STATS
- if (!claimed_stack_depth()->push(p)) {
- overflow_stack_depth()->push(p);
+ claimed_stack_depth()->push(p);
+
#if PS_PM_STATS
+ if (claimed_stack_depth()->overflow_stack()->length() != stack_length) {
++_overflow_pushes;
- uint stack_length = (uint) overflow_stack_depth()->length();
- if (stack_length > _max_overflow_length) {
- _max_overflow_length = stack_length;
+ if ((uint)stack_length + 1 > _max_overflow_length) {
+ _max_overflow_length = (uint)stack_length + 1;
}
+ }
#endif // PS_PM_STATS
- }
}
void push_breadth(oop o) {
@@ -170,18 +166,19 @@
#if PS_PM_STATS
++_total_pushes;
+ int stack_length = claimed_stack_breadth()->overflow_stack()->length();
#endif // PS_PM_STATS
- if(!claimed_stack_breadth()->push(o)) {
- overflow_stack_breadth()->push(o);
+ claimed_stack_breadth()->push(o);
+
#if PS_PM_STATS
+ if (claimed_stack_breadth()->overflow_stack()->length() != stack_length) {
++_overflow_pushes;
- uint stack_length = (uint) overflow_stack_breadth()->length();
- if (stack_length > _max_overflow_length) {
- _max_overflow_length = stack_length;
+ if ((uint)stack_length + 1 > _max_overflow_length) {
+ _max_overflow_length = (uint)stack_length + 1;
}
+ }
#endif // PS_PM_STATS
- }
}
protected:
@@ -199,12 +196,10 @@
static PSPromotionManager* vm_thread_promotion_manager();
static bool steal_depth(int queue_num, int* seed, StarTask& t) {
- assert(stack_array_depth() != NULL, "invariant");
return stack_array_depth()->steal(queue_num, seed, t);
}
- static bool steal_breadth(int queue_num, int* seed, Task& t) {
- assert(stack_array_breadth() != NULL, "invariant");
+ static bool steal_breadth(int queue_num, int* seed, oop& t) {
return stack_array_breadth()->steal(queue_num, seed, t);
}
@@ -214,7 +209,7 @@
OopStarTaskQueue* claimed_stack_depth() {
return &_claimed_stack_depth;
}
- OopTaskQueue* claimed_stack_breadth() {
+ OverflowTaskQueue<oop>* claimed_stack_breadth() {
return &_claimed_stack_breadth;
}
@@ -246,25 +241,13 @@
void drain_stacks_depth(bool totally_drain);
void drain_stacks_breadth(bool totally_drain);
- bool claimed_stack_empty() {
- if (depth_first()) {
- return claimed_stack_depth()->size() <= 0;
- } else {
- return claimed_stack_breadth()->size() <= 0;
- }
- }
- bool overflow_stack_empty() {
- if (depth_first()) {
- return overflow_stack_depth()->length() <= 0;
- } else {
- return overflow_stack_breadth()->length() <= 0;
- }
+ bool depth_first() const {
+ return _depth_first;
}
bool stacks_empty() {
- return claimed_stack_empty() && overflow_stack_empty();
- }
- bool depth_first() {
- return _depth_first;
+ return depth_first() ?
+ claimed_stack_depth()->is_empty() :
+ claimed_stack_breadth()->is_empty();
}
inline void process_popped_location_depth(StarTask p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -414,7 +414,6 @@
}
// Finally, flush the promotion_manager's labs, and deallocate its stacks.
- assert(promotion_manager->claimed_stack_empty(), "Sanity");
PSPromotionManager::post_scavenge();
promotion_failure_occurred = promotion_failed();
--- a/hotspot/src/share/vm/includeDB_compiler2 Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler2 Wed Jul 05 17:18:01 2017 +0200
@@ -89,6 +89,21 @@
allocation.hpp c2_globals.hpp
+bcEscapeAnalyzer.cpp bcEscapeAnalyzer.hpp
+bcEscapeAnalyzer.cpp bitMap.inline.hpp
+bcEscapeAnalyzer.cpp bytecode.hpp
+bcEscapeAnalyzer.cpp ciConstant.hpp
+bcEscapeAnalyzer.cpp ciField.hpp
+bcEscapeAnalyzer.cpp ciMethodBlocks.hpp
+bcEscapeAnalyzer.cpp ciStreams.hpp
+
+bcEscapeAnalyzer.hpp allocation.hpp
+bcEscapeAnalyzer.hpp ciMethod.hpp
+bcEscapeAnalyzer.hpp ciMethodData.hpp
+bcEscapeAnalyzer.hpp dependencies.hpp
+bcEscapeAnalyzer.hpp growableArray.hpp
+bcEscapeAnalyzer.hpp vectset.hpp
+
block.cpp allocation.inline.hpp
block.cpp block.hpp
block.cpp cfgnode.hpp
@@ -239,6 +254,7 @@
ciEnv.cpp compileLog.hpp
ciEnv.cpp runtime.hpp
+ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp ciTypeFlow.hpp
ciMethod.cpp methodOop.hpp
--- a/hotspot/src/share/vm/includeDB_core Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_core Wed Jul 05 17:18:01 2017 +0200
@@ -301,20 +301,6 @@
barrierSet.inline.hpp barrierSet.hpp
barrierSet.inline.hpp cardTableModRefBS.hpp
-bcEscapeAnalyzer.cpp bcEscapeAnalyzer.hpp
-bcEscapeAnalyzer.cpp bitMap.inline.hpp
-bcEscapeAnalyzer.cpp bytecode.hpp
-bcEscapeAnalyzer.cpp ciConstant.hpp
-bcEscapeAnalyzer.cpp ciField.hpp
-bcEscapeAnalyzer.cpp ciMethodBlocks.hpp
-bcEscapeAnalyzer.cpp ciStreams.hpp
-
-bcEscapeAnalyzer.hpp allocation.hpp
-bcEscapeAnalyzer.hpp ciMethod.hpp
-bcEscapeAnalyzer.hpp ciMethodData.hpp
-bcEscapeAnalyzer.hpp dependencies.hpp
-bcEscapeAnalyzer.hpp growableArray.hpp
-
biasedLocking.cpp biasedLocking.hpp
biasedLocking.cpp klass.inline.hpp
biasedLocking.cpp markOop.hpp
@@ -545,6 +531,7 @@
ciCPCache.hpp ciClassList.hpp
ciCPCache.hpp ciObject.hpp
+ciCPCache.hpp cpCacheOop.hpp
ciEnv.cpp allocation.inline.hpp
ciEnv.cpp ciConstant.hpp
@@ -664,7 +651,6 @@
ciMethod.cpp abstractCompiler.hpp
ciMethod.cpp allocation.inline.hpp
-ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp bitMap.inline.hpp
ciMethod.cpp ciCallProfile.hpp
ciMethod.cpp ciExceptionHandler.hpp
@@ -823,6 +809,7 @@
ciStreams.cpp ciCallSite.hpp
ciStreams.cpp ciConstant.hpp
+ciStreams.cpp ciCPCache.hpp
ciStreams.cpp ciField.hpp
ciStreams.cpp ciStreams.hpp
ciStreams.cpp ciUtilities.hpp
@@ -962,7 +949,6 @@
classLoader.cpp timer.hpp
classLoader.cpp universe.inline.hpp
classLoader.cpp vmSymbols.hpp
-classLoader.cpp vtune.hpp
classLoader.hpp classFileParser.hpp
classLoader.hpp perfData.hpp
@@ -1002,7 +988,6 @@
codeBlob.cpp safepoint.hpp
codeBlob.cpp sharedRuntime.hpp
codeBlob.cpp vframe.hpp
-codeBlob.cpp vtune.hpp
codeBlob.hpp codeBuffer.hpp
codeBlob.hpp frame.hpp
@@ -2165,7 +2150,6 @@
interpreter.cpp stubRoutines.hpp
interpreter.cpp templateTable.hpp
interpreter.cpp timer.hpp
-interpreter.cpp vtune.hpp
interpreter.hpp cppInterpreter.hpp
interpreter.hpp stubs.hpp
@@ -2321,7 +2305,6 @@
java.cpp vmError.hpp
java.cpp vm_operations.hpp
java.cpp vm_version_<arch>.hpp
-java.cpp vtune.hpp
java.hpp os.hpp
@@ -3048,7 +3031,6 @@
nmethod.cpp scopeDesc.hpp
nmethod.cpp sharedRuntime.hpp
nmethod.cpp sweeper.hpp
-nmethod.cpp vtune.hpp
nmethod.cpp xmlstream.hpp
nmethod.hpp codeBlob.hpp
@@ -3771,7 +3753,6 @@
sharedRuntime.cpp vmSymbols.hpp
sharedRuntime.cpp vmreg_<arch>.inline.hpp
sharedRuntime.cpp vtableStubs.hpp
-sharedRuntime.cpp vtune.hpp
sharedRuntime.cpp xmlstream.hpp
sharedRuntime.hpp allocation.hpp
@@ -3935,7 +3916,6 @@
stubCodeGenerator.cpp forte.hpp
stubCodeGenerator.cpp oop.inline.hpp
stubCodeGenerator.cpp stubCodeGenerator.hpp
-stubCodeGenerator.cpp vtune.hpp
stubCodeGenerator.hpp allocation.hpp
stubCodeGenerator.hpp assembler.hpp
@@ -4456,7 +4436,6 @@
universe.cpp universe.inline.hpp
universe.cpp vmSymbols.hpp
universe.cpp vm_operations.hpp
-universe.cpp vtune.hpp
universe.hpp growableArray.hpp
universe.hpp handles.hpp
@@ -4719,7 +4698,6 @@
vtableStubs.cpp resourceArea.hpp
vtableStubs.cpp sharedRuntime.hpp
vtableStubs.cpp vtableStubs.hpp
-vtableStubs.cpp vtune.hpp
vtableStubs.hpp allocation.hpp
@@ -4733,11 +4711,6 @@
vtableStubs_<arch_model>.cpp vmreg_<arch>.inline.hpp
vtableStubs_<arch_model>.cpp vtableStubs.hpp
-vtune.hpp allocation.hpp
-
-vtune_<os_family>.cpp interpreter.hpp
-vtune_<os_family>.cpp vtune.hpp
-
watermark.hpp allocation.hpp
watermark.hpp globalDefinitions.hpp
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -136,25 +136,24 @@
// Implementation of Bytecode_invoke
void Bytecode_invoke::verify() const {
- Bytecodes::Code bc = adjusted_invoke_code();
assert(is_valid(), "check invoke");
assert(method()->constants()->cache() != NULL, "do not call this from verifier or rewriter");
}
-symbolOop Bytecode_invoke::signature() const {
+symbolOop Bytecode_member_ref::signature() const {
constantPoolOop constants = method()->constants();
return constants->signature_ref_at(index());
}
-symbolOop Bytecode_invoke::name() const {
+symbolOop Bytecode_member_ref::name() const {
constantPoolOop constants = method()->constants();
return constants->name_ref_at(index());
}
-BasicType Bytecode_invoke::result_type(Thread *thread) const {
+BasicType Bytecode_member_ref::result_type(Thread *thread) const {
symbolHandle sh(thread, signature());
ResultTypeFinder rts(sh);
rts.iterate();
@@ -167,9 +166,9 @@
KlassHandle resolved_klass;
constantPoolHandle constants(THREAD, _method->constants());
- if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
+ if (java_code() == Bytecodes::_invokedynamic) {
LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
- } else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
+ } else if (java_code() != Bytecodes::_invokeinterface) {
LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
} else {
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
@@ -178,51 +177,68 @@
}
-int Bytecode_invoke::index() const {
+int Bytecode_member_ref::index() const {
// Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
// at the same time it allocates per-call-site CP cache entries.
- Bytecodes::Code stdc = Bytecodes::java_code(code());
- Bytecode* invoke = Bytecode_at(bcp());
- if (invoke->has_index_u4(stdc))
- return invoke->get_index_u4(stdc);
+ Bytecodes::Code rawc = code();
+ Bytecode* invoke = bytecode();
+ if (invoke->has_index_u4(rawc))
+ return invoke->get_index_u4(rawc);
else
- return invoke->get_index_u2_cpcache(stdc);
+ return invoke->get_index_u2_cpcache(rawc);
}
+int Bytecode_member_ref::pool_index() const {
+ int index = this->index();
+ DEBUG_ONLY({
+ if (!bytecode()->has_index_u4(code()))
+ index -= constantPoolOopDesc::CPCACHE_INDEX_TAG;
+ });
+ return _method->constants()->cache()->entry_at(index)->constant_pool_index();
+}
// Implementation of Bytecode_field
void Bytecode_field::verify() const {
- Bytecodes::Code stdc = Bytecodes::java_code(code());
- assert(stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic ||
- stdc == Bytecodes::_putfield || stdc == Bytecodes::_getfield, "check field");
-}
-
-
-bool Bytecode_field::is_static() const {
- Bytecodes::Code stdc = Bytecodes::java_code(code());
- return stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic;
+ assert(is_valid(), "check field");
}
-int Bytecode_field::index() const {
- Bytecode* invoke = Bytecode_at(bcp());
- return invoke->get_index_u2_cpcache(Bytecodes::_getfield);
+// Implementation of Bytecode_loadconstant
+
+int Bytecode_loadconstant::raw_index() const {
+ Bytecode* bcp = bytecode();
+ Bytecodes::Code rawc = bcp->code();
+ assert(rawc != Bytecodes::_wide, "verifier prevents this");
+ if (Bytecodes::java_code(rawc) == Bytecodes::_ldc)
+ return bcp->get_index_u1(rawc);
+ else
+ return bcp->get_index_u2(rawc, false);
}
-
-// Implementation of Bytecodes loac constant
+int Bytecode_loadconstant::pool_index() const {
+ int index = raw_index();
+ if (has_cache_index()) {
+ return _method->constants()->cache()->entry_at(index)->constant_pool_index();
+ }
+ return index;
+}
-int Bytecode_loadconstant::index() const {
- Bytecodes::Code stdc = Bytecodes::java_code(code());
- if (stdc != Bytecodes::_wide) {
- if (Bytecodes::java_code(stdc) == Bytecodes::_ldc)
- return get_index_u1(stdc);
- else
- return get_index_u2(stdc, false);
+BasicType Bytecode_loadconstant::result_type() const {
+ int index = pool_index();
+ constantTag tag = _method->constants()->tag_at(index);
+ return tag.basic_type();
+}
+
+oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
+ assert(_method.not_null(), "must supply method to resolve constant");
+ int index = raw_index();
+ constantPoolOop constants = _method->constants();
+ if (has_cache_index()) {
+ return constants->resolve_cached_constant_at(index, THREAD);
+ } else {
+ return constants->resolve_constant_at(index, THREAD);
}
- stdc = Bytecodes::code_at(addr_at(1));
- return get_index_u2(stdc, true);
}
//------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -76,9 +76,13 @@
return Bytes::get_native_u2(p);
else return Bytes::get_Java_u2(p);
}
+ int get_index_u1_cpcache(Bytecodes::Code bc) const {
+ assert_same_format_as(bc); assert_index_size(1, bc);
+ return *(jubyte*)addr_at(1) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
+ }
int get_index_u2_cpcache(Bytecodes::Code bc) const {
assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc);
- return Bytes::get_native_u2(addr_at(1)) DEBUG_ONLY(+ constantPoolOopDesc::CPCACHE_INDEX_TAG);
+ return Bytes::get_native_u2(addr_at(1)) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
}
int get_index_u4(Bytecodes::Code bc) const {
assert_same_format_as(bc); assert_index_size(4, bc);
@@ -152,7 +156,7 @@
inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -174,44 +178,56 @@
inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
-// Abstraction for invoke_{virtual, static, interface, special}
+// Common code for decoding invokes and field references.
-class Bytecode_invoke: public ResourceObj {
+class Bytecode_member_ref: public ResourceObj {
protected:
methodHandle _method; // method containing the bytecode
int _bci; // position of the bytecode
- Bytecode_invoke(methodHandle method, int bci) : _method(method), _bci(bci) {}
+ Bytecode_member_ref(methodHandle method, int bci) : _method(method), _bci(bci) {}
+
+ public:
+ // Attributes
+ methodHandle method() const { return _method; }
+ int bci() const { return _bci; }
+ address bcp() const { return _method->bcp_from(bci()); }
+ Bytecode* bytecode() const { return Bytecode_at(bcp()); }
+
+ int index() const; // cache index (loaded from instruction)
+ int pool_index() const; // constant pool index
+ symbolOop name() const; // returns the name of the method or field
+ symbolOop signature() const; // returns the signature of the method or field
+
+ BasicType result_type(Thread* thread) const; // returns the result type of the getfield or invoke
+
+ Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
+ Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
+};
+
+// Abstraction for invoke_{virtual, static, interface, special}
+
+class Bytecode_invoke: public Bytecode_member_ref {
+ protected:
+ Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
public:
void verify() const;
// Attributes
- methodHandle method() const { return _method; }
- int bci() const { return _bci; }
- address bcp() const { return _method->bcp_from(bci()); }
-
- int index() const; // the constant pool index for the invoke
- symbolOop name() const; // returns the name of the invoked method
- symbolOop signature() const; // returns the signature of the invoked method
- BasicType result_type(Thread *thread) const; // returns the result type of the invoke
-
- Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
- Bytecodes::Code adjusted_invoke_code() const { return Bytecodes::java_code(code()); }
-
methodHandle static_target(TRAPS); // "specified" method (from constant pool)
// Testers
- bool is_invokeinterface() const { return adjusted_invoke_code() == Bytecodes::_invokeinterface; }
- bool is_invokevirtual() const { return adjusted_invoke_code() == Bytecodes::_invokevirtual; }
- bool is_invokestatic() const { return adjusted_invoke_code() == Bytecodes::_invokestatic; }
- bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
- bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
+ bool is_invokeinterface() const { return java_code() == Bytecodes::_invokeinterface; }
+ bool is_invokevirtual() const { return java_code() == Bytecodes::_invokevirtual; }
+ bool is_invokestatic() const { return java_code() == Bytecodes::_invokestatic; }
+ bool is_invokespecial() const { return java_code() == Bytecodes::_invokespecial; }
+ bool is_invokedynamic() const { return java_code() == Bytecodes::_invokedynamic; }
bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); }
@@ -230,7 +246,7 @@
inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
Bytecode_invoke* b = new Bytecode_invoke(method, bci);
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -240,21 +256,34 @@
}
-// Abstraction for all field accesses (put/get field/static_
-class Bytecode_field: public Bytecode {
-public:
+// Abstraction for all field accesses (put/get field/static)
+class Bytecode_field: public Bytecode_member_ref {
+ protected:
+ Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
+
+ public:
+ // Testers
+ bool is_getfield() const { return java_code() == Bytecodes::_getfield; }
+ bool is_putfield() const { return java_code() == Bytecodes::_putfield; }
+ bool is_getstatic() const { return java_code() == Bytecodes::_getstatic; }
+ bool is_putstatic() const { return java_code() == Bytecodes::_putstatic; }
+
+ bool is_getter() const { return is_getfield() || is_getstatic(); }
+ bool is_static() const { return is_getstatic() || is_putstatic(); }
+
+ bool is_valid() const { return is_getfield() ||
+ is_putfield() ||
+ is_getstatic() ||
+ is_putstatic(); }
void verify() const;
- int index() const;
- bool is_static() const;
-
// Creation
- inline friend Bytecode_field* Bytecode_field_at(const methodOop method, address bcp);
+ inline friend Bytecode_field* Bytecode_field_at(methodHandle method, int bci);
};
-inline Bytecode_field* Bytecode_field_at(const methodOop method, address bcp) {
- Bytecode_field* b = (Bytecode_field*)bcp;
- debug_only(b->verify());
+inline Bytecode_field* Bytecode_field_at(methodHandle method, int bci) {
+ Bytecode_field* b = new Bytecode_field(method, bci);
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -274,7 +303,7 @@
inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -294,7 +323,7 @@
inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -312,7 +341,7 @@
inline Bytecode_new* Bytecode_new_at(address bcp) {
Bytecode_new* b = (Bytecode_new*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -330,7 +359,7 @@
inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
@@ -348,29 +377,57 @@
inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
- debug_only(b->verify());
+ DEBUG_ONLY(b->verify());
return b;
}
// Abstraction for ldc, ldc_w and ldc2_w
-class Bytecode_loadconstant: public Bytecode {
+class Bytecode_loadconstant: public ResourceObj {
+ private:
+ int _bci;
+ methodHandle _method;
+
+ Bytecodes::Code code() const { return bytecode()->code(); }
+
+ int raw_index() const;
+
+ Bytecode_loadconstant(methodHandle method, int bci) : _method(method), _bci(bci) {}
+
public:
+ // Attributes
+ methodHandle method() const { return _method; }
+ int bci() const { return _bci; }
+ address bcp() const { return _method->bcp_from(bci()); }
+ Bytecode* bytecode() const { return Bytecode_at(bcp()); }
+
void verify() const {
+ assert(_method.not_null(), "must supply method");
Bytecodes::Code stdc = Bytecodes::java_code(code());
assert(stdc == Bytecodes::_ldc ||
stdc == Bytecodes::_ldc_w ||
stdc == Bytecodes::_ldc2_w, "load constant");
}
- int index() const;
+ // Only non-standard bytecodes (fast_aldc) have CP cache indexes.
+ bool has_cache_index() const { return code() >= Bytecodes::number_of_java_codes; }
- inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp);
+ int pool_index() const; // index into constant pool
+ int cache_index() const { // index into CP cache (or -1 if none)
+ return has_cache_index() ? raw_index() : -1;
+ }
+
+ BasicType result_type() const; // returns the result type of the ldc
+
+ oop resolve_constant(TRAPS) const;
+
+ // Creation
+ inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci);
};
-inline Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp) {
- Bytecode_loadconstant* b = (Bytecode_loadconstant*)bcp;
- debug_only(b->verify());
+inline Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci) {
+ Bytecode_loadconstant* b = new Bytecode_loadconstant(method, bci);
+ DEBUG_ONLY(b->verify());
return b;
}
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -49,6 +49,7 @@
int get_index_u1() { return *(address)_next_pc++; }
int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
+ int get_index_u1_cpcache() { return get_index_u1() + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); }
@@ -60,6 +61,7 @@
bool check_index(int i, int& cp_index, outputStream* st = tty);
void print_constant(int i, outputStream* st = tty);
void print_field_or_method(int i, outputStream* st = tty);
+ void print_field_or_method(int orig_i, int i, outputStream* st = tty);
void print_attributes(int bci, outputStream* st = tty);
void bytecode_epilog(int bci, outputStream* st = tty);
@@ -177,18 +179,29 @@
_closure->trace(method, bcp, st);
}
+void print_symbol(symbolOop sym, outputStream* st) {
+ char buf[40];
+ int len = sym->utf8_length();
+ if (len >= (int)sizeof(buf)) {
+ st->print_cr(" %s...[%d]", sym->as_C_string(buf, sizeof(buf)), len);
+ } else {
+ st->print(" ");
+ sym->print_on(st); st->cr();
+ }
+}
+
void print_oop(oop value, outputStream* st) {
if (value == NULL) {
st->print_cr(" NULL");
- } else {
+ } else if (java_lang_String::is_instance(value)) {
EXCEPTION_MARK;
Handle h_value (THREAD, value);
symbolHandle sym = java_lang_String::as_symbol(h_value, CATCH);
- if (sym->utf8_length() > 32) {
- st->print_cr(" ....");
- } else {
- sym->print_on(st); st->cr();
- }
+ print_symbol(sym(), st);
+ } else if (value->is_symbol()) {
+ print_symbol(symbolOop(value), st);
+ } else {
+ st->print_cr(" " PTR_FORMAT, (intptr_t) value);
}
}
@@ -279,16 +292,27 @@
} else if (tag.is_double()) {
st->print_cr(" %f", constants->double_at(i));
} else if (tag.is_string()) {
- oop string = constants->resolved_string_at(i);
+ oop string = constants->pseudo_string_at(i);
print_oop(string, st);
} else if (tag.is_unresolved_string()) {
- st->print_cr(" <unresolved string at %d>", i);
+ const char* string = constants->string_at_noresolve(i);
+ st->print_cr(" %s", string);
} else if (tag.is_klass()) {
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
} else if (tag.is_unresolved_klass()) {
st->print_cr(" <unresolved klass at %d>", i);
} else if (tag.is_object()) {
- st->print_cr(" " PTR_FORMAT, constants->object_at(i));
+ st->print(" <Object>");
+ print_oop(constants->object_at(i), st);
+ } else if (tag.is_method_type()) {
+ int i2 = constants->method_type_index_at(i);
+ st->print(" <MethodType> %d", i2);
+ print_oop(constants->symbol_at(i2), st);
+ } else if (tag.is_method_handle()) {
+ int kind = constants->method_handle_ref_kind_at(i);
+ int i2 = constants->method_handle_index_at(i);
+ st->print(" <MethodHandle of kind %d>", kind, i2);
+ print_field_or_method(-i, i2, st);
} else {
st->print_cr(" bad tag=%d at %d", tag.value(), i);
}
@@ -297,7 +321,10 @@
void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
int orig_i = i;
if (!check_index(orig_i, i, st)) return;
+ print_field_or_method(orig_i, i, st);
+}
+void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) {
constantPoolOop constants = method()->constants();
constantTag tag = constants->tag_at(i);
@@ -314,9 +341,11 @@
return;
}
+ symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
symbolOop name = constants->uncached_name_ref_at(i);
symbolOop signature = constants->uncached_signature_ref_at(i);
- st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
+ const char* sep = (tag.is_field() ? "/" : "");
+ st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
}
@@ -340,12 +369,20 @@
st->print_cr(" " INT32_FORMAT, get_short());
break;
case Bytecodes::_ldc:
- print_constant(get_index_u1(), st);
+ if (Bytecodes::uses_cp_cache(raw_code())) {
+ print_constant(get_index_u1_cpcache(), st);
+ } else {
+ print_constant(get_index_u1(), st);
+ }
break;
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
- print_constant(get_index_u2(), st);
+ if (Bytecodes::uses_cp_cache(raw_code())) {
+ print_constant(get_index_u2_cpcache(), st);
+ } else {
+ print_constant(get_index_u2(), st);
+ }
break;
case Bytecodes::_iload:
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -489,6 +489,9 @@
def(_return_register_finalizer , "return_register_finalizer" , "b" , NULL , T_VOID , 0, true, _return);
+ def(_fast_aldc , "fast_aldc" , "bj" , NULL , T_OBJECT, 1, true, _ldc );
+ def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , NULL , T_OBJECT, 1, true, _ldc_w );
+
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , NULL , T_VOID , 0, false);
// platform specific JVM bytecodes
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -270,6 +270,10 @@
_fast_linearswitch ,
_fast_binaryswitch ,
+ // special handling of oop constants:
+ _fast_aldc ,
+ _fast_aldc_w ,
+
_return_register_finalizer ,
_shouldnotreachhere, // For debugging
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -99,11 +99,6 @@
#endif // PRODUCT
// need to hit every safepoint in order to call zapping routine
// register the interpreter
- VTune::register_stub(
- "Interpreter",
- AbstractInterpreter::code()->code_start(),
- AbstractInterpreter::code()->code_end()
- );
Forte::register_stub(
"Interpreter",
AbstractInterpreter::code()->code_start(),
@@ -267,20 +262,6 @@
}
#endif // PRODUCT
-static BasicType constant_pool_type(methodOop method, int index) {
- constantTag tag = method->constants()->tag_at(index);
- if (tag.is_int ()) return T_INT;
- else if (tag.is_float ()) return T_FLOAT;
- else if (tag.is_long ()) return T_LONG;
- else if (tag.is_double ()) return T_DOUBLE;
- else if (tag.is_string ()) return T_OBJECT;
- else if (tag.is_unresolved_string()) return T_OBJECT;
- else if (tag.is_klass ()) return T_OBJECT;
- else if (tag.is_unresolved_klass ()) return T_OBJECT;
- ShouldNotReachHere();
- return T_ILLEGAL;
-}
-
//------------------------------------------------------------------------------------------------------------------------
// Deoptimization support
@@ -330,13 +311,15 @@
}
case Bytecodes::_ldc :
- type = constant_pool_type( method, *(bcp+1) );
- break;
-
case Bytecodes::_ldc_w : // fall through
case Bytecodes::_ldc2_w:
- type = constant_pool_type( method, Bytes::get_Java_u2(bcp+1) );
- break;
+ {
+ Thread *thread = Thread::current();
+ ResourceMark rm(thread);
+ methodHandle mh(thread, method);
+ type = Bytecode_loadconstant_at(mh, bci)->result_type();
+ break;
+ }
default:
type = Bytecodes::result_type(code);
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -83,6 +83,18 @@
}
IRT_END
+IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
+ assert(bytecode == Bytecodes::_fast_aldc ||
+ bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
+ ResourceMark rm(thread);
+ methodHandle m (thread, method(thread));
+ Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(m, bci(thread));
+ oop result = ldc->resolve_constant(THREAD);
+ DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc->cache_index()));
+ assert(result == cpce->f1(), "expected result for assembly code");
+}
+IRT_END
+
//------------------------------------------------------------------------------------------------------------------------
// Allocation
@@ -328,7 +340,7 @@
typeArrayHandle h_extable (thread, h_method->exception_table());
bool should_repeat;
int handler_bci;
- int current_bci = bcp(thread) - h_method->code_base();
+ int current_bci = bci(thread);
// Need to do this check first since when _do_not_unlock_if_synchronized
// is set, we don't want to trigger any classloading which may make calls
@@ -615,8 +627,7 @@
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
ResourceMark rm(thread);
methodHandle m (thread, method(thread));
- int bci = m->bci_from(bcp(thread));
- Bytecode_invoke* call = Bytecode_invoke_at(m, bci);
+ Bytecode_invoke* call = Bytecode_invoke_at(m, bci(thread));
symbolHandle signature (thread, call->signature());
receiver = Handle(thread,
thread->last_frame().interpreter_callee_receiver(signature));
@@ -1257,7 +1268,7 @@
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
ArgumentSizeComputer asc(invoke->signature());
int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
- Copy::conjoint_bytes(src_address, dest_address,
+ Copy::conjoint_jbytes(src_address, dest_address,
size_of_arguments * Interpreter::stackElementSize);
IRT_END
#endif
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -34,6 +34,7 @@
static frame last_frame(JavaThread *thread) { return thread->last_frame(); }
static methodOop method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); }
static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); }
+ static int bci(JavaThread *thread) { return last_frame(thread).interpreter_frame_bci(); }
static void set_bcp_and_mdp(address bcp, JavaThread*thread);
static Bytecodes::Code code(JavaThread *thread) {
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
@@ -59,6 +60,7 @@
public:
// Constants
static void ldc (JavaThread* thread, bool wide);
+ static void resolve_ldc (JavaThread* thread, Bytecodes::Code bytecode);
// Allocation
static void _new (JavaThread* thread, constantPoolOopDesc* pool, int index);
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -38,6 +38,8 @@
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Fieldref : // fall through
case JVM_CONSTANT_Methodref : // fall through
+ case JVM_CONSTANT_MethodHandle : // fall through
+ case JVM_CONSTANT_MethodType : // fall through
add_cp_cache_entry(i);
break;
}
@@ -131,6 +133,27 @@
}
+// Rewrite some ldc bytecodes to _fast_aldc
+void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide) {
+ assert((*bcp) == (is_wide ? Bytecodes::_ldc_w : Bytecodes::_ldc), "");
+ address p = bcp + offset;
+ int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
+ constantTag tag = _pool->tag_at(cp_index).value();
+ if (tag.is_method_handle() || tag.is_method_type()) {
+ int cache_index = cp_entry_to_cp_cache(cp_index);
+ if (is_wide) {
+ (*bcp) = Bytecodes::_fast_aldc_w;
+ assert(cache_index == (u2)cache_index, "");
+ Bytes::put_native_u2(p, cache_index);
+ } else {
+ (*bcp) = Bytecodes::_fast_aldc;
+ assert(cache_index == (u1)cache_index, "");
+ (*p) = (u1)cache_index;
+ }
+ }
+}
+
+
// Rewrites a method given the index_map information
void Rewriter::scan_method(methodOop method) {
@@ -198,6 +221,12 @@
case Bytecodes::_invokedynamic:
rewrite_invokedynamic(bcp, prefix_length+1);
break;
+ case Bytecodes::_ldc:
+ maybe_rewrite_ldc(bcp, prefix_length+1, false);
+ break;
+ case Bytecodes::_ldc_w:
+ maybe_rewrite_ldc(bcp, prefix_length+1, true);
+ break;
case Bytecodes::_jsr : // fall through
case Bytecodes::_jsr_w : nof_jsrs++; break;
case Bytecodes::_monitorenter : // fall through
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -66,6 +66,7 @@
void rewrite_Object_init(methodHandle m, TRAPS);
void rewrite_member_reference(address bcp, int offset);
void rewrite_invokedynamic(address bcp, int offset);
+ void maybe_rewrite_ldc(address bcp, int offset, bool is_wide);
public:
// Driver routine:
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -507,6 +507,9 @@
def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );
def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );
+ def(Bytecodes::_fast_aldc , ubcp|____|clvm|____, vtos, atos, fast_aldc , false );
+ def(Bytecodes::_fast_aldc_w , ubcp|____|clvm|____, vtos, atos, fast_aldc , true );
+
def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return , vtos );
def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ );
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -123,6 +123,7 @@
static void sipush();
static void ldc(bool wide);
static void ldc2_w();
+ static void fast_aldc(bool wide);
static void locals_index(Register reg, int offset = 1);
static void iload();
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -284,12 +284,19 @@
committed_unique_to_self(ind, MemRegion(new_end_aligned,
cur_committed.end()));
if (!uncommit_region.is_empty()) {
- if (!os::uncommit_memory((char*)uncommit_region.start(),
- uncommit_region.byte_size())) {
- assert(false, "Card table contraction failed");
- // The call failed so don't change the end of the
- // committed region. This is better than taking the
- // VM down.
+ // It is not safe to uncommit cards if the boundary between
+ // the generations is moving. A shrink can uncommit cards
+ // owned by generation A but being used by generation B.
+ if (!UseAdaptiveGCBoundary) {
+ if (!os::uncommit_memory((char*)uncommit_region.start(),
+ uncommit_region.byte_size())) {
+ assert(false, "Card table contraction failed");
+ // The call failed so don't change the end of the
+ // committed region. This is better than taking the
+ // VM down.
+ new_end_aligned = _committed[ind].end();
+ }
+ } else {
new_end_aligned = _committed[ind].end();
}
}
@@ -297,6 +304,19 @@
// In any case, we can reset the end of the current committed entry.
_committed[ind].set_end(new_end_aligned);
+#ifdef ASSERT
+ // Check that the last card in the new region is committed according
+ // to the tables.
+ bool covered = false;
+ for (int cr = 0; cr < _cur_covered_regions; cr++) {
+ if (_committed[cr].contains(new_end - 1)) {
+ covered = true;
+ break;
+ }
+ }
+ assert(covered, "Card for end of new region not committed");
+#endif
+
// The default of 0 is not necessarily clean cards.
jbyte* entry;
if (old_region.last() < _whole_heap.start()) {
@@ -354,6 +374,9 @@
addr_for((jbyte*) _committed[ind].start()),
addr_for((jbyte*) _committed[ind].last()));
}
+ // Touch the last card of the covered region to show that it
+ // is committed (or SEGV).
+ debug_only(*byte_for(_covered[ind].last());)
debug_only(verify_guard();)
}
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -179,9 +179,14 @@
}
n_covered_regions += _gen_specs[i]->n_covered_regions();
}
- assert(total_reserved % pageSize == 0, "Gen size");
+ assert(total_reserved % pageSize == 0,
+ err_msg("Gen size; total_reserved=" SIZE_FORMAT ", pageSize="
+ SIZE_FORMAT, total_reserved, pageSize));
total_reserved += perm_gen_spec->max_size();
- assert(total_reserved % pageSize == 0, "Perm Gen size");
+ assert(total_reserved % pageSize == 0,
+ err_msg("Perm size; total_reserved=" SIZE_FORMAT ", pageSize="
+ SIZE_FORMAT ", perm gen max=" SIZE_FORMAT, total_reserved,
+ pageSize, perm_gen_spec->max_size()));
if (total_reserved < perm_gen_spec->max_size()) {
vm_exit_during_initialization(overflow_msg);
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -372,6 +372,13 @@
entry->print_value_on(st);
}
break;
+ case JVM_CONSTANT_MethodHandle :
+ st->print("ref_kind=%d", cp->method_handle_ref_kind_at(index));
+ st->print(" ref_index=%d", cp->method_handle_index_at(index));
+ break;
+ case JVM_CONSTANT_MethodType :
+ st->print("signature_index=%d", cp->method_type_index_at(index));
+ break;
default:
ShouldNotReachHere();
break;
@@ -437,6 +444,7 @@
// can be non-perm, can be non-instance (array)
}
}
+ // FIXME: verify JSR 292 tags JVM_CONSTANT_MethodHandle, etc.
base++;
}
guarantee(cp->tags()->is_perm(), "should be in permspace");
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -358,6 +358,11 @@
return klass_at_noresolve(ref_index);
}
+symbolOop constantPoolOopDesc::uncached_klass_ref_at_noresolve(int which) {
+ jint ref_index = uncached_klass_ref_index_at(which);
+ return klass_at_noresolve(ref_index);
+}
+
char* constantPoolOopDesc::string_at_noresolve(int which) {
// Test entry type in case string is resolved while in here.
oop entry = *(obj_at_addr(which));
@@ -384,6 +389,119 @@
}
}
+oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
+ oop result_oop = NULL;
+ if (cache_index >= 0) {
+ assert(index < 0, "only one kind of index at a time");
+ ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
+ result_oop = cpc_entry->f1();
+ if (result_oop != NULL) {
+ return result_oop; // that was easy...
+ }
+ index = cpc_entry->constant_pool_index();
+ }
+
+ int tag_value = this_oop->tag_at(index).value();
+ switch (tag_value) {
+
+ case JVM_CONSTANT_UnresolvedClass:
+ case JVM_CONSTANT_UnresolvedClassInError:
+ case JVM_CONSTANT_Class:
+ {
+ klassOop resolved = klass_at_impl(this_oop, index, CHECK_NULL);
+ // ldc wants the java mirror.
+ result_oop = resolved->klass_part()->java_mirror();
+ break;
+ }
+
+ case JVM_CONSTANT_String:
+ case JVM_CONSTANT_UnresolvedString:
+ if (this_oop->is_pseudo_string_at(index)) {
+ result_oop = this_oop->pseudo_string_at(index);
+ break;
+ }
+ result_oop = string_at_impl(this_oop, index, CHECK_NULL);
+ break;
+
+ case JVM_CONSTANT_Object:
+ result_oop = this_oop->object_at(index);
+ break;
+
+ case JVM_CONSTANT_MethodHandle:
+ {
+ int ref_kind = this_oop->method_handle_ref_kind_at(index);
+ int callee_index = this_oop->method_handle_klass_index_at(index);
+ symbolHandle name(THREAD, this_oop->method_handle_name_ref_at(index));
+ symbolHandle signature(THREAD, this_oop->method_handle_signature_ref_at(index));
+ if (PrintMiscellaneous)
+ tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
+ ref_kind, index, this_oop->method_handle_index_at(index),
+ callee_index, name->as_C_string(), signature->as_C_string());
+ KlassHandle callee;
+ { klassOop k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
+ callee = KlassHandle(THREAD, k);
+ }
+ KlassHandle klass(THREAD, this_oop->pool_holder());
+ Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
+ callee, name, signature,
+ CHECK_NULL);
+ result_oop = value();
+ // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+ break;
+ }
+
+ case JVM_CONSTANT_MethodType:
+ {
+ symbolHandle signature(THREAD, this_oop->method_type_signature_at(index));
+ if (PrintMiscellaneous)
+ tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
+ index, this_oop->method_type_index_at(index),
+ signature->as_C_string());
+ KlassHandle klass(THREAD, this_oop->pool_holder());
+ bool ignore_is_on_bcp = false;
+ Handle value = SystemDictionary::find_method_handle_type(signature,
+ klass,
+ ignore_is_on_bcp,
+ CHECK_NULL);
+ result_oop = value();
+ // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+ break;
+ }
+
+ /* maybe some day
+ case JVM_CONSTANT_Integer:
+ case JVM_CONSTANT_Float:
+ case JVM_CONSTANT_Long:
+ case JVM_CONSTANT_Double:
+ result_oop = java_lang_boxing_object::create(...);
+ break;
+ */
+
+ default:
+ DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
+ this_oop(), index, cache_index, tag_value) );
+ assert(false, "unexpected constant tag");
+ break;
+ }
+
+ if (cache_index >= 0) {
+ // Cache the oop here also.
+ Handle result(THREAD, result_oop);
+ result_oop = NULL; // safety
+ ObjectLocker ol(this_oop, THREAD);
+ ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
+ oop result_oop2 = cpc_entry->f1();
+ if (result_oop2 != NULL) {
+ // Race condition: May already be filled in while we were trying to lock.
+ return result_oop2;
+ }
+ cpc_entry->set_f1(result());
+ return result();
+ } else {
+ return result_oop;
+ }
+}
+
oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
oop entry = *(this_oop->obj_at_addr(which));
if (entry->is_symbol()) {
@@ -690,6 +808,28 @@
}
} break;
+ case JVM_CONSTANT_MethodType:
+ {
+ int k1 = method_type_index_at(index1);
+ int k2 = cp2->method_type_index_at(index2);
+ if (k1 == k2) {
+ return true;
+ }
+ } break;
+
+ case JVM_CONSTANT_MethodHandle:
+ {
+ int k1 = method_handle_ref_kind_at(index1);
+ int k2 = cp2->method_handle_ref_kind_at(index2);
+ if (k1 == k2) {
+ int i1 = method_handle_index_at(index1);
+ int i2 = cp2->method_handle_index_at(index2);
+ if (i1 == i2) {
+ return true;
+ }
+ }
+ } break;
+
case JVM_CONSTANT_UnresolvedString:
{
symbolOop s1 = unresolved_string_at(index1);
@@ -863,6 +1003,19 @@
to_cp->symbol_at_put(to_i, s);
} break;
+ case JVM_CONSTANT_MethodType:
+ {
+ jint k = method_type_index_at(from_i);
+ to_cp->method_type_index_at_put(to_i, k);
+ } break;
+
+ case JVM_CONSTANT_MethodHandle:
+ {
+ int k1 = method_handle_ref_kind_at(from_i);
+ int k2 = method_handle_index_at(from_i);
+ to_cp->method_handle_index_at_put(to_i, k1, k2);
+ } break;
+
// Invalid is used as the tag for the second constant pool entry
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
// not be seen by itself.
@@ -1066,8 +1219,12 @@
case JVM_CONSTANT_UnresolvedClassInError:
case JVM_CONSTANT_StringIndex:
case JVM_CONSTANT_UnresolvedString:
+ case JVM_CONSTANT_MethodType:
return 3;
+ case JVM_CONSTANT_MethodHandle:
+ return 4; //tag, ref_kind, ref_index
+
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
case JVM_CONSTANT_Fieldref:
@@ -1271,6 +1428,22 @@
DBG(printf("JVM_CONSTANT_StringIndex: %hd", idx1));
break;
}
+ case JVM_CONSTANT_MethodHandle: {
+ *bytes = JVM_CONSTANT_MethodHandle;
+ int kind = method_handle_ref_kind_at(idx);
+ idx1 = method_handle_index_at(idx);
+ *(bytes+1) = (unsigned char) kind;
+ Bytes::put_Java_u2((address) (bytes+2), idx1);
+ DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1));
+ break;
+ }
+ case JVM_CONSTANT_MethodType: {
+ *bytes = JVM_CONSTANT_MethodType;
+ idx1 = method_type_index_at(idx);
+ Bytes::put_Java_u2((address) (bytes+1), idx1);
+ DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
+ break;
+ }
}
DBG(printf("\n"));
bytes += ent_size;
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -146,6 +146,16 @@
oop_store_without_check(obj_at_addr(which), oop(s));
}
+ void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
+ tag_at_put(which, JVM_CONSTANT_MethodHandle);
+ *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;
+ }
+
+ void method_type_index_at_put(int which, int ref_index) {
+ tag_at_put(which, JVM_CONSTANT_MethodType);
+ *int_at_addr(which) = ref_index;
+ }
+
// Temporary until actual use
void unresolved_string_at_put(int which, symbolOop s) {
*obj_at_addr(which) = NULL;
@@ -357,6 +367,36 @@
return *int_at_addr(which);
}
+ int method_handle_ref_kind_at(int which) {
+ assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
+ return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits
+ }
+ int method_handle_index_at(int which) {
+ assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
+ return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits
+ }
+ int method_type_index_at(int which) {
+ assert(tag_at(which).is_method_type(), "Corrupted constant pool");
+ return *int_at_addr(which);
+ }
+ // Derived queries:
+ symbolOop method_handle_name_ref_at(int which) {
+ int member = method_handle_index_at(which);
+ return impl_name_ref_at(member, true);
+ }
+ symbolOop method_handle_signature_ref_at(int which) {
+ int member = method_handle_index_at(which);
+ return impl_signature_ref_at(member, true);
+ }
+ int method_handle_klass_index_at(int which) {
+ int member = method_handle_index_at(which);
+ return impl_klass_ref_index_at(member, true);
+ }
+ symbolOop method_type_signature_at(int which) {
+ int sym = method_type_index_at(which);
+ return symbol_at(sym);
+ }
+
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
// name_and_type_ref_index_at) all expect to be passed indices obtained
// directly from the bytecode, and extracted according to java byte order.
@@ -388,6 +428,17 @@
resolve_string_constants_impl(h_this, CHECK);
}
+ // Resolve late bound constants.
+ oop resolve_constant_at(int index, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+ return resolve_constant_at_impl(h_this, index, -1, THREAD);
+ }
+
+ oop resolve_cached_constant_at(int cache_index, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+ return resolve_constant_at_impl(h_this, -1, cache_index, THREAD);
+ }
+
// Klass name matches name at offset
bool klass_name_at_matches(instanceKlassHandle k, int which);
@@ -420,6 +471,7 @@
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
// future by other Java code. These take constant pool indices rather than possibly-byte-swapped
// constant pool cache indices as do the peer methods above.
+ symbolOop uncached_klass_ref_at_noresolve(int which);
symbolOop uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
symbolOop uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
@@ -436,6 +488,8 @@
#ifdef ASSERT
enum { CPCACHE_INDEX_TAG = 0x10000 }; // helps keep CP cache indices distinct from CP indices
+#else
+ enum { CPCACHE_INDEX_TAG = 0 }; // in product mode, this zero value is a no-op
#endif //ASSERT
private:
@@ -469,6 +523,8 @@
// Resolve string constants (to prevent allocation during compilation)
static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
+ static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
+
public:
// Merging constantPoolOop support:
bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -110,6 +110,7 @@
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
friend class constantPoolCacheKlass;
+ friend class constantPoolOopDesc; //resolve_constant_at_impl => set_f1
private:
volatile intx _indices; // constant pool index & rewrite bytecodes
--- a/hotspot/src/share/vm/opto/callnode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1524,7 +1524,7 @@
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
- es = cgr->escape_state(obj_node(), phase);
+ es = cgr->escape_state(obj_node());
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
// Mark it eliminated to update any counters
this->set_eliminated();
@@ -1627,7 +1627,7 @@
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
- es = cgr->escape_state(obj_node(), phase);
+ es = cgr->escape_state(obj_node());
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
// Mark it eliminated to update any counters
this->set_eliminated();
--- a/hotspot/src/share/vm/opto/cfgnode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -472,9 +472,7 @@
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
// Break dead loop data path.
// Eagerly replace phis with top to avoid phis copies generation.
- igvn->add_users_to_worklist(n);
- igvn->hash_delete(n); // Yank from hash before hacking edges
- igvn->subsume_node(n, top);
+ igvn->replace_node(n, top);
if( max != outcnt() ) {
progress = true;
j = refresh_out_pos(j);
@@ -518,18 +516,17 @@
igvn->hash_delete(n); // Remove from worklist before modifying edges
if( n->is_Phi() ) { // Collapse all Phis
// Eagerly replace phis to avoid copies generation.
- igvn->add_users_to_worklist(n);
- igvn->hash_delete(n); // Yank from hash before hacking edges
+ Node* in;
if( cnt == 0 ) {
assert( n->req() == 1, "No data inputs expected" );
- igvn->subsume_node(n, parent_ctrl); // replaced by top
+ in = parent_ctrl; // replaced by top
} else {
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
- Node* in1 = n->in(1); // replaced by unique input
- if( n->as_Phi()->is_unsafe_data_reference(in1) )
- in1 = phase->C->top(); // replaced by top
- igvn->subsume_node(n, in1);
+ in = n->in(1); // replaced by unique input
+ if( n->as_Phi()->is_unsafe_data_reference(in) )
+ in = phase->C->top(); // replaced by top
}
+ igvn->replace_node(n, in);
}
else if( n->is_Region() ) { // Update all incoming edges
assert( !igvn->eqv(n, this), "Must be removed from DefUse edges");
@@ -2127,7 +2124,7 @@
// if it's not there, there's nothing to do.
Node* fallthru = proj_out(0);
if (fallthru != NULL) {
- phase->is_IterGVN()->subsume_node(fallthru, in(0));
+ phase->is_IterGVN()->replace_node(fallthru, in(0));
}
return phase->C->top();
}
--- a/hotspot/src/share/vm/opto/compile.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -637,34 +637,6 @@
if (failing()) return;
NOT_PRODUCT( verify_graph_edges(); )
- // Perform escape analysis
- if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
- TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
- // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction.
- PhaseGVN* igvn = initial_gvn();
- Node* oop_null = igvn->zerocon(T_OBJECT);
- Node* noop_null = igvn->zerocon(T_NARROWOOP);
-
- _congraph = new(comp_arena()) ConnectionGraph(this);
- bool has_non_escaping_obj = _congraph->compute_escape();
-
-#ifndef PRODUCT
- if (PrintEscapeAnalysis) {
- _congraph->dump();
- }
-#endif
- // Cleanup.
- if (oop_null->outcnt() == 0)
- igvn->hash_delete(oop_null);
- if (noop_null->outcnt() == 0)
- igvn->hash_delete(noop_null);
-
- if (!has_non_escaping_obj) {
- _congraph = NULL;
- }
-
- if (failing()) return;
- }
// Now optimize
Optimize();
if (failing()) return;
@@ -1601,6 +1573,20 @@
if (failing()) return;
+ // Perform escape analysis
+ if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
+ TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
+ ConnectionGraph::do_analysis(this, &igvn);
+
+ if (failing()) return;
+
+ igvn.optimize();
+ print_method("Iter GVN 3", 2);
+
+ if (failing()) return;
+
+ }
+
// Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc.
@@ -2000,6 +1986,17 @@
}
}
+#ifdef ASSERT
+ if( n->is_Mem() ) {
+ Compile* C = Compile::current();
+ int alias_idx = C->get_alias_index(n->as_Mem()->adr_type());
+ assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw ||
+ // oop will be recorded in oop map if load crosses safepoint
+ n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() ||
+ LoadNode::is_immutable_value(n->in(MemNode::Address))),
+ "raw memory operations should have control edge");
+ }
+#endif
// Count FPU ops and common calls, implements item (3)
switch( nop ) {
// Count all float operations that may use FPU
--- a/hotspot/src/share/vm/opto/compile.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -362,6 +362,7 @@
Node* macro_node(int idx) { return _macro_nodes->at(idx); }
Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
ConnectionGraph* congraph() { return _congraph;}
+ void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;}
void add_macro_node(Node * n) {
//assert(n->is_macro(), "must be a macro node");
assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
--- a/hotspot/src/share/vm/opto/doCall.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -343,7 +343,8 @@
// being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen.
ciInstanceKlass* holder_klass = dest_method->holder();
- if (!holder_klass->is_initialized() &&
+ if (!holder_klass->is_being_initialized() &&
+ !holder_klass->is_initialized() &&
!holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret,
--- a/hotspot/src/share/vm/opto/escape.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -81,18 +81,18 @@
}
#endif
-ConnectionGraph::ConnectionGraph(Compile * C) :
+ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
_nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
_processed(C->comp_arena()),
_collecting(true),
_compile(C),
+ _igvn(igvn),
_node_map(C->comp_arena()) {
_phantom_object = C->top()->_idx,
add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
// Add ConP(#NULL) and ConN(#NULL) nodes.
- PhaseGVN* igvn = C->initial_gvn();
Node* oop_null = igvn->zerocon(T_OBJECT);
_oop_null = oop_null->_idx;
assert(_oop_null < C->unique(), "should be created already");
@@ -182,7 +182,7 @@
_processed.set(n->_idx);
}
-PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) {
+PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
uint idx = n->_idx;
PointsToNode::EscapeState es;
@@ -207,22 +207,26 @@
if (n->uncast()->_idx >= nodes_size())
return PointsToNode::UnknownEscape;
+ PointsToNode::EscapeState orig_es = es;
+
// compute max escape state of anything this node could point to
VectorSet ptset(Thread::current()->resource_area());
- PointsTo(ptset, n, phase);
+ PointsTo(ptset, n);
for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
uint pt = i.elem;
PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
if (pes > es)
es = pes;
}
- // cache the computed escape state
- assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
- ptnode_adr(idx)->set_escape_state(es);
+ if (orig_es != es) {
+ // cache the computed escape state
+ assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
+ ptnode_adr(idx)->set_escape_state(es);
+ } // orig_es could be PointsToNode::UnknownEscape
return es;
}
-void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
+void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
VectorSet visited(Thread::current()->resource_area());
GrowableArray<uint> worklist;
@@ -990,7 +994,7 @@
GrowableArray<Node *> memnode_worklist;
GrowableArray<PhiNode *> orig_phis;
- PhaseGVN *igvn = _compile->initial_gvn();
+ PhaseGVN *igvn = _igvn;
uint new_index_start = (uint) _compile->num_alias_types();
Arena* arena = Thread::current()->resource_area();
VectorSet visited(arena);
@@ -1012,7 +1016,7 @@
CallNode *alloc = n->as_Call();
// copy escape information to call node
PointsToNode* ptn = ptnode_adr(alloc->_idx);
- PointsToNode::EscapeState es = escape_state(alloc, igvn);
+ PointsToNode::EscapeState es = escape_state(alloc);
// We have an allocation or call which returns a Java object,
// see if it is unescaped.
if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
@@ -1123,7 +1127,7 @@
}
} else if (n->is_AddP()) {
ptset.Clear();
- PointsTo(ptset, get_addp_base(n), igvn);
+ PointsTo(ptset, get_addp_base(n));
assert(ptset.Size() == 1, "AddP address is unique");
uint elem = ptset.getelem(); // Allocation node's index
if (elem == _phantom_object) {
@@ -1143,7 +1147,7 @@
continue; // already processed
}
ptset.Clear();
- PointsTo(ptset, n, igvn);
+ PointsTo(ptset, n);
if (ptset.Size() == 1) {
uint elem = ptset.getelem(); // Allocation node's index
if (elem == _phantom_object) {
@@ -1478,6 +1482,26 @@
return false;
}
+void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
+ // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
+ // to create space for them in ConnectionGraph::_nodes[].
+ Node* oop_null = igvn->zerocon(T_OBJECT);
+ Node* noop_null = igvn->zerocon(T_NARROWOOP);
+
+ ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
+ // Perform escape analysis
+ if (congraph->compute_escape()) {
+ // There are non escaping objects.
+ C->set_congraph(congraph);
+ }
+
+ // Cleanup.
+ if (oop_null->outcnt() == 0)
+ igvn->hash_delete(oop_null);
+ if (noop_null->outcnt() == 0)
+ igvn->hash_delete(noop_null);
+}
+
bool ConnectionGraph::compute_escape() {
Compile* C = _compile;
@@ -1492,7 +1516,7 @@
}
GrowableArray<int> cg_worklist;
- PhaseGVN* igvn = C->initial_gvn();
+ PhaseGVN* igvn = _igvn;
bool has_allocations = false;
// Push all useful nodes onto CG list and set their type.
@@ -1661,6 +1685,12 @@
_collecting = false;
assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
+#ifndef PRODUCT
+ if (PrintEscapeAnalysis) {
+ dump(); // Dump ConnectionGraph
+ }
+#endif
+
bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0;
if ( has_scalar_replaceable_candidates &&
C->AliasLevel() >= 3 && EliminateAllocations ) {
@@ -1671,10 +1701,6 @@
if (C->failing()) return false;
- // Clean up after split unique types.
- ResourceMark rm;
- PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn());
-
C->print_method("After Escape Analysis", 2);
#ifdef ASSERT
@@ -1711,7 +1737,7 @@
int offset = ptn->offset();
Node* base = get_addp_base(n);
ptset.Clear();
- PointsTo(ptset, base, phase);
+ PointsTo(ptset, base);
int ptset_size = ptset.Size();
// Check if a oop field's initializing value is recorded and add
@@ -1889,7 +1915,7 @@
arg = get_addp_base(arg);
}
ptset.Clear();
- PointsTo(ptset, arg, phase);
+ PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem;
set_escape_state(pt, PointsToNode::ArgEscape);
@@ -1934,7 +1960,7 @@
}
ptset.Clear();
- PointsTo(ptset, arg, phase);
+ PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem;
if (global_escapes) {
@@ -1970,7 +1996,7 @@
Node *arg = call->in(i)->uncast();
set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
ptset.Clear();
- PointsTo(ptset, arg, phase);
+ PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem;
set_escape_state(pt, PointsToNode::GlobalEscape);
@@ -2433,7 +2459,7 @@
Node *base = get_addp_base(n);
// Create a field edge to this node from everything base could point to.
VectorSet ptset(Thread::current()->resource_area());
- PointsTo(ptset, base, phase);
+ PointsTo(ptset, base);
for( VectorSetI i(&ptset); i.test(); ++i ) {
uint pt = i.elem;
add_field_edge(pt, n_idx, address_offset(n, phase));
@@ -2501,7 +2527,7 @@
// For everything "adr_base" could point to, create a deferred edge from
// this node to each field with the same offset.
VectorSet ptset(Thread::current()->resource_area());
- PointsTo(ptset, adr_base, phase);
+ PointsTo(ptset, adr_base);
int offset = address_offset(adr, phase);
for( VectorSetI i(&ptset); i.test(); ++i ) {
uint pt = i.elem;
@@ -2594,7 +2620,7 @@
// For everything "adr_base" could point to, create a deferred edge
// to "val" from each field with the same offset.
VectorSet ptset(Thread::current()->resource_area());
- PointsTo(ptset, adr_base, phase);
+ PointsTo(ptset, adr_base);
for( VectorSetI i(&ptset); i.test(); ++i ) {
uint pt = i.elem;
add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
@@ -2638,7 +2664,6 @@
#ifndef PRODUCT
void ConnectionGraph::dump() {
- PhaseGVN *igvn = _compile->initial_gvn();
bool first = true;
uint size = nodes_size();
@@ -2648,7 +2673,7 @@
if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
continue;
- PointsToNode::EscapeState es = escape_state(ptn->_node, igvn);
+ PointsToNode::EscapeState es = escape_state(ptn->_node);
if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
if (first) {
tty->cr();
--- a/hotspot/src/share/vm/opto/escape.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -227,6 +227,7 @@
uint _noop_null; // ConN(#NULL)
Compile * _compile; // Compile object for current compilation
+ PhaseIterGVN * _igvn; // Value numbering
// Address of an element in _nodes. Used when the element is to be modified
PointsToNode *ptnode_adr(uint idx) const {
@@ -257,7 +258,7 @@
// walk the connection graph starting at the node corresponding to "n" and
// add the index of everything it could point to, to "ptset". This may cause
// Phi's encountered to get (re)processed (which requires "phase".)
- void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase);
+ void PointsTo(VectorSet &ptset, Node * n);
// Edge manipulation. The "from_i" and "to_i" arguments are the
// node indices of the source and destination of the edge
@@ -310,7 +311,7 @@
// Node: This assumes that escape analysis is run before
// PhaseIterGVN creation
void record_for_optimizer(Node *n) {
- _compile->record_for_igvn(n);
+ _igvn->_worklist.push(n);
}
// Set the escape state of a node
@@ -320,16 +321,20 @@
void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
public:
- ConnectionGraph(Compile *C);
+ ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
// Check for non-escaping candidates
static bool has_candidates(Compile *C);
+ // Perform escape analysis
+ static void do_analysis(Compile *C, PhaseIterGVN *igvn);
+
// Compute the escape information
bool compute_escape();
// escape state of a node
- PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
+ PointsToNode::EscapeState escape_state(Node *n);
+
// other information we have collected
bool is_scalar_replaceable(Node *n) {
if (_collecting || (n->_idx >= nodes_size()))
--- a/hotspot/src/share/vm/opto/graphKit.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1789,9 +1789,10 @@
void GraphKit::increment_counter(Node* counter_addr) {
int adr_type = Compile::AliasIdxRaw;
- Node* cnt = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
+ Node* ctrl = control();
+ Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type);
Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
- store_to_memory( NULL, counter_addr, incr, T_INT, adr_type );
+ store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type );
}
@@ -2771,11 +2772,7 @@
// Update the counter for this lock. Don't bother using an atomic
// operation since we don't require absolute accuracy.
lock->create_lock_counter(map()->jvms());
- int adr_type = Compile::AliasIdxRaw;
- Node* counter_addr = makecon(TypeRawPtr::make(lock->counter()->addr()));
- Node* cnt = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
- Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
- store_to_memory(control(), counter_addr, incr, T_INT, adr_type);
+ increment_counter(lock->counter()->addr());
}
#endif
--- a/hotspot/src/share/vm/opto/ifnode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1081,11 +1081,9 @@
igvn->register_new_node_with_optimizer(new_if_f);
igvn->register_new_node_with_optimizer(new_if_t);
- igvn->hash_delete(old_if_f);
- igvn->hash_delete(old_if_t);
// Flip test, so flip trailing control
- igvn->subsume_node(old_if_f, new_if_t);
- igvn->subsume_node(old_if_t, new_if_f);
+ igvn->replace_node(old_if_f, new_if_t);
+ igvn->replace_node(old_if_t, new_if_f);
// Progress
return iff;
--- a/hotspot/src/share/vm/opto/library_call.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -3512,8 +3512,7 @@
// Get the header out of the object, use LoadMarkNode when available
Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
- Node* header = make_load(NULL, header_addr, TypeRawPtr::BOTTOM, T_ADDRESS);
- header = _gvn.transform( new (C, 2) CastP2XNode(NULL, header) );
+ Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type());
// Test the header to see if it is unlocked.
Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
@@ -5202,7 +5201,7 @@
// super_check_offset, for the desired klass.
int sco_offset = Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc);
Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset);
- Node* n3 = new(C, 3) LoadINode(NULL, immutable_memory(), p3, TypeRawPtr::BOTTOM);
+ Node* n3 = new(C, 3) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr());
Node* check_offset = _gvn.transform(n3);
Node* check_value = dest_elem_klass;
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -194,8 +194,7 @@
addx = new (phase->C, 3) AddINode(x, inv);
}
phase->register_new_node(addx, phase->get_ctrl(x));
- phase->_igvn.hash_delete(n1);
- phase->_igvn.subsume_node(n1, addx);
+ phase->_igvn.replace_node(n1, addx);
return addx;
}
@@ -1586,8 +1585,7 @@
Node *phi = cl->phi();
Node *final = new (phase->C, 3) SubINode( cl->limit(), cl->stride() );
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
- phase->_igvn.hash_delete(phi);
- phase->_igvn.subsume_node(phi,final);
+ phase->_igvn.replace_node(phi,final);
phase->C->set_major_progress();
return true;
}
--- a/hotspot/src/share/vm/opto/loopnode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -400,7 +400,7 @@
nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl));
nphi = _igvn.register_new_node_with_optimizer(nphi);
set_ctrl(nphi, get_ctrl(phi));
- _igvn.subsume_node(phi, nphi);
+ _igvn.replace_node(phi, nphi);
phi = nphi->as_Phi();
}
cmp = cmp->clone();
@@ -760,7 +760,7 @@
// which in turn prevents removing an empty loop.
Node *id_old_phi = old_phi->Identity( &igvn );
if( id_old_phi != old_phi ) { // Found a simple identity?
- // Note that I cannot call 'subsume_node' here, because
+ // Note that I cannot call 'replace_node' here, because
// that will yank the edge from old_phi to the Region and
// I'm mid-iteration over the Region's uses.
for (DUIterator_Last imin, i = old_phi->last_outs(imin); i >= imin; ) {
@@ -1065,11 +1065,9 @@
l = igvn.register_new_node_with_optimizer(l, _head);
phase->set_created_loop_node();
// Go ahead and replace _head
- phase->_igvn.subsume_node( _head, l );
+ phase->_igvn.replace_node( _head, l );
_head = l;
phase->set_loop(_head, this);
- for (DUIterator_Fast imax, i = l->fast_outs(imax); i < imax; i++)
- phase->_igvn.add_users_to_worklist(l->fast_out(i));
}
// Now recursively beautify nested loops
@@ -1329,8 +1327,7 @@
Node* add = new (C, 3) AddINode(ratio_idx, diff);
phase->_igvn.register_new_node_with_optimizer(add);
phase->set_ctrl(add, cl);
- phase->_igvn.hash_delete( phi2 );
- phase->_igvn.subsume_node( phi2, add );
+ phase->_igvn.replace_node( phi2, add );
// Sometimes an induction variable is unused
if (add->outcnt() == 0) {
phase->_igvn.remove_dead_node(add);
--- a/hotspot/src/share/vm/opto/loopnode.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -626,8 +626,7 @@
_nodes.map( old_node->_idx, (Node*)((intptr_t)new_node + 1) );
}
void lazy_replace( Node *old_node, Node *new_node ) {
- _igvn.hash_delete(old_node);
- _igvn.subsume_node( old_node, new_node );
+ _igvn.replace_node( old_node, new_node );
lazy_update( old_node, new_node );
}
void lazy_replace_proj( Node *old_node, Node *new_node ) {
--- a/hotspot/src/share/vm/opto/loopopts.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -354,8 +354,7 @@
register_new_node( var_scale, n_ctrl );
Node *var_add = new (C, 3) AddINode( var_scale, inv_scale );
register_new_node( var_add, n_ctrl );
- _igvn.hash_delete( n );
- _igvn.subsume_node( n, var_add );
+ _igvn.replace_node( n, var_add );
return var_add;
}
@@ -390,8 +389,7 @@
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, n->in(2)->in(3) );
register_new_node( add2, n_ctrl );
- _igvn.hash_delete( n );
- _igvn.subsume_node( n, add2 );
+ _igvn.replace_node( n, add2 );
return add2;
}
}
@@ -412,8 +410,7 @@
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, V );
register_new_node( add2, n_ctrl );
- _igvn.hash_delete( n );
- _igvn.subsume_node( n, add2 );
+ _igvn.replace_node( n, add2 );
return add2;
}
}
@@ -555,8 +552,7 @@
}
Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) );
register_new_node( cmov, cmov_ctrl );
- _igvn.hash_delete(phi);
- _igvn.subsume_node( phi, cmov );
+ _igvn.replace_node( phi, cmov );
#ifndef PRODUCT
if( VerifyLoopOptimizations ) verify();
#endif
@@ -642,8 +638,7 @@
// Found a Phi to split thru!
// Replace 'n' with the new phi
- _igvn.hash_delete(n);
- _igvn.subsume_node( n, phi );
+ _igvn.replace_node( n, phi );
// Moved a load around the loop, 'en-registering' something.
if( n_blk->Opcode() == Op_Loop && n->is_Load() &&
!phi->in(LoopNode::LoopBackControl)->is_Load() )
@@ -789,13 +784,11 @@
// Found a Phi to split thru!
// Replace 'n' with the new phi
- _igvn.hash_delete(n);
- _igvn.subsume_node( n, phi );
+ _igvn.replace_node( n, phi );
// Now split the bool up thru the phi
Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
- _igvn.hash_delete(bol);
- _igvn.subsume_node( bol, bolphi );
+ _igvn.replace_node( bol, bolphi );
assert( iff->in(1) == bolphi, "" );
if( bolphi->Value(&_igvn)->singleton() )
return;
@@ -803,8 +796,7 @@
// Conditional-move? Must split up now
if( !iff->is_If() ) {
Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
- _igvn.hash_delete(iff);
- _igvn.subsume_node( iff, cmovphi );
+ _igvn.replace_node( iff, cmovphi );
return;
}
@@ -950,9 +942,7 @@
if( n_op == Op_Opaque2 &&
n->in(1) != NULL &&
get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) {
- _igvn.add_users_to_worklist(n);
- _igvn.hash_delete(n);
- _igvn.subsume_node( n, n->in(1) );
+ _igvn.replace_node( n, n->in(1) );
}
}
@@ -1425,7 +1415,7 @@
// IGVN does CSE).
Node *hit = _igvn.hash_find_insert(use);
if( hit ) // Go ahead and re-hash for hits.
- _igvn.subsume_node( use, hit );
+ _igvn.replace_node( use, hit );
}
// If 'use' was in the loop-exit block, it now needs to be sunk
--- a/hotspot/src/share/vm/opto/macro.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -135,8 +135,7 @@
if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1);
copy_call_debug_info(oldcall, call);
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
- _igvn.hash_delete(oldcall);
- _igvn.subsume_node(oldcall, call);
+ _igvn.replace_node(oldcall, call);
transform_later(call);
return call;
@@ -523,8 +522,7 @@
// Kill all new Phis
while(value_phis.is_nonempty()) {
Node* n = value_phis.node();
- _igvn.hash_delete(n);
- _igvn.subsume_node(n, C->top());
+ _igvn.replace_node(n, C->top());
value_phis.pop();
}
}
@@ -1311,8 +1309,7 @@
if (!always_slow) {
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
}
- _igvn.hash_delete(alloc);
- _igvn.subsume_node(alloc, call);
+ _igvn.replace_node(alloc, call);
transform_later(call);
// Identify the output projections from the allocate node and
@@ -1431,7 +1428,7 @@
Node* mark_node = NULL;
// For now only enable fast locking for non-array types
if (UseBiasedLocking && (length == NULL)) {
- mark_node = make_load(NULL, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
+ mark_node = make_load(control, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
} else {
mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype()));
}
--- a/hotspot/src/share/vm/opto/memnode.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -815,6 +815,16 @@
}
#endif
+#ifdef ASSERT
+//----------------------------is_immutable_value-------------------------------
+// Helper function to allow a raw load without control edge for some cases
+bool LoadNode::is_immutable_value(Node* adr) {
+ return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() &&
+ adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
+ (adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
+ in_bytes(JavaThread::osthread_offset())));
+}
+#endif
//----------------------------LoadNode::make-----------------------------------
// Polymorphic factory method:
@@ -828,6 +838,11 @@
assert(!(adr_type->isa_aryptr() &&
adr_type->offset() == arrayOopDesc::length_offset_in_bytes()),
"use LoadRangeNode instead");
+ // Check control edge of raw loads
+ assert( ctl != NULL || C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
+ // oop will be recorded in oop map if load crosses safepoint
+ rt->isa_oopptr() || is_immutable_value(adr),
+ "raw memory operations should have control edge");
switch (bt) {
case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() );
case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() );
@@ -2064,6 +2079,8 @@
// Polymorphic factory method:
StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) {
Compile* C = gvn.C;
+ assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
+ ctl != NULL, "raw memory operations should have control edge");
switch (bt) {
case T_BOOLEAN:
--- a/hotspot/src/share/vm/opto/memnode.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/memnode.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -189,6 +189,10 @@
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
#endif
+#ifdef ASSERT
+ // Helper function to allow a raw load without control edge for some cases
+ static bool is_immutable_value(Node* adr);
+#endif
protected:
const Type* load_array_final_field(const TypeKlassPtr *tkls,
ciKlass* klass) const;
--- a/hotspot/src/share/vm/opto/parse.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -480,6 +480,7 @@
bool push_constant(ciConstant con, bool require_constant = false);
// implementation of object creation bytecodes
+ void emit_guard_for_new(ciInstanceKlass* klass);
void do_new();
void do_newarray(BasicType elemtype);
void do_anewarray();
--- a/hotspot/src/share/vm/opto/parse1.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -88,15 +88,16 @@
Node *local_addrs_base) {
Node *mem = memory(Compile::AliasIdxRaw);
Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
+ Node *ctl = control();
// Very similar to LoadNode::make, except we handle un-aligned longs and
// doubles on Sparc. Intel can handle them just fine directly.
Node *l;
switch( bt ) { // Signature is flattened
- case T_INT: l = new (C, 3) LoadINode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
- case T_FLOAT: l = new (C, 3) LoadFNode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
- case T_ADDRESS: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break;
- case T_OBJECT: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
+ case T_INT: l = new (C, 3) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
+ case T_FLOAT: l = new (C, 3) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
+ case T_ADDRESS: l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break;
+ case T_OBJECT: l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
case T_LONG:
case T_DOUBLE: {
// Since arguments are in reverse order, the argument address 'adr'
@@ -104,12 +105,12 @@
adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize );
if( Matcher::misaligned_doubles_ok ) {
l = (bt == T_DOUBLE)
- ? (Node*)new (C, 3) LoadDNode( 0, mem, adr, TypeRawPtr::BOTTOM )
- : (Node*)new (C, 3) LoadLNode( 0, mem, adr, TypeRawPtr::BOTTOM );
+ ? (Node*)new (C, 3) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
+ : (Node*)new (C, 3) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
} else {
l = (bt == T_DOUBLE)
- ? (Node*)new (C, 3) LoadD_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM )
- : (Node*)new (C, 3) LoadL_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM );
+ ? (Node*)new (C, 3) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
+ : (Node*)new (C, 3) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
}
break;
}
--- a/hotspot/src/share/vm/opto/parse2.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1324,33 +1324,21 @@
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
// If the constant is unresolved, run this BC once in the interpreter.
- if (iter().is_unresolved_string()) {
- uncommon_trap(Deoptimization::make_trap_request
- (Deoptimization::Reason_unloaded,
- Deoptimization::Action_reinterpret,
- iter().get_constant_index()),
- NULL, "unresolved_string");
- break;
- } else {
+ {
ciConstant constant = iter().get_constant();
- if (constant.basic_type() == T_OBJECT) {
- ciObject* c = constant.as_object();
- if (c->is_klass()) {
- // The constant returned for a klass is the ciKlass for the
- // entry. We want the java_mirror so get it.
- ciKlass* klass = c->as_klass();
- if (klass->is_loaded()) {
- constant = ciConstant(T_OBJECT, klass->java_mirror());
- } else {
- uncommon_trap(Deoptimization::make_trap_request
- (Deoptimization::Reason_unloaded,
- Deoptimization::Action_reinterpret,
- iter().get_constant_index()),
- NULL, "unresolved_klass");
- break;
- }
- }
+ if (constant.basic_type() == T_OBJECT &&
+ !constant.as_object()->is_loaded()) {
+ int index = iter().get_constant_pool_index();
+ constantTag tag = iter().get_constant_pool_tag(index);
+ uncommon_trap(Deoptimization::make_trap_request
+ (Deoptimization::Reason_unloaded,
+ Deoptimization::Action_reinterpret,
+ index),
+ NULL, tag.internal_name());
+ break;
}
+ assert(constant.basic_type() != T_OBJECT || !constant.as_object()->is_klass(),
+ "must be java_mirror of klass");
bool pushed = push_constant(constant, true);
guarantee(pushed, "must be possible to push this constant");
}
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -197,6 +197,43 @@
}
+void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
+ // Emit guarded new
+ // if (klass->_init_thread != current_thread ||
+ // klass->_init_state != being_initialized)
+ // uncommon_trap
+ Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() );
+ Node* merge = new (C, 3) RegionNode(3);
+ _gvn.set_type(merge, Type::CONTROL);
+ Node* kls = makecon(TypeKlassPtr::make(klass));
+
+ Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+ Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
+ Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS);
+ Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
+ IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+ set_control(IfTrue(iff));
+ merge->set_req(1, IfFalse(iff));
+
+ Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+ adr_node = basic_plus_adr(kls, kls, init_state_offset);
+ Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT);
+ Node* being_init = _gvn.intcon(instanceKlass::being_initialized);
+ tst = Bool( CmpI( init_state, being_init), BoolTest::eq);
+ iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+ set_control(IfTrue(iff));
+ merge->set_req(2, IfFalse(iff));
+
+ PreserveJVMState pjvms(this);
+ record_for_igvn(merge);
+ set_control(merge);
+
+ uncommon_trap(Deoptimization::Reason_uninitialized,
+ Deoptimization::Action_reinterpret,
+ klass);
+}
+
+
//------------------------------do_new-----------------------------------------
void Parse::do_new() {
kill_dead_locals();
@@ -206,7 +243,7 @@
assert(will_link, "_new: typeflow responsibility");
// Should initialize, or throw an InstantiationError?
- if (!klass->is_initialized() ||
+ if (!klass->is_initialized() && !klass->is_being_initialized() ||
klass->is_abstract() || klass->is_interface() ||
klass->name() == ciSymbol::java_lang_Class() ||
iter().is_unresolved_klass()) {
@@ -215,6 +252,9 @@
klass);
return;
}
+ if (klass->is_being_initialized()) {
+ emit_guard_for_new(klass);
+ }
Node* kls = makecon(TypeKlassPtr::make(klass));
Node* obj = new_instance(kls);
--- a/hotspot/src/share/vm/opto/phaseX.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1447,16 +1447,12 @@
Node* m = n->out(i);
if( m->is_Phi() ) {
assert(type(m) == Type::TOP, "Unreachable region should not have live phis.");
- add_users_to_worklist(m);
- hash_delete(m); // Yank from hash before hacking edges
- subsume_node(m, nn);
+ replace_node(m, nn);
--i; // deleted this phi; rescan starting with next position
}
}
}
- add_users_to_worklist(n); // Users of about-to-be-constant 'n'
- hash_delete(n); // Removed 'n' from table before subsuming it
- subsume_node(n,nn); // Update DefUse edges for new constant
+ replace_node(n,nn); // Update DefUse edges for new constant
}
return nn;
}
--- a/hotspot/src/share/vm/opto/phaseX.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -393,6 +393,10 @@
// Idealize old Node 'n' with respect to its inputs and its value
virtual Node *transform_old( Node *a_node );
+
+ // Subsume users of node 'old' into node 'nn'
+ void subsume_node( Node *old, Node *nn );
+
protected:
// Idealize new Node 'n' with respect to its inputs and its value
@@ -439,10 +443,6 @@
remove_globally_dead_node(dead);
}
- // Subsume users of node 'old' into node 'nn'
- // If no Def-Use info existed for 'nn' it will after call.
- void subsume_node( Node *old, Node *nn );
-
// Add users of 'n' to worklist
void add_users_to_worklist0( Node *n );
void add_users_to_worklist ( Node *n );
@@ -450,7 +450,7 @@
// Replace old node with new one.
void replace_node( Node *old, Node *nn ) {
add_users_to_worklist(old);
- hash_delete(old);
+ hash_delete(old); // Yank from hash before hacking edges
subsume_node(old, nn);
}
--- a/hotspot/src/share/vm/opto/split_if.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/split_if.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -217,8 +217,7 @@
register_new_node(phi, blk1);
// Remove cloned-up value from optimizer; use phi instead
- _igvn.hash_delete(n);
- _igvn.subsume_node( n, phi );
+ _igvn.replace_node( n, phi );
// (There used to be a self-recursive call to split_up() here,
// but it is not needed. All necessary forward walking is done
@@ -352,8 +351,7 @@
}
if (use_blk == NULL) { // He's dead, Jim
- _igvn.hash_delete(use);
- _igvn.subsume_node(use, C->top());
+ _igvn.replace_node(use, C->top());
}
return use_blk;
--- a/hotspot/src/share/vm/opto/superword.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1172,8 +1172,7 @@
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
for (uint j = 0; j < p->size(); j++) {
Node* pm = p->at(j);
- _igvn.hash_delete(pm);
- _igvn.subsume_node(pm, vn);
+ _igvn.replace_node(pm, vn);
}
_igvn._worklist.push(vn);
}
--- a/hotspot/src/share/vm/opto/type.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -182,6 +182,8 @@
return t->hash();
}
+#define SMALLINT ((juint)3) // a value too insignificant to consider widening
+
//--------------------------Initialize_shared----------------------------------
void Type::Initialize_shared(Compile* current) {
// This method does not need to be locked because the first system
@@ -240,6 +242,7 @@
assert( TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" );
assert( TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" );
assert( TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" );
+ assert( (juint)(TypeInt::CC->_hi - TypeInt::CC->_lo) <= SMALLINT, "CC is truly small");
TypeLong::MINUS_1 = TypeLong::make(-1); // -1
TypeLong::ZERO = TypeLong::make( 0); // 0
@@ -1054,16 +1057,21 @@
return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons();
}
-#define SMALLINT ((juint)3) // a value too insignificant to consider widening
-
-const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
+static int normalize_int_widen( jint lo, jint hi, int w ) {
// Certain normalizations keep us sane when comparing types.
// The 'SMALLINT' covers constants and also CC and its relatives.
- assert(CC == NULL || (juint)(CC->_hi - CC->_lo) <= SMALLINT, "CC is truly small");
if (lo <= hi) {
- if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin;
- if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // plain int
+ if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin;
+ if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT
+ } else {
+ if ((juint)(lo - hi) <= SMALLINT) w = Type::WidenMin;
+ if ((juint)(lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT
}
+ return w;
+}
+
+const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
+ w = normalize_int_widen(lo, hi, w);
return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons();
}
@@ -1103,14 +1111,14 @@
// Expand covered set
const TypeInt *r = t->is_int();
- // (Avoid TypeInt::make, to avoid the argument normalizations it enforces.)
- return (new TypeInt( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
+ return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
}
//------------------------------xdual------------------------------------------
// Dual: reverse hi & lo; flip widen
const Type *TypeInt::xdual() const {
- return new TypeInt(_hi,_lo,WidenMax-_widen);
+ int w = normalize_int_widen(_hi,_lo, WidenMax-_widen);
+ return new TypeInt(_hi,_lo,w);
}
//------------------------------widen------------------------------------------
@@ -1202,7 +1210,7 @@
//-----------------------------filter------------------------------------------
const Type *TypeInt::filter( const Type *kills ) const {
const TypeInt* ft = join(kills)->isa_int();
- if (ft == NULL || ft->_lo > ft->_hi)
+ if (ft == NULL || ft->empty())
return Type::TOP; // Canonical empty value
if (ft->_widen < this->_widen) {
// Do not allow the value of kill->_widen to affect the outcome.
@@ -1304,13 +1312,21 @@
return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons();
}
-const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
+static int normalize_long_widen( jlong lo, jlong hi, int w ) {
// Certain normalizations keep us sane when comparing types.
- // The '1' covers constants.
+ // The 'SMALLINT' covers constants.
if (lo <= hi) {
- if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin;
- if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // plain long
+ if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin;
+ if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG
+ } else {
+ if ((julong)(lo - hi) <= SMALLINT) w = Type::WidenMin;
+ if ((julong)(lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG
}
+ return w;
+}
+
+const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
+ w = normalize_long_widen(lo, hi, w);
return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons();
}
@@ -1351,14 +1367,14 @@
// Expand covered set
const TypeLong *r = t->is_long(); // Turn into a TypeLong
- // (Avoid TypeLong::make, to avoid the argument normalizations it enforces.)
- return (new TypeLong( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
+ return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
}
//------------------------------xdual------------------------------------------
// Dual: reverse hi & lo; flip widen
const Type *TypeLong::xdual() const {
- return new TypeLong(_hi,_lo,WidenMax-_widen);
+ int w = normalize_long_widen(_hi,_lo, WidenMax-_widen);
+ return new TypeLong(_hi,_lo,w);
}
//------------------------------widen------------------------------------------
@@ -1453,7 +1469,7 @@
//-----------------------------filter------------------------------------------
const Type *TypeLong::filter( const Type *kills ) const {
const TypeLong* ft = join(kills)->isa_long();
- if (ft == NULL || ft->_lo > ft->_hi)
+ if (ft == NULL || ft->empty())
return Type::TOP; // Canonical empty value
if (ft->_widen < this->_widen) {
// Do not allow the value of kill->_widen to affect the outcome.
--- a/hotspot/src/share/vm/prims/jvm.h Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h Wed Jul 05 17:18:01 2017 +0200
@@ -1044,7 +1044,22 @@
JVM_CONSTANT_Fieldref,
JVM_CONSTANT_Methodref,
JVM_CONSTANT_InterfaceMethodref,
- JVM_CONSTANT_NameAndType
+ JVM_CONSTANT_NameAndType,
+ JVM_CONSTANT_MethodHandle = 15, // JSR 292
+ JVM_CONSTANT_MethodType = 16 // JSR 292
+};
+
+/* JVM_CONSTANT_MethodHandle subtypes */
+enum {
+ JVM_REF_getField = 1,
+ JVM_REF_getStatic = 2,
+ JVM_REF_putField = 3,
+ JVM_REF_putStatic = 4,
+ JVM_REF_invokeVirtual = 5,
+ JVM_REF_invokeStatic = 6,
+ JVM_REF_invokeSpecial = 7,
+ JVM_REF_newInvokeSpecial = 8,
+ JVM_REF_invokeInterface = 9
};
/* Used in the newarray instruction. */
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,30 +122,8 @@
}
}
- // we must name the CodeBlob - some CodeBlobs already have names :-
- // - stubs used by compiled code to call a (static) C++ runtime routine
- // - non-relocatable machine code such as the interpreter, stubroutines, etc.
- // - various singleton blobs
- //
- // others are unnamed so we create a name :-
- // - OSR adapter (interpreter frame that has been on-stack replaced)
- // - I2C and C2I adapters
- const char* name = NULL;
- if (cb->is_runtime_stub()) {
- name = ((RuntimeStub*)cb)->name();
- }
- if (cb->is_buffer_blob()) {
- name = ((BufferBlob*)cb)->name();
- }
- if (cb->is_deoptimization_stub() || cb->is_safepoint_stub()) {
- name = ((SingletonBlob*)cb)->name();
- }
- if (cb->is_uncommon_trap_stub() || cb->is_exception_stub()) {
- name = ((SingletonBlob*)cb)->name();
- }
-
// record the CodeBlob details as a JvmtiCodeBlobDesc
- JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(name, cb->instructions_begin(),
+ JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(cb->name(), cb->instructions_begin(),
cb->instructions_end());
_global_code_blobs->append(scb);
}
@@ -197,7 +175,10 @@
jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
CodeBlobCollector collector;
- // first collect all the code blobs
+ // First collect all the code blobs. This has to be done in a
+ // single pass over the code cache with CodeCache_lock held because
+ // there isn't any safe way to iterate over regular CodeBlobs since
+ // they can be freed at any point.
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
collector.collect();
@@ -213,168 +194,28 @@
}
-// Support class to describe a nmethod in the CodeCache
-
-class nmethodDesc: public CHeapObj {
- private:
- methodHandle _method;
- address _code_begin;
- address _code_end;
- jvmtiAddrLocationMap* _map;
- jint _map_length;
- public:
- nmethodDesc(methodHandle method, address code_begin, address code_end,
- jvmtiAddrLocationMap* map, jint map_length) {
- _method = method;
- _code_begin = code_begin;
- _code_end = code_end;
- _map = map;
- _map_length = map_length;
- }
- methodHandle method() const { return _method; }
- address code_begin() const { return _code_begin; }
- address code_end() const { return _code_end; }
- jvmtiAddrLocationMap* map() const { return _map; }
- jint map_length() const { return _map_length; }
-};
-
-
-// Support class to collect a list of the nmethod CodeBlobs in
-// the CodeCache.
-//
-// Usage :-
-//
-// nmethodCollector collector;
-//
-// collector.collect();
-// JvmtiCodeBlobDesc* blob = collector.first();
-// while (blob != NULL) {
-// :
-// blob = collector.next();
-// }
-//
-class nmethodCollector : StackObj {
- private:
- GrowableArray<nmethodDesc*>* _nmethods; // collect nmethods
- int _pos; // iteration support
-
- // used during a collection
- static GrowableArray<nmethodDesc*>* _global_nmethods;
- static void do_nmethod(nmethod* nm);
- public:
- nmethodCollector() {
- _nmethods = NULL;
- _pos = -1;
- }
- ~nmethodCollector() {
- if (_nmethods != NULL) {
- for (int i=0; i<_nmethods->length(); i++) {
- nmethodDesc* blob = _nmethods->at(i);
- if (blob->map()!= NULL) {
- FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, blob->map());
- }
- }
- delete _nmethods;
- }
- }
-
- // collect list of nmethods in the cache
- void collect();
-
- // iteration support - return first code blob
- nmethodDesc* first() {
- assert(_nmethods != NULL, "not collected");
- if (_nmethods->length() == 0) {
- return NULL;
- }
- _pos = 0;
- return _nmethods->at(0);
- }
-
- // iteration support - return next code blob
- nmethodDesc* next() {
- assert(_pos >= 0, "iteration not started");
- if (_pos+1 >= _nmethods->length()) {
- return NULL;
- }
- return _nmethods->at(++_pos);
- }
-};
-
-// used during collection
-GrowableArray<nmethodDesc*>* nmethodCollector::_global_nmethods;
-
-
-// called for each nmethod in the CodeCache
-//
-// This function simply adds a descriptor for each nmethod to the global list.
-
-void nmethodCollector::do_nmethod(nmethod* nm) {
- // ignore zombies
- if (!nm->is_alive()) {
- return;
- }
-
- assert(nm->method() != NULL, "checking");
-
- // create the location map for the nmethod.
- jvmtiAddrLocationMap* map;
- jint map_length;
- JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
-
- // record the nmethod details
- methodHandle mh(nm->method());
- nmethodDesc* snm = new nmethodDesc(mh,
- nm->code_begin(),
- nm->code_end(),
- map,
- map_length);
- _global_nmethods->append(snm);
-}
-
-// collects a list of nmethod in the CodeCache.
-//
-// The created list is growable array of nmethodDesc - each one describes
-// a nmethod and includs its JVMTI address location map.
-
-void nmethodCollector::collect() {
- assert_locked_or_safepoint(CodeCache_lock);
- assert(_global_nmethods == NULL, "checking");
-
- // create the list
- _global_nmethods = new (ResourceObj::C_HEAP) GrowableArray<nmethodDesc*>(100,true);
-
- // any a descriptor for each nmethod to the list.
- CodeCache::nmethods_do(do_nmethod);
-
- // make the list the instance list
- _nmethods = _global_nmethods;
- _global_nmethods = NULL;
-}
-
// Generate a COMPILED_METHOD_LOAD event for each nnmethod
-
jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
HandleMark hm;
- nmethodCollector collector;
-
- // first collect all nmethods
- {
- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- collector.collect();
- }
- // iterate over the list and post an event for each nmethod
- nmethodDesc* nm_desc = collector.first();
- while (nm_desc != NULL) {
- methodOop method = nm_desc->method()();
- jmethodID mid = method->jmethod_id();
- assert(mid != NULL, "checking");
- JvmtiExport::post_compiled_method_load(env, mid,
- (jint)(nm_desc->code_end() - nm_desc->code_begin()),
- nm_desc->code_begin(), nm_desc->map_length(),
- nm_desc->map());
- nm_desc = collector.next();
+ // Walk the CodeCache notifying for live nmethods. The code cache
+ // may be changing while this is happening which is ok since newly
+ // created nmethod will notify normally and nmethods which are freed
+ // can be safely skipped.
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ nmethod* current = CodeCache::first_nmethod();
+ while (current != NULL) {
+ // Only notify for live nmethods
+ if (current->is_alive()) {
+ // Lock the nmethod so it can't be freed
+ nmethodLocker nml(current);
+
+ // Don't hold the lock over the notify or jmethodID creation
+ MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ current->get_and_cache_jmethod_id();
+ JvmtiExport::post_compiled_method_load(current);
+ }
+ current = CodeCache::next_nmethod(current);
}
return JVMTI_ERROR_NONE;
}
--- a/hotspot/src/share/vm/prims/methodComparator.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -163,10 +163,10 @@
case Bytecodes::_ldc : // fall through
case Bytecodes::_ldc_w : {
- Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method()(), _s_old->bcp());
- Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method()(), _s_new->bcp());
- int cpi_old = ldc_old->index();
- int cpi_new = ldc_new->index();
+ Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method(), _s_old->bci());
+ Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
+ int cpi_old = ldc_old->pool_index();
+ int cpi_new = ldc_new->pool_index();
constantTag tag_old = _old_cp->tag_at(cpi_old);
constantTag tag_new = _new_cp->tag_at(cpi_new);
if (tag_old.is_int() || tag_old.is_float()) {
@@ -187,12 +187,30 @@
if (strcmp(_old_cp->string_at_noresolve(cpi_old),
_new_cp->string_at_noresolve(cpi_new)) != 0)
return false;
- } else { // tag_old should be klass - 4881222
+ } else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
+ // tag_old should be klass - 4881222
if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
return false;
if (_old_cp->klass_at_noresolve(cpi_old) !=
_new_cp->klass_at_noresolve(cpi_new))
return false;
+ } else if (tag_old.is_method_type() && tag_new.is_method_type()) {
+ int mti_old = _old_cp->method_type_index_at(cpi_old);
+ int mti_new = _new_cp->method_type_index_at(cpi_new);
+ if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new)))
+ return false;
+ } else if (tag_old.is_method_handle() && tag_new.is_method_handle()) {
+ if (_old_cp->method_handle_ref_kind_at(cpi_old) !=
+ _new_cp->method_handle_ref_kind_at(cpi_new))
+ return false;
+ int mhi_old = _old_cp->method_handle_index_at(cpi_old);
+ int mhi_new = _new_cp->method_handle_index_at(cpi_new);
+ if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) ||
+ (_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) ||
+ (_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new)))
+ return false;
+ } else {
+ return false; // unknown tag
}
break;
}
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1376,11 +1376,6 @@
}
no_shared_spaces();
- // Set the maximum pause time goal to be a reasonable default.
- if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
- FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
- }
-
if (FLAG_IS_DEFAULT(MarkStackSize)) {
FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE);
}
@@ -1513,6 +1508,9 @@
if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
}
+ if (AggressiveOpts && FLAG_IS_DEFAULT(OptimizeStringConcat)) {
+ FLAG_SET_DEFAULT(OptimizeStringConcat, true);
+ }
#endif
if (AggressiveOpts) {
@@ -1697,20 +1695,21 @@
status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
- // Check user specified sharing option conflict with Parallel GC
- bool cannot_share = ((UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC || UseParNewGC ||
- UseParallelGC || UseParallelOldGC ||
- SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages));
-
+ // Check whether user-specified sharing option conflicts with GC or page size.
+ // Both sharing and large pages are enabled by default on some platforms;
+ // large pages override sharing only if explicitly set on the command line.
+ const bool cannot_share = UseConcMarkSweepGC || CMSIncrementalMode ||
+ UseG1GC || UseParNewGC || UseParallelGC || UseParallelOldGC ||
+ UseLargePages && FLAG_IS_CMDLINE(UseLargePages);
if (cannot_share) {
// Either force sharing on by forcing the other options off, or
// force sharing off.
if (DumpSharedSpaces || ForceSharedSpaces) {
jio_fprintf(defaultStream::error_stream(),
- "Reverting to Serial GC because of %s\n",
- ForceSharedSpaces ? " -Xshare:on" : "-Xshare:dump");
+ "Using Serial GC and default page size because of %s\n",
+ ForceSharedSpaces ? "-Xshare:on" : "-Xshare:dump");
force_serial_gc();
- FLAG_SET_DEFAULT(SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages), false);
+ FLAG_SET_DEFAULT(UseLargePages, false);
} else {
if (UseSharedSpaces && Verbose) {
jio_fprintf(defaultStream::error_stream(),
@@ -1719,6 +1718,8 @@
}
no_shared_spaces();
}
+ } else if (UseLargePages && (UseSharedSpaces || DumpSharedSpaces)) {
+ FLAG_SET_DEFAULT(UseLargePages, false);
}
status = status && check_gc_consistency();
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1975,7 +1975,7 @@
"Adaptive size policy maximum GC pause time goal in msec, " \
"or (G1 Only) the max. GC time per MMU time slice") \
\
- product(intx, GCPauseIntervalMillis, 500, \
+ product(uintx, GCPauseIntervalMillis, 0, \
"Time slice for MMU specification") \
\
product(uintx, MaxGCMinorPauseMillis, max_uintx, \
@@ -2541,9 +2541,6 @@
"Enable String cache capabilities on String.java") \
\
/* statistics */ \
- develop(bool, UseVTune, false, \
- "enable support for Intel's VTune profiler") \
- \
develop(bool, CountCompiledCalls, false, \
"counts method invocations") \
\
--- a/hotspot/src/share/vm/runtime/init.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/init.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -34,7 +34,6 @@
// Initialization done by Java thread in init_globals()
void management_init();
-void vtune_init();
void bytecodes_init();
void classLoader_init();
void codeCache_init();
@@ -82,7 +81,6 @@
jint init_globals() {
HandleMark hm;
management_init();
- vtune_init();
bytecodes_init();
classLoader_init();
codeCache_init();
--- a/hotspot/src/share/vm/runtime/java.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -432,8 +432,6 @@
print_statistics();
Universe::heap()->print_tracing_info();
- VTune::exit();
-
{ MutexLocker ml(BeforeExit_lock);
_before_exit_status = BEFORE_EXIT_DONE;
BeforeExit_lock->notify_all();
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -66,6 +66,7 @@
jobject JNIHandles::make_global(Handle obj) {
+ assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
jobject res = NULL;
if (!obj.is_null()) {
// ignore null handles
@@ -81,6 +82,7 @@
jobject JNIHandles::make_weak_global(Handle obj) {
+ assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
jobject res = NULL;
if (!obj.is_null()) {
// ignore null handles
--- a/hotspot/src/share/vm/runtime/os.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -886,6 +886,11 @@
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
+
+ // ## TEMPORARY hack to keep the legacy launcher working when
+ // ## only the boot module is installed (cf. j.l.ClassLoader)
+ "%/lib/modules/jdk.boot.jar:"
+
"%/classes";
char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
if (sysclasspath == NULL) return false;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -779,7 +779,7 @@
// Find bytecode
Bytecode_invoke* bytecode = Bytecode_invoke_at(caller, bci);
- bc = bytecode->adjusted_invoke_code();
+ bc = bytecode->java_code();
int bytecode_index = bytecode->index();
// Find receiver for non-static call
@@ -2251,7 +2251,6 @@
B->name(),
fingerprint->as_string(),
B->instructions_begin());
- VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +132,6 @@
_cdesc->set_end(_cgen->assembler()->pc());
assert(StubCodeDesc::_list == _cdesc, "expected order on list");
_cgen->stub_epilog(_cdesc);
- VTune::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -135,28 +135,32 @@
static void test_arraycopy_func(address func, int alignment) {
int v = 0xcc;
int v2 = 0x11;
- jlong lbuffer[2];
- jlong lbuffer2[2];
- address buffer = (address) lbuffer;
- address buffer2 = (address) lbuffer2;
+ jlong lbuffer[8];
+ jlong lbuffer2[8];
+ address fbuffer = (address) lbuffer;
+ address fbuffer2 = (address) lbuffer2;
unsigned int i;
for (i = 0; i < sizeof(lbuffer); i++) {
- buffer[i] = v; buffer2[i] = v2;
+ fbuffer[i] = v; fbuffer2[i] = v2;
}
+ // C++ does not guarantee jlong[] array alignment to 8 bytes.
+ // Use middle of array to check that memory before it is not modified.
+ address buffer = (address) round_to((intptr_t)&lbuffer[4], BytesPerLong);
+ address buffer2 = (address) round_to((intptr_t)&lbuffer2[4], BytesPerLong);
// do an aligned copy
((arraycopy_fn)func)(buffer, buffer2, 0);
for (i = 0; i < sizeof(lbuffer); i++) {
- assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+ assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
}
// adjust destination alignment
((arraycopy_fn)func)(buffer, buffer2 + alignment, 0);
for (i = 0; i < sizeof(lbuffer); i++) {
- assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+ assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
}
// adjust source alignment
((arraycopy_fn)func)(buffer + alignment, buffer2, 0);
for (i = 0; i < sizeof(lbuffer); i++) {
- assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+ assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
}
}
#endif
@@ -183,7 +187,7 @@
test_arraycopy_func(arrayof_##type##_arraycopy(), sizeof(HeapWord)); \
test_arraycopy_func(arrayof_##type##_disjoint_arraycopy(), sizeof(HeapWord))
- // Make sure all the arraycopy stubs properly handle zeros
+ // Make sure all the arraycopy stubs properly handle zero count
TEST_ARRAYCOPY(jbyte);
TEST_ARRAYCOPY(jshort);
TEST_ARRAYCOPY(jint);
@@ -191,6 +195,25 @@
#undef TEST_ARRAYCOPY
+#define TEST_COPYRTN(type) \
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_##type##s_atomic), sizeof(type)); \
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::arrayof_conjoint_##type##s), (int)MAX2(sizeof(HeapWord), sizeof(type)))
+
+ // Make sure all the copy runtime routines properly handle zero count
+ TEST_COPYRTN(jbyte);
+ TEST_COPYRTN(jshort);
+ TEST_COPYRTN(jint);
+ TEST_COPYRTN(jlong);
+
+#undef TEST_COPYRTN
+
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_words), sizeof(HeapWord));
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words), sizeof(HeapWord));
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words_atomic), sizeof(HeapWord));
+ // Aligned to BytesPerLong
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong));
+ test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong));
+
#endif
}
@@ -221,15 +244,13 @@
#ifndef PRODUCT
SharedRuntime::_jbyte_array_copy_ctr++; // Slow-path byte array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
- Copy::conjoint_bytes_atomic(src, dest, count);
+ Copy::conjoint_jbytes_atomic(src, dest, count);
JRT_END
JRT_LEAF(void, StubRoutines::jshort_copy(jshort* src, jshort* dest, size_t count))
#ifndef PRODUCT
SharedRuntime::_jshort_array_copy_ctr++; // Slow-path short/char array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::conjoint_jshorts_atomic(src, dest, count);
JRT_END
@@ -237,7 +258,6 @@
#ifndef PRODUCT
SharedRuntime::_jint_array_copy_ctr++; // Slow-path int/float array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::conjoint_jints_atomic(src, dest, count);
JRT_END
@@ -245,7 +265,6 @@
#ifndef PRODUCT
SharedRuntime::_jlong_array_copy_ctr++; // Slow-path long/double array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::conjoint_jlongs_atomic(src, dest, count);
JRT_END
@@ -263,15 +282,13 @@
#ifndef PRODUCT
SharedRuntime::_jbyte_array_copy_ctr++; // Slow-path byte array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
- Copy::arrayof_conjoint_bytes(src, dest, count);
+ Copy::arrayof_conjoint_jbytes(src, dest, count);
JRT_END
JRT_LEAF(void, StubRoutines::arrayof_jshort_copy(HeapWord* src, HeapWord* dest, size_t count))
#ifndef PRODUCT
SharedRuntime::_jshort_array_copy_ctr++; // Slow-path short/char array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::arrayof_conjoint_jshorts(src, dest, count);
JRT_END
@@ -279,7 +296,6 @@
#ifndef PRODUCT
SharedRuntime::_jint_array_copy_ctr++; // Slow-path int/float array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::arrayof_conjoint_jints(src, dest, count);
JRT_END
@@ -287,7 +303,6 @@
#ifndef PRODUCT
SharedRuntime::_jlong_array_copy_ctr++; // Slow-path int/float array copy
#endif // !PRODUCT
- assert(count != 0, "count should be non-zero");
Copy::arrayof_conjoint_jlongs(src, dest, count);
JRT_END
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,15 +26,16 @@
# include "incls/_sweeper.cpp.incl"
long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
-CodeBlob* NMethodSweeper::_current = NULL; // Current nmethod
-int NMethodSweeper::_seen = 0 ; // No. of blobs we have currently processed in current pass of CodeCache
-int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+nmethod* NMethodSweeper::_current = NULL; // Current nmethod
+int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
+
+volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
jint NMethodSweeper::_locked_seen = 0;
jint NMethodSweeper::_not_entrant_seen_on_stack = 0;
bool NMethodSweeper::_rescan = false;
bool NMethodSweeper::_do_sweep = false;
-jint NMethodSweeper::_sweep_started = 0;
bool NMethodSweeper::_was_full = false;
jint NMethodSweeper::_advise_to_sweep = 0;
jlong NMethodSweeper::_last_was_full = 0;
@@ -108,23 +109,14 @@
// code cache is filling up
_last_was_full = os::javaTimeMillis();
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
}
}
}
}
void NMethodSweeper::possibly_sweep() {
+ assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
if ((!MethodFlushing) || (!_do_sweep)) return;
if (_invocations > 0) {
@@ -133,32 +125,31 @@
if (old != 0) {
return;
}
- sweep_code_cache();
+ if (_invocations > 0) {
+ sweep_code_cache();
+ _invocations--;
+ }
+ _sweep_started = 0;
}
- _sweep_started = 0;
}
void NMethodSweeper::sweep_code_cache() {
#ifdef ASSERT
jlong sweep_start;
- if(PrintMethodFlushing) {
+ if (PrintMethodFlushing) {
sweep_start = os::javaTimeMillis();
}
#endif
if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_blobs(), _invocations);
+ tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
}
- // We want to visit all nmethods after NmethodSweepFraction invocations.
- // If invocation is 1 we do the rest
- int todo = CodeCache::nof_blobs();
- if (_invocations > 1) {
- todo = (CodeCache::nof_blobs() - _seen) / _invocations;
- }
-
- // Compilers may check to sweep more often than stack scans happen,
- // don't keep trying once it is all scanned
- _invocations--;
+ // We want to visit all nmethods after NmethodSweepFraction
+ // invocations so divide the remaining number of nmethods by the
+ // remaining number of invocations. This is only an estimate since
+ // the number of nmethods changes during the sweep so the final
+ // stage must iterate until it there are no more nmethods.
+ int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -166,26 +157,25 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- for(int i = 0; i < todo && _current != NULL; i++) {
+ // The last invocation iterates until there are no more nmethods
+ for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
- // Since we will give up the CodeCache_lock, always skip ahead to an nmethod.
- // Other blobs can be deleted by other threads
- // Read next before we potentially delete current
- CodeBlob* next = CodeCache::next_nmethod(_current);
+ // Since we will give up the CodeCache_lock, always skip ahead
+ // to the next nmethod. Other blobs can be deleted by other
+ // threads but nmethods are only reclaimed by the sweeper.
+ nmethod* next = CodeCache::next_nmethod(_current);
// Now ready to process nmethod and give up CodeCache_lock
{
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- process_nmethod((nmethod *)_current);
+ process_nmethod(_current);
}
_seen++;
_current = next;
}
+ }
- // Skip forward to the next nmethod (if any). Code blobs other than nmethods
- // can be freed async to us and make _current invalid while we sleep.
- _current = CodeCache::next_nmethod(_current);
- }
+ assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
// we've completed a scan without making progress but there were
@@ -205,6 +195,10 @@
tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
}
#endif
+
+ if (_invocations == 1) {
+ log_sweep("finished");
+ }
}
@@ -227,7 +221,7 @@
if (nm->is_zombie()) {
// If it is first time, we see nmethod then we mark it. Otherwise,
// we reclame it. When we have seen a zombie method twice, we know that
- // there are no inline caches that referes to it.
+ // there are no inline caches that refer to it.
if (nm->is_marked_for_reclamation()) {
assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
if (PrintMethodFlushing && Verbose) {
@@ -324,16 +318,8 @@
jlong curr_interval = now - _last_was_full;
if (curr_interval < max_interval) {
_rescan = true;
- if (PrintMethodFlushing) {
- tty->print_cr("### handle full too often, turning off compiler");
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("disable_compiler flushing_interval='" UINT64_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- curr_interval/1000, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("disable_compiler", "flushing_interval='" UINT64_FORMAT "'",
+ curr_interval/1000);
return;
}
}
@@ -353,17 +339,7 @@
if ((!was_full()) && (is_full)) {
if (!CodeCache::needs_flushing()) {
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
return;
}
@@ -372,17 +348,7 @@
// Traverse the code cache trying to dump the oldest nmethods
uint curr_max_comp_id = CompileBroker::get_compilation_id();
uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
- if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Cleaning code cache: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("start_cleaning_code_cache live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("start_cleaning");
nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
jint disconnected = 0;
@@ -415,13 +381,9 @@
nm = CodeCache::alive_nmethod(CodeCache::next(nm));
}
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("stop_cleaning_code_cache disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("stop_cleaning",
+ "disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'",
+ disconnected, made_not_entrant);
// Shut off compiler. Sweeper will start over with a new stack scan and
// traversal cycle and turn it back on if it clears enough space.
@@ -439,3 +401,38 @@
}
#endif
}
+
+
+// Print out some state information about the current sweep and the
+// state of the code cache if it's requested.
+void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
+ if (PrintMethodFlushing) {
+ ttyLocker ttyl;
+ tty->print("### sweeper: %s ", msg);
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ tty->vprint(format, ap);
+ va_end(ap);
+ }
+ tty->print_cr(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ }
+
+ if (LogCompilation && (xtty != NULL)) {
+ ttyLocker ttyl;
+ xtty->begin_elem("sweeper state='%s' traversals='" INTX_FORMAT "' ", msg, (intx)traversal_count());
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ xtty->vprint(format, ap);
+ va_end(ap);
+ }
+ xtty->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ xtty->stamp();
+ xtty->end_elem();
+ }
+}
--- a/hotspot/src/share/vm/runtime/sweeper.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,14 +29,15 @@
class NMethodSweeper : public AllStatic {
static long _traversals; // Stack traversal count
- static CodeBlob* _current; // Current nmethod
+ static nmethod* _current; // Current nmethod
static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache
- static int _invocations; // No. of invocations left until we are completed with this pass
+
+ static volatile int _invocations; // No. of invocations left until we are completed with this pass
+ static volatile int _sweep_started; // Flag to control conc sweeper
static bool _rescan; // Indicates that we should do a full rescan of the
// of the code cache looking for work to do.
static bool _do_sweep; // Flag to skip the conc sweep if no stack scan happened
- static jint _sweep_started; // Flag to control conc sweeper
static int _locked_seen; // Number of locked nmethods encountered during the scan
static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
@@ -47,6 +48,9 @@
static long _was_full_traversal; // trav number at last emergency unloading
static void process_nmethod(nmethod *nm);
+
+ static void log_sweep(const char* msg, const char* format = NULL, ...);
+
public:
static long traversal_count() { return _traversals; }
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -747,6 +747,8 @@
ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ;
+ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL ;
+int ObjectSynchronizer::gOmInUseCount = 0;
static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache
static volatile int MonitorFreeCount = 0 ; // # on gFreeList
static volatile int MonitorPopulation = 0 ; // # Extant -- in circulation
@@ -826,6 +828,22 @@
}
}
}
+/* Too slow for general assert or debug
+void ObjectSynchronizer::verifyInUse (Thread *Self) {
+ ObjectMonitor* mid;
+ int inusetally = 0;
+ for (mid = Self->omInUseList; mid != NULL; mid = mid->FreeNext) {
+ inusetally ++;
+ }
+ assert(inusetally == Self->omInUseCount, "inuse count off");
+
+ int freetally = 0;
+ for (mid = Self->omFreeList; mid != NULL; mid = mid->FreeNext) {
+ freetally ++;
+ }
+ assert(freetally == Self->omFreeCount, "free count off");
+}
+*/
ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
// A large MAXPRIVATE value reduces both list lock contention
@@ -853,6 +871,9 @@
m->FreeNext = Self->omInUseList;
Self->omInUseList = m;
Self->omInUseCount ++;
+ // verifyInUse(Self);
+ } else {
+ m->FreeNext = NULL;
}
return m ;
}
@@ -874,13 +895,12 @@
guarantee (take->object() == NULL, "invariant") ;
guarantee (!take->is_busy(), "invariant") ;
take->Recycle() ;
- omRelease (Self, take) ;
+ omRelease (Self, take, false) ;
}
Thread::muxRelease (&ListLock) ;
Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;
if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
TEVENT (omFirst - reprovision) ;
- continue ;
const int mx = MonitorBound ;
if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) {
@@ -961,11 +981,34 @@
// That is, *not* one-at-a-time.
-void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m) {
+void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m, bool fromPerThreadAlloc) {
guarantee (m->object() == NULL, "invariant") ;
- m->FreeNext = Self->omFreeList ;
- Self->omFreeList = m ;
- Self->omFreeCount ++ ;
+
+ // Remove from omInUseList
+ if (MonitorInUseLists && fromPerThreadAlloc) {
+ ObjectMonitor* curmidinuse = NULL;
+ for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; ) {
+ if (m == mid) {
+ // extract from per-thread in-use-list
+ if (mid == Self->omInUseList) {
+ Self->omInUseList = mid->FreeNext;
+ } else if (curmidinuse != NULL) {
+ curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+ }
+ Self->omInUseCount --;
+ // verifyInUse(Self);
+ break;
+ } else {
+ curmidinuse = mid;
+ mid = mid->FreeNext;
+ }
+ }
+ }
+
+ // FreeNext is used for both onInUseList and omFreeList, so clear old before setting new
+ m->FreeNext = Self->omFreeList ;
+ Self->omFreeList = m ;
+ Self->omFreeCount ++ ;
}
// Return the monitors of a moribund thread's local free list to
@@ -975,6 +1018,10 @@
// consecutive STW safepoints. Relatedly, we might decay
// omFreeProvision at STW safepoints.
//
+// Also return the monitors of a moribund thread"s omInUseList to
+// a global gOmInUseList under the global list lock so these
+// will continue to be scanned.
+//
// We currently call omFlush() from the Thread:: dtor _after the thread
// has been excised from the thread list and is no longer a mutator.
// That means that omFlush() can run concurrently with a safepoint and
@@ -987,24 +1034,50 @@
void ObjectSynchronizer::omFlush (Thread * Self) {
ObjectMonitor * List = Self->omFreeList ; // Null-terminated SLL
Self->omFreeList = NULL ;
- if (List == NULL) return ;
ObjectMonitor * Tail = NULL ;
- ObjectMonitor * s ;
int Tally = 0;
- for (s = List ; s != NULL ; s = s->FreeNext) {
- Tally ++ ;
- Tail = s ;
- guarantee (s->object() == NULL, "invariant") ;
- guarantee (!s->is_busy(), "invariant") ;
- s->set_owner (NULL) ; // redundant but good hygiene
- TEVENT (omFlush - Move one) ;
+ if (List != NULL) {
+ ObjectMonitor * s ;
+ for (s = List ; s != NULL ; s = s->FreeNext) {
+ Tally ++ ;
+ Tail = s ;
+ guarantee (s->object() == NULL, "invariant") ;
+ guarantee (!s->is_busy(), "invariant") ;
+ s->set_owner (NULL) ; // redundant but good hygiene
+ TEVENT (omFlush - Move one) ;
+ }
+ guarantee (Tail != NULL && List != NULL, "invariant") ;
}
- guarantee (Tail != NULL && List != NULL, "invariant") ;
+ ObjectMonitor * InUseList = Self->omInUseList;
+ ObjectMonitor * InUseTail = NULL ;
+ int InUseTally = 0;
+ if (InUseList != NULL) {
+ Self->omInUseList = NULL;
+ ObjectMonitor *curom;
+ for (curom = InUseList; curom != NULL; curom = curom->FreeNext) {
+ InUseTail = curom;
+ InUseTally++;
+ }
+// TODO debug
+ assert(Self->omInUseCount == InUseTally, "inuse count off");
+ Self->omInUseCount = 0;
+ guarantee (InUseTail != NULL && InUseList != NULL, "invariant");
+ }
+
Thread::muxAcquire (&ListLock, "omFlush") ;
- Tail->FreeNext = gFreeList ;
- gFreeList = List ;
- MonitorFreeCount += Tally;
+ if (Tail != NULL) {
+ Tail->FreeNext = gFreeList ;
+ gFreeList = List ;
+ MonitorFreeCount += Tally;
+ }
+
+ if (InUseTail != NULL) {
+ InUseTail->FreeNext = gOmInUseList;
+ gOmInUseList = InUseList;
+ gOmInUseCount += InUseTally;
+ }
+
Thread::muxRelease (&ListLock) ;
TEVENT (omFlush) ;
}
@@ -1166,7 +1239,6 @@
// We do this before the CAS in order to minimize the length of time
// in which INFLATING appears in the mark.
m->Recycle();
- m->FreeNext = NULL ;
m->_Responsible = NULL ;
m->OwnerIsThread = 0 ;
m->_recursions = 0 ;
@@ -1174,7 +1246,7 @@
markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
if (cmp != mark) {
- omRelease (Self, m) ;
+ omRelease (Self, m, true) ;
continue ; // Interference -- just retry
}
@@ -1262,7 +1334,6 @@
m->set_object(object);
m->OwnerIsThread = 1 ;
m->_recursions = 0 ;
- m->FreeNext = NULL ;
m->_Responsible = NULL ;
m->_SpinDuration = Knob_SpinLimit ; // consider: keep metastats by type/class
@@ -1271,7 +1342,7 @@
m->set_owner (NULL) ;
m->OwnerIsThread = 0 ;
m->Recycle() ;
- omRelease (Self, m) ;
+ omRelease (Self, m, true) ;
m = NULL ;
continue ;
// interference - the markword changed - just retry.
@@ -1852,6 +1923,10 @@
// only scans the per-thread inuse lists. omAlloc() puts all
// assigned monitors on the per-thread list. deflate_idle_monitors()
// returns the non-busy monitors to the global free list.
+// When a thread dies, omFlush() adds the list of active monitors for
+// that thread to a global gOmInUseList acquiring the
+// global list lock. deflate_idle_monitors() acquires the global
+// list lock to scan for non-busy monitors to the global free list.
// An alternative could have used a single global inuse list. The
// downside would have been the additional cost of acquiring the global list lock
// for every omAlloc().
@@ -1904,6 +1979,7 @@
if (*FreeHeadp == NULL) *FreeHeadp = mid;
if (*FreeTailp != NULL) {
ObjectMonitor * prevtail = *FreeTailp;
+ assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); // TODO KK
prevtail->FreeNext = mid;
}
*FreeTailp = mid;
@@ -1912,6 +1988,39 @@
return deflated;
}
+// Caller acquires ListLock
+int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp,
+ ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
+ ObjectMonitor* mid;
+ ObjectMonitor* next;
+ ObjectMonitor* curmidinuse = NULL;
+ int deflatedcount = 0;
+
+ for (mid = *listheadp; mid != NULL; ) {
+ oop obj = (oop) mid->object();
+ bool deflated = false;
+ if (obj != NULL) {
+ deflated = deflate_monitor(mid, obj, FreeHeadp, FreeTailp);
+ }
+ if (deflated) {
+ // extract from per-thread in-use-list
+ if (mid == *listheadp) {
+ *listheadp = mid->FreeNext;
+ } else if (curmidinuse != NULL) {
+ curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+ }
+ next = mid->FreeNext;
+ mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
+ mid = next;
+ deflatedcount++;
+ } else {
+ curmidinuse = mid;
+ mid = mid->FreeNext;
+ }
+ }
+ return deflatedcount;
+}
+
void ObjectSynchronizer::deflate_idle_monitors() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
int nInuse = 0 ; // currently associated with objects
@@ -1929,36 +2038,25 @@
Thread::muxAcquire (&ListLock, "scavenge - return") ;
if (MonitorInUseLists) {
- ObjectMonitor* mid;
- ObjectMonitor* next;
- ObjectMonitor* curmidinuse;
+ int inUse = 0;
for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
- curmidinuse = NULL;
- for (mid = cur->omInUseList; mid != NULL; ) {
- oop obj = (oop) mid->object();
- deflated = false;
- if (obj != NULL) {
- deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
- }
- if (deflated) {
- // extract from per-thread in-use-list
- if (mid == cur->omInUseList) {
- cur->omInUseList = mid->FreeNext;
- } else if (curmidinuse != NULL) {
- curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
- }
- next = mid->FreeNext;
- mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
- mid = next;
- cur->omInUseCount--;
- nScavenged ++ ;
- } else {
- curmidinuse = mid;
- mid = mid->FreeNext;
- nInuse ++;
- }
+ nInCirculation+= cur->omInUseCount;
+ int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
+ cur->omInUseCount-= deflatedcount;
+ // verifyInUse(cur);
+ nScavenged += deflatedcount;
+ nInuse += cur->omInUseCount;
}
- }
+
+ // For moribund threads, scan gOmInUseList
+ if (gOmInUseList) {
+ nInCirculation += gOmInUseCount;
+ int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
+ gOmInUseCount-= deflatedcount;
+ nScavenged += deflatedcount;
+ nInuse += gOmInUseCount;
+ }
+
} else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
// Iterate over all extant monitors - Scavenge all idle monitors.
assert(block->object() == CHAINMARKER, "must be a block header");
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -122,8 +122,9 @@
static void reenter (Handle obj, intptr_t recursion, TRAPS);
// thread-specific and global objectMonitor free list accessors
+// static void verifyInUse (Thread * Self) ; too slow for general assert/debug
static ObjectMonitor * omAlloc (Thread * Self) ;
- static void omRelease (Thread * Self, ObjectMonitor * m) ;
+ static void omRelease (Thread * Self, ObjectMonitor * m, bool FromPerThreadAlloc) ;
static void omFlush (Thread * Self) ;
// Inflate light weight monitor to heavy weight monitor
@@ -150,6 +151,9 @@
// Basically we deflate all monitors that are not busy.
// An adaptive profile-based deflation policy could be used if needed
static void deflate_idle_monitors();
+ static int walk_monitor_list(ObjectMonitor** listheadp,
+ ObjectMonitor** FreeHeadp,
+ ObjectMonitor** FreeTailp);
static bool deflate_monitor(ObjectMonitor* mid, oop obj, ObjectMonitor** FreeHeadp,
ObjectMonitor** FreeTailp);
static void oops_do(OopClosure* f);
@@ -163,6 +167,8 @@
enum { _BLOCKSIZE = 128 };
static ObjectMonitor* gBlockList;
static ObjectMonitor * volatile gFreeList;
+ static ObjectMonitor * volatile gOmInUseList; // for moribund thread, so monitors they inflated still get scanned
+ static int gOmInUseCount;
public:
static void Initialize () ;
--- a/hotspot/src/share/vm/runtime/thread.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -2700,7 +2700,7 @@
if (in_bytes(size_in_bytes) != 0) {
_popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes));
_popframe_preserved_args_size = in_bytes(size_in_bytes);
- Copy::conjoint_bytes(start, _popframe_preserved_args, _popframe_preserved_args_size);
+ Copy::conjoint_jbytes(start, _popframe_preserved_args, _popframe_preserved_args_size);
}
}
--- a/hotspot/src/share/vm/runtime/thread.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -270,6 +270,7 @@
static void interrupt(Thread* thr);
static bool is_interrupted(Thread* thr, bool clear_interrupted);
+ ObjectMonitor** omInUseList_addr() { return (ObjectMonitor **)&omInUseList; }
Monitor* SR_lock() const { return _SR_lock; }
bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -355,9 +355,9 @@
} else {
base = iframe()->interpreter_frame_expression_stack();
}
- Copy::conjoint_bytes(saved_args,
- base,
- popframe_preserved_args_size_in_bytes);
+ Copy::conjoint_jbytes(saved_args,
+ base,
+ popframe_preserved_args_size_in_bytes);
thread->popframe_free_preserved_args();
}
}
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -111,6 +111,35 @@
return result;
}
+// Helper method.
+static bool failed_to_reserve_as_requested(char* base, char* requested_address,
+ const size_t size, bool special)
+{
+ if (base == requested_address || requested_address == NULL)
+ return false; // did not fail
+
+ if (base != NULL) {
+ // Different reserve address may be acceptable in other cases
+ // but for compressed oops heap should be at requested address.
+ assert(UseCompressedOops, "currently requested address used only for compressed oops");
+ if (PrintCompressedOopsMode) {
+ tty->cr();
+ tty->print_cr("Reserved memory at not requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
+ }
+ // OS ignored requested address. Try different address.
+ if (special) {
+ if (!os::release_memory_special(base, size)) {
+ fatal("os::release_memory_special failed");
+ }
+ } else {
+ if (!os::release_memory(base, size)) {
+ fatal("os::release_memory failed");
+ }
+ }
+ }
+ return true;
+}
+
ReservedSpace::ReservedSpace(const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
@@ -129,6 +158,10 @@
assert((suffix_align & prefix_align - 1) == 0,
"suffix_align not divisible by prefix_align");
+ // Assert that if noaccess_prefix is used, it is the same as prefix_align.
+ assert(noaccess_prefix == 0 ||
+ noaccess_prefix == prefix_align, "noaccess prefix wrong");
+
// Add in noaccess_prefix to prefix_size;
const size_t adjusted_prefix_size = prefix_size + noaccess_prefix;
const size_t size = adjusted_prefix_size + suffix_size;
@@ -150,15 +183,16 @@
_noaccess_prefix = 0;
_executable = false;
- // Assert that if noaccess_prefix is used, it is the same as prefix_align.
- assert(noaccess_prefix == 0 ||
- noaccess_prefix == prefix_align, "noaccess prefix wrong");
-
// Optimistically try to reserve the exact size needed.
char* addr;
if (requested_address != 0) {
- addr = os::attempt_reserve_memory_at(size,
- requested_address-noaccess_prefix);
+ requested_address -= noaccess_prefix; // adjust address
+ assert(requested_address != NULL, "huge noaccess prefix?");
+ addr = os::attempt_reserve_memory_at(size, requested_address);
+ if (failed_to_reserve_as_requested(addr, requested_address, size, false)) {
+ // OS ignored requested address. Try different address.
+ addr = NULL;
+ }
} else {
addr = os::reserve_memory(size, NULL, prefix_align);
}
@@ -222,11 +256,20 @@
bool special = large && !os::can_commit_large_page_memory();
char* base = NULL;
+ if (requested_address != 0) {
+ requested_address -= noaccess_prefix; // adjust requested address
+ assert(requested_address != NULL, "huge noaccess prefix?");
+ }
+
if (special) {
base = os::reserve_memory_special(size, requested_address, executable);
if (base != NULL) {
+ if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
+ // OS ignored requested address. Try different address.
+ return;
+ }
// Check alignment constraints
if (alignment > 0) {
assert((uintptr_t) base % alignment == 0,
@@ -235,6 +278,13 @@
_special = true;
} else {
// failed; try to reserve regular memory below
+ if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
+ !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
+ if (PrintCompressedOopsMode) {
+ tty->cr();
+ tty->print_cr("Reserve regular memory without large pages.");
+ }
+ }
}
}
@@ -248,8 +298,11 @@
// important. If available space is not detected, return NULL.
if (requested_address != 0) {
- base = os::attempt_reserve_memory_at(size,
- requested_address-noaccess_prefix);
+ base = os::attempt_reserve_memory_at(size, requested_address);
+ if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
+ // OS ignored requested address. Try different address.
+ base = NULL;
+ }
} else {
base = os::reserve_memory(size, NULL, alignment);
}
@@ -365,7 +418,12 @@
}
void ReservedSpace::protect_noaccess_prefix(const size_t size) {
- // If there is noaccess prefix, return.
+ assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL &&
+ (size_t(_base + _size) > OopEncodingHeapMax) &&
+ Universe::narrow_oop_use_implicit_null_checks()),
+ "noaccess_prefix should be used only with non zero based compressed oops");
+
+ // If there is no noaccess prefix, return.
if (_noaccess_prefix == 0) return;
assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
@@ -377,6 +435,10 @@
_special)) {
fatal("cannot protect protection page");
}
+ if (PrintCompressedOopsMode) {
+ tty->cr();
+ tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix);
+ }
_base += _noaccess_prefix;
_size -= _noaccess_prefix;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -614,7 +614,6 @@
/* NMethods (NOTE: incomplete, but only a little) */ \
/**************************************************/ \
\
- static_field(nmethod, _zombie_instruction_size, int) \
nonstatic_field(nmethod, _method, methodOop) \
nonstatic_field(nmethod, _entry_bci, int) \
nonstatic_field(nmethod, _osr_link, nmethod*) \
--- a/hotspot/src/share/vm/runtime/vtune.hpp Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-// Interface to Intel's VTune profiler.
-
-class VTune : AllStatic {
- public:
- static void create_nmethod(nmethod* nm); // register newly created nmethod
- static void delete_nmethod(nmethod* nm); // unregister nmethod before discarding it
-
- static void register_stub(const char* name, address start, address end);
- // register internal VM stub
- static void start_GC(); // start/end of GC or scavenge
- static void end_GC();
-
- static void start_class_load(); // start/end of class loading
- static void end_class_load();
-
- static void exit(); // VM exit
-};
-
-
-// helper objects
-class VTuneGCMarker : StackObj {
- public:
- VTuneGCMarker() { VTune::start_GC(); }
- ~VTuneGCMarker() { VTune::end_GC(); }
-};
-
-class VTuneClassLoadMarker : StackObj {
- public:
- VTuneClassLoadMarker() { VTune::start_class_load(); }
- ~VTuneClassLoadMarker() { VTune::end_class_load(); }
-};
--- a/hotspot/src/share/vm/utilities/constantTag.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/constantTag.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -28,56 +28,85 @@
#ifndef PRODUCT
void constantTag::print_on(outputStream* st) const {
+ st->print(internal_name());
+}
+
+#endif // PRODUCT
+
+BasicType constantTag::basic_type() const {
switch (_tag) {
- case JVM_CONSTANT_Class :
- st->print("Class");
- break;
- case JVM_CONSTANT_Fieldref :
- st->print("Field");
- break;
- case JVM_CONSTANT_Methodref :
- st->print("Method");
- break;
- case JVM_CONSTANT_InterfaceMethodref :
- st->print("InterfaceMethod");
- break;
- case JVM_CONSTANT_String :
- st->print("String");
- break;
case JVM_CONSTANT_Integer :
- st->print("Integer");
- break;
+ return T_INT;
case JVM_CONSTANT_Float :
- st->print("Float");
- break;
+ return T_FLOAT;
case JVM_CONSTANT_Long :
- st->print("Long");
- break;
+ return T_LONG;
case JVM_CONSTANT_Double :
- st->print("Double");
- break;
- case JVM_CONSTANT_NameAndType :
- st->print("NameAndType");
- break;
- case JVM_CONSTANT_Utf8 :
- st->print("Utf8");
- break;
+ return T_DOUBLE;
+
+ case JVM_CONSTANT_Class :
+ case JVM_CONSTANT_String :
case JVM_CONSTANT_UnresolvedClass :
- st->print("Unresolved class");
- break;
+ case JVM_CONSTANT_UnresolvedClassInError :
case JVM_CONSTANT_ClassIndex :
- st->print("Unresolved class index");
- break;
case JVM_CONSTANT_UnresolvedString :
- st->print("Unresolved string");
- break;
case JVM_CONSTANT_StringIndex :
- st->print("Unresolved string index");
- break;
+ case JVM_CONSTANT_MethodHandle :
+ case JVM_CONSTANT_MethodType :
+ case JVM_CONSTANT_Object :
+ return T_OBJECT;
default:
ShouldNotReachHere();
- break;
+ return T_ILLEGAL;
}
}
-#endif // PRODUCT
+
+
+const char* constantTag::internal_name() const {
+ switch (_tag) {
+ case JVM_CONSTANT_Invalid :
+ return "Invalid index";
+ case JVM_CONSTANT_Class :
+ return "Class";
+ case JVM_CONSTANT_Fieldref :
+ return "Field";
+ case JVM_CONSTANT_Methodref :
+ return "Method";
+ case JVM_CONSTANT_InterfaceMethodref :
+ return "InterfaceMethod";
+ case JVM_CONSTANT_String :
+ return "String";
+ case JVM_CONSTANT_Integer :
+ return "Integer";
+ case JVM_CONSTANT_Float :
+ return "Float";
+ case JVM_CONSTANT_Long :
+ return "Long";
+ case JVM_CONSTANT_Double :
+ return "Double";
+ case JVM_CONSTANT_NameAndType :
+ return "NameAndType";
+ case JVM_CONSTANT_MethodHandle :
+ return "MethodHandle";
+ case JVM_CONSTANT_MethodType :
+ return "MethodType";
+ case JVM_CONSTANT_Object :
+ return "Object";
+ case JVM_CONSTANT_Utf8 :
+ return "Utf8";
+ case JVM_CONSTANT_UnresolvedClass :
+ return "Unresolved Class";
+ case JVM_CONSTANT_UnresolvedClassInError :
+ return "Unresolved Class Error";
+ case JVM_CONSTANT_ClassIndex :
+ return "Unresolved Class Index";
+ case JVM_CONSTANT_UnresolvedString :
+ return "Unresolved String";
+ case JVM_CONSTANT_StringIndex :
+ return "Unresolved String Index";
+ default:
+ ShouldNotReachHere();
+ return "Illegal";
+ }
+}
--- a/hotspot/src/share/vm/utilities/constantTag.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/constantTag.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -78,13 +78,24 @@
bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); }
bool is_symbol() const { return is_utf8(); }
+ bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; }
+ bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; }
+
+ constantTag() {
+ _tag = JVM_CONSTANT_Invalid;
+ }
constantTag(jbyte tag) {
assert((tag >= 0 && tag <= JVM_CONSTANT_NameAndType) ||
+ (tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_MethodType) ||
(tag >= JVM_CONSTANT_InternalMin && tag <= JVM_CONSTANT_InternalMax), "Invalid constant tag");
_tag = tag;
}
jbyte value() { return _tag; }
+ BasicType basic_type() const; // if used with ldc, what kind of value gets pushed?
+
+ const char* internal_name() const; // for error reporting
+
void print_on(outputStream* st) const PRODUCT_RETURN;
};
--- a/hotspot/src/share/vm/utilities/copy.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/copy.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -48,7 +48,7 @@
Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
} else {
// Not aligned, so no need to be atomic.
- Copy::conjoint_bytes((void*) src, (void*) dst, size);
+ Copy::conjoint_jbytes((void*) src, (void*) dst, size);
}
}
--- a/hotspot/src/share/vm/utilities/copy.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/copy.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -73,6 +73,9 @@
// whole alignment units. E.g., if BytesPerLong is 2x word alignment, an odd
// count may copy an extra word. In the arrayof case, we are allowed to copy
// only the number of copy units specified.
+ //
+ // All callees check count for 0.
+ //
// HeapWords
@@ -99,7 +102,6 @@
// Object-aligned words, conjoint, not atomic on each word
static void aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
assert_params_aligned(from, to);
- assert_non_zero(count);
pd_aligned_conjoint_words(from, to, count);
}
@@ -107,49 +109,42 @@
static void aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
assert_params_aligned(from, to);
assert_disjoint(from, to, count);
- assert_non_zero(count);
pd_aligned_disjoint_words(from, to, count);
}
// bytes, jshorts, jints, jlongs, oops
// bytes, conjoint, not atomic on each byte (not that it matters)
- static void conjoint_bytes(void* from, void* to, size_t count) {
- assert_non_zero(count);
+ static void conjoint_jbytes(void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
// bytes, conjoint, atomic on each byte (not that it matters)
- static void conjoint_bytes_atomic(void* from, void* to, size_t count) {
- assert_non_zero(count);
+ static void conjoint_jbytes_atomic(void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
// jshorts, conjoint, atomic on each jshort
static void conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
assert_params_ok(from, to, LogBytesPerShort);
- assert_non_zero(count);
pd_conjoint_jshorts_atomic(from, to, count);
}
// jints, conjoint, atomic on each jint
static void conjoint_jints_atomic(jint* from, jint* to, size_t count) {
assert_params_ok(from, to, LogBytesPerInt);
- assert_non_zero(count);
pd_conjoint_jints_atomic(from, to, count);
}
// jlongs, conjoint, atomic on each jlong
static void conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
assert_params_ok(from, to, LogBytesPerLong);
- assert_non_zero(count);
pd_conjoint_jlongs_atomic(from, to, count);
}
// oops, conjoint, atomic on each oop
static void conjoint_oops_atomic(oop* from, oop* to, size_t count) {
assert_params_ok(from, to, LogBytesPerHeapOop);
- assert_non_zero(count);
pd_conjoint_oops_atomic(from, to, count);
}
@@ -157,7 +152,6 @@
static void conjoint_oops_atomic(narrowOop* from, narrowOop* to, size_t count) {
assert(sizeof(narrowOop) == sizeof(jint), "this cast is wrong");
assert_params_ok(from, to, LogBytesPerInt);
- assert_non_zero(count);
pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
}
@@ -168,36 +162,31 @@
static void conjoint_memory_atomic(void* from, void* to, size_t size);
// bytes, conjoint array, atomic on each byte (not that it matters)
- static void arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
- assert_non_zero(count);
+ static void arrayof_conjoint_jbytes(HeapWord* from, HeapWord* to, size_t count) {
pd_arrayof_conjoint_bytes(from, to, count);
}
// jshorts, conjoint array, atomic on each jshort
static void arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerShort);
- assert_non_zero(count);
pd_arrayof_conjoint_jshorts(from, to, count);
}
// jints, conjoint array, atomic on each jint
static void arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerInt);
- assert_non_zero(count);
pd_arrayof_conjoint_jints(from, to, count);
}
// jlongs, conjoint array, atomic on each jlong
static void arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerLong);
- assert_non_zero(count);
pd_arrayof_conjoint_jlongs(from, to, count);
}
// oops, conjoint array, atomic on each oop
static void arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerHeapOop);
- assert_non_zero(count);
pd_arrayof_conjoint_oops(from, to, count);
}
@@ -319,14 +308,6 @@
#endif
}
- static void assert_non_zero(size_t count) {
-#ifdef ASSERT
- if (count == 0) {
- basic_fatal("count must be non-zero");
- }
-#endif
- }
-
static void assert_byte_count_ok(size_t byte_count, size_t unit_size) {
#ifdef ASSERT
if ((size_t)round_to(byte_count, unit_size) != byte_count) {
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -182,73 +182,3 @@
_index < objArrayOop(_obj)->length();
}
#endif // ASSERT
-
-bool RegionTaskQueueWithOverflow::is_empty() {
- return (_region_queue.size() == 0) &&
- (_overflow_stack->length() == 0);
-}
-
-bool RegionTaskQueueWithOverflow::stealable_is_empty() {
- return _region_queue.size() == 0;
-}
-
-bool RegionTaskQueueWithOverflow::overflow_is_empty() {
- return _overflow_stack->length() == 0;
-}
-
-void RegionTaskQueueWithOverflow::initialize() {
- _region_queue.initialize();
- assert(_overflow_stack == 0, "Creating memory leak");
- _overflow_stack =
- new (ResourceObj::C_HEAP) GrowableArray<RegionTask>(10, true);
-}
-
-void RegionTaskQueueWithOverflow::save(RegionTask t) {
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: save " PTR_FORMAT, t);
- }
- if(!_region_queue.push(t)) {
- _overflow_stack->push(t);
- }
-}
-
-// Note that using this method will retrieve all regions
-// that have been saved but that it will always check
-// the overflow stack. It may be more efficient to
-// check the stealable queue and the overflow stack
-// separately.
-bool RegionTaskQueueWithOverflow::retrieve(RegionTask& region_task) {
- bool result = retrieve_from_overflow(region_task);
- if (!result) {
- result = retrieve_from_stealable_queue(region_task);
- }
- if (TraceRegionTasksQueuing && Verbose && result) {
- gclog_or_tty->print_cr(" CTQ: retrieve " PTR_FORMAT, result);
- }
- return result;
-}
-
-bool RegionTaskQueueWithOverflow::retrieve_from_stealable_queue(
- RegionTask& region_task) {
- bool result = _region_queue.pop_local(region_task);
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
- }
- return result;
-}
-
-bool
-RegionTaskQueueWithOverflow::retrieve_from_overflow(RegionTask& region_task) {
- bool result;
- if (!_overflow_stack->is_empty()) {
- region_task = _overflow_stack->pop();
- result = true;
- } else {
- region_task = (RegionTask) NULL;
- result = false;
- }
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
- }
- return result;
-}
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp Tue Jul 20 22:17:33 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -109,8 +109,9 @@
public:
TaskQueueSuper() : _bottom(0), _age() {}
- // Return true if the TaskQueue contains any tasks.
- bool peek() { return _bottom != _age.top(); }
+ // Return true if the TaskQueue contains/does not contain any tasks.
+ bool peek() const { return _bottom != _age.top(); }
+ bool is_empty() const { return size() == 0; }
// Return an estimate of the number of elements in the queue.
// The "careful" version admits the possibility of pop_local/pop_global
@@ -165,18 +166,16 @@
void initialize();
- // Push the task "t" on the queue. Returns "false" iff the queue is
- // full.
+ // Push the task "t" on the queue. Returns "false" iff the queue is full.
inline bool push(E t);
- // If succeeds in claiming a task (from the 'local' end, that is, the
- // most recently pushed task), returns "true" and sets "t" to that task.
- // Otherwise, the queue is empty and returns false.
+ // Attempts to claim a task from the "local" end of the queue (the most
+ // recently pushed). If successful, returns true and sets t to the task;
+ // otherwise, returns false (the queue is empty).
inline bool pop_local(E& t);
- // If succeeds in claiming a task (from the 'global' end, that is, the
- // least recently pushed task), returns "true" and sets "t" to that task.
- // Otherwise, the queue is empty and returns false.
+ // Like pop_local(), but uses the "global" end of the queue (the least
+ // recently pushed).
bool pop_global(E& t);
// Delete any resource associated with the queue.
@@ -198,7 +197,6 @@
template<class E, unsigned int N>
void GenericTaskQueue<E, N>::initialize() {
_elems = NEW_C_HEAP_ARRAY(E, N);
- guarantee(_elems != NULL, "Allocation failed.");
}
template<class E, unsigned int N>
@@ -289,7 +287,87 @@
FREE_C_HEAP_ARRAY(E, _elems);
}
-// Inherits the typedef of "Task" from above.
+// OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
+// elements that do not fit in the TaskQueue.
+//
+// Three methods from super classes are overridden:
+//
+// initialize() - initialize the super classes and create the overflow stack
+// push() - push onto the task queue or, if that fails, onto the overflow stack
+// is_empty() - return true if both the TaskQueue and overflow stack are empty
+//
+// Note that size() is not overridden--it returns the number of elements in the
+// TaskQueue, and does not include the size of the overflow stack. This
+// simplifies replacement of GenericTaskQueues with OverflowTaskQueues.
+template<class E, unsigned int N = TASKQUEUE_SIZE>
+class OverflowTaskQueue: public GenericTaskQueue<E, N>
+{
+public:
+ typedef GrowableArray<E> overflow_t;
+ typedef GenericTaskQueue<E, N> taskqueue_t;
+
+ OverflowTaskQueue();
+ ~OverflowTaskQueue();
+ void initialize();
+
+ inline overflow_t* overflow_stack() const { return _overflow_stack; }
+
+ // Push task t onto the queue or onto the overflow stack. Return true.
+ inline bool push(E t);
+
+ // Attempt to pop from the overflow stack; return true if anything was popped.
+ inline bool pop_overflow(E& t);
+
+ inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
+ inline bool overflow_empty() const { return overflow_stack()->is_empty(); }
+ inline bool is_empty() const {
+ return taskqueue_empty() && overflow_empty();
+ }
+
+private:
+ overflow_t* _overflow_stack;
+};
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::OverflowTaskQueue()
+{
+ _overflow_stack = NULL;
+}
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::~OverflowTaskQueue()
+{
+ if (_overflow_stack != NULL) {
+ delete _overflow_stack;
+ _overflow_stack = NULL;
+ }
+}
+
+template <class E, unsigned int N>
+void OverflowTaskQueue<E, N>::initialize()
+{
+ taskqueue_t::initialize();
+ assert(_overflow_stack == NULL, "memory leak");
+ _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<E>(10, true);
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::push(E t)
+{
+ if (!taskqueue_t::push(t)) {
+ overflow_stack()->push(t);
+ }
+ return true;
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::pop_overflow(E& t)
+{
+ if (overflow_empty()) return false;
+ t = overflow_stack()->pop();
+ return true;
+}
+
class TaskQueueSetSuper: public CHeapObj {
protected:
static int randomParkAndMiller(int* seed0);
@@ -323,11 +401,11 @@
T* queue(uint n);
- // The thread with queue number "queue_num" (and whose random number seed
- // is at "seed") is trying to steal a task from some other queue. (It
- // may try several queues, according to some configuration parameter.)
- // If some steal succeeds, returns "true" and sets "t" the stolen task,
- // otherwise returns false.
+ // The thread with queue number "queue_num" (and whose random number seed is
+ // at "seed") is trying to steal a task from some other queue. (It may try
+ // several queues, according to some configuration parameter.) If some steal
+ // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
+ // false.
bool steal(uint queue_num, int* seed, E& t);
bool peek();
@@ -507,7 +585,7 @@
uint localBot = _bottom;
// This value cannot be N-1. That can only occur as a result of
// the assignment to bottom in this method. If it does, this method
- // resets the size( to 0 before the next call (which is sequential,
+ // resets the size to 0 before the next call (which is sequential,
// since this is pop_local.)
uint dirty_n_elems = dirty_size(localBot, _age.top());
assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
@@ -533,8 +611,7 @@
}
}
-typedef oop Task;
-typedef GenericTaskQueue<Task> OopTaskQueue;
+typedef GenericTaskQueue<oop> OopTaskQueue;
typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet;
#ifdef _MSC_VER
@@ -615,35 +692,8 @@
#pragma warning(pop)
#endif
-typedef GenericTaskQueue<StarTask> OopStarTaskQueue;
+typedef OverflowTaskQueue<StarTask> OopStarTaskQueue;
typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet;
-typedef size_t RegionTask; // index for region
-typedef GenericTaskQueue<RegionTask> RegionTaskQueue;
-typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;
-
-class RegionTaskQueueWithOverflow: public CHeapObj {
- protected:
- RegionTaskQueue _region_queue;
- GrowableArray<RegionTask>* _overflow_stack;
-
- public:
- RegionTaskQueueWithOverflow() : _overflow_stack(NULL) {}
- // Initialize both stealable queue and overflow
- void initialize();
- // Save first to stealable queue and then to overflow
- void save(RegionTask t);
- // Retrieve first from overflow and then from stealable queue
- bool retrieve(RegionTask& region_index);
- // Retrieve from stealable queue
- bool retrieve_from_stealable_queue(RegionTask& region_index);
- // Retrieve from overflow
- bool retrieve_from_overflow(RegionTask& region_index);
- bool is_empty();
- bool stealable_is_empty();
- bool overflow_is_empty();
- uint stealable_size() { return _region_queue.size(); }
- RegionTaskQueue* task_queue() { return &_region_queue; }
-};
-
-#define USE_RegionTaskQueueWithOverflow
+typedef OverflowTaskQueue<size_t> RegionTaskQueue;
+typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;
--- a/jdk/.hgtags Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/.hgtags Wed Jul 05 17:18:01 2017 +0200
@@ -75,3 +75,4 @@
82593186fa54ab12f17af31f86a7bf364efaf4df jdk7-b98
2587c9f0b60dc3146b4247b8674ada456a643d6f jdk7-b99
820b4e843d5168370a3bf166d19751a3271d8575 jdk7-b100
+d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/common/shared/Defs-javadoc.gmk Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Copyright year for beginning of Java and some of the apis
+# (Needed when creating the javadocs)
+FIRST_COPYRIGHT_YEAR = 1993
+DOMAPI_FIRST_COPYRIGHT_YEAR = 2005
+MIRROR_FIRST_COPYRIGHT_YEAR = 2004
+DOCLETAPI_FIRST_COPYRIGHT_YEAR = 1993
+TAGLETAPI_FIRST_COPYRIGHT_YEAR = 1993
+JDI_FIRST_COPYRIGHT_YEAR = 1999
+JAAS_FIRST_COPYRIGHT_YEAR = 1998
+JGSS_FIRST_COPYRIGHT_YEAR = 2000
+SMARTCARDIO_FIRST_COPYRIGHT_YEAR = 2005
+HTTPSERVER_FIRST_COPYRIGHT_YEAR = 2005
+MGMT_FIRST_COPYRIGHT_YEAR = 2003
+ATTACH_FIRST_COPYRIGHT_YEAR = 2005
+JCONSOLE_FIRST_COPYRIGHT_YEAR = 2006
+SCTPAPI_FIRST_COPYRIGHT_YEAR = 2009
+TRACING_FIRST_COPYRIGHT_YEAR = 2008
+TREEAPI_FIRST_COPYRIGHT_YEAR = 2005
+JNLP_FIRST_COPYRIGHT_YEAR = 1998
+PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007
+
+# Oracle name
+COMPANY_NAME = Oracle and/or its affiliates
+
+# Copyright address
+COMPANY_ADDRESS = 500 Oracle Parkway<br>Redwood Shores, CA 94065 USA.
+
+# The trademark symbol
+TRADEMARK = ™
+
+# Common copyright lines used
+# The word "Copyright" might optionally be a link to the file cpyr.html.
+# The first year of copyright may vary or not be available.
+# The address to the company might be optional.
+COMMA:= ,
+EMPTY:=
+SPACE:=$(EMPTY) $(EMPTY)
+COPYRIGHT_SYMBOL = &\#x00a9;
+# Macros to handle the optional empty args.
+# (The GNU make 3.78.1 "if" conditional is broken, fixed in GNU make 3.81)
+define OptionalCopyrightUrl # url
+$(shell \
+ if [ "$1" != "" ] ; then \
+ printf "<a href=\"%s\">Copyright</a>" "$1"; \
+ else \
+ printf "Copyright"; \
+ fi)
+endef
+define OptionalCopyrightFirstYear # year
+$(shell \
+ if [ "$1" != "" ] ; then \
+ printf "%s," "$1";\
+ fi)
+endef
+define OptionalCompanyAddress # address
+$(shell \
+ if [ "$1" != "" ] ; then \
+ printf "%s" "$1";\
+ fi)
+endef
+define CopyrightLine # optionalurl optionalfirstyear optionaladdress
+$(call OptionalCopyrightUrl,$1) $(COPYRIGHT_SYMBOL)\
+$(call OptionalCopyrightFirstYear,$2) $(COPYRIGHT_YEAR),\
+$(COMPANY_NAME).\
+$(call OptionalCompanyAddress,$3)\
+All rights reserved.
+endef
+
--- a/jdk/make/common/shared/Defs-windows.gmk Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/common/shared/Defs-windows.gmk Wed Jul 05 17:18:01 2017 +0200
@@ -230,7 +230,8 @@
# Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
ifeq ($(ARCH_DATA_MODEL), 32)
- # Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
+ # Try looking in MSVCDIR or MSVCDir area first
+ # (set by vcvars32.bat for VC .NET, not defined in the VC 2008/2010)
ifdef MSVCDIR
xMSVCDIR :="$(subst \,/,$(MSVCDIR))"
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
@@ -238,11 +239,6 @@
ifdef MSVCDir
xMSVCDIR :="$(subst \,/,$(MSVCDir))"
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
- else
- ifneq ($(_program_files),)
- xMSVCDIR :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7"
- _msvc_dir :=$(call FullPath,$(xMSVCDIR))
- endif
endif
endif
# If we still don't have it, look for VSnnCOMNTOOLS (newest first),
--- a/jdk/make/docs/Makefile Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/docs/Makefile Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,4 @@
-#
-# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -30,6 +29,41 @@
PRODUCT=docs
include $(BUILDDIR)/common/Defs.gmk
+# Get CopyrightLine macro and other shared variables
+include $(BUILDDIR)/common/shared/Defs-javadoc.gmk
+
+# Url to root of documents
+DOCSDIR_URL = {@docroot}/$(GET2DOCSDIR)
+
+# Url to copyright html file
+COPYRIGHT_URL-7 = $(DOCSDIR_URL)/legal/cpyr.html
+COPYRIGHT_URL = $(COPYRIGHT_URL-$(JDK_MINOR_VERSION))
+
+# Url to bug filing site
+BUG_SUBMIT_URL = http://bugs.sun.com/services/bugreport/index.jsp
+
+# Common line for how to submit a bug or rfe
+BUG_SUBMIT_LINE = <a href=\"$(BUG_SUBMIT_URL)\">Submit a bug or feature</a>
+
+# Url to devdocs page
+# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
+DEV_DOCS_URL-5 = http://java.sun.com/j2se/1.5.0/docs
+DEV_DOCS_URL-6 = http://download.oracle.com/docs/cd/E17409_01/javase/6/docs
+DEV_DOCS_URL-7 = http://download.oracle.com/docs/cd/E17409_01/javase/7/docs
+DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
+
+# Url to Java Language Spec
+JLS3_URL = http://java.sun.com/docs/books/jls/
+
+# Common Java trademark line
+JAVA_TRADEMARK_LINE = Java is a trademark or registered trademark of \
+$(COMPANY_NAME) in the US and other countries.
+
+#
+# Definitions for imported components
+#
+include $(BUILDDIR)/common/internal/ImportComponents.gmk
+
# We override whatever the max VM memory setting is here.
# NOTE: javadoc will not complete without these larger settings.
# WARNING: This could cause thrashing on low memory machines.
@@ -39,418 +73,155 @@
MAX_VM_MEMORY = 512
endif
-#
-# Variables used by docs target
+# List of all possible directories for javadoc to look for sources
+# NOTE: Quotes are required around sourcepath argument only on Windows.
+# Otherwise, you get "No packages or classes specified." due
+# to $(CLASSPATH_SEPARATOR) being interpreted as an end of
+# command (newline or shell ; character)
+ALL_SOURCE_DIRS = $(SHARE_SRC)/classes \
+ $(IMPORTSRCDIR) \
+ $(GENSRCDIR) \
+ $(SHARE_SRC)/../solaris/classes \
+ $(SHARE_SRC)/../windows/classes \
+ $(SHARE_SRC)/doc/stub
+EMPTY:=
+SPACE:= $(EMPTY) $(EMPTY)
+RELEASEDOCS_SOURCEPATH = \
+ $(subst $(SPACE),$(CLASSPATH_SEPARATOR),$(strip $(ALL_SOURCE_DIRS)))
+
+# Prep for javadoc creation, assumes $@ is an index.html file
+define prep-javadoc
+@if [ -f "$@" -a "$?" != "" ] ; then \
+ $(ECHO) "# Dependencies have changed: $?"; \
+fi
+$(RM) -r $(@D)
+$(MKDIR) -p $(@D)
+endef
+
+# A cache of the directories in ALL_SOURCE_DIRS
+DIRECTORY_CACHE = $(DOCSTMPDIR)/directory.cache
+
+# Given a list of packages, return a list of files or dirs to be dependent on
+# (Currently only returning a list of directories)
+define PackageDependencies # packages
+$(shell \
+ if [ "$1" != "" -a -f $(DIRECTORY_CACHE) ] ; then \
+ for p in $1 ; do \
+ pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; \
+ $(CAT) $(DIRECTORY_CACHE) | $(GREP) "/$${pd}/" ; \
+ done; \
+ fi \
+)
+endef
+
+# Given a list of packages, add packages that exist to $@, print summary
+define PackageFilter # packages
+@if [ "$1" != "" ] ; then \
+ for p in $1 ; do \
+ pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; \
+ found="false"; \
+ for cp in $(ALL_SOURCE_DIRS) ; do \
+ if [ -d $${cp}/$${pd} ] ; then \
+ $(ECHO) "$${p}" >> $@; \
+ found="true"; \
+ break; \
+ fi; \
+ done; \
+ if [ "$${found}" = "false" ] ; then \
+ $(ECHO) "WARNING: Package not found: $${p}"; \
+ fi; \
+ done; \
+fi
+endef
+
+# Print out a summary of the javadoc command about to be run
+define JavadocSummary # optionsfile packagesfile
+@$(ECHO) "# Summary for $@";\
+ $(ECHO) "# Options (`$(BASENAME) $1`):"; $(SED) -e 's@^@# @' $1; \
+ $(ECHO) "# Packages (`$(BASENAME) $2`):";$(SED) -e 's@^@# @' $2
+endef
+
#
-DOCSTMPDIR = $(TEMPDIR)/doctmp
+# Temporary directory for javadoc creation
+#
+DOCSTMPDIR = $(TEMPDIR)/doctmp
+
+#
+# Different api directories created from root directory
+#
+COREAPI_DOCSDIR = $(DOCSDIR)/api
+JDK_API_DOCSDIR = $(DOCSDIR)/jdk/api
+JRE_API_DOCSDIR = $(DOCSDIR)/jre/api
+PLATFORM_DOCSDIR = $(DOCSDIR)/platform
+
+# The non-core api javadocs need to be able to access the root of the core
+# api directory, so for jdk/api or jre/api to get to the core api/
+# directory we would use this:
+JDKJRE2COREAPI = ../../api
+
+# Common bottom argument
+define CommonBottom # year
+<font size=\"-1\"><p> $(call CopyrightLine,,$1,)</font>
+endef
+# Common trademark bottom argument (Not sure why this is used sometimes)
+define CommonTrademarkBottom # year
+<font size=\"-1\">\
+$(BUG_SUBMIT_LINE)<br>$(JAVA_TRADEMARK_LINE)<br>\
+$(call CopyrightLine,,$1,$(COMPANY_ADDRESS))\
+</font>
+endef
+
+# Core api bottom argument (with special sauce)
+COREAPI_BOTTOM = <font size=\"-1\"> $(BUG_SUBMIT_LINE)\
+<br>For further API reference and developer documentation, \
+see <a href=\"$(DEV_DOCS_URL)\" target=\"_blank\">Java SE Documentation</a>. \
+That documentation contains more detailed, developer-targeted descriptions, \
+with conceptual overviews, definitions of terms, workarounds, \
+and working code examples.<p>\
+$(call CopyrightLine,$(COPYRIGHT_URL),$(FIRST_COPYRIGHT_YEAR),)\
+</font>
+
+# Common javadoc options used by all
COMMON_JAVADOCFLAGS = \
- $(NO_PROPRIETARY_API_WARNINGS) \
+ $(NO_PROPRIETARY_API_WARNINGS) \
-source 1.5 \
-quiet \
-use \
-keywords \
- $(JAVADOC_VM_MEMORY_FLAGS) \
$(ADDITIONAL_JAVADOCFLAGS)
ADDITIONAL_JAVADOCFLAGS =
-CORE_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- $(TAGS) \
- -encoding ISO-8859-1 \
- -splitIndex \
- -doctitle $(DOCTITLE_SWITCH) \
- -windowtitle $(WINDOWTITLE_SWITCH) \
- -header $(HEADER_SWITCH) \
- $(TOPOPTION) \
- -bottom $(JAVADOCBOTTOM_SWITCH) \
- $(OVERVIEW_OPTION)
-
-DRAFT = '<br><strong>DRAFT '$(MILESTONE)-$(BUILD_NUMBER)'</strong>'
-THIS_YEAR := $(shell $(DATE) | $(SED) -e 's/ / /g' | $(CUT) -d' ' -f6)
-TRADEMARK = &\#x2122;
-
-IGNORED_TAGS = beaninfo revised since.unbundled spec specdefault Note ToDo
-
-JLS3_URL = http://java.sun.com/docs/books/jls/
-JLS3_CITE = <a href="$(JLS3_URL)"> \
- The Java Language Specification, Third Edition</a>
-TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:'
-
-TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3)
-
-ifeq ($(MILESTONE), fcs)
- DOCTITLE_SWITCH = $(JAVADOCTITLE)
- WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)
- HEADER_SWITCH = $(JAVADOCHEADER)
- TOPOPTION=
- JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM)
- OVERVIEW_OPTION = -overview $(JAVADOCOVERVIEW)
-else
- DOCTITLE_SWITCH = $(JAVADOCTITLE_EARLYACCESS)$(DRAFT)
- WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)" $(BUILD_NUMBER)"
- HEADER_SWITCH = $(JAVADOCHEADER)$(DRAFT)
- JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM_EARLYACCESS)
- TOPOPTION= -top $(JAVADOCTOP_EARLYACCESS)
- OVERVIEW_OPTION =
+# Draft used for non-fcs documents
+JDK_IS_FCS = false
+DRAFT_HEADER =
+ifeq ($(JDK_MINOR_VERSION),5)
+ JDK_IS_FCS = true
+endif
+ifeq ($(JDK_MINOR_VERSION),6)
+ JDK_IS_FCS = true
+endif
+ifeq ($(JDK_IS_FCS),false)
+ ifneq ($(MILESTONE), fcs)
+ DRAFT_HEADER = <br><strong>DRAFT $(MILESTONE)-$(BUILD_NUMBER)</strong>
+ DRAFT_BOTTOM = <br><strong>DRAFT $(MILESTONE)-$(BUILD_NUMBER)</strong>
+ DRAFT_WINTITLE = $(BUILD_NUMBER)
+ # Early access top text (not used in FCS releases)
+ COREAPI_TOP_EARLYACCESS = \
+<div style=\"background-color: \#EEEEEE\"> \
+<div style=\"padding: 6px; margin-top: 2px; margin-bottom: 6px; \
+margin-left: 6px; margin-right: 6px; text-align: justify; \
+font-size: 80%; font-family: Helvetica, Arial, sans-serif; \
+font-weight: normal;\"> \
+Please note that the specifications and other information \
+contained herein are not final and are subject to change. \
+The information is being made available to you solely for purpose of \
+evaluation. \
+</div> </div>
+ endif
endif
-JAVADOCTITLE = 'Java$(TRADEMARK) Platform, Standard Edition $(JDK_MINOR_VERSION)<br>API Specification'
-JAVADOCWINDOWTITLE = 'Java Platform SE $(JDK_MINOR_VERSION)'
-JAVADOCHEADER = '<strong>Java$(TRADEMARK) Platform<br>Standard Ed. $(JDK_MINOR_VERSION)</strong>'
-JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>For further API reference and developer documentation, see <a href="{@docroot}/../../webnotes/devdocs-vs-specs.html">Java SE Developer Documentation</a>. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>. Also see the <a href="http://java.sun.com/docs/redist.html">documentation redistribution policy</a>.</font>'
-JAVADOCOVERVIEW = $(SHARE_SRC)/classes/overview-core.html
-
-#
-# Early access top and bottom text (for snapshots, beta and rc)
-#
-JAVADOCTOP_EARLYACCESS = '<div style="background-color: \#EEEEEE"> <div style="padding: 6px; margin-top: 2px; margin-bottom: 6px; margin-left: 6px; margin-right: 6px; text-align: justify; font-size: 80%; font-family: Helvetica, Arial, sans-serif; font-weight: normal;"> Please note that this documentation is not final and is subject to change. </div> </div>'
-JAVADOCBOTTOM_EARLYACCESS = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a> <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>.</font>'
-JAVADOCTITLE_EARLYACCESS = $(subst Specification,Documentation,$(JAVADOCTITLE))
-
-#
-# Variables used by domapidocs target
-#
-
-DOMAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -splitIndex \
- -doctitle $(DOMAPI_JAVADOCTITLE) \
- -windowtitle $(DOMAPI_JAVADOCWINDOWTITLE) \
- -header $(DOMAPI_JAVADOCHEADER) \
- -bottom $(DOMAPI_JAVADOCBOTTOM) \
- -group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)
-DOMAPI_JAVADOCTITLE = 'Common DOM API'
-DOMAPI_JAVADOCWINDOWTITLE = 'Common DOM API'
-DOMAPI_JAVADOCHEADER = '<strong>Common DOM API</strong>'
-DOMAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>'
-DOMAPI_GROUPNAME = "Packages"
-DOMAPI_REGEXP = "com.sun.java.browser.dom:org.w3c.dom*"
-# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by mirrordocs target
-#
-
-MIRROR_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -doctitle $(MIRROR_JAVADOCTITLE) \
- -windowtitle $(MIRROR_JAVADOCWINDOWTITLE) \
- -header $(MIRROR_JAVADOCHEADER) \
- -bottom $(MIRROR_JAVADOCBOTTOM) \
- -group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP) \
- -overview $(MIRROR_OVERVIEW)
-MIRROR_JAVADOCTITLE = 'Mirror API'
-MIRROR_JAVADOCWINDOWTITLE = 'Mirror API'
-MIRROR_JAVADOCHEADER = '<strong>Mirror API</strong>'
-MIRROR_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-MIRROR_GROUPNAME = "Packages"
-MIRROR_OVERVIEW = $(IMPORTSRCDIR)/com/sun/mirror/overview.html
-MIRROR_REGEXP = "com.sun.mirror.*"
-MIRROR_DESTDIR = $(DOCSDIR)/jdk/api/apt/mirror
-MIRROR_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# MIRROR_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by docletapidocs target
-#
-
-DOCLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -breakiterator \
- -encoding ascii \
- -doctitle $(DOCLETAPI_JAVADOCTITLE) \
- -windowtitle $(DOCLETAPI_JAVADOCWINDOWTITLE) \
- -header $(DOCLETAPI_JAVADOCHEADER) \
- -bottom $(DOCLETAPI_JAVADOCBOTTOM) \
- -group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)
-DOCLETAPI_JAVADOCTITLE = 'Doclet API'
-DOCLETAPI_JAVADOCWINDOWTITLE = 'Doclet API'
-DOCLETAPI_JAVADOCHEADER = '<strong>Doclet API</strong>'
-DOCLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>'
-DOCLETAPI_GROUPNAME = "Packages"
-DOCLETAPI_REGEXP = "com.sun.javadoc"
-DOCLETAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by tagletapidocs target
-#
-
-TAGLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nonavbar \
- -noindex \
- -bottom $(TAGLETAPI_JAVADOCBOTTOM)
-TAGLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>'
-# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jdi target
-#
-
-JPDA_SOURCEPATH = $(TOPDIR)/src/share/classes
-
-JDI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(DOCSDIR)/jdk/api/jpda/jdi \
- -sourcepath $(JPDA_SOURCEPATH) \
- -windowtitle $(JDI_WINDOWTITLE) \
- -doctitle $(JDI_DOCTITLE) \
- -header $(JDI_HEADER) \
- -linkoffline ../../../../api $(DOCSDIR)/api/ \
- -overview $(JPDA_SOURCEPATH)/jdi-overview.html
-JDI_WINDOWTITLE = "Java Debug Interface"
-JDI_DOCTITLE = "Java$(TRADEMARK) Debug Interface"
-JDI_HEADER = "Java Debug Interface"
-# JDI_PKGS is located in NON_CORE_PKGS.gmk
-
-# Variables used by security components
-SECURITYAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-
-#
-# Variables used by JAAS target
-#
-# NOTE: Quotes are required around sourcepath argument only on Windows. Otherwise,
-# you get "No packages or classes specified." due to $(CLASSPATH_SEPARATOR)
-# being interpreted as an end of command (newline)
-
-JAAS_SOURCEPATH = "$(TOPDIR)/src/share/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/solaris/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/windows/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/linux/classes"
-JAAS_DOCDIR = $(DOCSDIR)/jre/api/security/jaas/spec
-JAAS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(JAAS_DOCDIR) \
- -sourcepath $(JAAS_SOURCEPATH) \
- -windowtitle $(JAAS_WINDOWTITLE) \
- -doctitle $(JAAS_DOCTITLE) \
- -header $(JAAS_JAVADOCHEADER) \
- -bottom $(SECURITYAPI_JAVADOCBOTTOM) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/ \
- -overview $(TOPDIR)/src/share/classes/com/sun/security/auth/jaas-overview.html
-JAAS_WINDOWTITLE = "Java Authentication and Authorization Service "
-JAAS_DOCTITLE = "Java$(TRADEMARK) Authentication and Authorization Service"
-JAAS_JAVADOCHEADER = "JAAS"
-# JAAS_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by JGSS target
-#
-
-JGSS_SOURCEPATH = $(TOPDIR)/src/share/classes
-JGSS_DOCDIR = $(DOCSDIR)/jre/api/security/jgss/spec
-
-JGSS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(JGSS_DOCDIR) \
- -sourcepath $(JGSS_SOURCEPATH) \
- -windowtitle $(JGSS_WINDOWTITLE) \
- -doctitle $(JGSS_DOCTITLE) \
- -header $(JGSS_JAVADOCHEADER) \
- -bottom $(SECURITYAPI_JAVADOCBOTTOM) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/ \
- -overview $(JGSS_SOURCEPATH)/com/sun/security/jgss/jgss-overview.html
-
-JGSS_WINDOWTITLE = "Java GSS-API Utilities "
-JGSS_DOCTITLE = "Java$(TRADEMARK) GSS-API Utilities"
-JGSS_JAVADOCHEADER = "Java GSS-API Utilities"
-# JGSS_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by SMARTCARDIO target
-#
-
-SMARTCARDIO_SOURCEPATH = $(TOPDIR)/src/share/classes
-SMARTCARDIO_DOCDIR = $(DOCSDIR)/jre/api/security/smartcardio/spec
-
-SMARTCARDIO_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(SMARTCARDIO_DOCDIR) \
- -sourcepath $(SMARTCARDIO_SOURCEPATH) \
- -windowtitle $(SMARTCARDIO_WINDOWTITLE) \
- -doctitle $(SMARTCARDIO_DOCTITLE) \
- -header $(SMARTCARDIO_JAVADOCHEADER) \
- -bottom $(SECURITYAPI_JAVADOCBOTTOM) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-SMARTCARDIO_WINDOWTITLE = "Java Smart Card I/O"
-SMARTCARDIO_DOCTITLE = "Java$(TRADEMARK) Smart Card I/O"
-SMARTCARDIO_JAVADOCHEADER = "Java Smart Card I/O"
-# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by TRACING target
-#
-
-TRACING_SOURCEPATH = $(TOPDIR)/src/share/classes
-TRACING_DOCDIR = $(DOCSDIR)/jre/api/tracing
-
-TRACING_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(TRACING_DOCDIR) \
- -sourcepath $(TRACING_SOURCEPATH) \
- -windowtitle $(TRACING_WINDOWTITLE) \
- -doctitle $(TRACING_DOCTITLE) \
- -header $(TRACING_JAVADOCHEADER) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-TRACING_WINDOWTITLE = "Tracing"
-TRACING_DOCTITLE = "Java$(TRADEMARK) Platform Tracing"
-TRACING_JAVADOCHEADER = "Platform Tracing"
-# TRACING_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by HTTPSERVER target
-#
-
-HTTPSERVER_SOURCEPATH = $(TOPDIR)/src/share/classes
-HTTPSERVER_DOCDIR = $(DOCSDIR)/jre/api/net/httpserver/spec
-
-HTTPSERVER_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(HTTPSERVER_DOCDIR) \
- -sourcepath $(HTTPSERVER_SOURCEPATH) \
- -windowtitle $(HTTPSERVER_WINDOWTITLE) \
- -doctitle $(HTTPSERVER_DOCTITLE) \
- -header $(HTTPSERVER_JAVADOCHEADER) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-HTTPSERVER_WINDOWTITLE = "Java HTTP Server"
-HTTPSERVER_DOCTITLE = "Java$(TRADEMARK) HTTP Server"
-HTTPSERVER_JAVADOCHEADER = "Java HTTP Server"
-# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by sctp target
-#
-
-SCTPAPI_SOURCEPATH = $(TOPDIR)/src/share/classes
-SCTPAPI_DOCDIR = $(DOCSDIR)/jre/api/nio/sctp/spec
-
-SCTPAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(SCTPAPI_DOCDIR) \
- -sourcepath $(SCTPAPI_SOURCEPATH) \
- -windowtitle $(SCTPAPI_WINDOWTITLE) \
- -doctitle $(SCTPAPI_DOCTITLE) \
- -header $(SCTPAPI_JAVADOCHEADER) \
- -bottom $(SCTPAPI_JAVADOCBOTTOM) \
- -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-SCTPAPI_WINDOWTITLE = "SCTP API"
-SCTPAPI_DOCTITLE = "SCTP API"
-SCTPAPI_JAVADOCHEADER = "SCTP API"
-SCTPAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jvmti target
-#
-JVMTI_DOCS_SUBDIR = platform/jvmti
-JVMTI_HTML = $(HOTSPOT_DOCS_IMPORT_PATH)/$(JVMTI_DOCS_SUBDIR)/jvmti.html
-
-#
-# Variables used by mgmt target
-#
-MGMT_DOCDIR = $(DOCSDIR)/jre/api/management/
-MGMT_EXT_DIR = $(MGMT_DOCDIR)/extension
-MGMT_SOURCEPATH = $(TOPDIR)/src/share/classes
-JVM_MIB_NAME = JVM-MANAGEMENT-MIB.mib
-JVM_MIB_SRC = $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
-
-ifdef OPENJDK
- COPY-MIB-TARGET =
-else
- COPY-MIB-TARGET = copy-mib
-endif
-MGMT_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(MGMT_EXT_DIR) \
- -sourcepath $(MGMT_SOURCEPATH) \
- -windowtitle $(MGMT_WINDOWTITLE) \
- -doctitle $(MGMT_DOCTITLE) \
- -header $(MGMT_HEADER) \
- -linkoffline ../../../../api $(DOCSDIR)/api/ \
- -overview $(MGMT_SOURCEPATH)/com/sun/management/mgmt-overview.html
-MGMT_WINDOWTITLE = "Monitoring and Management Interface for the Java Platform"
-MGMT_DOCTITLE = "Monitoring and Management Interface for the Java$(TRADEMARK) Platform"
-MGMT_HEADER = "Monitoring and Management Interface for the Java Platform"
-# MGMT_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by attach target
-#
-
-ATTACH_SOURCEPATH = $(TOPDIR)/src/share/classes
-ATTACH_DOCDIR = $(DOCSDIR)/jdk/api/attach/spec
-ATTACH_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(ATTACH_DOCDIR) \
- -sourcepath $(ATTACH_SOURCEPATH) \
- -windowtitle $(ATTACH_WINDOWTITLE) \
- -doctitle $(ATTACH_DOCTITLE) \
- -header $(ATTACH_HEADER) \
- -linkoffline ../../../../api $(DOCSDIR)/api/
-ATTACH_WINDOWTITLE = "Attach API"
-ATTACH_DOCTITLE = "Attach API"
-ATTACH_HEADER = "Attach API"
-# ATTACH_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jconsole target
-#
-
-JCONSOLE_SOURCEPATH = $(TOPDIR)/src/share/classes
-JCONSOLE_DOCDIR = $(DOCSDIR)/jdk/api/jconsole/spec
-JCONSOLE_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -nodeprecatedlist \
- -d $(JCONSOLE_DOCDIR) \
- -sourcepath $(JCONSOLE_SOURCEPATH) \
- -windowtitle $(JCONSOLE_WINDOWTITLE) \
- -doctitle $(JCONSOLE_DOCTITLE) \
- -header $(JCONSOLE_HEADER) \
- -linkoffline ../../../../api $(DOCSDIR)/api/
-JCONSOLE_WINDOWTITLE = "JConsole API"
-JCONSOLE_DOCTITLE = "JConsole API"
-JCONSOLE_HEADER = "JConsole API"
-# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by treeapidocs target
-#
-
-TREEAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \
- -encoding ascii \
- -doctitle $(TREEAPI_JAVADOCTITLE) \
- -windowtitle $(TREEAPI_JAVADOCWINDOWTITLE) \
- -header $(TREEAPI_JAVADOCHEADER) \
- -bottom $(TREEAPI_JAVADOCBOTTOM) \
- -group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP)
-#
-# -overview $(TREEAPI_OVERVIEW)
-#
-TREEAPI_JAVADOCTITLE = 'Compiler Tree API'
-TREEAPI_JAVADOCWINDOWTITLE = 'Compiler Tree API'
-TREEAPI_JAVADOCHEADER = '<strong>Compiler Tree API</strong>'
-TREEAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-TREEAPI_GROUPNAME = "Packages"
-TREEAPI_OVERVIEW = $(SHARE_SRC)/classes/com/sun/source/overview.html
-TREEAPI_REGEXP = "com.sun.source.*"
-TREEAPI_DESTDIR = $(DOCSDIR)/jdk/api/javac/tree
-TREEAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Path where javadoc should find source files for release docs
-#
-RELEASEDOCS_SRCPATH = "$(SHARE_SRC)/classes$(CLASSPATH_SEPARATOR)$(PLATFORM_SRC)/classes$(CLASSPATH_SEPARATOR)$(GENSRCDIR)$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/doc/stub$(CLASSPATH_SEPARATOR)$(CLOSED_SRC)/share/classes$(CLASSPATH_SEPARATOR)$(IMPORTSRCDIR)"
+#################################################################
#
# CORE_PKGS environment variable has been moved to the following file
@@ -463,30 +234,13 @@
#
include NON_CORE_PKGS.gmk
-# Targets for all APIs other than the core platform APIs
-ALL_OTHER_TARGETS = \
- mirrordocs \
- docletapidocs \
- tagletapidocs \
- domapidocs \
- jpdadocs \
- jaasdocs \
- jgssdocs \
- smartcardiodocs \
- tracingdocs \
- httpserverdocs \
- sctpdocs \
- mgmtdocs \
- attachdocs \
- jconsoledocs \
- treeapidocs
+#################################################################
-.PHONY: all docs
-all docs: coredocs otherdocs
+#
+# Default target is same as docs target, create core api and all others it can
+#
-.PHONY: otherdocs
-otherdocs: ${ALL_OTHER_TARGETS}
-
+all docs: coredocs otherdocs
#################################################################
# Production Targets -- USE THESE TARGETS WHEN:
@@ -496,9 +250,9 @@
# the downloaded doc bundle.
#
# See: Notes.html#releaseTargets
-# Note: Spaces preceed ifdef/ifndef indents. Tabs preceed target commands (!)
+# Note: Spaces precede ifdef/ifndef indents. Tabs precede target commands (!)
#
-.PHONY: sanitycheckcoredocs
+
sanitycheckcoredocs:
@$(ECHO) ""
@$(ECHO) "Building core api docs with these values:"
@@ -512,199 +266,942 @@
exit 1
endif
-# Maximize performance and ensure that build number & milestone are set.
-.PHONY: rel-coredocs
-rel-coredocs: sanitycheckcoredocs
- @# ######## release version of core packages ########
- $(MAKE) coredocs
+#############################################################
+#
+# coredocs
+#
+COREAPI_DOCTITLE = Java$(TRADEMARK) Platform, Standard Edition \
+$(JDK_MINOR_VERSION)<br>API Specification
+COREAPI_WINDOWTITLE = Java Platform SE $(JDK_MINOR_VERSION)
+COREAPI_HEADER = \
+<strong>Java$(TRADEMARK) Platform<br>Standard Ed. $(JDK_MINOR_VERSION)</strong>
+
+# Ignored tags
+IGNORED_TAGS = beaninfo revised since.unbundled spec specdefault Note ToDo
+
+# Java language specification cite
+JLS3_CITE = <a href=\"$(JLS3_URL)\"> \
+ The Java Language Specification, Third Edition</a>
+TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:'
+
+TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3)
+
+# Overview file for core apis
+COREAPI_OVERVIEW = $(SHARE_SRC)/classes/overview-core.html
+
+# The index.html, options, and packages files
+COREAPI_INDEX_FILE = $(COREAPI_DOCSDIR)/index.html
+COREAPI_OPTIONS_FILE = $(DOCSTMPDIR)/coredocs.options
+COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages
+
+coredocs: $(COREAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(COREAPI_INDEX_FILE): GET2DOCSDIR=..
-.PHONY: rel-docs
-rel-docs: rel-coredocs ${ALL_OTHER_TARGETS}
+# Run javadoc if the index file is out of date or missing
+$(COREAPI_INDEX_FILE): $(COREAPI_OPTIONS_FILE) $(COREAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(COREAPI_OPTIONS_FILE),$(COREAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(COREAPI_OPTIONS_FILE) @$(COREAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(COREAPI_OPTIONS_FILE): $(COREAPI_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "$(TAGS)" ; \
+ $(ECHO) "-encoding ISO-8859-1" ; \
+ $(ECHO) "-splitIndex" ; \
+ $(ECHO) "-overview $(COREAPI_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(COREAPI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(COREAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(COREAPI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(COREAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ ) >> $@
+ifdef COREAPI_TOP_EARLYACCESS
+ @$(ECHO) "-top '$(COREAPI_TOP_EARLYACCESS)'" >> $@
+endif
+
+# Create a file with the package names in it
+$(COREAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(CORE_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(CORE_PKGS))
+
+#############################################################
#
-# end of production targets
-#############################################################
+# mirrordocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+ ALL_OTHER_TARGETS += mirrordocs
+endif
-.PHONY: coredocs
-coredocs:
- @# ######## core packages #######################
- $(RM) -r $(DOCSDIR)/api
- $(MKDIR) -p $(DOCSDIR)/api
- $(JAVADOC_CMD) $(CORE_JAVADOCFLAGS) \
- -d $(DOCSDIR)/api \
- -sourcepath $(RELEASEDOCS_SRCPATH) \
- $(CORE_PKGS)
+MIRROR_DOCDIR := $(JDK_API_DOCSDIR)/apt/mirror
+MIRROR2COREAPI := ../../$(JDKJRE2COREAPI)
+MIRROR_DOCTITLE := Mirror API
+MIRROR_WINDOWTITLE := Mirror API
+MIRROR_HEADER := <strong>Mirror API</strong>
+MIRROR_BOTTOM := $(call CommonBottom,$(MIRROR_FIRST_COPYRIGHT_YEAR))
+MIRROR_GROUPNAME := Packages
+MIRROR_OVERVIEW := $(IMPORTSRCDIR)/com/sun/mirror/overview.html
+MIRROR_REGEXP := com.sun.mirror.*
+# MIRROR_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+MIRROR_INDEX_FILE = $(MIRROR_DOCDIR)/index.html
+MIRROR_OPTIONS_FILE = $(DOCSTMPDIR)/mirror.options
+MIRROR_PACKAGES_FILE = $(DOCSTMPDIR)/mirror.packages
+
+mirrordocs: $(MIRROR_INDEX_FILE)
+
+# Set relative location to core api document root
+$(MIRROR_INDEX_FILE): GET2DOCSDIR=$(MIRROR2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(MIRROR_INDEX_FILE): $(MIRROR_OPTIONS_FILE) $(MIRROR_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(MIRROR_OPTIONS_FILE),$(MIRROR_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(MIRROR_OPTIONS_FILE) @$(MIRROR_PACKAGES_FILE)
-.PHONY: mirrordocs
-mirrordocs:
- @# ######## mirror api for apt ##################
- $(RM) -r $(MIRROR_DESTDIR)
- $(MKDIR) -p $(MIRROR_DESTDIR)
- $(JAVADOC_CMD) $(MIRROR_JAVADOCFLAGS) \
- -d $(MIRROR_DESTDIR) \
- -sourcepath $(RELEASEDOCS_SRCPATH) \
- $(MIRROR_LINKOPT) \
- $(MIRROR_PKGS)
+# Create file with javadoc options in it
+$(MIRROR_OPTIONS_FILE): $(MIRROR_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-overview $(MIRROR_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(MIRROR_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(MIRROR_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(MIRROR_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(MIRROR_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP)" ; \
+ $(ECHO) "-linkoffline $(MIRROR2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(MIRROR_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MIRROR_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(MIRROR_PKGS))
+
+#############################################################
+#
+# docletapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+ ALL_OTHER_TARGETS += docletapidocs
+endif
+
+DOCLETAPI_DOCDIR := $(JDK_API_DOCSDIR)/javadoc/doclet
+DOCLETAPI2COREAPI := ../../$(JDKJRE2COREAPI)
+DOCLETAPI_DOCTITLE := Doclet API
+DOCLETAPI_WINDOWTITLE := Doclet API
+DOCLETAPI_HEADER := <strong>Doclet API</strong>
+DOCLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOCLETAPI_FIRST_COPYRIGHT_YEAR))
+DOCLETAPI_GROUPNAME := Packages
+DOCLETAPI_REGEXP := com.sun.javadoc
+# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+DOCLETAPI_INDEX_FILE = $(DOCLETAPI_DOCDIR)/index.html
+DOCLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/docletapi.options
+DOCLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/docletapi.packages
+
+docletapidocs: $(DOCLETAPI_INDEX_FILE)
-.PHONY: docletapidocs
-docletapidocs:
- @# ######## doclet api ############################
- $(RM) -r $(DOCSDIR)/jdk/api/javadoc/doclet
- $(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/doclet
- $(JAVADOC_CMD) $(DOCLETAPI_JAVADOCFLAGS) \
- -d $(DOCSDIR)/jdk/api/javadoc/doclet \
- -sourcepath $(RELEASEDOCS_SRCPATH) \
- $(DOCLETAPI_LINKOPT) \
- $(DOCLETAPI_PKGS)
+# Set relative location to core api document root
+$(DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(DOCLETAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(DOCLETAPI_OPTIONS_FILE),$(DOCLETAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(DOCLETAPI_OPTIONS_FILE) @$(DOCLETAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(DOCLETAPI_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-breakiterator" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-doctitle '$(DOCLETAPI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(DOCLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(DOCLETAPI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(DOCLETAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)" ; \
+ $(ECHO) "-linkoffline $(DOCLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(DOCLETAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOCLETAPI_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(DOCLETAPI_PKGS))
+
+#############################################################
+#
+# tagletapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+ ALL_OTHER_TARGETS += tagletapidocs
+endif
+
+TAGLETAPI_DOCDIR := $(JDK_API_DOCSDIR)/javadoc/taglet
+TAGLETAPI2COREAPI := ../../$(JDKJRE2COREAPI)
+TAGLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(TAGLETAPI_FIRST_COPYRIGHT_YEAR))
+# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
+
+# Temporary directory (special generation rules)
+TAGLETAPI_TEMPDIR = $(DOCSTMPDIR)/taglets_temp
+
+# The index.html, options, and packages files
+TAGLETAPI_INDEX_FILE = $(TAGLETAPI_DOCDIR)/index.html
+TAGLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/tagletapi.options
+TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages
+
+tagletapidocs: $(TAGLETAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(TAGLETAPI_INDEX_FILE): GET2DOCSDIR=$(TAGLETAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(RM) -r $(TAGLETAPI_TEMPDIR)
+ $(MKDIR) -p $(TAGLETAPI_TEMPDIR)
+ $(call JavadocSummary,$(TAGLETAPI_OPTIONS_FILE),$(TAGLETAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(TAGLETAPI_TEMPDIR) \
+ @$(TAGLETAPI_OPTIONS_FILE) @$(TAGLETAPI_PACKAGES_FILE)
+ cp -r $(TAGLETAPI_TEMPDIR)/com $(@D)
+ cp $(TAGLETAPI_TEMPDIR)/stylesheet.css $(@D)
+ $(RM) -r $(TAGLETAPI_TEMPDIR)
-.PHONY: tagletapidocs
-tagletapidocs:
- @# ######## taglet api ############################
- $(RM) -r $(DOCSDIR)/jdk/api/javadoc/taglet
- $(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/taglet
- $(RM) -r $(DOCSTMPDIR)
- $(MKDIR) -p $(DOCSTMPDIR)
- $(JAVADOC_CMD) $(TAGLETAPI_JAVADOCFLAGS) \
- -d $(DOCSTMPDIR) \
- -linkoffline ../../../../api $(DOCSDIR)/api/ \
- $(IMPORTSRCDIR)/$(TAGLETAPI_FILE)
- cp -r $(DOCSTMPDIR)/com $(DOCSDIR)/jdk/api/javadoc/taglet
- cp $(DOCSTMPDIR)/stylesheet.css $(DOCSDIR)/jdk/api/javadoc/taglet
- $(RM) -r $(DOCSTMPDIR)
+# Create file with javadoc options in it
+$(TAGLETAPI_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nonavbar" ; \
+ $(ECHO) "-noindex" ; \
+ $(ECHO) "-bottom '$(TAGLETAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(TAGLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(TAGLETAPI_PACKAGES_FILE): $(IMPORTSRCDIR)/$(TAGLETAPI_FILE)
+ $(prep-target)
+ @($(ECHO) "$(IMPORTSRCDIR)/$(TAGLETAPI_FILE)" ) > $@
+
+#############################################################
+#
+# domapidocs
+#
+
+ALL_OTHER_TARGETS += domapidocs
+
+DOMAPI_DOCDIR := $(JRE_API_DOCSDIR)/plugin/dom
+DOMAPI2COREAPI := ../../$(JDKJRE2COREAPI)
+DOMAPI_DOCTITLE := Common DOM API
+DOMAPI_WINDOWTITLE := Common DOM API
+DOMAPI_HEADER := <strong>Common DOM API</strong>
+DOMAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOMAPI_FIRST_COPYRIGHT_YEAR))
+DOMAPI_GROUPNAME := Packages
+DOMAPI_REGEXP := com.sun.java.browser.dom:org.w3c.dom*
+# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+DOMAPI_INDEX_FILE = $(DOMAPI_DOCDIR)/index.html
+DOMAPI_OPTIONS_FILE = $(DOCSTMPDIR)/domapi.options
+DOMAPI_PACKAGES_FILE = $(DOCSTMPDIR)/domapi.packages
-.PHONY: domapidocs
-domapidocs:
- @# ######## dom api ############################
- $(RM) -r $(DOCSDIR)/jre/api/plugin/dom
- $(MKDIR) -p $(DOCSDIR)/jre/api/plugin/dom
- $(JAVADOC_CMD) $(DOMAPI_JAVADOCFLAGS) \
- -d $(DOCSDIR)/jre/api/plugin/dom \
- -sourcepath $(RELEASEDOCS_SRCPATH) \
- -linkoffline ../../../../api $(DOCSDIR)/api/ \
- $(DOMAPI_PKGS)
+domapidocs: $(DOMAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(DOMAPI_INDEX_FILE): GET2DOCSDIR=$(DOMAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(DOMAPI_OPTIONS_FILE),$(DOMAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(DOMAPI_OPTIONS_FILE) @$(DOMAPI_PACKAGES_FILE)
-.PHONY: jpdadocs
+# Create file with javadoc options in it
+$(DOMAPI_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-splitIndex" ; \
+ $(ECHO) "-doctitle '$(DOMAPI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(DOMAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(DOMAPI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(DOMAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)" ; \
+ $(ECHO) "-linkoffline $(DOMAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(DOMAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOMAPI_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(DOMAPI_PKGS))
+
+#############################################################
+#
+# jpdadocs
+#
+
+ALL_OTHER_TARGETS += jpdadocs
+
jpdadocs: jdidocs jdwpdocs jvmtidocs
-.PHONY: jdidocs
-jdidocs:
- @# ######## jdi #################################
- $(RM) -r $(DOCSDIR)/jdk/api/jpda/jdi
- $(MKDIR) -p $(DOCSDIR)/jdk/api/jpda/jdi
- $(JAVADOC_CMD) $(JDI_JAVADOCFLAGS) \
- $(JDI_PKGS)
+#############################################################
+#
+# jdidocs
+#
+
+ALL_OTHER_TARGETS += jdidocs
+
+JDI_DOCDIR := $(JDK_API_DOCSDIR)/jpda/jdi
+JDI2COREAPI := ../../$(JDKJRE2COREAPI)
+JDI_DOCTITLE := Java$(TRADEMARK) Debug Interface
+JDI_WINDOWTITLE := Java Debug Interface
+JDI_HEADER := <strong>Java Debug Interface</strong>
+JDI_BOTTOM := $(call CommonBottom,$(JDI_FIRST_COPYRIGHT_YEAR))
+JDI_OVERVIEW := $(SHARE_SRC)/classes/jdi-overview.html
+# JDI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+JDI_INDEX_FILE = $(JDI_DOCDIR)/index.html
+JDI_OPTIONS_FILE = $(DOCSTMPDIR)/jdi.options
+JDI_PACKAGES_FILE = $(DOCSTMPDIR)/jdi.packages
+
+jdidocs: $(JDI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JDI_INDEX_FILE): GET2DOCSDIR=$(JDI2COREAPI)/..
+# Run javadoc if the index file is out of date or missing
+$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(JDI_OPTIONS_FILE),$(JDI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(JDI_OPTIONS_FILE) @$(JDI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JDI_OPTIONS_FILE): $(JDI_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-overview $(JDI_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(JDI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(JDI_WINDOWTITLE) $(DRAFT_WINTITLE)'" ; \
+ $(ECHO) "-header '$(JDI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(JDI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(JDI2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(JDI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDI_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(JDI_PKGS))
+
+#############################################################
+#
+# jdwpdocs
+#
+
+ALL_OTHER_TARGETS += jdwpdocs
+
+JDWP_DOCDIR = $(PLATFORM_DOCSDIR)/jpda/jdwp
JDWP_SPEC = $(BUILDDIR)/jpda/jdwp/jdwp.spec
-JDWP_DOC = $(DOCSDIR)/platform/jpda/jdwp/jdwp-protocol.html
JDWPGEN_JARFILE = $(BUILDTOOLJARDIR)/jdwpgen.jar
-.PHONY: jdwpdocs
-jdwpdocs: $(JDWP_DOC)
+jdwpdocs: $(JDWP_DOCDIR)/jdwp-protocol.html
+$(JDWP_DOCDIR)/jdwp-protocol.html: $(JDWPGEN_JARFILE) $(JDWP_SPEC)
+ $(prep-javadoc)
+ $(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $@
-$(JDWP_DOC): $(JDWPGEN_JARFILE) $(JDWP_SPEC)
- $(prep-target)
- $(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $(JDWP_DOC)
+#############################################################
+#
+# jvmtidocs
+#
+
+ALL_OTHER_TARGETS += jvmtidocs
-.PHONY: jvmtidocs
-jvmtidocs:
- @# ######## jvmti #################################
- @if [ -f $(JVMTI_HTML) ] ; then \
- $(RM) -r $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
- $(MKDIR) -p $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
- $(ECHO) $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
- $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
- else \
- $(ECHO) "WARNING: Generated jvmti file does not exist: $(JVMTI_HTML)"; \
+JVMTI_DOCDIR = $(PLATFORM_DOCSDIR)/jvmti
+JVMTI_HTML = $(HOTSPOT_DOCS_IMPORT_PATH)/platform/jvmti/jvmti.html
+
+jvmtidocs: $(JVMTI_DOCDIR)/jvmti.html
+$(JVMTI_DOCDIR)/jvmti.html:
+ @$(prep-javadoc)
+ @if [ -f $(JVMTI_HTML) ] ; then \
+ $(ECHO) "$(CP) $(JVMTI_HTML) $@"; \
+ $(CP) $(JVMTI_HTML) $@; \
+ else \
+ $(ECHO) "WARNING: Generated file does not exist: $(JVMTI_HTML)"; \
fi
-.PHONY: jaasdocs
-jaasdocs:
- @# ######## api-jaas ############################
- $(RM) -r $(JAAS_DOCDIR)
- $(MKDIR) -p $(JAAS_DOCDIR)
- $(JAVADOC_CMD) $(JAAS_JAVADOCFLAGS) \
- $(JAAS_PKGS)
+#############################################################
+#
+# jaasdocs
+#
+
+ALL_OTHER_TARGETS += jaasdocs
+
+JAAS_DOCDIR := $(JRE_API_DOCSDIR)/security/jaas/spec
+JAAS2COREAPI := ../../../$(JDKJRE2COREAPI)
+JAAS_DOCTITLE := Java$(TRADEMARK) Authentication and Authorization Service
+JAAS_WINDOWTITLE := Java Authentication and Authorization Service
+JAAS_HEADER := <strong>Java Authentication and Authorization Service</strong>
+JAAS_BOTTOM := $(call CommonBottom,$(JAAS_FIRST_COPYRIGHT_YEAR))
+# JAAS_PKGS is located in NON_CORE_PKGS.gmk
+JAAS_OVERVIEW := $(SHARE_SRC)/classes/com/sun/security/auth/jaas-overview.html
+
+# The index.html, options, and packages files
+JAAS_INDEX_FILE = $(JAAS_DOCDIR)/index.html
+JAAS_OPTIONS_FILE = $(DOCSTMPDIR)/jaas.options
+JAAS_PACKAGES_FILE = $(DOCSTMPDIR)/jaas.packages
+
+jaasdocs: $(JAAS_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JAAS_INDEX_FILE): GET2DOCSDIR=$(JAAS2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(JAAS_OPTIONS_FILE),$(JAAS_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(JAAS_OPTIONS_FILE) @$(JAAS_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JAAS_OPTIONS_FILE): $(JAAS_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-overview $(JAAS_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(JAAS_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(JAAS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+ $(ECHO) "-header '$(JAAS_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(JAAS_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(JAAS2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(JAAS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JAAS_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(JAAS_PKGS))
+
+#############################################################
+#
+# jgssdocs
+#
+
+ALL_OTHER_TARGETS += jgssdocs
+
+JGSS_DOCDIR := $(JRE_API_DOCSDIR)/security/jgss/spec
+JGSS2COREAPI := ../../../$(JDKJRE2COREAPI)
+JGSS_DOCTITLE := Java$(TRADEMARK) GSS-API Utilities
+JGSS_WINDOWTITLE := Java GSS-API Utilities
+JGSS_HEADER := <strong>Java GSS-API Utilities</strong>
+JGSS_BOTTOM := $(call CommonBottom,$(JGSS_FIRST_COPYRIGHT_YEAR))
+JGSS_OVERVIEW := $(SHARE_SRC)/classes/com/sun/security/jgss/jgss-overview.html
+# JGSS_PKGS is located in NON_CORE_PKGS.gmk
-.PHONY: jgssdocs
-jgssdocs:
- @# ######## api-jgss ############################
- $(RM) -r $(JGSS_DOCDIR)
- $(MKDIR) -p $(JGSS_DOCDIR)
- $(JAVADOC_CMD) $(JGSS_JAVADOCFLAGS) \
- $(JGSS_PKGS)
+# The index.html, options, and packages files
+JGSS_INDEX_FILE = $(JGSS_DOCDIR)/index.html
+JGSS_OPTIONS_FILE = $(DOCSTMPDIR)/jgss.options
+JGSS_PACKAGES_FILE = $(DOCSTMPDIR)/jgss.packages
+
+jgssdocs: $(JGSS_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JGSS_INDEX_FILE): GET2DOCSDIR=$(JGSS2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(JGSS_OPTIONS_FILE),$(JGSS_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(JGSS_OPTIONS_FILE) @$(JGSS_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JGSS_OPTIONS_FILE): $(JGSS_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-overview $(JGSS_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(JGSS_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(JGSS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+ $(ECHO) "-header '$(JGSS_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(JGSS_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(JGSS2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(JGSS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JGSS_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(JGSS_PKGS))
+
+#############################################################
+#
+# smartcardiodocs
+#
+
+ALL_OTHER_TARGETS += smartcardiodocs
+
+SMARTCARDIO_DOCDIR := $(JRE_API_DOCSDIR)/security/smartcardio/spec
+SMARTCARDIO2COREAPI := ../../../$(JDKJRE2COREAPI)
+SMARTCARDIO_DOCTITLE := Java$(TRADEMARK) Smart Card I/O
+SMARTCARDIO_WINDOWTITLE := Java Smart Card I/O
+SMARTCARDIO_HEADER := <strong>Java Smart Card I/O</strong>
+SMARTCARDIO_BOTTOM := $(call CommonBottom,$(SMARTCARDIO_FIRST_COPYRIGHT_YEAR))
+# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+SMARTCARDIO_INDEX_FILE = $(SMARTCARDIO_DOCDIR)/index.html
+SMARTCARDIO_OPTIONS_FILE = $(DOCSTMPDIR)/smartcardio.options
+SMARTCARDIO_PACKAGES_FILE = $(DOCSTMPDIR)/smartcardio.packages
+
+smartcardiodocs: $(SMARTCARDIO_INDEX_FILE)
+
+# Set relative location to core api document root
+$(SMARTCARDIO_INDEX_FILE): GET2DOCSDIR=$(SMARTCARDIO2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(SMARTCARDIO_OPTIONS_FILE),$(SMARTCARDIO_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(SMARTCARDIO_OPTIONS_FILE) @$(SMARTCARDIO_PACKAGES_FILE)
-.PHONY: smartcardiodocs
-smartcardiodocs:
- @# ######## api-smartcardio ############################
- $(RM) -r $(SMARTCARDIO_DOCDIR)
- $(MKDIR) -p $(SMARTCARDIO_DOCDIR)
- $(JAVADOC_CMD) $(SMARTCARDIO_JAVADOCFLAGS) \
- $(SMARTCARDIO_PKGS)
+# Create file with javadoc options in it
+$(SMARTCARDIO_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(SMARTCARDIO_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(SMARTCARDIO_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(SMARTCARDIO_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(SMARTCARDIO_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(SMARTCARDIO2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(SMARTCARDIO_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SMARTCARDIO_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(SMARTCARDIO_PKGS))
+
+#############################################################
+#
+# httpserverdocs
+#
+
+ALL_OTHER_TARGETS += httpserverdocs
+
+HTTPSERVER_DOCDIR := $(JRE_API_DOCSDIR)/net/httpserver/spec
+HTTPSERVER2COREAPI := ../../../$(JDKJRE2COREAPI)
+HTTPSERVER_DOCTITLE := Java$(TRADEMARK) HTTP Server
+HTTPSERVER_WINDOWTITLE := Java HTTP Server
+HTTPSERVER_HEADER := <strong>Java HTTP Server</strong>
+HTTPSERVER_BOTTOM := $(call CommonBottom,$(HTTPSERVER_FIRST_COPYRIGHT_YEAR))
+# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk
+
+HTTPSERVER_INDEX_HTML = $(HTTPSERVER_DOCDIR)/index.html
+HTTPSERVER_OPTIONS_FILE = $(DOCSTMPDIR)/httpserver.options
+HTTPSERVER_PACKAGES_FILE = $(DOCSTMPDIR)/httpserver.packages
+
+httpserverdocs: $(HTTPSERVER_INDEX_HTML)
+
+# Set relative location to core api document root
+$(HTTPSERVER_INDEX_HTML): GET2DOCSDIR=$(HTTPSERVER2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(HTTPSERVER_OPTIONS_FILE),$(HTTPSERVER_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(HTTPSERVER_OPTIONS_FILE) @$(HTTPSERVER_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(HTTPSERVER_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(HTTPSERVER_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(HTTPSERVER_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(HTTPSERVER_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(HTTPSERVER_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(HTTPSERVER2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
-.PHONY: tracingdocs
-tracingdocs:
- @# ######## api-tracing ############################
- $(RM) -r $(TRACING_DOCDIR)
- $(MKDIR) -p $(TRACING_DOCDIR)
- $(JAVADOC_CMD) $(TRACING_JAVADOCFLAGS) \
- $(TRACING_PKGS)
+# Create a file with the package names in it
+$(HTTPSERVER_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(HTTPSERVER_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(HTTPSERVER_PKGS))
+
+#############################################################
+#
+# mgmtdocs
+#
+
+ALL_OTHER_TARGETS += mgmtdocs
+
+MGMT_DOCDIR := $(JRE_API_DOCSDIR)/management/extension
+MGMT2COREAPI := ../../$(JDKJRE2COREAPI)
+JVM_MIB_NAME := JVM-MANAGEMENT-MIB.mib
+JVM_MIB_SRC := $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
+MGMT_DOCTITLE := Monitoring and Management Interface for the Java$(TRADEMARK) Platform
+MGMT_WINDOWTITLE := Monitoring and Management Interface for the Java Platform
+MGMT_HEADER := <strong>Monitoring and Management Interface for the Java Platform</strong>
+MGMT_BOTTOM := $(call CommonBottom,$(MGMT_FIRST_COPYRIGHT_YEAR))
+MGMT_OVERVIEW := $(SHARE_SRC)/classes/com/sun/management/mgmt-overview.html
+# MGMT_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+MGMT_INDEX_FILE = $(MGMT_DOCDIR)/index.html
+MGMT_OPTIONS_FILE = $(DOCSTMPDIR)/mgmt.options
+MGMT_PACKAGES_FILE = $(DOCSTMPDIR)/mgmt.packages
+
+mgmtdocs: $(MGMT_INDEX_FILE)
+
+# Set relative location to core api document root
+$(MGMT_INDEX_FILE): GET2DOCSDIR=$(MGMT2COREAPI)/..
-.PHONY: httpserverdocs
-httpserverdocs:
- @# ######## api-httpserver #######################
- $(RM) -r $(HTTPSERVER_DOCDIR)
- $(MKDIR) -p $(HTTPSERVER_DOCDIR)
- $(JAVADOC_CMD) $(HTTPSERVER_JAVADOCFLAGS) \
- $(HTTPSERVER_PKGS)
+# Run javadoc if the index file is out of date or missing
+$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE)
+ $(prep-javadoc)
+ @if [ -f $(JVM_MIB_SRC) ] ; then \
+ $(ECHO) "$(CP) $(JVM_MIB_SRC) $(@D)/.."; \
+ $(CP) $(JVM_MIB_SRC) $(@D)/.. ; \
+ else \
+ $(ECHO) "WARNING: File $(JVM_MIB_NAME) not available."; \
+ fi
+ $(call JavadocSummary,$(MGMT_OPTIONS_FILE),$(MGMT_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(MGMT_OPTIONS_FILE) @$(MGMT_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(MGMT_OPTIONS_FILE): $(MGMT_OVERVIEW)
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-overview $(MGMT_OVERVIEW)" ; \
+ $(ECHO) "-doctitle '$(MGMT_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(MGMT_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+ $(ECHO) "-header '$(MGMT_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(MGMT_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(MGMT2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(MGMT_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MGMT_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(MGMT_PKGS))
+
+#############################################################
+#
+# attachdocs
+#
+
+ALL_OTHER_TARGETS += attachdocs
-.PHONY: sctpdocs
-sctpdocs:
- @# ######## api-sctp #######################
- $(RM) -r $(SCTPAPI_DOCDIR)
- $(MKDIR) -p $(SCTPAPI_DOCDIR)
- $(JAVADOC_CMD) $(SCTPAPI_JAVADOCFLAGS) \
- $(SCTPAPI_PKGS)
+ATTACH_DOCDIR := $(JDK_API_DOCSDIR)/attach/spec
+ATTACH2COREAPI := ../../$(JDKJRE2COREAPI)
+ATTACH_DOCTITLE := Attach API
+ATTACH_WINDOWTITLE := Attach API
+ATTACH_HEADER := <strong>Attach API</strong>
+ATTACH_BOTTOM := $(call CommonBottom,$(ATTACH_FIRST_COPYRIGHT_YEAR))
+# ATTACH_PKGS is located in NON_CORE_PKGS.gmk
+
+ATTACH_INDEX_HTML = $(ATTACH_DOCDIR)/index.html
+ATTACH_OPTIONS_FILE = $(DOCSTMPDIR)/attach.options
+ATTACH_PACKAGES_FILE = $(DOCSTMPDIR)/attach.packages
+
+attachdocs: $(ATTACH_INDEX_HTML)
+
+# Set relative location to core api document root
+$(ATTACH_INDEX_HTML): GET2DOCSDIR=$(ATTACH2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(ATTACH_OPTIONS_FILE),$(ATTACH_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(ATTACH_OPTIONS_FILE) @$(ATTACH_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(ATTACH_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(ATTACH_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(ATTACH_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(ATTACH_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(ATTACH_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(ATTACH2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(ATTACH_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(ATTACH_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(ATTACH_PKGS))
+
+#############################################################
+#
+# jconsoledocs
+#
+
+ALL_OTHER_TARGETS += jconsoledocs
+
+JCONSOLE_DOCDIR := $(JDK_API_DOCSDIR)/jconsole/spec
+JCONSOLE2COREAPI := ../../$(JDKJRE2COREAPI)
+JCONSOLE_DOCTITLE := JConsole API
+JCONSOLE_WINDOWTITLE := JConsole API
+JCONSOLE_HEADER := <strong>JConsole API</strong>
+JCONSOLE_BOTTOM := $(call CommonBottom,$(JCONSOLE_FIRST_COPYRIGHT_YEAR))
+# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk
+
+JCONSOLE_INDEX_HTML = $(JCONSOLE_DOCDIR)/index.html
+JCONSOLE_OPTIONS_FILE = $(DOCSTMPDIR)/jconsole.options
+JCONSOLE_PACKAGES_FILE = $(DOCSTMPDIR)/jconsole.packages
+
+jconsoledocs: $(JCONSOLE_INDEX_HTML)
-.PHONY: mgmtdocs
-mgmtdocs: $(COPY-MIB-TARGET)
- @# ######## api-management ############################
- $(RM) -r $(MGMT_EXT_DIR)
- $(MKDIR) -p $(MGMT_EXT_DIR)
- $(JAVADOC_CMD) $(MGMT_JAVADOCFLAGS) \
- $(MGMT_PKGS)
+# Set relative location to core api document root
+$(JCONSOLE_INDEX_HTML): GET2DOCSDIR=$(JCONSOLE2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(JCONSOLE_OPTIONS_FILE),$(JCONSOLE_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(JCONSOLE_OPTIONS_FILE) @$(JCONSOLE_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JCONSOLE_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(JCONSOLE_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(JCONSOLE_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(JCONSOLE_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(JCONSOLE_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(JCONSOLE2COREAPI) $(COREAPI_DOCSDIR)/"; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(JCONSOLE_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JCONSOLE_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(JCONSOLE_PKGS))
-copy-mib:
- @# ######## copy-snmp-mib ############################
- $(RM) $(MGMT_DOCDIR)/$(JVM_MIB_NAME)
- $(MKDIR) -p $(MGMT_DOCDIR)
- $(CP) $(JVM_MIB_SRC) $(MGMT_DOCDIR)
+#############################################################
+#
+# treeapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+ ALL_OTHER_TARGETS += treeapidocs
+endif
+
+TREEAPI_DOCDIR := $(JDK_API_DOCSDIR)/javac/tree
+TREEAPI2COREAPI := ../../$(JDKJRE2COREAPI)
+TREEAPI_DOCTITLE := Compiler Tree API
+TREEAPI_WINDOWTITLE := Compiler Tree API
+TREEAPI_HEADER := <strong>Compiler Tree API</strong>
+TREEAPI_BOTTOM := $(call CommonBottom,$(TREEAPI_FIRST_COPYRIGHT_YEAR))
+TREEAPI_GROUPNAME := Packages
+TREEAPI_REGEXP := com.sun.source.*
+# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+TREEAPI_INDEX_HTML = $(TREEAPI_DOCDIR)/index.html
+TREEAPI_OPTIONS_FILE = $(DOCSTMPDIR)/treeapi.options
+TREEAPI_PACKAGES_FILE = $(DOCSTMPDIR)/treeapi.packages
+
+treeapidocs: $(TREEAPI_INDEX_HTML)
+
+# Set relative location to core api document root
+$(TREEAPI_INDEX_HTML): GET2DOCSDIR=$(TREEAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(TREEAPI_OPTIONS_FILE),$(TREEAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(TREEAPI_OPTIONS_FILE) @$(TREEAPI_PACKAGES_FILE)
-.PHONY: attachdocs
-attachdocs:
- @# ######## api-attach ############################
- $(RM) -r $(ATTACH_DOCDIR)
- $(MKDIR) -p $(ATTACH_DOCDIR)
- $(JAVADOC_CMD) $(ATTACH_JAVADOCFLAGS) \
- $(ATTACH_PKGS)
+# Create file with javadoc options in it
+$(TREEAPI_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-doctitle '$(TREEAPI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(TREEAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(TREEAPI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(TREEAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP)" ; \
+ $(ECHO) "-linkoffline $(TREEAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(TREEAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TREEAPI_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(TREEAPI_PKGS))
+
+#############################################################
+#
+# sctpdocs
+#
+
+ALL_OTHER_TARGETS += sctpdocs
+
+SCTPAPI_DOCDIR := $(JRE_API_DOCSDIR)/nio/sctp/spec
+SCTPAPI2COREAPI := ../../../$(JDKJRE2COREAPI)
+SCTPAPI_DOCTITLE := SCTP API
+SCTPAPI_WINDOWTITLE := SCTP API
+SCTPAPI_HEADER := <strong>SCTP API</strong>
+SCTPAPI_BOTTOM := $(call CommonBottom,$(SCTPAPI_FIRST_COPYRIGHT_YEAR))
+# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+SCTPAPI_INDEX_HTML = $(SCTPAPI_DOCDIR)/index.html
+SCTPAPI_OPTIONS_FILE = $(DOCSTMPDIR)/sctp.options
+SCTPAPI_PACKAGES_FILE = $(DOCSTMPDIR)/sctp.packages
+
+sctpdocs: $(SCTPAPI_INDEX_HTML)
+
+# Set relative location to core api document root
+$(SCTSCTSCTP: GET2DOCSDIR=$(SCTPAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(SCTPAPI_OPTIONS_FILE),$(SCTPAPI_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(SCTPAPI_OPTIONS_FILE) @$(SCTPAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(SCTPAPI_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(SCTPAPI_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(SCTPAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(SCTPAPI_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(SCTPAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(SCTPAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(SCTPAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SCTPAPI_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(SCTPAPI_PKGS))
+
+#############################################################
+#
+# tracingdocs
+#
-.PHONY: jconsoledocs
-jconsoledocs:
- @# ######## api-jconsole ############################
- $(RM) -r $(JCONSOLE_DOCDIR)
- $(MKDIR) -p $(JCONSOLE_DOCDIR)
- $(JAVADOC_CMD) $(JCONSOLE_JAVADOCFLAGS) \
- $(JCONSOLE_PKGS)
+ALL_OTHER_TARGETS += tracingdocs
+
+TRACING_DOCDIR := $(JRE_API_DOCSDIR)/tracing
+TRACING2COREAPI := ../$(JDKJRE2COREAPI)
+TRACING_DOCTITLE := Java$(TRADEMARK) Platform Tracing
+TRACING_WINDOWTITLE := Platform Tracing
+TRACING_HEADER := <strong>Platform Tracing</strong>
+TRACING_BOTTOM := $(call CommonBottom,$(TRACING_FIRST_COPYRIGHT_YEAR))
+# TRACING_PKGS is located in NON_CORE_PKGS.gmk
+
+TRACING_INDEX_HTML = $(TRACING_DOCDIR)/index.html
+TRACING_OPTIONS_FILE = $(DOCSTMPDIR)/tracing.options
+TRACING_PACKAGES_FILE = $(DOCSTMPDIR)/tracing.packages
+
+tracingdocs: $(TRACING_INDEX_HTML)
+
+# Set relative location to core api document root
+$(TRACING_INDEX_HTML): GET2DOCSDIR=$(TRACING2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TRACING_INDEX_HTML): $(TRACING_OPTIONS_FILE) $(TRACING_PACKAGES_FILE)
+ $(prep-javadoc)
+ $(call JavadocSummary,$(TRACING_OPTIONS_FILE),$(TRACING_PACKAGES_FILE))
+ $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+ @$(TRACING_OPTIONS_FILE) @$(TRACING_PACKAGES_FILE)
-.PHONY: treeapidocs
-treeapidocs:
- @# ######## tree api for javac ##################
- $(RM) -r $(TREEAPI_DESTDIR)
- $(MKDIR) -p $(TREEAPI_DESTDIR)
- $(JAVADOC_CMD) $(TREEAPI_JAVADOCFLAGS) \
- -d $(TREEAPI_DESTDIR) \
- -sourcepath $(RELEASEDOCS_SRCPATH) \
- $(TREEAPI_LINKOPT) \
- $(TREEAPI_PKGS)
+# Create file with javadoc options in it
+$(TRACING_OPTIONS_FILE):
+ $(prep-target)
+ @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \
+ $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \
+ $(ECHO) "-encoding ascii" ; \
+ $(ECHO) "-nodeprecatedlist" ; \
+ $(ECHO) "-doctitle '$(TRACING_DOCTITLE)'" ; \
+ $(ECHO) "-windowtitle '$(TRACING_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+ $(ECHO) "-header '$(TRACING_HEADER)$(DRAFT_HEADER)'" ; \
+ $(ECHO) "-bottom '$(TRACING_BOTTOM)$(DRAFT_BOTTOM)'" ; \
+ $(ECHO) "-linkoffline $(TRACING2COREAPI) $(COREAPI_DOCSDIR)/" ; \
+ ) >> $@
+
+# Create a file with the package names in it
+$(TRACING_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TRACING_PKGS))
+ $(prep-target)
+ $(call PackageFilter,$(TRACING_PKGS))
+
+#############################################################
+#
+# Get a cache of all the directories
+$(DIRECTORY_CACHE): $(ALL_SOURCE_DIRS)
+ $(prep-target)
+ @for cp in $(ALL_SOURCE_DIRS) ; do \
+ $(ECHO) "$(FIND) $${cp} -type f >> $@"; \
+ $(FIND) $${cp} -type f >> $@; \
+ done
+
+#############################################################
+#release version of core packages ########
+# Maximize performance and ensure that build number & milestone are set.
+
+rel-coredocs: sanitycheckcoredocs
+ $(MAKE) coredocs
+
+rel-docs: rel-coredocs $(ALL_OTHER_TARGETS)
+#
+# end of production targets
+
+otherdocs: $(ALL_OTHER_TARGETS)
+
+clean:
+ $(RM) -r $(DOCSDIR) $(DOCSTMPDIR)
+
+#############################################################
# DEBUG TARGET
# List the values defined in the makefile hierarchy, to make sure everything
# is set properly, and to help identify values we can use instead of making new ones.
@@ -714,9 +1211,14 @@
# * BUILD_NUMBER defaults to b00 if not set on command line with BUILD_NUMBER=<value>
# * MILESTONE defaults to internal unless set to beta, rc, or fcs on command line
#
-.PHONY: echovalues
+
echovalues:
@$(ECHO) ""
+ @$(ECHO) --------------Imports---------------------------
+ @$(ECHO) "IMPORT_PACKAGES = $(IMPORT_PACKAGES)"
+ @$(ECHO) "IMPORT_PACKAGE_FILTER = $(IMPORT_PACKAGE_FILTER)"
+ @$(ECHO) --------------Imports---------------------------
+ @$(ECHO) ""
@$(ECHO) --------------Shared---------------------------
@$(ECHO) BUILD_NUMBER = $(BUILD_NUMBER)
@$(ECHO) FULL_VERSION = $(FULL_VERSION)
@@ -736,11 +1238,16 @@
@$(ECHO) --------------Shared---------------------------
@$(ECHO) ""
@$(ECHO) --------------common/Defs---------------------------
- @$(ECHO) "RELEASEDOCS_SRCPATH"
+ @$(ECHO) "RELEASEDOCS_SOURCEPATH"
@$(ECHO) " SHARE_SRC/classes: $(SHARE_SRC)/classes"
@$(ECHO) " PLATFORM_SRC/classes: $(PLATFORM_SRC)/classes"
@$(ECHO) " GENSRCDIR: $(GENSRCDIR)"
+ @$(ECHO) " SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub"
@$(ECHO) " IMPORTSRCDIR: $(IMPORTSRCDIR)"
- @$(ECHO) " SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub"
@$(ECHO) --------------common/Defs---------------------------
@$(ECHO) ""
+
+#############################################################
+.PHONY: all docs coredocs rel-docs echovalues otherdocs rel-coredocs \
+ sanitycheckcoredocs $(ALL_OTHER_TARGETS)
+
--- a/jdk/make/java/java/FILES_java.gmk Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/java/java/FILES_java.gmk Wed Jul 05 17:18:01 2017 +0200
@@ -30,6 +30,7 @@
#
JAVA_JAVA_java = \
java/lang/Object.java \
+ java/lang/AutoCloseable.java \
java/lang/Class.java \
java/lang/Thread.java \
java/lang/Character.java \
--- a/jdk/make/java/security/Makefile Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/java/security/Makefile Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 2010 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,11 @@
CACERTS_SRC = $(CACERTS_FILE)
CACERTS_BUILD = $(LIBDIR)/security/cacerts
+ifndef OPENJDK
+ BLACKLIST_SRC = $(CLOSED_SHARE_SRC)/lib/security/blacklist
+ BLACKLIST_BUILD = $(LIBDIR)/security/blacklist
+endif
+
FILES_class = $(FILES_java:%.java=$(CLASSBINDIR)/%.class)
#
@@ -69,7 +74,11 @@
#
include $(BUILDDIR)/common/Rules.gmk
+ifdef OPENJDK
build: properties policy cacerts
+else
+build: properties policy cacerts blacklist
+endif
install: all
@@ -79,6 +88,8 @@
cacerts: classes $(CACERTS_BUILD)
+blacklist: classes $(BLACKLIST_BUILD)
+
$(PROPS_BUILD): $(PROPS_SRC)
$(install-file)
@@ -88,9 +99,12 @@
$(CACERTS_BUILD): $(CACERTS_SRC)
$(install-file)
+$(BLACKLIST_BUILD): $(BLACKLIST_SRC)
+ $(install-file)
+
clean clobber:: .delete.classlist
$(RM) -r $(CLASSBINDIR)/java/security
- $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD)
+ $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD)
# Additional Rule for building sun.security.util
$(CLASSBINDIR)/%.class: $(SHARE_SRC)/sun/%.java
--- a/jdk/make/mkdemo/Makefile Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/mkdemo/Makefile Wed Jul 05 17:18:01 2017 +0200
@@ -46,11 +46,11 @@
$(RM) -r $(DEMODIR)/nbproject
$(MKDIR) -p $(DEMODIR)
( $(CD) $(SHARE_SRC)/demo && $(TAR) -cf - \
- `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
+ `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
( $(CD) $(DEMODIR) && $(TAR) -xf - )
ifndef OPENJDK
( $(CD) $(CLOSED_SHARE_SRC)/demo && $(TAR) -cf - \
- `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
+ `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
( $(CD) $(DEMODIR) && $(TAR) -xf - )
endif
--- a/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java Wed Jul 05 17:18:01 2017 +0200
@@ -28,7 +28,6 @@
* combine with an argument list of files and directories, and
* write a list of items to be included in a jar file.
*/
-
package build.tools.jarreorder;
import java.io.BufferedReader;
@@ -36,74 +35,68 @@
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.HashSet;
-import java.util.Vector;
import java.io.PrintStream;
import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
public class JarReorder {
// To deal with output
- private static PrintStream out;
+ private PrintStream out;
- private final static boolean useTopDir = false;
-
- private static void usage() {
+ private void usage() {
String help;
help =
- "Usage: jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n"
- + " order_list is a file containing names of files to load\n"
- + " in order at the end of a jar file.\n"
- + " exclude_list is a file containing names of files/directories\n"
- + " NOT to be included in a jar file.\n";
- if (useTopDir)
- help +=
- " top_dir is the top of the directory structure to be searched;\n"
- + " the contents of the lists and remaining arguments are\n"
- + " relative to this.\n";
- help +=
- "\n"
- + "The order_list or exclude_list may be replaced by a \"_\" if no\n"
- + "data is to be provided.\n"
- + "\n"
- + " The remaining arguments are files or directories to be included\n"
- + " in a jar file, from which will be excluded thse entries which\n"
- + " appear in the exclude list.\n";
+ "Usage: jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n"
+ + " order_list is a file containing names of files to load\n"
+ + " in order at the end of a jar file unless\n"
+ + " excluded in the exclude list.\n"
+ + " exclude_list is a file containing names of files/directories\n"
+ + " NOT to be included in a jar file.\n"
+ + "\n"
+ + "The order_list or exclude_list may be replaced by a \"-\" if no\n"
+ + "data is to be provided.\n"
+ + "\n"
+ + " The remaining arguments are files or directories to be included\n"
+ + " in a jar file, from which will be excluded those entries which\n"
+ + " appear in the exclude list.\n";
System.err.println(help);
- System.exit(1);
}
/*
- * Create a list of files to be included in a jar file, such that the
- * some the files will appear in a specific order, and allowing certain
+ * Create the file list to be included in a jar file, such that the
+ * list will appear in a specific order, and allowing certain
* files and directories to be excluded.
*
- * Command line arguments are
+ * Command path arguments are
* - optional -o outputfile
- * - name of a file containing a list of files to be included in a jar file.
- * - name of a file containing a list of files (or directories) to be
+ * - name of a file containing a set of files to be included in a jar file.
+ * - name of a file containing a set of files (or directories) to be
* excluded from the jar file.
* - names of files or directories to be searched for files to include
* in the jar file.
*/
public static void main(String[] args) {
+ JarReorder jr = new JarReorder();
+ jr.run(args);
+ }
- HashMap filesExcluded = new HashMap();
- Vector filesIncluded = new Vector();
- int fileArgs;
- String topDirName = "";
+ private void run(String args[]) {
+
int arglen = args.length;
int argpos = 0;
// Look for "-o outputfilename" option
- if ( arglen > 0 ) {
- if ( arglen >= 2 && args[0].equals("-o") ) {
+ if (arglen > 0) {
+ if (arglen >= 2 && args[0].equals("-o")) {
try {
out = new PrintStream(new FileOutputStream(args[1]));
- } catch ( FileNotFoundException e ) {
+ } catch (FileNotFoundException e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace(System.err);
System.exit(1);
@@ -118,128 +111,111 @@
out = System.out;
}
- fileArgs = useTopDir ? 3 : 2;
-
- if (arglen <= fileArgs) {
+ // Should be 2 or more args left
+ if (arglen <= 2) {
usage();
+ System.exit(1);
}
- // Read the ordered list of files to be included in rt.jar.
- // Read the list of files/directories to be excluded from rt.jar.
-
- Vector orderList = readListFromFile(args[argpos], true);
- Vector excludeList = readListFromFile(args[argpos+1], false);
- if (useTopDir) {
- topDirName = args[argpos+2];
- if (!topDirName.endsWith(File.separator))
- topDirName = topDirName + File.separator;
- }
+ // Read the ordered set of files to be included in rt.jar.
+ // Read the set of files/directories to be excluded from rt.jar.
+ String classListFile = args[argpos];
+ String excludeListFile = args[argpos + 1];
+ argpos += 2;
+ arglen -= 2;
- // Copy these lists into filesExcluded so that these files will be excluded
- // from the file list. (The orderList files will be appended later.)
+ // Create 2 lists and a set of processed files
+ List<String> orderList = readListFromFile(classListFile, true);
+ List<String> excludeList = readListFromFile(excludeListFile, false);
+ Set<String> processed = new HashSet<String>();
- for (int i = 0; i < orderList.size(); ++i) {
- String s = (String) orderList.elementAt(i);
- filesExcluded.put(s, s);
- }
- for (int i = 0; i < excludeList.size(); ++i) {
- String s = (String) excludeList.elementAt(i);
- filesExcluded.put(s, s);
- }
+ // Create set of all files and directories excluded, then expand
+ // that list completely
+ Set<String> excludeSet = new HashSet<String>(excludeList);
+ Set<String> allFilesExcluded = expand(null, excludeSet, processed);
+
+ // Indicate all these have been processed, orderList too, kept to end.
+ processed.addAll(orderList);
// The remaining arguments are names of files/directories to be included
// in the jar file.
-
- String[] files = new String[arglen - fileArgs];
- for (int i = fileArgs; i < arglen; ++i) {
- files[i-fileArgs] = args[argpos+i];
- filesExcluded.put(args[argpos+i], args[argpos+i]);
+ Set<String> inputSet = new HashSet<String>();
+ for (int i = 0; i < arglen; ++i) {
+ String name = args[argpos + i];
+ name = cleanPath(new File(name));
+ if ( name != null && name.length() > 0 && !inputSet.contains(name) ) {
+ inputSet.add(name);
+ }
}
- // Expand file/directory list to file list excluding those
- // read from the class list.
+ // Expand file/directory input so we get a complete set (except ordered)
+ // Should be everything not excluded and not in order list.
+ Set<String> allFilesIncluded = expand(null, inputSet, processed);
- if (useTopDir)
- expand(new File(topDirName), files, filesIncluded, filesExcluded, topDirName);
- else
- expand(null, files, filesIncluded, filesExcluded, null);
+ // Create simple sorted list so we can add ordered items at end.
+ List<String> allFiles = new ArrayList<String>(allFilesIncluded);
+ Collections.sort(allFiles);
- // Now add the ordered list to the end of the expanded list.
+ // Now add the ordered set to the end of the list.
// Add in REVERSE ORDER, so that the first element is closest to
// the end (and the index).
-
- HashSet excludeSet = new HashSet(excludeList);
for (int i = orderList.size() - 1; i >= 0; --i) {
- String s = (String) orderList.elementAt(i);
- if (excludeSet.contains(s)) {
- System.err.println("Included file " + s + " is also excluded, skipping.");
- continue;
+ String s = orderList.get(i);
+ if (allFilesExcluded.contains(s)) {
+ System.err.println("Included order file " + s
+ + " is also excluded, skipping.");
+ } else if (new File(s).exists()) {
+ allFiles.add(s);
+ } else {
+ System.err.println("Included order file " + s
+ + " missing, skipping.");
}
- if (new File(topDirName + s).exists())
- filesIncluded.addElement(s);
- else
- System.err.println("Included file "+s+" missing, skipping.");
}
- // Print results.
-
- for (int i = 0; i < filesIncluded.size(); ++i) {
- if (useTopDir) {
- out.print("-C ");
- out.print(topDirName);
- out.print(" ");
- }
- out.println((String)filesIncluded.elementAt(i));
+ // Print final results.
+ for (String str : allFiles) {
+ out.println(str);
}
-
out.flush();
out.close();
}
-
/*
- * Read a file containing a list of files into a Vector.
+ * Read a file containing a list of files and directories into a List.
*/
- private static Vector readListFromFile(String fileName,
- boolean addClassSuffix) {
+ private List<String> readListFromFile(String fileName,
+ boolean addClassSuffix) {
BufferedReader br = null;
- Vector v = new Vector(2000);
-
- if ("-".equals(fileName))
- return v;
-
+ List<String> list = new ArrayList<String>();
+ // If you see "-" for the name, just assume nothing was provided.
+ if ("-".equals(fileName)) {
+ return list;
+ }
try {
br = new BufferedReader(new FileReader(fileName));
-
- // Read the input file a line at a time. # in column 1 is a comment.
-
+ // Read the input file a path at a time. # in column 1 is a comment.
while (true) {
- String line = null;
- line = br.readLine();
-
- if (line == null)
+ String path = br.readLine();
+ if (path == null) {
break;
-
- if (line.length() == 0 ||
- line.charAt(0) == '#')
+ }
+ // Look for comments
+ path = path.trim();
+ if (path.length() == 0
+ || path.charAt(0) == '#') {
continue;
-
- // Convert forward or back slashes to the type expected for
- // the current platform.
-
- if (File.separatorChar == '/')
- line = line.replace('\\', '/');
- else
- line = line.replace('/', '\\');
-
- line = line.trim();
- if (addClassSuffix) {
- if (!line.endsWith(".class")) {
- line = line + ".class";
- }
+ }
+ // Add trailing .class if necessary
+ if (addClassSuffix && !path.endsWith(".class")) {
+ path = path + ".class";
}
- v.addElement(line);
+ // Normalize the path
+ path = cleanPath(new File(path));
+ // Add to list
+ if (path != null && path.length() > 0 && !list.contains(path)) {
+ list.add(path);
+ }
}
br.close();
} catch (FileNotFoundException e) {
@@ -249,68 +225,89 @@
e.printStackTrace();
System.exit(2);
}
- return v;
+ return list;
}
-
/*
- * Expands list of files to process into full list of all files that
+ * Expands inputSet (files or dirs) into full set of all files that
* can be found by recursively descending directories.
+ * @param dir root directory
+ * @param inputSet set of files or dirs to look into
+ * @param processed files or dirs already processed
+ * @return set of files
*/
- private static void expand(File dir, String[] files,
- Vector includedFiles, HashMap excludedFiles,
- String topDirName) {
- if (files == null) {
- return;
+ private Set<String> expand(File dir,
+ Set<String> inputSet,
+ Set<String> processed) {
+ Set<String> includedFiles = new HashSet<String>();
+ if (inputSet.isEmpty()) {
+ return includedFiles;
}
- for (int i = 0; i < files.length; i++) {
- File f = (dir == null) ? new File(files[i])
- : new File(dir, files[i]);
- if (f.isFile()) {
- String filePath = f.getPath();
-
- if (useTopDir) {
- if (filePath.startsWith(topDirName))
- filePath = filePath.substring(topDirName.length());
+ for (String name : inputSet) {
+ // Depending on start location
+ File f = (dir == null) ? new File(name)
+ : new File(dir, name);
+ // Normalized path to use
+ String path = cleanPath(f);
+ if (path != null && path.length() > 0
+ && !processed.contains(path)) {
+ if (f.isFile()) {
+ // Not in the excludeList, add it to both lists
+ includedFiles.add(path);
+ processed.add(path);
+ } else if (f.isDirectory()) {
+ // Add the directory entries
+ String[] dirList = f.list();
+ Set<String> dirInputSet = new HashSet<String>();
+ for (String x : dirList) {
+ dirInputSet.add(x);
+ }
+ // Process all entries in this directory
+ Set<String> subList = expand(f, dirInputSet, processed);
+ includedFiles.addAll(subList);
+ processed.add(path);
}
-
- if (filePath.length() >= 2 &&
- filePath.charAt(0) == '.' &&
- filePath.charAt(1) == File.separatorChar)
- filePath = filePath.substring(2);
-
- if (!excludedFiles.containsKey(filePath)) {
- excludedFiles.put(filePath, filePath);
- includedFiles.addElement(filePath);
- }
- } else if (f.isDirectory()) {
- String dirPath = f.getPath();
- dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
- (dirPath + File.separator);
-
- if (useTopDir) {
- if (dirPath.startsWith(topDirName))
- dirPath = dirPath.substring(topDirName.length());
- }
-
- if (dirPath.length() >= 2 &&
- dirPath.charAt(0) == '.' &&
- dirPath.charAt(1) == File.separatorChar)
- dirPath = dirPath.substring(2);
-
- if (!excludedFiles.containsKey(dirPath)) {
-
- // Sort the directory list so that entries in the jar file
- // are in a repeatable order. The order itself is not particularly
- // important. [File.list() is unpredictable.]
-
- String[] dirList = f.list();
- Arrays.sort(dirList);
- expand(f, dirList, includedFiles, excludedFiles, topDirName);
- }
- } else {
- System.err.println("Error accessing: " + f.getPath());
}
}
+ return includedFiles;
}
+
+ private String cleanPath(File f) {
+ String path = f.getPath();
+ if (f.isFile()) {
+ path = cleanFilePath(path);
+ } else if (f.isDirectory()) {
+ path = cleanDirPath(path);
+ } else {
+ System.err.println("WARNING: Path does not exist as file or directory: " + path);
+ path = null;
+ }
+ return path;
+ }
+
+ private String cleanFilePath(String path) {
+ // Remove leading and trailing whitespace
+ path = path.trim();
+ // Make all / and \ chars one
+ if (File.separatorChar == '/') {
+ path = path.replace('\\', '/');
+ } else {
+ path = path.replace('/', '\\');
+ }
+ // Remove leading ./
+ if (path.startsWith("." + File.separator)) {
+ path = path.substring(2);
+ }
+ return path;
+ }
+
+ private String cleanDirPath(String path) {
+ path = cleanFilePath(path);
+ // Make sure it ends with a file separator
+ if (!path.endsWith(File.separator)) {
+ path = path + File.separator;
+ }
+ return path;
+ }
+
}
--- a/jdk/src/share/bin/emessages.h Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/bin/emessages.h Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
#define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
#define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR
-#define JVM_ERROR3 "Error: SPARC V8 processor detected; Server compiler requires V9 or better.\nUse Client compiler on V8 processors.\nCould not create the Java virtual machine."
+#define JVM_ERROR3 "Error: SPARC V8 processor detected; Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1
#define JAR_ERROR1 "Error: Failed to load Main-Class manifest attribute from\n%s\n%s"
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
@@ -69,7 +69,8 @@
#define CFG_ERROR5 "Error: Could not determine application home."
#define CFG_ERROR6 "Error: could not open `%s'"
#define CFG_ERROR7 "Error: no known VMs. (check for corrupt jvm.cfg file)"
-#define CFG_ERROR8 "Error: no `%s' JVM at `%s'."
+#define CFG_ERROR8 "Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components."
+#define CFG_ERROR9 "Error: could not determine JVM type."
#define SPC_ERROR1 "Error: Syntax error in version specification \"%s\""
--- a/jdk/src/share/bin/java.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/bin/java.c Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -192,8 +192,8 @@
int ret;
InvocationFunctions ifn;
jlong start, end;
- char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
- char ** original_argv = argv;
+ char jvmpath[MAXPATHLEN];
+ char jrepath[MAXPATHLEN];
_fVersion = fullversion;
_dVersion = dotversion;
@@ -225,14 +225,17 @@
*/
SelectVersion(argc, argv, &main_class);
- /* copy original argv */
- JLI_TraceLauncher("Command line Args:\n");
- original_argv = (JLI_CopyArgs(argc, (const char**)argv));
+ if (JLI_IsTraceLauncher()) {
+ int i;
+ printf("Command line args:\n");
+ for (i = 0; i < argc ; i++) {
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
+ }
CreateExecutionEnvironment(&argc, &argv,
jrepath, sizeof(jrepath),
- jvmpath, sizeof(jvmpath),
- original_argv);
+ jvmpath, sizeof(jvmpath));
ifn.CreateJavaVM = 0;
ifn.GetDefaultJavaVMInitArgs = 0;
@@ -301,22 +304,43 @@
return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);
}
+/*
+ * Always detach the main thread so that it appears to have ended when
+ * the application's main method exits. This will invoke the
+ * uncaught exception handler machinery if main threw an
+ * exception. An uncaught exception handler cannot change the
+ * launcher's return code except by calling System.exit.
+ *
+ * Wait for all non-daemon threads to end, then destroy the VM.
+ * This will actually create a trivial new Java waiter thread
+ * named "DestroyJavaVM", but this will be seen as a different
+ * thread from the one that executed main, even though they are
+ * the same C thread. This allows mainThread.join() and
+ * mainThread.isAlive() to work as expected.
+ */
+#define LEAVE() \
+ if ((*vm)->DetachCurrentThread(vm) != 0) { \
+ JLI_ReportErrorMessage(JVM_ERROR2); \
+ ret = 1; \
+ } \
+ (*vm)->DestroyJavaVM(vm); \
+ return ret \
#define CHECK_EXCEPTION_NULL_LEAVE(e) \
if ((*env)->ExceptionOccurred(env)) { \
JLI_ReportExceptionDescription(env); \
- goto leave; \
+ LEAVE(); \
} \
if ((e) == NULL) { \
JLI_ReportErrorMessage(JNI_ERROR); \
- goto leave; \
+ LEAVE(); \
}
#define CHECK_EXCEPTION_LEAVE(rv) \
if ((*env)->ExceptionOccurred(env)) { \
JLI_ReportExceptionDescription(env); \
ret = (rv); \
- goto leave; \
+ LEAVE(); \
}
int JNICALL
@@ -349,8 +373,7 @@
PrintJavaVersion(env, showVersion);
CHECK_EXCEPTION_LEAVE(0);
if (printVersion) {
- ret = 0;
- goto leave;
+ LEAVE();
}
}
@@ -358,7 +381,7 @@
if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
PrintUsage(env, printXUsage);
CHECK_EXCEPTION_LEAVE(1);
- goto leave;
+ LEAVE();
}
FreeKnownVMs(); /* after last possible PrintUsage() */
@@ -430,30 +453,7 @@
* System.exit) will be non-zero if main threw an exception.
*/
ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
-
-leave:
- /*
- * Always detach the main thread so that it appears to have ended when
- * the application's main method exits. This will invoke the
- * uncaught exception handler machinery if main threw an
- * exception. An uncaught exception handler cannot change the
- * launcher's return code except by calling System.exit.
- */
- if ((*vm)->DetachCurrentThread(vm) != 0) {
- JLI_ReportErrorMessage(JVM_ERROR2);
- ret = 1;
- }
- /*
- * Wait for all non-daemon threads to end, then destroy the VM.
- * This will actually create a trivial new Java waiter thread
- * named "DestroyJavaVM", but this will be seen as a different
- * thread from the one that executed main, even though they are
- * the same C thread. This allows mainThread.join() and
- * mainThread.isAlive() to work as expected.
- */
- (*vm)->DestroyJavaVM(vm);
-
- return ret;
+ LEAVE();
}
/*
@@ -1076,15 +1076,17 @@
if (--argc >= 0) {
if (jarflag) {
*pjarfile = *argv++;
- *pclassname = 0;
+ *pclassname = NULL;
} else {
- *pjarfile = 0;
+ *pjarfile = NULL;
*pclassname = *argv++;
}
*pargc = argc;
*pargv = argv;
}
-
+ if (*pjarfile == NULL && *pclassname == NULL) {
+ *pret = 1;
+ }
return JNI_TRUE;
}
--- a/jdk/src/share/bin/java.h Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/bin/java.h Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,13 +114,19 @@
#define GetArch() GetArchPath(CURRENT_DATA_MODEL)
-void CreateExecutionEnvironment(int *_argc,
- char ***_argv,
- char jrepath[],
- jint so_jrepath,
- char jvmpath[],
- jint so_jvmpath,
- char **original_argv);
+/*
+ * Different platforms will implement this, here
+ * pargc is a pointer to the original argc,
+ * pargv is a pointer to the original argv,
+ * jrepath is an accessible path to the jre as determined by the call
+ * so_jrepath is the length of the buffer jrepath
+ * jvmpath is an accessible path to the jvm as determined by the call
+ * so_jvmpath is the length of the buffer jvmpath
+ */
+void CreateExecutionEnvironment(int *argc, char ***argv,
+ char *jrepath, jint so_jrepath,
+ char *jvmpath, jint so_jvmpath);
+
/* Reports an error message to stderr or a window as appropriate. */
void JLI_ReportErrorMessage(const char * message, ...);
--- a/jdk/src/share/bin/jli_util.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/bin/jli_util.c Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -85,23 +85,6 @@
}
/*
- * Makes a copy of arguments
- */
-char**
-JLI_CopyArgs(int argc, const char **iargv)
-{
- int i;
- char** oargv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
- for (i = 0 ; i < argc+1 ; i++) {
- oargv[i] = (iargv[i] == NULL) ? NULL : JLI_StringDup(iargv[i]);
- if (iargv[i] != NULL && JLI_IsTraceLauncher() == JNI_TRUE) {
- printf("\targv[%d] = '%s'\n",i,iargv[i]);
- }
- }
- return oargv;
-}
-
-/*
* debug helpers we use
*/
static jboolean _launcher_debug = JNI_FALSE;
--- a/jdk/src/share/bin/jli_util.h Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/bin/jli_util.h Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
void *JLI_MemRealloc(void *ptr, size_t size);
char *JLI_StringDup(const char *s1);
void JLI_MemFree(void *ptr);
-char **JLI_CopyArgs(int argc, const char **iargv);
int JLI_StrCCmp(const char *s1, const char* s2);
@@ -56,10 +55,12 @@
#include <io.h>
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
+#define JLI_Snprintf _snprintf
#else
#include <unistd.h>
#define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3))
+#define JLI_Snprintf snprintf
#endif /* _WIN32 */
/*
--- a/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
private final Class<? extends T> type;
private final boolean allow;
private final String suffix;
- private String[] packages;
+ private volatile String[] packages;
InstanceFinder(Class<? extends T> type, boolean allow, String suffix, String... packages) {
this.type = type;
@@ -49,9 +49,7 @@
}
public String[] getPackages() {
- return (this.packages.length > 0)
- ? this.packages.clone()
- : this.packages;
+ return this.packages.clone();
}
public void setPackages(String... packages) {
--- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -118,7 +118,7 @@
* @throws NoSuchMethodException if method is not accessible or is not found
* in specified superclass or interface
*/
- private static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
+ public static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
Class<?> type = method.getDeclaringClass();
if (Modifier.isPublic(type.getModifiers())) {
return method;
--- a/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,17 +47,22 @@
}
public void register(Class<?> type, PersistenceDelegate delegate) {
- if (delegate != null) {
- this.registry.put(type, delegate);
- }
- else {
- this.registry.remove(type);
+ synchronized (this.registry) {
+ if (delegate != null) {
+ this.registry.put(type, delegate);
+ }
+ else {
+ this.registry.remove(type);
+ }
}
}
@Override
public PersistenceDelegate find(Class<?> type) {
- PersistenceDelegate delegate = this.registry.get(type);
+ PersistenceDelegate delegate;
+ synchronized (this.registry) {
+ delegate = this.registry.get(type);
+ }
return (delegate != null) ? delegate : super.find(type);
}
}
--- a/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,12 +64,18 @@
}
public void register(Class<?> type, Class<?> editor) {
- this.registry.put(type, editor);
+ synchronized (this.registry) {
+ this.registry.put(type, editor);
+ }
}
@Override
public PropertyEditor find(Class<?> type) {
- PropertyEditor editor = instantiate(this.registry.get(type), null);
+ Class<?> predefined;
+ synchronized (this.registry) {
+ predefined = this.registry.get(type);
+ }
+ PropertyEditor editor = instantiate(predefined, null);
if (editor == null) {
editor = super.find(type);
if ((editor == null) && (null != type.getEnumConstants())) {
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Wed Jul 05 17:18:01 2017 +0200
@@ -1440,10 +1440,6 @@
}
}
- public Insets getBorderInsets(Component c) {
- return getBorderInsets(c, null);
- }
-
public Insets getBorderInsets(Component c, Insets i) {
SynthContext context = getContext(c);
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -271,7 +271,9 @@
}
public void uninstallUI(JComponent c) {
- getFileChooser().removeAll();
+ c.removePropertyChangeListener(filterComboBoxModel);
+ approveButton.removeActionListener(getApproveSelectionAction());
+ filenameTextField.removeActionListener(getApproveSelectionAction());
super.uninstallUI(c);
}
@@ -515,6 +517,7 @@
public void uninstallComponents(JFileChooser fc) {
fc.removeAll();
+ bottomPanel = null;
if (filterComboBoxModel != null) {
fc.removePropertyChangeListener(filterComboBoxModel);
}
--- a/jdk/src/share/classes/java/awt/EventDispatchThread.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java Wed Jul 05 17:18:01 2017 +0200
@@ -61,85 +61,43 @@
* @since 1.1
*/
class EventDispatchThread extends Thread {
+
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
private EventQueue theQueue;
private boolean doDispatch = true;
+ private boolean threadDeathCaught = false;
+
private static final int ANY_EVENT = -1;
private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
- // used in handleException
- private int modalFiltersCount = 0;
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
super(group, name);
- theQueue = queue;
+ setEventQueue(queue);
}
- void stopDispatchingImpl(boolean wait) {
- // Note: We stop dispatching via a flag rather than using
- // Thread.interrupt() because we can't guarantee that the wait()
- // we interrupt will be EventQueue.getNextEvent()'s. -fredx 8-11-98
-
- StopDispatchEvent stopEvent = new StopDispatchEvent();
-
- // wait for the dispatcher to complete
- if (Thread.currentThread() != this) {
-
- // fix 4122683, 4128923
- // Post an empty event to ensure getNextEvent is unblocked
- //
- // We have to use postEventPrivate instead of postEvent because
- // EventQueue.pop calls EventDispatchThread.stopDispatching.
- // Calling SunToolkit.flushPendingEvents in this case could
- // lead to deadlock.
- theQueue.postEventPrivate(stopEvent);
-
- if (wait) {
- try {
- join();
- } catch(InterruptedException e) {
- }
- }
- } else {
- stopEvent.dispatch();
- }
-
- theQueue.detachDispatchThread(this, false);
- }
-
+ /*
+ * Must be called on EDT only, that's why no synchronization
+ */
public void stopDispatching() {
- stopDispatchingImpl(true);
- }
-
- public void stopDispatchingLater() {
- stopDispatchingImpl(false);
- }
-
- class StopDispatchEvent extends AWTEvent implements ActiveEvent {
- /*
- * serialVersionUID
- */
- static final long serialVersionUID = -3692158172100730735L;
-
- public StopDispatchEvent() {
- super(EventDispatchThread.this,0);
- }
-
- public void dispatch() {
- doDispatch = false;
- }
+ doDispatch = false;
}
public void run() {
- try {
- pumpEvents(new Conditional() {
- public boolean evaluate() {
- return true;
+ while (true) {
+ try {
+ pumpEvents(new Conditional() {
+ public boolean evaluate() {
+ return true;
+ }
+ });
+ } finally {
+ EventQueue eq = getEventQueue();
+ if (eq.detachDispatchThread(this) || threadDeathCaught) {
+ break;
}
- });
- } finally {
- theQueue.detachDispatchThread(this, true);
+ }
}
}
@@ -190,7 +148,6 @@
}
}
eventFilters.add(k, filter);
- modalFiltersCount++;
} else {
eventFilters.add(filter);
}
@@ -200,28 +157,25 @@
void removeEventFilter(EventFilter filter) {
synchronized (eventFilters) {
- if (eventFilters.contains(filter)) {
- if (filter instanceof ModalEventFilter) {
- modalFiltersCount--;
- }
- eventFilters.remove(filter);
- }
+ eventFilters.remove(filter);
}
}
boolean pumpOneEventForFilters(int id) {
+ AWTEvent event = null;
+ boolean eventOK = false;
try {
- AWTEvent event;
- boolean eventOK;
- EventQueueDelegate.Delegate delegate =
- EventQueueDelegate.getDelegate();
+ EventQueue eq = null;
+ EventQueueDelegate.Delegate delegate = null;
do {
+ // EventQueue may change during the dispatching
+ eq = getEventQueue();
+ delegate = EventQueueDelegate.getDelegate();
+
if (delegate != null && id == ANY_EVENT) {
- event = delegate.getNextEvent(theQueue);
+ event = delegate.getNextEvent(eq);
} else {
- event = (id == ANY_EVENT)
- ? theQueue.getNextEvent()
- : theQueue.getNextEvent(id);
+ event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
}
eventOK = true;
@@ -252,13 +206,15 @@
if (delegate != null) {
handle = delegate.beforeDispatch(event);
}
- theQueue.dispatchEvent(event);
+ eq.dispatchEvent(event);
if (delegate != null) {
delegate.afterDispatch(event, handle);
}
+
return true;
}
catch (ThreadDeath death) {
+ threadDeathCaught = true;
return false;
}
@@ -267,12 +223,10 @@
// Threads in the AppContext
}
- // Can get and throw only unchecked exceptions
- catch (RuntimeException e) {
- processException(e);
- } catch (Error e) {
+ catch (Throwable e) {
processException(e);
}
+
return true;
}
@@ -281,14 +235,14 @@
eventLog.fine("Processing exception: " + e);
}
getUncaughtExceptionHandler().uncaughtException(this, e);
- // don't rethrow the exception to avoid EDT recreation
}
- boolean isDispatching(EventQueue eq) {
- return theQueue.equals(eq);
+ public synchronized EventQueue getEventQueue() {
+ return theQueue;
}
-
- EventQueue getEventQueue() { return theQueue; }
+ public synchronized void setEventQueue(EventQueue eq) {
+ theQueue = eq;
+ }
private static class HierarchyEventFilter implements EventFilter {
private Component modalComponent;
--- a/jdk/src/share/classes/java/awt/EventQueue.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/awt/EventQueue.java Wed Jul 05 17:18:01 2017 +0200
@@ -138,6 +138,15 @@
private final Lock pushPopLock;
private final Condition pushPopCond;
+ /*
+ * Dummy runnable to wake up EDT from getNextEvent() after
+ push/pop is performed
+ */
+ private final static Runnable dummyRunnable = new Runnable() {
+ public void run() {
+ }
+ };
+
private EventDispatchThread dispatchThread;
private final ThreadGroup threadGroup =
@@ -219,22 +228,22 @@
* @param theEvent an instance of <code>java.awt.AWTEvent</code>,
* or a subclass of it
*/
- final void postEventPrivate(AWTEvent theEvent) {
+ private final void postEventPrivate(AWTEvent theEvent) {
theEvent.isPosted = true;
pushPopLock.lock();
try {
- if (dispatchThread == null && nextQueue == null) {
+ if (nextQueue != null) {
+ // Forward the event to the top of EventQueue stack
+ nextQueue.postEventPrivate(theEvent);
+ return;
+ }
+ if (dispatchThread == null) {
if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
return;
} else {
initDispatchThread();
}
}
- if (nextQueue != null) {
- // Forward event to top of EventQueue stack.
- nextQueue.postEventPrivate(theEvent);
- return;
- }
postEvent(theEvent, getPriority(theEvent));
} finally {
pushPopLock.unlock();
@@ -242,29 +251,20 @@
}
private static int getPriority(AWTEvent theEvent) {
- if (theEvent instanceof PeerEvent &&
- (((PeerEvent)theEvent).getFlags() &
- PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0)
- {
- return ULTIMATE_PRIORITY;
+ if (theEvent instanceof PeerEvent) {
+ PeerEvent peerEvent = (PeerEvent)theEvent;
+ if ((peerEvent.getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
+ return ULTIMATE_PRIORITY;
+ }
+ if ((peerEvent.getFlags() & PeerEvent.PRIORITY_EVENT) != 0) {
+ return HIGH_PRIORITY;
+ }
+ if ((peerEvent.getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) {
+ return LOW_PRIORITY;
+ }
}
-
- if (theEvent instanceof PeerEvent &&
- (((PeerEvent)theEvent).getFlags() &
- PeerEvent.PRIORITY_EVENT) != 0)
- {
- return HIGH_PRIORITY;
- }
-
- if (theEvent instanceof PeerEvent &&
- (((PeerEvent)theEvent).getFlags() &
- PeerEvent.LOW_PRIORITY_EVENT) != 0)
- {
- return LOW_PRIORITY;
- }
-
int id = theEvent.getID();
- if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
+ if ((id >= PaintEvent.PAINT_FIRST) && (id <= PaintEvent.PAINT_LAST)) {
return LOW_PRIORITY;
}
return NORM_PRIORITY;
@@ -501,16 +501,9 @@
SunToolkit.flushPendingEvents();
pushPopLock.lock();
try {
- for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
- if (queues[i].head != null) {
- EventQueueItem entry = queues[i].head;
- queues[i].head = entry.next;
- if (entry.next == null) {
- queues[i].tail = null;
- }
- uncacheEQItem(entry);
- return entry.event;
- }
+ AWTEvent event = getNextEventPrivate();
+ if (event != null) {
+ return event;
}
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
pushPopCond.await();
@@ -520,6 +513,24 @@
} while(true);
}
+ /*
+ * Must be called under the lock. Doesn't call flushPendingEvents()
+ */
+ AWTEvent getNextEventPrivate() throws InterruptedException {
+ for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
+ if (queues[i].head != null) {
+ EventQueueItem entry = queues[i].head;
+ queues[i].head = entry.next;
+ if (entry.next == null) {
+ queues[i].tail = null;
+ }
+ uncacheEQItem(entry);
+ return entry.event;
+ }
+ }
+ return null;
+ }
+
AWTEvent getNextEvent(int id) throws InterruptedException {
do {
/*
@@ -659,7 +670,9 @@
dispatchThread.stopDispatching();
}
} else {
- System.err.println("unable to dispatch event: " + event);
+ if (eventLog.isLoggable(PlatformLogger.FINE)) {
+ eventLog.fine("Unable to dispatch event: " + event);
+ }
}
}
@@ -761,15 +774,23 @@
pushPopLock.lock();
try {
- EventQueue toPush = this;
- while (toPush.nextQueue != null) {
- toPush = toPush.nextQueue;
+ EventQueue topQueue = this;
+ while (topQueue.nextQueue != null) {
+ topQueue = topQueue.nextQueue;
+ }
+
+ if ((topQueue.dispatchThread != null) &&
+ (topQueue.dispatchThread.getEventQueue() == this))
+ {
+ newEventQueue.dispatchThread = topQueue.dispatchThread;
+ topQueue.dispatchThread.setEventQueue(newEventQueue);
}
// Transfer all events forward to new EventQueue.
- while (toPush.peekEvent() != null) {
+ while (topQueue.peekEvent() != null) {
try {
- newEventQueue.postEventPrivate(toPush.getNextEvent());
+ // Use getNextEventPrivate() as it doesn't call flushPendingEvents()
+ newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
if (eventLog.isLoggable(PlatformLogger.FINE)) {
eventLog.fine("Interrupted push", ie);
@@ -777,28 +798,21 @@
}
}
- newEventQueue.previousQueue = toPush;
+ // Wake up EDT waiting in getNextEvent(), so it can
+ // pick up a new EventQueue. Post the waking event before
+ // topQueue.nextQueue is assigned, otherwise the event would
+ // go newEventQueue
+ topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
- /*
- * Stop the event dispatch thread associated with the currently
- * active event queue, so that after the new queue is pushed
- * on the top this event dispatch thread won't prevent AWT from
- * being automatically shut down.
- * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
- * waits for the dispatch thread to exit, which in turn waits
- * for the lock in EQ.detachDispatchThread(), which is hold by
- * this method.
- */
- if (toPush.dispatchThread != null) {
- toPush.dispatchThread.stopDispatchingLater();
+ newEventQueue.previousQueue = topQueue;
+ topQueue.nextQueue = newEventQueue;
+
+ AppContext appContext = AppContext.getAppContext();
+ if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
+ appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
}
- toPush.nextQueue = newEventQueue;
-
- AppContext appContext = AppContext.getAppContext();
- if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) {
- appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
- }
+ pushPopCond.signalAll();
} finally {
pushPopLock.unlock();
}
@@ -822,44 +836,51 @@
eventLog.fine("EventQueue.pop(" + this + ")");
}
- EventDispatchThread dt = null;
pushPopLock.lock();
try {
- EventQueue toPop = this;
- while (toPop.nextQueue != null) {
- toPop = toPop.nextQueue;
+ EventQueue topQueue = this;
+ while (topQueue.nextQueue != null) {
+ topQueue = topQueue.nextQueue;
}
- EventQueue prev = toPop.previousQueue;
- if (prev == null) {
+ EventQueue prevQueue = topQueue.previousQueue;
+ if (prevQueue == null) {
throw new EmptyStackException();
}
- toPop.previousQueue = null;
+
+ topQueue.previousQueue = null;
+ prevQueue.nextQueue = null;
// Transfer all events back to previous EventQueue.
- prev.nextQueue = null;
- while (toPop.peekEvent() != null) {
+ while (topQueue.peekEvent() != null) {
try {
- prev.postEventPrivate(toPop.getNextEvent());
+ prevQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
if (eventLog.isLoggable(PlatformLogger.FINE)) {
eventLog.fine("Interrupted pop", ie);
}
}
}
- AppContext appContext = AppContext.getAppContext();
- if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
- appContext.put(AppContext.EVENT_QUEUE_KEY, prev);
+
+ if ((topQueue.dispatchThread != null) &&
+ (topQueue.dispatchThread.getEventQueue() == this))
+ {
+ prevQueue.dispatchThread = topQueue.dispatchThread;
+ topQueue.dispatchThread.setEventQueue(prevQueue);
}
- dt = toPop.dispatchThread;
+ AppContext appContext = AppContext.getAppContext();
+ if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
+ appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
+ }
+
+ // Wake up EDT waiting in getNextEvent(), so it can
+ // pick up a new EventQueue
+ topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
+
+ pushPopCond.signalAll();
} finally {
pushPopLock.unlock();
}
-
- if (dt != null) {
- dt.stopDispatching(); // Must be done outside synchronized
- // block to avoid possible deadlock
- }
}
/**
@@ -907,9 +928,9 @@
try {
AppContext appContext = AppContext.getAppContext();
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
- dispatchThread = (EventDispatchThread)
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
+ dispatchThread = AccessController.doPrivileged(
+ new PrivilegedAction<EventDispatchThread>() {
+ public EventDispatchThread run() {
EventDispatchThread t =
new EventDispatchThread(threadGroup,
name,
@@ -919,7 +940,8 @@
t.setDaemon(false);
return t;
}
- });
+ }
+ );
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
dispatchThread.start();
}
@@ -928,7 +950,7 @@
}
}
- final void detachDispatchThread(EventDispatchThread edt, boolean restart) {
+ final boolean detachDispatchThread(EventDispatchThread edt) {
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
@@ -939,26 +961,21 @@
*/
pushPopLock.lock();
try {
- EventDispatchThread oldDispatchThread = dispatchThread;
- if (dispatchThread == edt) {
- dispatchThread = null;
- }
- if (restart) {
+ if (edt == dispatchThread) {
/*
- * Event dispatch thread dies in case of an uncaught exception.
- * A new event dispatch thread for this queue will be started
- * only if a new event is posted to it. In case if no more
- * events are posted after this thread died all events that
- * currently are in the queue will never be dispatched.
+ * Don't detach the thread if any events are pending. Not
+ * sure if it's a possible scenario, though.
*
* Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue.
*/
if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
- initDispatchThread();
+ return false;
}
- AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread);
+ dispatchThread = null;
}
+ AWTAutoShutdown.getInstance().notifyThreadFree(edt);
+ return true;
} finally {
pushPopLock.unlock();
}
--- a/jdk/src/share/classes/java/beans/Encoder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Encoder.java Wed Jul 05 17:18:01 2017 +0200
@@ -194,13 +194,8 @@
* @see java.beans.BeanInfo#getBeanDescriptor
*/
public PersistenceDelegate getPersistenceDelegate(Class<?> type) {
- synchronized (this.finder) {
- PersistenceDelegate pd = this.finder.find(type);
- if (pd != null) {
- return pd;
- }
- }
- return MetaData.getPersistenceDelegate(type);
+ PersistenceDelegate pd = this.finder.find(type);
+ return (pd != null) ? pd : MetaData.getPersistenceDelegate(type);
}
/**
@@ -214,9 +209,7 @@
* @see java.beans.BeanInfo#getBeanDescriptor
*/
public void setPersistenceDelegate(Class<?> type, PersistenceDelegate delegate) {
- synchronized (this.finder) {
- this.finder.register(type, delegate);
- }
+ this.finder.register(type, delegate);
}
/**
--- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java Wed Jul 05 17:18:01 2017 +0200
@@ -27,6 +27,7 @@
import java.lang.ref.Reference;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
/**
* An EventSetDescriptor describes a group of events that a given Java
@@ -175,10 +176,8 @@
setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
// Be more forgiving of not finding the getListener method.
- Method method = Introspector.findMethod(sourceClass,
- getListenerMethodName, 0);
- if (method != null) {
- setGetListenerMethod(method);
+ if (getListenerMethodName != null) {
+ setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName));
}
}
@@ -188,7 +187,7 @@
return null;
}
Method method = Introspector.findMethod(cls, name, args);
- if (method == null) {
+ if ((method == null) || Modifier.isStatic(method.getModifiers())) {
throw new IntrospectionException("Method not found: " + name +
" on class " + cls.getName());
}
--- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java Wed Jul 05 17:18:01 2017 +0200
@@ -189,16 +189,11 @@
indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
}
}
-
- Class[] args = { int.class };
-
- indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
- 1, args);
+ indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
if (indexedReadMethod == null) {
// no "is" method, so look for a "get" method.
indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
- indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
- 1, args);
+ indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
}
setIndexedReadMethod0(indexedReadMethod);
}
@@ -270,8 +265,7 @@
if (indexedWriteMethodName == null) {
indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
}
- indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName,
- 2, (type == null) ? null : new Class[] { int.class, type });
+ indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type);
if (indexedWriteMethod != null) {
if (!indexedWriteMethod.getReturnType().equals(void.class)) {
indexedWriteMethod = null;
--- a/jdk/src/share/classes/java/beans/Introspector.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java Wed Jul 05 17:18:01 2017 +0200
@@ -28,6 +28,7 @@
import com.sun.beans.WeakCache;
import com.sun.beans.finder.BeanInfoFinder;
import com.sun.beans.finder.ClassFinder;
+import com.sun.beans.finder.MethodFinder;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
@@ -157,21 +158,23 @@
if (!ReflectUtil.isPackageAccessible(beanClass)) {
return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
}
+ Map<Class<?>, BeanInfo> beanInfoCache;
+ BeanInfo beanInfo;
synchronized (BEANINFO_CACHE) {
- Map<Class<?>, BeanInfo> beanInfoCache =
- (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE);
-
+ beanInfoCache = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE);
if (beanInfoCache == null) {
beanInfoCache = new WeakHashMap<Class<?>, BeanInfo>();
AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache);
}
- BeanInfo beanInfo = beanInfoCache.get(beanClass);
- if (beanInfo == null) {
- beanInfo = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
+ beanInfo = beanInfoCache.get(beanClass);
+ }
+ if (beanInfo == null) {
+ beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
+ synchronized (BEANINFO_CACHE) {
beanInfoCache.put(beanClass, beanInfo);
}
- return beanInfo;
}
+ return beanInfo;
}
/**
@@ -301,10 +304,7 @@
*/
public static String[] getBeanInfoSearchPath() {
- BeanInfoFinder finder = getFinder();
- synchronized (finder) {
- return finder.getPackages();
- }
+ return getFinder().getPackages();
}
/**
@@ -328,10 +328,7 @@
if (sm != null) {
sm.checkPropertiesAccess();
}
- BeanInfoFinder finder = getFinder();
- synchronized (finder) {
- finder.setPackages(path);
- }
+ getFinder().setPackages(path);
}
@@ -453,10 +450,7 @@
* @return Instance of an explicit BeanInfo class or null if one isn't found.
*/
private static BeanInfo findExplicitBeanInfo(Class beanClass) {
- BeanInfoFinder finder = getFinder();
- synchronized (finder) {
- return finder.find(beanClass);
- }
+ return getFinder().find(beanClass);
}
/**
@@ -849,8 +843,8 @@
Method read = result.getReadMethod();
if (read == null && write != null) {
- read = findMethod(result.getClass0(),
- GET_PREFIX + NameGenerator.capitalize(result.getName()), 0);
+ read = findInstanceMethod(result.getClass0(),
+ GET_PREFIX + NameGenerator.capitalize(result.getName()));
if (read != null) {
try {
result.setReadMethod(read);
@@ -860,9 +854,9 @@
}
}
if (write == null && read != null) {
- write = findMethod(result.getClass0(),
- SET_PREFIX + NameGenerator.capitalize(result.getName()), 1,
- new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) });
+ write = findInstanceMethod(result.getClass0(),
+ SET_PREFIX + NameGenerator.capitalize(result.getName()),
+ FeatureDescriptor.getReturnType(result.getClass0(), read));
if (write != null) {
try {
result.setWriteMethod(write);
@@ -1286,90 +1280,27 @@
// Package private support methods.
//======================================================================
- /**
- * Internal support for finding a target methodName with a given
- * parameter list on a given class.
- */
- private static Method internalFindMethod(Class start, String methodName,
- int argCount, Class args[]) {
- // For overriden methods we need to find the most derived version.
- // So we start with the given class and walk up the superclass chain.
-
- Method method = null;
-
- for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
- Method methods[] = getPublicDeclaredMethods(cl);
- for (int i = 0; i < methods.length; i++) {
- method = methods[i];
- if (method == null) {
- continue;
+ static Method findMethod(Class<?> type, String name, int args) {
+ for (Method method : type.getMethods()) {
+ if (method.getName().equals(name) && (args == method.getParameterTypes().length)) {
+ try {
+ return MethodFinder.findAccessibleMethod(method);
}
-
- // make sure method signature matches.
- Class params[] = FeatureDescriptor.getParameterTypes(start, method);
- if (method.getName().equals(methodName) &&
- params.length == argCount) {
- if (args != null) {
- boolean different = false;
- if (argCount > 0) {
- for (int j = 0; j < argCount; j++) {
- if (params[j] != args[j]) {
- different = true;
- continue;
- }
- }
- if (different) {
- continue;
- }
- }
- }
- return method;
+ catch (NoSuchMethodException exception) {
+ // continue search for a method with the specified count of parameters
}
}
}
- method = null;
-
- // Now check any inherited interfaces. This is necessary both when
- // the argument class is itself an interface, and when the argument
- // class is an abstract class.
- Class ifcs[] = start.getInterfaces();
- for (int i = 0 ; i < ifcs.length; i++) {
- // Note: The original implementation had both methods calling
- // the 3 arg method. This is preserved but perhaps it should
- // pass the args array instead of null.
- method = internalFindMethod(ifcs[i], methodName, argCount, null);
- if (method != null) {
- break;
- }
- }
- return method;
+ return null;
}
- /**
- * Find a target methodName on a given class.
- */
- static Method findMethod(Class cls, String methodName, int argCount) {
- return findMethod(cls, methodName, argCount, null);
- }
-
- /**
- * Find a target methodName with specific parameter list on a given class.
- * <p>
- * Used in the contructors of the EventSetDescriptor,
- * PropertyDescriptor and the IndexedPropertyDescriptor.
- * <p>
- * @param cls The Class object on which to retrieve the method.
- * @param methodName Name of the method.
- * @param argCount Number of arguments for the desired method.
- * @param args Array of argument types for the method.
- * @return the method or null if not found
- */
- static Method findMethod(Class cls, String methodName, int argCount,
- Class args[]) {
- if (methodName == null) {
+ static Method findInstanceMethod(Class<?> type, String name, Class<?>... args) {
+ try {
+ return MethodFinder.findInstanceMethod(type, name, args);
+ }
+ catch (NoSuchMethodException exception) {
return null;
}
- return internalFindMethod(cls, methodName, argCount, args);
}
/**
--- a/jdk/src/share/classes/java/beans/MethodDescriptor.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java Wed Jul 05 17:18:01 2017 +0200
@@ -82,21 +82,21 @@
Method method = getMethod0();
if (method == null) {
Class cls = getClass0();
- if (cls != null) {
+ String name = getName();
+ if ((cls != null) && (name != null)) {
Class[] params = getParams();
if (params == null) {
for (int i = 0; i < 3; i++) {
// Find methods for up to 2 params. We are guessing here.
// This block should never execute unless the classloader
// that loaded the argument classes disappears.
- method = Introspector.findMethod(cls, getName(), i, null);
+ method = Introspector.findMethod(cls, name, i);
if (method != null) {
break;
}
}
} else {
- method = Introspector.findMethod(cls, getName(),
- params.length, params);
+ method = Statement.getMethod(cls, name, params);
}
setMethod(method);
}
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java Wed Jul 05 17:18:01 2017 +0200
@@ -112,9 +112,7 @@
// If this class or one of its base classes allow PropertyChangeListener,
// then we assume that any properties we discover are "bound".
// See Introspector.getTargetPropertyInfo() method.
- String name = "addPropertyChangeListener";
- Class[] args = {PropertyChangeListener.class};
- this.bound = (null != Introspector.findMethod(beanClass, name, args.length, args));
+ this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class);
}
/**
@@ -225,10 +223,10 @@
// property type is. For booleans, there can be "is" and "get"
// methods. If an "is" method exists, this is the official
// reader method so look for this one first.
- readMethod = Introspector.findMethod(cls, readMethodName, 0);
+ readMethod = Introspector.findInstanceMethod(cls, readMethodName);
if (readMethod == null) {
readMethodName = Introspector.GET_PREFIX + getBaseName();
- readMethod = Introspector.findMethod(cls, readMethodName, 0);
+ readMethod = Introspector.findInstanceMethod(cls, readMethodName);
}
try {
setReadMethod(readMethod);
@@ -293,8 +291,7 @@
writeMethodName = Introspector.SET_PREFIX + getBaseName();
}
- writeMethod = Introspector.findMethod(cls, writeMethodName, 1,
- (type == null) ? null : new Class[] { type });
+ writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type);
if (writeMethod != null) {
if (!writeMethod.getReturnType().equals(void.class)) {
writeMethod = null;
--- a/jdk/src/share/classes/java/beans/PropertyEditorManager.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyEditorManager.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,10 +81,7 @@
if (sm != null) {
sm.checkPropertiesAccess();
}
- PropertyEditorFinder finder = getFinder();
- synchronized (finder) {
- finder.register(targetType, editorClass);
- }
+ getFinder().register(targetType, editorClass);
}
/**
@@ -95,10 +92,7 @@
* The result is null if no suitable editor can be found.
*/
public static PropertyEditor findEditor(Class<?> targetType) {
- PropertyEditorFinder finder = getFinder();
- synchronized (finder) {
- return finder.find(targetType);
- }
+ return getFinder().find(targetType);
}
/**
@@ -110,10 +104,7 @@
* e.g. Sun implementation initially sets to {"sun.beans.editors"}.
*/
public static String[] getEditorSearchPath() {
- PropertyEditorFinder finder = getFinder();
- synchronized (finder) {
- return finder.getPackages();
- }
+ return getFinder().getPackages();
}
/**
@@ -134,10 +125,7 @@
if (sm != null) {
sm.checkPropertiesAccess();
}
- PropertyEditorFinder finder = getFinder();
- synchronized (finder) {
- finder.setPackages(path);
- }
+ getFinder().setPackages(path);
}
private static PropertyEditorFinder getFinder() {
--- a/jdk/src/share/classes/java/beans/XMLDecoder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLDecoder.java Wed Jul 05 17:18:01 2017 +0200
@@ -60,7 +60,7 @@
*
* @author Philip Milne
*/
-public class XMLDecoder {
+public class XMLDecoder implements AutoCloseable {
private final DocumentHandler handler = new DocumentHandler();
private final InputSource input;
private Object owner;
--- a/jdk/src/share/classes/java/beans/XMLEncoder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLEncoder.java Wed Jul 05 17:18:01 2017 +0200
@@ -204,7 +204,7 @@
*
* @author Philip Milne
*/
-public class XMLEncoder extends Encoder {
+public class XMLEncoder extends Encoder implements AutoCloseable {
private final CharsetEncoder encoder;
private final String charset;
--- a/jdk/src/share/classes/java/io/Bits.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/io/Bits.java Wed Jul 05 17:18:01 2017 +0200
@@ -41,51 +41,39 @@
}
static char getChar(byte[] b, int off) {
- return (char) (((b[off + 1] & 0xFF) << 0) +
- ((b[off + 0]) << 8));
+ return (char) ((b[off + 1] & 0xFF) +
+ (b[off] << 8));
}
static short getShort(byte[] b, int off) {
- return (short) (((b[off + 1] & 0xFF) << 0) +
- ((b[off + 0]) << 8));
+ return (short) ((b[off + 1] & 0xFF) +
+ (b[off] << 8));
}
static int getInt(byte[] b, int off) {
- return ((b[off + 3] & 0xFF) << 0) +
- ((b[off + 2] & 0xFF) << 8) +
+ return ((b[off + 3] & 0xFF) ) +
+ ((b[off + 2] & 0xFF) << 8) +
((b[off + 1] & 0xFF) << 16) +
- ((b[off + 0]) << 24);
+ ((b[off ] ) << 24);
}
static float getFloat(byte[] b, int off) {
- int i = ((b[off + 3] & 0xFF) << 0) +
- ((b[off + 2] & 0xFF) << 8) +
- ((b[off + 1] & 0xFF) << 16) +
- ((b[off + 0]) << 24);
- return Float.intBitsToFloat(i);
+ return Float.intBitsToFloat(getInt(b, off));
}
static long getLong(byte[] b, int off) {
- return ((b[off + 7] & 0xFFL) << 0) +
- ((b[off + 6] & 0xFFL) << 8) +
+ return ((b[off + 7] & 0xFFL) ) +
+ ((b[off + 6] & 0xFFL) << 8) +
((b[off + 5] & 0xFFL) << 16) +
((b[off + 4] & 0xFFL) << 24) +
((b[off + 3] & 0xFFL) << 32) +
((b[off + 2] & 0xFFL) << 40) +
((b[off + 1] & 0xFFL) << 48) +
- (((long) b[off + 0]) << 56);
+ (((long) b[off]) << 56);
}
static double getDouble(byte[] b, int off) {
- long j = ((b[off + 7] & 0xFFL) << 0) +
- ((b[off + 6] & 0xFFL) << 8) +
- ((b[off + 5] & 0xFFL) << 16) +
- ((b[off + 4] & 0xFFL) << 24) +
- ((b[off + 3] & 0xFFL) << 32) +
- ((b[off + 2] & 0xFFL) << 40) +
- ((b[off + 1] & 0xFFL) << 48) +
- (((long) b[off + 0]) << 56);
- return Double.longBitsToDouble(j);
+ return Double.longBitsToDouble(getLong(b, off));
}
/*
@@ -98,50 +86,38 @@
}
static void putChar(byte[] b, int off, char val) {
- b[off + 1] = (byte) (val >>> 0);
- b[off + 0] = (byte) (val >>> 8);
+ b[off + 1] = (byte) (val );
+ b[off ] = (byte) (val >>> 8);
}
static void putShort(byte[] b, int off, short val) {
- b[off + 1] = (byte) (val >>> 0);
- b[off + 0] = (byte) (val >>> 8);
+ b[off + 1] = (byte) (val );
+ b[off ] = (byte) (val >>> 8);
}
static void putInt(byte[] b, int off, int val) {
- b[off + 3] = (byte) (val >>> 0);
- b[off + 2] = (byte) (val >>> 8);
+ b[off + 3] = (byte) (val );
+ b[off + 2] = (byte) (val >>> 8);
b[off + 1] = (byte) (val >>> 16);
- b[off + 0] = (byte) (val >>> 24);
+ b[off ] = (byte) (val >>> 24);
}
static void putFloat(byte[] b, int off, float val) {
- int i = Float.floatToIntBits(val);
- b[off + 3] = (byte) (i >>> 0);
- b[off + 2] = (byte) (i >>> 8);
- b[off + 1] = (byte) (i >>> 16);
- b[off + 0] = (byte) (i >>> 24);
+ putInt(b, off, Float.floatToIntBits(val));
}
static void putLong(byte[] b, int off, long val) {
- b[off + 7] = (byte) (val >>> 0);
- b[off + 6] = (byte) (val >>> 8);
+ b[off + 7] = (byte) (val );
+ b[off + 6] = (byte) (val >>> 8);
b[off + 5] = (byte) (val >>> 16);
b[off + 4] = (byte) (val >>> 24);
b[off + 3] = (byte) (val >>> 32);
b[off + 2] = (byte) (val >>> 40);
b[off + 1] = (byte) (val >>> 48);
- b[off + 0] = (byte) (val >>> 56);
+ b[off ] = (byte) (val >>> 56);
}
static void putDouble(byte[] b, int off, double val) {
- long j = Double.doubleToLongBits(val);
- b[off + 7] = (byte) (j >>> 0);
- b[off + 6] = (byte) (j >>> 8);
- b[off + 5] = (byte) (j >>> 16);
- b[off + 4] = (byte) (j >>> 24);
- b[off + 3] = (byte) (j >>> 32);
- b[off + 2] = (byte) (j >>> 40);
- b[off + 1] = (byte) (j >>> 48);
- b[off + 0] = (byte) (j >>> 56);
+ putLong(b, off, Double.doubleToLongBits(val));
}
}
--- a/jdk/src/share/classes/java/io/Closeable.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/io/Closeable.java Wed Jul 05 17:18:01 2017 +0200
@@ -28,14 +28,14 @@
import java.io.IOException;
/**
- * A <tt>Closeable</tt> is a source or destination of data that can be closed.
+ * A {@code Closeable} is a source or destination of data that can be closed.
* The close method is invoked to release resources that the object is
* holding (such as open files).
*
* @since 1.5
*/
-public interface Closeable {
+public interface Closeable extends AutoCloseable {
/**
* Closes this stream and releases any system resources associated
@@ -45,5 +45,4 @@
* @throws IOException if an I/O error occurs
*/
public void close() throws IOException;
-
}
--- a/jdk/src/share/classes/java/io/ObjectInput.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectInput.java Wed Jul 05 17:18:01 2017 +0200
@@ -36,7 +36,7 @@
* @see java.io.ObjectInputStream
* @since JDK1.1
*/
-public interface ObjectInput extends DataInput {
+public interface ObjectInput extends DataInput, AutoCloseable {
/**
* Read and return an object. The class that implements this interface
* defines where the object is "read" from.
--- a/jdk/src/share/classes/java/io/ObjectOutput.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectOutput.java Wed Jul 05 17:18:01 2017 +0200
@@ -36,7 +36,7 @@
* @see java.io.ObjectInputStream
* @since JDK1.1
*/
-public interface ObjectOutput extends DataOutput {
+public interface ObjectOutput extends DataOutput, AutoCloseable {
/**
* Write an object to the underlying storage or stream. The
* class that implements this interface defines how the object is
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Wed Jul 05 17:18:01 2017 +0200
@@ -721,20 +721,19 @@
* {@code codePoint} isn't a valid Unicode code point
*/
public AbstractStringBuilder appendCodePoint(int codePoint) {
- if (!Character.isValidCodePoint(codePoint)) {
+ final int count = this.count;
+
+ if (Character.isBmpCodePoint(codePoint)) {
+ ensureCapacityInternal(count + 1);
+ value[count] = (char) codePoint;
+ this.count = count + 1;
+ } else if (Character.isValidCodePoint(codePoint)) {
+ ensureCapacityInternal(count + 2);
+ Character.toSurrogates(codePoint, value, count);
+ this.count = count + 2;
+ } else {
throw new IllegalArgumentException();
}
- int n = 1;
- if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- n++;
- }
- ensureCapacityInternal(count + n);
- if (n == 1) {
- value[count++] = (char) codePoint;
- } else {
- Character.toSurrogates(codePoint, value, count);
- count += n;
- }
return this;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/AutoCloseable.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * A resource that must be closed when it is no longer needed.
+ *
+ * @author Josh Bloch
+ * @since 1.7
+ */
+public interface AutoCloseable {
+ /**
+ * Close this resource, relinquishing any underlying resources.
+ * This method is invoked automatically by the automatic resource
+ * management block construct.
+ *
+ * <p>Classes implementing this method are strongly encouraged to
+ * be declared to throw more specific exceptions (or no exception
+ * at all, if the close cannot fail).
+ *
+ * @throws Exception if this resource cannot be closed
+ */
+ void close() throws Exception;
+}
--- a/jdk/src/share/classes/java/lang/Character.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Character.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
*/
package java.lang;
+
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
@@ -67,17 +68,16 @@
* definition</i></a> of the U+<i>n</i> notation in the Unicode
* standard.)
*
- * <p>The set of characters from U+0000 to U+FFFF is sometimes
- * referred to as the <em>Basic Multilingual Plane (BMP)</em>. <a
- * name="supplementary">Characters</a> whose code points are greater
+ * <p><a name="BMP">The set of characters from U+0000 to U+FFFF is
+ * sometimes referred to as the <em>Basic Multilingual Plane (BMP)</em>.
+ * <a name="supplementary">Characters</a> whose code points are greater
* than U+FFFF are called <em>supplementary character</em>s. The Java
- * 2 platform uses the UTF-16 representation in <code>char</code>
- * arrays and in the <code>String</code> and <code>StringBuffer</code>
- * classes. In this representation, supplementary characters are
- * represented as a pair of <code>char</code> values, the first from
- * the <em>high-surrogates</em> range, (\uD800-\uDBFF), the
- * second from the <em>low-surrogates</em> range
- * (\uDC00-\uDFFF).
+ * platform uses the UTF-16 representation in <code>char</code> arrays and
+ * in the <code>String</code> and <code>StringBuffer</code> classes. In
+ * this representation, supplementary characters are represented as a pair
+ * of <code>char</code> values, the first from the <em>high-surrogates</em>
+ * range, (\uD800-\uDBFF), the second from the
+ * <em>low-surrogates</em> range (\uDC00-\uDFFF).
*
* <p>A <code>char</code> value, therefore, represents Basic
* Multilingual Plane (BMP) code points, including the surrogate
@@ -115,10 +115,12 @@
* @author Lee Boynton
* @author Guy Steele
* @author Akira Tanaka
+ * @author Martin Buchholz
+ * @author Ulf Zibis
* @since 1.0
*/
public final
-class Character extends Object implements java.io.Serializable, Comparable<Character> {
+class Character implements java.io.Serializable, Comparable<Character> {
/**
* The minimum radix available for conversion to and from strings.
* The constant value of this field is the smallest value permitted
@@ -127,10 +129,10 @@
* method, and the <code>toString</code> method of class
* <code>Integer</code>.
*
- * @see java.lang.Character#digit(char, int)
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Integer#toString(int, int)
- * @see java.lang.Integer#valueOf(java.lang.String)
+ * @see Character#digit(char, int)
+ * @see Character#forDigit(int, int)
+ * @see Integer#toString(int, int)
+ * @see Integer#valueOf(String)
*/
public static final int MIN_RADIX = 2;
@@ -142,10 +144,10 @@
* method, and the <code>toString</code> method of class
* <code>Integer</code>.
*
- * @see java.lang.Character#digit(char, int)
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Integer#toString(int, int)
- * @see java.lang.Integer#valueOf(java.lang.String)
+ * @see Character#digit(char, int)
+ * @see Character#forDigit(int, int)
+ * @see Integer#toString(int, int)
+ * @see Integer#valueOf(String)
*/
public static final int MAX_RADIX = 36;
@@ -155,7 +157,7 @@
*
* @since 1.0.2
*/
- public static final char MIN_VALUE = '\u0000';
+ public static final char MIN_VALUE = '\u0000';
/**
* The constant value of this field is the largest value of type
@@ -163,7 +165,7 @@
*
* @since 1.0.2
*/
- public static final char MAX_VALUE = '\uFFFF';
+ public static final char MAX_VALUE = '\uFFFF';
/**
* The <code>Class</code> instance representing the primitive type
@@ -171,230 +173,201 @@
*
* @since 1.1
*/
+ @SuppressWarnings("unchecked")
public static final Class<Character> TYPE = Class.getPrimitiveClass("char");
- /*
- * Normative general types
- */
-
- /*
- * General character types
- */
-
- /**
- * General category "Cn" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- UNASSIGNED = 0;
-
- /**
- * General category "Lu" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- UPPERCASE_LETTER = 1;
-
- /**
- * General category "Ll" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- LOWERCASE_LETTER = 2;
-
- /**
- * General category "Lt" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- TITLECASE_LETTER = 3;
-
- /**
- * General category "Lm" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- MODIFIER_LETTER = 4;
-
- /**
- * General category "Lo" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- OTHER_LETTER = 5;
-
- /**
- * General category "Mn" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- NON_SPACING_MARK = 6;
-
- /**
- * General category "Me" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- ENCLOSING_MARK = 7;
-
- /**
- * General category "Mc" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- COMBINING_SPACING_MARK = 8;
-
- /**
- * General category "Nd" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- DECIMAL_DIGIT_NUMBER = 9;
-
- /**
- * General category "Nl" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- LETTER_NUMBER = 10;
-
- /**
- * General category "No" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- OTHER_NUMBER = 11;
-
- /**
- * General category "Zs" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- SPACE_SEPARATOR = 12;
-
- /**
- * General category "Zl" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- LINE_SEPARATOR = 13;
-
- /**
- * General category "Zp" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- PARAGRAPH_SEPARATOR = 14;
-
- /**
- * General category "Cc" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- CONTROL = 15;
-
- /**
- * General category "Cf" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- FORMAT = 16;
-
- /**
- * General category "Co" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- PRIVATE_USE = 18;
-
- /**
- * General category "Cs" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- SURROGATE = 19;
-
- /**
- * General category "Pd" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- DASH_PUNCTUATION = 20;
-
- /**
- * General category "Ps" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- START_PUNCTUATION = 21;
-
- /**
- * General category "Pe" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- END_PUNCTUATION = 22;
-
- /**
- * General category "Pc" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- CONNECTOR_PUNCTUATION = 23;
-
- /**
- * General category "Po" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- OTHER_PUNCTUATION = 24;
-
- /**
- * General category "Sm" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- MATH_SYMBOL = 25;
-
- /**
- * General category "Sc" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- CURRENCY_SYMBOL = 26;
-
- /**
- * General category "Sk" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- MODIFIER_SYMBOL = 27;
-
- /**
- * General category "So" in the Unicode specification.
- * @since 1.1
- */
- public static final byte
- OTHER_SYMBOL = 28;
-
- /**
- * General category "Pi" in the Unicode specification.
- * @since 1.4
- */
- public static final byte
- INITIAL_QUOTE_PUNCTUATION = 29;
-
- /**
- * General category "Pf" in the Unicode specification.
- * @since 1.4
- */
- public static final byte
- FINAL_QUOTE_PUNCTUATION = 30;
+ /*
+ * Normative general types
+ */
+
+ /*
+ * General character types
+ */
+
+ /**
+ * General category "Cn" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte UNASSIGNED = 0;
+
+ /**
+ * General category "Lu" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte UPPERCASE_LETTER = 1;
+
+ /**
+ * General category "Ll" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte LOWERCASE_LETTER = 2;
+
+ /**
+ * General category "Lt" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte TITLECASE_LETTER = 3;
+
+ /**
+ * General category "Lm" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte MODIFIER_LETTER = 4;
+
+ /**
+ * General category "Lo" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte OTHER_LETTER = 5;
+
+ /**
+ * General category "Mn" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte NON_SPACING_MARK = 6;
+
+ /**
+ * General category "Me" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte ENCLOSING_MARK = 7;
+
+ /**
+ * General category "Mc" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte COMBINING_SPACING_MARK = 8;
+
+ /**
+ * General category "Nd" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte DECIMAL_DIGIT_NUMBER = 9;
+
+ /**
+ * General category "Nl" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte LETTER_NUMBER = 10;
+
+ /**
+ * General category "No" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte OTHER_NUMBER = 11;
+
+ /**
+ * General category "Zs" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte SPACE_SEPARATOR = 12;
+
+ /**
+ * General category "Zl" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte LINE_SEPARATOR = 13;
+
+ /**
+ * General category "Zp" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte PARAGRAPH_SEPARATOR = 14;
+
+ /**
+ * General category "Cc" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte CONTROL = 15;
+
+ /**
+ * General category "Cf" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte FORMAT = 16;
+
+ /**
+ * General category "Co" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte PRIVATE_USE = 18;
+
+ /**
+ * General category "Cs" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte SURROGATE = 19;
+
+ /**
+ * General category "Pd" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte DASH_PUNCTUATION = 20;
+
+ /**
+ * General category "Ps" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte START_PUNCTUATION = 21;
+
+ /**
+ * General category "Pe" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte END_PUNCTUATION = 22;
+
+ /**
+ * General category "Pc" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte CONNECTOR_PUNCTUATION = 23;
+
+ /**
+ * General category "Po" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte OTHER_PUNCTUATION = 24;
+
+ /**
+ * General category "Sm" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte MATH_SYMBOL = 25;
+
+ /**
+ * General category "Sc" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte CURRENCY_SYMBOL = 26;
+
+ /**
+ * General category "Sk" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte MODIFIER_SYMBOL = 27;
+
+ /**
+ * General category "So" in the Unicode specification.
+ * @since 1.1
+ */
+ public static final byte OTHER_SYMBOL = 28;
+
+ /**
+ * General category "Pi" in the Unicode specification.
+ * @since 1.4
+ */
+ public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
+
+ /**
+ * General category "Pf" in the Unicode specification.
+ * @since 1.4
+ */
+ public static final byte FINAL_QUOTE_PUNCTUATION = 30;
/**
* Error flag. Use int (code point) to avoid confusion with U+FFFF.
*/
- static final int ERROR = 0xFFFFFFFF;
+ static final int ERROR = 0xFFFFFFFF;
/**
@@ -402,7 +375,7 @@
* values have undefined directionality in the Unicode specification.
* @since 1.4
*/
- public static final byte DIRECTIONALITY_UNDEFINED = -1;
+ public static final byte DIRECTIONALITY_UNDEFINED = -1;
/**
* Strong bidirectional character type "L" in the Unicode specification.
@@ -609,9 +582,9 @@
/**
* Instances of this class represent particular subsets of the Unicode
* character set. The only family of subsets defined in the
- * <code>Character</code> class is <code>{@link Character.UnicodeBlock
- * UnicodeBlock}</code>. Other portions of the Java API may define other
- * subsets for their own purposes.
+ * <code>Character</code> class is {@link Character.UnicodeBlock}.
+ * Other portions of the Java API may define other subsets for their
+ * own purposes.
*
* @since 1.2
*/
@@ -624,6 +597,7 @@
*
* @exception NullPointerException if name is <code>null</code>
* @param name The name of this subset
+ * @exception NullPointerException if name is <code>null</code>
*/
protected Subset(String name) {
if (name == null) {
@@ -662,6 +636,9 @@
}
}
+ // See http://www.unicode.org/Public/UNIDATA/Blocks.txt
+ // for the latest specification of Unicode Blocks.
+
/**
* A family of character subsets representing the character blocks in the
* Unicode specification. Character blocks generally define characters
@@ -672,37 +649,35 @@
*/
public static final class UnicodeBlock extends Subset {
- private static Map map = new HashMap();
-
- /**
- * Create a UnicodeBlock with the given identifier name.
+ private static Map<String, UnicodeBlock> map
+ = new HashMap<String, UnicodeBlock>(256);
+
+ /**
+ * Creates a UnicodeBlock with the given identifier name.
* This name must be the same as the block identifier.
*/
private UnicodeBlock(String idName) {
super(idName);
- map.put(idName.toUpperCase(Locale.US), this);
+ map.put(idName, this);
}
/**
- * Create a UnicodeBlock with the given identifier name and
+ * Creates a UnicodeBlock with the given identifier name and
* alias name.
*/
private UnicodeBlock(String idName, String alias) {
this(idName);
- map.put(alias.toUpperCase(Locale.US), this);
+ map.put(alias, this);
}
/**
- * Create a UnicodeBlock with the given identifier name and
+ * Creates a UnicodeBlock with the given identifier name and
* alias names.
*/
- private UnicodeBlock(String idName, String[] aliasName) {
+ private UnicodeBlock(String idName, String... aliases) {
this(idName);
- if (aliasName != null) {
- for(int x=0; x<aliasName.length; ++x) {
- map.put(aliasName[x].toUpperCase(Locale.US), this);
- }
- }
+ for (String alias : aliases)
+ map.put(alias, this);
}
/**
@@ -710,51 +685,63 @@
* @since 1.2
*/
public static final UnicodeBlock BASIC_LATIN =
- new UnicodeBlock("BASIC_LATIN", new String[] {"Basic Latin", "BasicLatin" });
+ new UnicodeBlock("BASIC_LATIN",
+ "BASIC LATIN",
+ "BASICLATIN");
/**
* Constant for the "Latin-1 Supplement" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock LATIN_1_SUPPLEMENT =
- new UnicodeBlock("LATIN_1_SUPPLEMENT", new String[]{ "Latin-1 Supplement", "Latin-1Supplement"});
+ new UnicodeBlock("LATIN_1_SUPPLEMENT",
+ "LATIN-1 SUPPLEMENT",
+ "LATIN-1SUPPLEMENT");
/**
* Constant for the "Latin Extended-A" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock LATIN_EXTENDED_A =
- new UnicodeBlock("LATIN_EXTENDED_A", new String[]{ "Latin Extended-A", "LatinExtended-A"});
+ new UnicodeBlock("LATIN_EXTENDED_A",
+ "LATIN EXTENDED-A",
+ "LATINEXTENDED-A");
/**
* Constant for the "Latin Extended-B" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock LATIN_EXTENDED_B =
- new UnicodeBlock("LATIN_EXTENDED_B", new String[] {"Latin Extended-B", "LatinExtended-B"});
+ new UnicodeBlock("LATIN_EXTENDED_B",
+ "LATIN EXTENDED-B",
+ "LATINEXTENDED-B");
/**
* Constant for the "IPA Extensions" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock IPA_EXTENSIONS =
- new UnicodeBlock("IPA_EXTENSIONS", new String[] {"IPA Extensions", "IPAExtensions"});
+ new UnicodeBlock("IPA_EXTENSIONS",
+ "IPA EXTENSIONS",
+ "IPAEXTENSIONS");
/**
* Constant for the "Spacing Modifier Letters" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock SPACING_MODIFIER_LETTERS =
- new UnicodeBlock("SPACING_MODIFIER_LETTERS", new String[] { "Spacing Modifier Letters",
- "SpacingModifierLetters"});
+ new UnicodeBlock("SPACING_MODIFIER_LETTERS",
+ "SPACING MODIFIER LETTERS",
+ "SPACINGMODIFIERLETTERS");
/**
* Constant for the "Combining Diacritical Marks" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS =
- new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", new String[] {"Combining Diacritical Marks",
- "CombiningDiacriticalMarks" });
+ new UnicodeBlock("COMBINING_DIACRITICAL_MARKS",
+ "COMBINING DIACRITICAL MARKS",
+ "COMBININGDIACRITICALMARKS");
/**
* Constant for the "Greek and Coptic" Unicode character block.
@@ -763,8 +750,10 @@
*
* @since 1.2
*/
- public static final UnicodeBlock GREEK
- = new UnicodeBlock("GREEK", new String[] {"Greek and Coptic", "GreekandCoptic"});
+ public static final UnicodeBlock GREEK =
+ new UnicodeBlock("GREEK",
+ "GREEK AND COPTIC",
+ "GREEKANDCOPTIC");
/**
* Constant for the "Cyrillic" Unicode character block.
@@ -890,44 +879,54 @@
* @since 1.2
*/
public static final UnicodeBlock HANGUL_JAMO =
- new UnicodeBlock("HANGUL_JAMO", new String[] {"Hangul Jamo", "HangulJamo"});
+ new UnicodeBlock("HANGUL_JAMO",
+ "HANGUL JAMO",
+ "HANGULJAMO");
/**
* Constant for the "Latin Extended Additional" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL =
- new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", new String[] {"Latin Extended Additional",
- "LatinExtendedAdditional"});
+ new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL",
+ "LATIN EXTENDED ADDITIONAL",
+ "LATINEXTENDEDADDITIONAL");
/**
* Constant for the "Greek Extended" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock GREEK_EXTENDED =
- new UnicodeBlock("GREEK_EXTENDED", new String[] {"Greek Extended", "GreekExtended"});
+ new UnicodeBlock("GREEK_EXTENDED",
+ "GREEK EXTENDED",
+ "GREEKEXTENDED");
/**
* Constant for the "General Punctuation" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock GENERAL_PUNCTUATION =
- new UnicodeBlock("GENERAL_PUNCTUATION", new String[] {"General Punctuation", "GeneralPunctuation"});
+ new UnicodeBlock("GENERAL_PUNCTUATION",
+ "GENERAL PUNCTUATION",
+ "GENERALPUNCTUATION");
/**
* Constant for the "Superscripts and Subscripts" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS =
- new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", new String[] {"Superscripts and Subscripts",
- "SuperscriptsandSubscripts" });
+ new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS",
+ "SUPERSCRIPTS AND SUBSCRIPTS",
+ "SUPERSCRIPTSANDSUBSCRIPTS");
/**
* Constant for the "Currency Symbols" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock CURRENCY_SYMBOLS =
- new UnicodeBlock("CURRENCY_SYMBOLS", new String[] { "Currency Symbols", "CurrencySymbols"});
+ new UnicodeBlock("CURRENCY_SYMBOLS",
+ "CURRENCY SYMBOLS",
+ "CURRENCYSYMBOLS");
/**
* Constant for the "Combining Diacritical Marks for Symbols" Unicode character block.
@@ -936,24 +935,29 @@
* @since 1.2
*/
public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS =
- new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", new String[] {"Combining Diacritical Marks for Symbols",
- "CombiningDiacriticalMarksforSymbols",
- "Combining Marks for Symbols",
- "CombiningMarksforSymbols" });
+ new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS",
+ "COMBINING DIACRITICAL MARKS FOR SYMBOLS",
+ "COMBININGDIACRITICALMARKSFORSYMBOLS",
+ "COMBINING MARKS FOR SYMBOLS",
+ "COMBININGMARKSFORSYMBOLS");
/**
* Constant for the "Letterlike Symbols" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock LETTERLIKE_SYMBOLS =
- new UnicodeBlock("LETTERLIKE_SYMBOLS", new String[] { "Letterlike Symbols", "LetterlikeSymbols"});
+ new UnicodeBlock("LETTERLIKE_SYMBOLS",
+ "LETTERLIKE SYMBOLS",
+ "LETTERLIKESYMBOLS");
/**
* Constant for the "Number Forms" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock NUMBER_FORMS =
- new UnicodeBlock("NUMBER_FORMS", new String[] {"Number Forms", "NumberForms"});
+ new UnicodeBlock("NUMBER_FORMS",
+ "NUMBER FORMS",
+ "NUMBERFORMS");
/**
* Constant for the "Arrows" Unicode character block.
@@ -967,68 +971,81 @@
* @since 1.2
*/
public static final UnicodeBlock MATHEMATICAL_OPERATORS =
- new UnicodeBlock("MATHEMATICAL_OPERATORS", new String[] {"Mathematical Operators",
- "MathematicalOperators"});
+ new UnicodeBlock("MATHEMATICAL_OPERATORS",
+ "MATHEMATICAL OPERATORS",
+ "MATHEMATICALOPERATORS");
/**
* Constant for the "Miscellaneous Technical" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock MISCELLANEOUS_TECHNICAL =
- new UnicodeBlock("MISCELLANEOUS_TECHNICAL", new String[] {"Miscellaneous Technical",
- "MiscellaneousTechnical"});
+ new UnicodeBlock("MISCELLANEOUS_TECHNICAL",
+ "MISCELLANEOUS TECHNICAL",
+ "MISCELLANEOUSTECHNICAL");
/**
* Constant for the "Control Pictures" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock CONTROL_PICTURES =
- new UnicodeBlock("CONTROL_PICTURES", new String[] {"Control Pictures", "ControlPictures"});
+ new UnicodeBlock("CONTROL_PICTURES",
+ "CONTROL PICTURES",
+ "CONTROLPICTURES");
/**
* Constant for the "Optical Character Recognition" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION =
- new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", new String[] {"Optical Character Recognition",
- "OpticalCharacterRecognition"});
+ new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION",
+ "OPTICAL CHARACTER RECOGNITION",
+ "OPTICALCHARACTERRECOGNITION");
/**
* Constant for the "Enclosed Alphanumerics" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock ENCLOSED_ALPHANUMERICS =
- new UnicodeBlock("ENCLOSED_ALPHANUMERICS", new String[] {"Enclosed Alphanumerics",
- "EnclosedAlphanumerics"});
+ new UnicodeBlock("ENCLOSED_ALPHANUMERICS",
+ "ENCLOSED ALPHANUMERICS",
+ "ENCLOSEDALPHANUMERICS");
/**
* Constant for the "Box Drawing" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock BOX_DRAWING =
- new UnicodeBlock("BOX_DRAWING", new String[] {"Box Drawing", "BoxDrawing"});
+ new UnicodeBlock("BOX_DRAWING",
+ "BOX DRAWING",
+ "BOXDRAWING");
/**
* Constant for the "Block Elements" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock BLOCK_ELEMENTS =
- new UnicodeBlock("BLOCK_ELEMENTS", new String[] {"Block Elements", "BlockElements"});
+ new UnicodeBlock("BLOCK_ELEMENTS",
+ "BLOCK ELEMENTS",
+ "BLOCKELEMENTS");
/**
* Constant for the "Geometric Shapes" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock GEOMETRIC_SHAPES =
- new UnicodeBlock("GEOMETRIC_SHAPES", new String[] {"Geometric Shapes", "GeometricShapes"});
+ new UnicodeBlock("GEOMETRIC_SHAPES",
+ "GEOMETRIC SHAPES",
+ "GEOMETRICSHAPES");
/**
* Constant for the "Miscellaneous Symbols" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock MISCELLANEOUS_SYMBOLS =
- new UnicodeBlock("MISCELLANEOUS_SYMBOLS", new String[] {"Miscellaneous Symbols",
- "MiscellaneousSymbols"});
+ new UnicodeBlock("MISCELLANEOUS_SYMBOLS",
+ "MISCELLANEOUS SYMBOLS",
+ "MISCELLANEOUSSYMBOLS");
/**
* Constant for the "Dingbats" Unicode character block.
@@ -1042,8 +1059,9 @@
* @since 1.2
*/
public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION =
- new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", new String[] {"CJK Symbols and Punctuation",
- "CJKSymbolsandPunctuation"});
+ new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION",
+ "CJK SYMBOLS AND PUNCTUATION",
+ "CJKSYMBOLSANDPUNCTUATION");
/**
* Constant for the "Hiragana" Unicode character block.
@@ -1071,8 +1089,9 @@
* @since 1.2
*/
public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO =
- new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", new String[] {"Hangul Compatibility Jamo",
- "HangulCompatibilityJamo"});
+ new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO",
+ "HANGUL COMPATIBILITY JAMO",
+ "HANGULCOMPATIBILITYJAMO");
/**
* Constant for the "Kanbun" Unicode character block.
@@ -1086,37 +1105,45 @@
* @since 1.2
*/
public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS =
- new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", new String[] {"Enclosed CJK Letters and Months",
- "EnclosedCJKLettersandMonths"});
+ new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS",
+ "ENCLOSED CJK LETTERS AND MONTHS",
+ "ENCLOSEDCJKLETTERSANDMONTHS");
/**
* Constant for the "CJK Compatibility" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock CJK_COMPATIBILITY =
- new UnicodeBlock("CJK_COMPATIBILITY", new String[] {"CJK Compatibility", "CJKCompatibility"});
+ new UnicodeBlock("CJK_COMPATIBILITY",
+ "CJK COMPATIBILITY",
+ "CJKCOMPATIBILITY");
/**
* Constant for the "CJK Unified Ideographs" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS =
- new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", new String[] {"CJK Unified Ideographs",
- "CJKUnifiedIdeographs"});
+ new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS",
+ "CJK UNIFIED IDEOGRAPHS",
+ "CJKUNIFIEDIDEOGRAPHS");
/**
* Constant for the "Hangul Syllables" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock HANGUL_SYLLABLES =
- new UnicodeBlock("HANGUL_SYLLABLES", new String[] {"Hangul Syllables", "HangulSyllables"});
+ new UnicodeBlock("HANGUL_SYLLABLES",
+ "HANGUL SYLLABLES",
+ "HANGULSYLLABLES");
/**
* Constant for the "Private Use Area" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock PRIVATE_USE_AREA =
- new UnicodeBlock("PRIVATE_USE_AREA", new String[] {"Private Use Area", "PrivateUseArea"});
+ new UnicodeBlock("PRIVATE_USE_AREA",
+ "PRIVATE USE AREA",
+ "PRIVATEUSEAREA");
/**
* Constant for the "CJK Compatibility Ideographs" Unicode character block.
@@ -1124,56 +1151,62 @@
*/
public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS =
new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS",
- new String[] {"CJK Compatibility Ideographs",
- "CJKCompatibilityIdeographs"});
+ "CJK COMPATIBILITY IDEOGRAPHS",
+ "CJKCOMPATIBILITYIDEOGRAPHS");
/**
* Constant for the "Alphabetic Presentation Forms" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS =
- new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", new String[] {"Alphabetic Presentation Forms",
- "AlphabeticPresentationForms"});
+ new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS",
+ "ALPHABETIC PRESENTATION FORMS",
+ "ALPHABETICPRESENTATIONFORMS");
/**
* Constant for the "Arabic Presentation Forms-A" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A =
- new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", new String[] {"Arabic Presentation Forms-A",
- "ArabicPresentationForms-A"});
+ new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A",
+ "ARABIC PRESENTATION FORMS-A",
+ "ARABICPRESENTATIONFORMS-A");
/**
* Constant for the "Combining Half Marks" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock COMBINING_HALF_MARKS =
- new UnicodeBlock("COMBINING_HALF_MARKS", new String[] {"Combining Half Marks",
- "CombiningHalfMarks"});
+ new UnicodeBlock("COMBINING_HALF_MARKS",
+ "COMBINING HALF MARKS",
+ "COMBININGHALFMARKS");
/**
* Constant for the "CJK Compatibility Forms" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock CJK_COMPATIBILITY_FORMS =
- new UnicodeBlock("CJK_COMPATIBILITY_FORMS", new String[] {"CJK Compatibility Forms",
- "CJKCompatibilityForms"});
+ new UnicodeBlock("CJK_COMPATIBILITY_FORMS",
+ "CJK COMPATIBILITY FORMS",
+ "CJKCOMPATIBILITYFORMS");
/**
* Constant for the "Small Form Variants" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock SMALL_FORM_VARIANTS =
- new UnicodeBlock("SMALL_FORM_VARIANTS", new String[] {"Small Form Variants",
- "SmallFormVariants"});
+ new UnicodeBlock("SMALL_FORM_VARIANTS",
+ "SMALL FORM VARIANTS",
+ "SMALLFORMVARIANTS");
/**
* Constant for the "Arabic Presentation Forms-B" Unicode character block.
* @since 1.2
*/
public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B =
- new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", new String[] {"Arabic Presentation Forms-B",
- "ArabicPresentationForms-B"});
+ new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B",
+ "ARABIC PRESENTATION FORMS-B",
+ "ARABICPRESENTATIONFORMS-B");
/**
* Constant for the "Halfwidth and Fullwidth Forms" Unicode character block.
@@ -1181,8 +1214,8 @@
*/
public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS =
new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS",
- new String[] {"Halfwidth and Fullwidth Forms",
- "HalfwidthandFullwidthForms"});
+ "HALFWIDTH AND FULLWIDTH FORMS",
+ "HALFWIDTHANDFULLWIDTHFORMS");
/**
* Constant for the "Specials" Unicode character block.
@@ -1251,97 +1284,108 @@
*/
public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS =
new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS",
- new String[] {"Unified Canadian Aboriginal Syllabics",
- "UnifiedCanadianAboriginalSyllabics"});
+ "UNIFIED CANADIAN ABORIGINAL SYLLABICS",
+ "UNIFIEDCANADIANABORIGINALSYLLABICS");
/**
* Constant for the "Ogham" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock OGHAM =
- new UnicodeBlock("OGHAM");
+ new UnicodeBlock("OGHAM");
/**
* Constant for the "Runic" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock RUNIC =
- new UnicodeBlock("RUNIC");
+ new UnicodeBlock("RUNIC");
/**
* Constant for the "Khmer" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock KHMER =
- new UnicodeBlock("KHMER");
+ new UnicodeBlock("KHMER");
/**
* Constant for the "Mongolian" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock MONGOLIAN =
- new UnicodeBlock("MONGOLIAN");
+ new UnicodeBlock("MONGOLIAN");
/**
* Constant for the "Braille Patterns" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock BRAILLE_PATTERNS =
- new UnicodeBlock("BRAILLE_PATTERNS", new String[] {"Braille Patterns",
- "BraillePatterns"});
+ new UnicodeBlock("BRAILLE_PATTERNS",
+ "BRAILLE PATTERNS",
+ "BRAILLEPATTERNS");
/**
* Constant for the "CJK Radicals Supplement" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT =
- new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", new String[] {"CJK Radicals Supplement",
- "CJKRadicalsSupplement"});
+ new UnicodeBlock("CJK_RADICALS_SUPPLEMENT",
+ "CJK RADICALS SUPPLEMENT",
+ "CJKRADICALSSUPPLEMENT");
/**
* Constant for the "Kangxi Radicals" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock KANGXI_RADICALS =
- new UnicodeBlock("KANGXI_RADICALS", new String[] {"Kangxi Radicals", "KangxiRadicals"});
+ new UnicodeBlock("KANGXI_RADICALS",
+ "KANGXI RADICALS",
+ "KANGXIRADICALS");
/**
* Constant for the "Ideographic Description Characters" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS =
- new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", new String[] {"Ideographic Description Characters",
- "IdeographicDescriptionCharacters"});
+ new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS",
+ "IDEOGRAPHIC DESCRIPTION CHARACTERS",
+ "IDEOGRAPHICDESCRIPTIONCHARACTERS");
/**
* Constant for the "Bopomofo Extended" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock BOPOMOFO_EXTENDED =
- new UnicodeBlock("BOPOMOFO_EXTENDED", new String[] {"Bopomofo Extended",
- "BopomofoExtended"});
+ new UnicodeBlock("BOPOMOFO_EXTENDED",
+ "BOPOMOFO EXTENDED",
+ "BOPOMOFOEXTENDED");
/**
* Constant for the "CJK Unified Ideographs Extension A" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A =
- new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", new String[] {"CJK Unified Ideographs Extension A",
- "CJKUnifiedIdeographsExtensionA"});
+ new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A",
+ "CJK UNIFIED IDEOGRAPHS EXTENSION A",
+ "CJKUNIFIEDIDEOGRAPHSEXTENSIONA");
/**
* Constant for the "Yi Syllables" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock YI_SYLLABLES =
- new UnicodeBlock("YI_SYLLABLES", new String[] {"Yi Syllables", "YiSyllables"});
+ new UnicodeBlock("YI_SYLLABLES",
+ "YI SYLLABLES",
+ "YISYLLABLES");
/**
* Constant for the "Yi Radicals" Unicode character block.
* @since 1.4
*/
public static final UnicodeBlock YI_RADICALS =
- new UnicodeBlock("YI_RADICALS", new String[] {"Yi Radicals", "YiRadicals"});
+ new UnicodeBlock("YI_RADICALS",
+ "YI RADICALS",
+ "YIRADICALS");
/**
@@ -1350,10 +1394,10 @@
*/
public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY =
new UnicodeBlock("CYRILLIC_SUPPLEMENTARY",
- new String[] {"Cyrillic Supplementary",
- "CyrillicSupplementary",
- "Cyrillic Supplement",
- "CyrillicSupplement"});
+ "CYRILLIC SUPPLEMENTARY",
+ "CYRILLICSUPPLEMENTARY",
+ "CYRILLIC SUPPLEMENT",
+ "CYRILLICSUPPLEMENT");
/**
* Constant for the "Tagalog" Unicode character block.
@@ -1395,21 +1439,27 @@
* @since 1.5
*/
public static final UnicodeBlock TAI_LE =
- new UnicodeBlock("TAI_LE", new String[] {"Tai Le", "TaiLe"});
+ new UnicodeBlock("TAI_LE",
+ "TAI LE",
+ "TAILE");
/**
* Constant for the "Khmer Symbols" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock KHMER_SYMBOLS =
- new UnicodeBlock("KHMER_SYMBOLS", new String[] {"Khmer Symbols", "KhmerSymbols"});
+ new UnicodeBlock("KHMER_SYMBOLS",
+ "KHMER SYMBOLS",
+ "KHMERSYMBOLS");
/**
* Constant for the "Phonetic Extensions" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock PHONETIC_EXTENSIONS =
- new UnicodeBlock("PHONETIC_EXTENSIONS", new String[] {"Phonetic Extensions", "PhoneticExtensions"});
+ new UnicodeBlock("PHONETIC_EXTENSIONS",
+ "PHONETIC EXTENSIONS",
+ "PHONETICEXTENSIONS");
/**
* Constant for the "Miscellaneous Mathematical Symbols-A" Unicode character block.
@@ -1417,33 +1467,35 @@
*/
public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A =
new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A",
- new String[]{"Miscellaneous Mathematical Symbols-A",
- "MiscellaneousMathematicalSymbols-A"});
+ "MISCELLANEOUS MATHEMATICAL SYMBOLS-A",
+ "MISCELLANEOUSMATHEMATICALSYMBOLS-A");
/**
* Constant for the "Supplemental Arrows-A" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A =
- new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", new String[] {"Supplemental Arrows-A",
- "SupplementalArrows-A"});
+ new UnicodeBlock("SUPPLEMENTAL_ARROWS_A",
+ "SUPPLEMENTAL ARROWS-A",
+ "SUPPLEMENTALARROWS-A");
/**
* Constant for the "Supplemental Arrows-B" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B =
- new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", new String[] {"Supplemental Arrows-B",
- "SupplementalArrows-B"});
+ new UnicodeBlock("SUPPLEMENTAL_ARROWS_B",
+ "SUPPLEMENTAL ARROWS-B",
+ "SUPPLEMENTALARROWS-B");
/**
* Constant for the "Miscellaneous Mathematical Symbols-B" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B
- = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B",
- new String[] {"Miscellaneous Mathematical Symbols-B",
- "MiscellaneousMathematicalSymbols-B"});
+ public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B =
+ new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B",
+ "MISCELLANEOUS MATHEMATICAL SYMBOLS-B",
+ "MISCELLANEOUSMATHEMATICALSYMBOLS-B");
/**
* Constant for the "Supplemental Mathematical Operators" Unicode character block.
@@ -1451,127 +1503,151 @@
*/
public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS =
new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS",
- new String[]{"Supplemental Mathematical Operators",
- "SupplementalMathematicalOperators"} );
+ "SUPPLEMENTAL MATHEMATICAL OPERATORS",
+ "SUPPLEMENTALMATHEMATICALOPERATORS");
/**
* Constant for the "Miscellaneous Symbols and Arrows" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS =
- new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", new String[] {"Miscellaneous Symbols and Arrows",
- "MiscellaneousSymbolsandArrows"});
+ new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS",
+ "MISCELLANEOUS SYMBOLS AND ARROWS",
+ "MISCELLANEOUSSYMBOLSANDARROWS");
/**
* Constant for the "Katakana Phonetic Extensions" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS =
- new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", new String[] {"Katakana Phonetic Extensions",
- "KatakanaPhoneticExtensions"});
+ new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS",
+ "KATAKANA PHONETIC EXTENSIONS",
+ "KATAKANAPHONETICEXTENSIONS");
/**
* Constant for the "Yijing Hexagram Symbols" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS =
- new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", new String[] {"Yijing Hexagram Symbols",
- "YijingHexagramSymbols"});
+ new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS",
+ "YIJING HEXAGRAM SYMBOLS",
+ "YIJINGHEXAGRAMSYMBOLS");
/**
* Constant for the "Variation Selectors" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock VARIATION_SELECTORS =
- new UnicodeBlock("VARIATION_SELECTORS", new String[] {"Variation Selectors", "VariationSelectors"});
+ new UnicodeBlock("VARIATION_SELECTORS",
+ "VARIATION SELECTORS",
+ "VARIATIONSELECTORS");
/**
* Constant for the "Linear B Syllabary" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock LINEAR_B_SYLLABARY =
- new UnicodeBlock("LINEAR_B_SYLLABARY", new String[] {"Linear B Syllabary", "LinearBSyllabary"});
+ new UnicodeBlock("LINEAR_B_SYLLABARY",
+ "LINEAR B SYLLABARY",
+ "LINEARBSYLLABARY");
/**
* Constant for the "Linear B Ideograms" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock LINEAR_B_IDEOGRAMS =
- new UnicodeBlock("LINEAR_B_IDEOGRAMS", new String[] {"Linear B Ideograms", "LinearBIdeograms"});
+ new UnicodeBlock("LINEAR_B_IDEOGRAMS",
+ "LINEAR B IDEOGRAMS",
+ "LINEARBIDEOGRAMS");
/**
* Constant for the "Aegean Numbers" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock AEGEAN_NUMBERS =
- new UnicodeBlock("AEGEAN_NUMBERS", new String[] {"Aegean Numbers", "AegeanNumbers"});
+ new UnicodeBlock("AEGEAN_NUMBERS",
+ "AEGEAN NUMBERS",
+ "AEGEANNUMBERS");
/**
* Constant for the "Old Italic" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock OLD_ITALIC =
- new UnicodeBlock("OLD_ITALIC", new String[] {"Old Italic", "OldItalic"});
+ new UnicodeBlock("OLD_ITALIC",
+ "OLD ITALIC",
+ "OLDITALIC");
/**
* Constant for the "Gothic" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+ public static final UnicodeBlock GOTHIC =
+ new UnicodeBlock("GOTHIC");
/**
* Constant for the "Ugaritic" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+ public static final UnicodeBlock UGARITIC =
+ new UnicodeBlock("UGARITIC");
/**
* Constant for the "Deseret" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+ public static final UnicodeBlock DESERET =
+ new UnicodeBlock("DESERET");
/**
* Constant for the "Shavian" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+ public static final UnicodeBlock SHAVIAN =
+ new UnicodeBlock("SHAVIAN");
/**
* Constant for the "Osmanya" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+ public static final UnicodeBlock OSMANYA =
+ new UnicodeBlock("OSMANYA");
/**
* Constant for the "Cypriot Syllabary" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock CYPRIOT_SYLLABARY =
- new UnicodeBlock("CYPRIOT_SYLLABARY", new String[] {"Cypriot Syllabary", "CypriotSyllabary"});
+ new UnicodeBlock("CYPRIOT_SYLLABARY",
+ "CYPRIOT SYLLABARY",
+ "CYPRIOTSYLLABARY");
/**
* Constant for the "Byzantine Musical Symbols" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS =
- new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", new String[] {"Byzantine Musical Symbols",
- "ByzantineMusicalSymbols"});
+ new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS",
+ "BYZANTINE MUSICAL SYMBOLS",
+ "BYZANTINEMUSICALSYMBOLS");
/**
* Constant for the "Musical Symbols" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock MUSICAL_SYMBOLS =
- new UnicodeBlock("MUSICAL_SYMBOLS", new String[] {"Musical Symbols", "MusicalSymbols"});
+ new UnicodeBlock("MUSICAL_SYMBOLS",
+ "MUSICAL SYMBOLS",
+ "MUSICALSYMBOLS");
/**
* Constant for the "Tai Xuan Jing Symbols" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS =
- new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", new String[] {"Tai Xuan Jing Symbols",
- "TaiXuanJingSymbols"});
+ new UnicodeBlock("TAI_XUAN_JING_SYMBOLS",
+ "TAI XUAN JING SYMBOLS",
+ "TAIXUANJINGSYMBOLS");
/**
* Constant for the "Mathematical Alphanumeric Symbols" Unicode character block.
@@ -1579,7 +1655,8 @@
*/
public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS =
new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS",
- new String[] {"Mathematical Alphanumeric Symbols", "MathematicalAlphanumericSymbols"});
+ "MATHEMATICAL ALPHANUMERIC SYMBOLS",
+ "MATHEMATICALALPHANUMERICSYMBOLS");
/**
* Constant for the "CJK Unified Ideographs Extension B" Unicode character block.
@@ -1587,7 +1664,8 @@
*/
public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B =
new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B",
- new String[] {"CJK Unified Ideographs Extension B", "CJKUnifiedIdeographsExtensionB"});
+ "CJK UNIFIED IDEOGRAPHS EXTENSION B",
+ "CJKUNIFIEDIDEOGRAPHSEXTENSIONB");
/**
* Constant for the "CJK Compatibility Ideographs Supplement" Unicode character block.
@@ -1595,22 +1673,24 @@
*/
public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT =
new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT",
- new String[]{"CJK Compatibility Ideographs Supplement",
- "CJKCompatibilityIdeographsSupplement"});
+ "CJK COMPATIBILITY IDEOGRAPHS SUPPLEMENT",
+ "CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT");
/**
* Constant for the "Tags" Unicode character block.
* @since 1.5
*/
- public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+ public static final UnicodeBlock TAGS =
+ new UnicodeBlock("TAGS");
/**
* Constant for the "Variation Selectors Supplement" Unicode character block.
* @since 1.5
*/
public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT =
- new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", new String[] {"Variation Selectors Supplement",
- "VariationSelectorsSupplement"});
+ new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT",
+ "VARIATION SELECTORS SUPPLEMENT",
+ "VARIATIONSELECTORSSUPPLEMENT");
/**
* Constant for the "Supplementary Private Use Area-A" Unicode character block.
@@ -1618,8 +1698,8 @@
*/
public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A =
new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A",
- new String[] {"Supplementary Private Use Area-A",
- "SupplementaryPrivateUseArea-A"});
+ "SUPPLEMENTARY PRIVATE USE AREA-A",
+ "SUPPLEMENTARYPRIVATEUSEAREA-A");
/**
* Constant for the "Supplementary Private Use Area-B" Unicode character block.
@@ -1627,39 +1707,44 @@
*/
public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B =
new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B",
- new String[] {"Supplementary Private Use Area-B",
- "SupplementaryPrivateUseArea-B"});
+ "SUPPLEMENTARY PRIVATE USE AREA-B",
+ "SUPPLEMENTARYPRIVATEUSEAREA-B");
/**
* Constant for the "High Surrogates" Unicode character block.
* This block represents codepoint values in the high surrogate
- * range: 0xD800 through 0xDB7F
+ * range: U+D800 through U+DB7F
*
* @since 1.5
*/
public static final UnicodeBlock HIGH_SURROGATES =
- new UnicodeBlock("HIGH_SURROGATES", new String[] {"High Surrogates", "HighSurrogates"});
+ new UnicodeBlock("HIGH_SURROGATES",
+ "HIGH SURROGATES",
+ "HIGHSURROGATES");
/**
* Constant for the "High Private Use Surrogates" Unicode character block.
- * This block represents codepoint values in the high surrogate
- * range: 0xDB80 through 0xDBFF
+ * This block represents codepoint values in the private use high surrogate
+ * range: U+DB80 through U+DBFF
*
* @since 1.5
*/
public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES =
- new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", new String[] { "High Private Use Surrogates",
- "HighPrivateUseSurrogates"});
+ new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES",
+ "HIGH PRIVATE USE SURROGATES",
+ "HIGHPRIVATEUSESURROGATES");
/**
* Constant for the "Low Surrogates" Unicode character block.
- * This block represents codepoint values in the high surrogate
- * range: 0xDC00 through 0xDFFF
+ * This block represents codepoint values in the low surrogate
+ * range: U+DC00 through U+DFFF
*
* @since 1.5
*/
public static final UnicodeBlock LOW_SURROGATES =
- new UnicodeBlock("LOW_SURROGATES", new String[] {"Low Surrogates", "LowSurrogates"});
+ new UnicodeBlock("LOW_SURROGATES",
+ "LOW SURROGATES",
+ "LOWSURROGATES");
/**
* Constant for the "Arabic Supplement" Unicode character block.
@@ -1667,14 +1752,15 @@
*/
public static final UnicodeBlock ARABIC_SUPPLEMENT =
new UnicodeBlock("ARABIC_SUPPLEMENT",
- new String[] { "Arabic Supplement",
- "ArabicSupplement"});
+ "ARABIC SUPPLEMENT",
+ "ARABICSUPPLEMENT");
/**
* Constant for the "NKo" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock NKO = new UnicodeBlock("NKO");
+ public static final UnicodeBlock NKO =
+ new UnicodeBlock("NKO");
/**
* Constant for the "Ethiopic Supplement" Unicode character block.
@@ -1682,8 +1768,8 @@
*/
public static final UnicodeBlock ETHIOPIC_SUPPLEMENT =
new UnicodeBlock("ETHIOPIC_SUPPLEMENT",
- new String[] { "Ethiopic Supplement",
- "EthiopicSupplement"});
+ "ETHIOPIC SUPPLEMENT",
+ "ETHIOPICSUPPLEMENT");
/**
* Constant for the "New Tai Lue" Unicode character block.
@@ -1691,8 +1777,8 @@
*/
public static final UnicodeBlock NEW_TAI_LUE =
new UnicodeBlock("NEW_TAI_LUE",
- new String[] { "New Tai Lue",
- "NewTaiLue"});
+ "NEW TAI LUE",
+ "NEWTAILUE");
/**
* Constant for the "Buginese" Unicode character block.
@@ -1719,7 +1805,8 @@
* Constant for the "Lepcha" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock LEPCHA = new UnicodeBlock("LEPCHA");
+ public static final UnicodeBlock LEPCHA =
+ new UnicodeBlock("LEPCHA");
/**
* Constant for the "Ol Chiki" Unicode character block.
@@ -1727,8 +1814,8 @@
*/
public static final UnicodeBlock OL_CHIKI =
new UnicodeBlock("OL_CHIKI",
- new String[] { "Ol Chiki",
- "OlChiki"});
+ "OL CHIKI",
+ "OLCHIKI");
/**
* Constant for the "Phonetic Extensions Supplement" Unicode character
@@ -1737,8 +1824,8 @@
*/
public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT =
new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT",
- new String[] { "Phonetic Extensions Supplement",
- "PhoneticExtensionsSupplement"});
+ "PHONETIC EXTENSIONS SUPPLEMENT",
+ "PHONETICEXTENSIONSSUPPLEMENT");
/**
* Constant for the "Combining Diacritical Marks Supplement" Unicode
@@ -1747,8 +1834,8 @@
*/
public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT =
new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT",
- new String[] { "Combining Diacritical Marks Supplement",
- "CombiningDiacriticalMarksSupplement"});
+ "COMBINING DIACRITICAL MARKS SUPPLEMENT",
+ "COMBININGDIACRITICALMARKSSUPPLEMENT");
/**
* Constant for the "Glagolitic" Unicode character block.
@@ -1763,14 +1850,15 @@
*/
public static final UnicodeBlock LATIN_EXTENDED_C =
new UnicodeBlock("LATIN_EXTENDED_C",
- new String[] { "Latin Extended-C",
- "LatinExtended-C"});
+ "LATIN EXTENDED-C",
+ "LATINEXTENDED-C");
/**
* Constant for the "Coptic" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock COPTIC = new UnicodeBlock("COPTIC");
+ public static final UnicodeBlock COPTIC =
+ new UnicodeBlock("COPTIC");
/**
* Constant for the "Georgian Supplement" Unicode character block.
@@ -1778,8 +1866,8 @@
*/
public static final UnicodeBlock GEORGIAN_SUPPLEMENT =
new UnicodeBlock("GEORGIAN_SUPPLEMENT",
- new String[] { "Georgian Supplement",
- "GeorgianSupplement"});
+ "GEORGIAN SUPPLEMENT",
+ "GEORGIANSUPPLEMENT");
/**
* Constant for the "Tifinagh" Unicode character block.
@@ -1794,8 +1882,8 @@
*/
public static final UnicodeBlock ETHIOPIC_EXTENDED =
new UnicodeBlock("ETHIOPIC_EXTENDED",
- new String[] { "Ethiopic Extended",
- "EthiopicExtended"});
+ "ETHIOPIC EXTENDED",
+ "ETHIOPICEXTENDED");
/**
* Constant for the "Cyrillic Extended-A" Unicode character block.
@@ -1803,8 +1891,8 @@
*/
public static final UnicodeBlock CYRILLIC_EXTENDED_A =
new UnicodeBlock("CYRILLIC_EXTENDED_A",
- new String[] { "Cyrillic Extended-A",
- "CyrillicExtended-A"});
+ "CYRILLIC EXTENDED-A",
+ "CYRILLICEXTENDED-A");
/**
* Constant for the "Supplemental Punctuation" Unicode character block.
@@ -1812,8 +1900,8 @@
*/
public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION =
new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION",
- new String[] { "Supplemental Punctuation",
- "SupplementalPunctuation"});
+ "SUPPLEMENTAL PUNCTUATION",
+ "SUPPLEMENTALPUNCTUATION");
/**
* Constant for the "CJK Strokes" Unicode character block.
@@ -1821,14 +1909,15 @@
*/
public static final UnicodeBlock CJK_STROKES =
new UnicodeBlock("CJK_STROKES",
- new String[] { "CJK Strokes",
- "CJKStrokes"});
+ "CJK STROKES",
+ "CJKSTROKES");
/**
* Constant for the "Vai" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock VAI = new UnicodeBlock("VAI");
+ public static final UnicodeBlock VAI =
+ new UnicodeBlock("VAI");
/**
* Constant for the "Cyrillic Extended-B" Unicode character block.
@@ -1836,8 +1925,8 @@
*/
public static final UnicodeBlock CYRILLIC_EXTENDED_B =
new UnicodeBlock("CYRILLIC_EXTENDED_B",
- new String[] { "Cyrillic Extended-B",
- "CyrillicExtended-B"});
+ "CYRILLIC EXTENDED-B",
+ "CYRILLICEXTENDED-B");
/**
* Constant for the "Modifier Tone Letters" Unicode character block.
@@ -1845,8 +1934,8 @@
*/
public static final UnicodeBlock MODIFIER_TONE_LETTERS =
new UnicodeBlock("MODIFIER_TONE_LETTERS",
- new String[] { "Modifier Tone Letters",
- "ModifierToneLetters"});
+ "MODIFIER TONE LETTERS",
+ "MODIFIERTONELETTERS");
/**
* Constant for the "Latin Extended-D" Unicode character block.
@@ -1854,8 +1943,8 @@
*/
public static final UnicodeBlock LATIN_EXTENDED_D =
new UnicodeBlock("LATIN_EXTENDED_D",
- new String[] { "Latin Extended-D",
- "LatinExtended-D"});
+ "LATIN EXTENDED-D",
+ "LATINEXTENDED-D");
/**
* Constant for the "Syloti Nagri" Unicode character block.
@@ -1863,15 +1952,16 @@
*/
public static final UnicodeBlock SYLOTI_NAGRI =
new UnicodeBlock("SYLOTI_NAGRI",
- new String[] { "Syloti Nagri",
- "SylotiNagri"});
+ "SYLOTI NAGRI",
+ "SYLOTINAGRI");
/**
* Constant for the "Phags-pa" Unicode character block.
* @since 1.7
*/
public static final UnicodeBlock PHAGS_PA =
- new UnicodeBlock("PHAGS_PA", new String[] { "Phags-pa"});
+ new UnicodeBlock("PHAGS_PA",
+ "PHAGS-PA");
/**
* Constant for the "Saurashtra" Unicode character block.
@@ -1886,20 +1976,22 @@
*/
public static final UnicodeBlock KAYAH_LI =
new UnicodeBlock("KAYAH_LI",
- new String[] { "Kayah Li",
- "KayahLi"});
+ "KAYAH LI",
+ "KAYAHLI");
/**
* Constant for the "Rejang" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock REJANG = new UnicodeBlock("REJANG");
+ public static final UnicodeBlock REJANG =
+ new UnicodeBlock("REJANG");
/**
* Constant for the "Cham" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock CHAM = new UnicodeBlock("CHAM");
+ public static final UnicodeBlock CHAM =
+ new UnicodeBlock("CHAM");
/**
* Constant for the "Vertical Forms" Unicode character block.
@@ -1907,8 +1999,8 @@
*/
public static final UnicodeBlock VERTICAL_FORMS =
new UnicodeBlock("VERTICAL_FORMS",
- new String[] { "Vertical Forms",
- "VerticalForms"});
+ "VERTICAL FORMS",
+ "VERTICALFORMS");
/**
* Constant for the "Ancient Greek Numbers" Unicode character block.
@@ -1916,8 +2008,8 @@
*/
public static final UnicodeBlock ANCIENT_GREEK_NUMBERS =
new UnicodeBlock("ANCIENT_GREEK_NUMBERS",
- new String[] { "Ancient Greek Numbers",
- "AncientGreekNumbers"});
+ "ANCIENT GREEK NUMBERS",
+ "ANCIENTGREEKNUMBERS");
/**
* Constant for the "Ancient Symbols" Unicode character block.
@@ -1925,8 +2017,8 @@
*/
public static final UnicodeBlock ANCIENT_SYMBOLS =
new UnicodeBlock("ANCIENT_SYMBOLS",
- new String[] { "Ancient Symbols",
- "AncientSymbols"});
+ "ANCIENT SYMBOLS",
+ "ANCIENTSYMBOLS");
/**
* Constant for the "Phaistos Disc" Unicode character block.
@@ -1934,20 +2026,22 @@
*/
public static final UnicodeBlock PHAISTOS_DISC =
new UnicodeBlock("PHAISTOS_DISC",
- new String[] { "Phaistos Disc",
- "PhaistosDisc"});
+ "PHAISTOS DISC",
+ "PHAISTOSDISC");
/**
* Constant for the "Lycian" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock LYCIAN = new UnicodeBlock("LYCIAN");
+ public static final UnicodeBlock LYCIAN =
+ new UnicodeBlock("LYCIAN");
/**
* Constant for the "Carian" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock CARIAN = new UnicodeBlock("CARIAN");
+ public static final UnicodeBlock CARIAN =
+ new UnicodeBlock("CARIAN");
/**
* Constant for the "Old Persian" Unicode character block.
@@ -1955,8 +2049,8 @@
*/
public static final UnicodeBlock OLD_PERSIAN =
new UnicodeBlock("OLD_PERSIAN",
- new String[] { "Old Persian",
- "OldPersian"});
+ "OLD PERSIAN",
+ "OLDPERSIAN");
/**
* Constant for the "Phoenician" Unicode character block.
@@ -1969,7 +2063,8 @@
* Constant for the "Lydian" Unicode character block.
* @since 1.7
*/
- public static final UnicodeBlock LYDIAN = new UnicodeBlock("LYDIAN");
+ public static final UnicodeBlock LYDIAN =
+ new UnicodeBlock("LYDIAN");
/**
* Constant for the "Kharoshthi" Unicode character block.
@@ -1992,8 +2087,8 @@
*/
public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION =
new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION",
- new String[] { "Cuneiform Numbers and Punctuation",
- "CuneiformNumbersandPunctuation"});
+ "CUNEIFORM NUMBERS AND PUNCTUATION",
+ "CUNEIFORMNUMBERSANDPUNCTUATION");
/**
* Constant for the "Ancient Greek Musical Notation" Unicode character
@@ -2002,8 +2097,8 @@
*/
public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION =
new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION",
- new String[] { "Ancient Greek Musical Notation",
- "AncientGreekMusicalNotation"});
+ "ANCIENT GREEK MUSICAL NOTATION",
+ "ANCIENTGREEKMUSICALNOTATION");
/**
* Constant for the "Counting Rod Numerals" Unicode character block.
@@ -2011,8 +2106,8 @@
*/
public static final UnicodeBlock COUNTING_ROD_NUMERALS =
new UnicodeBlock("COUNTING_ROD_NUMERALS",
- new String[] { "Counting Rod Numerals",
- "CountingRodNumerals"});
+ "COUNTING ROD NUMERALS",
+ "COUNTINGRODNUMERALS");
/**
* Constant for the "Mahjong Tiles" Unicode character block.
@@ -2020,8 +2115,8 @@
*/
public static final UnicodeBlock MAHJONG_TILES =
new UnicodeBlock("MAHJONG_TILES",
- new String[] { "Mahjong Tiles",
- "MahjongTiles"});
+ "MAHJONG TILES",
+ "MAHJONGTILES");
/**
* Constant for the "Domino Tiles" Unicode character block.
@@ -2029,8 +2124,8 @@
*/
public static final UnicodeBlock DOMINO_TILES =
new UnicodeBlock("DOMINO_TILES",
- new String[] { "Domino Tiles",
- "DominoTiles"});
+ "DOMINO TILES",
+ "DOMINOTILES");
private static final int blockStarts[] = {
0x0000, // 0000..007F; Basic Latin
@@ -2046,7 +2141,7 @@
0x0530, // 0530..058F; Armenian
0x0590, // 0590..05FF; Hebrew
0x0600, // 0600..06FF; Arabic
- 0x0700, // 0700..074F; Syria
+ 0x0700, // 0700..074F; Syriac
0x0750, // 0750..077F; Arabic Supplement
0x0780, // 0780..07BF; Thaana
0x07C0, // 07C0..07FF; NKo
@@ -2446,11 +2541,10 @@
* given character, or <code>null</code> if the character is not a
* member of a defined block.
*
- * <p><b>Note:</b> This method cannot handle <a
- * href="Character.html#supplementary"> supplementary
- * characters</a>. To support all Unicode characters,
- * including supplementary characters, use the {@link
- * #of(int)} method.
+ * <p><b>Note:</b> This method cannot handle
+ * <a href="Character.html#supplementary"> supplementary
+ * characters</a>. To support all Unicode characters, including
+ * supplementary characters, use the {@link #of(int)} method.
*
* @param c The character in question
* @return The <code>UnicodeBlock</code> instance representing the
@@ -2462,22 +2556,21 @@
return of((int)c);
}
-
/**
* Returns the object representing the Unicode block
* containing the given character (Unicode code point), or
* <code>null</code> if the character is not a member of a
* defined block.
*
- * @param codePoint the character (Unicode code point) in question.
+ * @param codePoint the character (Unicode code point) in question.
* @return The <code>UnicodeBlock</code> instance representing the
* Unicode block of which this character is a member, or
* <code>null</code> if the character is not a member of any
* Unicode block
- * @exception IllegalArgumentException if the specified
- * <code>codePoint</code> is an invalid Unicode code point.
- * @see Character#isValidCodePoint(int)
- * @since 1.5
+ * @exception IllegalArgumentException if the specified
+ * <code>codePoint</code> is an invalid Unicode code point.
+ * @see Character#isValidCodePoint(int)
+ * @since 1.5
*/
public static UnicodeBlock of(int codePoint) {
if (!isValidCodePoint(codePoint)) {
@@ -2519,7 +2612,7 @@
* <li>The text representation of each constant UnicodeBlock identifier.
* For example, this method will return the {@link #BASIC_LATIN} block if
* provided with the "BASIC_LATIN" name. This form replaces all spaces and
- * hyphens in the canonical name with underscores.
+ * hyphens in the canonical name with underscores.
* </ol>
* Finally, character case is ignored for all of the valid block name forms.
* For example, "BASIC_LATIN" and "basic_latin" are both valid block names.
@@ -2538,7 +2631,7 @@
* @since 1.5
*/
public static final UnicodeBlock forName(String blockName) {
- UnicodeBlock block = (UnicodeBlock)map.get(blockName.toUpperCase(Locale.US));
+ UnicodeBlock block = map.get(blockName.toUpperCase(Locale.US));
if (block == null) {
throw new IllegalArgumentException();
}
@@ -3627,7 +3720,7 @@
private static HashMap<String, Character.UnicodeScript> aliases;
static {
- aliases = new HashMap<String, UnicodeScript>();
+ aliases = new HashMap<String, UnicodeScript>(128);
aliases.put("ARAB", ARABIC);
aliases.put("ARMI", IMPERIAL_ARAMAIC);
aliases.put("ARMN", ARMENIAN);
@@ -3809,7 +3902,7 @@
static final Character cache[] = new Character[127 + 1];
static {
- for(int i = 0; i < cache.length; i++)
+ for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}
@@ -3832,7 +3925,7 @@
* @since 1.5
*/
public static Character valueOf(char c) {
- if(c <= 127) { // must cache
+ if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
@@ -3914,7 +4007,29 @@
* @since 1.5
*/
public static boolean isValidCodePoint(int codePoint) {
- return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT;
+ // Optimized form of:
+ // codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
+ int plane = codePoint >>> 16;
+ return plane < ((MAX_CODE_POINT + 1) >>> 16);
+ }
+
+ /**
+ * Determines whether the specified character (Unicode code point)
+ * is in the <a href="#BMP">Basic Multilingual Plane (BMP)</a>.
+ * Such code points can be represented using a single {@code char}.
+ *
+ * @param codePoint the character (Unicode code point) to be tested
+ * @return {@code true} if the specified code point is between
+ * {@link #MIN_VALUE} and {@link #MAX_VALUE} inclusive;
+ * {@code false} otherwise.
+ * @since 1.7
+ */
+ public static boolean isBmpCodePoint(int codePoint) {
+ return codePoint >>> 16 == 0;
+ // Optimized form of:
+ // codePoint >= MIN_VALUE && codePoint <= MAX_VALUE
+ // We consistently use logical shift (>>>) to facilitate
+ // additional runtime optimizations.
}
/**
@@ -3930,7 +4045,7 @@
*/
public static boolean isSupplementaryCodePoint(int codePoint) {
return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT
- && codePoint <= MAX_CODE_POINT;
+ && codePoint < MAX_CODE_POINT + 1;
}
/**
@@ -3949,12 +4064,13 @@
* {@link #MIN_HIGH_SURROGATE} and
* {@link #MAX_HIGH_SURROGATE} inclusive;
* {@code false} otherwise.
- * @see #isLowSurrogate(char)
+ * @see Character#isLowSurrogate(char)
* @see Character.UnicodeBlock#of(int)
* @since 1.5
*/
public static boolean isHighSurrogate(char ch) {
- return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE;
+ // Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE
+ return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
}
/**
@@ -3973,11 +4089,11 @@
* {@link #MIN_LOW_SURROGATE} and
* {@link #MAX_LOW_SURROGATE} inclusive;
* {@code false} otherwise.
- * @see #isHighSurrogate(char)
+ * @see Character#isHighSurrogate(char)
* @since 1.5
*/
public static boolean isLowSurrogate(char ch) {
- return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE;
+ return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1);
}
/**
@@ -4001,7 +4117,7 @@
* @since 1.7
*/
public static boolean isSurrogate(char ch) {
- return ch >= MIN_SURROGATE && ch <= MAX_SURROGATE;
+ return ch >= MIN_SURROGATE && ch < (MAX_SURROGATE + 1);
}
/**
@@ -4039,11 +4155,11 @@
*
* @param codePoint the character (Unicode code point) to be tested.
* @return 2 if the character is a valid supplementary character; 1 otherwise.
- * @see #isSupplementaryCodePoint(int)
+ * @see Character#isSupplementaryCodePoint(int)
* @since 1.5
*/
public static int charCount(int codePoint) {
- return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT? 2 : 1;
+ return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1;
}
/**
@@ -4160,6 +4276,7 @@
return codePointAtImpl(a, index, limit);
}
+ // throws ArrayIndexOutofBoundsException if index out of bounds
static int codePointAtImpl(char[] a, int index, int limit) {
char c1 = a[index++];
if (isHighSurrogate(c1)) {
@@ -4266,6 +4383,7 @@
return codePointBeforeImpl(a, index, start);
}
+ // throws ArrayIndexOutofBoundsException if index-1 out of bounds
static int codePointBeforeImpl(char[] a, int index, int start) {
char c2 = a[--index];
if (isLowSurrogate(c2)) {
@@ -4280,6 +4398,63 @@
}
/**
+ * Returns the leading surrogate (a
+ * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
+ * high surrogate code unit</a>) of the
+ * <a href="http://www.unicode.org/glossary/#surrogate_pair">
+ * surrogate pair</a>
+ * representing the specified supplementary character (Unicode
+ * code point) in the UTF-16 encoding. If the specified character
+ * is not a
+ * <a href="Character.html#supplementary">supplementary character</a>,
+ * an unspecified {@code char} is returned.
+ *
+ * <p>If
+ * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)}
+ * is {@code true}, then
+ * {@link #isHighSurrogate isHighSurrogate}{@code (highSurrogate(x))} and
+ * {@link #toCodePoint toCodePoint}{@code (highSurrogate(x), }{@link #lowSurrogate lowSurrogate}{@code (x)) == x}
+ * are also always {@code true}.
+ *
+ * @param codePoint a supplementary character (Unicode code point)
+ * @return the leading surrogate code unit used to represent the
+ * character in the UTF-16 encoding
+ * @since 1.7
+ */
+ public static char highSurrogate(int codePoint) {
+ return (char) ((codePoint >>> 10)
+ + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
+ }
+
+ /**
+ * Returns the trailing surrogate (a
+ * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
+ * low surrogate code unit</a>) of the
+ * <a href="http://www.unicode.org/glossary/#surrogate_pair">
+ * surrogate pair</a>
+ * representing the specified supplementary character (Unicode
+ * code point) in the UTF-16 encoding. If the specified character
+ * is not a
+ * <a href="Character.html#supplementary">supplementary character</a>,
+ * an unspecified {@code char} is returned.
+ *
+ * <p>If
+ * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)}
+ * is {@code true}, then
+ * {@link #isLowSurrogate isLowSurrogate}{@code (lowSurrogate(x))} and
+ * {@link #toCodePoint toCodePoint}{@code (}{@link #highSurrogate highSurrogate}{@code (x), lowSurrogate(x)) == x}
+ * are also always {@code true}.
+ *
+ * @param codePoint a supplementary character (Unicode code point)
+ * @return the trailing surrogate code unit used to represent the
+ * character in the UTF-16 encoding
+ * @since 1.7
+ */
+ public static char lowSurrogate(int codePoint) {
+ return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
+ }
+
+ /**
* Converts the specified character (Unicode code point) to its
* UTF-16 representation. If the specified code point is a BMP
* (Basic Multilingual Plane or Plane 0) value, the same value is
@@ -4311,15 +4486,15 @@
* @since 1.5
*/
public static int toChars(int codePoint, char[] dst, int dstIndex) {
- if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
+ if (isBmpCodePoint(codePoint)) {
+ dst[dstIndex] = (char) codePoint;
+ return 1;
+ } else if (isValidCodePoint(codePoint)) {
+ toSurrogates(codePoint, dst, dstIndex);
+ return 2;
+ } else {
throw new IllegalArgumentException();
}
- if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
- dst[dstIndex] = (char) codePoint;
- return 1;
- }
- toSurrogates(codePoint, dst, dstIndex);
- return 2;
}
/**
@@ -4339,22 +4514,21 @@
* @since 1.5
*/
public static char[] toChars(int codePoint) {
- if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
+ if (isBmpCodePoint(codePoint)) {
+ return new char[] { (char) codePoint };
+ } else if (isValidCodePoint(codePoint)) {
+ char[] result = new char[2];
+ toSurrogates(codePoint, result, 0);
+ return result;
+ } else {
throw new IllegalArgumentException();
}
- if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
- return new char[] { (char) codePoint };
- }
- char[] result = new char[2];
- toSurrogates(codePoint, result, 0);
- return result;
}
static void toSurrogates(int codePoint, char[] dst, int index) {
// We write elements "backwards" to guarantee all-or-nothing
- dst[index+1] = (char)((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
- dst[index] = (char)((codePoint >>> 10)
- + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
+ dst[index+1] = lowSurrogate(codePoint);
+ dst[index] = highSurrogate(codePoint);
}
/**
@@ -4385,13 +4559,12 @@
if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) {
throw new IndexOutOfBoundsException();
}
- int n = 0;
+ int n = endIndex - beginIndex;
for (int i = beginIndex; i < endIndex; ) {
- n++;
- if (isHighSurrogate(seq.charAt(i++))) {
- if (i < endIndex && isLowSurrogate(seq.charAt(i))) {
- i++;
- }
+ if (isHighSurrogate(seq.charAt(i++)) && i < endIndex &&
+ isLowSurrogate(seq.charAt(i))) {
+ n--;
+ i++;
}
}
return n;
@@ -4425,13 +4598,12 @@
static int codePointCountImpl(char[] a, int offset, int count) {
int endIndex = offset + count;
- int n = 0;
+ int n = count;
for (int i = offset; i < endIndex; ) {
- n++;
- if (isHighSurrogate(a[i++])) {
- if (i < endIndex && isLowSurrogate(a[i])) {
- i++;
- }
+ if (isHighSurrogate(a[i++]) && i < endIndex &&
+ isLowSurrogate(a[i])) {
+ n--;
+ i++;
}
}
return n;
@@ -4470,10 +4642,9 @@
if (codePointOffset >= 0) {
int i;
for (i = 0; x < length && i < codePointOffset; i++) {
- if (isHighSurrogate(seq.charAt(x++))) {
- if (x < length && isLowSurrogate(seq.charAt(x))) {
- x++;
- }
+ if (isHighSurrogate(seq.charAt(x++)) && x < length &&
+ isLowSurrogate(seq.charAt(x))) {
+ x++;
}
}
if (i < codePointOffset) {
@@ -4482,10 +4653,9 @@
} else {
int i;
for (i = codePointOffset; x > 0 && i < 0; i++) {
- if (isLowSurrogate(seq.charAt(--x))) {
- if (x > 0 && isHighSurrogate(seq.charAt(x-1))) {
- x--;
- }
+ if (isLowSurrogate(seq.charAt(--x)) && x > 0 &&
+ isHighSurrogate(seq.charAt(x-1))) {
+ x--;
}
}
if (i < 0) {
@@ -4544,10 +4714,9 @@
int limit = start + count;
int i;
for (i = 0; x < limit && i < codePointOffset; i++) {
- if (isHighSurrogate(a[x++])) {
- if (x < limit && isLowSurrogate(a[x])) {
- x++;
- }
+ if (isHighSurrogate(a[x++]) && x < limit &&
+ isLowSurrogate(a[x])) {
+ x++;
}
}
if (i < codePointOffset) {
@@ -4556,10 +4725,9 @@
} else {
int i;
for (i = codePointOffset; x > start && i < 0; i++) {
- if (isLowSurrogate(a[--x])) {
- if (x > start && isHighSurrogate(a[x-1])) {
- x--;
- }
+ if (isLowSurrogate(a[--x]) && x > start &&
+ isHighSurrogate(a[x-1])) {
+ x--;
}
}
if (i < 0) {
@@ -4569,7 +4737,7 @@
return x;
}
- /**
+ /**
* Determines if the specified character is a lowercase character.
* <p>
* A character is lowercase if its general category type, provided
@@ -4594,10 +4762,10 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is lowercase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isTitleCase(char)
- * @see java.lang.Character#toLowerCase(char)
- * @see java.lang.Character#getType(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isTitleCase(char)
+ * @see Character#toLowerCase(char)
+ * @see Character#getType(char)
*/
public static boolean isLowerCase(char ch) {
return isLowerCase((int)ch);
@@ -4624,17 +4792,17 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is lowercase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.Character#isTitleCase(int)
- * @see java.lang.Character#toLowerCase(int)
- * @see java.lang.Character#getType(int)
+ * @see Character#isLowerCase(int)
+ * @see Character#isTitleCase(int)
+ * @see Character#toLowerCase(int)
+ * @see Character#getType(int)
* @since 1.5
*/
public static boolean isLowerCase(int codePoint) {
return getType(codePoint) == Character.LOWERCASE_LETTER;
}
- /**
+ /**
* Determines if the specified character is an uppercase character.
* <p>
* A character is uppercase if its general category type, provided by
@@ -4658,10 +4826,10 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is uppercase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isTitleCase(char)
- * @see java.lang.Character#toUpperCase(char)
- * @see java.lang.Character#getType(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isTitleCase(char)
+ * @see Character#toUpperCase(char)
+ * @see Character#getType(char)
* @since 1.0
*/
public static boolean isUpperCase(char ch) {
@@ -4687,10 +4855,10 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is uppercase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.Character#isTitleCase(int)
- * @see java.lang.Character#toUpperCase(int)
- * @see java.lang.Character#getType(int)
+ * @see Character#isLowerCase(int)
+ * @see Character#isTitleCase(int)
+ * @see Character#toUpperCase(int)
+ * @see Character#getType(int)
* @since 1.5
*/
public static boolean isUpperCase(int codePoint) {
@@ -4728,10 +4896,10 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is titlecase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isUpperCase(char)
- * @see java.lang.Character#toTitleCase(char)
- * @see java.lang.Character#getType(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isUpperCase(char)
+ * @see Character#toTitleCase(char)
+ * @see Character#getType(char)
* @since 1.0.2
*/
public static boolean isTitleCase(char ch) {
@@ -4764,10 +4932,10 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is titlecase;
* <code>false</code> otherwise.
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.Character#isUpperCase(int)
- * @see java.lang.Character#toTitleCase(int)
- * @see java.lang.Character#getType(int)
+ * @see Character#isLowerCase(int)
+ * @see Character#isUpperCase(int)
+ * @see Character#toTitleCase(int)
+ * @see Character#getType(int)
* @since 1.5
*/
public static boolean isTitleCase(int codePoint) {
@@ -4805,9 +4973,9 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is a digit;
* <code>false</code> otherwise.
- * @see java.lang.Character#digit(char, int)
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#getType(char)
+ * @see Character#digit(char, int)
+ * @see Character#forDigit(int, int)
+ * @see Character#getType(char)
*/
public static boolean isDigit(char ch) {
return isDigit((int)ch);
@@ -4839,8 +5007,8 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is a digit;
* <code>false</code> otherwise.
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#getType(int)
+ * @see Character#forDigit(int, int)
+ * @see Character#getType(int)
* @since 1.5
*/
public static boolean isDigit(int codePoint) {
@@ -4864,12 +5032,12 @@
* @param ch the character to be tested
* @return <code>true</code> if the character has a defined meaning
* in Unicode; <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isTitleCase(char)
- * @see java.lang.Character#isUpperCase(char)
+ * @see Character#isDigit(char)
+ * @see Character#isLetter(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isTitleCase(char)
+ * @see Character#isUpperCase(char)
* @since 1.0.2
*/
public static boolean isDefined(char ch) {
@@ -4888,12 +5056,12 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character has a defined meaning
* in Unicode; <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(int)
- * @see java.lang.Character#isLetter(int)
- * @see java.lang.Character#isLetterOrDigit(int)
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.Character#isTitleCase(int)
- * @see java.lang.Character#isUpperCase(int)
+ * @see Character#isDigit(int)
+ * @see Character#isLetter(int)
+ * @see Character#isLetterOrDigit(int)
+ * @see Character#isLowerCase(int)
+ * @see Character#isTitleCase(int)
+ * @see Character#isUpperCase(int)
* @since 1.5
*/
public static boolean isDefined(int codePoint) {
@@ -4925,15 +5093,15 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is a letter;
* <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(char)
- * @see java.lang.Character#isJavaIdentifierStart(char)
- * @see java.lang.Character#isJavaLetter(char)
- * @see java.lang.Character#isJavaLetterOrDigit(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isTitleCase(char)
- * @see java.lang.Character#isUnicodeIdentifierStart(char)
- * @see java.lang.Character#isUpperCase(char)
+ * @see Character#isDigit(char)
+ * @see Character#isJavaIdentifierStart(char)
+ * @see Character#isJavaLetter(char)
+ * @see Character#isJavaLetterOrDigit(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isTitleCase(char)
+ * @see Character#isUnicodeIdentifierStart(char)
+ * @see Character#isUpperCase(char)
*/
public static boolean isLetter(char ch) {
return isLetter((int)ch);
@@ -4959,13 +5127,13 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is a letter;
* <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(int)
- * @see java.lang.Character#isJavaIdentifierStart(int)
- * @see java.lang.Character#isLetterOrDigit(int)
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.Character#isTitleCase(int)
- * @see java.lang.Character#isUnicodeIdentifierStart(int)
- * @see java.lang.Character#isUpperCase(int)
+ * @see Character#isDigit(int)
+ * @see Character#isJavaIdentifierStart(int)
+ * @see Character#isLetterOrDigit(int)
+ * @see Character#isLowerCase(int)
+ * @see Character#isTitleCase(int)
+ * @see Character#isUnicodeIdentifierStart(int)
+ * @see Character#isUpperCase(int)
* @since 1.5
*/
public static boolean isLetter(int codePoint) {
@@ -4993,12 +5161,12 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is a letter or digit;
* <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(char)
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isJavaLetter(char)
- * @see java.lang.Character#isJavaLetterOrDigit(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isUnicodeIdentifierPart(char)
+ * @see Character#isDigit(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isJavaLetter(char)
+ * @see Character#isJavaLetterOrDigit(char)
+ * @see Character#isLetter(char)
+ * @see Character#isUnicodeIdentifierPart(char)
* @since 1.0.2
*/
public static boolean isLetterOrDigit(char ch) {
@@ -5016,10 +5184,10 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is a letter or digit;
* <code>false</code> otherwise.
- * @see java.lang.Character#isDigit(int)
- * @see java.lang.Character#isJavaIdentifierPart(int)
- * @see java.lang.Character#isLetter(int)
- * @see java.lang.Character#isUnicodeIdentifierPart(int)
+ * @see Character#isDigit(int)
+ * @see Character#isJavaIdentifierPart(int)
+ * @see Character#isLetter(int)
+ * @see Character#isUnicodeIdentifierPart(int)
* @since 1.5
*/
public static boolean isLetterOrDigit(int codePoint) {
@@ -5048,12 +5216,12 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may start a Java
* identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isJavaLetterOrDigit(char)
- * @see java.lang.Character#isJavaIdentifierStart(char)
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isUnicodeIdentifierStart(char)
+ * @see Character#isJavaLetterOrDigit(char)
+ * @see Character#isJavaIdentifierStart(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isLetter(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isUnicodeIdentifierStart(char)
* @since 1.02
* @deprecated Replaced by isJavaIdentifierStart(char).
*/
@@ -5083,13 +5251,13 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may be part of a
* Java identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isJavaLetter(char)
- * @see java.lang.Character#isJavaIdentifierStart(char)
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isUnicodeIdentifierPart(char)
- * @see java.lang.Character#isIdentifierIgnorable(char)
+ * @see Character#isJavaLetter(char)
+ * @see Character#isJavaIdentifierStart(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isLetter(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isUnicodeIdentifierPart(char)
+ * @see Character#isIdentifierIgnorable(char)
* @since 1.02
* @deprecated Replaced by isJavaIdentifierPart(char).
*/
@@ -5119,9 +5287,9 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may start a Java identifier;
* <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isUnicodeIdentifierStart(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isLetter(char)
+ * @see Character#isUnicodeIdentifierStart(char)
* @see javax.lang.model.SourceVersion#isIdentifier(CharSequence)
* @since 1.1
*/
@@ -5148,9 +5316,9 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character may start a Java identifier;
* <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierPart(int)
- * @see java.lang.Character#isLetter(int)
- * @see java.lang.Character#isUnicodeIdentifierStart(int)
+ * @see Character#isJavaIdentifierPart(int)
+ * @see Character#isLetter(int)
+ * @see Character#isUnicodeIdentifierStart(int)
* @see javax.lang.model.SourceVersion#isIdentifier(CharSequence)
* @since 1.5
*/
@@ -5184,10 +5352,10 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may be part of a
* Java identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isIdentifierIgnorable(char)
- * @see java.lang.Character#isJavaIdentifierStart(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isUnicodeIdentifierPart(char)
+ * @see Character#isIdentifierIgnorable(char)
+ * @see Character#isJavaIdentifierStart(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isUnicodeIdentifierPart(char)
* @see javax.lang.model.SourceVersion#isIdentifier(CharSequence)
* @since 1.1
*/
@@ -5217,10 +5385,10 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character may be part of a
* Java identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isIdentifierIgnorable(int)
- * @see java.lang.Character#isJavaIdentifierStart(int)
- * @see java.lang.Character#isLetterOrDigit(int)
- * @see java.lang.Character#isUnicodeIdentifierPart(int)
+ * @see Character#isIdentifierIgnorable(int)
+ * @see Character#isJavaIdentifierStart(int)
+ * @see Character#isLetterOrDigit(int)
+ * @see Character#isUnicodeIdentifierPart(int)
* @see javax.lang.model.SourceVersion#isIdentifier(CharSequence)
* @since 1.5
*/
@@ -5248,9 +5416,9 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may start a Unicode
* identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierStart(char)
- * @see java.lang.Character#isLetter(char)
- * @see java.lang.Character#isUnicodeIdentifierPart(char)
+ * @see Character#isJavaIdentifierStart(char)
+ * @see Character#isLetter(char)
+ * @see Character#isUnicodeIdentifierPart(char)
* @since 1.1
*/
public static boolean isUnicodeIdentifierStart(char ch) {
@@ -5272,9 +5440,9 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character may start a Unicode
* identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierStart(int)
- * @see java.lang.Character#isLetter(int)
- * @see java.lang.Character#isUnicodeIdentifierPart(int)
+ * @see Character#isJavaIdentifierStart(int)
+ * @see Character#isLetter(int)
+ * @see Character#isUnicodeIdentifierPart(int)
* @since 1.5
*/
public static boolean isUnicodeIdentifierStart(int codePoint) {
@@ -5306,10 +5474,10 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character may be part of a
* Unicode identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isIdentifierIgnorable(char)
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isLetterOrDigit(char)
- * @see java.lang.Character#isUnicodeIdentifierStart(char)
+ * @see Character#isIdentifierIgnorable(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isLetterOrDigit(char)
+ * @see Character#isUnicodeIdentifierStart(char)
* @since 1.1
*/
public static boolean isUnicodeIdentifierPart(char ch) {
@@ -5335,10 +5503,10 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character may be part of a
* Unicode identifier; <code>false</code> otherwise.
- * @see java.lang.Character#isIdentifierIgnorable(int)
- * @see java.lang.Character#isJavaIdentifierPart(int)
- * @see java.lang.Character#isLetterOrDigit(int)
- * @see java.lang.Character#isUnicodeIdentifierStart(int)
+ * @see Character#isIdentifierIgnorable(int)
+ * @see Character#isJavaIdentifierPart(int)
+ * @see Character#isLetterOrDigit(int)
+ * @see Character#isUnicodeIdentifierStart(int)
* @since 1.5
*/
public static boolean isUnicodeIdentifierPart(int codePoint) {
@@ -5372,8 +5540,8 @@
* @return <code>true</code> if the character is an ignorable control
* character that may be part of a Java or Unicode identifier;
* <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierPart(char)
- * @see java.lang.Character#isUnicodeIdentifierPart(char)
+ * @see Character#isJavaIdentifierPart(char)
+ * @see Character#isUnicodeIdentifierPart(char)
* @since 1.1
*/
public static boolean isIdentifierIgnorable(char ch) {
@@ -5402,8 +5570,8 @@
* @return <code>true</code> if the character is an ignorable control
* character that may be part of a Java or Unicode identifier;
* <code>false</code> otherwise.
- * @see java.lang.Character#isJavaIdentifierPart(int)
- * @see java.lang.Character#isUnicodeIdentifierPart(int)
+ * @see Character#isJavaIdentifierPart(int)
+ * @see Character#isUnicodeIdentifierPart(int)
* @since 1.5
*/
public static boolean isIdentifierIgnorable(int codePoint) {
@@ -5419,7 +5587,7 @@
* does not always return <code>true</code> for some ranges of
* characters, particularly those that are symbols or ideographs.
*
- * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map
+ * <p>In general, {@link String#toLowerCase()} should be used to map
* characters to lowercase. <code>String</code> case mapping methods
* have several benefits over <code>Character</code> case mapping methods.
* <code>String</code> case mapping methods can perform locale-sensitive
@@ -5434,8 +5602,8 @@
* @param ch the character to be converted.
* @return the lowercase equivalent of the character, if any;
* otherwise, the character itself.
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.String#toLowerCase()
+ * @see Character#isLowerCase(char)
+ * @see String#toLowerCase()
*/
public static char toLowerCase(char ch) {
return (char)toLowerCase((int)ch);
@@ -5451,7 +5619,7 @@
* does not always return <code>true</code> for some ranges of
* characters, particularly those that are symbols or ideographs.
*
- * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map
+ * <p>In general, {@link String#toLowerCase()} should be used to map
* characters to lowercase. <code>String</code> case mapping methods
* have several benefits over <code>Character</code> case mapping methods.
* <code>String</code> case mapping methods can perform locale-sensitive
@@ -5461,8 +5629,8 @@
* @param codePoint the character (Unicode code point) to be converted.
* @return the lowercase equivalent of the character (Unicode code
* point), if any; otherwise, the character itself.
- * @see java.lang.Character#isLowerCase(int)
- * @see java.lang.String#toLowerCase()
+ * @see Character#isLowerCase(int)
+ * @see String#toLowerCase()
*
* @since 1.5
*/
@@ -5479,7 +5647,7 @@
* does not always return <code>true</code> for some ranges of
* characters, particularly those that are symbols or ideographs.
*
- * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map
+ * <p>In general, {@link String#toUpperCase()} should be used to map
* characters to uppercase. <code>String</code> case mapping methods
* have several benefits over <code>Character</code> case mapping methods.
* <code>String</code> case mapping methods can perform locale-sensitive
@@ -5494,8 +5662,8 @@
* @param ch the character to be converted.
* @return the uppercase equivalent of the character, if any;
* otherwise, the character itself.
- * @see java.lang.Character#isUpperCase(char)
- * @see java.lang.String#toUpperCase()
+ * @see Character#isUpperCase(char)
+ * @see String#toUpperCase()
*/
public static char toUpperCase(char ch) {
return (char)toUpperCase((int)ch);
@@ -5511,7 +5679,7 @@
* does not always return <code>true</code> for some ranges of
* characters, particularly those that are symbols or ideographs.
*
- * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map
+ * <p>In general, {@link String#toUpperCase()} should be used to map
* characters to uppercase. <code>String</code> case mapping methods
* have several benefits over <code>Character</code> case mapping methods.
* <code>String</code> case mapping methods can perform locale-sensitive
@@ -5521,8 +5689,8 @@
* @param codePoint the character (Unicode code point) to be converted.
* @return the uppercase equivalent of the character, if any;
* otherwise, the character itself.
- * @see java.lang.Character#isUpperCase(int)
- * @see java.lang.String#toUpperCase()
+ * @see Character#isUpperCase(int)
+ * @see String#toUpperCase()
*
* @since 1.5
*/
@@ -5553,9 +5721,9 @@
* @param ch the character to be converted.
* @return the titlecase equivalent of the character, if any;
* otherwise, the character itself.
- * @see java.lang.Character#isTitleCase(char)
- * @see java.lang.Character#toLowerCase(char)
- * @see java.lang.Character#toUpperCase(char)
+ * @see Character#isTitleCase(char)
+ * @see Character#toLowerCase(char)
+ * @see Character#toUpperCase(char)
* @since 1.0.2
*/
public static char toTitleCase(char ch) {
@@ -5580,9 +5748,9 @@
* @param codePoint the character (Unicode code point) to be converted.
* @return the titlecase equivalent of the character, if any;
* otherwise, the character itself.
- * @see java.lang.Character#isTitleCase(int)
- * @see java.lang.Character#toLowerCase(int)
- * @see java.lang.Character#toUpperCase(int)
+ * @see Character#isTitleCase(int)
+ * @see Character#toLowerCase(int)
+ * @see Character#toUpperCase(int)
* @since 1.5
*/
public static int toTitleCase(int codePoint) {
@@ -5624,8 +5792,8 @@
* @param radix the radix.
* @return the numeric value represented by the character in the
* specified radix.
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#isDigit(char)
+ * @see Character#forDigit(int, int)
+ * @see Character#isDigit(char)
*/
public static int digit(char ch, int radix) {
return digit((int)ch, radix);
@@ -5661,8 +5829,8 @@
* @param radix the radix.
* @return the numeric value represented by the character in the
* specified radix.
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#isDigit(int)
+ * @see Character#forDigit(int, int)
+ * @see Character#isDigit(int)
* @since 1.5
*/
public static int digit(int codePoint, int radix) {
@@ -5699,8 +5867,8 @@
* @return the numeric value of the character, as a nonnegative <code>int</code>
* value; -2 if the character has a numeric value that is not a
* nonnegative integer; -1 if the character has no numeric value.
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#isDigit(char)
+ * @see Character#forDigit(int, int)
+ * @see Character#isDigit(char)
* @since 1.1
*/
public static int getNumericValue(char ch) {
@@ -5732,8 +5900,8 @@
* @return the numeric value of the character, as a nonnegative <code>int</code>
* value; -2 if the character has a numeric value that is not a
* nonnegative integer; -1 if the character has no numeric value.
- * @see java.lang.Character#forDigit(int, int)
- * @see java.lang.Character#isDigit(int)
+ * @see Character#forDigit(int, int)
+ * @see Character#isDigit(int)
* @since 1.5
*/
public static int getNumericValue(int codePoint) {
@@ -5760,8 +5928,8 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is ISO-LATIN-1 white
* space; <code>false</code> otherwise.
- * @see java.lang.Character#isSpaceChar(char)
- * @see java.lang.Character#isWhitespace(char)
+ * @see Character#isSpaceChar(char)
+ * @see Character#isWhitespace(char)
* @deprecated Replaced by isWhitespace(char).
*/
@Deprecated
@@ -5795,7 +5963,7 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is a space character;
* <code>false</code> otherwise.
- * @see java.lang.Character#isWhitespace(char)
+ * @see Character#isWhitespace(char)
* @since 1.1
*/
public static boolean isSpaceChar(char ch) {
@@ -5818,7 +5986,7 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is a space character;
* <code>false</code> otherwise.
- * @see java.lang.Character#isWhitespace(int)
+ * @see Character#isWhitespace(int)
* @since 1.5
*/
public static boolean isSpaceChar(int codePoint) {
@@ -5856,7 +6024,7 @@
* @param ch the character to be tested.
* @return <code>true</code> if the character is a Java whitespace
* character; <code>false</code> otherwise.
- * @see java.lang.Character#isSpaceChar(char)
+ * @see Character#isSpaceChar(char)
* @since 1.1
*/
public static boolean isWhitespace(char ch) {
@@ -5888,7 +6056,7 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is a Java whitespace
* character; <code>false</code> otherwise.
- * @see java.lang.Character#isSpaceChar(int)
+ * @see Character#isSpaceChar(int)
* @since 1.5
*/
public static boolean isWhitespace(int codePoint) {
@@ -5911,8 +6079,8 @@
* @return <code>true</code> if the character is an ISO control character;
* <code>false</code> otherwise.
*
- * @see java.lang.Character#isSpaceChar(char)
- * @see java.lang.Character#isWhitespace(char)
+ * @see Character#isSpaceChar(char)
+ * @see Character#isWhitespace(char)
* @since 1.1
*/
public static boolean isISOControl(char ch) {
@@ -5929,13 +6097,16 @@
* @param codePoint the character (Unicode code point) to be tested.
* @return <code>true</code> if the character is an ISO control character;
* <code>false</code> otherwise.
- * @see java.lang.Character#isSpaceChar(int)
- * @see java.lang.Character#isWhitespace(int)
+ * @see Character#isSpaceChar(int)
+ * @see Character#isWhitespace(int)
* @since 1.5
*/
public static boolean isISOControl(int codePoint) {
- return (codePoint >= 0x0000 && codePoint <= 0x001F) ||
- (codePoint >= 0x007F && codePoint <= 0x009F);
+ // Optimized form of:
+ // (codePoint >= 0x00 && codePoint <= 0x1F) ||
+ // (codePoint >= 0x7F && codePoint <= 0x9F);
+ return codePoint <= 0x9F &&
+ (codePoint >= 0x7F || (codePoint >>> 5 == 0));
}
/**
@@ -5949,36 +6120,36 @@
* @param ch the character to be tested.
* @return a value of type <code>int</code> representing the
* character's general category.
- * @see java.lang.Character#COMBINING_SPACING_MARK
- * @see java.lang.Character#CONNECTOR_PUNCTUATION
- * @see java.lang.Character#CONTROL
- * @see java.lang.Character#CURRENCY_SYMBOL
- * @see java.lang.Character#DASH_PUNCTUATION
- * @see java.lang.Character#DECIMAL_DIGIT_NUMBER
- * @see java.lang.Character#ENCLOSING_MARK
- * @see java.lang.Character#END_PUNCTUATION
- * @see java.lang.Character#FINAL_QUOTE_PUNCTUATION
- * @see java.lang.Character#FORMAT
- * @see java.lang.Character#INITIAL_QUOTE_PUNCTUATION
- * @see java.lang.Character#LETTER_NUMBER
- * @see java.lang.Character#LINE_SEPARATOR
- * @see java.lang.Character#LOWERCASE_LETTER
- * @see java.lang.Character#MATH_SYMBOL
- * @see java.lang.Character#MODIFIER_LETTER
- * @see java.lang.Character#MODIFIER_SYMBOL
- * @see java.lang.Character#NON_SPACING_MARK
- * @see java.lang.Character#OTHER_LETTER
- * @see java.lang.Character#OTHER_NUMBER
- * @see java.lang.Character#OTHER_PUNCTUATION
- * @see java.lang.Character#OTHER_SYMBOL
- * @see java.lang.Character#PARAGRAPH_SEPARATOR
- * @see java.lang.Character#PRIVATE_USE
- * @see java.lang.Character#SPACE_SEPARATOR
- * @see java.lang.Character#START_PUNCTUATION
- * @see java.lang.Character#SURROGATE
- * @see java.lang.Character#TITLECASE_LETTER
- * @see java.lang.Character#UNASSIGNED
- * @see java.lang.Character#UPPERCASE_LETTER
+ * @see Character#COMBINING_SPACING_MARK
+ * @see Character#CONNECTOR_PUNCTUATION
+ * @see Character#CONTROL
+ * @see Character#CURRENCY_SYMBOL
+ * @see Character#DASH_PUNCTUATION
+ * @see Character#DECIMAL_DIGIT_NUMBER
+ * @see Character#ENCLOSING_MARK
+ * @see Character#END_PUNCTUATION
+ * @see Character#FINAL_QUOTE_PUNCTUATION
+ * @see Character#FORMAT
+ * @see Character#INITIAL_QUOTE_PUNCTUATION
+ * @see Character#LETTER_NUMBER
+ * @see Character#LINE_SEPARATOR
+ * @see Character#LOWERCASE_LETTER
+ * @see Character#MATH_SYMBOL
+ * @see Character#MODIFIER_LETTER
+ * @see Character#MODIFIER_SYMBOL
+ * @see Character#NON_SPACING_MARK
+ * @see Character#OTHER_LETTER
+ * @see Character#OTHER_NUMBER
+ * @see Character#OTHER_PUNCTUATION
+ * @see Character#OTHER_SYMBOL
+ * @see Character#PARAGRAPH_SEPARATOR
+ * @see Character#PRIVATE_USE
+ * @see Character#SPACE_SEPARATOR
+ * @see Character#START_PUNCTUATION
+ * @see Character#SURROGATE
+ * @see Character#TITLECASE_LETTER
+ * @see Character#UNASSIGNED
+ * @see Character#UPPERCASE_LETTER
* @since 1.1
*/
public static int getType(char ch) {
@@ -6047,9 +6218,9 @@
* @param radix the radix.
* @return the <code>char</code> representation of the specified digit
* in the specified radix.
- * @see java.lang.Character#MIN_RADIX
- * @see java.lang.Character#MAX_RADIX
- * @see java.lang.Character#digit(char, int)
+ * @see Character#MIN_RADIX
+ * @see Character#MAX_RADIX
+ * @see Character#digit(char, int)
*/
public static char forDigit(int digit, int radix) {
if ((digit >= radix) || (digit < 0)) {
@@ -6230,10 +6401,10 @@
* @return either the uppercase equivalent of the character, if
* any, or an error flag (<code>Character.ERROR</code>)
* that indicates that a 1:M <code>char</code> mapping exists.
- * @see java.lang.Character#isLowerCase(char)
- * @see java.lang.Character#isUpperCase(char)
- * @see java.lang.Character#toLowerCase(char)
- * @see java.lang.Character#toTitleCase(char)
+ * @see Character#isLowerCase(char)
+ * @see Character#isUpperCase(char)
+ * @see Character#toLowerCase(char)
+ * @see Character#toTitleCase(char)
* @since 1.4
*/
static int toUpperCaseEx(int codePoint) {
@@ -6254,8 +6425,7 @@
*/
static char[] toUpperCaseCharArray(int codePoint) {
// As of Unicode 4.0, 1:M uppercasings only happen in the BMP.
- assert isValidCodePoint(codePoint) &&
- !isSupplementaryCodePoint(codePoint);
+ assert isBmpCodePoint(codePoint);
return CharacterData.of(codePoint).toUpperCaseCharArray(codePoint);
}
--- a/jdk/src/share/classes/java/lang/String.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Wed Jul 05 17:18:01 2017 +0200
@@ -38,7 +38,6 @@
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
-
/**
* The <code>String</code> class represents character strings. All
* string literals in Java programs, such as <code>"abc"</code>, are
@@ -99,6 +98,8 @@
*
* @author Lee Boynton
* @author Arthur van Hoff
+ * @author Martin Buchholz
+ * @author Ulf Zibis
* @see java.lang.Object#toString()
* @see java.lang.StringBuffer
* @see java.lang.StringBuilder
@@ -273,32 +274,32 @@
throw new StringIndexOutOfBoundsException(offset + count);
}
+ final int end = offset + count;
+
// Pass 1: Compute precise size of char[]
- int n = 0;
- for (int i = offset; i < offset + count; i++) {
+ int n = count;
+ for (int i = offset; i < end; i++) {
int c = codePoints[i];
- if (c >= Character.MIN_CODE_POINT &&
- c < Character.MIN_SUPPLEMENTARY_CODE_POINT)
- n += 1;
- else if (Character.isSupplementaryCodePoint(c))
- n += 2;
+ if (Character.isBmpCodePoint(c))
+ continue;
+ else if (Character.isValidCodePoint(c))
+ n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
- char[] v = new char[n];
- for (int i = offset, j = 0; i < offset + count; i++) {
+ final char[] v = new char[n];
+
+ for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
- if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- v[j++] = (char) c;
- } else {
- Character.toSurrogates(c, v, j);
- j += 2;
- }
+ if (Character.isBmpCodePoint(c))
+ v[j] = (char) c;
+ else
+ Character.toSurrogates(c, v, j++);
}
this.value = v;
- this.count = v.length;
+ this.count = n;
this.offset = 0;
}
@@ -1573,9 +1574,6 @@
* if the character does not occur.
*/
public int indexOf(int ch, int fromIndex) {
- int max = offset + count;
- char v[] = value;
-
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= count) {
@@ -1583,29 +1581,36 @@
return -1;
}
- int i = offset + fromIndex;
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
- for (; i < max ; i++) {
- if (v[i] == ch) {
+ final char[] value = this.value;
+ final int offset = this.offset;
+ final int max = offset + count;
+ for (int i = offset + fromIndex; i < max ; i++) {
+ if (value[i] == ch) {
return i - offset;
}
}
return -1;
+ } else {
+ return indexOfSupplementary(ch, fromIndex);
}
+ }
- if (ch <= Character.MAX_CODE_POINT) {
- // handle supplementary characters here
- char[] surrogates = Character.toChars(ch);
- for (; i < max; i++) {
- if (v[i] == surrogates[0]) {
- if (i + 1 == max) {
- break;
- }
- if (v[i+1] == surrogates[1]) {
- return i - offset;
- }
+ /**
+ * Handles (rare) calls of indexOf with a supplementary character.
+ */
+ private int indexOfSupplementary(int ch, int fromIndex) {
+ if (Character.isValidCodePoint(ch)) {
+ final char[] value = this.value;
+ final int offset = this.offset;
+ final char hi = Character.highSurrogate(ch);
+ final char lo = Character.lowSurrogate(ch);
+ final int max = offset + count - 1;
+ for (int i = offset + fromIndex; i < max; i++) {
+ if (value[i] == hi && value[i+1] == lo) {
+ return i - offset;
}
}
}
@@ -1674,34 +1679,36 @@
* if the character does not occur before that point.
*/
public int lastIndexOf(int ch, int fromIndex) {
- int min = offset;
- char v[] = value;
-
- int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex);
-
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
- for (; i >= min ; i--) {
- if (v[i] == ch) {
+ final char[] value = this.value;
+ final int offset = this.offset;
+ int i = offset + Math.min(fromIndex, count - 1);
+ for (; i >= offset ; i--) {
+ if (value[i] == ch) {
return i - offset;
}
}
return -1;
+ } else {
+ return lastIndexOfSupplementary(ch, fromIndex);
}
+ }
- int max = offset + count;
- if (ch <= Character.MAX_CODE_POINT) {
- // handle supplementary characters here
- char[] surrogates = Character.toChars(ch);
- for (; i >= min; i--) {
- if (v[i] == surrogates[0]) {
- if (i + 1 == max) {
- break;
- }
- if (v[i+1] == surrogates[1]) {
- return i - offset;
- }
+ /**
+ * Handles (rare) calls of lastIndexOf with a supplementary character.
+ */
+ private int lastIndexOfSupplementary(int ch, int fromIndex) {
+ if (Character.isValidCodePoint(ch)) {
+ final char[] value = this.value;
+ final int offset = this.offset;
+ char hi = Character.highSurrogate(ch);
+ char lo = Character.lowSurrogate(ch);
+ int i = offset + Math.min(fromIndex, count - 2);
+ for (; i >= offset; i--) {
+ if (value[i] == hi && value[i+1] == lo) {
+ return i - offset;
}
}
}
@@ -1710,18 +1717,17 @@
/**
* Returns the index within this string of the first occurrence of the
- * specified substring. The integer returned is the smallest value
- * <i>k</i> such that:
+ * specified substring.
+ *
+ * <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
* this.startsWith(str, <i>k</i>)
* </pre></blockquote>
- * is <code>true</code>.
+ * If no such value of <i>k</i> exists, then {@code -1} is returned.
*
- * @param str any string.
- * @return if the string argument occurs as a substring within this
- * object, then the index of the first character of the first
- * such substring is returned; if it does not occur as a
- * substring, <code>-1</code> is returned.
+ * @param str the substring to search for.
+ * @return the index of the first occurrence of the specified substring,
+ * or {@code -1} if there is no such occurrence.
*/
public int indexOf(String str) {
return indexOf(str, 0);
@@ -1729,17 +1735,19 @@
/**
* Returns the index within this string of the first occurrence of the
- * specified substring, starting at the specified index. The integer
- * returned is the smallest value <tt>k</tt> for which:
+ * specified substring, starting at the specified index.
+ *
+ * <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
- * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k)
+ * <i>k</i> >= fromIndex && this.startsWith(str, <i>k</i>)
* </pre></blockquote>
- * If no such value of <i>k</i> exists, then -1 is returned.
+ * If no such value of <i>k</i> exists, then {@code -1} is returned.
*
- * @param str the substring for which to search.
+ * @param str the substring to search for.
* @param fromIndex the index from which to start the search.
- * @return the index within this string of the first occurrence of the
- * specified substring, starting at the specified index.
+ * @return the index of the first occurrence of the specified substring,
+ * starting at the specified index,
+ * or {@code -1} if there is no such occurrence.
*/
public int indexOf(String str, int fromIndex) {
return indexOf(value, offset, count,
@@ -1798,20 +1806,19 @@
}
/**
- * Returns the index within this string of the rightmost occurrence
- * of the specified substring. The rightmost empty string "" is
- * considered to occur at the index value <code>this.length()</code>.
- * The returned index is the largest value <i>k</i> such that
+ * Returns the index within this string of the last occurrence of the
+ * specified substring. The last occurrence of the empty string ""
+ * is considered to occur at the index value {@code this.length()}.
+ *
+ * <p>The returned index is the largest value <i>k</i> for which:
* <blockquote><pre>
- * this.startsWith(str, k)
+ * this.startsWith(str, <i>k</i>)
* </pre></blockquote>
- * is true.
+ * If no such value of <i>k</i> exists, then {@code -1} is returned.
*
* @param str the substring to search for.
- * @return if the string argument occurs one or more times as a substring
- * within this object, then the index of the first character of
- * the last such substring is returned. If it does not occur as
- * a substring, <code>-1</code> is returned.
+ * @return the index of the last occurrence of the specified substring,
+ * or {@code -1} if there is no such occurrence.
*/
public int lastIndexOf(String str) {
return lastIndexOf(str, count);
@@ -1820,16 +1827,18 @@
/**
* Returns the index within this string of the last occurrence of the
* specified substring, searching backward starting at the specified index.
- * The integer returned is the largest value <i>k</i> such that:
+ *
+ * <p>The returned index is the largest value <i>k</i> for which:
* <blockquote><pre>
- * k <= Math.min(fromIndex, this.length()) && this.startsWith(str, k)
+ * <i>k</i> <= fromIndex && this.startsWith(str, <i>k</i>)
* </pre></blockquote>
- * If no such value of <i>k</i> exists, then -1 is returned.
+ * If no such value of <i>k</i> exists, then {@code -1} is returned.
*
* @param str the substring to search for.
* @param fromIndex the index to start the search from.
- * @return the index within this string of the last occurrence of the
- * specified substring.
+ * @return the index of the last occurrence of the specified substring,
+ * searching backward from the specified index,
+ * or {@code -1} if there is no such occurrence.
*/
public int lastIndexOf(String str, int fromIndex) {
return lastIndexOf(value, offset, count,
--- a/jdk/src/share/classes/java/lang/System.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/lang/System.java Wed Jul 05 17:18:01 2017 +0200
@@ -69,7 +69,7 @@
* corresponds to keyboard input or another input source specified by
* the host environment or user.
*/
- public final static InputStream in = nullInputStream();
+ public final static InputStream in = null;
/**
* The "standard" output stream. This stream is already
@@ -96,7 +96,7 @@
* @see java.io.PrintStream#println(java.lang.Object)
* @see java.io.PrintStream#println(java.lang.String)
*/
- public final static PrintStream out = nullPrintStream();
+ public final static PrintStream out = null;
/**
* The "standard" error output stream. This stream is already
@@ -110,7 +110,7 @@
* variable <code>out</code>, has been redirected to a file or other
* destination that is typically not continuously monitored.
*/
- public final static PrintStream err = nullPrintStream();
+ public final static PrintStream err = null;
/* The security manager for the system.
*/
@@ -1093,26 +1093,6 @@
public static native String mapLibraryName(String libname);
/**
- * The following two methods exist because in, out, and err must be
- * initialized to null. The compiler, however, cannot be permitted to
- * inline access to them, since they are later set to more sensible values
- * by initializeSystemClass().
- */
- private static InputStream nullInputStream() throws NullPointerException {
- if (currentTimeMillis() > 0) {
- return null;
- }
- throw new NullPointerException();
- }
-
- private static PrintStream nullPrintStream() throws NullPointerException {
- if (currentTimeMillis() > 0) {
- return null;
- }
- throw new NullPointerException();
- }
-
- /**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
--- a/jdk/src/share/classes/java/lang/Throwable.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Throwable.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,7 @@
package java.lang;
import java.io.*;
+import java.util.*;
/**
* The <code>Throwable</code> class is the superclass of all errors and
@@ -102,7 +103,7 @@
* lowLevelOp();
* } catch (LowLevelException le) {
* throw (HighLevelException)
- new HighLevelException().initCause(le); // Legacy constructor
+ * new HighLevelException().initCause(le); // Legacy constructor
* }
* </pre>
*
@@ -193,6 +194,24 @@
*/
/**
+ * The list of suppressed exceptions, as returned by
+ * {@link #getSuppressedExceptions()}.
+ *
+ * @serial
+ * @since 1.7
+ */
+ private List<Throwable> suppressedExceptions = Collections.emptyList();
+
+ /** Message for trying to suppress a null exception. */
+ private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
+
+ /** Caption for labeling causative exception stack traces */
+ private static final String CAUSE_CAPTION = "Caused by: ";
+
+ /** Caption for labeling suppressed exception stack traces */
+ private static final String SUPPRESSED_CAPTION = "Suppressed: ";
+
+ /**
* Constructs a new throwable with <code>null</code> as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
@@ -469,6 +488,52 @@
* class LowLevelException extends Exception {
* }
* </pre>
+ * As of release 7, the platform supports the notion of
+ * <i>suppressed exceptions</i> (in conjunction with automatic
+ * resource management blocks). Any exceptions that were
+ * suppressed in order to deliver an exception are printed out
+ * beneath the stack trace. The format of this information
+ * depends on the implementation, but the following example may be
+ * regarded as typical:
+ *
+ * <pre>
+ * Exception in thread "main" java.lang.Exception: Something happened
+ * at Foo.bar(Foo.java:10)
+ * at Foo.main(Foo.java:5)
+ * Suppressed: Resource$CloseFailException: Resource ID = 0
+ * at Resource.close(Resource.java:26)
+ * at Foo.bar(Foo.java:9)
+ * ... 1 more
+ * </pre>
+ * Note that the "... n more" notation is used on suppressed exceptions
+ * just at it is used on causes. Unlike causes, suppressed exceptions are
+ * indented beyond their "containing exceptions."
+ *
+ * <p>An exception can have both a cause and one or more suppressed
+ * exceptions:
+ * <pre>
+ * Exception in thread "main" java.lang.Exception: Main block
+ * at Foo3.main(Foo3.java:7)
+ * Suppressed: Resource$CloseFailException: Resource ID = 2
+ * at Resource.close(Resource.java:26)
+ * at Foo3.main(Foo3.java:5)
+ * Suppressed: Resource$CloseFailException: Resource ID = 1
+ * at Resource.close(Resource.java:26)
+ * at Foo3.main(Foo3.java:5)
+ * Caused by: java.lang.Exception: I did it
+ * at Foo3.main(Foo3.java:8)
+ * </pre>
+ * Likewise, a suppressed exception can have a cause:
+ * <pre>
+ * Exception in thread "main" java.lang.Exception: Main block
+ * at Foo4.main(Foo4.java:6)
+ * Suppressed: Resource2$CloseFailException: Resource ID = 1
+ * at Resource2.close(Resource2.java:20)
+ * at Foo4.main(Foo4.java:5)
+ * Caused by: java.lang.Exception: Rats, you caught me
+ * at Resource2$CloseFailException.<init>(Resource2.java:45)
+ * ... 2 more
+ * </pre>
*/
public void printStackTrace() {
printStackTrace(System.err);
@@ -480,44 +545,71 @@
* @param s <code>PrintStream</code> to use for output
*/
public void printStackTrace(PrintStream s) {
- synchronized (s) {
+ printStackTrace(new WrappedPrintStream(s));
+ }
+
+ private void printStackTrace(PrintStreamOrWriter s) {
+ Set<Throwable> dejaVu = new HashSet<Throwable>();
+ dejaVu.add(this);
+
+ synchronized (s.lock()) {
+ // Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
- for (int i=0; i < trace.length; i++)
- s.println("\tat " + trace[i]);
+ for (StackTraceElement traceElement : trace)
+ s.println("\tat " + traceElement);
+ // Print suppressed exceptions, if any
+ for (Throwable se : suppressedExceptions)
+ se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
+
+ // Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
- ourCause.printStackTraceAsCause(s, trace);
+ ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}
/**
- * Print our stack trace as a cause for the specified stack trace.
+ * Print our stack trace as an enclosed exception for the specified
+ * stack trace.
*/
- private void printStackTraceAsCause(PrintStream s,
- StackTraceElement[] causedTrace)
- {
- // assert Thread.holdsLock(s);
+ private void printEnclosedStackTrace(PrintStreamOrWriter s,
+ StackTraceElement[] enclosingTrace,
+ String caption,
+ String prefix,
+ Set<Throwable> dejaVu) {
+ assert Thread.holdsLock(s.lock());
+ if (dejaVu.contains(this)) {
+ s.println("\t[CIRCULAR REFERENCE:" + this + "]");
+ } else {
+ dejaVu.add(this);
+ // Compute number of frames in common between this and enclosing trace
+ StackTraceElement[] trace = getOurStackTrace();
+ int m = trace.length - 1;
+ int n = enclosingTrace.length - 1;
+ while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
+ m--; n--;
+ }
+ int framesInCommon = trace.length - 1 - m;
- // Compute number of frames in common between this and caused
- StackTraceElement[] trace = getOurStackTrace();
- int m = trace.length-1, n = causedTrace.length-1;
- while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
- m--; n--;
+ // Print our stack trace
+ s.println(prefix + caption + this);
+ for (int i = 0; i <= m; i++)
+ s.println(prefix + "\tat " + trace[i]);
+ if (framesInCommon != 0)
+ s.println(prefix + "\t... " + framesInCommon + " more");
+
+ // Print suppressed exceptions, if any
+ for (Throwable se : suppressedExceptions)
+ se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
+ prefix +"\t", dejaVu);
+
+ // Print cause, if any
+ Throwable ourCause = getCause();
+ if (ourCause != null)
+ ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
}
- int framesInCommon = trace.length - 1 - m;
-
- s.println("Caused by: " + this);
- for (int i=0; i <= m; i++)
- s.println("\tat " + trace[i]);
- if (framesInCommon != 0)
- s.println("\t... " + framesInCommon + " more");
-
- // Recurse if we have a cause
- Throwable ourCause = getCause();
- if (ourCause != null)
- ourCause.printStackTraceAsCause(s, trace);
}
/**
@@ -528,44 +620,51 @@
* @since JDK1.1
*/
public void printStackTrace(PrintWriter s) {
- synchronized (s) {
- s.println(this);
- StackTraceElement[] trace = getOurStackTrace();
- for (int i=0; i < trace.length; i++)
- s.println("\tat " + trace[i]);
-
- Throwable ourCause = getCause();
- if (ourCause != null)
- ourCause.printStackTraceAsCause(s, trace);
- }
+ printStackTrace(new WrappedPrintWriter(s));
}
/**
- * Print our stack trace as a cause for the specified stack trace.
+ * Wrapper class for PrintStream and PrintWriter to enable a single
+ * implementation of printStackTrace.
*/
- private void printStackTraceAsCause(PrintWriter s,
- StackTraceElement[] causedTrace)
- {
- // assert Thread.holdsLock(s);
+ private abstract static class PrintStreamOrWriter {
+ /** Returns the object to be locked when using this StreamOrWriter */
+ abstract Object lock();
+
+ /** Prints the specified string as a line on this StreamOrWriter */
+ abstract void println(Object o);
+ }
- // Compute number of frames in common between this and caused
- StackTraceElement[] trace = getOurStackTrace();
- int m = trace.length-1, n = causedTrace.length-1;
- while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
- m--; n--;
+ private static class WrappedPrintStream extends PrintStreamOrWriter {
+ private final PrintStream printStream;
+
+ WrappedPrintStream(PrintStream printStream) {
+ this.printStream = printStream;
+ }
+
+ Object lock() {
+ return printStream;
}
- int framesInCommon = trace.length - 1 - m;
+
+ void println(Object o) {
+ printStream.println(o);
+ }
+ }
+
+ private static class WrappedPrintWriter extends PrintStreamOrWriter {
+ private final PrintWriter printWriter;
- s.println("Caused by: " + this);
- for (int i=0; i <= m; i++)
- s.println("\tat " + trace[i]);
- if (framesInCommon != 0)
- s.println("\t... " + framesInCommon + " more");
+ WrappedPrintWriter(PrintWriter printWriter) {
+ this.printWriter = printWriter;
+ }
- // Recurse if we have a cause
- Throwable ourCause = getCause();
- if (ourCause != null)
- ourCause.printStackTraceAsCause(s, trace);
+ Object lock() {
+ return printWriter;
+ }
+
+ void println(Object o) {
+ printWriter.println(o);
+ }
}
/**
@@ -667,10 +766,60 @@
*/
native StackTraceElement getStackTraceElement(int index);
- private synchronized void writeObject(java.io.ObjectOutputStream s)
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject(); // read in all fields
+ List<Throwable> suppressed = Collections.emptyList();
+ if (suppressedExceptions != null &&
+ !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
+ suppressed = new ArrayList<Throwable>();
+ for(Throwable t : suppressedExceptions) {
+ if (t == null)
+ throw new NullPointerException(NULL_CAUSE_MESSAGE);
+ suppressed.add(t);
+ }
+ }
+ suppressedExceptions = suppressed;
+ }
+
+ private synchronized void writeObject(ObjectOutputStream s)
throws IOException
{
getOurStackTrace(); // Ensure that stackTrace field is initialized.
s.defaultWriteObject();
}
+
+ /**
+ * Adds the specified exception to the list of exceptions that
+ * were suppressed, typically by the automatic resource management
+ * statement, in order to deliver this exception.
+ *
+ * @param exception the exception to be added to the list of
+ * suppressed exceptions
+ * @throws NullPointerException if {@code exception} is null
+ * @since 1.7
+ */
+ public synchronized void addSuppressedException(Throwable exception) {
+ if (exception == null)
+ throw new NullPointerException(NULL_CAUSE_MESSAGE);
+
+ if (suppressedExceptions.size() == 0)
+ suppressedExceptions = new ArrayList<Throwable>();
+ suppressedExceptions.add(exception);
+ }
+
+ private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
+
+ /**
+ * Returns an array containing all of the exceptions that were
+ * suppressed, typically by the automatic resource management
+ * statement, in order to deliver this exception.
+ *
+ * @return an array containing all of the exceptions that were
+ * suppressed to deliver this exception.
+ * @since 1.7
+ */
+ public Throwable[] getSuppressedExceptions() {
+ return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
+ }
}
--- a/jdk/src/share/classes/java/net/Inet6Address.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/net/Inet6Address.java Wed Jul 05 17:18:01 2017 +0200
@@ -427,8 +427,9 @@
try {
scope_id = deriveNumericScope (scope_ifname);
} catch (UnknownHostException e) {
- // should not happen
- assert false;
+ // typically should not happen, but it may be that
+ // the machine being used for deserialization has
+ // the same interface name but without IPv6 configured.
}
}
} catch (SocketException e) {}
--- a/jdk/src/share/classes/java/nio/Bits.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/nio/Bits.java Wed Jul 05 17:18:01 2017 +0200
@@ -41,25 +41,19 @@
// -- Swapping --
static short swap(short x) {
- return (short)((x << 8) |
- ((char)x >>> 8));
+ return Short.reverseBytes(x);
}
static char swap(char x) {
- return (char)((x << 8) |
- (x >>> 8));
+ return Character.reverseBytes(x);
}
static int swap(int x) {
- return ((x << 24) |
- ((x & 0x0000ff00) << 8) |
- ((x & 0x00ff0000) >>> 8) |
- (x >>> 24));
+ return Integer.reverseBytes(x);
}
static long swap(long x) {
- return (((long)swap((int)x) << 32) |
- ((long)swap((int)(x >>> 32)) & 0xffffffffL));
+ return Long.reverseBytes(x);
}
@@ -71,52 +65,52 @@
static char getCharL(ByteBuffer bb, int bi) {
return makeChar(bb._get(bi + 1),
- bb._get(bi + 0));
+ bb._get(bi ));
}
static char getCharL(long a) {
return makeChar(_get(a + 1),
- _get(a + 0));
+ _get(a ));
}
static char getCharB(ByteBuffer bb, int bi) {
- return makeChar(bb._get(bi + 0),
+ return makeChar(bb._get(bi ),
bb._get(bi + 1));
}
static char getCharB(long a) {
- return makeChar(_get(a + 0),
+ return makeChar(_get(a ),
_get(a + 1));
}
static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getCharB(bb, bi) : getCharL(bb, bi));
+ return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);
}
static char getChar(long a, boolean bigEndian) {
- return (bigEndian ? getCharB(a) : getCharL(a));
+ return bigEndian ? getCharB(a) : getCharL(a);
}
private static byte char1(char x) { return (byte)(x >> 8); }
- private static byte char0(char x) { return (byte)(x >> 0); }
+ private static byte char0(char x) { return (byte)(x ); }
static void putCharL(ByteBuffer bb, int bi, char x) {
- bb._put(bi + 0, char0(x));
+ bb._put(bi , char0(x));
bb._put(bi + 1, char1(x));
}
static void putCharL(long a, char x) {
- _put(a + 0, char0(x));
+ _put(a , char0(x));
_put(a + 1, char1(x));
}
static void putCharB(ByteBuffer bb, int bi, char x) {
- bb._put(bi + 0, char1(x));
+ bb._put(bi , char1(x));
bb._put(bi + 1, char0(x));
}
static void putCharB(long a, char x) {
- _put(a + 0, char1(x));
+ _put(a , char1(x));
_put(a + 1, char0(x));
}
@@ -143,52 +137,52 @@
static short getShortL(ByteBuffer bb, int bi) {
return makeShort(bb._get(bi + 1),
- bb._get(bi + 0));
+ bb._get(bi ));
}
static short getShortL(long a) {
return makeShort(_get(a + 1),
- _get(a));
+ _get(a ));
}
static short getShortB(ByteBuffer bb, int bi) {
- return makeShort(bb._get(bi + 0),
+ return makeShort(bb._get(bi ),
bb._get(bi + 1));
}
static short getShortB(long a) {
- return makeShort(_get(a),
+ return makeShort(_get(a ),
_get(a + 1));
}
static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getShortB(bb, bi) : getShortL(bb, bi));
+ return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
}
static short getShort(long a, boolean bigEndian) {
- return (bigEndian ? getShortB(a) : getShortL(a));
+ return bigEndian ? getShortB(a) : getShortL(a);
}
private static byte short1(short x) { return (byte)(x >> 8); }
- private static byte short0(short x) { return (byte)(x >> 0); }
+ private static byte short0(short x) { return (byte)(x ); }
static void putShortL(ByteBuffer bb, int bi, short x) {
- bb._put(bi + 0, short0(x));
+ bb._put(bi , short0(x));
bb._put(bi + 1, short1(x));
}
static void putShortL(long a, short x) {
- _put(a, short0(x));
+ _put(a , short0(x));
_put(a + 1, short1(x));
}
static void putShortB(ByteBuffer bb, int bi, short x) {
- bb._put(bi + 0, short1(x));
+ bb._put(bi , short1(x));
bb._put(bi + 1, short0(x));
}
static void putShortB(long a, short x) {
- _put(a, short1(x));
+ _put(a , short1(x));
_put(a + 1, short0(x));
}
@@ -210,76 +204,76 @@
// -- get/put int --
static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
- return (((b3 & 0xff) << 24) |
+ return (((b3 ) << 24) |
((b2 & 0xff) << 16) |
((b1 & 0xff) << 8) |
- ((b0 & 0xff) << 0));
+ ((b0 & 0xff) ));
}
static int getIntL(ByteBuffer bb, int bi) {
return makeInt(bb._get(bi + 3),
bb._get(bi + 2),
bb._get(bi + 1),
- bb._get(bi + 0));
+ bb._get(bi ));
}
static int getIntL(long a) {
return makeInt(_get(a + 3),
_get(a + 2),
_get(a + 1),
- _get(a + 0));
+ _get(a ));
}
static int getIntB(ByteBuffer bb, int bi) {
- return makeInt(bb._get(bi + 0),
+ return makeInt(bb._get(bi ),
bb._get(bi + 1),
bb._get(bi + 2),
bb._get(bi + 3));
}
static int getIntB(long a) {
- return makeInt(_get(a + 0),
+ return makeInt(_get(a ),
_get(a + 1),
_get(a + 2),
_get(a + 3));
}
static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getIntB(bb, bi) : getIntL(bb, bi));
+ return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ;
}
static int getInt(long a, boolean bigEndian) {
- return (bigEndian ? getIntB(a) : getIntL(a));
+ return bigEndian ? getIntB(a) : getIntL(a) ;
}
private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >> 8); }
- private static byte int0(int x) { return (byte)(x >> 0); }
+ private static byte int0(int x) { return (byte)(x ); }
static void putIntL(ByteBuffer bb, int bi, int x) {
bb._put(bi + 3, int3(x));
bb._put(bi + 2, int2(x));
bb._put(bi + 1, int1(x));
- bb._put(bi + 0, int0(x));
+ bb._put(bi , int0(x));
}
static void putIntL(long a, int x) {
_put(a + 3, int3(x));
_put(a + 2, int2(x));
_put(a + 1, int1(x));
- _put(a + 0, int0(x));
+ _put(a , int0(x));
}
static void putIntB(ByteBuffer bb, int bi, int x) {
- bb._put(bi + 0, int3(x));
+ bb._put(bi , int3(x));
bb._put(bi + 1, int2(x));
bb._put(bi + 2, int1(x));
bb._put(bi + 3, int0(x));
}
static void putIntB(long a, int x) {
- _put(a + 0, int3(x));
+ _put(a , int3(x));
_put(a + 1, int2(x));
_put(a + 2, int1(x));
_put(a + 3, int0(x));
@@ -305,14 +299,14 @@
static private long makeLong(byte b7, byte b6, byte b5, byte b4,
byte b3, byte b2, byte b1, byte b0)
{
- return ((((long)b7 & 0xff) << 56) |
+ return ((((long)b7 ) << 56) |
(((long)b6 & 0xff) << 48) |
(((long)b5 & 0xff) << 40) |
(((long)b4 & 0xff) << 32) |
(((long)b3 & 0xff) << 24) |
(((long)b2 & 0xff) << 16) |
(((long)b1 & 0xff) << 8) |
- (((long)b0 & 0xff) << 0));
+ (((long)b0 & 0xff) ));
}
static long getLongL(ByteBuffer bb, int bi) {
@@ -323,7 +317,7 @@
bb._get(bi + 3),
bb._get(bi + 2),
bb._get(bi + 1),
- bb._get(bi + 0));
+ bb._get(bi ));
}
static long getLongL(long a) {
@@ -334,11 +328,11 @@
_get(a + 3),
_get(a + 2),
_get(a + 1),
- _get(a + 0));
+ _get(a ));
}
static long getLongB(ByteBuffer bb, int bi) {
- return makeLong(bb._get(bi + 0),
+ return makeLong(bb._get(bi ),
bb._get(bi + 1),
bb._get(bi + 2),
bb._get(bi + 3),
@@ -349,7 +343,7 @@
}
static long getLongB(long a) {
- return makeLong(_get(a + 0),
+ return makeLong(_get(a ),
_get(a + 1),
_get(a + 2),
_get(a + 3),
@@ -360,11 +354,11 @@
}
static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getLongB(bb, bi) : getLongL(bb, bi));
+ return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);
}
static long getLong(long a, boolean bigEndian) {
- return (bigEndian ? getLongB(a) : getLongL(a));
+ return bigEndian ? getLongB(a) : getLongL(a);
}
private static byte long7(long x) { return (byte)(x >> 56); }
@@ -374,7 +368,7 @@
private static byte long3(long x) { return (byte)(x >> 24); }
private static byte long2(long x) { return (byte)(x >> 16); }
private static byte long1(long x) { return (byte)(x >> 8); }
- private static byte long0(long x) { return (byte)(x >> 0); }
+ private static byte long0(long x) { return (byte)(x ); }
static void putLongL(ByteBuffer bb, int bi, long x) {
bb._put(bi + 7, long7(x));
@@ -384,7 +378,7 @@
bb._put(bi + 3, long3(x));
bb._put(bi + 2, long2(x));
bb._put(bi + 1, long1(x));
- bb._put(bi + 0, long0(x));
+ bb._put(bi , long0(x));
}
static void putLongL(long a, long x) {
@@ -395,11 +389,11 @@
_put(a + 3, long3(x));
_put(a + 2, long2(x));
_put(a + 1, long1(x));
- _put(a + 0, long0(x));
+ _put(a , long0(x));
}
static void putLongB(ByteBuffer bb, int bi, long x) {
- bb._put(bi + 0, long7(x));
+ bb._put(bi , long7(x));
bb._put(bi + 1, long6(x));
bb._put(bi + 2, long5(x));
bb._put(bi + 3, long4(x));
@@ -410,7 +404,7 @@
}
static void putLongB(long a, long x) {
- _put(a + 0, long7(x));
+ _put(a , long7(x));
_put(a + 1, long6(x));
_put(a + 2, long5(x));
_put(a + 3, long4(x));
@@ -454,11 +448,11 @@
}
static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi));
+ return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);
}
static float getFloat(long a, boolean bigEndian) {
- return (bigEndian ? getFloatB(a) : getFloatL(a));
+ return bigEndian ? getFloatB(a) : getFloatL(a);
}
static void putFloatL(ByteBuffer bb, int bi, float x) {
@@ -511,11 +505,11 @@
}
static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
- return (bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi));
+ return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);
}
static double getDouble(long a, boolean bigEndian) {
- return (bigEndian ? getDoubleB(a) : getDoubleL(a));
+ return bigEndian ? getDoubleB(a) : getDoubleL(a);
}
static void putDoubleL(ByteBuffer bb, int bi, double x) {
@@ -794,7 +788,7 @@
static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
long length);
static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
- long length);
+ long length);
static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
long length);
--- a/jdk/src/share/classes/java/nio/channels/FileLock.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/nio/channels/FileLock.java Wed Jul 05 17:18:01 2017 +0200
@@ -116,7 +116,7 @@
* @since 1.4
*/
-public abstract class FileLock {
+public abstract class FileLock implements AutoCloseable {
private final Channel channel;
private final long position;
@@ -299,6 +299,17 @@
public abstract void release() throws IOException;
/**
+ * This method invokes the {@link #release} method. It was added
+ * to the class so that it could be used in conjunction with the
+ * automatic resource management block construct.
+ *
+ * @since 1.7
+ */
+ public final void close() throws IOException {
+ release();
+ }
+
+ /**
* Returns a string describing the range, type, and validity of this lock.
*
* @return A descriptive string
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
/**
* This class implements the Dual-Pivot Quicksort algorithm by
- * Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. The algorithm
+ * Vladimir Yaroslavskiy, Jon Bentley, and Josh Bloch. The algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
@@ -36,7 +36,8 @@
* @author Jon Bentley
* @author Josh Bloch
*
- * @version 2009.11.29 m765.827.12i
+ * @version 2010.06.21 m765.827.12i:5\7
+ * @since 1.7
*/
final class DualPivotQuicksort {
@@ -68,7 +69,7 @@
private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
/*
- * Sorting methods for 7 primitive types.
+ * Sorting methods for seven primitive types.
*/
/**
@@ -77,7 +78,7 @@
* @param a the array to be sorted
*/
public static void sort(int[] a) {
- doSort(a, 0, a.length - 1);
+ sort(a, 0, a.length - 1, true);
}
/**
@@ -95,98 +96,132 @@
*/
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- doSort(a, fromIndex, toIndex - 1);
+ sort(a, fromIndex, toIndex - 1, true);
}
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in that the
- * {@code right} index is inclusive, and it does no range checking
- * on {@code left} or {@code right}.
+ * Sorts the specified range of the array into ascending order by the
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
*/
- private static void doSort(int[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- int ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
+ private static void sort(int[] a, int left, int right, boolean leftmost) {
+ int length = right - left + 1;
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void dualPivotQuicksort(int[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ int ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ int ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
+
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
- // Sort these elements using a 5-element sorting network
- int ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { int t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
- if (ae1 > ae2) { int t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { int t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { int t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { int t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { int t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
-
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ if (a[e3] < a[e2]) { int t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { int t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { int t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- int pivot1 = ae2; a[e2] = a[left];
- int pivot2 = ae4; a[e4] = a[right];
+ int pivot1 = a[e2];
+ int pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -194,16 +229,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
int ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -213,26 +246,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ int ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = pivot1;
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -240,20 +354,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- int ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ int ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -261,92 +374,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
a[k] = pivot1;
- a[great--] = ak;
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- int ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -355,7 +409,7 @@
* @param a the array to be sorted
*/
public static void sort(long[] a) {
- doSort(a, 0, a.length - 1);
+ sort(a, 0, a.length - 1, true);
}
/**
@@ -373,98 +427,132 @@
*/
public static void sort(long[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- doSort(a, fromIndex, toIndex - 1);
+ sort(a, fromIndex, toIndex - 1, true);
}
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in that the
- * {@code right} index is inclusive, and it does no range checking on
- * {@code left} or {@code right}.
+ * Sorts the specified range of the array into ascending order by the
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
*/
- private static void doSort(long[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- long ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
+ private static void sort(long[] a, int left, int right, boolean leftmost) {
+ int length = right - left + 1;
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void dualPivotQuicksort(long[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ long ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ long ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
+
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
- // Sort these elements using a 5-element sorting network
- long ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { long t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
- if (ae1 > ae2) { long t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { long t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { long t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { long t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { long t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
-
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ if (a[e3] < a[e2]) { long t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { long t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { long t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- long pivot1 = ae2; a[e2] = a[left];
- long pivot2 = ae4; a[e4] = a[right];
+ long pivot1 = a[e2];
+ long pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -472,16 +560,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
long ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -491,26 +577,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ long ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = pivot1;
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -518,20 +685,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- long ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ long ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -539,92 +705,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
a[k] = pivot1;
- a[great--] = ak;
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- long ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -633,7 +740,11 @@
* @param a the array to be sorted
*/
public static void sort(short[] a) {
- doSort(a, 0, a.length - 1);
+ if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ countingSort(a, 0, a.length - 1);
+ } else {
+ sort(a, 0, a.length - 1, true);
+ }
}
/**
@@ -651,115 +762,166 @@
*/
public static void sort(short[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- doSort(a, fromIndex, toIndex - 1);
+
+ if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ countingSort(a, fromIndex, toIndex - 1);
+ } else {
+ sort(a, fromIndex, toIndex - 1, true);
+ }
}
/** The number of distinct short values. */
private static final int NUM_SHORT_VALUES = 1 << 16;
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in that the
- * {@code right} index is inclusive, and it does no range checking on
- * {@code left} or {@code right}.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void doSort(short[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- short ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- // Use counting sort on huge arrays
- int[] count = new int[NUM_SHORT_VALUES];
-
- for (int i = left; i <= right; i++) {
- count[a[i] - Short.MIN_VALUE]++;
- }
- for (int i = 0, k = left; i < count.length && k <= right; i++) {
- short value = (short) (i + Short.MIN_VALUE);
-
- for (int s = count[i]; s > 0; s--) {
- a[k++] = value;
- }
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
+ * Sorts the specified range of the array by counting sort.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
- private static void dualPivotQuicksort(short[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
- int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ private static void countingSort(short[] a, int left, int right) {
+ int[] count = new int[NUM_SHORT_VALUES];
+
+ for (int i = left; i <= right; i++) {
+ count[a[i] - Short.MIN_VALUE]++;
+ }
+ for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) {
+ while (count[i] == 0) {
+ i--;
+ }
+ short value = (short) (i + Short.MIN_VALUE);
+ int s = count[i];
- // Sort these elements using a 5-element sorting network
- short ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ do {
+ a[k--] = value;
+ } while (--s > 0);
+ }
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending order by the
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
+ *
+ * @param a the array to be sorted
+ * @param left the index of the first element, inclusive, to be sorted
+ * @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
+ */
+ private static void sort(short[] a, int left, int right,boolean leftmost) {
+ int length = right - left + 1;
- if (ae1 > ae2) { short t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { short t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { short t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { short t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { short t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ short ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ short ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
+ int e3 = (left + right) >>> 1; // The midpoint
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
+
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { short t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+ if (a[e3] < a[e2]) { short t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { short t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { short t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- short pivot1 = ae2; a[e2] = a[left];
- short pivot2 = ae4; a[e4] = a[right];
+ short pivot1 = a[e2];
+ short pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -767,16 +929,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
short ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -786,26 +946,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ short ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = pivot1;
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -813,20 +1054,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- short ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ short ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -834,92 +1074,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
a[k] = pivot1;
- a[great--] = ak;
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- short ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -928,7 +1109,11 @@
* @param a the array to be sorted
*/
public static void sort(char[] a) {
- doSort(a, 0, a.length - 1);
+ if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ countingSort(a, 0, a.length - 1);
+ } else {
+ sort(a, 0, a.length - 1, true);
+ }
}
/**
@@ -946,113 +1131,166 @@
*/
public static void sort(char[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- doSort(a, fromIndex, toIndex - 1);
+
+ if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ countingSort(a, fromIndex, toIndex - 1);
+ } else {
+ sort(a, fromIndex, toIndex - 1, true);
+ }
}
/** The number of distinct char values. */
private static final int NUM_CHAR_VALUES = 1 << 16;
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in that the
- * {@code right} index is inclusive, and it does no range checking on
- * {@code left} or {@code right}.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void doSort(char[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- char ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- // Use counting sort on huge arrays
- int[] count = new int[NUM_CHAR_VALUES];
-
- for (int i = left; i <= right; i++) {
- count[a[i]]++;
- }
- for (int i = 0, k = left; i < count.length && k <= right; i++) {
- for (int s = count[i]; s > 0; s--) {
- a[k++] = (char) i;
- }
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
+ * Sorts the specified range of the array by counting sort.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
- private static void dualPivotQuicksort(char[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
- int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ private static void countingSort(char[] a, int left, int right) {
+ int[] count = new int[NUM_CHAR_VALUES];
+
+ for (int i = left; i <= right; i++) {
+ count[a[i]]++;
+ }
+ for (int i = 0, k = left; k <= right; i++) {
+ while (count[i] == 0) {
+ i++;
+ }
+ char value = (char) i;
+ int s = count[i];
- // Sort these elements using a 5-element sorting network
- char ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ do {
+ a[k++] = value;
+ } while (--s > 0);
+ }
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending order by the
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
+ *
+ * @param a the array to be sorted
+ * @param left the index of the first element, inclusive, to be sorted
+ * @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
+ */
+ private static void sort(char[] a, int left, int right, boolean leftmost) {
+ int length = right - left + 1;
- if (ae1 > ae2) { char t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { char t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { char t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { char t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { char t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ char ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ char ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
+ int e3 = (left + right) >>> 1; // The midpoint
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
+
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { char t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+ if (a[e3] < a[e2]) { char t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { char t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { char t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- char pivot1 = ae2; a[e2] = a[left];
- char pivot2 = ae4; a[e4] = a[right];
+ char pivot1 = a[e2];
+ char pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1060,16 +1298,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
char ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -1079,26 +1315,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ char ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = pivot1;
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1106,20 +1423,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- char ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ char ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -1127,92 +1443,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
a[k] = pivot1;
- a[great--] = ak;
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- char ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -1221,7 +1478,11 @@
* @param a the array to be sorted
*/
public static void sort(byte[] a) {
- doSort(a, 0, a.length - 1);
+ if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+ countingSort(a, 0, a.length - 1);
+ } else {
+ sort(a, 0, a.length - 1, true);
+ }
}
/**
@@ -1239,115 +1500,166 @@
*/
public static void sort(byte[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- doSort(a, fromIndex, toIndex - 1);
+
+ if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+ countingSort(a, fromIndex, toIndex - 1);
+ } else {
+ sort(a, fromIndex, toIndex - 1, true);
+ }
}
/** The number of distinct byte values. */
private static final int NUM_BYTE_VALUES = 1 << 8;
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in that the
- * {@code right} index is inclusive, and it does no range checking on
- * {@code left} or {@code right}.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void doSort(byte[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- byte ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
- // Use counting sort on huge arrays
- int[] count = new int[NUM_BYTE_VALUES];
-
- for (int i = left; i <= right; i++) {
- count[a[i] - Byte.MIN_VALUE]++;
- }
- for (int i = 0, k = left; i < count.length && k <= right; i++) {
- byte value = (byte) (i + Byte.MIN_VALUE);
-
- for (int s = count[i]; s > 0; s--) {
- a[k++] = value;
- }
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
+ * Sorts the specified range of the array by counting sort.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
- private static void dualPivotQuicksort(byte[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
- int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ private static void countingSort(byte[] a, int left, int right) {
+ int[] count = new int[NUM_BYTE_VALUES];
+
+ for (int i = left; i <= right; i++) {
+ count[a[i] - Byte.MIN_VALUE]++;
+ }
+ for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) {
+ while (count[i] == 0) {
+ i--;
+ }
+ byte value = (byte) (i + Byte.MIN_VALUE);
+ int s = count[i];
- // Sort these elements using a 5-element sorting network
- byte ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ do {
+ a[k--] = value;
+ } while (--s > 0);
+ }
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending order by the
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
+ *
+ * @param a the array to be sorted
+ * @param left the index of the first element, inclusive, to be sorted
+ * @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
+ */
+ private static void sort(byte[] a, int left, int right, boolean leftmost) {
+ int length = right - left + 1;
- if (ae1 > ae2) { byte t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { byte t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { byte t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { byte t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { byte t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ byte ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ byte ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
+ int e3 = (left + right) >>> 1; // The midpoint
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
+
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+ if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- byte pivot1 = ae2; a[e2] = a[left];
- byte pivot2 = ae4; a[e4] = a[right];
+ byte pivot1 = a[e2];
+ byte pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1355,16 +1667,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
byte ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -1374,26 +1684,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ byte ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = pivot1;
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1401,20 +1792,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- byte ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ byte ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -1422,92 +1812,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
a[k] = pivot1;
- a[great--] = ak;
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- byte ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -1531,7 +1862,7 @@
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty and the call is a no-op).
+ * the range to be sorted is empty (and the call is a no-op).
*
* <p>The {@code <} relation does not provide a total order on all float
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
@@ -1565,162 +1896,207 @@
*/
private static void sortNegZeroAndNaN(float[] a, int left, int right) {
/*
- * Phase 1: Count negative zeros and move NaNs to end of array
+ * Phase 1: Move NaNs to the end of the array.
*/
- final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
- int numNegativeZeros = 0;
- int n = right;
-
- for (int k = left; k <= n; k++) {
+ while (left <= right && Float.isNaN(a[right])) {
+ right--;
+ }
+ for (int k = right - 1; k >= left; k--) {
float ak = a[k];
- if (ak == 0.0f && NEGATIVE_ZERO == Float.floatToIntBits(ak)) {
- a[k] = 0.0f;
- numNegativeZeros++;
- } else if (ak != ak) { // i.e., ak is NaN
- a[k--] = a[n];
- a[n--] = Float.NaN;
+ if (ak != ak) { // a[k] is NaN
+ a[k] = a[right];
+ a[right] = ak;
+ right--;
}
}
/*
- * Phase 2: Sort everything except NaNs (which are already in place)
+ * Phase 2: Sort everything except NaNs (which are already in place).
*/
- doSort(a, left, n);
+ sort(a, left, right, true);
/*
- * Phase 3: Turn positive zeros back into negative zeros as appropriate
+ * Phase 3: Place negative zeros before positive zeros.
*/
- if (numNegativeZeros == 0) {
- return;
- }
-
- // Find first zero element
- int zeroIndex = findAnyZero(a, left, n);
-
- for (int i = zeroIndex - 1; i >= left && a[i] == 0.0f; i--) {
- zeroIndex = i;
- }
+ int hi = right;
- // Turn the right number of positive zeros back into negative zeros
- for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
- a[i] = -0.0f;
- }
- }
-
- /**
- * Returns the index of some zero element in the specified range via
- * binary search. The range is assumed to be sorted, and must contain
- * at least one zero.
- *
- * @param a the array to be searched
- * @param low the index of the first element, inclusive, to be searched
- * @param high the index of the last element, inclusive, to be searched
- */
- private static int findAnyZero(float[] a, int low, int high) {
- while (true) {
- int middle = (low + high) >>> 1;
+ /*
+ * Search first zero, or first positive, or last negative element.
+ */
+ while (left < hi) {
+ int middle = (left + hi) >>> 1;
float middleValue = a[middle];
if (middleValue < 0.0f) {
- low = middle + 1;
- } else if (middleValue > 0.0f) {
- high = middle - 1;
- } else { // middleValue == 0.0f
- return middle;
+ left = middle + 1;
+ } else {
+ hi = middle;
+ }
+ }
+
+ /*
+ * Skip the last negative value (if any) or all leading negative zeros.
+ */
+ while (left <= right && Float.floatToRawIntBits(a[left]) < 0) {
+ left++;
+ }
+
+ /*
+ * Move negative zeros to the beginning of the sub-range.
+ *
+ * Partitioning:
+ *
+ * +---------------------------------------------------+
+ * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
+ * +---------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * left p k
+ *
+ * Invariants:
+ *
+ * all in (*, left) < 0.0
+ * all in [left, p) == -0.0
+ * all in [p, k) == 0.0
+ * all in [k, right] >= 0.0
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ for (int k = left + 1, p = left; k <= right; k++) {
+ float ak = a[k];
+ if (ak != 0.0f) {
+ break;
+ }
+ if (Float.floatToRawIntBits(ak) < 0) { // ak is -0.0f
+ a[k] = 0.0f;
+ a[p++] = -0.0f;
}
}
}
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in three ways:
- * {@code right} index is inclusive, it does no range checking on
- * {@code left} or {@code right}, and it does not handle negative
- * zeros or NaNs in the array.
- *
- * @param a the array to be sorted, which must not contain -0.0f or NaN
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void doSort(float[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- float ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
-
- /**
* Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
*/
- private static void dualPivotQuicksort(float[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
- int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ private static void sort(float[] a, int left, int right,boolean leftmost) {
+ int length = right - left + 1;
- // Sort these elements using a 5-element sorting network
- float ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ float ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ float ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
- if (ae1 > ae2) { float t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { float t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { float t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { float t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { float t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
+ int e3 = (left + right) >>> 1; // The midpoint
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { float t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+ if (a[e3] < a[e2]) { float t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { float t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { float t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- float pivot1 = ae2; a[e2] = a[left];
- float pivot2 = ae4; a[e4] = a[right];
+ float pivot1 = a[e2];
+ float pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1728,16 +2104,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
float ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -1747,26 +2121,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ float ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = a[great];
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -1774,20 +2229,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- float ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ float ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -1795,92 +2249,33 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
- a[k] = pivot1;
- a[great--] = ak;
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
+ a[k] = a[great];
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- float ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
@@ -1938,162 +2333,207 @@
*/
private static void sortNegZeroAndNaN(double[] a, int left, int right) {
/*
- * Phase 1: Count negative zeros and move NaNs to end of array
+ * Phase 1: Move NaNs to the end of the array.
*/
- final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
- int numNegativeZeros = 0;
- int n = right;
-
- for (int k = left; k <= n; k++) {
+ while (left <= right && Double.isNaN(a[right])) {
+ right--;
+ }
+ for (int k = right - 1; k >= left; k--) {
double ak = a[k];
- if (ak == 0.0d && NEGATIVE_ZERO == Double.doubleToLongBits(ak)) {
- a[k] = 0.0d;
- numNegativeZeros++;
- } else if (ak != ak) { // i.e., ak is NaN
- a[k--] = a[n];
- a[n--] = Double.NaN;
+ if (ak != ak) { // a[k] is NaN
+ a[k] = a[right];
+ a[right] = ak;
+ right--;
}
}
/*
- * Phase 2: Sort everything except NaNs (which are already in place)
+ * Phase 2: Sort everything except NaNs (which are already in place).
*/
- doSort(a, left, n);
+ sort(a, left, right, true);
/*
- * Phase 3: Turn positive zeros back into negative zeros as appropriate
+ * Phase 3: Place negative zeros before positive zeros.
*/
- if (numNegativeZeros == 0) {
- return;
- }
-
- // Find first zero element
- int zeroIndex = findAnyZero(a, left, n);
-
- for (int i = zeroIndex - 1; i >= left && a[i] == 0.0d; i--) {
- zeroIndex = i;
- }
+ int hi = right;
- // Turn the right number of positive zeros back into negative zeros
- for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
- a[i] = -0.0d;
- }
- }
-
- /**
- * Returns the index of some zero element in the specified range via
- * binary search. The range is assumed to be sorted, and must contain
- * at least one zero.
- *
- * @param a the array to be searched
- * @param low the index of the first element, inclusive, to be searched
- * @param high the index of the last element, inclusive, to be searched
- */
- private static int findAnyZero(double[] a, int low, int high) {
- while (true) {
- int middle = (low + high) >>> 1;
+ /*
+ * Search first zero, or first positive, or last negative element.
+ */
+ while (left < hi) {
+ int middle = (left + hi) >>> 1;
double middleValue = a[middle];
if (middleValue < 0.0d) {
- low = middle + 1;
- } else if (middleValue > 0.0d) {
- high = middle - 1;
- } else { // middleValue == 0.0d
- return middle;
+ left = middle + 1;
+ } else {
+ hi = middle;
+ }
+ }
+
+ /*
+ * Skip the last negative value (if any) or all leading negative zeros.
+ */
+ while (left <= right && Double.doubleToRawLongBits(a[left]) < 0) {
+ left++;
+ }
+
+ /*
+ * Move negative zeros to the beginning of the sub-range.
+ *
+ * Partitioning:
+ *
+ * +---------------------------------------------------+
+ * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
+ * +---------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * left p k
+ *
+ * Invariants:
+ *
+ * all in (*, left) < 0.0
+ * all in [left, p) == -0.0
+ * all in [p, k) == 0.0
+ * all in [k, right] >= 0.0
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ for (int k = left + 1, p = left; k <= right; k++) {
+ double ak = a[k];
+ if (ak != 0.0d) {
+ break;
+ }
+ if (Double.doubleToRawLongBits(ak) < 0) { // ak is -0.0d
+ a[k] = 0.0d;
+ a[p++] = -0.0d;
}
}
}
/**
- * Sorts the specified range of the array into ascending order. This
- * method differs from the public {@code sort} method in three ways:
- * {@code right} index is inclusive, it does no range checking on
- * {@code left} or {@code right}, and it does not handle negative
- * zeros or NaNs in the array.
- *
- * @param a the array to be sorted, which must not contain -0.0d and NaN
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- */
- private static void doSort(double[] a, int left, int right) {
- // Use insertion sort on tiny arrays
- if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
- for (int i = left + 1; i <= right; i++) {
- double ai = a[i];
- int j;
- for (j = i - 1; j >= left && ai < a[j]; j--) {
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else { // Use Dual-Pivot Quicksort on large arrays
- dualPivotQuicksort(a, left, right);
- }
- }
-
- /**
* Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm.
+ * Dual-Pivot Quicksort algorithm. This method differs from the public
+ * {@code sort} method in that the {@code right} index is inclusive,
+ * it does no range checking on {@code left} or {@code right}, and has
+ * boolean flag whether insertion sort with sentinel is used or not.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param leftmost indicates if the part is the most left in the range
*/
- private static void dualPivotQuicksort(double[] a, int left, int right) {
- // Compute indices of five evenly spaced elements
- int sixth = (right - left + 1) / 6;
- int e1 = left + sixth;
- int e5 = right - sixth;
- int e3 = (left + right) >>> 1; // The midpoint
- int e4 = e3 + sixth;
- int e2 = e3 - sixth;
+ private static void sort(double[] a, int left,int right,boolean leftmost) {
+ int length = right - left + 1;
- // Sort these elements using a 5-element sorting network
- double ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+ // Use insertion sort on tiny arrays
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (!leftmost) {
+ /*
+ * Every element in adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid
+ * the j >= left check on each iteration.
+ */
+ for (int j, i = left + 1; i <= right; i++) {
+ double ai = a[i];
+ for (j = i - 1; ai < a[j]; j--) {
+ // assert j >= left;
+ a[j + 1] = a[j];
+ }
+ a[j + 1] = ai;
+ }
+ } else {
+ /*
+ * For case of leftmost part traditional (without a sentinel)
+ * insertion sort, optimized for server JVM, is used.
+ */
+ for (int i = left, j = i; i < right; j = ++i) {
+ double ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ return;
+ }
- if (ae1 > ae2) { double t = ae1; ae1 = ae2; ae2 = t; }
- if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
- if (ae1 > ae3) { double t = ae1; ae1 = ae3; ae3 = t; }
- if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
- if (ae1 > ae4) { double t = ae1; ae1 = ae4; ae4 = t; }
- if (ae3 > ae4) { double t = ae3; ae3 = ae4; ae4 = t; }
- if (ae2 > ae5) { double t = ae2; ae2 = ae5; ae5 = t; }
- if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
- if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
+ // Inexpensive approximation of length / 7
+ int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+ /*
+ * Sort five evenly spaced elements around (and including) the
+ * center element in the range. These elements will be used for
+ * pivot selection as described below. The choice for spacing
+ * these elements was empirically determined to work well on
+ * a wide variety of inputs.
+ */
+ int e3 = (left + right) >>> 1; // The midpoint
+ int e2 = e3 - seventh;
+ int e1 = e2 - seventh;
+ int e4 = e3 + seventh;
+ int e5 = e4 + seventh;
- a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+ // Sort these elements using insertion sort
+ if (a[e2] < a[e1]) { double t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+ if (a[e3] < a[e2]) { double t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ if (a[e4] < a[e3]) { double t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ if (a[e5] < a[e4]) { double t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+ if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+ if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+ if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+ }
+ }
+ }
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
- *
- * The pivots are stored in local variables, and the first and
- * the last of the elements to be sorted are moved to the locations
- * formerly occupied by the pivots. When partitioning is complete,
- * the pivots are swapped back into their final positions, and
- * excluded from subsequent sorting.
*/
- double pivot1 = ae2; a[e2] = a[left];
- double pivot2 = ae4; a[e4] = a[right];
+ double pivot1 = a[e2];
+ double pivot2 = a[e4];
// Pointers
- int less = left + 1; // The index of first element of center part
- int great = right - 1; // The index before first element of right part
+ int less = left; // The index of the first element of center part
+ int great = right; // The index before the first element of right part
- boolean pivotsDiffer = (pivot1 != pivot2);
+ if (pivot1 != pivot2) {
+ /*
+ * The first and the last elements to be sorted are moved to the
+ * locations formerly occupied by the pivots. When partitioning
+ * is complete, the pivots are swapped back into their final
+ * positions, and excluded from subsequent sorting.
+ */
+ a[e2] = a[left];
+ a[e4] = a[right];
- if (pivotsDiffer) {
+ /*
+ * Skip elements, which are less or greater than pivot values.
+ */
+ while (a[++less] < pivot1);
+ while (a[--great] > pivot2);
+
/*
* Partitioning:
*
- * left part center part right part
- * +------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +--------------------------------------------------------------+
+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
+ * +--------------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -2101,16 +2541,14 @@
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
outer:
for (int k = less; k <= great; k++) {
double ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
@@ -2120,26 +2558,107 @@
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
- a[great--] = ak;
+ }
+ a[great] = ak;
+ great--;
+ }
+ }
+
+ // Swap pivots into their final positions
+ a[left] = a[less - 1]; a[less - 1] = pivot1;
+ a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+ // Sort left and right parts recursively, excluding known pivots
+ sort(a, left, less - 2, leftmost);
+ sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 5/7 of the array),
+ * swap internal pivot values to ends.
+ */
+ if (less < e1 && e5 < great) {
+ /*
+ * Skip elements, which are equal to pivot values.
+ */
+ while (a[less] == pivot1) {
+ less++;
+ }
+ while (a[great] == pivot2) {
+ great--;
+ }
+
+ /*
+ * Partitioning:
+ *
+ * left part center part right part
+ * +----------------------------------------------------------+
+ * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
+ * +----------------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
+ *
+ * Invariants:
+ *
+ * all in (*, less) == pivot1
+ * pivot1 < all in [less, k) < pivot2
+ * all in (great, *) == pivot2
+ *
+ * Pointer k is the first index of ?-part.
+ */
+ outer:
+ for (int k = less; k <= great; k++) {
+ double ak = a[k];
+ if (ak == pivot1) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ less++;
+ } else if (ak == pivot2) { // Move a[k] to right part
+ while (a[great] == pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ if (a[great] == pivot1) {
+ a[k] = a[less];
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[less] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point zeros
+ * of different signs. Therefore in float and
+ * double sorting methods we have to use more
+ * accurate assignment a[less] = a[great].
+ */
+ a[less] = a[great];
+ less++;
+ } else { // pivot1 < a[great] < pivot2
+ a[k] = a[great];
+ }
+ a[great] = ak;
+ great--;
}
}
}
+
+ // Sort center part recursively
+ sort(a, less, great, false);
+
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way,
- * or "Dutch National Flag", partition:
+ * Partition degenerates to the traditional 3-way
+ * (or "Dutch National Flag") schema:
*
- * left part center part right part
- * +----------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +----------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
+ * left part center part right part
+ * +-------------------------------------------------+
+ * | < pivot | == pivot | ? | > pivot |
+ * +-------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * less k great
*
* Invariants:
*
@@ -2147,20 +2666,19 @@
* all in [less, k) == pivot
* all in (great, right) > pivot
*
- * Pointer k is the first index of ?-part
+ * Pointer k is the first index of ?-part.
*/
- for (int k = less; k <= great; k++) {
- double ak = a[k];
- if (ak == pivot1) {
+ for (int k = left; k <= great; k++) {
+ if (a[k] == pivot1) {
continue;
}
+ double ak = a[k];
+
if (ak < pivot1) { // Move a[k] to left part
- if (k != less) {
- a[k] = a[less];
- a[less] = ak;
- }
+ a[k] = a[less];
+ a[less] = ak;
less++;
- } else { // (a[k] > pivot1) - Move a[k] to right part
+ } else { // a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
@@ -2168,102 +2686,43 @@
* In other words, a[e3] acts as a sentinel for great.
*/
while (a[great] > pivot1) {
+ // assert great > k;
great--;
}
if (a[great] < pivot1) {
a[k] = a[less];
- a[less++] = a[great];
- a[great--] = ak;
+ a[less] = a[great];
+ less++;
} else { // a[great] == pivot1
- a[k] = pivot1;
- a[great--] = ak;
+ /*
+ * Even though a[great] equals to pivot1, the
+ * assignment a[k] = pivot1 may be incorrect,
+ * if a[great] and pivot1 are floating-point
+ * zeros of different signs. Therefore in float
+ * and double sorting methods we have to use
+ * more accurate assignment a[k] = a[great].
+ */
+ a[k] = a[great];
}
+ a[great] = ak;
+ great--;
}
}
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivot values
- doSort(a, left, less - 2);
- doSort(a, great + 2, right);
-
- /*
- * If pivot1 == pivot2, all elements from center
- * part are equal and, therefore, already sorted
- */
- if (!pivotsDiffer) {
- return;
- }
-
- /*
- * If center part is too large (comprises > 2/3 of the array),
- * swap internal pivot values to ends
- */
- if (less < e1 && great > e5) {
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part
- */
- outer:
- for (int k = less; k <= great; k++) {
- double ak = a[k];
- if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- a[less++] = pivot1;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great--] = pivot2;
- } else if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less++] = pivot1;
- }
- }
+ // Sort left and right parts recursively
+ sort(a, left, less - 1, leftmost);
+ sort(a, great + 1, right, false);
}
-
- // Sort center part recursively, excluding known pivot values
- doSort(a, less, great);
}
/**
- * Checks that {@code fromIndex} and {@code toIndex} are in
- * the range and throws an appropriate exception, if they aren't.
+ * Checks that {@code fromIndex} and {@code toIndex} are in the range,
+ * otherwise throws an appropriate exception.
*/
private static void rangeCheck(int length, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
- "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+ "fromIndex: " + fromIndex + " > toIndex: " + toIndex);
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
--- a/jdk/src/share/classes/java/util/Scanner.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/util/Scanner.java Wed Jul 05 17:18:01 2017 +0200
@@ -343,7 +343,7 @@
*
* @since 1.5
*/
-public final class Scanner implements Iterator<String> {
+public final class Scanner implements Iterator<String>, Closeable {
// Internal buffer used to hold input
private CharBuffer buf;
--- a/jdk/src/share/classes/java/util/logging/LogManager.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
import java.io.*;
import java.util.*;
import java.security.*;
+import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
@@ -154,10 +155,10 @@
= new PropertyChangeSupport(LogManager.class);
private final static Level defaultLevel = Level.INFO;
- // Table of known loggers. Maps names to Loggers.
- private Hashtable<String,WeakReference<Logger>> loggers =
- new Hashtable<String,WeakReference<Logger>>();
- // Tree of known loggers
+ // Table of named Loggers that maps names to Loggers.
+ private Hashtable<String,LoggerWeakRef> namedLoggers =
+ new Hashtable<String,LoggerWeakRef>();
+ // Tree of named Loggers
private LogNode root = new LogNode(null);
private Logger rootLogger;
@@ -417,6 +418,121 @@
}});
}
+
+ // loggerRefQueue holds LoggerWeakRef objects for Logger objects
+ // that have been GC'ed.
+ private final ReferenceQueue<Logger> loggerRefQueue
+ = new ReferenceQueue<Logger>();
+
+ // Package-level inner class.
+ // Helper class for managing WeakReferences to Logger objects.
+ //
+ // LogManager.namedLoggers
+ // - has weak references to all named Loggers
+ // - namedLoggers keeps the LoggerWeakRef objects for the named
+ // Loggers around until we can deal with the book keeping for
+ // the named Logger that is being GC'ed.
+ // LogManager.LogNode.loggerRef
+ // - has a weak reference to a named Logger
+ // - the LogNode will also keep the LoggerWeakRef objects for
+ // the named Loggers around; currently LogNodes never go away.
+ // Logger.kids
+ // - has a weak reference to each direct child Logger; this
+ // includes anonymous and named Loggers
+ // - anonymous Loggers are always children of the rootLogger
+ // which is a strong reference; rootLogger.kids keeps the
+ // LoggerWeakRef objects for the anonymous Loggers around
+ // until we can deal with the book keeping.
+ //
+ final class LoggerWeakRef extends WeakReference<Logger> {
+ private String name; // for namedLoggers cleanup
+ private LogNode node; // for loggerRef cleanup
+ private WeakReference<Logger> parentRef; // for kids cleanup
+
+ LoggerWeakRef(Logger logger) {
+ super(logger, loggerRefQueue);
+
+ name = logger.getName(); // save for namedLoggers cleanup
+ }
+
+ // dispose of this LoggerWeakRef object
+ void dispose() {
+ if (node != null) {
+ // if we have a LogNode, then we were a named Logger
+ // so clear namedLoggers weak ref to us
+ manager.namedLoggers.remove(name);
+ name = null; // clear our ref to the Logger's name
+
+ node.loggerRef = null; // clear LogNode's weak ref to us
+ node = null; // clear our ref to LogNode
+ }
+
+ if (parentRef != null) {
+ // this LoggerWeakRef has or had a parent Logger
+ Logger parent = parentRef.get();
+ if (parent != null) {
+ // the parent Logger is still there so clear the
+ // parent Logger's weak ref to us
+ parent.removeChildLogger(this);
+ }
+ parentRef = null; // clear our weak ref to the parent Logger
+ }
+ }
+
+ // set the node field to the specified value
+ void setNode(LogNode node) {
+ this.node = node;
+ }
+
+ // set the parentRef field to the specified value
+ void setParentRef(WeakReference<Logger> parentRef) {
+ this.parentRef = parentRef;
+ }
+ }
+
+ // Package-level method.
+ // Drain some Logger objects that have been GC'ed.
+ //
+ // drainLoggerRefQueueBounded() is called by addLogger() below
+ // and by Logger.getAnonymousLogger(String) so we'll drain up to
+ // MAX_ITERATIONS GC'ed Loggers for every Logger we add.
+ //
+ // On a WinXP VMware client, a MAX_ITERATIONS value of 400 gives
+ // us about a 50/50 mix in increased weak ref counts versus
+ // decreased weak ref counts in the AnonLoggerWeakRefLeak test.
+ // Here are stats for cleaning up sets of 400 anonymous Loggers:
+ // - test duration 1 minute
+ // - sample size of 125 sets of 400
+ // - average: 1.99 ms
+ // - minimum: 0.57 ms
+ // - maximum: 25.3 ms
+ //
+ // The same config gives us a better decreased weak ref count
+ // than increased weak ref count in the LoggerWeakRefLeak test.
+ // Here are stats for cleaning up sets of 400 named Loggers:
+ // - test duration 2 minutes
+ // - sample size of 506 sets of 400
+ // - average: 0.57 ms
+ // - minimum: 0.02 ms
+ // - maximum: 10.9 ms
+ //
+ private final static int MAX_ITERATIONS = 400;
+ final synchronized void drainLoggerRefQueueBounded() {
+ for (int i = 0; i < MAX_ITERATIONS; i++) {
+ if (loggerRefQueue == null) {
+ // haven't finished loading LogManager yet
+ break;
+ }
+
+ LoggerWeakRef ref = (LoggerWeakRef) loggerRefQueue.poll();
+ if (ref == null) {
+ break;
+ }
+ // a Logger object has been GC'ed so clean it up
+ ref.dispose();
+ }
+ }
+
/**
* Add a named logger. This does nothing and returns false if a logger
* with the same name is already registered.
@@ -439,13 +555,16 @@
throw new NullPointerException();
}
- WeakReference<Logger> ref = loggers.get(name);
+ // cleanup some Loggers that have been GC'ed
+ drainLoggerRefQueueBounded();
+
+ LoggerWeakRef ref = namedLoggers.get(name);
if (ref != null) {
if (ref.get() == null) {
- // Hashtable holds stale weak reference
- // to a logger which has been GC-ed.
- // Allow to register new one.
- loggers.remove(name);
+ // It's possible that the Logger was GC'ed after the
+ // drainLoggerRefQueueBounded() call above so allow
+ // a new one to be registered.
+ namedLoggers.remove(name);
} else {
// We already have a registered logger with the given name.
return false;
@@ -454,7 +573,8 @@
// We're adding a new logger.
// Note that we are creating a weak reference here.
- loggers.put(name, new WeakReference<Logger>(logger));
+ ref = new LoggerWeakRef(logger);
+ namedLoggers.put(name, ref);
// Apply any initial level defined for the new logger.
Level level = getLevelProperty(name+".level", null);
@@ -469,11 +589,11 @@
// Find the new node and its parent.
LogNode node = findNode(name);
- node.loggerRef = new WeakReference<Logger>(logger);
+ node.loggerRef = ref;
Logger parent = null;
LogNode nodep = node.parent;
while (nodep != null) {
- WeakReference<Logger> nodeRef = nodep.loggerRef;
+ LoggerWeakRef nodeRef = nodep.loggerRef;
if (nodeRef != null) {
parent = nodeRef.get();
if (parent != null) {
@@ -489,6 +609,9 @@
// Walk over the children and tell them we are their new parent.
node.walkAndSetParent(logger);
+ // new LogNode is ready so tell the LoggerWeakRef about it
+ ref.setNode(node);
+
return true;
}
@@ -572,7 +695,7 @@
* @return matching logger or null if none is found
*/
public synchronized Logger getLogger(String name) {
- WeakReference<Logger> ref = loggers.get(name);
+ LoggerWeakRef ref = namedLoggers.get(name);
if (ref == null) {
return null;
}
@@ -580,7 +703,7 @@
if (logger == null) {
// Hashtable holds stale weak reference
// to a logger which has been GC-ed.
- loggers.remove(name);
+ namedLoggers.remove(name);
}
return logger;
}
@@ -594,7 +717,7 @@
* @return enumeration of logger name strings
*/
public synchronized Enumeration<String> getLoggerNames() {
- return loggers.keys();
+ return namedLoggers.keys();
}
/**
@@ -942,7 +1065,7 @@
// Nested class to represent a node in our tree of named loggers.
private static class LogNode {
HashMap<String,LogNode> children;
- WeakReference<Logger> loggerRef;
+ LoggerWeakRef loggerRef;
LogNode parent;
LogNode(LogNode parent) {
@@ -958,7 +1081,7 @@
Iterator<LogNode> values = children.values().iterator();
while (values.hasNext()) {
LogNode node = values.next();
- WeakReference<Logger> ref = node.loggerRef;
+ LoggerWeakRef ref = node.loggerRef;
Logger logger = (ref == null) ? null : ref.get();
if (logger == null) {
node.walkAndSetParent(parent);
--- a/jdk/src/share/classes/java/util/logging/Logger.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -183,7 +183,7 @@
// We keep weak references from parents to children, but strong
// references from children to parents.
private volatile Logger parent; // our nearest parent.
- private ArrayList<WeakReference<Logger>> kids; // WeakReferences to loggers that have us as parent
+ private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
private volatile Level levelObject;
private volatile int levelValue; // current effective level value
@@ -366,13 +366,8 @@
*
* @return a newly created private Logger
*/
- public static synchronized Logger getAnonymousLogger() {
- LogManager manager = LogManager.getLogManager();
- Logger result = new Logger(null, null);
- result.anonymous = true;
- Logger root = manager.getLogger("");
- result.doSetParent(root);
- return result;
+ public static Logger getAnonymousLogger() {
+ return getAnonymousLogger(null);
}
/**
@@ -401,6 +396,8 @@
*/
public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
LogManager manager = LogManager.getLogManager();
+ // cleanup some Loggers that have been GC'ed
+ manager.drainLoggerRefQueueBounded();
Logger result = new Logger(null, resourceBundleName);
result.anonymous = true;
Logger root = manager.getLogger("");
@@ -1380,14 +1377,18 @@
synchronized (treeLock) {
// Remove ourself from any previous parent.
+ LogManager.LoggerWeakRef ref = null;
if (parent != null) {
// assert parent.kids != null;
- for (Iterator<WeakReference<Logger>> iter = parent.kids.iterator(); iter.hasNext(); ) {
- WeakReference<Logger> ref = iter.next();
+ for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
+ ref = iter.next();
Logger kid = ref.get();
if (kid == this) {
+ // ref is used down below to complete the reparenting
iter.remove();
break;
+ } else {
+ ref = null;
}
}
// We have now removed ourself from our parents' kids.
@@ -1396,9 +1397,14 @@
// Set our new parent.
parent = newParent;
if (parent.kids == null) {
- parent.kids = new ArrayList<WeakReference<Logger>>(2);
+ parent.kids = new ArrayList<LogManager.LoggerWeakRef>(2);
}
- parent.kids.add(new WeakReference<Logger>(this));
+ if (ref == null) {
+ // we didn't have a previous parent
+ ref = manager.new LoggerWeakRef(this);
+ }
+ ref.setParentRef(new WeakReference<Logger>(parent));
+ parent.kids.add(ref);
// As a result of the reparenting, the effective level
// may have changed for us and our children.
@@ -1407,6 +1413,21 @@
}
}
+ // Package-level method.
+ // Remove the weak reference for the specified child Logger from the
+ // kid list. We should only be called from LoggerWeakRef.dispose().
+ final void removeChildLogger(LogManager.LoggerWeakRef child) {
+ synchronized (treeLock) {
+ for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
+ LogManager.LoggerWeakRef ref = iter.next();
+ if (ref == child) {
+ iter.remove();
+ return;
+ }
+ }
+ }
+ }
+
// Recalculate the effective level for this node and
// recursively for our children.
@@ -1438,7 +1459,7 @@
// Recursively update the level on each of our kids.
if (kids != null) {
for (int i = 0; i < kids.size(); i++) {
- WeakReference<Logger> ref = kids.get(i);
+ LogManager.LoggerWeakRef ref = kids.get(i);
Logger kid = ref.get();
if (kid != null) {
kid.updateEffectiveLevel();
--- a/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,7 @@
package javax.imageio.stream;
+import java.io.Closeable;
import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteOrder;
@@ -42,7 +43,7 @@
* @see MemoryCacheImageInputStream
*
*/
-public interface ImageInputStream extends DataInput {
+public interface ImageInputStream extends DataInput, Closeable {
/**
* Sets the desired byte order for future reads of data values
--- a/jdk/src/share/classes/javax/sound/midi/MidiDevice.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/MidiDevice.java Wed Jul 05 17:18:01 2017 +0200
@@ -107,7 +107,7 @@
* @author Florian Bomers
*/
-public interface MidiDevice {
+public interface MidiDevice extends AutoCloseable {
/**
--- a/jdk/src/share/classes/javax/sound/midi/Receiver.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Receiver.java Wed Jul 05 17:18:01 2017 +0200
@@ -38,7 +38,7 @@
*
* @author Kara Kytle
*/
-public interface Receiver {
+public interface Receiver extends AutoCloseable {
//$$fb 2002-04-12: fix for 4662090: Contradiction in Receiver specification
--- a/jdk/src/share/classes/javax/sound/midi/Transmitter.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Transmitter.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,7 +35,7 @@
*
* @author Kara Kytle
*/
-public interface Transmitter {
+public interface Transmitter extends AutoCloseable {
/**
--- a/jdk/src/share/classes/javax/sound/sampled/Line.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/sampled/Line.java Wed Jul 05 17:18:01 2017 +0200
@@ -70,7 +70,7 @@
* @see LineEvent
* @since 1.3
*/
-public interface Line {
+public interface Line extends AutoCloseable {
/**
* Obtains the <code>Line.Info</code> object describing this
--- a/jdk/src/share/classes/javax/swing/JSplitPane.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JSplitPane.java Wed Jul 05 17:18:01 2017 +0200
@@ -242,19 +242,19 @@
/**
* Creates a new <code>JSplitPane</code> configured to arrange the child
- * components side-by-side horizontally with no continuous
- * layout, using two buttons for the components.
+ * components side-by-side horizontally, using two buttons for the components.
*/
public JSplitPane() {
- this(JSplitPane.HORIZONTAL_SPLIT, false,
- new JButton(UIManager.getString("SplitPane.leftButtonText")),
- new JButton(UIManager.getString("SplitPane.rightButtonText")));
+ this(JSplitPane.HORIZONTAL_SPLIT,
+ UIManager.getBoolean("SplitPane.continuousLayout"),
+ new JButton(UIManager.getString("SplitPane.leftButtonText")),
+ new JButton(UIManager.getString("SplitPane.rightButtonText")));
}
/**
* Creates a new <code>JSplitPane</code> configured with the
- * specified orientation and no continuous layout.
+ * specified orientation.
*
* @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
* <code>JSplitPane.VERTICAL_SPLIT</code>
@@ -263,7 +263,8 @@
*/
@ConstructorProperties({"orientation"})
public JSplitPane(int newOrientation) {
- this(newOrientation, false);
+ this(newOrientation,
+ UIManager.getBoolean("SplitPane.continuousLayout"));
}
@@ -287,9 +288,7 @@
/**
* Creates a new <code>JSplitPane</code> with the specified
- * orientation and
- * with the specified components that do not do continuous
- * redrawing.
+ * orientation and the specified components.
*
* @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
* <code>JSplitPane.VERTICAL_SPLIT</code>
@@ -307,7 +306,9 @@
public JSplitPane(int newOrientation,
Component newLeftComponent,
Component newRightComponent){
- this(newOrientation, false, newLeftComponent, newRightComponent);
+ this(newOrientation,
+ UIManager.getBoolean("SplitPane.continuousLayout"),
+ newLeftComponent, newRightComponent);
}
--- a/jdk/src/share/classes/javax/swing/JTable.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTable.java Wed Jul 05 17:18:01 2017 +0200
@@ -1048,7 +1048,7 @@
/**
* Returns the horizontal and vertical space between cells.
- * The default spacing is (1, 1), which provides room to draw the grid.
+ * The default spacing is look and feel dependent.
*
* @return the horizontal and vertical spacing between cells
* @see #setIntercellSpacing
@@ -1155,7 +1155,7 @@
/**
* Returns true if the table draws horizontal lines between cells, false if it
- * doesn't. The default is true.
+ * doesn't. The default value is look and feel dependent.
*
* @return true if the table draws horizontal lines between cells, false if it
* doesn't
@@ -1167,7 +1167,7 @@
/**
* Returns true if the table draws vertical lines between cells, false if it
- * doesn't. The default is true.
+ * doesn't. The default value is look and feel dependent.
*
* @return true if the table draws vertical lines between cells, false if it
* doesn't
--- a/jdk/src/share/classes/javax/swing/JTree.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTree.java Wed Jul 05 17:18:01 2017 +0200
@@ -1986,20 +1986,17 @@
* true if all nodes in the path are expanded
*/
public boolean isExpanded(TreePath path) {
+
if(path == null)
return false;
-
- // Is this node expanded?
- Boolean value = expandedState.get(path);
-
- if(value == null || !value.booleanValue())
- return false;
-
- // It is, make sure its parent is also expanded.
- TreePath parentPath = path.getParentPath();
-
- if(parentPath != null)
- return isExpanded(parentPath);
+ Object value;
+
+ do{
+ value = expandedState.get(path);
+ if(value == null || !((Boolean)value).booleanValue())
+ return false;
+ } while( (path=path.getParentPath())!=null );
+
return true;
}
--- a/jdk/src/share/classes/javax/swing/border/TitledBorder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/border/TitledBorder.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,20 @@
*/
package javax.swing.border;
-import sun.swing.SwingUtilities2;
-
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Point;
-import java.awt.Toolkit;
-import java.awt.Component;
-import java.awt.Dimension;
+import java.awt.geom.Path2D;
import java.beans.ConstructorProperties;
-
import javax.swing.JComponent;
+import javax.swing.JLabel;
import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicHTML;
/**
* A class which implements an arbitrary border
@@ -73,40 +71,40 @@
{
protected String title;
protected Border border;
- protected int titlePosition;
- protected int titleJustification;
- protected Font titleFont;
- protected Color titleColor;
+ protected int titlePosition;
+ protected int titleJustification;
+ protected Font titleFont;
+ protected Color titleColor;
- private Point textLoc = new Point();
+ private final JLabel label;
/**
* Use the default vertical orientation for the title text.
*/
static public final int DEFAULT_POSITION = 0;
/** Position the title above the border's top line. */
- static public final int ABOVE_TOP = 1;
+ static public final int ABOVE_TOP = 1;
/** Position the title in the middle of the border's top line. */
- static public final int TOP = 2;
+ static public final int TOP = 2;
/** Position the title below the border's top line. */
- static public final int BELOW_TOP = 3;
+ static public final int BELOW_TOP = 3;
/** Position the title above the border's bottom line. */
- static public final int ABOVE_BOTTOM = 4;
+ static public final int ABOVE_BOTTOM = 4;
/** Position the title in the middle of the border's bottom line. */
- static public final int BOTTOM = 5;
+ static public final int BOTTOM = 5;
/** Position the title below the border's bottom line. */
- static public final int BELOW_BOTTOM = 6;
+ static public final int BELOW_BOTTOM = 6;
/**
* Use the default justification for the title text.
*/
static public final int DEFAULT_JUSTIFICATION = 0;
/** Position title text at the left side of the border line. */
- static public final int LEFT = 1;
+ static public final int LEFT = 1;
/** Position title text in the center of the border line. */
- static public final int CENTER = 2;
+ static public final int CENTER = 2;
/** Position title text at the right side of the border line. */
- static public final int RIGHT = 3;
+ static public final int RIGHT = 3;
/** Position title text at the left side of the border line
* for left to right orientation, at the right side of the
* border line for right to left orientation.
@@ -132,7 +130,7 @@
*
* @param title the title the border should display
*/
- public TitledBorder(String title) {
+ public TitledBorder(String title) {
this(null, title, LEADING, DEFAULT_POSITION, null, null);
}
@@ -142,7 +140,7 @@
*
* @param border the border
*/
- public TitledBorder(Border border) {
+ public TitledBorder(Border border) {
this(border, "", LEADING, DEFAULT_POSITION, null, null);
}
@@ -167,9 +165,9 @@
* @param titlePosition the position for the title
*/
public TitledBorder(Border border,
- String title,
- int titleJustification,
- int titlePosition) {
+ String title,
+ int titleJustification,
+ int titlePosition) {
this(border, title, titleJustification,
titlePosition, null, null);
}
@@ -185,10 +183,10 @@
* @param titleFont the font for rendering the title
*/
public TitledBorder(Border border,
- String title,
- int titleJustification,
- int titlePosition,
- Font titleFont) {
+ String title,
+ int titleJustification,
+ int titlePosition,
+ Font titleFont) {
this(border, title, titleJustification,
titlePosition, titleFont, null);
}
@@ -207,11 +205,11 @@
*/
@ConstructorProperties({"border", "title", "titleJustification", "titlePosition", "titleFont", "titleColor"})
public TitledBorder(Border border,
- String title,
- int titleJustification,
- int titlePosition,
- Font titleFont,
- Color titleColor) {
+ String title,
+ int titleJustification,
+ int titlePosition,
+ Font titleFont,
+ Color titleColor) {
this.title = title;
this.border = border;
this.titleFont = titleFont;
@@ -219,6 +217,10 @@
setTitleJustification(titleJustification);
setTitlePosition(titlePosition);
+
+ this.label = new JLabel();
+ this.label.setOpaque(false);
+ this.label.putClientProperty(BasicHTML.propertyKey, null);
}
/**
@@ -232,178 +234,111 @@
* @param height the height of the painted border
*/
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
-
- Border border = getBorder();
-
- if (getTitle() == null || getTitle().equals("")) {
- if (border != null) {
- border.paintBorder(c, g, x, y, width, height);
- }
- return;
- }
-
- Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
- width - (EDGE_SPACING * 2),
- height - (EDGE_SPACING * 2));
- Font font = g.getFont();
- Color color = g.getColor();
+ Border border = getBorderUI();
+ String title = getTitle();
+ if ((title != null) && !title.isEmpty()) {
+ int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+ JLabel label = getLabel(c);
+ Dimension size = label.getPreferredSize();
+ Insets insets = (border != null)
+ ? border.getBorderInsets(c)
+ : new Insets(0, 0, 0, 0);
- g.setFont(getFont(c));
-
- JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
- FontMetrics fm = SwingUtilities2.getFontMetrics(jc, g);
- int fontHeight = fm.getHeight();
- int descent = fm.getDescent();
- int ascent = fm.getAscent();
- int diff;
- int stringWidth = SwingUtilities2.stringWidth(jc, fm,
- getTitle());
- Insets insets;
-
- if (border != null) {
- insets = border.getBorderInsets(c);
- } else {
- insets = new Insets(0, 0, 0, 0);
- }
+ int borderX = x + edge;
+ int borderY = y + edge;
+ int borderW = width - edge - edge;
+ int borderH = height - edge - edge;
- int titlePos = getTitlePosition();
- switch (titlePos) {
- case ABOVE_TOP:
- diff = ascent + descent + (Math.max(EDGE_SPACING,
- TEXT_SPACING*2) - EDGE_SPACING);
- grooveRect.y += diff;
- grooveRect.height -= diff;
- textLoc.y = grooveRect.y - (descent + TEXT_SPACING);
- break;
- case TOP:
- case DEFAULT_POSITION:
- diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING);
- grooveRect.y += diff;
- grooveRect.height -= diff;
- textLoc.y = (grooveRect.y - descent) +
- (insets.top + ascent + descent)/2;
- break;
- case BELOW_TOP:
- textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING;
- break;
- case ABOVE_BOTTOM:
- textLoc.y = (grooveRect.y + grooveRect.height) -
- (insets.bottom + descent + TEXT_SPACING);
- break;
- case BOTTOM:
- grooveRect.height -= fontHeight/2;
- textLoc.y = ((grooveRect.y + grooveRect.height) - descent) +
- ((ascent + descent) - insets.bottom)/2;
- break;
- case BELOW_BOTTOM:
- grooveRect.height -= fontHeight;
- textLoc.y = grooveRect.y + grooveRect.height + ascent +
- TEXT_SPACING;
- break;
- }
-
- int justification = getTitleJustification();
- if(isLeftToRight(c)) {
- if(justification==LEADING ||
- justification==DEFAULT_JUSTIFICATION) {
- justification = LEFT;
- }
- else if(justification==TRAILING) {
- justification = RIGHT;
- }
- }
- else {
- if(justification==LEADING ||
- justification==DEFAULT_JUSTIFICATION) {
- justification = RIGHT;
+ int labelY = y;
+ int labelH = size.height;
+ int position = getPosition();
+ switch (position) {
+ case ABOVE_TOP:
+ insets.left = 0;
+ insets.right = 0;
+ borderY += labelH - edge;
+ borderH -= labelH - edge;
+ break;
+ case TOP:
+ insets.top = edge + insets.top/2 - labelH/2;
+ if (insets.top < edge) {
+ borderY -= insets.top;
+ borderH += insets.top;
+ }
+ else {
+ labelY += insets.top;
+ }
+ break;
+ case BELOW_TOP:
+ labelY += insets.top + edge;
+ break;
+ case ABOVE_BOTTOM:
+ labelY += height - labelH - insets.bottom - edge;
+ break;
+ case BOTTOM:
+ labelY += height - labelH;
+ insets.bottom = edge + (insets.bottom - labelH) / 2;
+ if (insets.bottom < edge) {
+ borderH += insets.bottom;
+ }
+ else {
+ labelY -= insets.bottom;
+ }
+ break;
+ case BELOW_BOTTOM:
+ insets.left = 0;
+ insets.right = 0;
+ labelY += height - labelH;
+ borderH -= labelH - edge;
+ break;
}
- else if(justification==TRAILING) {
- justification = LEFT;
- }
- }
-
- switch (justification) {
- case LEFT:
- textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
- break;
- case RIGHT:
- textLoc.x = (grooveRect.x + grooveRect.width) -
- (stringWidth + TEXT_INSET_H + insets.right);
- break;
- case CENTER:
- textLoc.x = grooveRect.x +
- ((grooveRect.width - stringWidth) / 2);
- break;
- }
+ insets.left += edge + TEXT_INSET_H;
+ insets.right += edge + TEXT_INSET_H;
- // If title is positioned in middle of border AND its fontsize
- // is greater than the border's thickness, we'll need to paint
- // the border in sections to leave space for the component's background
- // to show through the title.
- //
- if (border != null) {
- if (((titlePos == TOP || titlePos == DEFAULT_POSITION) &&
- (grooveRect.y > textLoc.y - ascent)) ||
- (titlePos == BOTTOM &&
- (grooveRect.y + grooveRect.height < textLoc.y + descent))) {
-
- Rectangle clipRect = new Rectangle();
-
- // save original clip
- Rectangle saveClip = g.getClipBounds();
-
- // paint strip left of text
- clipRect.setBounds(saveClip);
- if (computeIntersection(clipRect, x, y, textLoc.x-1-x, height)) {
- g.setClip(clipRect);
- border.paintBorder(c, g, grooveRect.x, grooveRect.y,
- grooveRect.width, grooveRect.height);
- }
+ int labelX = x;
+ int labelW = width - insets.left - insets.right;
+ if (labelW > size.width) {
+ labelW = size.width;
+ }
+ switch (getJustification(c)) {
+ case LEFT:
+ labelX += insets.left;
+ break;
+ case RIGHT:
+ labelX += width - insets.right - labelW;
+ break;
+ case CENTER:
+ labelX += (width - labelW) / 2;
+ break;
+ }
- // paint strip right of text
- clipRect.setBounds(saveClip);
- if (computeIntersection(clipRect, textLoc.x+stringWidth+1, y,
- x+width-(textLoc.x+stringWidth+1), height)) {
- g.setClip(clipRect);
- border.paintBorder(c, g, grooveRect.x, grooveRect.y,
- grooveRect.width, grooveRect.height);
+ if (border != null) {
+ if ((position != TOP) && (position != BOTTOM)) {
+ border.paintBorder(c, g, borderX, borderY, borderW, borderH);
}
-
- if (titlePos == TOP || titlePos == DEFAULT_POSITION) {
- // paint strip below text
- clipRect.setBounds(saveClip);
- if (computeIntersection(clipRect, textLoc.x-1, textLoc.y+descent,
- stringWidth+2, y+height-textLoc.y-descent)) {
- g.setClip(clipRect);
- border.paintBorder(c, g, grooveRect.x, grooveRect.y,
- grooveRect.width, grooveRect.height);
+ else {
+ Graphics g2 = g.create();
+ if (g2 instanceof Graphics2D) {
+ Graphics2D g2d = (Graphics2D) g2;
+ Path2D path = new Path2D.Float();
+ path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false);
+ path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false);
+ path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY, borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false);
+ path.append(new Rectangle(borderX, labelY + labelH, borderW, borderY - labelY + borderH - labelH), false);
+ g2d.clip(path);
}
-
- } else { // titlePos == BOTTOM
- // paint strip above text
- clipRect.setBounds(saveClip);
- if (computeIntersection(clipRect, textLoc.x-1, y,
- stringWidth+2, textLoc.y - ascent - y)) {
- g.setClip(clipRect);
- border.paintBorder(c, g, grooveRect.x, grooveRect.y,
- grooveRect.width, grooveRect.height);
- }
+ border.paintBorder(c, g2, borderX, borderY, borderW, borderH);
+ g2.dispose();
}
-
- // restore clip
- g.setClip(saveClip);
-
- } else {
- border.paintBorder(c, g, grooveRect.x, grooveRect.y,
- grooveRect.width, grooveRect.height);
}
+ g.translate(labelX, labelY);
+ label.setSize(labelW, labelH);
+ label.paint(g);
+ g.translate(-labelX, -labelY);
}
-
- g.setColor(getTitleColor());
- SwingUtilities2.drawString(jc, g, getTitle(), textLoc.x, textLoc.y);
-
- g.setFont(font);
- g.setColor(color);
+ else if (border != null) {
+ border.paintBorder(c, g, x, y, width, height);
+ }
}
/**
@@ -412,69 +347,54 @@
* @param insets the object to be reinitialized
*/
public Insets getBorderInsets(Component c, Insets insets) {
- FontMetrics fm;
- int descent = 0;
- int ascent = 16;
- int height = 16;
-
- Border border = getBorder();
- if (border != null) {
- if (border instanceof AbstractBorder) {
- ((AbstractBorder)border).getBorderInsets(c, insets);
- } else {
- // Can't reuse border insets because the Border interface
- // can't be enhanced.
- Insets i = border.getBorderInsets(c);
- insets.top = i.top;
- insets.right = i.right;
- insets.bottom = i.bottom;
- insets.left = i.left;
- }
- } else {
- insets.left = insets.top = insets.right = insets.bottom = 0;
+ Border border = getBorderUI();
+ if (border == null) {
+ insets.set(0, 0, 0, 0);
+ }
+ else if (border instanceof AbstractBorder) {
+ AbstractBorder ab = (AbstractBorder) border;
+ insets = ab.getBorderInsets(c, insets);
}
-
- insets.left += EDGE_SPACING + TEXT_SPACING;
- insets.right += EDGE_SPACING + TEXT_SPACING;
- insets.top += EDGE_SPACING + TEXT_SPACING;
- insets.bottom += EDGE_SPACING + TEXT_SPACING;
-
- if(c == null || getTitle() == null || getTitle().equals("")) {
- return insets;
+ else {
+ Insets i = border.getBorderInsets(c);
+ insets.set(i.top, i.left, i.bottom, i.right);
}
+ String title = getTitle();
+ if ((title != null) && !title.isEmpty()) {
+ int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+ JLabel label = getLabel(c);
+ Dimension size = label.getPreferredSize();
- Font font = getFont(c);
-
- fm = c.getFontMetrics(font);
-
- if(fm != null) {
- descent = fm.getDescent();
- ascent = fm.getAscent();
- height = fm.getHeight();
- }
-
- switch (getTitlePosition()) {
- case ABOVE_TOP:
- insets.top += ascent + descent
- + (Math.max(EDGE_SPACING, TEXT_SPACING*2)
- - EDGE_SPACING);
- break;
- case TOP:
- case DEFAULT_POSITION:
- insets.top += ascent + descent;
- break;
- case BELOW_TOP:
- insets.top += ascent + descent + TEXT_SPACING;
- break;
- case ABOVE_BOTTOM:
- insets.bottom += ascent + descent + TEXT_SPACING;
- break;
- case BOTTOM:
- insets.bottom += ascent + descent;
- break;
- case BELOW_BOTTOM:
- insets.bottom += height;
- break;
+ switch (getPosition()) {
+ case ABOVE_TOP:
+ insets.top += size.height - edge;
+ break;
+ case TOP: {
+ if (insets.top < size.height) {
+ insets.top = size.height - edge;
+ }
+ break;
+ }
+ case BELOW_TOP:
+ insets.top += size.height;
+ break;
+ case ABOVE_BOTTOM:
+ insets.bottom += size.height;
+ break;
+ case BOTTOM: {
+ if (insets.bottom < size.height) {
+ insets.bottom = size.height - edge;
+ }
+ break;
+ }
+ case BELOW_BOTTOM:
+ insets.bottom += size.height - edge;
+ break;
+ }
+ insets.top += edge + TEXT_SPACING;
+ insets.left += edge + TEXT_SPACING;
+ insets.right += edge + TEXT_SPACING;
+ insets.bottom += edge + TEXT_SPACING;
}
return insets;
}
@@ -492,41 +412,14 @@
/**
* Returns the border of the titled border.
*/
- public Border getBorder() {
- Border b = border;
- if (b == null)
- b = UIManager.getBorder("TitledBorder.border");
- return b;
+ public Border getBorder() {
+ return border;
}
/**
* Returns the title-position of the titled border.
*/
public int getTitlePosition() {
- if (titlePosition == DEFAULT_POSITION) {
- Object value = UIManager.get("TitledBorder.position");
- if (value instanceof String) {
- String s = (String)value;
- if ("ABOVE_TOP".equalsIgnoreCase(s)) {
- return ABOVE_TOP;
- } else if ("TOP".equalsIgnoreCase(s)) {
- return TOP;
- } else if ("BELOW_TOP".equalsIgnoreCase(s)) {
- return BELOW_TOP;
- } else if ("ABOVE_BOTTOM".equalsIgnoreCase(s)) {
- return ABOVE_BOTTOM;
- } else if ("BOTTOM".equalsIgnoreCase(s)) {
- return BOTTOM;
- } else if ("BELOW_BOTTOM".equalsIgnoreCase(s)) {
- return BELOW_BOTTOM;
- }
- } else if (value instanceof Integer) {
- int i = (Integer)value;
- if (i >= 0 && i <= 6) {
- return i;
- }
- }
- }
return titlePosition;
}
@@ -539,20 +432,14 @@
* Returns the title-font of the titled border.
*/
public Font getTitleFont() {
- Font f = titleFont;
- if (f == null)
- f = UIManager.getFont("TitledBorder.font");
- return f;
+ return titleFont;
}
/**
* Returns the title-color of the titled border.
*/
public Color getTitleColor() {
- Color c = titleColor;
- if (c == null)
- c = UIManager.getColor("TitledBorder.titleColor");
- return c;
+ return titleColor;
}
@@ -576,18 +463,18 @@
*/
public void setTitlePosition(int titlePosition) {
switch (titlePosition) {
- case ABOVE_TOP:
- case TOP:
- case BELOW_TOP:
- case ABOVE_BOTTOM:
- case BOTTOM:
- case BELOW_BOTTOM:
- case DEFAULT_POSITION:
+ case ABOVE_TOP:
+ case TOP:
+ case BELOW_TOP:
+ case ABOVE_BOTTOM:
+ case BOTTOM:
+ case BELOW_BOTTOM:
+ case DEFAULT_POSITION:
this.titlePosition = titlePosition;
break;
- default:
- throw new IllegalArgumentException(titlePosition +
- " is not a valid title position.");
+ default:
+ throw new IllegalArgumentException(titlePosition +
+ " is not a valid title position.");
}
}
@@ -624,7 +511,7 @@
* @param titleColor the color for the border title
*/
public void setTitleColor(Color titleColor) {
- this.titleColor = titleColor;
+ this.titleColor = titleColor;
}
/**
@@ -636,22 +523,18 @@
Insets insets = getBorderInsets(c);
Dimension minSize = new Dimension(insets.right+insets.left,
insets.top+insets.bottom);
- Font font = getFont(c);
- FontMetrics fm = c.getFontMetrics(font);
- JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
- switch (getTitlePosition()) {
- case ABOVE_TOP:
- case BELOW_BOTTOM:
- minSize.width = Math.max(SwingUtilities2.stringWidth(jc, fm,
- getTitle()), minSize.width);
- break;
- case BELOW_TOP:
- case ABOVE_BOTTOM:
- case TOP:
- case BOTTOM:
- case DEFAULT_POSITION:
- default:
- minSize.width += SwingUtilities2.stringWidth(jc, fm, getTitle());
+ String title = getTitle();
+ if ((title != null) && !title.isEmpty()) {
+ JLabel label = getLabel(c);
+ Dimension size = label.getPreferredSize();
+
+ int position = getPosition();
+ if ((position != ABOVE_TOP) && (position != BELOW_BOTTOM)) {
+ minSize.width += size.width;
+ }
+ else if (minSize.width < size.width) {
+ minSize.width += size.width;
+ }
}
return minSize;
}
@@ -674,48 +557,36 @@
if (height < 0) {
throw new IllegalArgumentException("Height must be >= 0");
}
+ Border border = getBorderUI();
String title = getTitle();
- if (title != null && !"".equals(title)) {
- Font font = getFont(c);
- Border border2 = getBorder();
- Insets borderInsets;
- if (border2 != null) {
- borderInsets = border2.getBorderInsets(c);
- }
- else {
- borderInsets = new Insets(0, 0, 0, 0);
- }
- FontMetrics fm = c.getFontMetrics(font);
- int fontHeight = fm.getHeight();
- int descent = fm.getDescent();
- int ascent = fm.getAscent();
- int y = EDGE_SPACING;
- int h = height - EDGE_SPACING * 2;
- int diff;
- switch (getTitlePosition()) {
- case ABOVE_TOP:
- diff = ascent + descent + (Math.max(EDGE_SPACING,
- TEXT_SPACING * 2) -
- EDGE_SPACING);
- return y + diff - (descent + TEXT_SPACING);
- case TOP:
- case DEFAULT_POSITION:
- diff = Math.max(0, ((ascent/2) + TEXT_SPACING) -
- EDGE_SPACING);
- return (y + diff - descent) +
- (borderInsets.top + ascent + descent)/2;
- case BELOW_TOP:
- return y + borderInsets.top + ascent + TEXT_SPACING;
- case ABOVE_BOTTOM:
- return (y + h) - (borderInsets.bottom + descent +
- TEXT_SPACING);
- case BOTTOM:
- h -= fontHeight / 2;
- return ((y + h) - descent) +
- ((ascent + descent) - borderInsets.bottom)/2;
- case BELOW_BOTTOM:
- h -= fontHeight;
- return y + h + ascent + TEXT_SPACING;
+ if ((title != null) && !title.isEmpty()) {
+ int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+ JLabel label = getLabel(c);
+ Dimension size = label.getPreferredSize();
+ Insets insets = (border != null)
+ ? border.getBorderInsets(c)
+ : new Insets(0, 0, 0, 0);
+
+ int baseline = label.getBaseline(size.width, size.height);
+ switch (getPosition()) {
+ case ABOVE_TOP:
+ return baseline;
+ case TOP:
+ insets.top = edge + (insets.top - size.height) / 2;
+ return (insets.top < edge)
+ ? baseline
+ : baseline + insets.top;
+ case BELOW_TOP:
+ return baseline + insets.top + edge;
+ case ABOVE_BOTTOM:
+ return baseline + height - size.height - insets.bottom - edge;
+ case BOTTOM:
+ insets.bottom = edge + (insets.bottom - size.height) / 2;
+ return (insets.bottom < edge)
+ ? baseline + height - size.height
+ : baseline + height - size.height + insets.bottom;
+ case BELOW_BOTTOM:
+ return baseline + height - size.height;
}
}
return -1;
@@ -732,44 +603,111 @@
public Component.BaselineResizeBehavior getBaselineResizeBehavior(
Component c) {
super.getBaselineResizeBehavior(c);
- switch(getTitlePosition()) {
- case TitledBorder.ABOVE_TOP:
- case TitledBorder.TOP:
- case TitledBorder.DEFAULT_POSITION:
- case TitledBorder.BELOW_TOP:
- return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
- case TitledBorder.ABOVE_BOTTOM:
- case TitledBorder.BOTTOM:
- case TitledBorder.BELOW_BOTTOM:
- return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
+ switch (getPosition()) {
+ case TitledBorder.ABOVE_TOP:
+ case TitledBorder.TOP:
+ case TitledBorder.BELOW_TOP:
+ return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
+ case TitledBorder.ABOVE_BOTTOM:
+ case TitledBorder.BOTTOM:
+ case TitledBorder.BELOW_BOTTOM:
+ return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
}
return Component.BaselineResizeBehavior.OTHER;
}
+ private Border getBorderUI() {
+ Border border = getBorder();
+ return border != null
+ ? border
+ : UIManager.getBorder("TitledBorder.border");
+ }
+
+ private int getPosition() {
+ int position = getTitlePosition();
+ if (position != DEFAULT_POSITION) {
+ return position;
+ }
+ Object value = UIManager.get("TitledBorder.position");
+ if (value instanceof Integer) {
+ int i = (Integer) value;
+ if ((0 < i) && (i <= 6)) {
+ return i;
+ }
+ }
+ else if (value instanceof String) {
+ String s = (String) value;
+ if (s.equalsIgnoreCase("ABOVE_TOP")) {
+ return ABOVE_TOP;
+ }
+ if (s.equalsIgnoreCase("TOP")) {
+ return TOP;
+ }
+ if (s.equalsIgnoreCase("BELOW_TOP")) {
+ return BELOW_TOP;
+ }
+ if (s.equalsIgnoreCase("ABOVE_BOTTOM")) {
+ return ABOVE_BOTTOM;
+ }
+ if (s.equalsIgnoreCase("BOTTOM")) {
+ return BOTTOM;
+ }
+ if (s.equalsIgnoreCase("BELOW_BOTTOM")) {
+ return BELOW_BOTTOM;
+ }
+ }
+ return TOP;
+ }
+
+ private int getJustification(Component c) {
+ int justification = getTitleJustification();
+ if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) {
+ return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT;
+ }
+ if (justification == TRAILING) {
+ return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT;
+ }
+ return justification;
+ }
+
protected Font getFont(Component c) {
- Font font;
- if ((font = getTitleFont()) != null) {
+ Font font = getTitleFont();
+ if (font != null) {
+ return font;
+ }
+ font = UIManager.getFont("TitledBorder.font");
+ if (font != null) {
return font;
- } else if (c != null && (font = c.getFont()) != null) {
- return font;
+ }
+ if (c != null) {
+ font = c.getFont();
+ if (font != null) {
+ return font;
+ }
}
return new Font(Font.DIALOG, Font.PLAIN, 12);
}
- private static boolean computeIntersection(Rectangle dest,
- int rx, int ry, int rw, int rh) {
- int x1 = Math.max(rx, dest.x);
- int x2 = Math.min(rx + rw, dest.x + dest.width);
- int y1 = Math.max(ry, dest.y);
- int y2 = Math.min(ry + rh, dest.y + dest.height);
- dest.x = x1;
- dest.y = y1;
- dest.width = x2 - x1;
- dest.height = y2 - y1;
+ private Color getColor(Component c) {
+ Color color = getTitleColor();
+ if (color != null) {
+ return color;
+ }
+ color = UIManager.getColor("TitledBorder.titleColor");
+ if (color != null) {
+ return color;
+ }
+ return (c != null)
+ ? c.getForeground()
+ : null;
+ }
- if (dest.width <= 0 || dest.height <= 0) {
- return false;
- }
- return true;
+ private JLabel getLabel(Component c) {
+ this.label.setText(getTitle());
+ this.label.setFont(getFont(c));
+ this.label.setForeground(getColor(c));
+ this.label.setComponentOrientation(c.getComponentOrientation());
+ this.label.setEnabled(c.isEnabled());
+ return this.label;
}
}
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Wed Jul 05 17:18:01 2017 +0200
@@ -195,9 +195,8 @@
}
ButtonModel model = b.getModel();
+ model.setPressed(false);
model.setArmed(false);
- model.setPressed(false);
-
b.repaint();
}
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java Wed Jul 05 17:18:01 2017 +0200
@@ -876,7 +876,7 @@
String name = getName();
if (TOGGLE_SORT_ORDER == name) {
JTable table = th.getTable();
- RowSorter sorter = table.getRowSorter();
+ RowSorter sorter = table == null ? null : table.getRowSorter();
if (sorter != null) {
int columnIndex = ui.getSelectedColumnIndex();
columnIndex = table.convertColumnIndexToModel(
--- a/jdk/src/share/classes/javax/swing/plaf/nimbus/skin.laf Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/skin.laf Wed Jul 05 17:18:01 2017 +0200
@@ -21276,6 +21276,7 @@
<uiProperty name="centerOneTouchButtons" type="BOOLEAN" value="true"/>
<uiProperty name="oneTouchButtonOffset" type="INT" value="30"/>
<uiProperty name="oneTouchExpandable" type="BOOLEAN" value="false"/>
+ <uiProperty name="continuousLayout" type="BOOLEAN" value="true"/>
</uiproperties>
</style>
<backgroundStates>
--- a/jdk/src/share/classes/sun/awt/PlatformFont.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/PlatformFont.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,10 +25,10 @@
package sun.awt;
-import java.awt.GraphicsEnvironment;
import java.awt.peer.FontPeer;
import java.util.Locale;
import java.util.Vector;
+import sun.font.SunFontManager;
import sun.java2d.FontSupport;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
@@ -57,9 +57,9 @@
protected static String osVersion;
public PlatformFont(String name, int style){
- GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
- if (ge instanceof FontSupport) {
- fontConfig = ((FontSupport)ge).getFontConfiguration();
+ SunFontManager sfm = SunFontManager.getInstance();
+ if (sfm instanceof FontSupport) {
+ fontConfig = ((FontSupport)sfm).getFontConfiguration();
}
if (fontConfig == null) {
return;
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Jul 05 17:18:01 2017 +0200
@@ -39,6 +39,7 @@
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import sun.util.logging.PlatformLogger;
import sun.misc.SoftCache;
@@ -592,7 +593,7 @@
}
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
- if(postEventQueue != null) {
+ if (postEventQueue != null) {
postEventQueue.postEvent(event);
}
}
@@ -610,16 +611,29 @@
postEvent(targetToAppContext(e.getSource()), pe);
}
+ private static final Lock flushLock = new ReentrantLock();
+ private static boolean isFlushingPendingEvents = false;
+
/*
* Flush any pending events which haven't been posted to the AWT
* EventQueue yet.
*/
public static void flushPendingEvents() {
- AppContext appContext = AppContext.getAppContext();
- PostEventQueue postEventQueue =
- (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
- if(postEventQueue != null) {
- postEventQueue.flush();
+ flushLock.lock();
+ try {
+ // Don't call flushPendingEvents() recursively
+ if (!isFlushingPendingEvents) {
+ isFlushingPendingEvents = true;
+ AppContext appContext = AppContext.getAppContext();
+ PostEventQueue postEventQueue =
+ (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
+ if (postEventQueue != null) {
+ postEventQueue.flush();
+ }
+ }
+ } finally {
+ isFlushingPendingEvents = false;
+ flushLock.unlock();
}
}
@@ -1930,6 +1944,25 @@
return (Window)comp;
}
+ /**
+ * Returns the value of the system property indicated by the specified key.
+ */
+ public static String getSystemProperty(final String key) {
+ return (String)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty(key);
+ }
+ });
+ }
+
+ /**
+ * Returns the boolean value of the system property indicated by the specified key.
+ */
+ protected static Boolean getBooleanSystemProperty(String key) {
+ return Boolean.valueOf(AccessController.
+ doPrivileged(new GetBooleanAction(key)));
+ }
+
private static Boolean sunAwtDisableMixing = null;
/**
@@ -1938,9 +1971,7 @@
*/
public synchronized static boolean getSunAwtDisableMixing() {
if (sunAwtDisableMixing == null) {
- sunAwtDisableMixing = Boolean.valueOf(
- AccessController.doPrivileged(
- new GetBooleanAction("sun.awt.disableMixing")));
+ sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
}
return sunAwtDisableMixing.booleanValue();
}
@@ -2079,12 +2110,14 @@
eventQueue = eq;
}
- public boolean noEvents() {
+ public synchronized boolean noEvents() {
return queueHead == null;
}
/*
- * Continually post pending AWTEvents to the Java EventQueue.
+ * Continually post pending AWTEvents to the Java EventQueue. The method
+ * is synchronized to ensure the flush is completed before a new event
+ * can be posted to this queue.
*/
public synchronized void flush() {
EventQueueItem tempQueue = queueHead;
--- a/jdk/src/share/classes/sun/font/FontUtilities.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/font/FontUtilities.java Wed Jul 05 17:18:01 2017 +0200
@@ -60,6 +60,10 @@
static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf";
+ private static boolean debugFonts = false;
+ private static PlatformLogger logger = null;
+ private static boolean logging;
+
// This static initializer block figures out the OS constants.
static {
@@ -115,6 +119,25 @@
File lucidaFile = new File(jreFontDirName + File.separator
+ LUCIDA_FILE_NAME);
isOpenJDK = !lucidaFile.exists();
+
+ String debugLevel =
+ System.getProperty("sun.java2d.debugfonts");
+
+ if (debugLevel != null && !debugLevel.equals("false")) {
+ debugFonts = true;
+ logger = PlatformLogger.getLogger("sun.java2d");
+ if (debugLevel.equals("warning")) {
+ logger.setLevel(PlatformLogger.WARNING);
+ } else if (debugLevel.equals("severe")) {
+ logger.setLevel(PlatformLogger.SEVERE);
+ }
+ }
+
+ if (debugFonts) {
+ logger = PlatformLogger.getLogger("sun.java2d");
+ logging = logger.isEnabled();
+ }
+
return null;
}
});
@@ -140,32 +163,6 @@
*/
public static final int MAX_LAYOUT_CHARCODE = 0x206F;
- private static boolean debugFonts = false;
- private static PlatformLogger logger = null;
- private static boolean logging;
-
- static {
-
- String debugLevel =
- System.getProperty("sun.java2d.debugfonts");
-
- if (debugLevel != null && !debugLevel.equals("false")) {
- debugFonts = true;
- logger = PlatformLogger.getLogger("sun.java2d");
- if (debugLevel.equals("warning")) {
- logger.setLevel(PlatformLogger.WARNING);
- } else if (debugLevel.equals("severe")) {
- logger.setLevel(PlatformLogger.SEVERE);
- }
- }
-
- if (debugFonts) {
- logger = PlatformLogger.getLogger("sun.java2d");
- logging = logger.isEnabled();
- }
-
- }
-
/**
* Calls the private getFont2D() method in java.awt.Font objects.
*
--- a/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,7 +24,6 @@
*/
package sun.io;
-import sun.nio.cs.Surrogate;
import sun.nio.cs.ext.DoubleByte;
import static sun.nio.cs.CharsetMapping.*;
--- a/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,7 +24,6 @@
*/
package sun.io;
-import sun.nio.cs.Surrogate;
import sun.nio.cs.ext.DoubleByte;
import static sun.nio.cs.CharsetMapping.*;
--- a/jdk/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java Wed Jul 05 17:18:01 2017 +0200
@@ -59,17 +59,12 @@
* Headless decorator implementation of a SunGraphicsEnvironment
*/
-public class HeadlessGraphicsEnvironment extends GraphicsEnvironment
- implements FontSupport {
+public class HeadlessGraphicsEnvironment extends GraphicsEnvironment {
private GraphicsEnvironment ge;
- private FontSupport fontSupport;
public HeadlessGraphicsEnvironment(GraphicsEnvironment ge) {
this.ge = ge;
- if (ge instanceof FontSupport) {
- fontSupport = (FontSupport)ge;
- }
}
public GraphicsDevice[] getScreenDevices()
@@ -101,13 +96,6 @@
public String[] getAvailableFontFamilyNames(Locale l) {
return ge.getAvailableFontFamilyNames(l); }
- public FontConfiguration getFontConfiguration() {
- if (fontSupport != null) {
- return fontSupport.getFontConfiguration();
- }
- return null;
- }
-
/* Used by FontManager : internal API */
public GraphicsEnvironment getSunGraphicsEnvironment() {
return ge;
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -208,7 +208,7 @@
Method method = null;
try {
method = clazz.getMethod("main", String[].class);
- } catch (Exception e) {
+ } catch (NoSuchMethodException nsme) {
ostream.println(getLocalizedMessage("java.launcher.cls.error4",
classname));
throw new RuntimeException("Main method not found in " + classname);
@@ -225,8 +225,7 @@
throw new RuntimeException("Main method is not static in class " +
classname);
}
- Class<?> rType = method.getReturnType();
- if (!rType.isPrimitive() || !rType.getName().equals("void")) {
+ if (method.getReturnType() != java.lang.Void.TYPE) {
ostream.println(getLocalizedMessage("java.launcher.cls.error3",
classname));
throw new RuntimeException("Main method must return a value" +
--- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Wed Jul 05 17:18:01 2017 +0200
@@ -52,14 +52,16 @@
boolean http10 = false;
/* for formatting the Date: header */
- static TimeZone tz;
- static DateFormat df;
- static {
- String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
- tz = TimeZone.getTimeZone ("GMT");
- df = new SimpleDateFormat (pattern, Locale.US);
- df.setTimeZone (tz);
- }
+ private static final String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
+ private static final TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
+ private static final ThreadLocal<DateFormat> dateFormat =
+ new ThreadLocal<DateFormat>() {
+ @Override protected DateFormat initialValue() {
+ DateFormat df = new SimpleDateFormat(pattern, Locale.US);
+ df.setTimeZone(gmtTZ);
+ return df;
+ }
+ };
private static final String HEAD = "HEAD";
@@ -206,7 +208,7 @@
PlaceholderOutputStream o = getPlaceholderResponseBody();
tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
boolean noContentToSend = false; // assume there is content
- rspHdrs.set ("Date", df.format (new Date()));
+ rspHdrs.set ("Date", dateFormat.get().format (new Date()));
/* check for response type that is not allowed to send a body */
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Jul 05 17:18:01 2017 +0200
@@ -2331,7 +2331,7 @@
* closed the connection to the web server.
*/
private void disconnectWeb() throws IOException {
- if (usingProxy()) {
+ if (usingProxy() && http.isKeepingAlive()) {
responseCode = -1;
// clean up, particularly, skip the content part
// of a 401 error response
--- a/jdk/src/share/classes/sun/nio/cs/Surrogate.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/Surrogate.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,8 +34,9 @@
* Utility class for dealing with surrogates.
*
* @author Mark Reinhold
+ * @author Martin Buchholz
+ * @author Ulf Zibis
*/
-
public class Surrogate {
private Surrogate() { }
@@ -75,16 +76,9 @@
}
/**
- * Tells whether or not the given UCS-4 character is in the Basic
- * Multilingual Plane, and can be represented using a single char.
- */
- public static boolean isBMPCodePoint(int uc) {
- return uc >> 16 == 0;
- }
-
- /**
* Tells whether or not the given UCS-4 character must be represented as a
* surrogate pair in UTF-16.
+ * Use of {@link Character#isSupplementaryCodePoint} is generally preferred.
*/
public static boolean neededFor(int uc) {
return Character.isSupplementaryCodePoint(uc);
@@ -92,24 +86,25 @@
/**
* Returns the high UTF-16 surrogate for the given supplementary UCS-4 character.
+ * Use of {@link Character#highSurrogate} is generally preferred.
*/
public static char high(int uc) {
assert Character.isSupplementaryCodePoint(uc);
- return (char)((uc >> 10)
- + (Character.MIN_HIGH_SURROGATE
- - (Character.MIN_SUPPLEMENTARY_CODE_POINT >> 10)));
+ return Character.highSurrogate(uc);
}
/**
* Returns the low UTF-16 surrogate for the given supplementary UCS-4 character.
+ * Use of {@link Character#lowSurrogate} is generally preferred.
*/
public static char low(int uc) {
assert Character.isSupplementaryCodePoint(uc);
- return (char)((uc & 0x3ff) + Character.MIN_LOW_SURROGATE);
+ return Character.lowSurrogate(uc);
}
/**
* Converts the given surrogate pair into a 32-bit UCS-4 character.
+ * Use of {@link Character#toCodePoint} is generally preferred.
*/
public static int toUCS4(char c, char d) {
assert Character.isHighSurrogate(c) && Character.isLowSurrogate(d);
@@ -290,8 +285,9 @@
* error() will return a descriptive result object
*/
public int generate(int uc, int len, CharBuffer dst) {
- if (Surrogate.isBMPCodePoint(uc)) {
- if (Surrogate.is(uc)) {
+ if (Character.isBmpCodePoint(uc)) {
+ char c = (char) uc;
+ if (Character.isSurrogate(c)) {
error = CoderResult.malformedForLength(len);
return -1;
}
@@ -299,16 +295,16 @@
error = CoderResult.OVERFLOW;
return -1;
}
- dst.put((char)uc);
+ dst.put(c);
error = null;
return 1;
- } else if (Character.isSupplementaryCodePoint(uc)) {
+ } else if (Character.isValidCodePoint(uc)) {
if (dst.remaining() < 2) {
error = CoderResult.OVERFLOW;
return -1;
}
- dst.put(Surrogate.high(uc));
- dst.put(Surrogate.low(uc));
+ dst.put(Character.highSurrogate(uc));
+ dst.put(Character.lowSurrogate(uc));
error = null;
return 2;
} else {
@@ -334,8 +330,9 @@
* error() will return a descriptive result object
*/
public int generate(int uc, int len, char[] da, int dp, int dl) {
- if (Surrogate.isBMPCodePoint(uc)) {
- if (Surrogate.is(uc)) {
+ if (Character.isBmpCodePoint(uc)) {
+ char c = (char) uc;
+ if (Character.isSurrogate(c)) {
error = CoderResult.malformedForLength(len);
return -1;
}
@@ -343,16 +340,16 @@
error = CoderResult.OVERFLOW;
return -1;
}
- da[dp] = (char)uc;
+ da[dp] = c;
error = null;
return 1;
- } else if (Character.isSupplementaryCodePoint(uc)) {
+ } else if (Character.isValidCodePoint(uc)) {
if (dl - dp < 2) {
error = CoderResult.OVERFLOW;
return -1;
}
- da[dp] = Surrogate.high(uc);
- da[dp + 1] = Surrogate.low(uc);
+ da[dp] = Character.highSurrogate(uc);
+ da[dp + 1] = Character.lowSurrogate(uc);
error = null;
return 2;
} else {
--- a/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Wed Jul 05 17:18:01 2017 +0200
@@ -86,22 +86,21 @@
src.position(mark);
}
}
- while (src.remaining() > 3) {
+ while (src.remaining() >= 4) {
cp = getCP(src);
- if (cp < 0 || cp > Surrogate.UCS4_MAX) {
- return CoderResult.malformedForLength(4);
- }
- if (cp < Surrogate.UCS4_MIN) {
+ if (Character.isBmpCodePoint(cp)) {
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
mark += 4;
- dst.put((char)cp);
- } else {
+ dst.put((char) cp);
+ } else if (Character.isValidCodePoint(cp)) {
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
mark += 4;
- dst.put(Surrogate.high(cp));
- dst.put(Surrogate.low(cp));
+ dst.put(Character.highSurrogate(cp));
+ dst.put(Character.lowSurrogate(cp));
+ } else {
+ return CoderResult.malformedForLength(4);
}
}
return CoderResult.UNDERFLOW;
@@ -154,7 +153,12 @@
try {
while (src.hasRemaining()) {
char c = src.get();
- if (Character.isHighSurrogate(c)) {
+ if (!Character.isSurrogate(c)) {
+ if (dst.remaining() < 4)
+ return CoderResult.OVERFLOW;
+ mark++;
+ put(c, dst);
+ } else if (Character.isHighSurrogate(c)) {
if (!src.hasRemaining())
return CoderResult.UNDERFLOW;
char low = src.get();
@@ -162,17 +166,13 @@
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
mark += 2;
- put(Surrogate.toUCS4(c, low), dst);
+ put(Character.toCodePoint(c, low), dst);
} else {
return CoderResult.malformedForLength(1);
}
- } else if (Character.isLowSurrogate(c)) {
+ } else {
+ // assert Character.isLowSurrogate(c);
return CoderResult.malformedForLength(1);
- } else {
- if (dst.remaining() < 4)
- return CoderResult.OVERFLOW;
- mark++;
- put(c, dst);
}
}
return CoderResult.UNDERFLOW;
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java Wed Jul 05 17:18:01 2017 +0200
@@ -102,7 +102,7 @@
// [F1..F3] [80..BF] [80..BF] [80..BF]
// [F4] [80..8F] [80..BF] [80..BF]
// only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...]
- // will be checked by Surrogate.neededFor(uc)
+ // will be checked by Character.isSupplementaryCodePoint(uc)
private static boolean isMalformed4(int b2, int b3, int b4) {
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
(b4 & 0xc0) != 0x80;
@@ -207,15 +207,15 @@
// ASCII only loop
while (dp < dlASCII && sa[sp] >= 0)
- da[dp++] = (char)sa[sp++];
+ da[dp++] = (char) sa[sp++];
while (sp < sl) {
int b1 = sa[sp];
- if (b1 >= 0) {
+ if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dp >= dl)
return xflow(src, sp, sl, dst, dp, 1);
- da[dp++] = (char)b1;
+ da[dp++] = (char) b1;
sp++;
} else if ((b1 >> 5) == -2) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
@@ -224,7 +224,10 @@
int b2 = sa[sp + 1];
if (isMalformed2(b1, b2))
return malformed(src, sp, dst, dp, 2);
- da[dp++] = (char) (((b1 << 6) ^ b2) ^ 0x0f80);
+ da[dp++] = (char) (((b1 << 6) ^ b2)
+ ^
+ (((byte) 0xC0 << 6) ^
+ ((byte) 0x80 << 0)));
sp += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
@@ -234,7 +237,13 @@
int b3 = sa[sp + 2];
if (isMalformed3(b1, b2, b3))
return malformed(src, sp, dst, dp, 3);
- da[dp++] = (char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80);
+ da[dp++] = (char)
+ ((b1 << 12) ^
+ (b2 << 6) ^
+ (b3 ^
+ (((byte) 0xE0 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0))));
sp += 3;
} else if ((b1 >> 3) == -2) {
// 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
@@ -243,16 +252,21 @@
int b2 = sa[sp + 1];
int b3 = sa[sp + 2];
int b4 = sa[sp + 3];
- int uc = ((b1 & 0x07) << 18) |
- ((b2 & 0x3f) << 12) |
- ((b3 & 0x3f) << 06) |
- (b4 & 0x3f);
+ int uc = ((b1 << 18) ^
+ (b2 << 12) ^
+ (b3 << 6) ^
+ (b4 ^
+ (((byte) 0xF0 << 18) ^
+ ((byte) 0x80 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
- !Surrogate.neededFor(uc)) {
+ // shortest form check
+ !Character.isSupplementaryCodePoint(uc)) {
return malformed(src, sp, dst, dp, 4);
}
- da[dp++] = Surrogate.high(uc);
- da[dp++] = Surrogate.low(uc);
+ da[dp++] = Character.highSurrogate(uc);
+ da[dp++] = Character.lowSurrogate(uc);
sp += 4;
} else
return malformed(src, sp, dst, dp, 1);
@@ -270,8 +284,8 @@
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dst.remaining() < 1)
- return xflow(src, mark, 1); //overflow
- dst.put((char)b1);
+ return xflow(src, mark, 1); // overflow
+ dst.put((char) b1);
mark++;
} else if ((b1 >> 5) == -2) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
@@ -280,7 +294,10 @@
int b2 = src.get();
if (isMalformed2(b1, b2))
return malformed(src, mark, 2);
- dst.put((char) (((b1 << 6) ^ b2) ^ 0x0f80));
+ dst.put((char) (((b1 << 6) ^ b2)
+ ^
+ (((byte) 0xC0 << 6) ^
+ ((byte) 0x80 << 0))));
mark += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
@@ -290,7 +307,13 @@
int b3 = src.get();
if (isMalformed3(b1, b2, b3))
return malformed(src, mark, 3);
- dst.put((char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80));
+ dst.put((char)
+ ((b1 << 12) ^
+ (b2 << 6) ^
+ (b3 ^
+ (((byte) 0xE0 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0)))));
mark += 3;
} else if ((b1 >> 3) == -2) {
// 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
@@ -299,16 +322,21 @@
int b2 = src.get();
int b3 = src.get();
int b4 = src.get();
- int uc = ((b1 & 0x07) << 18) |
- ((b2 & 0x3f) << 12) |
- ((b3 & 0x3f) << 06) |
- (b4 & 0x3f);
+ int uc = ((b1 << 18) ^
+ (b2 << 12) ^
+ (b3 << 6) ^
+ (b4 ^
+ (((byte) 0xF0 << 18) ^
+ ((byte) 0x80 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
- !Surrogate.neededFor(uc)) { // shortest form check
+ // shortest form check
+ !Character.isSupplementaryCodePoint(uc)) {
return malformed(src, mark, 4);
}
- dst.put(Surrogate.high(uc));
- dst.put(Surrogate.low(uc));
+ dst.put(Character.highSurrogate(uc));
+ dst.put(Character.lowSurrogate(uc));
mark += 4;
} else {
return malformed(src, mark, 1);
@@ -366,7 +394,7 @@
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
- //ASCII only loop
+ // ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
@@ -380,7 +408,7 @@
// 2 bytes, 11 bits
if (dl - dp < 2)
return overflow(src, sp, dst, dp);
- da[dp++] = (byte)(0xc0 | ((c >> 06)));
+ da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
@@ -395,7 +423,7 @@
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
- da[dp++] = (byte)(0x80 | ((uc >> 06) & 0x3f));
+ da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (uc & 0x3f));
sp++; // 2 chars
} else {
@@ -403,7 +431,7 @@
if (dl - dp < 3)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xe0 | ((c >> 12)));
- da[dp++] = (byte)(0x80 | ((c >> 06) & 0x3f));
+ da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (c & 0x3f));
}
sp++;
@@ -427,7 +455,7 @@
// 2 bytes, 11 bits
if (dst.remaining() < 2)
return overflow(src, mark);
- dst.put((byte)(0xc0 | ((c >> 06))));
+ dst.put((byte)(0xc0 | (c >> 6)));
dst.put((byte)(0x80 | (c & 0x3f)));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
@@ -442,15 +470,15 @@
return overflow(src, mark);
dst.put((byte)(0xf0 | ((uc >> 18))));
dst.put((byte)(0x80 | ((uc >> 12) & 0x3f)));
- dst.put((byte)(0x80 | ((uc >> 06) & 0x3f)));
+ dst.put((byte)(0x80 | ((uc >> 6) & 0x3f)));
dst.put((byte)(0x80 | (uc & 0x3f)));
- mark++; //2 chars
+ mark++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dst.remaining() < 3)
return overflow(src, mark);
dst.put((byte)(0xe0 | ((c >> 12))));
- dst.put((byte)(0x80 | ((c >> 06) & 0x3f)));
+ dst.put((byte)(0x80 | ((c >> 6) & 0x3f)));
dst.put((byte)(0x80 | (c & 0x3f)));
}
mark++;
--- a/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Wed Jul 05 17:18:01 2017 +0200
@@ -93,8 +93,8 @@
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
mark += 2;
- put(Surrogate.high(d), dst);
- put(Surrogate.low(d), dst);
+ put(Character.highSurrogate(d), dst);
+ put(Character.lowSurrogate(d), dst);
}
return CoderResult.UNDERFLOW;
} finally {
--- a/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java Wed Jul 05 17:18:01 2017 +0200
@@ -34,7 +34,6 @@
import java.nio.charset.CoderResult;
import java.util.Arrays;
import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
import static sun.nio.cs.CharsetMapping.*;
public class EUC_TW extends Charset implements HistoricallyNamedCharset
@@ -159,8 +158,8 @@
c1[0] = c;
return c1;
} else {
- c2[0] = Surrogate.high(0x20000 + c);
- c2[1] = Surrogate.low(0x20000 + c);
+ c2[0] = Character.highSurrogate(0x20000 + c);
+ c2[1] = Character.lowSurrogate(0x20000 + c);
return c2;
}
}
@@ -441,7 +440,7 @@
}
static int encode(char hi, char low, byte[] bb) {
- int c = Surrogate.toUCS4(hi, low);
+ int c = Character.toCodePoint(hi, low);
if ((c & 0xf0000) != 0x20000)
return -1;
c -= 0x20000;
--- a/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java Wed Jul 05 17:18:01 2017 +0200
@@ -12628,7 +12628,7 @@
if (Character.isSurrogate(c)) {
if ((condensedKey=sgp.parse(c, sa, sp, sl)) < 0)
return sgp.error();
- // Surogate.toUCS4 looks like
+ // Character.toCodePoint looks like
// (((high & 0x3ff) << 10) | (low & 0x3ff)) + 0x10000;
// so we add (0x2e248 - 0x10000) to get the "key".
condensedKey += 0x1E248;
--- a/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java Wed Jul 05 17:18:01 2017 +0200
@@ -36,7 +36,6 @@
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
public class IBM33722
extends Charset
--- a/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java Wed Jul 05 17:18:01 2017 +0200
@@ -36,7 +36,6 @@
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
public class IBM964
extends Charset
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,9 +33,7 @@
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.ccache.CredentialsCache;
-import sun.security.krb5.internal.ktab.*;
import sun.security.krb5.internal.crypto.EType;
-import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.net.InetAddress;
@@ -506,59 +504,6 @@
return result;
}
-
- /**
- * Gets service credential from key table. The credential is used to
- * decrypt the received client message
- * and authenticate the client by verifying the client's credential.
- *
- * @param serviceName the name of service, using format component@realm
- * @param keyTabFile the file of key table.
- * @return a <code>KrbCreds</code> object.
- */
- public static Credentials getServiceCreds(String serviceName,
- File keyTabFile) {
- EncryptionKey k = null;
- PrincipalName service = null;
- Credentials result = null;
- try {
- service = new PrincipalName(serviceName);
- if (service.getRealm() == null) {
- String realm = Config.getInstance().getDefaultRealm();
- if (realm == null) {
- return null;
- } else {
- service.setRealm(realm);
- }
- }
- } catch (RealmException e) {
- if (DEBUG) {
- e.printStackTrace();
- }
- return null;
- } catch (KrbException e) {
- if (DEBUG) {
- e.printStackTrace();
- }
- return null;
- }
- KeyTab kt;
- if (keyTabFile == null) {
- kt = KeyTab.getInstance();
- } else {
- kt = KeyTab.getInstance(keyTabFile);
- }
- if ((kt != null) && (kt.findServiceEntry(service))) {
- k = kt.readServiceKey(service);
- result = new Credentials(null, service, null, null, null,
- null, null, null, null, null);
- result.serviceKey = k;
- }
- return result;
- }
-
-
-
/**
* Acquires credentials for a specified service using initial credential.
* When the service has a different realm
--- a/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -336,38 +336,29 @@
}
/**
- * Reset data stream after decryption, remove redundant bytes.
+ * Reset asn.1 data stream after decryption, remove redundant bytes.
* @param data the decrypted data from decrypt().
- * @param encoded true if the encrypted data is ASN1 encoded data,
- * false if the encrypted data is not ASN1 encoded data.
* @return the reset byte array which holds exactly one asn1 datum
* including its tag and length.
*
*/
- public byte[] reset(byte[] data, boolean encoded) {
+ public byte[] reset(byte[] data) {
byte[] bytes = null;
- // if it is encoded data, we use length field to
+ // for asn.1 encoded data, we use length field to
// determine the data length and remove redundant paddings.
- if (encoded) {
- if ((data[1] & 0xFF) < 128) {
- bytes = new byte[data[1] + 2];
- System.arraycopy(data, 0, bytes, 0, data[1] + 2);
- } else
- if ((data[1] & 0xFF) > 128) {
- int len = data[1] & (byte)0x7F;
- int result = 0;
- for (int i = 0; i < len; i++) {
- result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
- }
- bytes = new byte[result + len + 2];
- System.arraycopy(data, 0, bytes, 0, result + len + 2);
+ if ((data[1] & 0xFF) < 128) {
+ bytes = new byte[data[1] + 2];
+ System.arraycopy(data, 0, bytes, 0, data[1] + 2);
+ } else {
+ if ((data[1] & 0xFF) > 128) {
+ int len = data[1] & (byte)0x7F;
+ int result = 0;
+ for (int i = 0; i < len; i++) {
+ result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
}
- } else {
- // if it is not encoded, which happens in GSS tokens,
- // we remove padding data according to padding pattern.
- bytes = new byte[data.length - data[data.length - 1]];
- System.arraycopy(data, 0, bytes, 0,
- data.length - data[data.length - 1]);
+ bytes = new byte[result + len + 2];
+ System.arraycopy(data, 0, bytes, 0, result + len + 2);
+ }
}
return bytes;
}
--- a/jdk/src/share/classes/sun/security/krb5/KrbApRep.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApRep.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -130,7 +130,7 @@
byte[] temp = rep.encPart.decrypt(tgs_creds.key,
KeyUsage.KU_ENC_AP_REP_PART);
- byte[] enc_ap_rep_part = rep.encPart.reset(temp, true);
+ byte[] enc_ap_rep_part = rep.encPart.reset(temp);
encoding = new DerValue(enc_ap_rep_part);
encPart = new EncAPRepPart(encoding);
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -279,14 +279,14 @@
byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey,
KeyUsage.KU_TICKET);
- byte[] temp = apReqMessg.ticket.encPart.reset(bytes, true);
+ byte[] temp = apReqMessg.ticket.encPart.reset(bytes);
EncTicketPart enc_ticketPart = new EncTicketPart(temp);
checkPermittedEType(enc_ticketPart.key.getEType());
byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key,
KeyUsage.KU_AP_REQ_AUTHENTICATOR);
- byte[] temp2 = apReqMessg.authenticator.reset(bytes2, true);
+ byte[] temp2 = apReqMessg.authenticator.reset(bytes2);
authenticator = new Authenticator(temp2);
ctime = authenticator.ctime;
cusec = authenticator.cusec;
--- a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -95,7 +95,7 @@
byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
KeyUsage.KU_ENC_AS_REP_PART);
- byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes, true);
+ byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes);
encoding = new DerValue(enc_as_rep_part);
EncASRepPart enc_part = new EncASRepPart(encoding);
--- a/jdk/src/share/classes/sun/security/krb5/KrbCred.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbCred.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -130,7 +130,7 @@
byte[] temp = credMessg.encPart.decrypt(key,
KeyUsage.KU_ENC_KRB_CRED_PART);
- byte[] plainText = credMessg.encPart.reset(temp, true);
+ byte[] plainText = credMessg.encPart.reset(temp);
DerValue encoding = new DerValue(plainText);
EncKrbCredPart encPart = new EncKrbCredPart(encoding);
--- a/jdk/src/share/classes/sun/security/krb5/KrbPriv.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbPriv.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
package sun.security.krb5;
-import sun.security.krb5.EncryptionKey;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import sun.security.util.*;
@@ -159,7 +158,7 @@
byte[] bytes = krb_priv.encPart.decrypt(key,
KeyUsage.KU_ENC_KRB_PRIV_PART);
- byte[] temp = krb_priv.encPart.reset(bytes, true);
+ byte[] temp = krb_priv.encPart.reset(bytes);
DerValue ref = new DerValue(temp);
EncKrbPrivPart enc_part = new EncKrbPrivPart(ref);
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
tgsReq.usedSubkey() ? KeyUsage.KU_ENC_TGS_REP_PART_SUBKEY :
KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
- byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes, true);
+ byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes);
ref = new DerValue(enc_tgs_rep_part);
EncTGSRepPart enc_part = new EncTGSRepPart(ref);
rep.ticket.sname.setRealm(rep.ticket.realm);
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Wed Jul 05 17:18:01 2017 +0200
@@ -185,20 +185,20 @@
// is set to false.
private static final int[] BUILTIN_ETYPES = new int[] {
- EncryptedData.ETYPE_DES_CBC_MD5,
- EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
EncryptedData.ETYPE_ARCFOUR_HMAC,
- EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
- EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
- EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_DES_CBC_MD5,
};
private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
- EncryptedData.ETYPE_DES_CBC_MD5,
- EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
EncryptedData.ETYPE_ARCFOUR_HMAC,
- EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
- EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_DES_CBC_MD5,
};
@@ -217,8 +217,8 @@
result = BUILTIN_ETYPES;
}
if (!ALLOW_WEAK_CRYPTO) {
- // The first 2 etypes are now weak ones
- return Arrays.copyOfRange(result, 2, result.length);
+ // The last 2 etypes are now weak ones
+ return Arrays.copyOfRange(result, 0, result.length - 2);
}
return result;
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -228,37 +228,6 @@
}
/**
- * Reads the service key from the keytab file.
- * @param service the PrincipalName of the requested service.
- * @return the last service key in the keytab with the highest kvno
- */
- public EncryptionKey readServiceKey(PrincipalName service) {
- KeyTabEntry entry = null;
- EncryptionKey key = null;
- if (entries != null) {
- // Find latest entry for this service that has an etype
- // that has been configured for use
- for (int i = entries.size()-1; i >= 0; i--) {
- entry = entries.elementAt(i);
- if (entry.service.match(service)) {
- if (EType.isSupported(entry.keyType)) {
- if (key == null ||
- entry.keyVersion > key.getKeyVersionNumber()) {
- key = new EncryptionKey(entry.keyblock,
- entry.keyType,
- new Integer(entry.keyVersion));
- }
- } else if (DEBUG) {
- System.out.println("Found unsupported keytype (" +
- entry.keyType + ") for " + service);
- }
- }
- }
- }
- return key;
- }
-
- /**
* Reads all keys for a service from the keytab file that have
* etypes that have been configured for use. If there are multiple
* keys with same etype, the one with the highest kvno is returned.
@@ -309,7 +278,7 @@
Arrays.sort(retVal, new Comparator<EncryptionKey>() {
@Override
public int compare(EncryptionKey o1, EncryptionKey o2) {
- if (etypes != null && etypes != EType.getBuiltInDefaults()) {
+ if (etypes != null) {
int o1EType = o1.getEType();
int o2EType = o2.getEType();
if (o1EType != o2EType) {
@@ -320,6 +289,9 @@
return 1;
}
}
+ // Neither o1EType nor o2EType in default_tkt_enctypes,
+ // therefore won't be used in AS-REQ. We do not care
+ // about their order, use kvno is OK.
}
}
return o2.getKeyVersionNumber().intValue()
--- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -180,24 +180,15 @@
String alias;
};
- private static class KeyId {
- byte[] keyId;
-
- KeyId(byte[] keyId) {
+ // A certificate with its PKCS #9 attributes
+ private static class CertEntry {
+ final X509Certificate cert;
+ final byte[] keyId;
+ final String alias;
+ CertEntry(X509Certificate cert, byte[] keyId, String alias) {
+ this.cert = cert;
this.keyId = keyId;
- }
- public int hashCode() {
- int hash = 0;
-
- for (int i = 0; i < keyId.length; i++)
- hash += keyId[i];
- return hash;
- }
- public boolean equals(Object obj) {
- if (!(obj instanceof KeyId))
- return false;
- KeyId that = (KeyId)obj;
- return (Arrays.equals(this.keyId, that.keyId));
+ this.alias = alias;
}
}
@@ -209,7 +200,9 @@
new Hashtable<String, KeyEntry>();
private ArrayList<KeyEntry> keyList = new ArrayList<KeyEntry>();
- private LinkedHashMap<Object, X509Certificate> certs = new LinkedHashMap<Object, X509Certificate>();
+ private LinkedHashMap<X500Principal, X509Certificate> certsMap =
+ new LinkedHashMap<X500Principal, X509Certificate>();
+ private ArrayList<CertEntry> certEntries = new ArrayList<CertEntry>();
/**
* Returns the key associated with the given alias, using the given
@@ -472,6 +465,15 @@
KeyEntry entry = new KeyEntry();
entry.date = new Date();
+ try {
+ // set the keyId to current date
+ entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8");
+ } catch (UnsupportedEncodingException ex) {
+ // Won't happen
+ }
+ // set the alias
+ entry.alias = alias.toLowerCase();
+
entry.protectedPrivKey = key.clone();
if (chain != null) {
entry.chain = chain.clone();
@@ -1027,10 +1029,9 @@
// All Certs should have a unique friendlyName.
// This change is made to meet NSS requirements.
byte[] bagAttrs = null;
- String friendlyName = cert.getSubjectX500Principal().getName();
if (i == 0) {
// Only End-Entity Cert should have a localKeyId.
- bagAttrs = getBagAttributes(friendlyName, entry.keyId);
+ bagAttrs = getBagAttributes(entry.alias, entry.keyId);
} else {
// Trusted root CA certs and Intermediate CA certs do not
// need to have a localKeyId, and hence localKeyId is null
@@ -1038,7 +1039,8 @@
// NSS pkcs12 library requires trusted CA certs in the
// certificate chain to have unique or null localKeyID.
// However, IE/OpenSSL do not impose this restriction.
- bagAttrs = getBagAttributes(friendlyName, null);
+ bagAttrs = getBagAttributes(
+ cert.getSubjectX500Principal().getName(), null);
}
if (bagAttrs != null) {
safeBag.write(bagAttrs);
@@ -1333,24 +1335,49 @@
if (entry.keyId != null) {
ArrayList<X509Certificate> chain =
new ArrayList<X509Certificate>();
- X509Certificate cert = certs.get(new KeyId(entry.keyId));
+ X509Certificate cert = findMatchedCertificate(entry);
while (cert != null) {
chain.add(cert);
X500Principal issuerDN = cert.getIssuerX500Principal();
if (issuerDN.equals(cert.getSubjectX500Principal())) {
break;
}
- cert = certs.get(issuerDN);
+ cert = certsMap.get(issuerDN);
}
/* Update existing KeyEntry in entries table */
if (chain.size() > 0)
entry.chain = chain.toArray(new Certificate[chain.size()]);
}
}
- certs.clear();
+ certEntries.clear();
+ certsMap.clear();
keyList.clear();
}
+ /**
+ * Locates a matched CertEntry from certEntries, and returns its cert.
+ * @param entry the KeyEntry to match
+ * @return a certificate, null if not found
+ */
+ private X509Certificate findMatchedCertificate(KeyEntry entry) {
+ CertEntry keyIdMatch = null;
+ CertEntry aliasMatch = null;
+ for (CertEntry ce: certEntries) {
+ if (Arrays.equals(entry.keyId, ce.keyId)) {
+ keyIdMatch = ce;
+ if (entry.alias.equalsIgnoreCase(ce.alias)) {
+ // Full match!
+ return ce.cert;
+ }
+ } else if (entry.alias.equalsIgnoreCase(ce.alias)) {
+ aliasMatch = ce;
+ }
+ }
+ // keyId match first, for compatibility
+ if (keyIdMatch != null) return keyIdMatch.cert;
+ else if (aliasMatch != null) return aliasMatch.cert;
+ else return null;
+ }
private void loadSafeContents(DerInputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException
@@ -1491,19 +1518,12 @@
keyId = "01".getBytes("UTF8");
}
}
- if (keyId != null) {
- KeyId keyid = new KeyId(keyId);
- if (!certs.containsKey(keyid))
- certs.put(keyid, cert);
- }
- if (alias != null) {
- if (!certs.containsKey(alias))
- certs.put(alias, cert);
- }
+ certEntries.add(new CertEntry(cert, keyId, alias));
X500Principal subjectDN = cert.getSubjectX500Principal();
if (subjectDN != null) {
- if (!certs.containsKey(subjectDN))
- certs.put(subjectDN, cert);
+ if (!certsMap.containsKey(subjectDN)) {
+ certsMap.put(subjectDN, cert);
+ }
}
}
}
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Wed Jul 05 17:18:01 2017 +0200
@@ -212,7 +212,7 @@
byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET);
// Reset data stream after decryption, remove redundant bytes
- byte[] temp = encPart.reset(bytes, true);
+ byte[] temp = encPart.reset(bytes);
EncTicketPart encTicketPart = new EncTicketPart(temp);
// Record the Kerberos Principals
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
import java.io.*;
import java.security.*;
-import java.security.interfaces.*;
+import java.util.Arrays;
import javax.net.ssl.*;
@@ -128,8 +128,8 @@
"are not supported for TLS Kerberos cipher suites");
}
- // Decrypt premaster secret
- try {
+ // Decrypt premaster secret
+ try {
EncryptedData data = new EncryptedData(sessionKey.getEType(),
null /* optional kvno */, encrypted);
@@ -141,8 +141,25 @@
}
}
- // Reset data stream after decryption, remove redundant bytes
- preMaster = data.reset(temp, false);
+ // Remove padding bytes after decryption. Only DES and DES3 have
+ // paddings and we don't support DES3 in TLS (see above)
+
+ if (temp.length == 52 &&
+ data.getEType() == EncryptedData.ETYPE_DES_CBC_CRC) {
+ // For des-cbc-crc, 4 paddings. Value can be 0x04 or 0x00.
+ if (paddingByteIs(temp, 52, (byte)4) ||
+ paddingByteIs(temp, 52, (byte)0)) {
+ temp = Arrays.copyOf(temp, 48);
+ }
+ } else if (temp.length == 56 &&
+ data.getEType() == EncryptedData.ETYPE_DES_CBC_MD5) {
+ // For des-cbc-md5, 8 paddings with 0x08, or no padding
+ if (paddingByteIs(temp, 56, (byte)8)) {
+ temp = Arrays.copyOf(temp, 48);
+ }
+ }
+
+ preMaster = temp;
protocolVersion = ProtocolVersion.valueOf(preMaster[0],
preMaster[1]);
@@ -191,6 +208,19 @@
}
}
+ /**
+ * Checks if all paddings of data are b
+ * @param data the block with padding
+ * @param len length of data, >= 48
+ * @param b expected padding byte
+ */
+ private static boolean paddingByteIs(byte[] data, int len, byte b) {
+ for (int i=48; i<len; i++) {
+ if (data[i] != b) return false;
+ }
+ return true;
+ }
+
/*
* Used by server to generate premaster secret in case of
* problem decoding ticket.
--- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java Wed Jul 05 17:18:01 2017 +0200
@@ -438,8 +438,12 @@
// c may be null here.
String clipString = "...";
availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString);
+ if (availTextWidth <= 0) {
+ //can not fit any characters
+ return clipString;
+ }
+
boolean needsTextLayout;
-
synchronized (charsBufferLock) {
int stringLength = syncCharsBuffer(string);
needsTextLayout =
--- a/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c Wed Jul 05 17:18:01 2017 +0200
@@ -111,6 +111,10 @@
{
BufImgSDOps *bisdo =
(BufImgSDOps*)SurfaceData_InitOps(env, bisd, sizeof(BufImgSDOps));
+ if (bisdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+ return;
+ }
bisdo->sdOps.Lock = BufImg_Lock;
bisdo->sdOps.GetRasInfo = BufImg_GetRasInfo;
bisdo->sdOps.Release = BufImg_Release;
--- a/jdk/src/solaris/bin/java_md.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/bin/java_md.c Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -183,13 +183,9 @@
}
void
-CreateExecutionEnvironment(int *_argcp,
- char ***_argvp,
- char jrepath[],
- jint so_jrepath,
- char jvmpath[],
- jint so_jvmpath,
- char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+ char jrepath[], jint so_jrepath,
+ char jvmpath[], jint so_jvmpath) {
/*
* First, determine if we are running the desired data model. If we
* are running the desired data model, all the error messages
@@ -200,18 +196,17 @@
* os/processor combination has dual mode capabilities.
*/
- int original_argc = *_argcp;
jboolean jvmpathExists;
/* Compute/set the name of the executable */
- SetExecname(*_argvp);
+ SetExecname(*pargv);
/* Check data model flags, and exec process, if needed */
{
char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
char * jvmtype = NULL;
- int argc = *_argcp;
- char **argv = original_argv;
+ int argc = *pargc;
+ char **argv = *pargv;
int running = CURRENT_DATA_MODEL;
@@ -233,7 +228,7 @@
{ /* open new scope to declare local variables */
int i;
- newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
+ newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*));
newargv[newargc++] = argv[0];
/* scan for data model arguments and remove from argument list;
@@ -293,7 +288,11 @@
}
jvmpath[0] = '\0';
- jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
+ jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+ if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+ JLI_ReportErrorMessage(CFG_ERROR9);
+ exit(4);
+ }
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
@@ -309,7 +308,9 @@
if (running != wanted) {
/* Find out where the JRE is that we will be using. */
if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) {
- goto EndDataModelSpeculate;
+ /* give up and let other code report error message */
+ JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+ exit(1);
}
/*
@@ -317,16 +318,21 @@
* selection options.
*/
if (ReadKnownVMs(jrepath, GetArchPath(wanted), JNI_TRUE) < 1) {
- goto EndDataModelSpeculate;
+ /* give up and let other code report error message */
+ JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+ exit(1);
}
jvmpath[0] = '\0';
- jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
+ jvmtype = CheckJvmType(pargc, pargv, JNI_TRUE);
+ if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+ JLI_ReportErrorMessage(CFG_ERROR9);
+ exit(4);
+ }
+
/* exec child can do error checking on the existence of the path */
jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted));
}
- EndDataModelSpeculate: /* give up and let other code report error message */
- ;
#else
JLI_ReportErrorMessage(JRE_ERROR2, wanted);
exit(1);
@@ -398,9 +404,9 @@
struct stat s;
if (JLI_StrChr(jvmtype, '/')) {
- sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
+ JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype);
} else {
- sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
+ JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
}
JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
@@ -424,26 +430,24 @@
if (GetApplicationHome(path, pathsize)) {
/* Is JRE co-located with the application? */
- sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
+ JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
if (access(libjava, F_OK) == 0) {
- goto found;
+ JLI_TraceLauncher("JRE path is %s\n", path);
+ return JNI_TRUE;
}
/* Does the app ship a private JRE in <apphome>/jre directory? */
- sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
+ JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch);
if (access(libjava, F_OK) == 0) {
JLI_StrCat(path, "/jre");
- goto found;
+ JLI_TraceLauncher("JRE path is %s\n", path);
+ return JNI_TRUE;
}
}
if (!speculative)
JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
return JNI_FALSE;
-
- found:
- JLI_TraceLauncher("JRE path is %s\n", path);
- return JNI_TRUE;
}
jboolean
@@ -463,14 +467,18 @@
int location;
fp = fopen(jvmpath, "r");
- if(fp == NULL)
- goto error;
+ if (fp == NULL) {
+ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+ return JNI_FALSE;
+ }
/* read in elf header */
count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
fclose(fp);
- if(count < 1)
- goto error;
+ if (count < 1) {
+ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+ return JNI_FALSE;
+ }
/*
* Check for running a server vm (compiled with -xarch=v8plus)
@@ -481,41 +489,42 @@
* does not have to be checked for in binaries with an LP64 data
* model.
*/
- if(elf_head.e_machine == EM_SPARC32PLUS) {
+ if (elf_head.e_machine == EM_SPARC32PLUS) {
char buf[257]; /* recommended buffer size from sysinfo man
page */
long length;
char* location;
length = sysinfo(SI_ISALIST, buf, 257);
- if(length > 0) {
- location = JLI_StrStr(buf, "sparcv8plus ");
- if(location == NULL) {
+ if (length > 0) {
+ location = JLI_StrStr(buf, "sparcv8plus ");
+ if (location == NULL) {
JLI_ReportErrorMessage(JVM_ERROR3);
return JNI_FALSE;
}
}
}
#endif
- JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
- goto error;
+ JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
+ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+ return JNI_FALSE;
}
ifn->CreateJavaVM = (CreateJavaVM_t)
- dlsym(libjvm, "JNI_CreateJavaVM");
- if (ifn->CreateJavaVM == NULL)
- goto error;
+ dlsym(libjvm, "JNI_CreateJavaVM");
+ if (ifn->CreateJavaVM == NULL) {
+ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+ return JNI_FALSE;
+ }
ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
- if (ifn->GetDefaultJavaVMInitArgs == NULL)
- goto error;
+ if (ifn->GetDefaultJavaVMInitArgs == NULL) {
+ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+ return JNI_FALSE;
+ }
return JNI_TRUE;
-
-error:
- JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
- return JNI_FALSE;
}
/*
@@ -575,7 +584,7 @@
char name[PATH_MAX + 2], *real;
if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1) > PATH_MAX) return 0;
- sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
+ JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd);
if (!ProgramExists(name)) return 0;
real = JLI_MemAlloc(PATH_MAX + 2);
if (!realpath(name, real))
@@ -622,7 +631,7 @@
else {
/* relative path element */
char dir[2*PATH_MAX];
- sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
+ JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
FILE_SEPARATOR, s);
result = Resolve(dir, program);
}
@@ -746,7 +755,7 @@
if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX)
return (0); /* Silently reject "impossibly" long paths */
- sprintf(buffer, "%s/%s/bin/java", path, dir);
+ JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir);
return ((access(buffer, X_OK) == 0) ? 1 : 0);
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Jul 05 17:18:01 2017 +0200
@@ -1053,10 +1053,28 @@
return peer;
}
+ private static Boolean sunAwtDisableGtkFileDialogs = null;
+
+ /**
+ * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default
+ * value is {@code false}.
+ */
+ public synchronized static boolean getSunAwtDisableGtkFileDialogs() {
+ if (sunAwtDisableGtkFileDialogs == null) {
+ sunAwtDisableGtkFileDialogs =
+ getBooleanSystemProperty("sun.awt.disableGtkFileDialogs");
+ }
+ return sunAwtDisableGtkFileDialogs.booleanValue();
+ }
+
public FileDialogPeer createFileDialog(FileDialog target) {
+ FileDialogPeer peer = null;
// The current GtkFileChooser is available from GTK+ 2.4
- FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer(
- target) : new XFileDialogPeer(target);
+ if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
+ peer = new GtkFileDialogPeer(target);
+ } else {
+ peer = new XFileDialogPeer(target);
+ }
targetCreatedPeer(target, peer);
return peer;
}
@@ -1201,14 +1219,6 @@
}
}
- static String getSystemProperty(final String name) {
- return (String)AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- return System.getProperty(name);
- }
- });
- }
-
public PrintJob getPrintJob(final Frame frame, final String doctitle,
final Properties props) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java Wed Jul 05 17:18:01 2017 +0200
@@ -778,8 +778,8 @@
x, y,
xbe.get_x_root(),
xbe.get_y_root(),
- clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
- 3,button==4 ? -1 : 1);
+ 1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
+ 3,button==4 ? -1*clickCount : 1*clickCount);
postEventToEventQueue(mwe);
}
}
--- a/jdk/src/solaris/demo/jni/Poller/Poller.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/demo/jni/Poller/Poller.c Wed Jul 05 17:18:01 2017 +0200
@@ -160,10 +160,10 @@
return -1;
}
-#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" ## str)
-#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" ## str)
+#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" str)
+#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" str)
#define INTERRUPT_EXCEPTION(str) throwInterruptedIOException(env, \
- "Poller:" ## str)
+ "Poller:" str)
jint addfd(JNIEnv *, ioevent_t *, jint, jshort);
jint removefd(JNIEnv *, ioevent_t *, jint);
--- a/jdk/src/solaris/native/java/net/NetworkInterface.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c Wed Jul 05 17:18:01 2017 +0200
@@ -23,6 +23,7 @@
* questions.
*/
+
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
@@ -33,23 +34,23 @@
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
+
#ifdef __solaris__
#include <sys/dlpi.h>
#include <fcntl.h>
#include <stropts.h>
+#include <sys/sockio.h>
#endif
+
#ifdef __linux__
#include <sys/ioctl.h>
#include <bits/ioctls.h>
#include <linux/sockios.h>
#include <sys/utsname.h>
#include <stdio.h>
-#else
-#include <sys/sockio.h>
#endif
#ifdef __linux__
-#define ifr_index ifr_ifindex
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
#endif
@@ -108,20 +109,41 @@
static jfieldID ni_ib4broadcastID;
static jfieldID ni_ib4maskID;
+/** Private methods declarations **/
static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
+static int getFlags0(JNIEnv *env, jstring ifname);
-static netif *enumInterfaces(JNIEnv *env);
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs);
+static netif *enumInterfaces(JNIEnv *env);
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
+
#ifdef AF_INET6
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs);
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
#endif
-static netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index,
- int family, struct sockaddr *new_addrP, int new_addrlen,
- short prefix);
-static void freeif(netif *ifs);
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname);
-static short getSubnet(JNIEnv *env, const char *ifname);
+static netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static void freeif(netif *ifs);
+
+static int openSocket(JNIEnv *env, int proto);
+static int openSocketWithFallback(JNIEnv *env, const char *ifname);
+
+
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
+static short getSubnet(JNIEnv *env, int sock, const char *ifname);
+static int getIndex(int sock, const char *ifname);
+
+static int getFlags(JNIEnv *env, int sock, const char *ifname);
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf);
+static int getMTU(JNIEnv *env, int sock, const char *ifname);
+
+
+
+#ifdef __solaris__
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
+static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
+#endif
+
+
+/******************* Java entry points *****************************/
/*
* Class: java_net_NetworkInterface
@@ -172,7 +194,7 @@
netif *ifs, *curr;
jboolean isCopy;
- const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ const char* name_utf;
jobject obj = NULL;
ifs = enumInterfaces(env);
@@ -180,6 +202,8 @@
return NULL;
}
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
/*
* Search the list of interface based on name
*/
@@ -253,12 +277,13 @@
(JNIEnv *env, jclass cls, jobject iaObj) {
netif *ifs, *curr;
+
#ifdef AF_INET6
- int family = (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4?
- AF_INET : AF_INET6;
+ int family = ( (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6;
#else
- int family = AF_INET;
+ int family = AF_INET;
#endif
+
jobject obj = NULL;
jboolean match = JNI_FALSE;
@@ -390,18 +415,169 @@
return netIFArr;
}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isUp0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isP2P0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isLoopback0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: supportsMulticast0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMacAddr0
+ * Signature: ([bLjava/lang/String;I)[b
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
+ jint addr;
+ jbyte caddr[4];
+ struct in_addr iaddr;
+ jbyteArray ret = NULL;
+ unsigned char mac[16];
+ int len;
+ int sock;
+ jboolean isCopy;
+ const char* name_utf;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return JNI_FALSE;
+ }
+
+
+ if (!IS_NULL(addrArray)) {
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ iaddr.s_addr = htonl(addr);
+ len = getMacAddress(env, sock, name_utf, &iaddr, mac);
+ } else {
+ len = getMacAddress(env, sock, name_utf,NULL, mac);
+ }
+ if (len > 0) {
+ ret = (*env)->NewByteArray(env, len);
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto fexit;
+ }
+ (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
+ }
+ fexit:
+ /* release the UTF string and interface list */
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ close(sock);
+ return ret;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMTU0
+ * Signature: ([bLjava/lang/String;I)I
+ */
+
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
+ jboolean isCopy;
+ int ret = -1;
+ int sock;
+ const char* name_utf;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return JNI_FALSE;
+ }
+
+ ret = getMTU(env, sock, name_utf);
+
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ close(sock);
+ return ret;
+}
+
+/*** Private methods definitions ****/
+
+static int getFlags0(JNIEnv *env, jstring name) {
+ jboolean isCopy;
+ int ret, sock;
+ const char* name_utf;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return -1;
+ }
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ ret = getFlags(env, sock, name_utf);
+
+ close(sock);
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ if (ret < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+ return -1;
+ }
+
+ return ret;
+}
+
+
+
+
/*
* Create a NetworkInterface object, populate the name and index, and
* populate the InetAddress array based on the IP addresses for this
* interface.
*/
-jobject createNetworkInterface(JNIEnv *env, netif *ifs)
-{
+jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
jobject netifObj;
jobject name;
jobjectArray addrArr;
jobjectArray bindArr;
jobjectArray childArr;
+ netaddr *addrs;
jint addr_index, addr_count, bind_index;
jint child_count, child_index;
netaddr *addrP;
@@ -441,7 +617,7 @@
bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
if (bindArr == NULL) {
- return NULL;
+ return NULL;
}
addrP = ifs->addr;
addr_index = 0;
@@ -453,23 +629,22 @@
if (addrP->family == AF_INET) {
iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (iaObj) {
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+ (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
}
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj) {
- (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
- if (addrP->brdcast) {
- jobject ia2Obj = NULL;
- ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
- if (ia2Obj) {
- (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
- htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
- (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
- (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
- }
- }
- (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+ (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+ if (addrP->brdcast) {
+ jobject ia2Obj = NULL;
+ ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (ia2Obj) {
+ (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
+ htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+ (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
+ (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+ }
+ }
+ (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
}
}
@@ -483,14 +658,10 @@
return NULL;
}
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
- (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
-#ifdef __linux__
- if (!kernelIsV22()) {
- scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
- }
-#else
+ (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+
scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
-#endif
+
if (scope != 0) { /* zero is default value, no need to set */
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
@@ -500,9 +671,9 @@
}
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj) {
- (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
- (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
- (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+ (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+ (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+ (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
}
}
#endif
@@ -521,13 +692,13 @@
child_count = 0;
childP = ifs->childs;
while (childP) {
- child_count++;
- childP = childP->next;
+ child_count++;
+ childP = childP->next;
}
childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
if (childArr == NULL) {
- return NULL;
+ return NULL;
}
/*
@@ -539,7 +710,7 @@
while(childP) {
tmp = createNetworkInterface(env, childP);
if (tmp == NULL) {
- return NULL;
+ return NULL;
}
(*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
(*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
@@ -558,294 +729,56 @@
*/
static netif *enumInterfaces(JNIEnv *env) {
netif *ifs;
+ int sock;
/*
* Enumerate IPv4 addresses
*/
- ifs = enumIPv4Interfaces(env, NULL);
- if (ifs == NULL) {
- if ((*env)->ExceptionOccurred(env)) {
- return NULL;
- }
+
+ sock = openSocket(env, AF_INET);
+ if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ return NULL;
}
+ ifs = enumIPv4Interfaces(env, sock, NULL);
+ close(sock);
+
+ if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
+ return NULL;
+ }
+
+ /* return partial list if exception occure in the middle of process ???*/
+
/*
* If IPv6 is available then enumerate IPv6 addresses.
*/
#ifdef AF_INET6
- if (ipv6_available()) {
- ifs = enumIPv6Interfaces(env, ifs);
+ sock = openSocket(env, AF_INET6);
+ if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ freeif(ifs);
+ return NULL;
+ }
+
+ ifs = enumIPv6Interfaces(env, sock, ifs);
+ close(sock);
if ((*env)->ExceptionOccurred(env)) {
freeif(ifs);
return NULL;
}
- }
#endif
return ifs;
}
-
-/*
- * Enumerates and returns all IPv4 interfaces
- */
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) {
- int sock;
- struct ifconf ifc;
- struct ifreq *ifreqP;
- char *buf;
- int numifs;
- unsigned i;
- unsigned bufsize;
-
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- /*
- * If EPROTONOSUPPORT is returned it means we don't have
- * IPv4 support so don't throw an exception.
- */
- if (errno != EPROTONOSUPPORT) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- }
- return ifs;
- }
-
-#ifdef __linux__
- /* need to do a dummy SIOCGIFCONF to determine the buffer size.
- * SIOCGIFCOUNT doesn't work
- */
- ifc.ifc_buf = NULL;
- if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "ioctl SIOCGIFCONF failed");
- close(sock);
- return ifs;
- }
- bufsize = ifc.ifc_len;
-#else
- if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "ioctl SIOCGIFNUM failed");
- close(sock);
- return ifs;
- }
- bufsize = numifs * sizeof (struct ifreq);
-#endif /* __linux__ */
-
- buf = (char *)malloc(bufsize);
- if (!buf) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- (void) close(sock);
- return ifs;
- }
- ifc.ifc_len = bufsize;
- ifc.ifc_buf = buf;
- if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "ioctl SIOCGIFCONF failed");
- (void) close(sock);
- (void) free(buf);
- return ifs;
- }
-
- /*
- * Iterate through each interface
- */
- ifreqP = ifc.ifc_req;
- for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
- int index;
- struct ifreq if2;
-
- memset((char *)&if2, 0, sizeof(if2));
- strcpy(if2.ifr_name, ifreqP->ifr_name);
-
- /*
- * Try to get the interface index
- * (Not supported on Solaris 2.6 or 7)
- */
- if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) {
- index = if2.ifr_index;
- } else {
- index = -1;
- }
-
- /*
- * Add to the list
- */
- ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET,
- (struct sockaddr *)&(ifreqP->ifr_addr),
- sizeof(struct sockaddr_in), 0);
-
- /*
- * If an exception occurred then free the list
- */
- if ((*env)->ExceptionOccurred(env)) {
- close(sock);
- free(buf);
- freeif(ifs);
- return NULL;
- }
- }
-
- /*
- * Free socket and buffer
- */
- close(sock);
- free(buf);
- return ifs;
-}
-
-
-#if defined(__solaris__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Solaris
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
- int sock;
- struct lifconf ifc;
- struct lifreq *ifr;
- int n;
- char *buf;
- struct lifnum numifs;
- unsigned bufsize;
-
- sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "Failed to create IPv6 socket");
- return ifs;
- }
-
- /*
- * Get the interface count
- */
- numifs.lifn_family = AF_UNSPEC;
- numifs.lifn_flags = 0;
- if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "ioctl SIOCGLIFNUM failed");
- close(sock);
- return ifs;
- }
-
- /*
- * Enumerate the interface configurations
- */
- bufsize = numifs.lifn_count * sizeof (struct lifreq);
- buf = (char *)malloc(bufsize);
- if (!buf) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- (void) close(sock);
- return ifs;
- }
- ifc.lifc_family = AF_UNSPEC;
- ifc.lifc_flags = 0;
- ifc.lifc_len = bufsize;
- ifc.lifc_buf = buf;
- if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
- NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
- "ioctl SIOCGLIFCONF failed");
- close(sock);
- free(buf);
- return ifs;
- }
-
- /*
- * Iterate through each interface
- */
- ifr = ifc.lifc_req;
- for (n=0; n<numifs.lifn_count; n++, ifr++) {
- int index = -1;
- struct lifreq if2;
-
- /*
- * Ignore non-IPv6 addresses
- */
- if (ifr->lifr_addr.ss_family != AF_INET6) {
- continue;
- }
-
- /*
- * Get the index
- */
- memset((char *)&if2, 0, sizeof(if2));
- strcpy(if2.lifr_name, ifr->lifr_name);
- if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) {
- struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
- index = if2.lifr_index;
- s6->sin6_scope_id = index;
- }
-
- /* add to the list */
- ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6,
- (struct sockaddr *)&(ifr->lifr_addr),
- sizeof(struct sockaddr_in6), (short) ifr->lifr_addrlen);
-
- /*
- * If an exception occurred we return
- */
- if ((*env)->ExceptionOccurred(env)) {
- close(sock);
- free(buf);
- return ifs;
- }
-
- }
-
- close(sock);
- free(buf);
- return ifs;
-
-}
-#endif
-
-
-#if defined(__linux__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
- FILE *f;
- char addr6[40], devname[20];
- char addr6p[8][5];
- int plen, scope, dad_status, if_idx;
- uint8_t ipv6addr[16];
-
- if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
- while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
- addr6p[0], addr6p[1], addr6p[2], addr6p[3],
- addr6p[4], addr6p[5], addr6p[6], addr6p[7],
- &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
- struct sockaddr_in6 addr;
-
- sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
- addr6p[0], addr6p[1], addr6p[2], addr6p[3],
- addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
- inet_pton(AF_INET6, addr6, ipv6addr);
-
- memset(&addr, 0, sizeof(struct sockaddr_in6));
- memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
- addr.sin6_scope_id = if_idx;
-
- ifs = addif(env, ifs, devname, if_idx, AF_INET6,
- (struct sockaddr *)&addr,
- sizeof(struct sockaddr_in6), plen);
-
- /*
- * If an exception occurred then return the list as is.
- */
- if ((*env)->ExceptionOccurred(env)) {
- fclose(f);
- return ifs;
- }
- }
- fclose(f);
- }
- return ifs;
-}
-#endif
+#define CHECKED_MALLOC3(_pointer,_type,_size) \
+ do{ \
+ _pointer = (_type)malloc( _size ); \
+ if (_pointer == NULL) { \
+ JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); \
+ return ifs; /* return untouched list */ \
+ } \
+ } while(0)
/*
@@ -853,52 +786,43 @@
*/
void freeif(netif *ifs) {
netif *currif = ifs;
+ netif *child = NULL;
while (currif != NULL) {
netaddr *addrP = currif->addr;
while (addrP != NULL) {
netaddr *next = addrP->next;
- if (addrP->addr != NULL)
- free(addrP->addr);
- if (addrP->brdcast != NULL)
- free(addrP->brdcast);
free(addrP);
addrP = next;
- }
-
- free(currif->name);
+ }
- /*
- * Don't forget to free the sub-interfaces.
- */
- if (currif->childs != NULL) {
- freeif(currif->childs);
- }
+ /*
+ * Don't forget to free the sub-interfaces.
+ */
+ if (currif->childs != NULL) {
+ freeif(currif->childs);
+ }
- ifs = currif->next;
- free(currif);
- currif = ifs;
+ ifs = currif->next;
+ free(currif);
+ currif = ifs;
}
}
-/*
- * Add an interface to the list. If known interface just link
- * a new netaddr onto the list. If new interface create new
- * netif structure.
- */
-netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family,
- struct sockaddr *new_addrP, int new_addrlen, short prefix) {
- netif *currif = ifs, *parent;
+netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix) {
+ netif *currif = ifs, *parent;
netaddr *addrP;
-#ifdef LIFNAMSIZ
- char name[LIFNAMSIZ];
- char vname[LIFNAMSIZ];
-#else
- char name[IFNAMSIZ];
- char vname[IFNAMSIZ];
-#endif
- char *unit;
+
+ #ifdef __solaris__
+ char name[LIFNAMSIZ], vname[LIFNAMSIZ];
+ #else
+ char name[IFNAMSIZ], vname[IFNAMSIZ];
+ #endif
+
+ char *name_colonP;
+ int mask;
int isVirtual = 0;
+ int addr_size;
/*
* If the interface name is a logical interface then we
@@ -908,107 +832,63 @@
* logical interfaces.
*/
strcpy(name, if_name);
+ *vname = 0;
/*
* Create and populate the netaddr node. If allocation fails
* return an un-updated list.
*/
- addrP = (netaddr *)malloc(sizeof(netaddr));
- if (addrP) {
- addrP->addr = (struct sockaddr *)malloc(new_addrlen);
- if (addrP->addr == NULL) {
- free(addrP);
- addrP = NULL;
- }
- }
- if (addrP == NULL) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- return ifs; /* return untouched list */
- }
- memcpy(addrP->addr, new_addrP, new_addrlen);
+ /*Allocate for addr and brdcast at once*/
+
+#ifdef AF_INET6
+ addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+#else
+ addr_size = sizeof(struct sockaddr_in);
+#endif
+
+ CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
+ addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+ memcpy(addrP->addr, ifr_addrP, addr_size);
+
addrP->family = family;
-
addrP->brdcast = NULL;
addrP->mask = prefix;
+ addrP->next = 0;
if (family == AF_INET) {
/*
* Deal with brodcast addr & subnet mask
*/
- addrP->brdcast = getBroadcast(env, name);
- if (addrP->brdcast) {
- addrP->mask = getSubnet(env, name);
- }
- }
+ struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
+ addrP->brdcast = getBroadcast(env, sock, name, brdcast_to );
- vname[0] = 0;
- unit = strchr(name, ':');
- if (unit != NULL) {
+ if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
+ addrP->mask = mask;
+ }
+ }
+
+ /**
+ * Deal with virtual interface with colon notaion e.g. eth0:1
+ */
+ name_colonP = strchr(name, ':');
+ if (name_colonP != NULL) {
/**
* This is a virtual interface. If we are able to access the parent
* we need to create a new entry if it doesn't exist yet *and* update
* the 'parent' interface with the new records.
*/
- struct ifreq if2;
- int sock;
- int len;
-
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return ifs; /* return untouched list */
- }
-
- len = unit - name;
- if (len > 0) {
- // temporarily use vname to hold the parent name of the interface
- // instead of creating another buffer.
- memcpy(&vname, name, len);
- vname[len] = '\0';
-
- memset((char *) &if2, 0, sizeof(if2));
- strcpy(if2.ifr_name, vname);
-
- if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
- // Got access to parent, so create it if necessary.
- strcpy(vname, name);
- *unit = '\0';
- } else {
-#if defined(__solaris__) && defined(AF_INET6)
- struct lifreq lifr;
- memset((char *) &lifr, 0, sizeof(lifr));
- strcpy(lifr.lifr_name, vname);
-
- /* Try with an IPv6 socket in case the interface has only IPv6
- * addresses assigned to it */
- close(sock);
- sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return ifs; /* return untouched list */
- }
-
- if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
- // Got access to parent, so create it if necessary.
- strcpy(vname, name);
- *unit = '\0';
- } else {
+ *name_colonP = 0;
+ if (getFlags(env,sock,name) < 0) {
// failed to access parent interface do not create parent.
// We are a virtual interface with no parent.
isVirtual = 1;
- vname[0] = 0;
- }
-#else
- // failed to access parent interface do not create parent.
- // We are a virtual interface with no parent.
- isVirtual = 1;
- vname[0] = 0;
-#endif
+ *name_colonP = ':';
}
- }
- close(sock);
+ else{
+ // Got access to parent, so create it if necessary.
+ // Save original name to vname and truncate name by ':'
+ memcpy(vname, name, sizeof(vname) );
+ vname[name_colonP - name] = ':';
+ }
}
/*
@@ -1028,24 +908,15 @@
* insert it onto the list.
*/
if (currif == NULL) {
- currif = (netif *)malloc(sizeof(netif));
- if (currif) {
- currif->name = strdup(name);
- if (currif->name == NULL) {
- free(currif);
- currif = NULL;
- }
- }
- if (currif == NULL) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- return ifs;
- }
- currif->index = index;
- currif->addr = NULL;
- currif->childs = NULL;
- currif->virtual = isVirtual;
- currif->next = ifs;
- ifs = currif;
+ CHECKED_MALLOC3(currif, netif *, sizeof(netif)+IFNAMSIZ );
+ currif->name = (char *) currif+sizeof(netif);
+ strcpy(currif->name, name);
+ currif->index = getIndex(sock, name);
+ currif->addr = NULL;
+ currif->childs = NULL;
+ currif->virtual = isVirtual;
+ currif->next = ifs;
+ ifs = currif;
}
/*
@@ -1060,161 +931,251 @@
* Let's deal with the virtual interface now.
*/
if (vname[0]) {
- netaddr *tmpaddr;
+ netaddr *tmpaddr;
- currif = parent->childs;
+ currif = parent->childs;
- while (currif != NULL) {
- if (strcmp(vname, currif->name) == 0) {
- break;
- }
- currif = currif->next;
- }
- if (currif == NULL) {
- currif = (netif *)malloc(sizeof(netif));
- if (currif) {
- currif->name = strdup(vname);
- if (currif->name == NULL) {
- free(currif);
- currif = NULL;
- }
- }
- if (currif == NULL) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- return ifs;
+ while (currif != NULL) {
+ if (strcmp(vname, currif->name) == 0) {
+ break;
+ }
+ currif = currif->next;
}
- currif->index = index;
- currif->addr = NULL;
- /* Need to duplicate the addr entry? */
- currif->virtual = 1;
- currif->childs = NULL;
- currif->next = parent->childs;
- parent->childs = currif;
- }
+
+ if (currif == NULL) {
+ CHECKED_MALLOC3(currif, netif *, sizeof(netif)+ IFNAMSIZ );
+ currif->name = (char *) currif + sizeof(netif);
+ strcpy(currif->name, vname);
+ currif->index = getIndex(sock, vname);
+ currif->addr = NULL;
+ /* Need to duplicate the addr entry? */
+ currif->virtual = 1;
+ currif->childs = NULL;
+ currif->next = parent->childs;
+ parent->childs = currif;
+ }
- tmpaddr = (netaddr *) malloc(sizeof(netaddr));
- if (tmpaddr == NULL) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
- return ifs;
- }
- memcpy(tmpaddr, addrP, sizeof(netaddr));
- /**
- * Let's duplicate the address and broadcast address structures
- * if there are any.
- */
- if (addrP->addr != NULL) {
- tmpaddr->addr = malloc(new_addrlen);
- if (tmpaddr->addr != NULL)
- memcpy(tmpaddr->addr, addrP->addr, new_addrlen);
- }
- if (addrP->brdcast != NULL) {
- tmpaddr->brdcast = malloc(new_addrlen);
- if (tmpaddr->brdcast != NULL)
- memcpy(tmpaddr->brdcast, addrP->brdcast, new_addrlen);
- }
- tmpaddr->next = currif->addr;
- currif->addr = tmpaddr;
+ CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
+ memcpy(tmpaddr, addrP, sizeof(netaddr));
+ if (addrP->addr != NULL) {
+ tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
+ memcpy(tmpaddr->addr, addrP->addr, addr_size);
+ }
+
+ if (addrP->brdcast != NULL) {
+ tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
+ memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
+ }
+
+ tmpaddr->next = currif->addr;
+ currif->addr = tmpaddr;
}
return ifs;
}
-/**
- * Get flags from a NetworkInterface.
+/* Open socket for further ioct calls
+ * proto is AF_INET/AF_INET6
*/
-static short getFlags(JNIEnv *env, jstring name) {
- int sock;
- struct ifreq if2;
- jboolean isCopy;
- const char* name_utf;
- short ret = -1;
+static int openSocket(JNIEnv *env, int proto){
+ int sock;
+
+ if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
+ /*
+ * If EPROTONOSUPPORT is returned it means we don't have
+ * support for this proto so don't throw an exception.
+ */
+ if (errno != EPROTONOSUPPORT) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
+ }
+ return -1;
+ }
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return -1;
- }
+ return sock;
+}
+
+
+/** Linux **/
+#ifdef __linux__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ int sock;
+ struct ifreq if2;
- name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
- memset((char *) &if2, 0, sizeof(if2));
- strcpy(if2.ifr_name, name_utf);
+ if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (errno == EPROTONOSUPPORT){
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+ }
+ else{ // errno is not NOSUPPORT
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+ return -1;
+ }
+ }
+
+ /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
+ of address of an interface */
+
+ return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ return openSocket(env,AF_INET);
+}
+#endif
- if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
- ret = if2.ifr_flags;
- } else {
-#if defined(__solaris__) && defined(AF_INET6)
- /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
- struct lifreq lifr;
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ struct ifconf ifc;
+ struct ifreq *ifreqP;
+ char *buf;
+ int numifs;
+ unsigned i;
+
- close(sock);
- sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+ /* need to do a dummy SIOCGIFCONF to determine the buffer size.
+ * SIOCGIFCOUNT doesn't work
+ */
+ ifc.ifc_buf = NULL;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+ return ifs;
+ }
- if (sock < 0) {
- (*env)->ReleaseStringUTFChars(env, name, name_utf);
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return -1;
+ CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
+
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+ (void) free(buf);
+ return ifs;
}
- memset((caddr_t)&lifr, 0, sizeof(lifr));
- strcpy((caddr_t)&(lifr.lifr_name), name_utf);
+ /*
+ * Iterate through each interface
+ */
+ ifreqP = ifc.ifc_req;
+ for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+ /*
+ * Add to the list
+ */
+ ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
- if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
- ret = lifr.lifr_flags;
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
+ /*
+ * If an exception occurred then free the list
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ free(buf);
+ freeif(ifs);
+ return NULL;
+ }
}
-#else
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
+
+ /*
+ * Free socket and buffer
+ */
+ free(buf);
+ return ifs;
+}
+
+
+/*
+ * Enumerates and returns all IPv6 interfaces on Linux
+ */
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ FILE *f;
+ char addr6[40], devname[20];
+ char addr6p[8][5];
+ int plen, scope, dad_status, if_idx;
+ uint8_t ipv6addr[16];
+
+ if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+ &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
+
+ struct netif *ifs_ptr = NULL;
+ struct netif *last_ptr = NULL;
+ struct sockaddr_in6 addr;
+
+ sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+ inet_pton(AF_INET6, addr6, ipv6addr);
+
+ memset(&addr, 0, sizeof(struct sockaddr_in6));
+ memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
+
+ addr.sin6_scope_id = if_idx;
+
+ ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
+
+
+ /*
+ * If an exception occurred then return the list as is.
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ fclose(f);
+ return ifs;
+ }
+ }
+ fclose(f);
+ }
+ return ifs;
+}
#endif
- }
- close(sock);
- /* release the UTF string and interface list */
- (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
- return ret;
+static int getIndex(int sock, const char *name){
+ /*
+ * Try to get the interface index
+ * (Not supported on Solaris 2.6 or 7)
+ */
+ struct ifreq if2;
+ strcpy(if2.ifr_name, name);
+
+ if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
+ return -1;
+ }
+
+ return if2.ifr_ifindex;
}
/**
* Returns the IPv4 broadcast address of a named interface, if it exists.
* Returns 0 if it doesn't have one.
*/
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname) {
- int sock;
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
struct sockaddr *ret = NULL;
struct ifreq if2;
- short flag = 0;
-
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return ret;
- }
memset((char *) &if2, 0, sizeof(if2));
strcpy(if2.ifr_name, ifname);
+
/* Let's make sure the interface does have a broadcast address */
- if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
- flag = if2.ifr_flags;
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
+ return ret;
}
- if (flag & IFF_BROADCAST) {
- /* It does, let's retrieve it*/
- if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) >= 0) {
- ret = (struct sockaddr*) malloc(sizeof(struct sockaddr));
+
+ if (if2.ifr_flags & IFF_BROADCAST) {
+ /* It does, let's retrieve it*/
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
+ return ret;
+ }
+
+ ret = brdcast_store;
memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- }
}
- close(sock);
+
return ret;
}
@@ -1222,39 +1183,314 @@
* Returns the IPv4 subnet prefix length (aka subnet mask) for the named
* interface, if it has one, otherwise return -1.
*/
-static short getSubnet(JNIEnv *env, const char *ifname) {
- int sock;
- unsigned int mask;
- short ret;
- struct ifreq if2;
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+ unsigned int mask;
+ short ret;
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+ return -1;
+ }
+
+ mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
+ ret = 0;
+ while (mask) {
+ mask <<= 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+ static struct ifreq ifr;
+ int i;
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
+ return -1;
+ }
+
+ memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+ /*
+ * All bytes to 0 means no hardware address.
+ */
+
+ for (i = 0; i < IFHWADDRLEN; i++) {
+ if (buf[i] != 0)
+ return IFHWADDRLEN;
+ }
+
return -1;
- }
+}
+
+static int getMTU(JNIEnv *env, int sock, const char *ifname) {
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+ return -1;
+ }
+
+ return if2.ifr_mtu;
+}
+
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+ struct ifreq if2;
+ int ret = -1;
memset((char *) &if2, 0, sizeof(if2));
strcpy(if2.ifr_name, ifname);
- if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) >= 0) {
- mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
- ret = 0;
- while (mask) {
- mask <<= 1;
- ret++;
+
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+ return -1;
+ }
+
+ return if2.ifr_flags;
+}
+
+#endif
+
+/** Solaris **/
+#ifdef __solaris__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ int sock, alreadyV6 = 0;
+ struct lifreq if2;
+
+ if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (errno == EPROTONOSUPPORT){
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+
+ alreadyV6=1;
+ }
+ else{ // errno is not NOSUPPORT
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+ return -1;
+ }
+ }
+
+ /**
+ * Solaris requires that we have IPv6 socket to query an
+ * interface without IPv4 address - check it here
+ * POSIX 1 require the kernell to return ENOTTY if the call is
+ * unappropriate for device e.g. NETMASK for device having IPv6
+ * only address but not all devices follows the standart so
+ * fallback on any error. It's not an ecology friendly but more
+ * reliable.
+ */
+
+ if (! alreadyV6 ){
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+ if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+ close(sock);
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+ }
}
- close(sock);
- return ret;
- }
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- close(sock);
- return -1;
+
+ return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ return openSocket(env,AF_INET);
+}
+#endif
+
+/*
+ * Enumerates and returns all IPv4 interfaces
+ * (linux verison)
+ */
+
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ return enumIPvXInterfaces(env,sock, ifs, AF_INET);
}
-#ifdef __solaris__
-#define DEV_PREFIX "/dev/"
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
+}
+#endif
+
+/*
+ Enumerates and returns all interfaces on Solaris
+ use the same code for IPv4 and IPv6
+ */
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
+ struct lifconf ifc;
+ struct lifreq *ifr;
+ int n;
+ char *buf;
+ struct lifnum numifs;
+ unsigned bufsize;
+
+ /*
+ * Get the interface count
+ */
+ numifs.lifn_family = family;
+ numifs.lifn_flags = 0;
+ if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
+ return ifs;
+ }
+
+ /*
+ * Enumerate the interface configurations
+ */
+ bufsize = numifs.lifn_count * sizeof (struct lifreq);
+ CHECKED_MALLOC3(buf, char *, bufsize);
+
+ ifc.lifc_family = family;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = bufsize;
+ ifc.lifc_buf = buf;
+ if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
+ free(buf);
+ return ifs;
+ }
+
+ /*
+ * Iterate through each interface
+ */
+ ifr = ifc.lifc_req;
+ for (n=0; n<numifs.lifn_count; n++, ifr++) {
+ int index = -1;
+ struct lifreq if2;
+
+ /*
+ * Ignore either IPv4 or IPv6 addresses
+ */
+ if (ifr->lifr_addr.ss_family != family) {
+ continue;
+ }
+
+#ifdef AF_INET6
+ if (ifr->lifr_addr.ss_family == AF_INET6) {
+ struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
+ s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
+ }
+#endif
+
+ /* add to the list */
+ ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
+
+ /*
+ * If an exception occurred we return immediately
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ free(buf);
+ return ifs;
+ }
+
+ }
+
+ free(buf);
+ return ifs;
+}
+
+static int getIndex(int sock, const char *name){
+ /*
+ * Try to get the interface index
+ * (Not supported on Solaris 2.6 or 7)
+ */
+ struct lifreq if2;
+ strcpy(if2.lifr_name, name);
+
+ if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
+ return -1;
+ }
+
+ return if2.lifr_index;
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+ struct sockaddr *ret = NULL;
+ struct lifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+
+ /* Let's make sure the interface does have a broadcast address */
+ if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+ return ret;
+ }
+
+ if (if2.lifr_flags & IFF_BROADCAST) {
+ /* It does, let's retrieve it*/
+ if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
+ return ret;
+ }
+
+ ret = brdcast_store;
+ memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
+ }
+
+ return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+ unsigned int mask;
+ short ret;
+ struct lifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+
+ if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
+ return -1;
+ }
+
+ mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
+ ret = 0;
+
+ while (mask) {
+ mask <<= 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+
+
+#define DEV_PREFIX "/dev/"
/**
* Solaris specific DLPI code to get hardware address from a device.
@@ -1262,306 +1498,147 @@
* privileges (i.e. be root).
*/
static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
- char style1dev[MAXPATHLEN];
- int fd;
- dl_phys_addr_req_t dlpareq;
- dl_phys_addr_ack_t *dlpaack;
- struct strbuf msg;
- char buf[128];
- int flags = 0;
+ char style1dev[MAXPATHLEN];
+ int fd;
+ dl_phys_addr_req_t dlpareq;
+ dl_phys_addr_ack_t *dlpaack;
+ struct strbuf msg;
+ char buf[128];
+ int flags = 0;
+
+ /**
+ * Device is in /dev
+ * e.g.: /dev/bge0
+ */
+ strcpy(style1dev, DEV_PREFIX);
+ strcat(style1dev, ifname);
+ if ((fd = open(style1dev, O_RDWR)) < 0) {
+ /*
+ * Can't open it. We probably are missing the privilege.
+ * We'll have to try something else
+ */
+ return 0;
+ }
+
+ dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
+ dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
- /**
- * Device is in /dev
- * e.g.: /dev/bge0
- */
- strcpy(style1dev, DEV_PREFIX);
- strcat(style1dev, ifname);
- if ((fd = open(style1dev, O_RDWR)) == -1) {
- /*
- * Can't open it. We probably are missing the privilege.
- * We'll have to try something else
- */
- return 0;
- }
- dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
- dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
- msg.buf = (char *)&dlpareq;
- msg.len = DL_PHYS_ADDR_REQ_SIZE;
- if (putmsg(fd, &msg, NULL, 0) < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "putmsg failed");
- return -1;
- }
- dlpaack = (dl_phys_addr_ack_t *)buf;
- msg.buf = (char *)buf;
- msg.len = 0;
- msg.maxlen = sizeof (buf);
- if (getmsg(fd, &msg, NULL, &flags) < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "getmsg failed");
- return -1;
- }
- if (msg.len < DL_PHYS_ADDR_ACK_SIZE ||
- dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Couldn't obtain phys addr\n");
- return -1;
- }
+ msg.buf = (char *)&dlpareq;
+ msg.len = DL_PHYS_ADDR_REQ_SIZE;
+
+ if (putmsg(fd, &msg, NULL, 0) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
+ return -1;
+ }
+
+ dlpaack = (dl_phys_addr_ack_t *)buf;
- memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
- return dlpaack->dl_addr_length;
+ msg.buf = (char *)buf;
+ msg.len = 0;
+ msg.maxlen = sizeof (buf);
+ if (getmsg(fd, &msg, NULL, &flags) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
+ return -1;
+ }
+
+ if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
+ return -1;
+ }
+
+ memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
+ return dlpaack->dl_addr_length;
}
-#endif
/**
* Get the Hardware address (usually MAC address) for the named interface.
* return puts the data in buf, and returns the length, in byte, of the
* MAC address. Returns -1 if there is no hardware address on that interface.
*/
-int getMacAddress(JNIEnv *env, const struct in_addr* addr, const char* ifname,
- unsigned char *buf) {
- int sock;
-#ifdef __linux__
- static struct ifreq ifr;
- int i;
+static int getMacAddress(JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr, unsigned char *buf) {
+ struct arpreq arpreq;
+ struct sockaddr_in* sin;
+ struct sockaddr_in ipAddr;
+ int len, i;
+
+ /**
+ * On Solaris we have to use DLPI, but it will only work if we have
+ * privileged access (i.e. root). If that fails, we try a lookup
+ * in the ARP table, which requires an IPv4 address.
+ */
+ if ((len = getMacFromDevice(env, ifname, buf)) == 0) {
+ /*DLPI failed - trying to do arp lookup*/
+
+ if (addr == NULL) {
+ /**
+ * No IPv4 address for that interface, so can't do an ARP lookup.
+ */
+ return -1;
+ }
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
+ len = 6; //???
+
+ sin = (struct sockaddr_in *) &arpreq.arp_pa;
+ memset((char *) &arpreq, 0, sizeof(struct arpreq));
+ ipAddr.sin_port = 0;
+ ipAddr.sin_family = AF_INET;
+ memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
+ memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
+ arpreq.arp_flags= ATF_PUBL;
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return -1;
+ if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
+ if (errno != ENXIO) {
+ // "No such device or address" means no hardware address, so it's
+ // normal don't throw an exception
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL failed");
+ return -1;
+ }
+ }
+
+ memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
}
- strcpy(ifr.ifr_name, ifname);
-
- if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
- fprintf(stderr, "SIOCIFHWADDR: %s\n",
- strerror(errno));
- close(sock);
- return -1;
- }
- memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
- close(sock);
- for (i = 0; i < IFHWADDRLEN; i++) {
- if (buf[i] != 0)
- return IFHWADDRLEN;
- }
- /*
- * All bytes to 0 means no hardware address.
- */
- return -1;
-#else
- struct arpreq arpreq;
- struct sockaddr_in* sin;
- struct sockaddr_in ipAddr;
- int len;
-
- /**
- * On Solaris we have to use DLPI, but it will only work if we have
- * privileged access (i.e. root). If that fails, we try a lookup
- * in the ARP table, which requires an IPv4 address.
- */
- if ((len = getMacFromDevice(env, ifname, buf)) > 0) {
- return len;
- }
- if (addr == NULL) {
- /**
- * No IPv4 address for that interface, so can't do an ARP lookup.
+ /*
+ * All bytes to 0 means no hardware address.
*/
- return -1;
- }
- sin = (struct sockaddr_in *) &arpreq.arp_pa;
- memset((char *) &arpreq, 0, sizeof(struct arpreq));
- ipAddr.sin_port = 0;
- ipAddr.sin_family = AF_INET;
- memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
- memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
- arpreq.arp_flags= ATF_PUBL;
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return -1;
- }
- if (ioctl(sock, SIOCGARP, &arpreq) >= 0) {
- close(sock);
- memcpy(buf, &arpreq.arp_ha.sa_data[0], 6);
- return 6;
- }
-
- if (errno != ENXIO) {
- // "No such device or address" means no hardware address, so it's
- // normal don't throw an exception
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- }
- close(sock);
-#endif
- return -1;
-}
-
-/*
- * Class: java_net_NetworkInterface
- * Method: isUp0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
- (JNIEnv *env, jclass cls, jstring name, jint index) {
- short val;
+ for (i = 0; i < len; i++) {
+ if (buf[i] != 0)
+ return len;
+ }
- val = getFlags(env, name);
- if ( (val & IFF_UP) && (val & IFF_RUNNING))
- return JNI_TRUE;
- return JNI_FALSE;
-}
-
-/*
- * Class: java_net_NetworkInterface
- * Method: isP2P0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
- (JNIEnv *env, jclass cls, jstring name, jint index) {
- if (getFlags(env, name) & IFF_POINTOPOINT)
- return JNI_TRUE;
- return JNI_FALSE;
-}
-
-/*
- * Class: java_net_NetworkInterface
- * Method: isLoopback0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
- (JNIEnv *env, jclass cls, jstring name, jint index) {
- if (getFlags(env, name) & IFF_LOOPBACK)
- return JNI_TRUE;
- return JNI_FALSE;
+ return -1;
}
-/*
- * Class: java_net_NetworkInterface
- * Method: supportsMulticast0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
-(JNIEnv *env, jclass cls, jstring name, jint index) {
- short val;
+static int getMTU(JNIEnv *env, int sock, const char *ifname) {
+ struct lifreq if2;
- val = getFlags(env, name);
- if (val & IFF_MULTICAST)
- return JNI_TRUE;
- return JNI_FALSE;
-}
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
-/*
- * Class: java_net_NetworkInterface
- * Method: getMacAddr0
- * Signature: ([bLjava/lang/String;I)[b
- */
-JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
- jint addr;
- jbyte caddr[4];
- struct in_addr iaddr;
- jbyteArray ret = NULL;
- unsigned char mac[16];
- int len;
- jboolean isCopy;
- const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
+ return -1;
+ }
- if (!IS_NULL(addrArray)) {
- (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- iaddr.s_addr = htonl(addr);
- len = getMacAddress(env, &iaddr, name_utf, mac);
- } else {
- len = getMacAddress(env, NULL, name_utf, mac);
- }
- if (len > 0) {
- ret = (*env)->NewByteArray(env, len);
- if (IS_NULL(ret)) {
- /* we may have memory to free at the end of this */
- goto fexit;
- }
- (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
- }
- fexit:
- /* release the UTF string and interface list */
- (*env)->ReleaseStringUTFChars(env, name, name_utf);
- return ret;
+ return if2.lifr_mtu;
}
-/*
- * Class: java_net_NetworkInterface
- * Method: getMTU0
- * Signature: ([bLjava/lang/String;I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
- jboolean isCopy;
- int sock;
- struct ifreq if2;
- int ret = -1;
- const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-
- sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- } else {
-
-#ifdef __linux__
- memset((char *) &if2, 0, sizeof(if2));
- strcpy(if2.ifr_name, name_utf);
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+ struct lifreq lifr;
+ memset((caddr_t)&lifr, 0, sizeof(lifr));
+ strcpy((caddr_t)&(lifr.lifr_name), ifname);
- if (ioctl(sock, SIOCGIFMTU, (char *)&if2) >= 0) {
- ret= if2.ifr_mtu;
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- }
-#else /* Solaris */
- struct lifreq lifr;
- memset((caddr_t)&lifr, 0, sizeof(lifr));
- strcpy((caddr_t)&(lifr.lifr_name), name_utf);
- if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
- ret = lifr.lifr_mtu;
-#ifdef AF_INET6
- } else {
- /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
- close(sock);
- sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+ if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+ return -1;
+ }
- if (sock < 0) {
- (*env)->ReleaseStringUTFChars(env, name, name_utf);
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Socket creation failed");
- return -1;
- }
+ return lifr.lifr_flags;
+}
+
- if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
- ret = lifr.lifr_mtu;
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- }
- }
-#else
- } else {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "IOCTL failed");
- }
#endif
-#endif
- close(sock);
- }
- /* release the UTF string and interface list */
- (*env)->ReleaseStringUTFChars(env, name, name_utf);
- return ret;
-}
+
+
--- a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Wed Jul 05 17:18:01 2017 +0200
@@ -42,6 +42,29 @@
filename);
}
+static void quit(gboolean isSignalHandler)
+{
+ if (dialog != NULL)
+ {
+ // Callbacks from GTK signals are made within the GTK lock
+ // So, within a signal handler there is no need to call
+ // gdk_threads_enter() / fp_gdk_threads_leave()
+ if (!isSignalHandler) {
+ fp_gdk_threads_enter();
+ }
+
+ fp_gtk_widget_hide (dialog);
+ fp_gtk_widget_destroy (dialog);
+
+ fp_gtk_main_quit ();
+ dialog = NULL;
+
+ if (!isSignalHandler) {
+ fp_gdk_threads_leave();
+ }
+ }
+}
+
/*
* Class: sun_awt_X11_GtkFileDialogPeer
* Method: quit
@@ -50,18 +73,7 @@
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
(JNIEnv * env, jobject jpeer)
{
- if (dialog != NULL)
- {
- fp_gdk_threads_enter();
-
- fp_gtk_widget_hide (dialog);
- fp_gtk_widget_destroy (dialog);
-
- fp_gtk_main_quit ();
- dialog = NULL;
-
- fp_gdk_threads_leave();
- }
+ quit(FALSE);
}
/**
@@ -147,7 +159,7 @@
jfilenames);
fp_g_free(current_folder);
- Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL);
+ quit(TRUE);
}
/*
--- a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Wed Jul 05 17:18:01 2017 +0200
@@ -65,6 +65,11 @@
J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps");
+ if (oglsdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+ return;
+ }
+
if (glxsdo == NULL) {
JNU_ThrowOutOfMemoryError(env, "creating native GLX ops");
return;
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Wed Jul 05 17:18:01 2017 +0200
@@ -253,6 +253,10 @@
{
#ifndef HEADLESS
X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps));
+ if (xsdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+ return;
+ }
xsdo->sdOps.Lock = X11SD_Lock;
xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo;
xsdo->sdOps.Unlock = X11SD_Unlock;
--- a/jdk/src/windows/bin/java_md.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/windows/bin/java_md.c Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,26 +80,22 @@
*
*/
void
-CreateExecutionEnvironment(int *_argc,
- char ***_argv,
- char jrepath[],
- jint so_jrepath,
- char jvmpath[],
- jint so_jvmpath,
- char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+ char *jrepath, jint so_jrepath,
+ char *jvmpath, jint so_jvmpath) {
char * jvmtype;
int i = 0;
- char** pargv = *_argv;
int running = CURRENT_DATA_MODEL;
int wanted = running;
- for (i = 0; i < *_argc ; i++) {
- if (JLI_StrCmp(pargv[i], "-J-d64") == 0 || JLI_StrCmp(pargv[i], "-d64") == 0) {
+ char** argv = *pargv;
+ for (i = 0; i < *pargc ; i++) {
+ if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) {
wanted = 64;
continue;
}
- if (JLI_StrCmp(pargv[i], "-J-d32") == 0 || JLI_StrCmp(pargv[i], "-d32") == 0) {
+ if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) {
wanted = 32;
continue;
}
@@ -123,7 +119,12 @@
JLI_ReportErrorMessage(CFG_ERROR7);
exit(1);
}
- jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE);
+
+ jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+ if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+ JLI_ReportErrorMessage(CFG_ERROR9);
+ exit(4);
+ }
jvmpath[0] = '\0';
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) {
@@ -131,7 +132,6 @@
exit(4);
}
/* If we got here, jvmpath has been correctly initialized. */
-
}
@@ -203,19 +203,21 @@
PREJVMSTART PreJVMStart;
struct stat s;
+ /* Make sure the jrepath contains something */
+ if (jrepath[0] == NULL) {
+ return;
+ }
/* 32 bit windows only please */
- if (strcmp(GetArch(), "i386") != 0 ) {
+ if (JLI_StrCmp(GetArch(), "i386") != 0 ) {
return;
}
/* Does our bundle directory exist ? */
- strcpy(tmpbuf, jrepath);
- strcat(tmpbuf, "\\lib\\bundles");
+ JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\lib\\bundles", jrepath);
if (stat(tmpbuf, &s) != 0) {
return;
}
/* Does our jkernel dll exist ? */
- strcpy(tmpbuf, jrepath);
- strcat(tmpbuf, "\\bin\\jkernel.dll");
+ JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\bin\\jkernel.dll", jrepath);
if (stat(tmpbuf, &s) != 0) {
return;
}
@@ -249,30 +251,30 @@
if (GetApplicationHome(path, pathsize)) {
/* Is JRE co-located with the application? */
- sprintf(javadll, "%s\\bin\\" JAVA_DLL, path);
+ JLI_Snprintf(javadll, sizeof(javadll), "%s\\bin\\" JAVA_DLL, path);
if (stat(javadll, &s) == 0) {
- goto found;
+ JLI_TraceLauncher("JRE path is %s\n", path);
+ return JNI_TRUE;
}
/* Does this app ship a private JRE in <apphome>\jre directory? */
- sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path);
+ JLI_Snprintf(javadll, sizeof (javadll), "%s\\jre\\bin\\" JAVA_DLL, path);
if (stat(javadll, &s) == 0) {
JLI_StrCat(path, "\\jre");
- goto found;
+ JLI_TraceLauncher("JRE path is %s\n", path);
+ return JNI_TRUE;
}
}
/* Look for a public JRE on this machine. */
if (GetPublicJREHome(path, pathsize)) {
- goto found;
+ JLI_TraceLauncher("JRE path is %s\n", path);
+ return JNI_TRUE;
}
JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
return JNI_FALSE;
- found:
- JLI_TraceLauncher("JRE path is %s\n", path);
- return JNI_TRUE;
}
/*
@@ -286,9 +288,9 @@
{
struct stat s;
if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) {
- sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype);
+ JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype);
} else {
- sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
+ JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
}
if (stat(jvmpath, &s) == 0) {
return JNI_TRUE;
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Wed Jul 05 17:18:01 2017 +0200
@@ -312,14 +312,17 @@
private int processSelectedKeys(long updateCount) {
int numKeysUpdated = 0;
numKeysUpdated += processFDSet(updateCount, readFds,
- PollArrayWrapper.POLLIN);
+ PollArrayWrapper.POLLIN,
+ false);
numKeysUpdated += processFDSet(updateCount, writeFds,
PollArrayWrapper.POLLCONN |
- PollArrayWrapper.POLLOUT);
+ PollArrayWrapper.POLLOUT,
+ false);
numKeysUpdated += processFDSet(updateCount, exceptFds,
PollArrayWrapper.POLLIN |
PollArrayWrapper.POLLCONN |
- PollArrayWrapper.POLLOUT);
+ PollArrayWrapper.POLLOUT,
+ true);
return numKeysUpdated;
}
@@ -331,7 +334,9 @@
*
* me.updateCount <= me.clearedCount <= updateCount
*/
- private int processFDSet(long updateCount, int[] fds, int rOps) {
+ private int processFDSet(long updateCount, int[] fds, int rOps,
+ boolean isExceptFds)
+ {
int numKeysUpdated = 0;
for (int i = 1; i <= fds[0]; i++) {
int desc = fds[i];
@@ -347,6 +352,17 @@
if (me == null)
continue;
SelectionKeyImpl sk = me.ski;
+
+ // The descriptor may be in the exceptfds set because there is
+ // OOB data queued to the socket. If there is OOB data then it
+ // is discarded and the key is not added to the selected set.
+ if (isExceptFds &&
+ (sk.channel() instanceof SocketChannelImpl) &&
+ discardUrgentData(desc))
+ {
+ continue;
+ }
+
if (selectedKeys.contains(sk)) { // Key in selected set
if (me.clearedCount != updateCount) {
if (sk.channel.translateAndSetReadyOps(rOps, sk) &&
@@ -460,6 +476,8 @@
private native void resetWakeupSocket0(int wakeupSourceFd);
+ private native boolean discardUrgentData(int fd);
+
// We increment this counter on each call to updateSelectedKeys()
// each entry in SubSelector.fdsMap has a memorized value of
// updateCount. When we increment numKeysUpdated we set updateCount
--- a/jdk/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c Wed Jul 05 17:18:01 2017 +0200
@@ -66,6 +66,10 @@
J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps");
+ if (oglsdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+ return;
+ }
if (wglsdo == NULL) {
JNU_ThrowOutOfMemoryError(env, "creating native wgl ops");
return;
--- a/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Wed Jul 05 17:18:01 2017 +0200
@@ -363,6 +363,10 @@
{
J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initOps");
GDIWinSDOps *wsdo = (GDIWinSDOps *)SurfaceData_InitOps(env, wsd, sizeof(GDIWinSDOps));
+ if (wsdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+ return;
+ }
wsdo->sdOps.Lock = GDIWinSD_Lock;
wsdo->sdOps.GetRasInfo = GDIWinSD_GetRasInfo;
wsdo->sdOps.Unlock = GDIWinSD_Unlock;
--- a/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Wed Jul 05 17:18:01 2017 +0200
@@ -214,3 +214,19 @@
recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0);
}
}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_WindowsSelectorImpl_discardUrgentData(JNIEnv* env, jobject this,
+ jint s)
+{
+ char data[8];
+ jboolean discarded = JNI_FALSE;
+ int n;
+ do {
+ n = recv(s, &data, sizeof(data), MSG_OOB);
+ if (n > 0) {
+ discarded = JNI_TRUE;
+ }
+ } while (n > 0);
+ return discarded;
+}
--- a/jdk/test/Makefile Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/Makefile Wed Jul 05 17:18:01 2017 +0200
@@ -495,19 +495,17 @@
jdk_nio1: java/nio/file
$(call RunSamevmBatch)
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-# Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_nio2
jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
$(call SharedLibraryPermissions,java/nio/channels)
- $(call RunOthervmBatch)
+ $(call RunSamevmBatch)
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-# Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_nio3
jdk_nio3: com/sun/nio sun/nio
- $(call RunOthervmBatch)
+ $(call RunSamevmBatch)
# All nio tests
jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
--- a/jdk/test/ProblemList.txt Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/ProblemList.txt Wed Jul 05 17:18:01 2017 +0200
@@ -295,9 +295,6 @@
# jdk_misc
-# On Windows com.sun.java.swing.plaf.gtk does not exist, always fails there
-com/sun/java/swing/plaf/gtk/Test6635110.java windows-all
-
# Need to be marked othervm, or changed to be samevm safe
com/sun/jndi/ldap/ReadTimeoutTest.java generic-all
com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java generic-all
@@ -379,9 +376,6 @@
# Interrupted or IO exception, maybe writing to non-unique named file?
com/sun/net/httpserver/bugs/B6373555.java generic-all
-# Fails on OpenSolaris, BindException unexpected
-java/net/BindException/Test.java generic-all
-
# Fails on OpenSolaris, times out
java/net/MulticastSocket/SetOutgoingIf.java generic-all
@@ -507,25 +501,46 @@
############################################################################
+# jdk_io
+
+# 6962637
+java/io/File/MaxPathLength.java windows-all
+
+############################################################################
+
# jdk_nio
-# Suspect many of these tests auffer from using fixed ports, no concrete
-# evidence.
+# 6944810
+java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all
+
+# 6963118
+java/nio/channels/Selector/Wakeup.java windows-all
-# Occasionally Failing with java.lang.AssertionError on Windows X64
-# at sun.nio.ch.PendingIoCache.clearPendingIoMap(PendingIoCache.java:144)
-#java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all
+# The asynchronous I/O implementation on Windows requires Windows XP or newer.
+# We can remove the following once all Windows 2000 machines have been
+# decommissioned.
+java/nio/channels/AsynchronousChannelGroup/Basic.java windows-5.0
+java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Identity.java windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Restart.java windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Unbounded.java windows-5.0
+java/nio/channels/AsynchronousDatagramChannel/Basic.java windows-5.0
+java/nio/channels/AsynchronousFileChannel/Lock.java windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/Basic.java windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Basic.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Leaky.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
+java/nio/channels/Channels/Basic2.java windows-5.0
-# Some kind of sleep/wake problem on Windows X64
-java/nio/channels/Selector/Wakeup.java windows-all
+# 6959891
+com/sun/nio/sctp/SctpChannel/SocketOptionTests.java
# Fails with -ea -esa, Assertion error, but only on Solaris 10 machines?
com/sun/nio/sctp/SctpChannel/Send.java generic-all
com/sun/nio/sctp/SctpChannel/Shutdown.java generic-all
-# Fails on Windows 2000, times out
-java/nio/channels/FileChannel/Transfer.java generic-all
-
# Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses
# from a channel that is bound to the wildcard address
com/sun/nio/sctp/SctpChannel/Bind.java generic-all
@@ -533,18 +548,6 @@
# Failed on OpenSolaris, java.lang.AssertionError: Unknown event type
com/sun/nio/sctp/SctpChannel/Receive.java generic-all
-# Triggers a hotspot crash on Fedora 9 32bit -server and Windows X64 samevm
-sun/nio/cs/TestUTF8.java generic-all
-
-# Runtime exception on windows X64, samevm mode
-java/nio/channels/Selector/WakeupNow.java generic-all
-
-# Occasional errors, solarix x86, address already in use, othervm mode
-java/nio/channels/Selector/SelectorTest.java generic-all
-
-# Fails on Linux Fedora 9 X64
-sun/nio/cs/FindDecoderBugs.java generic-all
-
# Solaris 11 gave assert error and "connection refused", samevm issues?
com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java generic-all
@@ -555,49 +558,6 @@
com/sun/nio/sctp/SctpMultiChannel/Send.java generic-all
com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java generic-all
-# Linux 64bit failures. too many files open
-java/nio/channels/Selector/HelperSlowToDie.java generic-all
-
-# Gets java.lang.ExceptionInInitializerError on Windows 2000 (need XP or newer)
-java/nio/channels/AsynchronousChannelGroup/Basic.java windows-5.0
-java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Identity.java windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Restart.java windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Unbounded.java windows-5.0
-java/nio/channels/AsynchronousDatagramChannel/Basic.java windows-5.0
-java/nio/channels/AsynchronousFileChannel/Lock.java windows-5.0
-java/nio/channels/AsynchronousServerSocketChannel/Basic.java windows-5.0
-java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/Basic.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/Leaky.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
-java/nio/channels/Channels/Basic2.java windows-5.0
-
-# Failed loopback connection? On windows 32bit?
-# Considered a stress test, can consume all resources.
-java/nio/channels/Selector/LotsOfChannels.java generic-all
-
-# Windows i586 client, crashed hotspot? Unpredictable
-# Considered a stress test, can consume all resources.
-java/nio/channels/Selector/RegAfterPreClose.java generic-all
-
-# Solaris i586, cannot assign address, samevm issues
-java/nio/channels/Selector/SelectorLimit.java generic-all
-
-# Socket timeout windows X64
-java/nio/channels/ServerSocketChannel/AdaptServerSocket.java windows-all
-
-# Timeouts etc. on Window
-java/nio/channels/SocketChannel/ConnectState.java windows-all
-java/nio/channels/SocketChannel/FinishConnect.java windows-all
-
-# Fails on all platforms due to overlap of JDK jar file contents:
-sun/nio/cs/Test4200310.sh generic-all
-
-# Depends on motif packages that do not exist all the time:
-sun/nio/cs/TestX11CNS.java generic-all
-
############################################################################
# jdk_rmi
@@ -848,9 +808,6 @@
# jdk_swing (not using samevm)
-# Fails on solaris 10 sparc, throws RuntimeException that just says "failed"
-javax/swing/JLabel/6501991/bug6501991.java generic-all
-
# Fails on solaris 11 i586, with othervm
javax/swing/JFileChooser/6570445/bug6570445.java generic-all
javax/swing/JFileChooser/6738668/bug6738668.java generic-all
--- a/jdk/test/com/sun/java/swing/plaf/gtk/Test6635110.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/com/sun/java/swing/plaf/gtk/Test6635110.java Wed Jul 05 17:18:01 2017 +0200
@@ -28,7 +28,6 @@
@run main Test6635110
*/
-import com.sun.java.swing.plaf.gtk.GTKLookAndFeel;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
@@ -59,7 +58,12 @@
}
public static void main(String[] args) throws Exception {
- UIManager.setLookAndFeel(new GTKLookAndFeel());
+ try {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+ } catch (Exception e) {
+ System.out.println("GTKLookAndFeel cannot be set, skipping this test");
+ return;
+ }
SwingUtilities.invokeAndWait(new Test6635110());
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/java/swing/plaf/gtk/Test6963870.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 6963870
+ @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets()
+ doesn't return null
+ @author Peter Zhelezniakov
+ @run main Test6963870
+*/
+
+import java.awt.Insets;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+
+public class Test6963870 implements Runnable {
+
+ final static String[] UI_NAMES = {
+ "List.focusCellHighlightBorder",
+ "List.focusSelectedCellHighlightBorder",
+ "List.noFocusBorder",
+ "Table.focusCellHighlightBorder",
+ "Table.focusSelectedCellHighlightBorder",
+ };
+
+ public void run() {
+ for (String uiName: UI_NAMES) {
+ test(uiName);
+ }
+ }
+
+ void test(String uiName) {
+ Border b = UIManager.getBorder(uiName);
+ Insets i = b.getBorderInsets(null);
+ if (i == null) {
+ throw new RuntimeException("getBorderInsets() returns null for " + uiName);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ try {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+ } catch (Exception e) {
+ System.out.println("GTKLookAndFeel cannot be set, skipping this test");
+ return;
+ }
+
+ SwingUtilities.invokeAndWait(new Test6963870());
+ }
+}
+
--- a/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
/*
@test
@bug 6304473 6727884
--- a/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Wed Jul 05 17:18:01 2017 +0200
@@ -34,35 +34,40 @@
import java.awt.*;
import java.awt.event.*;
-import java.lang.Math;
+
+import sun.awt.SunToolkit;
+
import test.java.awt.regtesthelpers.Util;
public class LoopRobustness {
- static int clicks = 0;
+
final static long TIMEOUT = 5000;
final static Object LOCK = new Object();
- static volatile boolean notifyOccur = false;
- public static void main(String [] args) {
+ public static int clicks = 0;
+ public static volatile boolean notifyOccured = false;
+ public static volatile boolean otherExceptionsCaught = false;
+
+ public static void main(String [] args) throws Exception {
ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
long at;
//wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
- synchronized (LoopRobustness.LOCK){
+ synchronized (LoopRobustness.LOCK) {
new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
at = System.currentTimeMillis();
try {
- while(!notifyOccur && System.currentTimeMillis() - at < TIMEOUT) {
+ while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) {
LoopRobustness.LOCK.wait(1000);
}
- } catch(InterruptedException e){
+ } catch (InterruptedException e) {
throw new RuntimeException("Test interrupted.", e);
}
}
- if( !notifyOccur){
+ if (!notifyOccured) {
//notify doesn't occur after a reasonable time.
- throw new RuntimeException("Test failed. Second Thread didn't notify MainThread.");
+ throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread");
}
//now wait for two clicks
@@ -75,7 +80,10 @@
}
}
if (clicks != 2) {
- throw new RuntimeException("robot should press button twice");
+ throw new RuntimeException("Test FAILED: robot should press button twice");
+ }
+ if (otherExceptionsCaught) {
+ throw new RuntimeException("Test FAILED: unexpected exceptions caught");
}
}
}
@@ -83,18 +91,11 @@
class Impl implements Runnable{
static Robot robot;
public void run() {
+ SunToolkit.createNewAppContext();
+
Button b = new Button("Press me to test the AWT-Event Queue thread");
Frame lr = new Frame("ROBUST FRAME");
- /* Must load Toolkit on this thread only, rather then on Main.
- If load on Main (on the parent ThreadGroup of current ThreadGroup) then
- EDT will be created on Main thread and supplied with it's own exceptionHandler,
- which just throws an Exception and terminates current thread.
- The test implies that EDT is created on the child ThreadGroup (testThreadGroup)
- which is supplied with its own uncaughtException().
- */
- Toolkit.getDefaultToolkit();
lr.setBounds(100, 100, 300, 100);
-
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LoopRobustness.clicks++;
@@ -107,40 +108,46 @@
try {
robot = new Robot();
- } catch(AWTException e){
+ } catch (AWTException e) {
throw new RuntimeException("Test interrupted.", e);
}
Util.waitForIdle(robot);
synchronized (LoopRobustness.LOCK){
LoopRobustness.LOCK.notify();
- LoopRobustness.notifyOccur = true;
+ LoopRobustness.notifyOccured = true;
}
int i = 0;
- while(i < 2){
+ while (i < 2) {
robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
- b.getLocationOnScreen().y + b.getHeight()/2 );
+ b.getLocationOnScreen().y + b.getHeight()/2);
+ Util.waitForIdle(robot);
robot.mousePress(InputEvent.BUTTON1_MASK);
- // robot.delay(10);
+ Util.waitForIdle(robot);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(robot);
i++;
- robot.delay(1000);
}
}
}
class TestThreadGroup extends ThreadGroup {
- TestThreadGroup(ThreadGroup threadGroup, String name){
+ TestThreadGroup(ThreadGroup threadGroup, String name) {
super(threadGroup, name);
}
- public void uncaughtException(Thread exitedThread, Throwable e) {
- e.printStackTrace();
- if ((e instanceof ExceptionInInitializerError) || (e instanceof
- NoClassDefFoundError)){
- throw new RuntimeException("Test failed: other Exceptions were thrown ", e);
+ public void uncaughtException(Thread thread, Throwable e) {
+ System.out.println("Exception caught: " + e);
+ e.printStackTrace(System.out);
+ System.out.flush();
+ if ((e instanceof ExceptionInInitializerError) ||
+ (e instanceof NoClassDefFoundError))
+ {
+ // These two are expected
+ return;
}
+ LoopRobustness.otherExceptionsCaught = true;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/EventDispatchThread/PreserveDispathThread/PreserveDispatchThread.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ @test
+ @bug 6424157
+ @author Artem Ananiev: area=eventqueue
+ @run main PreserveDispatchThread
+*/
+
+import java.awt.*;
+import java.awt.event.*;
+
+public class PreserveDispatchThread {
+
+ private static volatile Frame f;
+ private static volatile Dialog d;
+
+ private static volatile boolean isEDT = true;
+
+ public static void main(String[] args) throws Exception {
+ f = new Frame("F");
+ f.setSize(320, 340);
+ f.setLocationRelativeTo(null);
+ f.setVisible(true);
+
+ try {
+ test1();
+ if (!isEDT) {
+ throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
+ }
+
+ test2();
+ if (!isEDT) {
+ throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
+ }
+
+ test3();
+ if (!isEDT) {
+ throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
+ }
+ } finally {
+ if (d != null) {
+ d.dispose();
+ }
+ f.dispose();
+ }
+ }
+
+ /*
+ * Tests that push/pop doesn't change the dispatch thread if
+ * called on EDT.
+ */
+ private static void test1() throws Exception {
+ EventQueue.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ TestEventQueue teq = new TestEventQueue();
+ EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ try {
+ seq.push(teq);
+ d = new TestDialog();
+ d.setVisible(true);
+ checkEDT();
+ } finally {
+ teq.pop();
+ }
+ checkEDT();
+ }
+ });
+ }
+
+ /*
+ * Tests that push/pop doesn't change the dispatch thread if
+ * called on the main thread.
+ */
+ private static void test2() throws Exception {
+ TestEventQueue teq = new TestEventQueue();
+ EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ try {
+ seq.push(teq);
+ EventQueue.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ checkEDT();
+ d = new TestDialog();
+ d.setVisible(true);
+ checkEDT();
+ }
+ });
+ } finally {
+ teq.pop();
+ }
+ }
+
+ private static final Object test3Lock = new Object();
+ private static boolean test3Sync = false;
+
+ /*
+ * A complex test: several nested invokeLater() are called and
+ * in every runnable a check for EDT is performed. At the ent
+ * of the test we wait for all the runnables to be processed
+ * and the dialog is disposed; otherwise the last EDT check can
+ * be later than this method returns and the whole test is passed.
+ */
+ private static void test3() throws Exception {
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ d = new Dialog(f, true);
+ d.setSize(240, 180);
+ d.setLocationRelativeTo(f);
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ d.setVisible(true);
+ checkEDT();
+ }
+ });
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ TestEventQueue teq = new TestEventQueue();
+ EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ try {
+ seq.push(teq);
+ checkEDT();
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ d.dispose();
+ checkEDT();
+ synchronized (test3Lock) {
+ test3Sync = true;
+ test3Lock.notify();
+ }
+ }
+ });
+ } finally {
+ teq.pop();
+ }
+ checkEDT();
+ }
+ });
+ checkEDT();
+ }
+ });
+ synchronized (test3Lock) {
+ while (!test3Sync) {
+ try {
+ test3Lock.wait();
+ } catch (InterruptedException ie) {
+ break;
+ }
+ }
+ }
+ // Make sure all the nested invokeLater/invokeAndWait are processed
+ EventQueue.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ }
+ });
+ }
+
+ private static void checkEDT() {
+ isEDT = isEDT && EventQueue.isDispatchThread();
+ }
+
+ private static class TestEventQueue extends EventQueue {
+ public TestEventQueue() {
+ super();
+ }
+ public void pop() {
+ super.pop();
+ }
+ }
+
+ private static class TestDialog extends Dialog {
+ private volatile boolean dialogShown = false;
+ private volatile boolean paintCalled = false;
+ public TestDialog() {
+ super(f, true);
+ setSize(240, 180);
+ setLocationRelativeTo(f);
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentShown(ComponentEvent e) {
+ if (paintCalled) {
+ dispose();
+ }
+ dialogShown = true;
+ }
+ });
+ }
+ @Override
+ public void paint(Graphics g) {
+ if (dialogShown) {
+ dispose();
+ }
+ paintCalled = true;
+ }
+ }
+
+}
--- a/jdk/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java Wed Jul 05 17:18:01 2017 +0200
@@ -43,6 +43,7 @@
Runnable dummy = new Runnable() {
public void run() {
System.err.println("Dummy is here.");
+ System.err.flush();
}
};
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
@@ -58,10 +59,11 @@
Runnable runnable = new Runnable() {
public void run() {
System.err.println("Dummy from SunToolkit");
+ System.err.flush();
}
};
InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
- System.err.println(ie);
+// System.err.println(ie);
SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
eq1.pop();
frame.dispose();
@@ -70,14 +72,14 @@
class MyEventQueue1 extends EventQueue {
- public void pop() throws EmptyStackException {
+ public void pop() {
super.pop();
}
}
class MyEventQueue2 extends EventQueue {
- protected void pop() throws EmptyStackException {
+ protected void pop() {
System.err.println("pop2()");
Thread.dumpStack();
try {
@@ -85,7 +87,8 @@
public void run() {
Runnable runnable = new Runnable() {
public void run() {
- System.err.println("Dummy from here");
+ System.err.println("Dummy from pop");
+ System.err.flush();
}
};
InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
--- a/jdk/test/java/awt/FontClass/FontPrivilege.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/awt/FontClass/FontPrivilege.java Wed Jul 05 17:18:01 2017 +0200
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 5010310 6319835 6904882
+ * @bug 5010310 6319835 6904882 6968373
* @summary test fonts can be created in the presence of a security manager
* @run main/othervm/secure=java.lang.SecurityManager FontPrivilege
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test6707234.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6707234
+ * @summary Tests setter in a complex bean
+ * @author Sergey Malenkov
+ */
+
+public class Test6707234 {
+ public static void main(String[] args) {
+ if (null == BeanUtils.getPropertyDescriptor(C.class, "number").getWriteMethod()) {
+ throw new Error("no write method");
+ }
+ }
+
+ public interface I {
+ void setNumber(Object number);
+ Number getNumber();
+ }
+
+ public class C implements I {
+ public void setNumber(Object value) {
+ }
+ public void setNumber(Long value) {
+ }
+ public Long getNumber() {
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test6963811.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6963811
+ * @summary Tests deadlock in Introspector
+ * @author Sergey Malenkov
+ */
+
+import java.beans.Introspector;
+import java.beans.SimpleBeanInfo;
+
+public class Test6963811 implements Runnable {
+ private final long time;
+ private final boolean sync;
+
+ public Test6963811(long time, boolean sync) {
+ this.time = time;
+ this.sync = sync;
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(this.time); // increase the chance of the deadlock
+ Introspector.getBeanInfo(
+ this.sync ? Super.class : Sub.class,
+ this.sync ? null : Object.class);
+ }
+ catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Thread[] threads = new Thread[2];
+ for (int i = 0; i < threads.length; i++) {
+ threads[i] = new Thread(new Test6963811(0L, i > 0));
+ threads[i].start();
+ Thread.sleep(500L); // increase the chance of the deadlock
+ }
+ for (Thread thread : threads) {
+ thread.join();
+ }
+ }
+
+ public static class Super {
+ }
+
+ public static class Sub extends Super {
+ }
+
+ public static class SubBeanInfo extends SimpleBeanInfo {
+ public SubBeanInfo() {
+ new Test6963811(1000L, true).run();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/PropertyEditor/Test6963811.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6963811
+ * @summary Tests deadlock in PropertyEditorManager
+ * @author Sergey Malenkov
+ */
+
+import java.beans.PropertyEditorManager;
+import sun.beans.editors.StringEditor;
+
+public class Test6963811 implements Runnable {
+ private final long time;
+ private final boolean sync;
+
+ public Test6963811(long time, boolean sync) {
+ this.time = time;
+ this.sync = sync;
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(this.time); // increase the chance of the deadlock
+ if (this.sync) {
+ synchronized (Test6963811.class) {
+ PropertyEditorManager.findEditor(Super.class);
+ }
+ }
+ else {
+ PropertyEditorManager.findEditor(Sub.class);
+ }
+ }
+ catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Thread[] threads = new Thread[2];
+ for (int i = 0; i < threads.length; i++) {
+ threads[i] = new Thread(new Test6963811(0L, i > 0));
+ threads[i].start();
+ Thread.sleep(500L); // increase the chance of the deadlock
+ }
+ for (Thread thread : threads) {
+ thread.join();
+ }
+ }
+
+ public static class Super {
+ }
+
+ public static class Sub extends Super {
+ }
+
+ public static class SubEditor extends StringEditor {
+ public SubEditor() {
+ new Test6963811(1000L, true).run();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/Test6963811.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6963811
+ * @summary Tests deadlock in Encoder
+ * @author Sergey Malenkov
+ */
+
+import java.beans.Encoder;
+import java.beans.DefaultPersistenceDelegate;
+
+public class Test6963811 implements Runnable {
+ private static final Encoder ENCODER = new Encoder();
+ private final long time;
+ private final boolean sync;
+
+ public Test6963811(long time, boolean sync) {
+ this.time = time;
+ this.sync = sync;
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(this.time); // increase the chance of the deadlock
+ if (this.sync) {
+ synchronized (Test6963811.class) {
+ ENCODER.getPersistenceDelegate(Super.class);
+ }
+ }
+ else {
+ ENCODER.getPersistenceDelegate(Sub.class);
+ }
+ }
+ catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Thread[] threads = new Thread[2];
+ for (int i = 0; i < threads.length; i++) {
+ threads[i] = new Thread(new Test6963811(0L, i > 0));
+ threads[i].start();
+ Thread.sleep(500L); // increase the chance of the deadlock
+ }
+ for (Thread thread : threads) {
+ thread.join();
+ }
+ }
+
+ public static class Super {
+ }
+
+ public static class Sub extends Super {
+ }
+
+ public static class SubPersistenceDelegate extends DefaultPersistenceDelegate {
+ public SubPersistenceDelegate() {
+ new Test6963811(1000L, true).run();
+ }
+ }
+}
--- a/jdk/test/java/lang/String/Supplementary.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/lang/String/Supplementary.java Wed Jul 05 17:18:01 2017 +0200
@@ -62,7 +62,7 @@
0 1 2345 678 9 012 345678 9 01 2 */
"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
- // includes an undefined supprementary characters in Unicode 4.0.0
+ // includes an undefined supplementary character in Unicode 4.0.0
/* 1 11 1 1111 1
0 1 2345 6 789 0 12 3 4567 8 */
"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -168,7 +168,7 @@
* string in input[m].
*
* The meaning of each element in golden3[][n]
- * golden3[][0]: characater which is searched.
+ * golden3[][0]: character which is searched.
* golden3[][2]: the golden data for indexOf(int ch)
* From golden3[][2] to golden3[][n-1]:
* the golden data for indexOf(int ch, int fromIndex)
@@ -201,17 +201,17 @@
/*
* Normal case
*/
- testIndexOf(First, s, golden3[i][0], golden3[i][2]);
+ testIndexOf(s, golden3[i][0], golden3[i][2]);
/*
* Abnormal case - char which isn't included in the string.
*/
- testIndexOf(First, s, 'Z', -1);
- testIndexOf(First, s, 0xDB98, -1);
- testIndexOf(First, s, 0xDE76, -1);
- testIndexOf(First, s, 0x12345, -1);
- testIndexOf(First, s, -1, -1);
- testIndexOf(First, s, 0x110000, -1);
+ testIndexOf(s, 'Z', -1);
+ testIndexOf(s, 0xDB98, -1);
+ testIndexOf(s, 0xDE76, -1);
+ testIndexOf(s, 0x12345, -1);
+ testIndexOf(s, -1, -1);
+ testIndexOf(s, 0x110000, -1);
}
}
@@ -229,7 +229,7 @@
*/
int fromIndex = 0;
for (int j = 2; j < golden3[i].length; j++) {
- fromIndex = testIndexOf(First, s, fromIndex, ch,
+ fromIndex = testIndexOf(s, fromIndex, ch,
golden3[i][j]) + 1;
}
@@ -237,19 +237,19 @@
* Abnormal case1 - char is included in the string but fromIndex
* is incorrect.
*/
- testIndexOf(First, s, -1, ch, golden3[i][2]);
- testIndexOf(First, s, s.length(), ch,
+ testIndexOf(s, -1, ch, golden3[i][2]);
+ testIndexOf(s, s.length(), ch,
golden3[i][golden3[i].length-1]);
/*
* Abnormal case2 - char which isn't included in the string.
*/
- testIndexOf(First, s, 0, 'Z', -1);
- testIndexOf(First, s, 0, 0xDB98, -1);
- testIndexOf(First, s, 0, 0xDE76, -1);
- testIndexOf(First, s, 0, 0x12345, -1);
- testIndexOf(First, s, 0, -1, -1);
- testIndexOf(First, s, 0, 0x110000, -1);
+ testIndexOf(s, 0, 'Z', -1);
+ testIndexOf(s, 0, 0xDB98, -1);
+ testIndexOf(s, 0, 0xDE76, -1);
+ testIndexOf(s, 0, 0x12345, -1);
+ testIndexOf(s, 0, -1, -1);
+ testIndexOf(s, 0, 0x110000, -1);
}
}
@@ -264,18 +264,18 @@
/*
* Normal case
*/
- testIndexOf(Last, s, golden3[i][0],
+ testLastIndexOf(s, golden3[i][0],
golden3[i][golden3[i].length-2]);
/*
* Abnormal case - char which isn't included in the string.
*/
- testIndexOf(Last, s, 'Z', -1);
- testIndexOf(Last, s, 0xDB98, -1);
- testIndexOf(Last, s, 0xDE76, -1);
- testIndexOf(Last, s, 0x12345, -1);
- testIndexOf(Last, s, -1, -1);
- testIndexOf(Last, s, 0x110000, -1);
+ testLastIndexOf(s, 'Z', -1);
+ testLastIndexOf(s, 0xDB98, -1);
+ testLastIndexOf(s, 0xDE76, -1);
+ testLastIndexOf(s, 0x12345, -1);
+ testLastIndexOf(s, -1, -1);
+ testLastIndexOf(s, 0x110000, -1);
}
}
@@ -294,7 +294,7 @@
*/
int fromIndex = len - 1;
for (int j = golden3[i].length - 2; j > 0; j--) {
- fromIndex = testIndexOf(Last, s, fromIndex, ch,
+ fromIndex = testLastIndexOf(s, fromIndex, ch,
golden3[i][j]) - 1;
}
@@ -302,18 +302,18 @@
* Abnormal case1 - char is included in the string but fromIndex
* is incorrect.
*/
- testIndexOf(Last, s, -1, ch, golden3[i][1]);
- testIndexOf(Last, s, len, ch, golden3[i][golden3[i].length-2]);
+ testLastIndexOf(s, -1, ch, golden3[i][1]);
+ testLastIndexOf(s, len, ch, golden3[i][golden3[i].length-2]);
/*
* Abnormal case2 - char which isn't included in the string.
*/
- testIndexOf(Last, s, len, 'Z', -1);
- testIndexOf(Last, s, len, 0xDB98, -1);
- testIndexOf(Last, s, len, 0xDE76, -1);
- testIndexOf(Last, s, len, 0x12345, -1);
- testIndexOf(Last, s, len, -1, -1);
- testIndexOf(Last, s, len, 0x110000, -1);
+ testLastIndexOf(s, len, 'Z', -1);
+ testLastIndexOf(s, len, 0xDB98, -1);
+ testLastIndexOf(s, len, 0xDE76, -1);
+ testLastIndexOf(s, len, 0x12345, -1);
+ testLastIndexOf(s, len, -1, -1);
+ testLastIndexOf(s, len, 0x110000, -1);
}
}
@@ -471,7 +471,7 @@
result, expected);
result = str.offsetByCodePoints(j, -nCodePoints);
check(result != 0,
- "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+ "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
result, 0);
}
@@ -531,7 +531,7 @@
result, expected);
result = str.offsetByCodePoints(j, -nCodePoints);
check(result != 0,
- "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+ "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
result, 0);
}
}
@@ -539,7 +539,7 @@
static final boolean At = true, Before = false;
- static final boolean First = true, Last = false;
+ static final boolean FIRST = true, LAST = false;
static void testCodePoint(boolean isAt, String s, int index, int expected) {
int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);
@@ -563,22 +563,72 @@
+ s + "> should throw StringIndexOutOfBoundsPointerException.");
}
- static void testIndexOf(boolean isFirst, String s, int c, int expected) {
- int index = isFirst ? s.indexOf(c) : s.lastIndexOf(c);
+ static void testIndexOf(String s, int c, int expected) {
+ testIndexOf2(s, c, expected);
+ if (s.indexOf(c) != -1) {
+ testIndexOf2(s + (char) c, c, expected);
+ if (Character.isSupplementaryCodePoint(c)) {
+ char[] surrogates = Character.toChars(c);
+ testIndexOf2(s + new String(surrogates), c, expected);
+ testIndexOf2(s + surrogates[0], c, expected);
+ testIndexOf2(s + surrogates[1], c, expected);
+ testIndexOf2(new String(surrogates) + s, c, 0);
+ testIndexOf2(surrogates[0] + s, c, expected + 1);
+ testIndexOf2(surrogates[1] + s, c, expected + 1);
+ }
+ }
+ }
+
+ static void testIndexOf2(String s, int c, int expected) {
+ int index = s.indexOf(c);
check(index != expected,
- (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c)
- + ") for <" + s + ">", index, expected);
+ "indexOf(" + toHexString(c) + ") for <" + s + ">",
+ index, expected);
}
- static int testIndexOf(boolean isFirst, String s, int fromIndex, int c,
- int expected) {
- int index = isFirst ? s.indexOf(c, fromIndex) :
- s.lastIndexOf(c, fromIndex);
+ static void testLastIndexOf(String s, int c, int expected) {
+ testLastIndexOf2(s, c, expected);
+ if (s.lastIndexOf(c) != -1) {
+ testLastIndexOf2((char) c + s, c, expected + 1);
+ if (Character.isSupplementaryCodePoint(c)) {
+ char[] surrogates = Character.toChars(c);
+ testLastIndexOf2(s + new String(surrogates), c, s.length());
+ testLastIndexOf2(s + surrogates[0], c, expected);
+ testLastIndexOf2(s + surrogates[1], c, expected);
+ testLastIndexOf2(new String(surrogates) + s, c, expected + 2);
+ testLastIndexOf2(surrogates[0] + s, c, expected + 1);
+ testLastIndexOf2(surrogates[1] + s, c, expected + 1);
+ }
+ }
+ }
+
+ static void testLastIndexOf2(String s, int c, int expected) {
+ int index = s.lastIndexOf(c);
check(index != expected,
- (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c) + ", "
- + fromIndex + ") for <" + s + ">", index, expected);
+ "lastIndexOf(" + toHexString(c) + ") for <" + s + ">",
+ index, expected);
+ }
+
+ static int testIndexOf(String s, int fromIndex, int c, int expected) {
+ int index = s.indexOf(c, fromIndex);
+
+ check(index != expected,
+ "indexOf(" + toHexString(c) + ", "
+ + fromIndex + ") for <" + s + ">",
+ index, expected);
+
+ return index;
+ }
+
+ static int testLastIndexOf(String s, int fromIndex, int c, int expected) {
+ int index = s.lastIndexOf(c, fromIndex);
+
+ check(index != expected,
+ "lastIndexOf(" + toHexString(c) + ", "
+ + fromIndex + ") for <" + s + ">",
+ index, expected);
return index;
}
--- a/jdk/test/java/lang/StringBuffer/Supplementary.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/lang/StringBuffer/Supplementary.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,7 +24,7 @@
/*
*
* @test
- * @bug 4533872 4915683 4985217 5017280
+ * @bug 4533872 4915683 4985217 5017280 6937112
* @summary Unit tests for supplementary character support (JSR-204)
*/
@@ -57,7 +57,7 @@
0 1 2345 678 9 012 345678 9 01 2 */
"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
- // includes an undefined supprementary characters in Unicode 4.0.0
+ // includes an undefined supplementary character in Unicode 4.0.0
/* 1 11 1 1111 1
0 1 2345 6 789 0 12 3 4567 8 */
"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -151,7 +151,7 @@
"\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",
"\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",
- // includes an undefined supprementary characters in Unicode 4.0.0
+ // includes an undefined supplementary character in Unicode 4.0.0
"\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",
};
--- a/jdk/test/java/lang/StringBuilder/Supplementary.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/lang/StringBuilder/Supplementary.java Wed Jul 05 17:18:01 2017 +0200
@@ -57,7 +57,7 @@
0 1 2345 678 9 012 345678 9 01 2 */
"\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
- // includes an undefined supprementary characters in Unicode 4.0.0
+ // includes an undefined supplementary character in Unicode 4.0.0
/* 1 11 1 1111 1
0 1 2345 6 789 0 12 3 4567 8 */
"\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -151,7 +151,7 @@
"\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",
"\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",
- // includes an undefined supprementary characters in Unicode 4.0.0
+ // includes an undefined supplementary character in Unicode 4.0.0
"\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Throwable/SuppressedExceptions.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 6911258 6962571
+ * @summary Basic tests of suppressed exceptions
+ * @author Joseph D. Darcy
+ */
+
+public class SuppressedExceptions {
+ private static String message = "Bad suppressed exception information";
+
+ public static void main(String... args) throws Exception {
+ basicSupressionTest();
+ serializationTest();
+ selfReference();
+ }
+
+ private static void basicSupressionTest() {
+ Throwable throwable = new Throwable();
+ RuntimeException suppressed = new RuntimeException("A suppressed exception.");
+ AssertionError repressed = new AssertionError("A repressed error.");
+
+ Throwable[] t0 = throwable.getSuppressedExceptions();
+ if (t0.length != 0) {
+ throw new RuntimeException(message);
+ }
+ throwable.printStackTrace();
+
+ throwable.addSuppressedException(suppressed);
+ Throwable[] t1 = throwable.getSuppressedExceptions();
+ if (t1.length != 1 ||
+ t1[0] != suppressed) {throw new RuntimeException(message);
+ }
+ throwable.printStackTrace();
+
+ throwable.addSuppressedException(repressed);
+ Throwable[] t2 = throwable.getSuppressedExceptions();
+ if (t2.length != 2 ||
+ t2[0] != suppressed ||
+ t2[1] != repressed) {
+ throw new RuntimeException(message);
+ }
+ throwable.printStackTrace();
+ }
+
+ private static void serializationTest() throws Exception {
+ /*
+ * Bytes of the serial form of
+ *
+ * (new Throwable())setStackTrace(new StackTraceElement[0])
+ *
+ * from JDK 6; suppressedException field will be missing and
+ * thus default to null upon deserialization.
+ */
+ byte[] bytes = {
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61,
+ (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39,
+ (byte)0x77, (byte)0xb8, (byte)0xcb, (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00,
+ (byte)0x05, (byte)0x63, (byte)0x61, (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00,
+ (byte)0x15, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+ (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f,
+ (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00,
+ (byte)0x0d, (byte)0x64, (byte)0x65, (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d,
+ (byte)0x65, (byte)0x73, (byte)0x73, (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00,
+ (byte)0x12, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+ (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69,
+ (byte)0x6e, (byte)0x67, (byte)0x3b, (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74,
+ (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65,
+ (byte)0x74, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76,
+ (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53,
+ (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63,
+ (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74,
+ (byte)0x3b, (byte)0x78, (byte)0x70, (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04,
+ (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a,
+ (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+ (byte)0x2e, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72,
+ (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65,
+ (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c,
+ (byte)0xfd, (byte)0x22, (byte)0x39, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0xac, (byte)0xed, (byte)0x00,
+ (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x6a, (byte)0x61, (byte)0x76,
+ (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x54,
+ (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65,
+ (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39, (byte)0x77, (byte)0xb8, (byte)0xcb,
+ (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00, (byte)0x05, (byte)0x63, (byte)0x61,
+ (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x15, (byte)0x4c, (byte)0x6a,
+ (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+ (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62,
+ (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00, (byte)0x0d, (byte)0x64, (byte)0x65,
+ (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d, (byte)0x65, (byte)0x73, (byte)0x73,
+ (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x12, (byte)0x4c, (byte)0x6a,
+ (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x6e, (byte)0x67, (byte)0x3b,
+ (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69,
+ (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b,
+ (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x1e,
+ (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+ (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63,
+ (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c,
+ (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x78, (byte)0x70,
+ (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04, (byte)0x70, (byte)0x75, (byte)0x72,
+ (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+ (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53, (byte)0x74,
+ (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65,
+ (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b,
+ (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c, (byte)0xfd, (byte)0x22, (byte)0x39,
+ (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ };
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+
+ Object o = ois.readObject();
+ Throwable throwable = (Throwable) o;
+
+ System.err.println("TESTING SERIALIZED EXCEPTION");
+
+ Throwable[] t0 = throwable.getSuppressedExceptions();
+ if (t0.length != 0) { // Will fail if t0 is null.
+ throw new RuntimeException(message);
+ }
+ throwable.printStackTrace();
+ }
+
+ private static void selfReference() {
+ Throwable throwable1 = new RuntimeException();
+ Throwable throwable2 = new AssertionError();
+ throwable1.initCause(throwable2);
+ throwable2.initCause(throwable1);
+
+ throwable1.printStackTrace();
+
+
+ throwable1.addSuppressedException(throwable1);
+ throwable1.addSuppressedException(throwable2);
+
+ throwable1.printStackTrace();
+ }
+}
--- a/jdk/test/java/net/Authenticator/B4769350.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/net/Authenticator/B4769350.java Wed Jul 05 17:18:01 2017 +0200
@@ -54,6 +54,7 @@
boolean allowerror;
Client (String authority, String path, boolean allowerror) {
+ super("Thread-" + path);
this.authority = authority;
this.path = path;
this.allowerror = allowerror;
@@ -72,7 +73,8 @@
error = true;
} catch (IOException e) {
if (!allowerror) {
- System.out.println (e);
+ System.out.println (Thread.currentThread().getName() + " " + e);
+ e.printStackTrace();
error = true;
}
}
@@ -94,6 +96,7 @@
}
void okReply (HttpTransaction req) throws IOException {
+ req.addResponseHeader ("Connection", "close");
req.setResponseEntityBody ("Hello .");
req.sendResponse (200, "Ok");
req.orderlyClose();
--- a/jdk/test/java/net/BindException/Test.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/net/BindException/Test.java Wed Jul 05 17:18:01 2017 +0200
@@ -180,7 +180,7 @@
while (addrs.hasMoreElements()) {
InetAddress ia = (InetAddress)addrs.nextElement();
- if (ia.isLoopbackAddress()) {
+ if (ia.isLoopbackAddress() || ia.isAnyLocalAddress()) {
continue;
}
--- a/jdk/test/java/net/Inet6Address/B6214234.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/net/Inet6Address/B6214234.java Wed Jul 05 17:18:01 2017 +0200
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6214234
+ * @bug 6214234 6967937
* @summary IPv6 scope_id for local addresses not set in Solaris 10
*/
@@ -51,6 +51,7 @@
return;
}
if (addr.getScopeId() == 0) {
+ System.out.println("addr: "+ addr);
throw new RuntimeException ("Non zero scope_id expected");
}
}
--- a/jdk/test/java/net/ipv6tests/Tests.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/net/ipv6tests/Tests.java Wed Jul 05 17:18:01 2017 +0200
@@ -248,7 +248,8 @@
}
while (addrs.hasMoreElements()) {
InetAddress addr = (InetAddress) addrs.nextElement();
- if (filter.isInstance (addr) && !addr.isLoopbackAddress()) {
+ if (filter.isInstance (addr) && !addr.isLoopbackAddress()
+ && !addr.isAnyLocalAddress()) {
if (Arrays.equals (addr.getAddress(), fe80_loopback)) {
continue;
}
--- a/jdk/test/java/nio/BufferPoolMXBean/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/BufferPoolMXBean/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 6606598
* @summary Unit test for java.nio.BufferPoolMXBean
+ * @run main/othervm Basic
*/
import java.nio.ByteBuffer;
--- a/jdk/test/java/nio/MappedByteBuffer/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4462336
* @summary Simple MappedByteBuffer tests
+ * @run main/othervm Basic
*/
import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/Force.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Force.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4625907
* @summary Testing force()
+ * @run main/othervm Force
*/
import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4802340
* @summary Testing force(), load() isLoaded() of zero len MBB
+ * @run main/othervm ZeroMap
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Wed Jul 05 17:18:01 2017 +0200
@@ -29,6 +29,7 @@
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
+import java.util.*;
import java.util.concurrent.*;
import java.io.IOException;
@@ -44,8 +45,12 @@
final AsynchronousServerSocketChannel listener =
AsynchronousServerSocketChannel.open()
.bind(new InetSocketAddress(0));
+ final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>();
listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
public void completed(AsynchronousSocketChannel ch, Void att) {
+ synchronized (accepted) {
+ accepted.add(ch);
+ }
listener.accept((Void)null, this);
}
public void failed(Throwable exc, Void att) {
@@ -58,6 +63,14 @@
test(sa, true, false);
test(sa, false, true);
test(sa, true, true);
+
+ // clean-up
+ listener.close();
+ synchronized (accepted) {
+ for (AsynchronousSocketChannel ch: accepted) {
+ ch.close();
+ }
+ }
}
static void test(SocketAddress sa,
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Wed Jul 05 17:18:01 2017 +0200
@@ -32,6 +32,7 @@
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
+import java.io.IOException;
/**
* Tests that the completion handler is invoked by a thread with
@@ -81,14 +82,18 @@
listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
public void completed(final AsynchronousSocketChannel ch, Void att) {
listener.accept((Void)null, this);
-
final ByteBuffer buf = ByteBuffer.allocate(100);
- ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
- public void completed(Integer bytesRead, Void att) {
- buf.clear();
- ch.read(buf, (Void)null, this);
+ ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+ public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
+ if (bytesRead < 0) {
+ try { ch.close(); } catch (IOException ignore) { }
+ } else {
+ buf.clear();
+ ch.read(buf, ch, this);
+ }
}
- public void failed(Throwable exc, Void att) {
+ public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+ try { ch.close(); } catch (IOException ignore) { }
}
});
}
@@ -100,7 +105,8 @@
// create 3-10 channels, each in its own group
final int groupCount = 3 + rand.nextInt(8);
- final AsynchronousSocketChannel[] channel = new AsynchronousSocketChannel[groupCount];
+ AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
+ final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount];
for (int i=0; i<groupCount; i++) {
ThreadFactory factory = createThreadFactory(i);
AsynchronousChannelGroup group;
@@ -111,17 +117,18 @@
ExecutorService pool = Executors.newCachedThreadPool(factory);
group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
}
+ groups[i] = group;
// create channel in group and connect it to the server
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
ch.connect(sa).get();
- channel[i] = ch;
+ channels[i] = ch;
}
// randomly write to each channel, ensuring that the completion handler
// is always invoked by a thread with the right identity.
final AtomicInteger writeCount = new AtomicInteger(100);
- channel[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
+ channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
public void completed(Integer bytesWritten, Integer groupId) {
if (bytesWritten != 1)
fail("Expected 1 byte to be written");
@@ -129,7 +136,7 @@
fail("Handler invoked by thread with the wrong identity");
if (writeCount.decrementAndGet() > 0) {
int id = rand.nextInt(groupCount);
- channel[id].write(getBuffer(), id, this);
+ channels[id].write(getBuffer(), id, this);
} else {
done.countDown();
}
@@ -139,8 +146,16 @@
}
});
- // wait until
+ // wait until done
done.await();
+
+ // clean-up
+ for (AsynchronousSocketChannel ch: channels)
+ ch.close();
+ for (AsynchronousChannelGroup group: groups)
+ group.shutdownNow();
+ listener.close();
+
if (failed.get())
throw new RuntimeException("Test failed - see log for details");
}
--- a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -371,17 +371,22 @@
static void doMulticastTests() throws Exception {
final byte[] msg = "hello".getBytes();
+ InetAddress lh = InetAddress.getLocalHost();
+ NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
+ if (interf.isLoopback() || !interf.supportsMulticast()) {
+ System.out.println("Multicasting not tested");
+ return;
+ }
+
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
.open(StandardProtocolFamily.INET, null)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(0));
- InetAddress lh = InetAddress.getLocalHost();
int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
// join group
InetAddress group = InetAddress.getByName("225.4.5.6");
- NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
MembershipKey key = ch.join(group, interf);
// check key
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -45,16 +45,18 @@
File blah = File.createTempFile("blah", null);
blah.deleteOnExit();
- final AsynchronousFileChannel ch = AsynchronousFileChannel
+ AsynchronousFileChannel ch = AsynchronousFileChannel
.open(blah.toPath(), READ, WRITE);
+ try {
+ // run tests
+ testUsingCompletionHandlers(ch);
+ testUsingWaitOnResult(ch);
+ testInterruptHandlerThread(ch);
+ } finally {
+ ch.close();
+ }
- // run tests
- testUsingCompletionHandlers(ch);
- testUsingWaitOnResult(ch);
- testInterruptHandlerThread(ch);
-
- // close channel and invoke test that expects channel to be closed
- ch.close();
+ // run test that expects channel to be closed
testClosedChannel(ch);
// these tests open the file themselves
@@ -63,6 +65,9 @@
testAsynchronousClose(blah.toPath());
testCancel(blah.toPath());
testTruncate(blah.toPath());
+
+ // eagerly clean-up
+ blah.delete();
}
/*
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Wed Jul 05 17:18:01 2017 +0200
@@ -53,13 +53,17 @@
LockSlaveMirror slave = startLockSlave();
try {
- // create temporary file
+ // create temporary file
File blah = File.createTempFile("blah", null);
blah.deleteOnExit();
+ // run tests
testLockProtocol(blah, slave);
testAsyncClose(blah, slave);
+ // eagerly clean-up
+ blah.delete();
+
} finally {
slave.shutdown();
}
@@ -150,7 +154,12 @@
String sep = FileSystems.getDefault().getSeparator();
String command = System.getProperty("java.home") +
- sep + "bin" + sep + "java Lock -lockslave " + port;
+ sep + "bin" + sep + "java";
+ String testClasses = System.getProperty("test.classes");
+ if (testClasses != null)
+ command += " -cp " + testClasses;
+ command += " Lock -lockslave " + port;
+
Process p = Runtime.getRuntime().exec(command);
IOHandler.handle(p.getInputStream());
IOHandler.handle(p.getErrorStream());
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Wed Jul 05 17:18:01 2017 +0200
@@ -135,6 +135,7 @@
latch.await();
// verify content of each file
+ boolean failed = false;
byte[] buf = new byte[8192];
for (int i=0; i<count ;i++) {
Writer writer = writers[i];
@@ -145,18 +146,35 @@
int nread = in.read(buf);
while (nread > 0) {
for (int j=0; j<nread; j++) {
- if (buf[j] != expected)
- throw new RuntimeException("Unexpected byte");
+ if (buf[j] != expected) {
+ System.err.println("Unexpected contents");
+ failed = true;
+ break;
+ }
expected++;
}
+ if (failed)
+ break;
size += nread;
nread = in.read(buf);
}
- if (size != writer.size())
- throw new RuntimeException("Unexpected size");
+ if (!failed && size != writer.size()) {
+ System.err.println("Unexpected size");
+ failed = true;
+ }
+ if (failed)
+ break;
} finally {
in.close();
}
}
+
+ // clean-up
+ for (int i=0; i<count; i++) {
+ writers[i].file().delete();
+ }
+
+ if (failed)
+ throw new RuntimeException("Test failed");
}
}
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -776,6 +776,7 @@
throw new RuntimeException("RuntimeException expected after timeout.");
ch.close();
+ server.close();
}
// returns ByteBuffer with random bytes
--- a/jdk/test/java/nio/channels/Channels/Basic2.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Basic2.java Wed Jul 05 17:18:01 2017 +0200
@@ -61,6 +61,9 @@
writerThread.join();
readerThread.join();
+ // shutdown listener
+ listener.close();
+
// check that reader received what we expected
if (reader.total() != writer.total())
throw new RuntimeException("Unexpected number of bytes read");
--- a/jdk/test/java/nio/channels/Channels/Write.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Write.java Wed Jul 05 17:18:01 2017 +0200
@@ -47,5 +47,6 @@
out.close();
fc.close();
fos.close();
+ testFile.delete();
}
}
--- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Wed Jul 05 17:18:01 2017 +0200
@@ -82,8 +82,6 @@
}
throw x;
}
- if (shouldTimeout)
- throw new Exception("Receive did not time out");
break;
}
--- a/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Wed Jul 05 17:18:01 2017 +0200
@@ -46,21 +46,25 @@
Thread serverThread = new Thread(server);
serverThread.start();
DatagramChannel dc = DatagramChannel.open();
- ByteBuffer bb = ByteBuffer.allocateDirect(12);
- bb.order(ByteOrder.BIG_ENDIAN);
- bb.putInt(1).putLong(1);
- bb.flip();
- InetAddress address = InetAddress.getLocalHost();
- InetSocketAddress isa = new InetSocketAddress(address, server.port());
- dc.connect(isa);
- dc.write(bb);
- bb.rewind();
- dc.write(bb);
- bb.rewind();
- dc.write(bb);
- Thread.sleep(2000);
- serverThread.interrupt();
- server.throwException();
+ try {
+ ByteBuffer bb = ByteBuffer.allocateDirect(12);
+ bb.order(ByteOrder.BIG_ENDIAN);
+ bb.putInt(1).putLong(1);
+ bb.flip();
+ InetAddress address = InetAddress.getLocalHost();
+ InetSocketAddress isa = new InetSocketAddress(address, server.port());
+ dc.connect(isa);
+ dc.write(bb);
+ bb.rewind();
+ dc.write(bb);
+ bb.rewind();
+ dc.write(bb);
+ Thread.sleep(2000);
+ serverThread.interrupt();
+ server.throwException();
+ } finally {
+ dc.close();
+ }
}
public static class Server implements Runnable {
@@ -118,6 +122,8 @@
}
} catch (Exception ex) {
e = ex;
+ } finally {
+ try { dc.close(); } catch (IOException ignore) { }
}
}
}
--- a/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java Wed Jul 05 17:18:01 2017 +0200
@@ -66,6 +66,10 @@
rb.clear();
}
+ dc1.close();
+ dc2.close();
+ dc3.close();
+
/*
* Check that sa[0] equals sa[1] (both from dc1)
* Check that sa[1] not equal to sa[2] (one from dc1, one from dc2)
--- a/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Wed Jul 05 17:18:01 2017 +0200
@@ -43,9 +43,9 @@
SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port);
dc = DatagramChannel.open().bind(new InetSocketAddress(0));
+ Selector sel = Selector.open();
try {
dc.configureBlocking(false);
- Selector sel = Selector.open();
dc.register(sel, SelectionKey.OP_READ);
/* Test 1: not connected so ICMP port unreachable should not be received */
@@ -81,6 +81,7 @@
}
} finally {
+ sel.close();
dc.close();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/Args.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Args.java Wed Jul 05 17:18:01 2017 +0200
@@ -97,6 +97,8 @@
(long)Integer.MAX_VALUE << 3);
}});
+ fc.close();
+ f.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Wed Jul 05 17:18:01 2017 +0200
@@ -38,6 +38,7 @@
test1(channel);
test2(channel);
channel.close();
+ file.delete();
}
static void test1(FileChannel channel) throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,7 @@
* @bug 4938372 6541641
* @summary Flushing dirty pages prior to unmap can cause Cleaner thread to
* abort VM if memory system has pages locked
+ * @run main/othervm ExpandingMap
*/
import java.io.File;
import java.io.RandomAccessFile;
--- a/jdk/test/java/nio/channels/FileChannel/Lock.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Lock.java Wed Jul 05 17:18:01 2017 +0200
@@ -55,6 +55,7 @@
test2(blah, true);
test2(blah, false);
test3(blah);
+ blah.delete();
}
private static void test2(File blah, boolean b) throws Exception {
@@ -90,7 +91,11 @@
// Exec the tamperer
String command = System.getProperty("java.home") +
- File.separator + "bin" + File.separator + "java Lock " + str + " " + blah;
+ File.separator + "bin" + File.separator + "java";
+ String testClasses = System.getProperty("test.classes");
+ if (testClasses != null)
+ command += " -cp " + testClasses;
+ command += " Lock " + str + " " + blah;
Process p = Runtime.getRuntime().exec(command);
BufferedReader in = new BufferedReader
--- a/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4463036
* @summary Check if file mapping extends beyond end of file
+ * @run main/othervm MapOverEnd
*/
import java.nio.*;
--- a/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4510489
* @summary Verify IOUtil.java reads to buffer limits
+ * @run main/othervm MapReadOnly
*/
import java.io.*;
import java.nio.*;
--- a/jdk/test/java/nio/channels/FileChannel/MapTest.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapTest.java Wed Jul 05 17:18:01 2017 +0200
@@ -23,6 +23,7 @@
/* @test
* @summary Test file mapping with FileChannel
+ * @run main/othervm MapTest
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Mode.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Mode.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
@bug 4462298
* @summary Test FileChannel maps with different accesses
+ * @run main/othervm Mode
*/
import java.nio.channels.*;
--- a/jdk/test/java/nio/channels/FileChannel/Position.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Position.java Wed Jul 05 17:18:01 2017 +0200
@@ -63,6 +63,7 @@
c.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/Pread.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pread.java Wed Jul 05 17:18:01 2017 +0200
@@ -65,6 +65,9 @@
throw new RuntimeException("Expected exception not thrown");
} catch(IllegalArgumentException e) {
// Correct result
+ } finally {
+ fc.close();
+ blah.delete();
}
}
@@ -73,13 +76,18 @@
File blah = File.createTempFile("blah2", null);
blah.deleteOnExit();
FileOutputStream fos = new FileOutputStream(blah);
- fos.write(new byte[128]);
- FileChannel fc = fos.getChannel();
try {
- fc.read(ByteBuffer.allocate(256),1);
- throw new RuntimeException("Expected exception not thrown");
- } catch(NonReadableChannelException e) {
- // Correct result
+ fos.write(new byte[128]);
+ FileChannel fc = fos.getChannel();
+ try {
+ fc.read(ByteBuffer.allocate(256),1);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch(NonReadableChannelException e) {
+ // Correct result
+ }
+ } finally {
+ fos.close();
+ blah.delete();
}
}
@@ -130,6 +138,7 @@
c.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/Pwrite.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pwrite.java Wed Jul 05 17:18:01 2017 +0200
@@ -62,6 +62,9 @@
throw new RuntimeException("Expected exception not thrown");
} catch(NonWritableChannelException e) {
// Correct result
+ } finally {
+ fc.close();
+ blah.delete();
}
}
@@ -123,6 +126,7 @@
}
c.close();
raf.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/Read.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Read.java Wed Jul 05 17:18:01 2017 +0200
@@ -80,6 +80,7 @@
c.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/ReadFull.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadFull.java Wed Jul 05 17:18:01 2017 +0200
@@ -54,5 +54,6 @@
fc.close();
fis.close();
+ blah.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java Wed Jul 05 17:18:01 2017 +0200
@@ -48,6 +48,7 @@
throw new Exception("Test failed");
fc.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Wed Jul 05 17:18:01 2017 +0200
@@ -39,8 +39,12 @@
public static void main(String[] args) throws IOException {
File blah = File.createTempFile("blah", null);
blah.deleteOnExit();
- for (int i=0; i<100; i++) {
- test(blah.toPath());
+ try {
+ for (int i=0; i<100; i++) {
+ test(blah.toPath());
+ }
+ } finally {
+ blah.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
@bug 4452020 4629048 4638365 4869859
* @summary Test FileChannel scattering reads
+ * @run main/othervm ScatteringRead
*/
import java.nio.channels.*;
--- a/jdk/test/java/nio/channels/FileChannel/Size.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Size.java Wed Jul 05 17:18:01 2017 +0200
@@ -24,6 +24,7 @@
/* @test
* @bug 4563125
* @summary Test size method of FileChannel
+ * @run main/othervm Size
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Transfer.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,7 +25,6 @@
* @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
* @summary Test FileChannel.transferFrom and transferTo
* @library ..
- * @run main/timeout=180 Transfer
*/
import java.io.*;
@@ -33,6 +32,8 @@
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.SelectorProvider;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.FileAlreadyExistsException;
import java.util.Random;
@@ -96,6 +97,9 @@
sourceChannel.close();
sinkChannel.close();
+
+ source.delete();
+ sink.delete();
}
private static void testReadableByteChannel(int size) throws Exception {
@@ -139,6 +143,8 @@
fc.close();
sink.close();
source.close();
+
+ f.delete();
}
public static void xferTest02() throws Exception {
@@ -173,6 +179,9 @@
fc2.close();
raf1.close();
raf2.close();
+
+ source.delete();
+ dest.delete();
}
public static void xferTest03() throws Exception {
@@ -207,6 +216,9 @@
fc2.close();
raf1.close();
raf2.close();
+
+ source.delete();
+ dest.delete();
}
// Test transferTo with large file
@@ -245,27 +257,36 @@
sourceChannel.close();
sinkChannel.close();
+ source.delete();
+ sink.delete();
}
// Test transferFrom with large file
public static void xferTest05() throws Exception {
- // Linux can't handle the really large file sizes for a
- // truncate or a positional write
- String osName = System.getProperty("os.name");
- if (osName.startsWith("Linux"))
- return;
-
// Create a source file & large sink file for the test
File source = File.createTempFile("blech", null);
source.deleteOnExit();
initTestFile(source, 100);
- File sink = File.createTempFile("sink", null);
+ // Create the sink file as a sparse file if possible
+ File sink = null;
+ FileChannel fc = null;
+ while (fc == null) {
+ sink = File.createTempFile("sink", null);
+ // re-create as a sparse file
+ sink.toPath().delete();
+ try {
+ fc = FileChannel.open(sink.toPath(),
+ StandardOpenOption.CREATE_NEW,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.SPARSE);
+ } catch (FileAlreadyExistsException ignore) {
+ // someone else got it
+ }
+ }
sink.deleteOnExit();
long testSize = ((long)Integer.MAX_VALUE) * 2;
- RandomAccessFile raf = new RandomAccessFile(sink, "rw");
- FileChannel fc = raf.getChannel();
try {
fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
testSize - 40);
@@ -275,24 +296,28 @@
return;
} finally {
fc.close();
- raf.close();
}
// Get new channels for the source and sink and attempt transfer
- FileInputStream fis = new FileInputStream(source);
- FileChannel sourceChannel = fis.getChannel();
-
- raf = new RandomAccessFile(sink, "rw");
- FileChannel sinkChannel = raf.getChannel();
+ FileChannel sourceChannel = new FileInputStream(source).getChannel();
+ try {
+ FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
+ try {
+ long bytesWritten = sinkChannel.transferFrom(sourceChannel,
+ testSize - 40, 10);
+ if (bytesWritten != 10) {
+ throw new RuntimeException("Transfer test 5 failed " +
+ bytesWritten);
+ }
+ } finally {
+ sinkChannel.close();
+ }
+ } finally {
+ sourceChannel.close();
+ }
- long bytesWritten = sinkChannel.transferFrom(sourceChannel,
- testSize - 40, 10);
- if (bytesWritten != 10) {
- throw new RuntimeException("Transfer test 5 failed " +
- bytesWritten);
- }
- sourceChannel.close();
- sinkChannel.close();
+ source.delete();
+ sink.delete();
}
static void checkFileData(File file, String expected) throws Exception {
@@ -338,6 +363,8 @@
checkFileData(source, data);
checkFileData(sink, data.substring(7,data.length()));
+
+ source.delete();
}
// Test transferTo to non-blocking socket channel
@@ -371,6 +398,7 @@
sink.close();
other.close();
ssc.close();
+ source.delete();
}
@@ -473,6 +501,7 @@
source.close();
ssc.close();
fc.close();
+ file.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java Wed Jul 05 17:18:01 2017 +0200
@@ -51,6 +51,8 @@
test1();
test2();
in.close();
+ file.delete();
+ outFile.delete();
}
static void test1() throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java Wed Jul 05 17:18:01 2017 +0200
@@ -43,6 +43,9 @@
throw new RuntimeException("Test failed");
} catch (NonWritableChannelException nwce) {
// Correct result
+ } finally {
+ channel.close();
+ blah.delete();
}
}
}
--- a/jdk/test/java/nio/channels/FileChannel/Transfers.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfers.java Wed Jul 05 17:18:01 2017 +0200
@@ -554,6 +554,10 @@
break;
}
+ sourceFile.delete();
+ targetFile.delete();
+ fn.delete();
+
if (failures > 0) {
out.println();
throw new RuntimeException("Some tests failed");
--- a/jdk/test/java/nio/channels/FileChannel/TryLock.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TryLock.java Wed Jul 05 17:18:01 2017 +0200
@@ -56,7 +56,6 @@
public static void test1(boolean shared, boolean trylock) throws Exception {
File testFile = File.createTempFile("test1", null);
- testFile.deleteOnExit();
FileInputStream fis = new FileInputStream(testFile);
FileChannel fc = fis.getChannel();
FileLock fl = null;
@@ -73,12 +72,13 @@
} finally {
if (fl != null)
fl.release();
+ fc.close();
+ testFile.delete();
}
}
public static void test2(boolean shared, boolean trylock) throws Exception {
File testFile = File.createTempFile("test2", null);
- testFile.deleteOnExit();
FileOutputStream fis = new FileOutputStream(testFile);
FileChannel fc = fis.getChannel();
FileLock fl = null;
@@ -95,19 +95,25 @@
} finally {
if (fl != null)
fl.release();
+ fc.close();
+ testFile.delete();
}
}
public static void test3(boolean shared, boolean trylock) throws Exception {
File testFile = File.createTempFile("test3", null);
- testFile.deleteOnExit();
RandomAccessFile fis = new RandomAccessFile(testFile, "rw");
FileChannel fc = fis.getChannel();
- FileLock fl = null;
- if (trylock)
- fl = fc.tryLock(0, fc.size(), shared);
- else
- fl = fc.lock(0, fc.size(), shared);
- fl.release();
+ try {
+ FileLock fl = null;
+ if (trylock)
+ fl = fc.tryLock(0, fc.size(), shared);
+ else
+ fl = fc.lock(0, fc.size(), shared);
+ fl.release();
+ } finally {
+ fc.close();
+ testFile.delete();
+ }
}
}
--- a/jdk/test/java/nio/channels/FileChannel/Write.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Write.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,7 @@
* @test
* @bug 4475533 4698138 4638365 4796221
* @summary Test FileChannel write
+ * @run main/othervm Write
*/
import java.nio.channels.*;
@@ -46,23 +47,25 @@
// Test to see that offset > length does not throw exception
static void test1() throws Exception {
- File testFile = File.createTempFile("test1", null);
- testFile.deleteOnExit();
-
ByteBuffer[] dsts = new ByteBuffer[4];
for (int i=0; i<4; i++)
dsts[i] = ByteBuffer.allocateDirect(10);
- FileOutputStream fos = new FileOutputStream(testFile);
- FileChannel fc = fos.getChannel();
- fc.write(dsts, 2, 1);
- fos.close();
+ File testFile = File.createTempFile("test1", null);
+ try {
+ FileOutputStream fos = new FileOutputStream(testFile);
+ FileChannel fc = fos.getChannel();
+ fc.write(dsts, 2, 1);
+ fos.close();
+ } finally {
+ testFile.delete();
+ }
}
// Test to see that the appropriate buffers are updated
static void test2() throws Exception {
File testFile = File.createTempFile("test2", null);
- testFile.deleteOnExit();
+ testFile.delete();
ByteBuffer[] srcs = new ByteBuffer[4];
for (int i=0; i<4; i++)
srcs[i] = ByteBuffer.allocateDirect(10);
@@ -74,25 +77,34 @@
FileOutputStream fos = new FileOutputStream(testFile);
FileChannel fc = fos.getChannel();
- fc.write(srcs, 1, 2);
- fos.close();
+ try {
+ fc.write(srcs, 1, 2);
+ } finally {
+ fc.close();
+ }
FileInputStream fis = new FileInputStream(testFile);
fc = fis.getChannel();
- ByteBuffer bb = ByteBuffer.allocateDirect(10);
- fc.read(bb);
- bb.flip();
- if (bb.get() != 2)
- throw new RuntimeException("Write failure");
- if (bb.get() != 3)
- throw new RuntimeException("Write failure");
try {
- bb.get();
- throw new RuntimeException("Write failure");
- } catch (BufferUnderflowException bufe) {
- // correct result
+ ByteBuffer bb = ByteBuffer.allocateDirect(10);
+ fc.read(bb);
+ bb.flip();
+ if (bb.get() != 2)
+ throw new RuntimeException("Write failure");
+ if (bb.get() != 3)
+ throw new RuntimeException("Write failure");
+ try {
+ bb.get();
+ throw new RuntimeException("Write failure");
+ } catch (BufferUnderflowException bufe) {
+ // correct result
+ }
+ } finally {
+ fc.close();
}
- fis.close();
+
+ // eagerly clean-up
+ testFile.delete();
}
// Test write to a negative position (bug 4698138).
--- a/jdk/test/java/nio/channels/Pipe/NonBlocking.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/NonBlocking.java Wed Jul 05 17:18:01 2017 +0200
@@ -41,12 +41,17 @@
static void test1() throws Exception {
Pipe p = Pipe.open();
- p.sink().configureBlocking(false);
- if (p.sink().isBlocking())
- throw new Exception("Sink still blocking");
- p.source().configureBlocking(false);
- if (p.source().isBlocking())
- throw new Exception("Source still blocking");
+ try {
+ p.sink().configureBlocking(false);
+ if (p.sink().isBlocking())
+ throw new Exception("Sink still blocking");
+ p.source().configureBlocking(false);
+ if (p.source().isBlocking())
+ throw new Exception("Source still blocking");
+ } finally {
+ p.sink().close();
+ p.source().close();
+ }
}
}
--- a/jdk/test/java/nio/channels/Pipe/SelectPipe.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/SelectPipe.java Wed Jul 05 17:18:01 2017 +0200
@@ -78,10 +78,12 @@
totalRead += bytesRead;
} while(totalRead < 10);
+ sink.close();
+ source.close();
+ selector.close();
+
for(int i=0; i<10; i++)
if (outgoingdata.get(i) != incomingdata.get(i))
throw new Exception("Pipe failed");
- sink.close();
- source.close();
}
}
--- a/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Wed Jul 05 17:18:01 2017 +0200
@@ -58,6 +58,11 @@
};
t.join();
+
+ pipe.sink().close();
+ pipe.source().close();
+ selector.close();
+
int count = errorCount.get();
if (count > 0) {
throw new RuntimeException("Error count:" + count);
--- a/jdk/test/java/nio/channels/Selector/BasicAccept.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicAccept.java Wed Jul 05 17:18:01 2017 +0200
@@ -36,49 +36,60 @@
public class BasicAccept {
- public static int TEST_PORT = 40170;
-
- static void server() throws Exception {
+ static void server(ServerSocketChannel ssc) throws Exception {
Selector acceptSelector = Selector.open();
- ServerSocketChannel ssc = ServerSocketChannel.open();
- ssc.configureBlocking(false);
- InetAddress lh = InetAddress.getLocalHost();
- InetSocketAddress isa
- = new InetSocketAddress(lh, SelectorTest.TEST_PORT);
- ssc.socket().bind(isa);
- SelectionKey acceptKey
- = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
- for (;;) {
- if (acceptSelector.select() == 0)
- continue;
- Set readyKeys = acceptSelector.selectedKeys();
- Iterator i = readyKeys.iterator();
- while (i.hasNext()) {
- SelectionKey sk = (SelectionKey)i.next();
- i.remove();
- ServerSocketChannel nextReady
- = (ServerSocketChannel)sk.channel();
- SocketChannel sc = nextReady.accept();
- ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 });
- sc.write(bb);
+ try {
+ ssc.configureBlocking(false);
+ SelectionKey acceptKey
+ = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+ for (;;) {
+ int n = acceptSelector.select();
+ if (Thread.interrupted())
+ break;
+ if (n == 0)
+ continue;
+ Set<SelectionKey> readyKeys = acceptSelector.selectedKeys();
+ Iterator<SelectionKey> i = readyKeys.iterator();
+ while (i.hasNext()) {
+ SelectionKey sk = i.next();
+ i.remove();
+ ServerSocketChannel nextReady
+ = (ServerSocketChannel)sk.channel();
+ SocketChannel sc = nextReady.accept();
+ ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 });
+ sc.write(bb);
+ sc.close();
+ }
+ }
+ } finally {
+ acceptSelector.close();
+ }
+ }
+
+ private static class Server extends TestThread {
+ final ServerSocketChannel ssc;
+ Server() throws IOException {
+ super("Server", System.err);
+ this.ssc = ServerSocketChannel.open()
+ .bind(new InetSocketAddress(0));
+ }
+ int port() {
+ return ssc.socket().getLocalPort();
+ }
+ void go() throws Exception {
+ try {
+ server(ssc);
+ } finally {
+ ssc.close();
}
}
}
- private static class Server extends TestThread {
- Server() {
- super("Server", System.err);
- }
- void go() throws Exception {
- server();
- }
- }
-
- static void client() throws Exception {
+ static void client(int port) throws Exception {
// Get a connection from the server
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa
- = new InetSocketAddress(lh, SelectorTest.TEST_PORT);
+ = new InetSocketAddress(lh, port);
int connectFailures = 0;
boolean result = false;
SocketChannel sc = SocketChannel.open();
@@ -122,17 +133,17 @@
if (bb.get(0) != 42)
throw new RuntimeException("Read wrong byte from server");
System.err.println("Read from server");
+ sc.close();
}
public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- Server server = new Server();
- server.start();
- client();
- } else if (args[0].equals("client")) {
- client();
- } else if (args[0].equals("server")) {
- server();
+ Server server = new Server();
+ server.start();
+ try {
+ client(server.port());
+ } finally {
+ server.interrupt();
+ server.finish(2000);
}
}
--- a/jdk/test/java/nio/channels/Selector/BasicConnect.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicConnect.java Wed Jul 05 17:18:01 2017 +0200
@@ -83,10 +83,13 @@
ByteBuffer bb2 = ByteBuffer.allocateDirect(100);
int n = sc.read(bb2);
bb2.flip();
+
+ sc.close();
+ connectSelector.close();
+
if (!bb.equals(bb2))
throw new Exception("Echoed bytes incorrect: Sent "
+ bb + ", got " + bb2);
- sc.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/CheckLocking.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CheckLocking.java Wed Jul 05 17:18:01 2017 +0200
@@ -61,5 +61,7 @@
doSelect();
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
+ sc.close();
+ selector.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Wed Jul 05 17:18:01 2017 +0200
@@ -33,12 +33,16 @@
public static void main (String [] args) throws Exception {
DatagramChannel ch = DatagramChannel.open();
- ch.configureBlocking(false);
- Selector sel = Selector.open();
- SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE);
- sel.close();
- if (key.isValid())
- throw new Exception("Key valid after selector closed");
+ try {
+ ch.configureBlocking(false);
+ Selector sel = Selector.open();
+ SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE);
+ sel.close();
+ if (key.isValid())
+ throw new Exception("Key valid after selector closed");
+ } finally {
+ ch.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Wed Jul 05 17:18:01 2017 +0200
@@ -111,10 +111,14 @@
// select should block
int spinCount = 0;
+ boolean failed = false;
for (;;) {
int n = sel.select();
- if (n > 0)
- throw new RuntimeException("channel should not be selected");
+ if (n > 0) {
+ System.err.println("Channel should not be selected!!!");
+ failed = true;
+ break;
+ }
// wakeup
if (wakeupDone)
@@ -123,10 +127,19 @@
// wakeup for no reason - if it happens a few times then we have a
// problem
spinCount++;
- if (spinCount >= 3)
- throw new RuntimeException("Selector appears to be spinning");
+ if (spinCount >= 3) {
+ System.err.println("Selector appears to be spinning");
+ failed = true;
+ break;
+ }
}
+ sc1.close();
+ sel.close();
+
+ if (failed)
+ throw new RuntimeException("Test failed");
+
System.out.println("PASS");
}
--- a/jdk/test/java/nio/channels/Selector/Connect.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/Connect.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,7 +25,6 @@
* @bug 4511624
* @summary Test Making lots of Selectors
* @library ..
- * @run main/timeout=240 Connect
*/
import java.io.*;
@@ -38,7 +37,7 @@
public class Connect {
static int success = 0;
- static int LIMIT = 500;
+ static int LIMIT = 100;
public static void main(String[] args) throws Exception {
scaleTest();
@@ -51,29 +50,30 @@
for (int j=0; j<LIMIT; j++) {
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
- boolean result = sc.connect(isa);
- if (!result) {
+ boolean connected = sc.connect(isa);
+ if (!connected) {
Selector RSelector = SelectorProvider.provider().openSelector();
SelectionKey RKey = sc.register (RSelector, SelectionKey.OP_CONNECT);
- while (!result) {
+ while (!connected) {
int keysAdded = RSelector.select(100);
if (keysAdded > 0) {
- Set readyKeys = RSelector.selectedKeys();
- Iterator i = readyKeys.iterator();
+ Set<SelectionKey> readyKeys = RSelector.selectedKeys();
+ Iterator<SelectionKey> i = readyKeys.iterator();
while (i.hasNext()) {
- SelectionKey sk = (SelectionKey)i.next();
+ SelectionKey sk = i.next();
SocketChannel nextReady = (SocketChannel)sk.channel();
- result = nextReady.finishConnect();
+ connected = nextReady.finishConnect();
}
+ readyKeys.clear();
}
}
RSelector.close();
}
- read(sc);
+ readAndClose(sc);
}
}
- static void read(SocketChannel sc) throws Exception {
+ static void readAndClose(SocketChannel sc) throws Exception {
ByteBuffer bb = ByteBuffer.allocateDirect(100);
int n = 0;
while (n == 0) // Note this is not a rigorous check for done reading
--- a/jdk/test/java/nio/channels/Selector/ConnectWrite.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/ConnectWrite.java Wed Jul 05 17:18:01 2017 +0200
@@ -45,8 +45,8 @@
Selector selector = SelectorProvider.provider().openSelector();
InetAddress myAddress=InetAddress.getByName(TestUtil.HOST);
InetSocketAddress isa = new InetSocketAddress(myAddress, port);
+ SocketChannel sc = SocketChannel.open();
try {
- SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
boolean result = sc.connect(isa);
@@ -80,6 +80,7 @@
}
}
} finally {
+ sc.close();
selector.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java Wed Jul 05 17:18:01 2017 +0200
@@ -33,9 +33,15 @@
public class HelperSlowToDie {
private static final int CHANNELS_PER_THREAD = 1023;
+ private static final int TEST_ITERATIONS = 200;
private static volatile boolean done;
public static void main(String[] args) throws IOException {
+ if (!System.getProperty("os.name").startsWith("Windows")) {
+ System.out.println("Test skipped as it verifies a Windows specific bug");
+ return;
+ }
+
Selector sel = Selector.open();
// register channels
@@ -60,7 +66,7 @@
new Thread(busy).start();
// Loop changing the number of channels from 1023 to 1024 and back.
- for (int i=0; i<1000; i++) {
+ for (int i=0; i<TEST_ITERATIONS; i++) {
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_CONNECT);
@@ -71,5 +77,11 @@
// terminate busy threads
done = true;
+
+ // clean-up
+ for (int i=0; i<CHANNELS_PER_THREAD; i++) {
+ channels[i].close();
+ }
+ sel.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/KeysReady.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/KeysReady.java Wed Jul 05 17:18:01 2017 +0200
@@ -49,14 +49,18 @@
// Prepare a selector
Selector selector = SelectorProvider.provider().openSelector();
- SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
- int keysAdded = selector.select();
- if (keysAdded > 0) {
- keysAdded = selector.select(1000);
- if (keysAdded > 0)
- throw new Exception("Same key reported added twice");
+ try {
+ SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
+ int keysAdded = selector.select();
+ if (keysAdded > 0) {
+ keysAdded = selector.select(1000);
+ if (keysAdded > 0)
+ throw new Exception("Same key reported added twice");
+ }
+ } finally {
+ selector.close();
+ sc.close();
}
- sc.close();
}
public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/Selector/LotsOfChannels.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/LotsOfChannels.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,19 +35,11 @@
public class LotsOfChannels {
- private final static int PIPES_COUNT = 1900;
+ private final static int PIPES_COUNT = 256;
private final static int BUF_SIZE = 8192;
private final static int LOOPS = 10;
public static void main(String[] argv) throws Exception {
-
-
- String os = System.getProperty("os.name");
- if (!(os.equals("Windows NT")
- || os.equals("Windows 2000")
- || os.equals("Windows XP")))
- return;
-
Pipe[] pipes = new Pipe[PIPES_COUNT];
Pipe pipe = Pipe.open();
Pipe.SinkChannel sink = pipe.sink();
@@ -72,6 +64,13 @@
sel.selectedKeys().clear();
source.read(ByteBuffer.allocate(BUF_SIZE));
}
+
+ for (int i = 0; i < PIPES_COUNT; i++ ) {
+ pipes[i].sink().close();
+ pipes[i].source().close();
+ }
+ pipe.sink().close();
+ pipe.source().close();
sel.close();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/Selector/OutOfBand.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6213702
+ * @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be
+ * selected
+ */
+
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.io.IOException;
+
+public class OutOfBand {
+
+ public static void main(String[] args) throws Exception {
+ ServerSocketChannel ssc = null;
+ SocketChannel sc = null;
+ Selector sel = null;
+ Socket s = null;
+
+ try {
+ // establish loopback connection.
+ ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+ s = new Socket(InetAddress.getLocalHost(),
+ ssc.socket().getLocalPort());
+ sc = ssc.accept();
+
+ sel = Selector.open();
+ sc.configureBlocking(false);
+ sc.register(sel, SelectionKey.OP_READ);
+
+ // OOB data should be disabled by default
+ if (sc.socket().getOOBInline())
+ throw new RuntimeException("SO_OOBINLINE enabled");
+ test(s, false, 0, 0, sel);
+ test(s, false, 512, 0, sel);
+ test(s, false, 0, 512, sel);
+ test(s, false, 512, 512, sel);
+
+ // enable SO_OOBINLINE
+ sc.socket().setOOBInline(true);
+
+ // OOB data should be received
+ test(s, true, 0, 0, sel);
+ test(s, true, 512, 0, sel);
+ test(s, true, 0, 512, sel);
+ test(s, true, 512, 512, sel);
+
+ } finally {
+ if (sel != null) sel.close();
+ if (sc != null) sc.close();
+ if (ssc != null) ssc.close();
+ if (s != null) sc.close();
+ }
+ }
+
+ static void test(Socket s, boolean urgentExpected,
+ int bytesBefore, int bytesAfter,
+ Selector sel)
+ throws IOException
+ {
+ // send data
+ int bytesExpected = 0;
+ if (bytesBefore > 0) {
+ s.getOutputStream().write(new byte[bytesBefore]);
+ bytesExpected += bytesBefore;
+ }
+ s.sendUrgentData(0xff);
+ if (urgentExpected)
+ bytesExpected++;
+ if (bytesAfter > 0) {
+ s.getOutputStream().write(new byte[bytesAfter]);
+ bytesExpected += bytesAfter;
+ }
+
+ // receive data, checking for spurious wakeups and reads
+ int spuriousWakeups = 0;
+ int spuriousReads = 0;
+ int bytesRead = 0;
+ ByteBuffer bb = ByteBuffer.allocate(100);
+ for (;;) {
+ int n = sel.select(2000);
+ if (n == 0) {
+ if (bytesRead == bytesExpected) {
+ System.out.format("Selector wakeups %d\tSpurious reads %d%n",
+ spuriousWakeups, spuriousReads);
+ return;
+ }
+ if (++spuriousWakeups >= 3)
+ throw new RuntimeException("Selector appears to be spinning" +
+ " or data not received");
+ continue;
+ }
+ if (n > 1)
+ throw new RuntimeException("More than one key selected????");
+ SelectionKey key = sel.selectedKeys().iterator().next();
+ bb.clear();
+ n = ((SocketChannel)key.channel()).read(bb);
+ if (n == 0) {
+ if (++spuriousReads >=3)
+ throw new RuntimeException("Too many spurious reads");
+ } else {
+ bytesRead += n;
+ if (bytesRead > bytesExpected)
+ throw new RuntimeException("Received more than expected");
+ }
+ sel.selectedKeys().clear();
+ }
+ }
+}
--- a/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,6 +35,7 @@
public class RegAfterPreClose {
+ static final int TEST_ITERATIONS = 300;
static volatile boolean done;
/**
@@ -96,26 +97,21 @@
}
};
- // schedule test to run for 1 minute
- Executors.newScheduledThreadPool(1, factory).schedule(new Runnable() {
- public void run() {
- done = true;
- sel.wakeup();
- }}, 1, TimeUnit.MINUTES);
-
// create Executor that handles tasks that closes channels
// "asynchronously" - this creates the conditions to provoke the bug.
- Executor executor = Executors.newFixedThreadPool(2, factory);
+ ExecutorService executor = Executors.newFixedThreadPool(2, factory);
// submit task that connects to listener
executor.execute(new Connector(ssc.socket().getLocalPort()));
// loop accepting connections until done (or an IOException is thrown)
- while (!done) {
+ int remaining = TEST_ITERATIONS;
+ while (remaining > 0) {
sel.select();
if (key.isAcceptable()) {
SocketChannel sc = ssc.accept();
if (sc != null) {
+ remaining--;
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_READ);
executor.execute(new Closer(sc));
@@ -123,5 +119,8 @@
}
sel.selectedKeys().clear();
}
+ done = true;
+ sel.close();
+ executor.shutdown();
}
}
--- a/jdk/test/java/nio/channels/Selector/SelectAndCancel.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectAndCancel.java Wed Jul 05 17:18:01 2017 +0200
@@ -31,11 +31,7 @@
import java.net.*;
public class SelectAndCancel {
- static ServerSocketChannel ssc;
- static Selector selector;
static SelectionKey sk;
- static InetSocketAddress isa;
- public static int TEST_PORT = 40170;
/*
* CancelledKeyException is the failure symptom of 4729342
@@ -43,17 +39,17 @@
* seen immediately when the bug is present.
*/
public static void main(String[] args) throws Exception {
- InetAddress lh = InetAddress.getLocalHost();
- isa = new InetSocketAddress(lh, TEST_PORT);
- selector = Selector.open();
- ssc = ServerSocketChannel.open();
+ final Selector selector = Selector.open();
+ final ServerSocketChannel ssc =
+ ServerSocketChannel.open().bind(new InetSocketAddress(0));
+ final InetSocketAddress isa =
+ new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort());
// Create and start a selector in a separate thread.
new Thread(new Runnable() {
public void run() {
try {
ssc.configureBlocking(false);
- ssc.socket().bind(isa);
sk = ssc.register(selector, SelectionKey.OP_ACCEPT);
selector.select();
} catch (IOException e) {
--- a/jdk/test/java/nio/channels/Selector/SelectorLimit.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java Wed Jul 05 17:18:01 2017 +0200
@@ -26,6 +26,8 @@
* @summary Ensure that a Selector can return at least 100 selected keys
* @author Mark Reinhold
* @library ..
+ * @build SelectorLimit
+ * @run main/othervm SelectorLimit
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/Selector/SelectorTest.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorTest.java Wed Jul 05 17:18:01 2017 +0200
@@ -57,13 +57,13 @@
*/
public static void main(String[] args) throws Exception {
if (args.length == 0) {
- InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT);
- Server server = new Server(isa);
+ Server server = new Server(0);
server.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
+ InetSocketAddress isa
+ = new InetSocketAddress(InetAddress.getLocalHost(), server.port());
Client client = new Client(isa);
client.start();
if ((server.finish(FINISH_TIME) & client.finish(FINISH_TIME)) == 0)
@@ -74,9 +74,7 @@
if (args.length > 1)
TEST_PORT = Integer.parseInt(args[1]);
- InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT);
- Server server = new Server(isa);
+ Server server = new Server(TEST_PORT);
server.start();
if (server.finish(FINISH_TIME) == 0)
throw new Exception("Failure");
@@ -136,18 +134,22 @@
}
static class Server extends TestThread {
+ private final ServerSocketChannel ssc;
private List socketList = new ArrayList();
private ServerSocket ss;
private int connectionsAccepted = 0;
private Selector pollSelector;
private Selector acceptSelector;
- private InetSocketAddress isa;
private Set pkeys;
private Set pskeys;
- Server(InetSocketAddress isa) {
+ Server(int port) throws IOException {
super("Server", SelectorTest.log);
- this.isa = isa;
+ this.ssc = ServerSocketChannel.open().bind(new InetSocketAddress(port));
+ }
+
+ int port() {
+ return ssc.socket().getLocalPort();
}
public void go() throws Exception {
@@ -162,11 +164,7 @@
requestThread.start();
- ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
- ssc.socket().setReuseAddress(true);
- ssc.socket().bind(isa);
-
SelectionKey acceptKey = ssc.register(acceptSelector,
SelectionKey.OP_ACCEPT);
while(connectionsAccepted < SelectorTest.NUM_CLIENTS) {
--- a/jdk/test/java/nio/channels/Selector/WakeupNow.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupNow.java Wed Jul 05 17:18:01 2017 +0200
@@ -44,10 +44,15 @@
p.source().configureBlocking(false);
p.source().register(sel, SelectionKey.OP_READ);
sel.wakeup();
+ // ensure wakeup is consumed by selectNow
+ Thread.sleep(2000);
sel.selectNow();
long startTime = System.currentTimeMillis();
int n = sel.select(2000);
long endTime = System.currentTimeMillis();
+ p.source().close();
+ p.sink().close();
+ sel.close();
if (endTime - startTime < 1000)
throw new RuntimeException("test failed");
}
@@ -60,10 +65,13 @@
Pipe p = Pipe.open();
p.source().configureBlocking(false);
sel.wakeup();
+ // ensure wakeup is consumed by selectNow
+ Thread.sleep(2000);
sel.selectNow();
long startTime = System.currentTimeMillis();
int n = sel.select(2000);
long endTime = System.currentTimeMillis();
+ sel.close();
if (endTime - startTime < 1000)
throw new RuntimeException("test failed");
}
--- a/jdk/test/java/nio/channels/Selector/WakeupOverflow.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupOverflow.java Wed Jul 05 17:18:01 2017 +0200
@@ -31,8 +31,12 @@
public class WakeupOverflow {
public static void main( String[] args ) throws Exception {
Selector selector = Selector.open();
- for(int i=0; i<10000; i++) {
- selector.wakeup();
+ try {
+ for(int i=0; i<10000; i++) {
+ selector.wakeup();
+ }
+ } finally {
+ selector.close();
}
}
}
--- a/jdk/test/java/nio/channels/Selector/WakeupSpeed.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupSpeed.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,16 +35,19 @@
public static void main(String argv[]) throws Exception {
int waitTime = 4000;
Selector selector = Selector.open();
-
- selector.wakeup();
+ try {
+ selector.wakeup();
- long t1 = System.currentTimeMillis();
- selector.select(waitTime);
- long t2 = System.currentTimeMillis();
- long totalTime = t2 - t1;
+ long t1 = System.currentTimeMillis();
+ selector.select(waitTime);
+ long t2 = System.currentTimeMillis();
+ long totalTime = t2 - t1;
- if (totalTime > waitTime)
- throw new RuntimeException("Test failed");
+ if (totalTime > waitTime)
+ throw new RuntimeException("Test failed");
+ } finally {
+ selector.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary test the address returned in socket from accept
- */
-
-import java.io.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
-
-
-public class AcceptAddress {
-
- public static void main(String[] args) throws Exception {
- InetAddress local = InetAddress.getLocalHost();
- InetSocketAddress isa = new InetSocketAddress(local, 5555);
-
- ServerSocketChannel ssc;
- ssc = ServerSocketChannel.open();
- ssc.socket().bind(isa);
-
- SocketChannel sc;
- sc = SocketChannel.open();
- sc.connect(isa);
-
- SocketChannel sc2 = ssc.accept();
- System.err.println("Socket connected to " + sc2);
- }
-}
--- a/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Wed Jul 05 17:18:01 2017 +0200
@@ -78,8 +78,6 @@
throw x;
}
}
- if (shouldTimeout)
- throw new Exception("Connection did not time out");
}
out.println("connected: " + so);
out.println(" " + sc);
@@ -118,8 +116,6 @@
}
throw x;
}
- if (shouldTimeout)
- throw new Exception("Read did not time out");
}
static void testRead(String hn, int timeout, boolean shouldTimeout)
--- a/jdk/test/java/nio/channels/SocketChannel/Bind.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Bind.java Wed Jul 05 17:18:01 2017 +0200
@@ -31,13 +31,20 @@
public class Bind {
public static void main(String[] args) throws Exception {
+ SocketChannel sc1 = SocketChannel.open();
try {
- SocketChannel channel1 = SocketChannel.open();
- channel1.socket().bind(new InetSocketAddress(5555));
- SocketChannel channel2 = SocketChannel.open();
- channel2.socket().bind(new InetSocketAddress(5555));
+ sc1.bind(new InetSocketAddress(0));
+ int port = sc1.socket().getLocalPort();
+ SocketChannel sc2 = SocketChannel.open();
+ try {
+ sc2.bind(new InetSocketAddress(port));
+ } finally {
+ sc2.close();
+ }
} catch (BindException be) {
// Correct result
+ } finally {
+ sc1.close();
}
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/Close.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Close.java Wed Jul 05 17:18:01 2017 +0200
@@ -56,8 +56,12 @@
static void testChannelClose() throws IOException {
SelectionKey sk = open();
- sk.channel().close();
- check(sk);
+ try {
+ sk.channel().close();
+ check(sk);
+ } finally {
+ sk.selector().close();
+ }
}
public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Wed Jul 05 17:18:01 2017 +0200
@@ -55,5 +55,8 @@
System.out.println ("Will hang here...");
int nb = slave.read (ByteBuffer.allocate (1024));
//System.out.println("read nb=" + nb);
+
+ selector.close();
+ server.close();
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Wed Jul 05 17:18:01 2017 +0200
@@ -33,11 +33,12 @@
import java.net.*;
public class CloseTimeoutChannel {
- final static int PORT=6347;
public static void main(String args[]) throws Exception {
+ int port = -1;
try {
ServerSocketChannel listener=ServerSocketChannel.open();
- listener.socket().bind(new InetSocketAddress(PORT));
+ listener.socket().bind(new InetSocketAddress(0));
+ port = listener.socket().getLocalPort();
AcceptorThread thread=new AcceptorThread(listener);
thread.start();
} catch (IOException e) {
@@ -50,7 +51,7 @@
try {
System.out.println("Establishing connection");
Socket socket=SocketChannel.open(
- new InetSocketAddress("127.0.0.1", PORT)).socket();
+ new InetSocketAddress("127.0.0.1", port)).socket();
OutputStream out=socket.getOutputStream();
InputStream in=socket.getInputStream();
@@ -98,7 +99,8 @@
Thread.sleep(100);
} catch (InterruptedException e) { }
- System.out.println(INDENT+"Listening on port "+ PORT);
+ System.out.println(INDENT+"Listening on port "+
+ _listener.socket().getLocalPort());
ByteBuffer buf=ByteBuffer.allocate(5);
Socket client=_listener.accept().socket();;
System.out.println(INDENT+"Accepted client");
@@ -123,6 +125,8 @@
client.close();
} catch (IOException e) {
System.out.println(INDENT+"Error accepting!");
+ } finally {
+ try { _listener.close(); } catch (IOException ignore) { }
}
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Wed Jul 05 17:18:01 2017 +0200
@@ -48,27 +48,31 @@
sc.connect(isa);
Selector selector = SelectorProvider.provider().openSelector();
- SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
- int keysAdded = selector.select();
- if (keysAdded > 0) {
- boolean result = sc.finishConnect();
- if (result) {
- keysAdded = selector.select(5000);
- // 4750573: keysAdded should not be incremented when op is dropped
- // from a key already in the selected key set
- if (keysAdded > 0)
- throw new Exception("Test failed: 4750573 detected");
- Set sel = selector.selectedKeys();
- Iterator i = sel.iterator();
- SelectionKey sk = (SelectionKey)i.next();
- // 4737146: isConnectable should be false while connected
- if (sk.isConnectable())
- throw new Exception("Test failed: 4737146 detected");
+ try {
+ SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
+ int keysAdded = selector.select();
+ if (keysAdded > 0) {
+ boolean result = sc.finishConnect();
+ if (result) {
+ keysAdded = selector.select(5000);
+ // 4750573: keysAdded should not be incremented when op is dropped
+ // from a key already in the selected key set
+ if (keysAdded > 0)
+ throw new Exception("Test failed: 4750573 detected");
+ Set<SelectionKey> sel = selector.selectedKeys();
+ Iterator<SelectionKey> i = sel.iterator();
+ SelectionKey sk = i.next();
+ // 4737146: isConnectable should be false while connected
+ if (sk.isConnectable())
+ throw new Exception("Test failed: 4737146 detected");
+ }
+ } else {
+ throw new Exception("Select failed");
}
- } else {
- throw new Exception("Select failed");
+ } finally {
+ sc.close();
+ selector.close();
}
- sc.close();
}
public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Wed Jul 05 17:18:01 2017 +0200
@@ -38,25 +38,33 @@
static void test1() throws Exception {
InetAddress bogus = InetAddress.getByName("0.0.0.0");
- SocketChannel sc = SocketChannel.open();
InetSocketAddress saddr = new InetSocketAddress(
InetAddress.getByName(TestUtil.HOST), 23);
//Test1: connect only
- sc.connect(saddr);
- InetAddress isa = sc.socket().getLocalAddress();
- if (isa == null || isa.equals(bogus))
- throw new RuntimeException("test failed");
+ SocketChannel sc = SocketChannel.open();
+ try {
+ sc.connect(saddr);
+ InetAddress ia = sc.socket().getLocalAddress();
+ if (ia == null || ia.equals(bogus))
+ throw new RuntimeException("test failed");
+ } finally {
+ sc.close();
+ }
//Test2: bind and connect
sc = SocketChannel.open();
- sc.socket().bind(new InetSocketAddress(0));
- if (sc.socket().getLocalPort() == 0)
- throw new RuntimeException("test failed");
- sc.socket().connect(saddr);
- isa = sc.socket().getLocalAddress();
- if (isa == null || isa.isAnyLocalAddress())
- throw new RuntimeException("test failed");
+ try {
+ sc.socket().bind(new InetSocketAddress(0));
+ if (sc.socket().getLocalPort() == 0)
+ throw new RuntimeException("test failed");
+ sc.socket().connect(saddr);
+ InetAddress ia = sc.socket().getLocalAddress();
+ if (ia == null || ia.isAnyLocalAddress())
+ throw new RuntimeException("test failed");
+ } finally {
+ sc.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java Wed Jul 05 17:18:01 2017 +0200
@@ -105,7 +105,11 @@
// launch the child
String cmd = System.getProperty("java.home") + File.separator + "bin" +
- File.separator + "java SocketInheritance -child " + port;
+ File.separator + "java";
+ String testClasses = System.getProperty("test.classes");
+ if (testClasses != null)
+ cmd += " -cp " + testClasses;
+ cmd += " SocketInheritance -child " + port;
Process p = Runtime.getRuntime().exec(cmd);
--- a/jdk/test/java/nio/channels/SocketChannel/Trivial.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Trivial.java Wed Jul 05 17:18:01 2017 +0200
@@ -33,22 +33,27 @@
public static void main(String[] args) throws Exception {
SocketChannel sc = SocketChannel.open();
Selector sel = Selector.open();
- if (sc.keyFor(sel) != null)
- throw new Exception("keyFor != null");
- sc.configureBlocking(false);
- SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args);
- if (sc.keyFor(sel) != sk)
- throw new Exception("keyFor returned " + sc.keyFor(sel));
- if (sk.attachment() != args)
- throw new Exception("attachment() returned " + sk.attachment());
- Trivial t = new Trivial();
- sk.attach(t);
- if (sk.attachment() != t)
- throw new Exception("Wrong attachment");
- sk.isReadable();
- sk.isWritable();
- sk.isConnectable();
- sk.isAcceptable();
+ try {
+ if (sc.keyFor(sel) != null)
+ throw new Exception("keyFor != null");
+ sc.configureBlocking(false);
+ SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args);
+ if (sc.keyFor(sel) != sk)
+ throw new Exception("keyFor returned " + sc.keyFor(sel));
+ if (sk.attachment() != args)
+ throw new Exception("attachment() returned " + sk.attachment());
+ Trivial t = new Trivial();
+ sk.attach(t);
+ if (sk.attachment() != t)
+ throw new Exception("Wrong attachment");
+ sk.isReadable();
+ sk.isWritable();
+ sk.isConnectable();
+ sk.isAcceptable();
+ } finally {
+ sel.close();
+ sc.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Wed Jul 05 17:18:01 2017 +0200
@@ -57,39 +57,47 @@
System.out.println("\n-- SocketChannel --");
SocketChannel sc = SocketChannel.open();
+ try {
+ check("getLocalPort()", sc.socket().getLocalPort(), -1);
+ checkIsAnyLocalAddress("getLocalAddress()",
+ sc.socket().getLocalAddress());
+ check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null);
- check("getLocalPort()", sc.socket().getLocalPort(), -1);
- checkIsAnyLocalAddress("getLocalAddress()",
- sc.socket().getLocalAddress());
- check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null);
-
- check("getPort()", sc.socket().getPort(), 0);
- check("getInetAddress()", sc.socket().getInetAddress(), null);
- check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null);
-
+ check("getPort()", sc.socket().getPort(), 0);
+ check("getInetAddress()", sc.socket().getInetAddress(), null);
+ check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null);
+ } finally {
+ sc.close();
+ }
System.out.println("\n-- ServerSocketChannel --");
ServerSocketChannel ssc = ServerSocketChannel.open();
-
- check("getLocalPort()", ssc.socket().getLocalPort(), -1);
- check("getInetAddress()", ssc.socket().getInetAddress(), null);
- check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null);
+ try {
+ check("getLocalPort()", ssc.socket().getLocalPort(), -1);
+ check("getInetAddress()", ssc.socket().getInetAddress(), null);
+ check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null);
+ } finally {
+ ssc.close();
+ }
System.out.println("\n-- DatagramChannel --");
DatagramChannel dc = DatagramChannel.open();
-
- // not specified
- check("getLocalPort()", dc.socket().getLocalPort(), 0);
+ try {
+ // not specified
+ check("getLocalPort()", dc.socket().getLocalPort(), 0);
- checkIsAnyLocalAddress("getLocalAddress()",
- dc.socket().getLocalAddress());
- check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null);
+ checkIsAnyLocalAddress("getLocalAddress()",
+ dc.socket().getLocalAddress());
+ check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null);
- check("getPort()", dc.socket().getPort(), -1);
- check("getInetAddress()", dc.socket().getInetAddress(), null);
- check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null);
+ check("getPort()", dc.socket().getPort(), -1);
+ check("getInetAddress()", dc.socket().getInetAddress(), null);
+ check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null);
+ } finally {
+ dc.close();
+ }
if (failures > 0) {
throw new RuntimeException(failures + " sub-tests(s) failed.");
--- a/jdk/test/java/nio/channels/etc/Shadow.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/etc/Shadow.java Wed Jul 05 17:18:01 2017 +0200
@@ -35,7 +35,6 @@
public class Shadow {
- private static final int PORT = 2019;
static PrintStream log = System.err;
private static void dump(ServerSocket s) {
@@ -69,7 +68,7 @@
public static void main(String[] args) throws Exception {
boolean useChannels
= ((args.length == 0) || Boolean.valueOf(args[0]).booleanValue());
- int port = (args.length > 1 ? Integer.parseInt(args[1]) : PORT);
+ int port = (args.length > 1 ? Integer.parseInt(args[1]) : -1);
// open server socket
ServerSocket serverSocket;
@@ -86,7 +85,8 @@
}
// bind server socket to port
- SocketAddress bindAddr = new InetSocketAddress(port);
+ SocketAddress bindAddr =
+ new InetSocketAddress((port == -1) ? 0 : port);
serverSocket.bind(bindAddr);
log.println("bound ServerSocket: " + serverSocket);
--- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Wed Jul 05 17:18:01 2017 +0200
@@ -26,6 +26,8 @@
* @bug 4997227
* @summary Calling inheritedChannel() after FileDescriptor.in was closed
* caused an InternalError to be thrown.
+ * @build ClosedStreams
+ * @run main/othervm ClosedStreams
*/
import java.io.FileDescriptor;
--- a/jdk/test/java/nio/charset/coders/BashStreams.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/BashStreams.java Wed Jul 05 17:18:01 2017 +0200
@@ -46,7 +46,7 @@
CharacterGenerator(long seed, String csn, int limit) {
rand = new Random(seed);
- this.max = Surrogate.UCS4_MAX + 1;
+ this.max = Character.MAX_CODE_POINT + 1;
this.limit = limit;
}
@@ -77,17 +77,20 @@
int c;
for (;;) {
c = rand.nextInt(max);
- if (Surrogate.is(c) || (c == 0xfffe) || (c == 0xffff))
+ if ((Character.isBmpCodePoint(c)
+ && (Character.isSurrogate((char) c)
+ || (c == 0xfffe) || (c == 0xffff))))
continue;
- if (Surrogate.neededFor(c) && (count == limit - 1))
+ if (Character.isSupplementaryCodePoint(c)
+ && (count == limit - 1))
continue;
break;
}
count++;
- if (Surrogate.neededFor(c)) {
+ if (Character.isSupplementaryCodePoint(c)) {
count++;
- push(Surrogate.low(c));
- return Surrogate.high(c);
+ push(Character.lowSurrogate(c));
+ return Character.highSurrogate(c);
}
return (char)c;
}
@@ -137,7 +140,7 @@
char d = cg.next();
if (c != d) {
if (c == '?') {
- if (Surrogate.isHigh(d))
+ if (Character.isHighSurrogate(d))
cg.next();
continue;
}
@@ -187,7 +190,7 @@
w.write(ca, 0, n);
count += n;
}
- if (Surrogate.isHigh(ca[n - 1]))
+ if (Character.isHighSurrogate(ca[n - 1]))
w.write(cg.next());
w.close();
}
@@ -253,7 +256,8 @@
if (!cg.hasNext())
break;
char c = cg.next();
- if (Surrogate.isHigh(c) && (cb.remaining() == 1)) {
+ if (Character.isHighSurrogate(c)
+ && cb.remaining() == 1) {
cg.push(c);
break;
}
@@ -311,7 +315,7 @@
mismatchedEOF(csn, count + i, cg.count());
char d = cg.next();
if (c == '?') {
- if (Surrogate.isHigh(d)) {
+ if (Character.isHighSurrogate(d)) {
cg.next();
continue;
}
--- a/jdk/test/java/nio/charset/coders/Surrogate.java Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-public class Surrogate {
-
- public static final int UCS4_SURROGATE_MIN = 0x10000;
- public static final int UCS4_MAX = (1 << 20) + UCS4_SURROGATE_MIN - 1;
-
- // UTF-16 surrogate-character ranges
- //
- public static final char MIN_HIGH = '\uD800';
- public static final char MAX_HIGH = '\uDBFF';
- public static final char MIN_LOW = '\uDC00';
- public static final char MAX_LOW = '\uDFFF';
- public static final char MIN = MIN_HIGH;
- public static final char MAX = MAX_LOW;
-
- public static boolean neededFor(int uc) {
- return (uc >= UCS4_SURROGATE_MIN) && (uc <= UCS4_MAX);
- }
-
- public static boolean isHigh(int c) {
- return (MIN_HIGH <= c) && (c <= MAX_HIGH);
- }
-
- static char high(int uc) {
- return (char)(0xd800 | (((uc - UCS4_SURROGATE_MIN) >> 10) & 0x3ff));
- }
-
- public static boolean isLow(int c) {
- return (MIN_LOW <= c) && (c <= MAX_LOW);
- }
-
- static char low(int uc) {
- return (char)(0xdc00 | ((uc - UCS4_SURROGATE_MIN) & 0x3ff));
- }
-
- public static boolean is(int c) {
- return (MIN <= c) && (c <= MAX);
- }
-
- static int toUCS4(char c, char d) {
- return (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000;
- }
-
-}
--- a/jdk/test/java/nio/charset/coders/Surrogates.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/Surrogates.java Wed Jul 05 17:18:01 2017 +0200
@@ -42,9 +42,8 @@
static void initData() throws IOException {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < LEN; i++) {
- int c = Surrogate.UCS4_SURROGATE_MIN + 1;
- sb.append(Surrogate.high(c));
- sb.append(Surrogate.low(c));
+ int c = Character.MIN_SUPPLEMENTARY_CODE_POINT + 1;
+ sb.append(Character.toChars(c));
}
input = sb.toString().toCharArray();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
--- a/jdk/test/java/util/Arrays/Sorting.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/java/util/Arrays/Sorting.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,10 +43,11 @@
// Array lengths used in a long run (default)
private static final int[] LONG_RUN_LENGTHS = {
- 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000};
+ 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 };
// Array lengths used in a short run
- private static final int[] SHORT_RUN_LENGTHS = { 1, 2, 3, 21, 55, 1000, 10000 };
+ private static final int[] SHORT_RUN_LENGTHS = {
+ 1, 2, 3, 21, 55, 1000, 10000 };
// Random initial values used in a long run (default)
private static final long[] LONG_RUN_RANDOMS = {666, 0xC0FFEE, 999};
@@ -65,99 +66,338 @@
}
long end = System.currentTimeMillis();
- out.format("PASS in %d sec.\n", Math.round((end - start) / 1E3));
+ out.format("\nPASSED in %d sec.\n", Math.round((end - start) / 1E3));
}
private static void testAndCheck(int[] lengths, long[] randoms) {
+ testEmptyAndNullIntArray();
+ testEmptyAndNullLongArray();
+ testEmptyAndNullShortArray();
+ testEmptyAndNullCharArray();
+ testEmptyAndNullByteArray();
+ testEmptyAndNullFloatArray();
+ testEmptyAndNullDoubleArray();
+
for (long random : randoms) {
reset(random);
- for (int len : lengths) {
- testAndCheckWithCheckSum(len, random);
- }
- reset(random);
-
- for (int len : lengths) {
- testAndCheckWithScrambling(len, random);
+ for (int length : lengths) {
+ testAndCheckWithCheckSum(length, random);
}
reset(random);
- for (int len : lengths) {
- testAndCheckFloat(len, random);
+ for (int length : lengths) {
+ testAndCheckWithScrambling(length, random);
+ }
+ reset(random);
+
+ for (int length : lengths) {
+ testAndCheckFloat(length, random);
}
reset(random);
- for (int len : lengths) {
- testAndCheckDouble(len, random);
+ for (int length : lengths) {
+ testAndCheckDouble(length, random);
}
reset(random);
- for (int len : lengths) {
- testAndCheckRange(len, random);
+ for (int length : lengths) {
+ testAndCheckRange(length, random);
}
reset(random);
- for (int len : lengths) {
- testAndCheckSubArray(len, random);
+ for (int length : lengths) {
+ testAndCheckSubArray(length, random);
+ }
+ reset(random);
+
+ for (int length : lengths) {
+ testStable(length, random);
}
}
}
- private static void testAndCheckSubArray(int len, long random) {
- int[] golden = new int[len];
+ private static void testEmptyAndNullIntArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new int[] {});
+ Arrays.sort(new int[] {}, 0, 0);
+
+ try {
+ Arrays.sort((int[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((int[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(int[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(int[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullLongArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new long[] {});
+ Arrays.sort(new long[] {}, 0, 0);
+
+ try {
+ Arrays.sort((long[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((long[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(long[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(long[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullShortArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new short[] {});
+ Arrays.sort(new short[] {}, 0, 0);
+
+ try {
+ Arrays.sort((short[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((short[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(short[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(short[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullCharArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new char[] {});
+ Arrays.sort(new char[] {}, 0, 0);
- for (int m = 1; m < len / 2; m *= 2) {
+ try {
+ Arrays.sort((char[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((char[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(char[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(char[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullByteArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new byte[] {});
+ Arrays.sort(new byte[] {}, 0, 0);
+
+ try {
+ Arrays.sort((byte[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((byte[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(byte[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(byte[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullFloatArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new float[] {});
+ Arrays.sort(new float[] {}, 0, 0);
+
+ try {
+ Arrays.sort((float[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((float[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(float[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(float[]) shouldn't catch null array");
+ }
+
+ private static void testEmptyAndNullDoubleArray() {
+ ourDescription = "Check empty and null array";
+ Arrays.sort(new double[] {});
+ Arrays.sort(new double[] {}, 0, 0);
+
+ try {
+ Arrays.sort((double[]) null);
+ } catch (NullPointerException expected) {
+ try {
+ Arrays.sort((double[]) null, 0, 0);
+ } catch (NullPointerException expected2) {
+ return;
+ }
+ failed("Arrays.sort(double[],fromIndex,toIndex) shouldn't " +
+ "catch null array");
+ }
+ failed("Arrays.sort(double[]) shouldn't catch null array");
+ }
+
+ private static void testAndCheckSubArray(int length, long random) {
+ ourDescription = "Check sorting of subarray";
+ int[] golden = new int[length];
+ boolean newLine = false;
+
+ for (int m = 1; m < length / 2; m *= 2) {
+ newLine = true;
int fromIndex = m;
- int toIndex = len - m;
+ int toIndex = length - m;
prepareSubArray(golden, fromIndex, toIndex, m);
int[] test = golden.clone();
for (TypeConverter converter : TypeConverter.values()) {
- out.println("Test #6: " + converter +
- " len = " + len + ", m = " + m);
+ out.println("Test 'subarray': " + converter +
+ " length = " + length + ", m = " + m);
Object convertedGolden = converter.convert(golden);
Object convertedTest = converter.convert(test);
-
- // outArr(test);
+ // outArray(test);
sortSubArray(convertedTest, fromIndex, toIndex);
- // outArr(test);
+ // outArray(test);
checkSubArray(convertedTest, fromIndex, toIndex, m);
}
}
+ if (newLine) {
+ out.println();
+ }
+ }
+
+ private static void testAndCheckRange(int length, long random) {
+ ourDescription = "Check range check";
+ int[] golden = new int[length];
+
+ for (int m = 1; m < 2 * length; m *= 2) {
+ for (int i = 1; i <= length; i++) {
+ golden[i - 1] = i % m + m % i;
+ }
+ for (TypeConverter converter : TypeConverter.values()) {
+ out.println("Test 'range': " + converter +
+ ", length = " + length + ", m = " + m);
+ Object convertedGolden = converter.convert(golden);
+ checkRange(convertedGolden, m);
+ }
+ }
out.println();
}
- private static void testAndCheckRange(int len, long random) {
- int[] golden = new int[len];
+ private static void testStable(int length, long random) {
+ ourDescription = "Check if sorting is stable";
+ Pair[] a = build(length);
- for (int m = 1; m < 2 * len; m *= 2) {
- for (int i = 1; i <= len; i++) {
- golden[i - 1] = i % m + m % i;
+ out.println("Test 'stable': " + "random = " + random +
+ ", length = " + length);
+ Arrays.sort(a);
+ checkSorted(a);
+ checkStable(a);
+ }
+
+ private static void checkSorted(Pair[] a) {
+ for (int i = 0; i < a.length - 1; i++) {
+ if (a[i].getKey() > a[i + 1].getKey()) {
+ failed(i, "" + a[i].getKey(), "" + a[i + 1].getKey());
}
- for (TypeConverter converter : TypeConverter.values()) {
- out.println("Test #5: " + converter +
- ", len = " + len + ", m = " + m);
- Object convertedGolden = converter.convert(golden);
- sortRange(convertedGolden, m);
- sortEmpty(convertedGolden);
+ }
+ }
+
+ private static void checkStable(Pair[] a) {
+ for (int i = 0; i < a.length / 4; ) {
+ int key1 = a[i].getKey();
+ int value1 = a[i++].getValue();
+ int key2 = a[i].getKey();
+ int value2 = a[i++].getValue();
+ int key3 = a[i].getKey();
+ int value3 = a[i++].getValue();
+ int key4 = a[i].getKey();
+ int value4 = a[i++].getValue();
+
+ if (!(key1 == key2 && key2 == key3 && key3 == key4)) {
+ failed("On position " + i + " must keys are different " +
+ key1 + ", " + key2 + ", " + key3 + ", " + key4);
+ }
+ if (!(value1 < value2 && value2 < value3 && value3 < value4)) {
+ failed("Sorting is not stable at position " + i +
+ ". Second values have been changed: " + value1 + ", " +
+ value2 + ", " + value3 + ", " + value4);
}
}
- out.println();
+ }
+
+ private static Pair[] build(int length) {
+ Pair[] a = new Pair[length * 4];
+
+ for (int i = 0; i < a.length; ) {
+ int key = ourRandom.nextInt();
+ a[i++] = new Pair(key, 1);
+ a[i++] = new Pair(key, 2);
+ a[i++] = new Pair(key, 3);
+ a[i++] = new Pair(key, 4);
+ }
+ return a;
}
- private static void testAndCheckWithCheckSum(int len, long random) {
- int[] golden = new int[len];
+ private static final class Pair implements Comparable<Pair> {
+ Pair(int key, int value) {
+ myKey = key;
+ myValue = value;
+ }
+
+ int getKey() {
+ return myKey;
+ }
+
+ int getValue() {
+ return myValue;
+ }
- for (int m = 1; m < 2 * len; m *= 2) {
+ public int compareTo(Pair pair) {
+ if (myKey < pair.myKey) {
+ return -1;
+ }
+ if (myKey > pair.myKey) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + myKey + ", " + myValue + ")";
+ }
+
+ private int myKey;
+ private int myValue;
+ }
+
+ private static void testAndCheckWithCheckSum(int length, long random) {
+ ourDescription = "Check sorting with check sum";
+ int[] golden = new int[length];
+
+ for (int m = 1; m < 2 * length; m *= 2) {
for (UnsortedBuilder builder : UnsortedBuilder.values()) {
builder.build(golden, m);
int[] test = golden.clone();
for (TypeConverter converter : TypeConverter.values()) {
- out.println("Test #1: " + converter + " " + builder +
- "random = " + random + ", len = " + len +
- ", m = " + m);
+ out.println("Test 'check sum': " + converter + " " +
+ builder + "random = " + random + ", length = " +
+ length + ", m = " + m);
Object convertedGolden = converter.convert(golden);
Object convertedTest = converter.convert(test);
sort(convertedTest);
@@ -168,11 +408,12 @@
out.println();
}
- private static void testAndCheckWithScrambling(int len, long random) {
- int[] golden = new int[len];
+ private static void testAndCheckWithScrambling(int length, long random) {
+ ourDescription = "Check sorting with scrambling";
+ int[] golden = new int[length];
for (int m = 1; m <= 7; m++) {
- if (m > len) {
+ if (m > length) {
break;
}
for (SortedBuilder builder : SortedBuilder.values()) {
@@ -181,9 +422,9 @@
scramble(test);
for (TypeConverter converter : TypeConverter.values()) {
- out.println("Test #2: " + converter + " " + builder +
- "random = " + random + ", len = " + len +
- ", m = " + m);
+ out.println("Test 'scrambling': " + converter + " " +
+ builder + "random = " + random + ", length = " +
+ length + ", m = " + m);
Object convertedGolden = converter.convert(golden);
Object convertedTest = converter.convert(test);
sort(convertedTest);
@@ -194,8 +435,9 @@
out.println();
}
- private static void testAndCheckFloat(int len, long random) {
- float[] golden = new float[len];
+ private static void testAndCheckFloat(int length, long random) {
+ ourDescription = "Check float sorting";
+ float[] golden = new float[length];
final int MAX = 10;
boolean newLine = false;
@@ -204,22 +446,23 @@
for (int z = 0; z <= MAX; z++) {
for (int n = 0; n <= MAX; n++) {
for (int p = 0; p <= MAX; p++) {
- if (a + g + z + n + p > len) {
+ if (a + g + z + n + p > length) {
continue;
}
- if (a + g + z + n + p < len) {
+ if (a + g + z + n + p < length) {
continue;
}
for (FloatBuilder builder : FloatBuilder.values()) {
- out.println("Test #3: random = " + random +
- ", len = " + len + ", a = " + a + ", g = " + g +
- ", z = " + z + ", n = " + n + ", p = " + p);
+ out.println("Test 'float': random = " + random +
+ ", length = " + length + ", a = " + a +
+ ", g = " + g + ", z = " + z + ", n = " + n +
+ ", p = " + p);
builder.build(golden, a, g, z, n, p);
float[] test = golden.clone();
scramble(test);
- // outArr(test);
+ // outArray(test);
sort(test);
- // outArr(test);
+ // outArray(test);
compare(test, golden, a, n, g);
}
newLine = true;
@@ -233,8 +476,9 @@
}
}
- private static void testAndCheckDouble(int len, long random) {
- double[] golden = new double[len];
+ private static void testAndCheckDouble(int length, long random) {
+ ourDescription = "Check double sorting";
+ double[] golden = new double[length];
final int MAX = 10;
boolean newLine = false;
@@ -243,22 +487,22 @@
for (int z = 0; z <= MAX; z++) {
for (int n = 0; n <= MAX; n++) {
for (int p = 0; p <= MAX; p++) {
- if (a + g + z + n + p > len) {
+ if (a + g + z + n + p > length) {
continue;
}
- if (a + g + z + n + p < len) {
+ if (a + g + z + n + p < length) {
continue;
}
for (DoubleBuilder builder : DoubleBuilder.values()) {
- out.println("Test #4: random = " + random +
- ", len = " + len + ", a = " + a + ", g = " + g +
- ", z = " + z + ", n = " + n + ", p = " + p);
+ out.println("Test 'double': random = " + random +
+ ", length = " + length + ", a = " + a + ", g = " +
+ g + ", z = " + z + ", n = " + n + ", p = " + p);
builder.build(golden, a, g, z, n, p);
double[] test = golden.clone();
scramble(test);
- // outArr(test);
+ // outArray(test);
sort(test);
- // outArr(test);
+ // outArray(test);
compare(test, golden, a, n, g);
}
newLine = true;
@@ -276,37 +520,29 @@
for (int i = 0; i < fromIndex; i++) {
a[i] = 0xBABA;
}
-
for (int i = fromIndex; i < toIndex; i++) {
a[i] = -i + m;
}
-
for (int i = toIndex; i < a.length; i++) {
a[i] = 0xDEDA;
}
}
private static void scramble(int[] a) {
- int length = a.length;
-
- for (int i = 0; i < length * 7; i++) {
- swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+ for (int i = 0; i < a.length * 7; i++) {
+ swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
}
}
private static void scramble(float[] a) {
- int length = a.length;
-
- for (int i = 0; i < length * 7; i++) {
- swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+ for (int i = 0; i < a.length * 7; i++) {
+ swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
}
}
private static void scramble(double[] a) {
- int length = a.length;
-
- for (int i = 0; i < length * 7; i++) {
- swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+ for (int i = 0; i < a.length * 7; i++) {
+ swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
}
}
@@ -393,6 +629,16 @@
}
return b;
}
+ },
+ INTEGER {
+ Object convert(int[] a) {
+ Integer[] b = new Integer[a.length];
+
+ for (int i = 0; i < a.length; i++) {
+ b[i] = new Integer(a[i]);
+ }
+ return b;
+ }
};
abstract Object convert(int[] a);
@@ -691,6 +937,8 @@
compare((float[]) test, (float[]) golden);
} else if (test instanceof double[]) {
compare((double[]) test, (double[]) golden);
+ } else if (test instanceof Integer[]) {
+ compare((Integer[]) test, (Integer[]) golden);
} else {
failed("Unknow type of array: " + test + " of class " +
test.getClass().getName());
@@ -703,13 +951,13 @@
}
private static void failed(String message) {
- err.format("\n*** FAILED: %s\n\n", message);
+ err.format("\n*** TEST FAILED - %s\n\n%s\n\n", ourDescription, message);
throw new RuntimeException("Test failed - see log file for details");
}
private static void failed(int index, String value1, String value2) {
- failed("Array is not sorted at " + index + "-th position: " + value1 +
- " and " + value2);
+ failed("Array is not sorted at " + index + "-th position: " +
+ value1 + " and " + value2);
}
private static void checkSorted(Object object) {
@@ -727,12 +975,22 @@
checkSorted((float[]) object);
} else if (object instanceof double[]) {
checkSorted((double[]) object);
+ } else if (object instanceof Integer[]) {
+ checkSorted((Integer[]) object);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
}
}
+ private static void compare(Integer[] a, Integer[] b) {
+ for (int i = 0; i < a.length; i++) {
+ if (a[i].intValue() != b[i].intValue()) {
+ failed(i, "" + a[i], "" + b[i]);
+ }
+ }
+ }
+
private static void compare(int[] a, int[] b) {
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
@@ -789,6 +1047,14 @@
}
}
+ private static void checkSorted(Integer[] a) {
+ for (int i = 0; i < a.length - 1; i++) {
+ if (a[i].intValue() > a[i + 1].intValue()) {
+ failed(i, "" + a[i], "" + a[i + 1]);
+ }
+ }
+ }
+
private static void checkSorted(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
@@ -847,7 +1113,7 @@
private static void checkCheckSum(Object test, Object golden) {
if (checkSum(test) != checkSum(golden)) {
- failed("Original and sorted arrays seems not identical");
+ failed("It seems that original and sorted arrays are not identical");
}
}
@@ -866,6 +1132,8 @@
return checkSum((float[]) object);
} else if (object instanceof double[]) {
return checkSum((double[]) object);
+ } else if (object instanceof Integer[]) {
+ return checkSum((Integer[]) object);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
@@ -873,6 +1141,15 @@
}
}
+ private static int checkSum(Integer[] a) {
+ int checkXorSum = 0;
+
+ for (Integer e : a) {
+ checkXorSum ^= e.intValue();
+ }
+ return checkXorSum;
+ }
+
private static int checkSum(int[] a) {
int checkXorSum = 0;
@@ -951,6 +1228,8 @@
Arrays.sort((float[]) object);
} else if (object instanceof double[]) {
Arrays.sort((double[]) object);
+ } else if (object instanceof Integer[]) {
+ Arrays.sort((Integer[]) object);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
@@ -972,6 +1251,8 @@
Arrays.sort((float[]) object, fromIndex, toIndex);
} else if (object instanceof double[]) {
Arrays.sort((double[]) object, fromIndex, toIndex);
+ } else if (object instanceof Integer[]) {
+ Arrays.sort((Integer[]) object, fromIndex, toIndex);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
@@ -993,12 +1274,36 @@
checkSubArray((float[]) object, fromIndex, toIndex, m);
} else if (object instanceof double[]) {
checkSubArray((double[]) object, fromIndex, toIndex, m);
+ } else if (object instanceof Integer[]) {
+ checkSubArray((Integer[]) object, fromIndex, toIndex, m);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
}
}
+ private static void checkSubArray(Integer[] a, int fromIndex, int toIndex, int m) {
+ for (int i = 0; i < fromIndex; i++) {
+ if (a[i].intValue() != 0xBABA) {
+ failed("Range sort changes left element on position " + i +
+ ": " + a[i] + ", must be " + 0xBABA);
+ }
+ }
+
+ for (int i = fromIndex; i < toIndex - 1; i++) {
+ if (a[i].intValue() > a[i + 1].intValue()) {
+ failed(i, "" + a[i], "" + a[i + 1]);
+ }
+ }
+
+ for (int i = toIndex; i < a.length; i++) {
+ if (a[i].intValue() != 0xDEDA) {
+ failed("Range sort changes right element on position " + i +
+ ": " + a[i] + ", must be " + 0xDEDA);
+ }
+ }
+ }
+
private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) {
for (int i = 0; i < fromIndex; i++) {
if (a[i] != 0xBABA) {
@@ -1153,49 +1458,30 @@
}
}
- private static void sortRange(Object object, int m) {
+ private static void checkRange(Object object, int m) {
if (object instanceof int[]) {
- sortRange((int[]) object, m);
+ checkRange((int[]) object, m);
} else if (object instanceof long[]) {
- sortRange((long[]) object, m);
+ checkRange((long[]) object, m);
} else if (object instanceof short[]) {
- sortRange((short[]) object, m);
+ checkRange((short[]) object, m);
} else if (object instanceof byte[]) {
- sortRange((byte[]) object, m);
+ checkRange((byte[]) object, m);
} else if (object instanceof char[]) {
- sortRange((char[]) object, m);
+ checkRange((char[]) object, m);
} else if (object instanceof float[]) {
- sortRange((float[]) object, m);
+ checkRange((float[]) object, m);
} else if (object instanceof double[]) {
- sortRange((double[]) object, m);
+ checkRange((double[]) object, m);
+ } else if (object instanceof Integer[]) {
+ checkRange((Integer[]) object, m);
} else {
failed("Unknow type of array: " + object + " of class " +
object.getClass().getName());
}
}
- private static void sortEmpty(Object object) {
- if (object instanceof int[]) {
- Arrays.sort(new int [] {});
- } else if (object instanceof long[]) {
- Arrays.sort(new long [] {});
- } else if (object instanceof short[]) {
- Arrays.sort(new short [] {});
- } else if (object instanceof byte[]) {
- Arrays.sort(new byte [] {});
- } else if (object instanceof char[]) {
- Arrays.sort(new char [] {});
- } else if (object instanceof float[]) {
- Arrays.sort(new float [] {});
- } else if (object instanceof double[]) {
- Arrays.sort(new double [] {});
- } else {
- failed("Unknow type of array: " + object + " of class " +
- object.getClass().getName());
- }
- }
-
- private static void sortRange(int[] a, int m) {
+ private static void checkRange(Integer[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1224,7 +1510,36 @@
}
}
- private static void sortRange(long[] a, int m) {
+ private static void checkRange(int[] a, int m) {
+ try {
+ Arrays.sort(a, m + 1, m);
+
+ failed("Sort does not throw IllegalArgumentException " +
+ " as expected: fromIndex = " + (m + 1) +
+ " toIndex = " + m);
+ }
+ catch (IllegalArgumentException iae) {
+ try {
+ Arrays.sort(a, -m, a.length);
+
+ failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+ " as expected: fromIndex = " + (-m));
+ }
+ catch (ArrayIndexOutOfBoundsException aoe) {
+ try {
+ Arrays.sort(a, 0, a.length + m);
+
+ failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+ " as expected: toIndex = " + (a.length + m));
+ }
+ catch (ArrayIndexOutOfBoundsException aie) {
+ return;
+ }
+ }
+ }
+ }
+
+ private static void checkRange(long[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1253,7 +1568,7 @@
}
}
- private static void sortRange(byte[] a, int m) {
+ private static void checkRange(byte[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1282,7 +1597,7 @@
}
}
- private static void sortRange(short[] a, int m) {
+ private static void checkRange(short[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1311,7 +1626,7 @@
}
}
- private static void sortRange(char[] a, int m) {
+ private static void checkRange(char[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1340,7 +1655,7 @@
}
}
- private static void sortRange(float[] a, int m) {
+ private static void checkRange(float[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1369,7 +1684,7 @@
}
}
- private static void sortRange(double[] a, int m) {
+ private static void checkRange(double[] a, int m) {
try {
Arrays.sort(a, m + 1, m);
@@ -1410,31 +1725,36 @@
ourSecond = 0;
}
- private static void outArr(int[] a) {
+ private static void outArray(Object[] a) {
+ for (int i = 0; i < a.length; i++) {
+ out.print(a[i] + " ");
+ }
+ out.println();
+ }
+
+ private static void outArray(int[] a) {
for (int i = 0; i < a.length; i++) {
out.print(a[i] + " ");
}
out.println();
- out.println();
}
- private static void outArr(float[] a) {
+ private static void outArray(float[] a) {
for (int i = 0; i < a.length; i++) {
out.print(a[i] + " ");
}
out.println();
- out.println();
}
- private static void outArr(double[] a) {
+ private static void outArray(double[] a) {
for (int i = 0; i < a.length; i++) {
out.print(a[i] + " ");
}
out.println();
- out.println();
}
private static int ourFirst;
private static int ourSecond;
private static Random ourRandom;
+ private static String ourDescription;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.logging.*;
+
+public class AnonLoggerWeakRefLeak {
+ public static int DEFAULT_LOOP_TIME = 60; // time is in seconds
+
+ public static void main(String[] args) {
+ int loop_time = 0;
+ int max_loop_time = DEFAULT_LOOP_TIME;
+
+ if (args.length == 0) {
+ System.out.println("INFO: using default time of "
+ + max_loop_time + " seconds.");
+ } else {
+ try {
+ max_loop_time = Integer.parseInt(args[0]);
+ } catch (NumberFormatException nfe) {
+ System.err.println("Error: '" + args[0]
+ + "': is not a valid seconds value.");
+ System.err.println("Usage: AnonLoggerWeakRefLeak [seconds]");
+ System.exit(1);
+ }
+ }
+
+ long count = 0;
+ long now = 0;
+ long startTime = System.currentTimeMillis();
+
+ while (now < (startTime + (max_loop_time * 1000))) {
+ if ((count % 1000) == 0) {
+ // Print initial call count to let caller know that
+ // we're up and running and then periodically
+ System.out.println("INFO: call count = " + count);
+ }
+
+ for (int i = 0; i < 100; i++) {
+ // this Logger call is leaking a WeakReference in Logger.kids
+ java.util.logging.Logger.getAnonymousLogger();
+ count++;
+ }
+
+ try {
+ // delay for 1/10 of a second to avoid CPU saturation
+ Thread.sleep(100);
+ } catch (InterruptedException ie) {
+ // ignore any exceptions
+ }
+
+ now = System.currentTimeMillis();
+ }
+
+ System.out.println("INFO: final loop count = " + count);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,247 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 6942989
+# @ignore until 6964018 is fixed
+# @summary Check for WeakReference leak in anonymous Logger objects
+# @author Daniel D. Daugherty
+#
+# @run build AnonLoggerWeakRefLeak
+# @run shell/timeout=180 AnonLoggerWeakRefLeak.sh
+
+# The timeout is: 2 minutes for infrastructure and 1 minute for the test
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+JAVA="${TESTJAVA}"/bin/java
+JMAP="${TESTJAVA}"/bin/jmap
+JPS="${TESTJAVA}"/bin/jps
+
+set -eu
+
+TEST_NAME="AnonLoggerWeakRefLeak"
+TARGET_CLASS="java\.lang\.ref\.WeakReference"
+
+is_cygwin=false
+is_mks=false
+is_windows=false
+
+case `uname -s` in
+CYGWIN*)
+ is_cygwin=true
+ is_windows=true
+ ;;
+Windows_*)
+ is_mks=true
+ is_windows=true
+ ;;
+*)
+ ;;
+esac
+
+
+# wrapper for grep
+#
+grep_cmd() {
+ set +e
+ if $is_windows; then
+ # need dos2unix to get rid of CTRL-M chars from java output
+ dos2unix | grep "$@"
+ status="$?"
+ else
+ grep "$@"
+ status="$?"
+ fi
+ set -e
+}
+
+
+# MAIN begins here
+#
+
+seconds=
+if [ "$#" -gt 0 ]; then
+ seconds="$1"
+fi
+
+# see if this version of jmap supports the '-histo:live' option
+jmap_option="-histo:live"
+set +e
+"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1
+grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1
+status="$?"
+set -e
+if [ "$status" = 0 ]; then
+ echo "INFO: switching jmap option from '$jmap_option'\c"
+ jmap_option="-histo"
+ echo " to '$jmap_option'."
+fi
+
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \
+ "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 &
+test_pid="$!"
+echo "INFO: starting $TEST_NAME as pid = $test_pid"
+
+# wait for test program to get going
+count=0
+while [ "$count" -lt 30 ]; do
+ sleep 2
+ grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1
+ if [ "$status" = 0 ]; then
+ break
+ fi
+ count=`expr $count + 1`
+done
+
+if [ "$count" -ge 30 ]; then
+ echo "ERROR: $TEST_NAME failed to get going." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 1
+elif [ "$count" -gt 1 ]; then
+ echo "INFO: $TEST_NAME took $count loops to start."
+fi
+
+if $is_cygwin; then
+ # We need the Windows pid for jmap and not the Cygwin pid.
+ # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris.
+ jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'`
+ if [ -z "$jmap_pid" ]; then
+ echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid"
+else
+ jmap_pid="$test_pid"
+fi
+
+decreasing_cnt=0
+increasing_cnt=0
+loop_cnt=0
+prev_instance_cnt=0
+
+while true; do
+ # Output format for 'jmap -histo' in JDK1.5.0:
+ #
+ # <#bytes> <#instances> <class_name>
+ #
+ # Output format for 'jmap -histo:live':
+ #
+ # <num>: <#instances> <#bytes> <class_name>
+ #
+ set +e
+ "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1
+ status="$?"
+ set -e
+
+ if [ "$status" != 0 ]; then
+ echo "INFO: jmap exited with exit code = $status"
+ if [ "$loop_cnt" = 0 ]; then
+ echo "INFO: on the first iteration so no samples were taken."
+ echo "INFO: start of jmap output:"
+ cat "$TEST_NAME.jmap"
+ echo "INFO: end of jmap output."
+ echo "FAIL: jmap is unable to take any samples." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ echo "INFO: The likely reason is that $TEST_NAME has finished running."
+ break
+ fi
+
+ instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \
+ < "$TEST_NAME.jmap" \
+ | sed '
+ # strip leading whitespace; does nothing in JDK1.5.0
+ s/^[ ][ ]*//
+ # strip <#bytes> in JDK1.5.0; does nothing otherwise
+ s/^[1-9][0-9]*[ ][ ]*//
+ # strip <num>: field; does nothing in JDK1.5.0
+ s/^[1-9][0-9]*:[ ][ ]*//
+ # strip <class_name> field
+ s/[ ].*//
+ '`
+ if [ -z "$instance_cnt" ]; then
+ echo "INFO: instance count is unexpectedly empty"
+ if [ "$loop_cnt" = 0 ]; then
+ echo "INFO: on the first iteration so no sample was found."
+ echo "INFO: There is likely a problem with the sed filter."
+ echo "INFO: start of jmap output:"
+ cat "$TEST_NAME.jmap"
+ echo "INFO: end of jmap output."
+ echo "FAIL: cannot find the instance count value." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ else
+ echo "INFO: instance_cnt = $instance_cnt"
+
+ if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
+ increasing_cnt=`expr $increasing_cnt + 1`
+ else
+ decreasing_cnt=`expr $decreasing_cnt + 1`
+ fi
+ prev_instance_cnt="$instance_cnt"
+ fi
+
+ # delay between samples
+ sleep 5
+
+ loop_cnt=`expr $loop_cnt + 1`
+done
+
+echo "INFO: increasing_cnt = $increasing_cnt"
+echo "INFO: decreasing_cnt = $decreasing_cnt"
+
+echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
+if [ "$decreasing_cnt" = 0 ]; then
+ echo "INFO: is always increasing."
+ echo "FAIL: This indicates that there is a memory leak." >&2
+ exit 2
+fi
+
+echo "INFO: is both increasing and decreasing."
+echo "PASS: This indicates that there is not a memory leak."
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.logging.*;
+
+public class LoggerWeakRefLeak {
+ // AnonLoggerWeakRefLeak checks for one weak reference leak.
+ // LoggerWeakRefLeak checks for two weak reference leaks so
+ // this test runs twice as long, by default.
+ public static int DEFAULT_LOOP_TIME = 120; // time is in seconds
+
+ public static void main(String[] args) {
+ int loop_time = 0;
+ int max_loop_time = DEFAULT_LOOP_TIME;
+
+ if (args.length == 0) {
+ System.out.println("INFO: using default time of "
+ + max_loop_time + " seconds.");
+ } else {
+ try {
+ max_loop_time = Integer.parseInt(args[0]);
+ } catch (NumberFormatException nfe) {
+ System.err.println("Error: '" + args[0]
+ + "': is not a valid seconds value.");
+ System.err.println("Usage: LoggerWeakRefLeak [seconds]");
+ System.exit(1);
+ }
+ }
+
+ long count = 0;
+ int loggerCount = 0;
+ long now = 0;
+ long startTime = System.currentTimeMillis();
+
+ while (now < (startTime + (max_loop_time * 1000))) {
+ if ((count % 1000) == 0) {
+ // Print initial call count to let caller know that
+ // we're up and running and then periodically
+ System.out.println("INFO: call count = " + count);
+ }
+
+ for (int i = 0; i < 100; i++) {
+ // This Logger call is leaking two different WeakReferences:
+ // - one in LogManager.LogNode
+ // - one in Logger.kids
+ java.util.logging.Logger.getLogger("logger-" + loggerCount);
+ count++;
+ if (++loggerCount >= 25000) {
+ // Limit the Logger namespace used by the test so
+ // the weak refs in LogManager.loggers that are
+ // being properly managed don't skew the counts
+ // by too much.
+ loggerCount = 0;
+ }
+ }
+
+ try {
+ // delay for 1/10 of a second to avoid CPU saturation
+ Thread.sleep(100);
+ } catch (InterruptedException ie) {
+ // ignore any exceptions
+ }
+
+ now = System.currentTimeMillis();
+ }
+
+ System.out.println("INFO: final loop count = " + count);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,247 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 6942989
+# @ignore until 6964018 is fixed
+# @summary Check for WeakReference leak in Logger objects
+# @author Daniel D. Daugherty
+#
+# @run build LoggerWeakRefLeak
+# @run shell/timeout=240 LoggerWeakRefLeak.sh
+
+# The timeout is: 2 minutes for infrastructure and 1 minute for the test
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+JAVA="${TESTJAVA}"/bin/java
+JMAP="${TESTJAVA}"/bin/jmap
+JPS="${TESTJAVA}"/bin/jps
+
+set -eu
+
+TEST_NAME="LoggerWeakRefLeak"
+TARGET_CLASS="java\.lang\.ref\.WeakReference"
+
+is_cygwin=false
+is_mks=false
+is_windows=false
+
+case `uname -s` in
+CYGWIN*)
+ is_cygwin=true
+ is_windows=true
+ ;;
+Windows_*)
+ is_mks=true
+ is_windows=true
+ ;;
+*)
+ ;;
+esac
+
+
+# wrapper for grep
+#
+grep_cmd() {
+ set +e
+ if $is_windows; then
+ # need dos2unix to get rid of CTRL-M chars from java output
+ dos2unix | grep "$@"
+ status="$?"
+ else
+ grep "$@"
+ status="$?"
+ fi
+ set -e
+}
+
+
+# MAIN begins here
+#
+
+seconds=
+if [ "$#" -gt 0 ]; then
+ seconds="$1"
+fi
+
+# see if this version of jmap supports the '-histo:live' option
+jmap_option="-histo:live"
+set +e
+"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1
+grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1
+status="$?"
+set -e
+if [ "$status" = 0 ]; then
+ echo "INFO: switching jmap option from '$jmap_option'\c"
+ jmap_option="-histo"
+ echo " to '$jmap_option'."
+fi
+
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \
+ "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 &
+test_pid="$!"
+echo "INFO: starting $TEST_NAME as pid = $test_pid"
+
+# wait for test program to get going
+count=0
+while [ "$count" -lt 30 ]; do
+ sleep 2
+ grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1
+ if [ "$status" = 0 ]; then
+ break
+ fi
+ count=`expr $count + 1`
+done
+
+if [ "$count" -ge 30 ]; then
+ echo "ERROR: $TEST_NAME failed to get going." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 1
+elif [ "$count" -gt 1 ]; then
+ echo "INFO: $TEST_NAME took $count loops to start."
+fi
+
+if $is_cygwin; then
+ # We need the Windows pid for jmap and not the Cygwin pid.
+ # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris.
+ jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'`
+ if [ -z "$jmap_pid" ]; then
+ echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid"
+else
+ jmap_pid="$test_pid"
+fi
+
+decreasing_cnt=0
+increasing_cnt=0
+loop_cnt=0
+prev_instance_cnt=0
+
+while true; do
+ # Output format for 'jmap -histo' in JDK1.5.0:
+ #
+ # <#bytes> <#instances> <class_name>
+ #
+ # Output format for 'jmap -histo:live':
+ #
+ # <num>: <#instances> <#bytes> <class_name>
+ #
+ set +e
+ "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1
+ status="$?"
+ set -e
+
+ if [ "$status" != 0 ]; then
+ echo "INFO: jmap exited with exit code = $status"
+ if [ "$loop_cnt" = 0 ]; then
+ echo "INFO: on the first iteration so no samples were taken."
+ echo "INFO: start of jmap output:"
+ cat "$TEST_NAME.jmap"
+ echo "INFO: end of jmap output."
+ echo "FAIL: jmap is unable to take any samples." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ echo "INFO: The likely reason is that $TEST_NAME has finished running."
+ break
+ fi
+
+ instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \
+ < "$TEST_NAME.jmap" \
+ | sed '
+ # strip leading whitespace; does nothing in JDK1.5.0
+ s/^[ ][ ]*//
+ # strip <#bytes> in JDK1.5.0; does nothing otherwise
+ s/^[1-9][0-9]*[ ][ ]*//
+ # strip <num>: field; does nothing in JDK1.5.0
+ s/^[1-9][0-9]*:[ ][ ]*//
+ # strip <class_name> field
+ s/[ ].*//
+ '`
+ if [ -z "$instance_cnt" ]; then
+ echo "INFO: instance count is unexpectedly empty"
+ if [ "$loop_cnt" = 0 ]; then
+ echo "INFO: on the first iteration so no sample was found."
+ echo "INFO: There is likely a problem with the sed filter."
+ echo "INFO: start of jmap output:"
+ cat "$TEST_NAME.jmap"
+ echo "INFO: end of jmap output."
+ echo "FAIL: cannot find the instance count value." >&2
+ echo "INFO: killing $test_pid"
+ kill "$test_pid"
+ exit 2
+ fi
+ else
+ echo "INFO: instance_cnt = $instance_cnt"
+
+ if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
+ increasing_cnt=`expr $increasing_cnt + 1`
+ else
+ decreasing_cnt=`expr $decreasing_cnt + 1`
+ fi
+ prev_instance_cnt="$instance_cnt"
+ fi
+
+ # delay between samples
+ sleep 5
+
+ loop_cnt=`expr $loop_cnt + 1`
+done
+
+echo "INFO: increasing_cnt = $increasing_cnt"
+echo "INFO: decreasing_cnt = $decreasing_cnt"
+
+echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
+if [ "$decreasing_cnt" = 0 ]; then
+ echo "INFO: is always increasing."
+ echo "FAIL: This indicates that there is a memory leak." >&2
+ exit 2
+fi
+
+echo "INFO: is both increasing and decreasing."
+echo "PASS: This indicates that there is not a memory leak."
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/AbstractButton/6711682/bug6711682.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @bug 6711682
+ @summary JCheckBox in JTable: checkbox doesn't alaways respond to the first mouse click
+ @author Alexander Potochkin
+ @run main bug6711682
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.event.CellEditorListener;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.EventObject;
+
+public class bug6711682 {
+ private static JCheckBox editorCb;
+ private static JCheckBox rendererCb;
+ private static JTable table;
+
+ public static void main(String[] args) throws Exception {
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ createAndShowGUI();
+ }
+ });
+ toolkit.realSync();
+ Point l = table.getLocationOnScreen();
+ int h = table.getRowHeight();
+ for (int i = 0; i < 3; i++) {
+ robot.mouseMove(l.x + 5, l.y + 5 + i * h);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ }
+ // Without pressing F2 the last table's cell
+ // reported <code>false</code> value
+ // note that I can't press it inside the for loop
+ // because it doesn't reproduce the bug
+ robot.keyPress(KeyEvent.VK_F2);
+ robot.keyRelease(KeyEvent.VK_F2);
+
+ for (int i = 0; i < 3; i++) {
+ if (!Boolean.TRUE.equals(table.getValueAt(i, 0))) {
+ throw new RuntimeException("Row #" + i + " checkbox is not selected");
+ }
+ }
+ for (int i = 2; i >= 0; i--) {
+ robot.mouseMove(l.x + 5, l.y + 5 + i * h);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ }
+ robot.keyPress(KeyEvent.VK_F2);
+ robot.keyRelease(KeyEvent.VK_F2);
+ for (int i = 0; i < 3; i++) {
+ if (Boolean.TRUE.equals(table.getValueAt(i, 0))) {
+ throw new RuntimeException("Row #" + i + " checkbox is selected");
+ }
+ }
+ }
+
+ private static void createAndShowGUI() {
+ editorCb = new JCheckBox();
+ rendererCb = new JCheckBox();
+ JFrame f = new JFrame("Table with CheckBox");
+ Container p = f.getContentPane();
+ p.setLayout(new BorderLayout());
+ table = new JTable(new Object[][]{{false}, {false}, {false}}, new Object[]{"CheckBox"});
+ TableCellEditor editor = new TableCellEditor() {
+ int editedRow;
+
+ public Component getTableCellEditorComponent(JTable table,
+ Object value, boolean isSelected, int row, int column) {
+ this.editedRow = row;
+ editorCb.setSelected(Boolean.TRUE.equals(value));
+ editorCb.setBackground(UIManager.getColor("Table.selectionBackground"));
+ return editorCb;
+ }
+
+ public void addCellEditorListener(CellEditorListener l) {
+ }
+
+ public void cancelCellEditing() {
+ }
+
+ public Object getCellEditorValue() {
+ return editorCb.isSelected();
+ }
+
+ public boolean isCellEditable(EventObject anEvent) {
+ return true;
+ }
+
+ public void removeCellEditorListener(CellEditorListener l) {
+ }
+
+ public boolean shouldSelectCell(EventObject anEvent) {
+ return true;
+ }
+
+ public boolean stopCellEditing() {
+ table.getModel().setValueAt(editorCb.isSelected(), editedRow, 0);
+ return true;
+ }
+ };
+ table.getColumnModel().getColumn(0).setCellEditor(editor);
+
+ TableCellRenderer renderer = new TableCellRenderer() {
+ public Component getTableCellRendererComponent(JTable table,
+ Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ rendererCb.setSelected(Boolean.TRUE.equals(value));
+ return rendererCb;
+ }
+ };
+ table.getColumnModel().getColumn(0).setCellRenderer(renderer);
+
+ p.add(table, BorderLayout.CENTER);
+
+ f.pack();
+ f.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6520101/bug6520101.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test @(#)bug6520101
+ * @bug 6520101
+ * @summary JFileChooser throws OOM in 1.4.2, 5.0u4 and 1.6.0
+ * @author Praveen Gupta
+ * @run main/othervm/timeout=600 -Xmx8m -verify bug6520101
+*/
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class bug6520101 implements Runnable {
+
+ private static final int ATTEMPTS = 500;
+ private static final int INTERVAL = 100;
+
+ private static final boolean ALWAYS_NEW_INSTANCE = false;
+ private static final boolean DO_GC_EACH_INTERVAL = false;
+ private static final boolean UPDATE_UI_EACH_INTERVAL = true;
+ private static final boolean AUTO_CLOSE_DIALOG = true;
+
+ private static JFileChooser CHOOSER;
+
+ public static void main(String[] args) throws Exception {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
+
+ for (int i = 0; i < ATTEMPTS; i++) {
+ doAttempt();
+ }
+
+ System.out.println("Test passed successfully");
+ }
+
+ private static void doAttempt() throws InterruptedException {
+ if (ALWAYS_NEW_INSTANCE || (CHOOSER == null))
+ CHOOSER = new JFileChooser(".");
+
+ if (UPDATE_UI_EACH_INTERVAL) {
+ CHOOSER.updateUI();
+ }
+
+ if (AUTO_CLOSE_DIALOG) {
+ Thread t = new Thread(new bug6520101(CHOOSER));
+ t.start();
+ CHOOSER.showOpenDialog(null);
+ t.join();
+ } else {
+ CHOOSER.showOpenDialog(null);
+ }
+
+ if (DO_GC_EACH_INTERVAL) {
+ System.gc();
+ }
+ }
+
+ private final JFileChooser chooser;
+
+ bug6520101(JFileChooser chooser) {
+ this.chooser = chooser;
+ }
+
+ public void run() {
+ while (!this.chooser.isShowing()) {
+ try {
+ Thread.sleep(30);
+ } catch (InterruptedException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ Timer timer = new Timer(INTERVAL, new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ chooser.cancelSelection();
+ }
+ });
+
+ timer.setRepeats(false);
+ timer.start();
+ }
+}
--- a/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
new com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel());
} catch(UnsupportedLookAndFeelException e) {
System.out.println("The test is for Windows LaF only");
- System.exit(0);
+ return;
}
final bug6725409 bug6725409 = new bug6725409();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6495920
+ * @summary Tests that if the JPopupMenu.setVisible method throws an exception,
+ interaction with GNOME is not crippled
+ * @author Sergey Malenkov
+ * @library ../..
+ */
+
+import sun.awt.AppContext;
+
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.lang.reflect.Field;
+import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.basic.BasicPopupMenuUI;
+
+public class bug6495920 implements Thread.UncaughtExceptionHandler {
+
+ public static void main(String[] args) throws Throwable {
+ SwingTest.start(bug6495920.class);
+ }
+
+ private static Robot robot;
+ private final JPanel panel;
+
+ public bug6495920(JFrame frame) {
+ JPopupMenu menu = new JPopupMenu() {
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ throw new AssertionError(visible ? "show popup" : "hide popup");
+ }
+ };
+ for (int i = 0; i < 10; i++) {
+ menu.add(new JMenuItem(String.valueOf(i)));
+ }
+ this.panel = new JPanel();
+ this.panel.setComponentPopupMenu(menu);
+ frame.add(this.panel);
+ }
+
+ public void firstShowPopup() throws Exception {
+ Point point = this.panel.getLocation();
+ SwingUtilities.convertPointToScreen(point, this.panel);
+
+ robot = new Robot(); // initialize shared static field first time
+ robot.mouseMove(point.x + 1, point.y + 1);
+ robot.mousePress(InputEvent.BUTTON3_MASK);
+ Thread.currentThread().setUncaughtExceptionHandler(this);
+ robot.mouseRelease(InputEvent.BUTTON3_MASK); // causes first AssertionError on EDT
+ }
+
+ public void secondHidePopup() {
+ Point point = this.panel.getLocation();
+ SwingUtilities.convertPointToScreen(point, this.panel);
+
+ robot.mouseMove(point.x - 1, point.y - 1);
+ Thread.currentThread().setUncaughtExceptionHandler(this);
+ robot.mousePress(InputEvent.BUTTON1_MASK); // causes second AssertionError on EDT
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ }
+
+ public void thirdValidate() throws Exception {
+ Field key = BasicPopupMenuUI.class.getDeclaredField("MOUSE_GRABBER_KEY");
+ key.setAccessible(true);
+
+ Object grabber = AppContext.getAppContext().get(key.get(null));
+ if (grabber == null) {
+ throw new Exception("cannot find a mouse grabber in app's context");
+ }
+
+ Field field = grabber.getClass().getDeclaredField("grabbedWindow");
+ field.setAccessible(true);
+
+ Object window = field.get(grabber);
+ if (window != null) {
+ throw new Exception("interaction with GNOME is crippled");
+ }
+ }
+
+ public void uncaughtException(Thread thread, Throwable throwable) {
+ System.out.println(throwable);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/6777378/bug6777378.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @bug 6777378
+ @summary NullPointerException in XPDefaultRenderer.paint()
+ @author Alexander Potochkin
+ @run main bug6777378
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import java.awt.event.MouseEvent;
+import java.awt.event.InputEvent;
+import java.awt.*;
+
+public class bug6777378 {
+ private static JFrame frame;
+ private static JTableHeader header;
+
+ public static void main(String[] args) throws Exception {
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ Robot robot = new Robot();
+ robot.setAutoDelay(20);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ UIManager.setLookAndFeel(new MetalLookAndFeel());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ JTable table = new JTable(new AbstractTableModel() {
+ public int getRowCount() {
+ return 10;
+ }
+
+ public int getColumnCount() {
+ return 10;
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return "" + rowIndex + " " + columnIndex;
+ }
+ });
+
+ header = new JTableHeader(table.getColumnModel());
+ header.setToolTipText("hello");
+
+ frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.add(header);
+
+ frame.setSize(300, 300);
+ frame.setVisible(true);
+ }
+ });
+ toolkit.realSync();
+ Point point = header.getLocationOnScreen();
+ robot.mouseMove(point.x + 20, point.y + 50);
+ robot.mouseMove(point.x + 30, point.y + 50);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4129681.html Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,10 @@
+<html>
+<body>
+When applet starts, you'll see a checkbox and a label with a titled border.
+Turn on the checkbox to disable the label.
+The test passes if the title of the border is disabled as well as the label.
+
+<applet width="300" height="200" code="Test4129681.class">
+</applet>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4129681.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4129681
+ * @summary Tests enabling/disabling of titled border's caption
+ * @author Sergey Malenkov
+ * @run applet/manual=yesno Test4129681.html
+ */
+
+import java.awt.BorderLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import javax.swing.BorderFactory;
+import javax.swing.JApplet;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+
+public class Test4129681 extends JApplet implements ItemListener {
+ private JLabel label;
+
+ @Override
+ public void init() {
+ JCheckBox check = new JCheckBox("disable");
+ check.addItemListener(this);
+
+ this.label = new JLabel("message");
+ this.label.setBorder(BorderFactory.createTitledBorder("label"));
+ this.label.setEnabled(!check.isSelected());
+
+ add(BorderLayout.NORTH, check);
+ add(BorderLayout.CENTER, this.label);
+ }
+
+ public void itemStateChanged(ItemEvent event) {
+ this.label.setEnabled(ItemEvent.DESELECTED == event.getStateChange());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4760089.html Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,10 @@
+<html>
+<body>
+When applet starts, you'll see a panel with a compound titled border.
+If one of its titles is overstriken with the border's line then test fails.
+Otherwise test passes.
+
+<applet width="600" height="300" code="Test4760089.class">
+</applet>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4760089.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4760089
+ * @summary Tests that titled border do not paint inner titled border over its caption
+ * @author Sergey Malenkov
+ * @run applet/manual=yesno Test4760089.html
+ */
+
+import javax.swing.JApplet;
+import javax.swing.JPanel;
+import javax.swing.border.Border;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+
+public class Test4760089 extends JApplet {
+ @Override
+ public void init() {
+ Border border = new EtchedBorder();
+ border = new TitledBorder(border, "LEFT", TitledBorder.LEFT, TitledBorder.TOP);
+ border = new TitledBorder(border, "RIGHT", TitledBorder.RIGHT, TitledBorder.TOP);
+
+ JPanel panel = new JPanel();
+ panel.setBorder(border);
+ getContentPane().add(panel);
+ }
+}
--- a/jdk/test/sun/nio/ch/Basic.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/ch/Basic.java Wed Jul 05 17:18:01 2017 +0200
@@ -32,5 +32,7 @@
public class Basic {
public static void main(String[] args) throws Exception {
Pipe p = Pipe.open();
+ p.source().close();
+ p.sink().close();
}
}
--- a/jdk/test/sun/nio/ch/TempBuffer.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/ch/TempBuffer.java Wed Jul 05 17:18:01 2017 +0200
@@ -54,8 +54,12 @@
blah.deleteOnExit();
TempBuffer.initTestFile(blah);
RandomAccessFile raf = new RandomAccessFile(blah, "rw");
- FileChannel fs = raf.getChannel();
- fs.transferTo(0, SIZE, Channels.newChannel(out));
+ FileChannel fc = raf.getChannel();
+ try {
+ fc.transferTo(0, SIZE, Channels.newChannel(out));
+ } finally {
+ fc.close();
+ }
out.flush();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
@@ -69,10 +73,17 @@
File blah = File.createTempFile("blah2", null);
blah.deleteOnExit();
RandomAccessFile raf = new RandomAccessFile(blah, "rw");
- FileChannel fs = raf.getChannel();
- raf.setLength(SIZE);
- fs.transferFrom(Channels.newChannel(in), 0, SIZE);
- fs.close();
+ FileChannel fc = raf.getChannel();
+ try {
+ raf.setLength(SIZE);
+ fc.transferFrom(Channels.newChannel(in), 0, SIZE);
+ } finally {
+ fc.close();
+ }
+
+ sourceChannel.close();
+ sinkChannel.close();
+ blah.delete();
}
private static void initTestFile(File blah) throws IOException {
--- a/jdk/test/sun/nio/cs/FindDecoderBugs.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/cs/FindDecoderBugs.java Wed Jul 05 17:18:01 2017 +0200
@@ -298,7 +298,7 @@
void testRandomly(byte[] prefix, int n) {
int len = prefix.length;
byte[] ia = Arrays.copyOf(prefix, len + n);
- for (int i = 0; i < 10000; i++) {
+ for (int i = 0; i < 5000; i++) {
for (int j = 0; j < n; j++)
ia[len + j] = randomByte();
test(ia);
@@ -435,6 +435,9 @@
static void equal(Object x, Object y) {
if (x == null ? y == null : x.equals(y)) pass();
else fail(x + " not equal to " + y);}
+ static void equal(int x, int y) {
+ if (x == y) pass();
+ else fail(x + " not equal to " + y);}
public static void main(String[] args) throws Throwable {
try {realMain(args);} catch (Throwable t) {unexpected(t);}
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
--- a/jdk/test/sun/nio/cs/ReadZero.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/cs/ReadZero.java Wed Jul 05 17:18:01 2017 +0200
@@ -43,15 +43,18 @@
return 0;
}
};
-
- is.read(new byte[1], 0, 1); // ok
- InputStreamReader isr = new InputStreamReader(is);
+ try {
+ is.read(new byte[1], 0, 1); // ok
+ InputStreamReader isr = new InputStreamReader(is);
- try {
- int res = isr.read(new char[1], 0, 1);
- } catch (IOException x) {
- System.out.println("IOException caught");
- return;
+ try {
+ int res = isr.read(new char[1], 0, 1);
+ } catch (IOException x) {
+ System.out.println("IOException caught");
+ return;
+ }
+ } finally {
+ is.close();
}
throw new RuntimeException("IOException not thrown");
}
--- a/jdk/test/sun/nio/cs/Test4206507.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/cs/Test4206507.java Wed Jul 05 17:18:01 2017 +0200
@@ -32,7 +32,12 @@
public class Test4206507 {
public static void main(String[] args) throws UnsupportedEncodingException {
- Locale.setDefault(new Locale("tr", "TR"));
- byte[] b = "".getBytes("ISO8859-9");
+ Locale l = Locale.getDefault();
+ try {
+ Locale.setDefault(new Locale("tr", "TR"));
+ byte[] b = "".getBytes("ISO8859-9");
+ } finally {
+ Locale.setDefault(l);
+ }
}
}
--- a/jdk/test/sun/nio/cs/TestStringCoding.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestStringCoding.java Wed Jul 05 17:18:01 2017 +0200
@@ -26,7 +26,7 @@
/* @test
@bug 6636323 6636319
@summary Test if StringCoding and NIO result have the same de/encoding result
- * @run main/timeout=2000 TestStringCoding
+ * @run main/othervm/timeout=2000 TestStringCoding
*/
import java.util.*;
--- a/jdk/test/sun/nio/cs/TestX11CNS.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestX11CNS.java Wed Jul 05 17:18:01 2017 +0200
@@ -94,6 +94,8 @@
}
static void compare(Charset newCS, Charset oldCS) throws Exception {
+ if (newCS == null)
+ return; // does not exist on this platform
char[] cc = getChars(newCS, oldCS);
System.out.printf(" Diff <%s> <%s>...%n", newCS.name(), oldCS.name());
@@ -120,14 +122,22 @@
}
}
+ private static Charset getCharset(String czName)
+ throws Exception {
+ try {
+ return (Charset)Class.forName(czName).newInstance();
+ } catch (ClassNotFoundException e){}
+ return null; // does not exist
+ }
+
public static void main(String[] args) throws Exception {
- compare(new sun.awt.motif.X11CNS11643P1(),
+ compare(getCharset("sun.awt.motif.X11CNS11643P1"),
new X11CNS11643P1());
- compare(new sun.awt.motif.X11CNS11643P2(),
+ compare(getCharset("sun.awt.motif.X11CNS11643P2"),
new X11CNS11643P2());
- compare(new sun.awt.motif.X11CNS11643P3(),
+ compare(getCharset("sun.awt.motif.X11CNS11643P3"),
new X11CNS11643P3());
}
--- a/jdk/test/sun/security/krb5/auto/SSL.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/security/krb5/auto/SSL.java Wed Jul 05 17:18:01 2017 +0200
@@ -25,6 +25,16 @@
* @test
* @bug 6894643 6913636
* @summary Test JSSE Kerberos ciphersuite
+ * @run main SSL TLS_KRB5_WITH_RC4_128_SHA
+ * @run main SSL TLS_KRB5_WITH_RC4_128_MD5
+ * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA
+ * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5
+ * @run main SSL TLS_KRB5_WITH_DES_CBC_SHA
+ * @run main SSL TLS_KRB5_WITH_DES_CBC_MD5
+ * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_SHA
+ * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_MD5
+ * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
+ * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
*/
import java.io.*;
import java.net.InetAddress;
@@ -37,7 +47,7 @@
public class SSL {
- private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
+ private static String krb5Cipher;
private static final int LOOP_LIMIT = 1;
private static int loopCount = 0;
private static volatile String server;
@@ -45,6 +55,8 @@
public static void main(String[] args) throws Exception {
+ krb5Cipher = args[0];
+
KDC kdc = KDC.create(OneKDC.REALM);
// Run this after KDC, so our own DNS service can be started
try {
@@ -117,7 +129,7 @@
SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(server, port);
// Enable only a KRB5 cipher suite.
- String enabledSuites[] = {KRB5_CIPHER};
+ String enabledSuites[] = {krb5Cipher};
sslSocket.setEnabledCipherSuites(enabledSuites);
// Should check for exception if enabledSuites is not supported
@@ -155,7 +167,7 @@
port = sslServerSocket.getLocalPort();
// Enable only a KRB5 cipher suite.
- String enabledSuites[] = {KRB5_CIPHER};
+ String enabledSuites[] = {krb5Cipher};
sslServerSocket.setEnabledCipherSuites(enabledSuites);
// Should check for exception if enabledSuites is not supported
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/etype/ETypeOrder.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 6844907
+ * @summary krb5 etype order should be from strong to weak
+ */
+
+import sun.security.krb5.internal.crypto.EType;
+
+public class ETypeOrder {
+ public static void main(String[] args) throws Exception {
+
+ // File does not exist, so that the system-default one won't be used
+ System.setProperty("java.security.krb5.conf", "no_such_file");
+ int[] etypes = EType.getBuiltInDefaults();
+
+ // Reference order, note that 2 is not implemented in Java
+ int correct[] = { 18, 17, 16, 23, 1, 3, 2 };
+
+ int match = 0;
+ loopi: for (int i=0; i<etypes.length; i++) {
+ for (; match < correct.length; match++) {
+ if (etypes[i] == correct[match]) {
+ System.out.println("Find " + etypes[i] + " at #" + match);
+ continue loopi;
+ }
+ }
+ throw new Exception("No match or bad order for " + etypes[i]);
+ }
+ }
+}
--- a/jdk/test/sun/security/krb5/ktab/HighestKvno.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/sun/security/krb5/ktab/HighestKvno.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,9 +227,6 @@
if (keys[0].getKeyVersionNumber() != 5) {
throw new Exception("Highest not first");
}
- if (ktab.readServiceKey(pn).getKeyVersionNumber() != 5) {
- throw new Exception("Highest not chosen");
- }
new File("kt").delete();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs12/PKCS12SameKeyId.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6958026
+ * @summary Problem with PKCS12 keystore
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.AlgorithmParameters;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import sun.security.pkcs.EncryptedPrivateKeyInfo;
+import sun.security.tools.KeyTool;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.X500Name;
+
+public class PKCS12SameKeyId {
+
+ private static final String JKSFILE = "PKCS12SameKeyId.jks";
+ private static final String P12FILE = "PKCS12SameKeyId.p12";
+ private static final char[] PASSWORD = "changeit".toCharArray();
+ private static final int SIZE = 10;
+
+ public static void main(String[] args) throws Exception {
+
+ // Prepare a JKS keystore with many entries
+ new File(JKSFILE).delete();
+ for (int i=0; i<SIZE; i++) {
+ System.err.print(".");
+ String cmd = "-keystore " + JKSFILE
+ + " -storepass changeit -keypass changeit "
+ + "-genkeypair -alias p" + i + " -dname CN=" + i;
+ KeyTool.main(cmd.split(" "));
+ }
+
+ // Prepare EncryptedPrivateKeyInfo parameters, copied from various
+ // places in PKCS12KeyStore.java
+ AlgorithmParameters algParams =
+ AlgorithmParameters.getInstance("PBEWithSHA1AndDESede");
+ algParams.init(new PBEParameterSpec("12345678".getBytes(), 1024));
+ AlgorithmId algid = new AlgorithmId(
+ new ObjectIdentifier("1.2.840.113549.1.12.1.3"), algParams);
+
+ PBEKeySpec keySpec = new PBEKeySpec(PASSWORD);
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+ SecretKey skey = skFac.generateSecret(keySpec);
+
+ Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
+ cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
+
+ // Pre-calculated keys and certs and aliases
+ byte[][] keys = new byte[SIZE][];
+ Certificate[][] certChains = new Certificate[SIZE][];
+ String[] aliases = new String[SIZE];
+
+ // Reads from JKS keystore and pre-calculate
+ KeyStore ks = KeyStore.getInstance("jks");
+ ks.load(new FileInputStream(JKSFILE), PASSWORD);
+ for (int i=0; i<SIZE; i++) {
+ aliases[i] = "p" + i;
+ byte[] enckey = cipher.doFinal(
+ ks.getKey(aliases[i], PASSWORD).getEncoded());
+ keys[i] = new EncryptedPrivateKeyInfo(algid, enckey).getEncoded();
+ certChains[i] = ks.getCertificateChain(aliases[i]);
+ }
+
+ // Write into PKCS12 keystore. Use this overloaded version of
+ // setKeyEntry() to be as fast as possible, so that they would
+ // have same localKeyId.
+ KeyStore p12 = KeyStore.getInstance("pkcs12");
+ p12.load(null, PASSWORD);
+ for (int i=0; i<SIZE; i++) {
+ p12.setKeyEntry(aliases[i], keys[i], certChains[i]);
+ }
+ p12.store(new FileOutputStream(P12FILE), PASSWORD);
+
+ // Check private keys still match certs
+ p12 = KeyStore.getInstance("pkcs12");
+ p12.load(new FileInputStream(P12FILE), PASSWORD);
+ for (int i=0; i<SIZE; i++) {
+ String a = "p" + i;
+ X509Certificate x = (X509Certificate)p12.getCertificate(a);
+ X500Name name = (X500Name)x.getSubjectDN();
+ if (!name.getCommonName().equals(""+i)) {
+ throw new Exception(a + "'s cert is " + name);
+ }
+ }
+ }
+}
--- a/jdk/test/tools/launcher/Arrrghs.java Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java Wed Jul 05 17:18:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881
+ * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
* @summary Argument parsing validation.
* @compile -XDignore.symbol.file Arrrghs.java TestHelper.java
* @run main Arrrghs
@@ -223,6 +223,20 @@
tr.checkPositive();
tr.isNotZeroOutput();
System.out.println(tr);
+
+ // 6753938, test for non-negative exit value for an incorrectly formed
+ // command line, '% java'
+ tr = TestHelper.doExec(TestHelper.javaCmd);
+ tr.checkNegative();
+ tr.isNotZeroOutput();
+ System.out.println(tr);
+
+ // 6753938, test for non-negative exit value for an incorrectly formed
+ // command line, '% java -Xcomp'
+ tr = TestHelper.doExec(TestHelper.javaCmd, "-Xcomp");
+ tr.checkNegative();
+ tr.isNotZeroOutput();
+ System.out.println(tr);
}
/*
--- a/jdk/test/tools/launcher/Makefile.SolarisRunpath Tue Jul 20 22:17:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-
-#
-
-# This is a not quite automated Makefile to generate the Solaris
-# binaries used for the SolarisRunpath.sh test. First,
-# libraryCaller.java program must be compiled. Next, javah is called
-# on the class file to generate the needed header file for the jni
-# code. Then, 2 Solaris executables are generated in separate
-# directories, a default one meant to be pointed to by LD_LIBRARY_PATH
-# (this function returns 0) and another one for the data model
-# specific LD_LIBRARY_PATH (this function returns the size of integers
-# in the data model, 32 or 64). A better makefile would run, say
-# isainfo -v, and generated binaries for all supported data models.
-# To do this a mapping would be needed from data models to
-# architecture dependent compiler options; e.g. 64 bit on sparc =>
-# -xarch=v9. Also, the settings for JINCLUDE, JAVAC, and JAVAH should
-# come from the current build. The C compiler should be the one
-# approved for the build. To be extra safe, the binaries should be
-# generated on the oldest Solaris release supported by the current
-# Java build.
-
-# Include directory in JRE or JDK install; e.g.
-JINCLUDE=/java/re/jdk/1.4.1/latest/binaries/solaris-sparc/include
-
-# Path to javac executable; e.g.
-JAVAC=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javac
-
-# Path to javah executable; e.g.
-JAVAH=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javah
-
-# Path to C compiler; e.g.
-CC=/java/devtools/sparc/SUNWspro/SC6.1/bin/cc
-
-
-ARCH=`uname -p`
-
-# 32-bit Solaris Options
-DM=32
-# Default architecture is fine for both sparc and x86 32-bit builds
-OPTIONS=
-
-# 64-bit Solaris Options
-#DM=64
-#OPTIONS=-xarch=v9
-
-
-all: libraryCaller.java libraryCaller.c
- $(JAVAC) libraryCaller.java; \
- $(JAVAH) libraryCaller; \
- $(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=0 \
- $(OPTIONS) libraryCaller.c \
- -o lib/$(ARCH)/lib$(DM)/liblibrary.so; \
- $(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=$(DM)\
- $(OPTIONS) libraryCaller.c \
- -o lib/$(ARCH)/lib$(DM)/lib$(DM)/liblibrary.so;
--- a/jdk/test/tools/launcher/UnicodeTest.sh Tue Jul 20 22:17:33 2010 -0700
+++ b/jdk/test/tools/launcher/UnicodeTest.sh Wed Jul 05 17:18:01 2017 +0200
@@ -54,7 +54,11 @@
echo "creating test source files"
"$JAVAC" -d . "${TESTSRC}"/UnicodeTest.java
-CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' `
+if [ "`uname -s | grep CYGWIN`" != "" ] ; then
+ CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' `
+else
+ CLASS_NAME=`"$JAVA" UnicodeTest`
+fi
if [ "$CLASS_NAME" = "" ]
then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/VerifyExceptions.java Wed Jul 05 17:18:01 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6856415
+ * @summary Checks to ensure that proper exceptions are thrown by java
+ * @compile -XDignore.symbol.file VerifyExceptions.java TestHelper.java
+ * @run main VerifyExceptions
+ */
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+
+public class VerifyExceptions {
+
+ static void test6856415() {
+ // No pkcs library on win-x64, so we bail out.
+ if (TestHelper.is64Bit && TestHelper.isWindows) {
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("public static void main(String... args) {\n");
+ sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11(args[0]);\n");
+ sb.append("java.security.Security.insertProviderAt(p, 1);\n");
+ sb.append("}");
+ File testJar = new File("Foo.jar");
+ testJar.delete();
+ try {
+ TestHelper.createJar(testJar, sb.toString());
+ } catch (FileNotFoundException fnfe) {
+ throw new RuntimeException(fnfe);
+ }
+ TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javacCmd,
+ "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
+ tr.checkNegative();
+ tr.contains("Exception in thread \"main\" java.security.AccessControlException: access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.security.pkcs11\")\")");
+ }
+
+ public static void main(String... args) {
+ test6856415();
+ }
+}
Binary file jdk/test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/i386/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/liblibrary.so has changed