mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 04:24:49 +02:00
Merge
This commit is contained in:
commit
673cb7c129
213 changed files with 4368 additions and 2010 deletions
2
.hgtags
2
.hgtags
|
@ -77,3 +77,5 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99
|
||||||
2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100
|
2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100
|
||||||
2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101
|
2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101
|
||||||
88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102
|
88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102
|
||||||
|
64770970865839b0443066370e7d476ef47e90cd jdk7-b103
|
||||||
|
10bc903a228d3a8efdf46fb8c3fcf82a59b88bc5 jdk7-b104
|
||||||
|
|
|
@ -77,3 +77,5 @@ e7f18db469a3e947b7096bfd12e87380e5a042cd jdk7-b99
|
||||||
b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100
|
b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100
|
||||||
4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101
|
4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101
|
||||||
a136a51f5113da4dad3853b74a8536ab583ab112 jdk7-b102
|
a136a51f5113da4dad3853b74a8536ab583ab112 jdk7-b102
|
||||||
|
be2aedc4e3b1751c1310f334242ba69e90867f38 jdk7-b103
|
||||||
|
f8be576feefce0c6695f188ef97ec16b73ad9cfd jdk7-b104
|
||||||
|
|
|
@ -77,3 +77,5 @@ edc2a2659c77dabc55cb55bb617bad89e3a05bb3 jdk7-b96
|
||||||
a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
|
a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
|
||||||
86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101
|
86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101
|
||||||
78561a95779090b5106c8d0f1a75360a027ef087 jdk7-b102
|
78561a95779090b5106c8d0f1a75360a027ef087 jdk7-b102
|
||||||
|
11e7678c3eb169b77d9a9892fe5e3dfa1d1a0d51 jdk7-b103
|
||||||
|
9607213481d400ac477183191cc080e1bef6f475 jdk7-b104
|
||||||
|
|
|
@ -107,3 +107,6 @@ ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100
|
||||||
6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101
|
6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101
|
||||||
ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03
|
ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03
|
||||||
c5cadf1a07717955cf60dbaec16e35b529fd2cb0 jdk7-b102
|
c5cadf1a07717955cf60dbaec16e35b529fd2cb0 jdk7-b102
|
||||||
|
cb4250ef73b21de6c487ea14e2b0b99eed67b4b6 jdk7-b103
|
||||||
|
e55900b5c1b865cac17e18abc639c7dc50de7fd8 hs19-b04
|
||||||
|
b4acf10eb134fe930802c97e36db65e7ccb544b5 jdk7-b104
|
||||||
|
|
|
@ -297,6 +297,7 @@ public class ConstantPool extends Oop implements ClassConstants {
|
||||||
case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";
|
case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";
|
||||||
case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
|
case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
|
||||||
case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
|
case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
|
||||||
|
case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic";
|
||||||
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
|
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
|
||||||
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
|
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
|
||||||
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
||||||
|
@ -355,6 +356,7 @@ public class ConstantPool extends Oop implements ClassConstants {
|
||||||
case JVM_CONSTANT_NameAndType:
|
case JVM_CONSTANT_NameAndType:
|
||||||
case JVM_CONSTANT_MethodHandle:
|
case JVM_CONSTANT_MethodHandle:
|
||||||
case JVM_CONSTANT_MethodType:
|
case JVM_CONSTANT_MethodType:
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
|
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -517,6 +519,18 @@ public class ConstantPool extends Oop implements ClassConstants {
|
||||||
+ ", type = " + signatureIndex);
|
+ ", type = " + signatureIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_InvokeDynamic: {
|
||||||
|
dos.writeByte(cpConstType);
|
||||||
|
int value = getIntAt(ci);
|
||||||
|
short bootstrapMethodIndex = (short) extractLowShortFromInt(value);
|
||||||
|
short nameAndTypeIndex = (short) extractHighShortFromInt(value);
|
||||||
|
dos.writeShort(bootstrapMethodIndex);
|
||||||
|
dos.writeShort(nameAndTypeIndex);
|
||||||
|
if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex
|
||||||
|
+ ", N&T = " + nameAndTypeIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new InternalError("unknown tag: " + cpConstType);
|
throw new InternalError("unknown tag: " + cpConstType);
|
||||||
} // switch
|
} // switch
|
||||||
|
|
|
@ -42,6 +42,7 @@ public interface ClassConstants
|
||||||
public static final int JVM_CONSTANT_NameAndType = 12;
|
public static final int JVM_CONSTANT_NameAndType = 12;
|
||||||
public static final int JVM_CONSTANT_MethodHandle = 15;
|
public static final int JVM_CONSTANT_MethodHandle = 15;
|
||||||
public static final int JVM_CONSTANT_MethodType = 16;
|
public static final int JVM_CONSTANT_MethodType = 16;
|
||||||
|
public static final int JVM_CONSTANT_InvokeDynamic = 17;
|
||||||
|
|
||||||
// JVM_CONSTANT_MethodHandle subtypes
|
// JVM_CONSTANT_MethodHandle subtypes
|
||||||
public static final int JVM_REF_getField = 1;
|
public static final int JVM_REF_getField = 1;
|
||||||
|
|
|
@ -303,12 +303,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
||||||
case JVM_CONSTANT_MethodHandle: {
|
case JVM_CONSTANT_MethodHandle: {
|
||||||
dos.writeByte(cpConstType);
|
dos.writeByte(cpConstType);
|
||||||
int value = cpool.getIntAt(ci);
|
int value = cpool.getIntAt(ci);
|
||||||
short refIndex = (short) extractHighShortFromInt(value);
|
short bootstrapMethodIndex = (short) extractLowShortFromInt(value);
|
||||||
byte refKind = (byte) extractLowShortFromInt(value);
|
short nameAndTypeIndex = (short) extractHighShortFromInt(value);
|
||||||
dos.writeByte(refKind);
|
dos.writeShort(bootstrapMethodIndex);
|
||||||
dos.writeShort(refIndex);
|
dos.writeShort(nameAndTypeIndex);
|
||||||
if (DEBUG) debugMessage("CP[" + ci + "] = MH index = " + refIndex
|
if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " +
|
||||||
+ ", kind = " + refKind);
|
bootstrapMethodIndex + ", N&T = " + nameAndTypeIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +321,15 @@ public class ClassWriter implements /* imports */ ClassConstants
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_InvokeDynamic: {
|
||||||
|
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:
|
default:
|
||||||
throw new InternalError("Unknown tag: " + cpConstType);
|
throw new InternalError("Unknown tag: " + cpConstType);
|
||||||
} // switch
|
} // switch
|
||||||
|
|
|
@ -582,6 +582,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||||
buf.cell(Integer.toString(cpool.getIntAt(index)));
|
buf.cell(Integer.toString(cpool.getIntAt(index)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
|
buf.cell("JVM_CONSTANT_InvokeDynamic");
|
||||||
|
buf.cell(genLowHighShort(cpool.getIntAt(index)));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InternalError("unknown tag: " + ctag);
|
throw new InternalError("unknown tag: " + ctag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class ConstantTag {
|
||||||
private static int JVM_CONSTANT_NameAndType = 12;
|
private static int JVM_CONSTANT_NameAndType = 12;
|
||||||
private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
|
private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
|
||||||
private static int JVM_CONSTANT_MethodType = 16; // JSR 292
|
private static int JVM_CONSTANT_MethodType = 16; // JSR 292
|
||||||
|
private static int JVM_CONSTANT_InvokeDynamic = 17; // JSR 292
|
||||||
private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
|
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_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_ClassIndex = 101; // Temporary tag while constructing constant pool
|
||||||
|
@ -78,6 +79,7 @@ public class ConstantTag {
|
||||||
public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; }
|
public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; }
|
||||||
public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
|
public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
|
||||||
public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
|
public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
|
||||||
|
public boolean isInvokeDynamic() { return tag == JVM_CONSTANT_InvokeDynamic; }
|
||||||
|
|
||||||
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
|
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2010
|
||||||
|
|
||||||
HS_MAJOR_VER=19
|
HS_MAJOR_VER=19
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=04
|
HS_BUILD_NUMBER=05
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=7
|
JDK_MINOR_VER=7
|
||||||
|
|
|
@ -1007,9 +1007,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp));
|
__ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp));
|
||||||
__ delayed()->cmp(to_from, byte_count);
|
__ delayed()->cmp(to_from, byte_count);
|
||||||
if (NOLp == NULL)
|
if (NOLp == NULL)
|
||||||
__ brx(Assembler::greaterEqual, false, Assembler::pt, no_overlap_target);
|
__ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target);
|
||||||
else
|
else
|
||||||
__ brx(Assembler::greaterEqual, false, Assembler::pt, (*NOLp));
|
__ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp));
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -728,8 +728,8 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the invoker methodOop from the constant pool.
|
// Get the invoker methodOop from the constant pool.
|
||||||
intptr_t f2_value = cpool->cache()->main_entry_at(index)->f2();
|
oop f1_value = cpool->cache()->main_entry_at(index)->f1();
|
||||||
methodOop signature_invoker = methodOop(f2_value);
|
methodOop signature_invoker = methodOop(f1_value);
|
||||||
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
||||||
"correct result from LinkResolver::resolve_invokedynamic");
|
"correct result from LinkResolver::resolve_invokedynamic");
|
||||||
|
|
||||||
|
|
|
@ -694,30 +694,21 @@ int ciMethod::scale_count(int count, float prof_factor) {
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciMethod::is_method_handle_invoke
|
// ciMethod::is_method_handle_invoke
|
||||||
//
|
//
|
||||||
// Return true if the method is a MethodHandle target.
|
// Return true if the method is an instance of one of the two
|
||||||
|
// signature-polymorphic MethodHandle methods, invokeExact or invokeGeneric.
|
||||||
bool ciMethod::is_method_handle_invoke() const {
|
bool ciMethod::is_method_handle_invoke() const {
|
||||||
bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() &&
|
if (!is_loaded()) return false;
|
||||||
methodOopDesc::is_method_handle_invoke_name(name()->sid()));
|
VM_ENTRY_MARK;
|
||||||
#ifdef ASSERT
|
return get_methodOop()->is_method_handle_invoke();
|
||||||
if (is_loaded()) {
|
|
||||||
bool flag2 = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
|
||||||
{
|
|
||||||
VM_ENTRY_MARK;
|
|
||||||
bool flag3 = get_methodOop()->is_method_handle_invoke();
|
|
||||||
assert(flag2 == flag3, "consistent");
|
|
||||||
assert(flag == flag3, "consistent");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //ASSERT
|
|
||||||
return flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciMethod::is_method_handle_adapter
|
// ciMethod::is_method_handle_adapter
|
||||||
//
|
//
|
||||||
// Return true if the method is a generated MethodHandle adapter.
|
// Return true if the method is a generated MethodHandle adapter.
|
||||||
|
// These are built by MethodHandleCompiler.
|
||||||
bool ciMethod::is_method_handle_adapter() const {
|
bool ciMethod::is_method_handle_adapter() const {
|
||||||
check_is_loaded();
|
if (!is_loaded()) return false;
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
return get_methodOop()->is_method_handle_adapter();
|
return get_methodOop()->is_method_handle_adapter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
|
||||||
if (!EnableMethodHandles ||
|
if (!EnableMethodHandles ||
|
||||||
_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
||||||
classfile_parse_error(
|
classfile_parse_error(
|
||||||
(!EnableInvokeDynamic ?
|
(!EnableMethodHandles ?
|
||||||
"This JVM does not support constant tag %u in class file %s" :
|
"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"),
|
"Class file version does not support constant tag %u in class file %s"),
|
||||||
tag, CHECK);
|
tag, CHECK);
|
||||||
|
@ -140,6 +140,22 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_InvokeDynamic :
|
||||||
|
{
|
||||||
|
if (!EnableInvokeDynamic ||
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags
|
||||||
|
u2 bootstrap_method_index = cfs->get_u2_fast();
|
||||||
|
u2 name_and_type_index = cfs->get_u2_fast();
|
||||||
|
cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case JVM_CONSTANT_Integer :
|
case JVM_CONSTANT_Integer :
|
||||||
{
|
{
|
||||||
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
|
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
|
||||||
|
@ -414,6 +430,24 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
|
||||||
ref_index, CHECK_(nullHandle));
|
ref_index, CHECK_(nullHandle));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_InvokeDynamic :
|
||||||
|
{
|
||||||
|
int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
|
||||||
|
int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index);
|
||||||
|
check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292)
|
||||||
|
||
|
||||||
|
(valid_cp_range(bootstrap_method_ref_index, length) &&
|
||||||
|
cp->tag_at(bootstrap_method_ref_index).is_method_handle()),
|
||||||
|
"Invalid constant pool index %u in class file %s",
|
||||||
|
bootstrap_method_ref_index,
|
||||||
|
CHECK_(nullHandle));
|
||||||
|
check_property(valid_cp_range(name_and_type_ref_index, length) &&
|
||||||
|
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
|
||||||
|
"Invalid constant pool index %u in class file %s",
|
||||||
|
name_and_type_ref_index,
|
||||||
|
CHECK_(nullHandle));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fatal(err_msg("bad constant pool tag value %u",
|
fatal(err_msg("bad constant pool tag value %u",
|
||||||
cp->tag_at(index).value()));
|
cp->tag_at(index).value()));
|
||||||
|
|
|
@ -2507,6 +2507,10 @@ Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method,
|
||||||
int caller_bci,
|
int caller_bci,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
Handle empty;
|
Handle empty;
|
||||||
|
guarantee(bootstrap_method.not_null() &&
|
||||||
|
java_dyn_MethodHandle::is_instance(bootstrap_method()),
|
||||||
|
"caller must supply a valid BSM");
|
||||||
|
|
||||||
Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
|
Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
|
||||||
MethodHandles::init_MemberName(caller_mname(), caller_method());
|
MethodHandles::init_MemberName(caller_mname(), caller_method());
|
||||||
|
|
||||||
|
@ -2537,20 +2541,61 @@ Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method,
|
||||||
return call_site_oop;
|
return call_site_oop;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) {
|
Handle SystemDictionary::find_bootstrap_method(methodHandle caller_method, int caller_bci,
|
||||||
|
int cache_index, TRAPS) {
|
||||||
Handle empty;
|
Handle empty;
|
||||||
if (!caller->oop_is_instance()) return empty;
|
|
||||||
|
|
||||||
instanceKlassHandle ik(THREAD, caller());
|
constantPoolHandle pool;
|
||||||
|
{
|
||||||
|
klassOop caller = caller_method->method_holder();
|
||||||
|
if (!Klass::cast(caller)->oop_is_instance()) return empty;
|
||||||
|
pool = constantPoolHandle(THREAD, instanceKlass::cast(caller)->constants());
|
||||||
|
}
|
||||||
|
|
||||||
oop boot_method_oop = ik->bootstrap_method();
|
int constant_pool_index = pool->cache()->entry_at(cache_index)->constant_pool_index();
|
||||||
if (boot_method_oop != NULL) {
|
constantTag tag = pool->tag_at(constant_pool_index);
|
||||||
if (TraceMethodHandles) {
|
|
||||||
tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop);
|
if (tag.is_invoke_dynamic()) {
|
||||||
|
// JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type]
|
||||||
|
// The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
|
||||||
|
int bsm_index = pool->invoke_dynamic_bootstrap_method_ref_index_at(constant_pool_index);
|
||||||
|
if (bsm_index != 0) {
|
||||||
|
int bsm_index_in_cache = pool->cache()->entry_at(cache_index)->bootstrap_method_index_in_cache();
|
||||||
|
DEBUG_ONLY(int bsm_index_2 = pool->cache()->entry_at(bsm_index_in_cache)->constant_pool_index());
|
||||||
|
assert(bsm_index == bsm_index_2, "BSM constant lifted to cache");
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print_cr("resolving bootstrap method for "PTR_FORMAT" at %d at cache[%d]CP[%d]...",
|
||||||
|
(intptr_t) caller_method(), caller_bci, cache_index, constant_pool_index);
|
||||||
|
}
|
||||||
|
oop bsm_oop = pool->resolve_cached_constant_at(bsm_index_in_cache, CHECK_(empty));
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print_cr("bootstrap method for "PTR_FORMAT" at %d retrieved as "PTR_FORMAT":",
|
||||||
|
(intptr_t) caller_method(), caller_bci, (intptr_t) bsm_oop);
|
||||||
|
}
|
||||||
|
assert(bsm_oop->is_oop()
|
||||||
|
&& java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane");
|
||||||
|
return Handle(THREAD, bsm_oop);
|
||||||
}
|
}
|
||||||
assert(boot_method_oop->is_oop()
|
// else null BSM; fall through
|
||||||
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
|
} else if (tag.is_name_and_type()) {
|
||||||
return Handle(THREAD, boot_method_oop);
|
// JSR 292 EDR does not have JVM_CONSTANT_InvokeDynamic
|
||||||
|
// a bare name&type defaults its BSM to null, so fall through...
|
||||||
|
} else {
|
||||||
|
ShouldNotReachHere(); // verifier does not allow this
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall through to pick up the per-class bootstrap method.
|
||||||
|
// This mechanism may go away in the PFD.
|
||||||
|
assert(AllowTransitionalJSR292, "else the verifier should have stopped us already");
|
||||||
|
oop bsm_oop = instanceKlass::cast(caller_method->method_holder())->bootstrap_method();
|
||||||
|
if (bsm_oop != NULL) {
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print_cr("bootstrap method for "PTR_FORMAT" registered as "PTR_FORMAT":",
|
||||||
|
(intptr_t) caller_method(), (intptr_t) bsm_oop);
|
||||||
|
}
|
||||||
|
assert(bsm_oop->is_oop()
|
||||||
|
&& java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane");
|
||||||
|
return Handle(THREAD, bsm_oop);
|
||||||
}
|
}
|
||||||
|
|
||||||
return empty;
|
return empty;
|
||||||
|
|
|
@ -492,7 +492,10 @@ public:
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
// coordinate with Java about bootstrap methods
|
// coordinate with Java about bootstrap methods
|
||||||
static Handle find_bootstrap_method(KlassHandle caller, TRAPS);
|
static Handle find_bootstrap_method(methodHandle caller_method,
|
||||||
|
int caller_bci, // N.B. must be an invokedynamic
|
||||||
|
int cache_index, // must be corresponding main_entry
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
// Utility for printing loader "name" as part of tracing constraints
|
// Utility for printing loader "name" as part of tracing constraints
|
||||||
static const char* loader_name(oop loader) {
|
static const char* loader_name(oop loader) {
|
||||||
|
|
|
@ -1913,7 +1913,8 @@ void ClassVerifier::verify_invoke_instructions(
|
||||||
unsigned int types = (opcode == Bytecodes::_invokeinterface
|
unsigned int types = (opcode == Bytecodes::_invokeinterface
|
||||||
? 1 << JVM_CONSTANT_InterfaceMethodref
|
? 1 << JVM_CONSTANT_InterfaceMethodref
|
||||||
: opcode == Bytecodes::_invokedynamic
|
: opcode == Bytecodes::_invokedynamic
|
||||||
? 1 << JVM_CONSTANT_NameAndType
|
? (1 << JVM_CONSTANT_NameAndType
|
||||||
|
|1 << JVM_CONSTANT_InvokeDynamic)
|
||||||
: 1 << JVM_CONSTANT_Methodref);
|
: 1 << JVM_CONSTANT_Methodref);
|
||||||
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
|
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,11 @@ void BufferBlob::free( BufferBlob *blob ) {
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Implementation of AdapterBlob
|
// Implementation of AdapterBlob
|
||||||
|
|
||||||
|
AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) :
|
||||||
|
BufferBlob("I2C/C2I adapters", size, cb) {
|
||||||
|
CodeCache::commit(this);
|
||||||
|
}
|
||||||
|
|
||||||
AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
|
AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
|
||||||
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
|
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
|
||||||
|
|
||||||
|
@ -210,7 +215,6 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
|
||||||
{
|
{
|
||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
blob = new (size) AdapterBlob(size, cb);
|
blob = new (size) AdapterBlob(size, cb);
|
||||||
CodeCache::commit(blob);
|
|
||||||
}
|
}
|
||||||
// Track memory usage statistic after releasing CodeCache_lock
|
// Track memory usage statistic after releasing CodeCache_lock
|
||||||
MemoryService::track_code_cache_memory_usage();
|
MemoryService::track_code_cache_memory_usage();
|
||||||
|
|
|
@ -219,8 +219,7 @@ class BufferBlob: public CodeBlob {
|
||||||
|
|
||||||
class AdapterBlob: public BufferBlob {
|
class AdapterBlob: public BufferBlob {
|
||||||
private:
|
private:
|
||||||
AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {}
|
AdapterBlob(int size, CodeBuffer* cb);
|
||||||
AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Creation
|
// Creation
|
||||||
|
|
|
@ -664,19 +664,14 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX use a global constant instead of 64!
|
typedef Padded<OopTaskQueue> PaddedOopTaskQueue;
|
||||||
typedef struct OopTaskQueuePadded {
|
|
||||||
OopTaskQueue work_queue;
|
|
||||||
char pad[64 - sizeof(OopTaskQueue)]; // prevent false sharing
|
|
||||||
} OopTaskQueuePadded;
|
|
||||||
|
|
||||||
for (i = 0; i < num_queues; i++) {
|
for (i = 0; i < num_queues; i++) {
|
||||||
OopTaskQueuePadded *q_padded = new OopTaskQueuePadded();
|
PaddedOopTaskQueue *q = new PaddedOopTaskQueue();
|
||||||
if (q_padded == NULL) {
|
if (q == NULL) {
|
||||||
warning("work_queue allocation failure.");
|
warning("work_queue allocation failure.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_task_queues->register_queue(i, &q_padded->work_queue);
|
_task_queues->register_queue(i, q);
|
||||||
}
|
}
|
||||||
for (i = 0; i < num_queues; i++) {
|
for (i = 0; i < num_queues; i++) {
|
||||||
_task_queues->queue(i)->initialize();
|
_task_queues->queue(i)->initialize();
|
||||||
|
|
|
@ -234,6 +234,11 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
if (_gc_cause != GCCause::_gc_locker &&
|
if (_gc_cause != GCCause::_gc_locker &&
|
||||||
gch->total_full_collections_completed() <= _full_gc_count_before) {
|
gch->total_full_collections_completed() <= _full_gc_count_before) {
|
||||||
|
// maybe we should change the condition to test _gc_cause ==
|
||||||
|
// GCCause::_java_lang_system_gc, instead of
|
||||||
|
// _gc_cause != GCCause::_gc_locker
|
||||||
|
assert(_gc_cause == GCCause::_java_lang_system_gc,
|
||||||
|
"the only way to get here if this was a System.gc()-induced GC");
|
||||||
assert(ExplicitGCInvokesConcurrent, "Error");
|
assert(ExplicitGCInvokesConcurrent, "Error");
|
||||||
// Now, wait for witnessing concurrent gc cycle to complete,
|
// Now, wait for witnessing concurrent gc cycle to complete,
|
||||||
// but do so in native mode, because we want to lock the
|
// but do so in native mode, because we want to lock the
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -271,21 +271,16 @@ jbyte* ConcurrentG1Refine::add_card_count(jbyte* card_ptr, int* count, bool* def
|
||||||
if (cas_res == prev_epoch_entry) {
|
if (cas_res == prev_epoch_entry) {
|
||||||
// We successfully updated the card num value in the epoch entry
|
// We successfully updated the card num value in the epoch entry
|
||||||
count_ptr->_count = 0; // initialize counter for new card num
|
count_ptr->_count = 0; // initialize counter for new card num
|
||||||
|
jbyte* old_card_ptr = card_num_2_ptr(old_card_num);
|
||||||
|
|
||||||
// Even though the region containg the card at old_card_num was not
|
// Even though the region containg the card at old_card_num was not
|
||||||
// in the young list when old_card_num was recorded in the epoch
|
// in the young list when old_card_num was recorded in the epoch
|
||||||
// cache it could have been added to the free list and subsequently
|
// cache it could have been added to the free list and subsequently
|
||||||
// added to the young list in the intervening time. If the evicted
|
// added to the young list in the intervening time. See CR 6817995.
|
||||||
// card is in a young region just return the card_ptr and the evicted
|
// We do not deal with this case here - it will be handled in
|
||||||
// card will not be cleaned. See CR 6817995.
|
// HeapRegion::oops_on_card_seq_iterate_careful after it has been
|
||||||
|
// determined that the region containing the card has been allocated
|
||||||
jbyte* old_card_ptr = card_num_2_ptr(old_card_num);
|
// to, and it's safe to check the young type of the region.
|
||||||
if (is_young_card(old_card_ptr)) {
|
|
||||||
*count = 0;
|
|
||||||
// We can defer the processing of card_ptr
|
|
||||||
*defer = true;
|
|
||||||
return card_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do not want to defer processing of card_ptr in this case
|
// We do not want to defer processing of card_ptr in this case
|
||||||
// (we need to refine old_card_ptr and card_ptr)
|
// (we need to refine old_card_ptr and card_ptr)
|
||||||
|
@ -301,22 +296,22 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) {
|
||||||
jbyte* cached_ptr = add_card_count(card_ptr, &count, defer);
|
jbyte* cached_ptr = add_card_count(card_ptr, &count, defer);
|
||||||
assert(cached_ptr != NULL, "bad cached card ptr");
|
assert(cached_ptr != NULL, "bad cached card ptr");
|
||||||
|
|
||||||
if (is_young_card(cached_ptr)) {
|
// We've just inserted a card pointer into the card count cache
|
||||||
// The region containing cached_ptr has been freed during a clean up
|
// and got back the card that we just inserted or (evicted) the
|
||||||
// pause, reallocated, and tagged as young.
|
// previous contents of that count slot.
|
||||||
assert(cached_ptr != card_ptr, "shouldn't be");
|
|
||||||
|
|
||||||
// We've just inserted a new old-gen card pointer into the card count
|
// The card we got back could be in a young region. When the
|
||||||
// cache and evicted the previous contents of that count slot.
|
// returned card (if evicted) was originally inserted, we had
|
||||||
// The evicted card pointer has been determined to be in a young region
|
// determined that its containing region was not young. However
|
||||||
// and so cannot be the newly inserted card pointer (that will be
|
// it is possible for the region to be freed during a cleanup
|
||||||
// in an old region).
|
// pause, then reallocated and tagged as young which will result
|
||||||
// The count for newly inserted card will be set to zero during the
|
// in the returned card residing in a young region.
|
||||||
// insertion, so we don't want to defer the cleaning of the newly
|
//
|
||||||
// inserted card pointer.
|
// We do not deal with this case here - the change from non-young
|
||||||
assert(*defer == false, "deferring non-hot card");
|
// to young could be observed at any time - it will be handled in
|
||||||
return NULL;
|
// HeapRegion::oops_on_card_seq_iterate_careful after it has been
|
||||||
}
|
// determined that the region containing the card has been allocated
|
||||||
|
// to.
|
||||||
|
|
||||||
// The card pointer we obtained from card count cache is not hot
|
// The card pointer we obtained from card count cache is not hot
|
||||||
// so do not store it in the cache; return it for immediate
|
// so do not store it in the cache; return it for immediate
|
||||||
|
@ -325,7 +320,7 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) {
|
||||||
return cached_ptr;
|
return cached_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, the pointer we got from the _card_counts is hot.
|
// Otherwise, the pointer we got from the _card_counts cache is hot.
|
||||||
jbyte* res = NULL;
|
jbyte* res = NULL;
|
||||||
MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
if (_n_hot == _hot_cache_size) {
|
if (_n_hot == _hot_cache_size) {
|
||||||
|
@ -338,17 +333,8 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) {
|
||||||
if (_hot_cache_idx == _hot_cache_size) _hot_cache_idx = 0;
|
if (_hot_cache_idx == _hot_cache_size) _hot_cache_idx = 0;
|
||||||
_n_hot++;
|
_n_hot++;
|
||||||
|
|
||||||
if (res != NULL) {
|
// The card obtained from the hot card cache could be in a young
|
||||||
// Even though the region containg res was not in the young list
|
// region. See above on how this can happen.
|
||||||
// when it was recorded in the hot cache it could have been added
|
|
||||||
// to the free list and subsequently added to the young list in
|
|
||||||
// the intervening time. If res is in a young region, return NULL
|
|
||||||
// so that res is not cleaned. See CR 6817995.
|
|
||||||
|
|
||||||
if (is_young_card(res)) {
|
|
||||||
res = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,6 +266,12 @@ void ConcurrentMarkThread::run() {
|
||||||
_cm->clearNextBitmap();
|
_cm->clearNextBitmap();
|
||||||
_sts.leave();
|
_sts.leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the number of full collections that have been
|
||||||
|
// completed. This will also notify the FullGCCount_lock in case a
|
||||||
|
// Java thread is waiting for a full GC to happen (e.g., it
|
||||||
|
// called System.gc() with +ExplicitGCInvokesConcurrent).
|
||||||
|
g1->increment_full_collections_completed(true /* outer */);
|
||||||
}
|
}
|
||||||
assert(_should_terminate, "just checking");
|
assert(_should_terminate, "just checking");
|
||||||
|
|
||||||
|
|
|
@ -638,6 +638,11 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
|
|
||||||
// Now retry the allocation.
|
// Now retry the allocation.
|
||||||
if (_cur_alloc_region != NULL) {
|
if (_cur_alloc_region != NULL) {
|
||||||
|
if (allocated_young_region != NULL) {
|
||||||
|
// We need to ensure that the store to top does not
|
||||||
|
// float above the setting of the young type.
|
||||||
|
OrderAccess::storestore();
|
||||||
|
}
|
||||||
res = _cur_alloc_region->allocate(word_size);
|
res = _cur_alloc_region->allocate(word_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,7 +814,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
void G1CollectedHeap::do_collection(bool explicit_gc,
|
||||||
|
bool clear_all_soft_refs,
|
||||||
size_t word_size) {
|
size_t word_size) {
|
||||||
if (GC_locker::check_active_before_gc()) {
|
if (GC_locker::check_active_before_gc()) {
|
||||||
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
||||||
|
@ -821,10 +827,6 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||||
Universe::print_heap_before_gc();
|
Universe::print_heap_before_gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full && DisableExplicitGC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
|
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
|
||||||
assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
|
assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
|
||||||
|
|
||||||
|
@ -837,9 +839,11 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||||
IsGCActiveMark x;
|
IsGCActiveMark x;
|
||||||
|
|
||||||
// Timing
|
// Timing
|
||||||
|
bool system_gc = (gc_cause() == GCCause::_java_lang_system_gc);
|
||||||
|
assert(!system_gc || explicit_gc, "invariant");
|
||||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||||
TraceTime t(full ? "Full GC (System.gc())" : "Full GC",
|
TraceTime t(system_gc ? "Full GC (System.gc())" : "Full GC",
|
||||||
PrintGC, true, gclog_or_tty);
|
PrintGC, true, gclog_or_tty);
|
||||||
|
|
||||||
TraceMemoryManagerStats tms(true /* fullGC */);
|
TraceMemoryManagerStats tms(true /* fullGC */);
|
||||||
|
@ -944,7 +948,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||||
heap_region_iterate(&rs_clear);
|
heap_region_iterate(&rs_clear);
|
||||||
|
|
||||||
// Resize the heap if necessary.
|
// Resize the heap if necessary.
|
||||||
resize_if_necessary_after_full_collection(full ? 0 : word_size);
|
resize_if_necessary_after_full_collection(explicit_gc ? 0 : word_size);
|
||||||
|
|
||||||
if (_cg1r->use_cache()) {
|
if (_cg1r->use_cache()) {
|
||||||
_cg1r->clear_and_record_card_counts();
|
_cg1r->clear_and_record_card_counts();
|
||||||
|
@ -1009,13 +1013,18 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||||
"young list should be empty at this point");
|
"young list should be empty at this point");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the number of full collections that have been completed.
|
||||||
|
increment_full_collections_completed(false /* outer */);
|
||||||
|
|
||||||
if (PrintHeapAtGC) {
|
if (PrintHeapAtGC) {
|
||||||
Universe::print_heap_after_gc();
|
Universe::print_heap_after_gc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
||||||
do_collection(true, clear_all_soft_refs, 0);
|
do_collection(true, /* explicit_gc */
|
||||||
|
clear_all_soft_refs,
|
||||||
|
0 /* word_size */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code is mostly copied from TenuredGeneration.
|
// This code is mostly copied from TenuredGeneration.
|
||||||
|
@ -1331,6 +1340,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||||
_young_list(new YoungList(this)),
|
_young_list(new YoungList(this)),
|
||||||
_gc_time_stamp(0),
|
_gc_time_stamp(0),
|
||||||
_surviving_young_words(NULL),
|
_surviving_young_words(NULL),
|
||||||
|
_full_collections_completed(0),
|
||||||
_in_cset_fast_test(NULL),
|
_in_cset_fast_test(NULL),
|
||||||
_in_cset_fast_test_base(NULL),
|
_in_cset_fast_test_base(NULL),
|
||||||
_dirty_cards_region_list(NULL) {
|
_dirty_cards_region_list(NULL) {
|
||||||
|
@ -1689,6 +1699,51 @@ size_t G1CollectedHeap::unsafe_max_alloc() {
|
||||||
return car->free();
|
return car->free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||||
|
return
|
||||||
|
((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||||
|
(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void G1CollectedHeap::increment_full_collections_completed(bool outer) {
|
||||||
|
MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
|
// We have already incremented _total_full_collections at the start
|
||||||
|
// of the GC, so total_full_collections() represents how many full
|
||||||
|
// collections have been started.
|
||||||
|
unsigned int full_collections_started = total_full_collections();
|
||||||
|
|
||||||
|
// Given that this method is called at the end of a Full GC or of a
|
||||||
|
// concurrent cycle, and those can be nested (i.e., a Full GC can
|
||||||
|
// interrupt a concurrent cycle), the number of full collections
|
||||||
|
// completed should be either one (in the case where there was no
|
||||||
|
// nesting) or two (when a Full GC interrupted a concurrent cycle)
|
||||||
|
// behind the number of full collections started.
|
||||||
|
|
||||||
|
// This is the case for the inner caller, i.e. a Full GC.
|
||||||
|
assert(outer ||
|
||||||
|
(full_collections_started == _full_collections_completed + 1) ||
|
||||||
|
(full_collections_started == _full_collections_completed + 2),
|
||||||
|
err_msg("for inner caller: full_collections_started = %u "
|
||||||
|
"is inconsistent with _full_collections_completed = %u",
|
||||||
|
full_collections_started, _full_collections_completed));
|
||||||
|
|
||||||
|
// This is the case for the outer caller, i.e. the concurrent cycle.
|
||||||
|
assert(!outer ||
|
||||||
|
(full_collections_started == _full_collections_completed + 1),
|
||||||
|
err_msg("for outer caller: full_collections_started = %u "
|
||||||
|
"is inconsistent with _full_collections_completed = %u",
|
||||||
|
full_collections_started, _full_collections_completed));
|
||||||
|
|
||||||
|
_full_collections_completed += 1;
|
||||||
|
|
||||||
|
// This notify_all() will ensure that a thread that called
|
||||||
|
// System.gc() with (with ExplicitGCInvokesConcurrent set or not)
|
||||||
|
// and it's waiting for a full GC to finish will be woken up. It is
|
||||||
|
// waiting in VM_G1IncCollectionPause::doit_epilogue().
|
||||||
|
FullGCCount_lock->notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
|
void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
|
||||||
assert(Thread::current()->is_VM_thread(), "Precondition#1");
|
assert(Thread::current()->is_VM_thread(), "Precondition#1");
|
||||||
assert(Heap_lock->is_locked(), "Precondition#2");
|
assert(Heap_lock->is_locked(), "Precondition#2");
|
||||||
|
@ -1709,25 +1764,41 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
|
||||||
// The caller doesn't have the Heap_lock
|
// The caller doesn't have the Heap_lock
|
||||||
assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
|
assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
|
||||||
|
|
||||||
int gc_count_before;
|
unsigned int gc_count_before;
|
||||||
|
unsigned int full_gc_count_before;
|
||||||
{
|
{
|
||||||
MutexLocker ml(Heap_lock);
|
MutexLocker ml(Heap_lock);
|
||||||
// Read the GC count while holding the Heap_lock
|
// Read the GC count while holding the Heap_lock
|
||||||
gc_count_before = SharedHeap::heap()->total_collections();
|
gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
|
full_gc_count_before = SharedHeap::heap()->total_full_collections();
|
||||||
|
|
||||||
// Don't want to do a GC until cleanup is completed.
|
// Don't want to do a GC until cleanup is completed.
|
||||||
wait_for_cleanup_complete();
|
wait_for_cleanup_complete();
|
||||||
} // We give up heap lock; VMThread::execute gets it back below
|
|
||||||
switch (cause) {
|
// We give up heap lock; VMThread::execute gets it back below
|
||||||
case GCCause::_scavenge_alot: {
|
}
|
||||||
// Do an incremental pause, which might sometimes be abandoned.
|
|
||||||
VM_G1IncCollectionPause op(gc_count_before, cause);
|
if (should_do_concurrent_full_gc(cause)) {
|
||||||
|
// Schedule an initial-mark evacuation pause that will start a
|
||||||
|
// concurrent cycle.
|
||||||
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
true, /* should_initiate_conc_mark */
|
||||||
|
g1_policy()->max_pause_time_ms(),
|
||||||
|
cause);
|
||||||
|
VMThread::execute(&op);
|
||||||
|
} else {
|
||||||
|
if (cause == GCCause::_gc_locker
|
||||||
|
DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {
|
||||||
|
|
||||||
|
// Schedule a standard evacuation pause.
|
||||||
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
false, /* should_initiate_conc_mark */
|
||||||
|
g1_policy()->max_pause_time_ms(),
|
||||||
|
cause);
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
break;
|
} else {
|
||||||
}
|
// Schedule a Full GC.
|
||||||
default: {
|
VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause);
|
||||||
// In all other cases, we currently do a full gc.
|
|
||||||
VM_G1CollectFull op(gc_count_before, cause);
|
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1989,6 +2060,11 @@ void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
|
||||||
|
|
||||||
void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r,
|
void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r,
|
||||||
HeapRegionClosure *cl) {
|
HeapRegionClosure *cl) {
|
||||||
|
if (r == NULL) {
|
||||||
|
// The CSet is empty so there's nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(r->in_collection_set(),
|
assert(r->in_collection_set(),
|
||||||
"Start region must be a member of the collection set.");
|
"Start region must be a member of the collection set.");
|
||||||
HeapRegion* cur = r;
|
HeapRegion* cur = r;
|
||||||
|
@ -2481,11 +2557,13 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::do_collection_pause() {
|
void G1CollectedHeap::do_collection_pause() {
|
||||||
|
assert(Heap_lock->owned_by_self(), "we assume we'reholding the Heap_lock");
|
||||||
|
|
||||||
// Read the GC count while holding the Heap_lock
|
// Read the GC count while holding the Heap_lock
|
||||||
// we need to do this _before_ wait_for_cleanup_complete(), to
|
// we need to do this _before_ wait_for_cleanup_complete(), to
|
||||||
// ensure that we do not give up the heap lock and potentially
|
// ensure that we do not give up the heap lock and potentially
|
||||||
// pick up the wrong count
|
// pick up the wrong count
|
||||||
int gc_count_before = SharedHeap::heap()->total_collections();
|
unsigned int gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
|
|
||||||
// Don't want to do a GC pause while cleanup is being completed!
|
// Don't want to do a GC pause while cleanup is being completed!
|
||||||
wait_for_cleanup_complete();
|
wait_for_cleanup_complete();
|
||||||
|
@ -2493,7 +2571,10 @@ void G1CollectedHeap::do_collection_pause() {
|
||||||
g1_policy()->record_stop_world_start();
|
g1_policy()->record_stop_world_start();
|
||||||
{
|
{
|
||||||
MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
|
MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
|
||||||
VM_G1IncCollectionPause op(gc_count_before);
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
false, /* should_initiate_conc_mark */
|
||||||
|
g1_policy()->max_pause_time_ms(),
|
||||||
|
GCCause::_g1_inc_collection_pause);
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2612,7 +2693,7 @@ struct PrepareForRSScanningClosure : public HeapRegionClosure {
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
G1CollectedHeap::do_collection_pause_at_safepoint() {
|
G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||||
if (GC_locker::check_active_before_gc()) {
|
if (GC_locker::check_active_before_gc()) {
|
||||||
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
||||||
}
|
}
|
||||||
|
@ -2637,8 +2718,12 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
|
||||||
else
|
else
|
||||||
strcat(verbose_str, "(partial)");
|
strcat(verbose_str, "(partial)");
|
||||||
}
|
}
|
||||||
if (g1_policy()->during_initial_mark_pause())
|
if (g1_policy()->during_initial_mark_pause()) {
|
||||||
strcat(verbose_str, " (initial-mark)");
|
strcat(verbose_str, " (initial-mark)");
|
||||||
|
// We are about to start a marking cycle, so we increment the
|
||||||
|
// full collection counter.
|
||||||
|
increment_total_full_collections();
|
||||||
|
}
|
||||||
|
|
||||||
// if PrintGCDetails is on, we'll print long statistics information
|
// if PrintGCDetails is on, we'll print long statistics information
|
||||||
// in the collector policy code, so let's not print this as the output
|
// in the collector policy code, so let's not print this as the output
|
||||||
|
@ -2661,7 +2746,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
|
||||||
"young list should be well formed");
|
"young list should be well formed");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool abandoned = false;
|
|
||||||
{ // Call to jvmpi::post_class_unload_events must occur outside of active GC
|
{ // Call to jvmpi::post_class_unload_events must occur outside of active GC
|
||||||
IsGCActiveMark x;
|
IsGCActiveMark x;
|
||||||
|
|
||||||
|
@ -2743,7 +2827,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint() {
|
||||||
|
|
||||||
// Now choose the CS. We may abandon a pause if we find no
|
// Now choose the CS. We may abandon a pause if we find no
|
||||||
// region that will fit in the MMU pause.
|
// region that will fit in the MMU pause.
|
||||||
bool abandoned = g1_policy()->choose_collection_set();
|
bool abandoned = g1_policy()->choose_collection_set(target_pause_time_ms);
|
||||||
|
|
||||||
// Nothing to do if we were unable to choose a collection set.
|
// Nothing to do if we were unable to choose a collection set.
|
||||||
if (!abandoned) {
|
if (!abandoned) {
|
||||||
|
|
|
@ -277,6 +277,18 @@ private:
|
||||||
void update_surviving_young_words(size_t* surv_young_words);
|
void update_surviving_young_words(size_t* surv_young_words);
|
||||||
void cleanup_surviving_young_words();
|
void cleanup_surviving_young_words();
|
||||||
|
|
||||||
|
// It decides whether an explicit GC should start a concurrent cycle
|
||||||
|
// instead of doing a STW GC. Currently, a concurrent cycle is
|
||||||
|
// explicitly started if:
|
||||||
|
// (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
|
||||||
|
// (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
|
||||||
|
bool should_do_concurrent_full_gc(GCCause::Cause cause);
|
||||||
|
|
||||||
|
// Keeps track of how many "full collections" (i.e., Full GCs or
|
||||||
|
// concurrent cycles) we have completed. The number of them we have
|
||||||
|
// started is maintained in _total_full_collections in CollectedHeap.
|
||||||
|
volatile unsigned int _full_collections_completed;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Returns "true" iff none of the gc alloc regions have any allocations
|
// Returns "true" iff none of the gc alloc regions have any allocations
|
||||||
|
@ -356,13 +368,14 @@ protected:
|
||||||
// GC pause.
|
// GC pause.
|
||||||
void retire_alloc_region(HeapRegion* alloc_region, bool par);
|
void retire_alloc_region(HeapRegion* alloc_region, bool par);
|
||||||
|
|
||||||
// Helper function for two callbacks below.
|
// - if explicit_gc is true, the GC is for a System.gc() or a heap
|
||||||
// "full", if true, indicates that the GC is for a System.gc() request,
|
// inspection request and should collect the entire heap
|
||||||
// and should collect the entire heap. If "clear_all_soft_refs" is true,
|
// - if clear_all_soft_refs is true, all soft references are cleared
|
||||||
// all soft references are cleared during the GC. If "full" is false,
|
// during the GC
|
||||||
// "word_size" describes the allocation that the GC should
|
// - if explicit_gc is false, word_size describes the allocation that
|
||||||
// attempt (at least) to satisfy.
|
// the GC should attempt (at least) to satisfy
|
||||||
void do_collection(bool full, bool clear_all_soft_refs,
|
void do_collection(bool explicit_gc,
|
||||||
|
bool clear_all_soft_refs,
|
||||||
size_t word_size);
|
size_t word_size);
|
||||||
|
|
||||||
// Callback from VM_G1CollectFull operation.
|
// Callback from VM_G1CollectFull operation.
|
||||||
|
@ -431,6 +444,26 @@ public:
|
||||||
_in_cset_fast_test_length * sizeof(bool));
|
_in_cset_fast_test_length * sizeof(bool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called at the end of either a concurrent cycle or a Full
|
||||||
|
// GC to update the number of full collections completed. Those two
|
||||||
|
// can happen in a nested fashion, i.e., we start a concurrent
|
||||||
|
// cycle, a Full GC happens half-way through it which ends first,
|
||||||
|
// and then the cycle notices that a Full GC happened and ends
|
||||||
|
// too. The outer parameter is a boolean to help us do a bit tighter
|
||||||
|
// consistency checking in the method. If outer is false, the caller
|
||||||
|
// is the inner caller in the nesting (i.e., the Full GC). If outer
|
||||||
|
// is true, the caller is the outer caller in this nesting (i.e.,
|
||||||
|
// the concurrent cycle). Further nesting is not currently
|
||||||
|
// supported. The end of the this call also notifies the
|
||||||
|
// FullGCCount_lock in case a Java thread is waiting for a full GC
|
||||||
|
// to happen (e.g., it called System.gc() with
|
||||||
|
// +ExplicitGCInvokesConcurrent).
|
||||||
|
void increment_full_collections_completed(bool outer);
|
||||||
|
|
||||||
|
unsigned int full_collections_completed() {
|
||||||
|
return _full_collections_completed;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Shrink the garbage-first heap by at most the given size (in bytes!).
|
// Shrink the garbage-first heap by at most the given size (in bytes!).
|
||||||
|
@ -444,7 +477,7 @@ protected:
|
||||||
|
|
||||||
// The guts of the incremental collection pause, executed by the vm
|
// The guts of the incremental collection pause, executed by the vm
|
||||||
// thread.
|
// thread.
|
||||||
virtual void do_collection_pause_at_safepoint();
|
virtual void do_collection_pause_at_safepoint(double target_pause_time_ms);
|
||||||
|
|
||||||
// Actually do the work of evacuating the collection set.
|
// Actually do the work of evacuating the collection set.
|
||||||
virtual void evacuate_collection_set();
|
virtual void evacuate_collection_set();
|
||||||
|
|
|
@ -154,7 +154,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||||
_known_garbage_bytes(0),
|
_known_garbage_bytes(0),
|
||||||
|
|
||||||
_young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)),
|
_young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)),
|
||||||
_target_pause_time_ms(-1.0),
|
|
||||||
|
|
||||||
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
|
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
|
||||||
|
|
||||||
|
@ -1635,8 +1634,6 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
||||||
double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
|
double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
|
||||||
adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
|
adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
|
||||||
// </NEW PREDICTION>
|
// </NEW PREDICTION>
|
||||||
|
|
||||||
_target_pause_time_ms = -1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// <NEW PREDICTION>
|
// <NEW PREDICTION>
|
||||||
|
@ -2366,7 +2363,6 @@ G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t
|
||||||
if (reached_target_length) {
|
if (reached_target_length) {
|
||||||
assert( young_list_length > 0 && _g1->young_list()->length() > 0,
|
assert( young_list_length > 0 && _g1->young_list()->length() > 0,
|
||||||
"invariant" );
|
"invariant" );
|
||||||
_target_pause_time_ms = max_pause_time_ms;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2398,6 +2394,17 @@ bool G1CollectorPolicy_BestRegionsFirst::assertMarkedBytesDataOK() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool
|
||||||
|
G1CollectorPolicy::force_initial_mark_if_outside_cycle() {
|
||||||
|
bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
|
||||||
|
if (!during_cycle) {
|
||||||
|
set_initiate_conc_mark_if_possible();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
G1CollectorPolicy::decide_on_conc_mark_initiation() {
|
G1CollectorPolicy::decide_on_conc_mark_initiation() {
|
||||||
// We are about to decide on whether this pause will be an
|
// We are about to decide on whether this pause will be an
|
||||||
|
@ -2864,7 +2871,8 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream
|
||||||
#endif // !PRODUCT
|
#endif // !PRODUCT
|
||||||
|
|
||||||
bool
|
bool
|
||||||
G1CollectorPolicy_BestRegionsFirst::choose_collection_set() {
|
G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
|
||||||
|
double target_pause_time_ms) {
|
||||||
// Set this here - in case we're not doing young collections.
|
// Set this here - in case we're not doing young collections.
|
||||||
double non_young_start_time_sec = os::elapsedTime();
|
double non_young_start_time_sec = os::elapsedTime();
|
||||||
|
|
||||||
|
@ -2877,26 +2885,19 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set() {
|
||||||
|
|
||||||
start_recording_regions();
|
start_recording_regions();
|
||||||
|
|
||||||
guarantee(_target_pause_time_ms > -1.0
|
guarantee(target_pause_time_ms > 0.0,
|
||||||
NOT_PRODUCT(|| Universe::heap()->gc_cause() == GCCause::_scavenge_alot),
|
err_msg("target_pause_time_ms = %1.6lf should be positive",
|
||||||
"_target_pause_time_ms should have been set!");
|
target_pause_time_ms));
|
||||||
#ifndef PRODUCT
|
guarantee(_collection_set == NULL, "Precondition");
|
||||||
if (_target_pause_time_ms <= -1.0) {
|
|
||||||
assert(ScavengeALot && Universe::heap()->gc_cause() == GCCause::_scavenge_alot, "Error");
|
|
||||||
_target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
assert(_collection_set == NULL, "Precondition");
|
|
||||||
|
|
||||||
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
|
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
|
||||||
double predicted_pause_time_ms = base_time_ms;
|
double predicted_pause_time_ms = base_time_ms;
|
||||||
|
|
||||||
double target_time_ms = _target_pause_time_ms;
|
double time_remaining_ms = target_pause_time_ms - base_time_ms;
|
||||||
double time_remaining_ms = target_time_ms - base_time_ms;
|
|
||||||
|
|
||||||
// the 10% and 50% values are arbitrary...
|
// the 10% and 50% values are arbitrary...
|
||||||
if (time_remaining_ms < 0.10*target_time_ms) {
|
if (time_remaining_ms < 0.10 * target_pause_time_ms) {
|
||||||
time_remaining_ms = 0.50 * target_time_ms;
|
time_remaining_ms = 0.50 * target_pause_time_ms;
|
||||||
_within_target = false;
|
_within_target = false;
|
||||||
} else {
|
} else {
|
||||||
_within_target = true;
|
_within_target = true;
|
||||||
|
@ -3059,7 +3060,18 @@ choose_collection_set_end:
|
||||||
_recorded_non_young_cset_choice_time_ms =
|
_recorded_non_young_cset_choice_time_ms =
|
||||||
(non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
|
(non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
|
||||||
|
|
||||||
return abandon_collection;
|
// Here we are supposed to return whether the pause should be
|
||||||
|
// abandoned or not (i.e., whether the collection set is empty or
|
||||||
|
// not). However, this introduces a subtle issue when a pause is
|
||||||
|
// initiated explicitly with System.gc() and
|
||||||
|
// +ExplicitGCInvokesConcurrent (see Comment #2 in CR 6944166), it's
|
||||||
|
// supposed to start a marking cycle, and it's abandoned. So, by
|
||||||
|
// returning false here we are telling the caller never to consider
|
||||||
|
// a pause to be abandoned. We'll actually remove all the code
|
||||||
|
// associated with abandoned pauses as part of CR 6963209, but we are
|
||||||
|
// just disabling them this way for the moment to avoid increasing
|
||||||
|
// further the amount of changes for CR 6944166.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() {
|
void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() {
|
||||||
|
|
|
@ -199,8 +199,6 @@ protected:
|
||||||
size_t _young_cset_length;
|
size_t _young_cset_length;
|
||||||
bool _last_young_gc_full;
|
bool _last_young_gc_full;
|
||||||
|
|
||||||
double _target_pause_time_ms;
|
|
||||||
|
|
||||||
unsigned _full_young_pause_num;
|
unsigned _full_young_pause_num;
|
||||||
unsigned _partial_young_pause_num;
|
unsigned _partial_young_pause_num;
|
||||||
|
|
||||||
|
@ -526,6 +524,10 @@ public:
|
||||||
return _mmu_tracker;
|
return _mmu_tracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double max_pause_time_ms() {
|
||||||
|
return _mmu_tracker->max_gc_time() * 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
double predict_init_time_ms() {
|
double predict_init_time_ms() {
|
||||||
return get_new_prediction(_concurrent_mark_init_times_ms);
|
return get_new_prediction(_concurrent_mark_init_times_ms);
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1010,7 @@ public:
|
||||||
// Choose a new collection set. Marks the chosen regions as being
|
// Choose a new collection set. Marks the chosen regions as being
|
||||||
// "in_collection_set", and links them together. The head and number of
|
// "in_collection_set", and links them together. The head and number of
|
||||||
// the collection set are available via access methods.
|
// the collection set are available via access methods.
|
||||||
virtual bool choose_collection_set() = 0;
|
virtual bool choose_collection_set(double target_pause_time_ms) = 0;
|
||||||
|
|
||||||
// The head of the list (via "next_in_collection_set()") representing the
|
// The head of the list (via "next_in_collection_set()") representing the
|
||||||
// current collection set.
|
// current collection set.
|
||||||
|
@ -1077,6 +1079,12 @@ public:
|
||||||
void set_during_initial_mark_pause() { _during_initial_mark_pause = true; }
|
void set_during_initial_mark_pause() { _during_initial_mark_pause = true; }
|
||||||
void clear_during_initial_mark_pause(){ _during_initial_mark_pause = false; }
|
void clear_during_initial_mark_pause(){ _during_initial_mark_pause = false; }
|
||||||
|
|
||||||
|
// This sets the initiate_conc_mark_if_possible() flag to start a
|
||||||
|
// new cycle, as long as we are not already in one. It's best if it
|
||||||
|
// is called during a safepoint when the test whether a cycle is in
|
||||||
|
// progress or not is stable.
|
||||||
|
bool force_initial_mark_if_outside_cycle();
|
||||||
|
|
||||||
// This is called at the very beginning of an evacuation pause (it
|
// This is called at the very beginning of an evacuation pause (it
|
||||||
// has to be the first thing that the pause does). If
|
// has to be the first thing that the pause does). If
|
||||||
// initiate_conc_mark_if_possible() is true, and the concurrent
|
// initiate_conc_mark_if_possible() is true, and the concurrent
|
||||||
|
@ -1259,7 +1267,7 @@ class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy {
|
||||||
// If the estimated is less then desirable, resize if possible.
|
// If the estimated is less then desirable, resize if possible.
|
||||||
void expand_if_possible(size_t numRegions);
|
void expand_if_possible(size_t numRegions);
|
||||||
|
|
||||||
virtual bool choose_collection_set();
|
virtual bool choose_collection_set(double target_pause_time_ms);
|
||||||
virtual void record_collection_pause_start(double start_time_sec,
|
virtual void record_collection_pause_start(double start_time_sec,
|
||||||
size_t start_used);
|
size_t start_used);
|
||||||
virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes,
|
virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes,
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -676,9 +676,27 @@ void HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i
|
||||||
// We must complete this write before we do any of the reads below.
|
// We must complete this write before we do any of the reads below.
|
||||||
OrderAccess::storeload();
|
OrderAccess::storeload();
|
||||||
// And process it, being careful of unallocated portions of TLAB's.
|
// And process it, being careful of unallocated portions of TLAB's.
|
||||||
|
|
||||||
|
// The region for the current card may be a young region. The
|
||||||
|
// current card may have been a card that was evicted from the
|
||||||
|
// card cache. When the card was inserted into the cache, we had
|
||||||
|
// determined that its region was non-young. While in the cache,
|
||||||
|
// the region may have been freed during a cleanup pause, reallocated
|
||||||
|
// and tagged as young.
|
||||||
|
//
|
||||||
|
// We wish to filter out cards for such a region but the current
|
||||||
|
// thread, if we're running conucrrently, may "see" the young type
|
||||||
|
// change at any time (so an earlier "is_young" check may pass or
|
||||||
|
// fail arbitrarily). We tell the iteration code to perform this
|
||||||
|
// filtering when it has been determined that there has been an actual
|
||||||
|
// allocation in this region and making it safe to check the young type.
|
||||||
|
bool filter_young = true;
|
||||||
|
|
||||||
HeapWord* stop_point =
|
HeapWord* stop_point =
|
||||||
r->oops_on_card_seq_iterate_careful(dirtyRegion,
|
r->oops_on_card_seq_iterate_careful(dirtyRegion,
|
||||||
&filter_then_update_rs_oop_cl);
|
&filter_then_update_rs_oop_cl,
|
||||||
|
filter_young);
|
||||||
|
|
||||||
// If stop_point is non-null, then we encountered an unallocated region
|
// If stop_point is non-null, then we encountered an unallocated region
|
||||||
// (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the
|
// (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the
|
||||||
// card and re-enqueue: if we put off the card until a GC pause, then the
|
// card and re-enqueue: if we put off the card until a GC pause, then the
|
||||||
|
@ -789,8 +807,14 @@ void HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
assert(_g1->is_in_permanent(start), "Or else where?");
|
assert(_g1->is_in_permanent(start), "Or else where?");
|
||||||
} else {
|
} else {
|
||||||
guarantee(!r->is_young(), "It was evicted in the current minor cycle.");
|
// Checking whether the region we got back from the cache
|
||||||
// Process card pointer we get back from the hot card cache
|
// is young here is inappropriate. The region could have been
|
||||||
|
// freed, reallocated and tagged as young while in the cache.
|
||||||
|
// Hence we could see its young type change at any time.
|
||||||
|
//
|
||||||
|
// Process card pointer we get back from the hot card cache. This
|
||||||
|
// will check whether the region containing the card is young
|
||||||
|
// _after_ checking that the region has been allocated from.
|
||||||
concurrentRefineOneCard_impl(res, worker_i);
|
concurrentRefineOneCard_impl(res, worker_i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -658,7 +658,8 @@ HeapRegion::object_iterate_mem_careful(MemRegion mr,
|
||||||
HeapWord*
|
HeapWord*
|
||||||
HeapRegion::
|
HeapRegion::
|
||||||
oops_on_card_seq_iterate_careful(MemRegion mr,
|
oops_on_card_seq_iterate_careful(MemRegion mr,
|
||||||
FilterOutOfRegionClosure* cl) {
|
FilterOutOfRegionClosure* cl,
|
||||||
|
bool filter_young) {
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
|
|
||||||
// If we're within a stop-world GC, then we might look at a card in a
|
// If we're within a stop-world GC, then we might look at a card in a
|
||||||
|
@ -672,6 +673,16 @@ oops_on_card_seq_iterate_careful(MemRegion mr,
|
||||||
if (mr.is_empty()) return NULL;
|
if (mr.is_empty()) return NULL;
|
||||||
// Otherwise, find the obj that extends onto mr.start().
|
// Otherwise, find the obj that extends onto mr.start().
|
||||||
|
|
||||||
|
// The intersection of the incoming mr (for the card) and the
|
||||||
|
// allocated part of the region is non-empty. This implies that
|
||||||
|
// we have actually allocated into this region. The code in
|
||||||
|
// G1CollectedHeap.cpp that allocates a new region sets the
|
||||||
|
// is_young tag on the region before allocating. Thus we
|
||||||
|
// safely know if this region is young.
|
||||||
|
if (is_young() && filter_young) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// We used to use "block_start_careful" here. But we're actually happy
|
// We used to use "block_start_careful" here. But we're actually happy
|
||||||
// to update the BOT while we do this...
|
// to update the BOT while we do this...
|
||||||
HeapWord* cur = block_start(mr.start());
|
HeapWord* cur = block_start(mr.start());
|
||||||
|
|
|
@ -252,7 +252,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||||
// survivor
|
// survivor
|
||||||
};
|
};
|
||||||
|
|
||||||
YoungType _young_type;
|
volatile YoungType _young_type;
|
||||||
int _young_index_in_cset;
|
int _young_index_in_cset;
|
||||||
SurvRateGroup* _surv_rate_group;
|
SurvRateGroup* _surv_rate_group;
|
||||||
int _age_index;
|
int _age_index;
|
||||||
|
@ -726,9 +726,12 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||||
HeapWord*
|
HeapWord*
|
||||||
object_iterate_mem_careful(MemRegion mr, ObjectClosure* cl);
|
object_iterate_mem_careful(MemRegion mr, ObjectClosure* cl);
|
||||||
|
|
||||||
|
// In this version - if filter_young is true and the region
|
||||||
|
// is a young region then we skip the iteration.
|
||||||
HeapWord*
|
HeapWord*
|
||||||
oops_on_card_seq_iterate_careful(MemRegion mr,
|
oops_on_card_seq_iterate_careful(MemRegion mr,
|
||||||
FilterOutOfRegionClosure* cl);
|
FilterOutOfRegionClosure* cl,
|
||||||
|
bool filter_young);
|
||||||
|
|
||||||
// The region "mr" is entirely in "this", and starts and ends at block
|
// The region "mr" is entirely in "this", and starts and ends at block
|
||||||
// boundaries. The caller declares that all the contained blocks are
|
// boundaries. The caller declares that all the contained blocks are
|
||||||
|
|
|
@ -42,8 +42,65 @@ void VM_G1CollectFull::doit() {
|
||||||
void VM_G1IncCollectionPause::doit() {
|
void VM_G1IncCollectionPause::doit() {
|
||||||
JvmtiGCForAllocationMarker jgcm;
|
JvmtiGCForAllocationMarker jgcm;
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
|
assert(!_should_initiate_conc_mark ||
|
||||||
|
((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||||
|
(_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
|
||||||
|
"only a GC locker or a System.gc() induced GC should start a cycle");
|
||||||
|
|
||||||
GCCauseSetter x(g1h, _gc_cause);
|
GCCauseSetter x(g1h, _gc_cause);
|
||||||
g1h->do_collection_pause_at_safepoint();
|
if (_should_initiate_conc_mark) {
|
||||||
|
// It's safer to read full_collections_completed() here, given
|
||||||
|
// that noone else will be updating it concurrently. Since we'll
|
||||||
|
// only need it if we're initiating a marking cycle, no point in
|
||||||
|
// setting it earlier.
|
||||||
|
_full_collections_completed_before = g1h->full_collections_completed();
|
||||||
|
|
||||||
|
// At this point we are supposed to start a concurrent cycle. We
|
||||||
|
// will do so if one is not already in progress.
|
||||||
|
bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle();
|
||||||
|
}
|
||||||
|
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VM_G1IncCollectionPause::doit_epilogue() {
|
||||||
|
VM_GC_Operation::doit_epilogue();
|
||||||
|
|
||||||
|
// If the pause was initiated by a System.gc() and
|
||||||
|
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
|
||||||
|
// that just started (or maybe one that was already in progress) to
|
||||||
|
// finish.
|
||||||
|
if (_gc_cause == GCCause::_java_lang_system_gc &&
|
||||||
|
_should_initiate_conc_mark) {
|
||||||
|
assert(ExplicitGCInvokesConcurrent,
|
||||||
|
"the only way to be here is if ExplicitGCInvokesConcurrent is set");
|
||||||
|
|
||||||
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
|
|
||||||
|
// In the doit() method we saved g1h->full_collections_completed()
|
||||||
|
// in the _full_collections_completed_before field. We have to
|
||||||
|
// wait until we observe that g1h->full_collections_completed()
|
||||||
|
// has increased by at least one. This can happen if a) we started
|
||||||
|
// a cycle and it completes, b) a cycle already in progress
|
||||||
|
// completes, or c) a Full GC happens.
|
||||||
|
|
||||||
|
// If the condition has already been reached, there's no point in
|
||||||
|
// actually taking the lock and doing the wait.
|
||||||
|
if (g1h->full_collections_completed() <=
|
||||||
|
_full_collections_completed_before) {
|
||||||
|
// The following is largely copied from CMS
|
||||||
|
|
||||||
|
Thread* thr = Thread::current();
|
||||||
|
assert(thr->is_Java_thread(), "invariant");
|
||||||
|
JavaThread* jt = (JavaThread*)thr;
|
||||||
|
ThreadToNativeFromVM native(jt);
|
||||||
|
|
||||||
|
MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
while (g1h->full_collections_completed() <=
|
||||||
|
_full_collections_completed_before) {
|
||||||
|
FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_CGC_Operation::doit() {
|
void VM_CGC_Operation::doit() {
|
||||||
|
|
|
@ -31,13 +31,12 @@
|
||||||
// - VM_G1PopRegionCollectionPause
|
// - VM_G1PopRegionCollectionPause
|
||||||
|
|
||||||
class VM_G1CollectFull: public VM_GC_Operation {
|
class VM_G1CollectFull: public VM_GC_Operation {
|
||||||
private:
|
|
||||||
public:
|
public:
|
||||||
VM_G1CollectFull(int gc_count_before,
|
VM_G1CollectFull(unsigned int gc_count_before,
|
||||||
GCCause::Cause gc_cause)
|
unsigned int full_gc_count_before,
|
||||||
: VM_GC_Operation(gc_count_before)
|
GCCause::Cause cause)
|
||||||
{
|
: VM_GC_Operation(gc_count_before, full_gc_count_before) {
|
||||||
_gc_cause = gc_cause;
|
_gc_cause = cause;
|
||||||
}
|
}
|
||||||
~VM_G1CollectFull() {}
|
~VM_G1CollectFull() {}
|
||||||
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
||||||
|
@ -67,12 +66,28 @@ class VM_G1CollectForAllocation: public VM_GC_Operation {
|
||||||
};
|
};
|
||||||
|
|
||||||
class VM_G1IncCollectionPause: public VM_GC_Operation {
|
class VM_G1IncCollectionPause: public VM_GC_Operation {
|
||||||
public:
|
private:
|
||||||
VM_G1IncCollectionPause(int gc_count_before,
|
bool _should_initiate_conc_mark;
|
||||||
GCCause::Cause gc_cause = GCCause::_g1_inc_collection_pause) :
|
double _target_pause_time_ms;
|
||||||
VM_GC_Operation(gc_count_before) { _gc_cause = gc_cause; }
|
unsigned int _full_collections_completed_before;
|
||||||
|
public:
|
||||||
|
VM_G1IncCollectionPause(unsigned int gc_count_before,
|
||||||
|
bool should_initiate_conc_mark,
|
||||||
|
double target_pause_time_ms,
|
||||||
|
GCCause::Cause cause)
|
||||||
|
: VM_GC_Operation(gc_count_before),
|
||||||
|
_full_collections_completed_before(0),
|
||||||
|
_should_initiate_conc_mark(should_initiate_conc_mark),
|
||||||
|
_target_pause_time_ms(target_pause_time_ms) {
|
||||||
|
guarantee(target_pause_time_ms > 0.0,
|
||||||
|
err_msg("target_pause_time_ms = %1.6lf should be positive",
|
||||||
|
target_pause_time_ms));
|
||||||
|
|
||||||
|
_gc_cause = cause;
|
||||||
|
}
|
||||||
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
|
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
|
virtual void doit_epilogue();
|
||||||
virtual const char* name() const {
|
virtual const char* name() const {
|
||||||
return "garbage-first incremental collection pause";
|
return "garbage-first incremental collection pause";
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,4 +367,6 @@ vm_operations_g1.hpp vmGCOperations.hpp
|
||||||
|
|
||||||
vm_operations_g1.cpp vm_operations_g1.hpp
|
vm_operations_g1.cpp vm_operations_g1.hpp
|
||||||
vm_operations_g1.cpp g1CollectedHeap.inline.hpp
|
vm_operations_g1.cpp g1CollectedHeap.inline.hpp
|
||||||
|
vm_operations_g1.cpp g1CollectorPolicy.hpp
|
||||||
|
vm_operations_g1.cpp interfaceSupport.hpp
|
||||||
vm_operations_g1.cpp isGCActiveMark.hpp
|
vm_operations_g1.cpp isGCActiveMark.hpp
|
||||||
|
|
|
@ -539,10 +539,9 @@ ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
|
||||||
guarantee(_task_queues != NULL, "task_queues allocation failure.");
|
guarantee(_task_queues != NULL, "task_queues allocation failure.");
|
||||||
|
|
||||||
for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
|
for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
|
||||||
ObjToScanQueuePadded *q_padded = new ObjToScanQueuePadded();
|
ObjToScanQueue *q = new ObjToScanQueue();
|
||||||
guarantee(q_padded != NULL, "work_queue Allocation failure.");
|
guarantee(q != NULL, "work_queue Allocation failure.");
|
||||||
|
_task_queues->register_queue(i1, q);
|
||||||
_task_queues->register_queue(i1, &q_padded->work_queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
|
for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -33,8 +33,8 @@ class ParEvacuateFollowersClosure;
|
||||||
// but they must be here to allow ParScanClosure::do_oop_work to be defined
|
// but they must be here to allow ParScanClosure::do_oop_work to be defined
|
||||||
// in genOopClosures.inline.hpp.
|
// in genOopClosures.inline.hpp.
|
||||||
|
|
||||||
typedef OopTaskQueue ObjToScanQueue;
|
typedef Padded<OopTaskQueue> ObjToScanQueue;
|
||||||
typedef OopTaskQueueSet ObjToScanQueueSet;
|
typedef GenericTaskQueueSet<ObjToScanQueue> ObjToScanQueueSet;
|
||||||
|
|
||||||
// Enable this to get push/pop/steal stats.
|
// Enable this to get push/pop/steal stats.
|
||||||
const int PAR_STATS_ENABLED = 0;
|
const int PAR_STATS_ENABLED = 0;
|
||||||
|
@ -304,12 +304,6 @@ class ParNewGeneration: public DefNewGeneration {
|
||||||
friend class ParEvacuateFollowersClosure;
|
friend class ParEvacuateFollowersClosure;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// XXX use a global constant instead of 64!
|
|
||||||
struct ObjToScanQueuePadded {
|
|
||||||
ObjToScanQueue work_queue;
|
|
||||||
char pad[64 - sizeof(ObjToScanQueue)]; // prevent false sharing
|
|
||||||
};
|
|
||||||
|
|
||||||
// The per-worker-thread work queues
|
// The per-worker-thread work queues
|
||||||
ObjToScanQueueSet* _task_queues;
|
ObjToScanQueueSet* _task_queues;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
class ParScanThreadState;
|
class ParScanThreadState;
|
||||||
class ParNewGeneration;
|
class ParNewGeneration;
|
||||||
typedef OopTaskQueueSet ObjToScanQueueSet;
|
typedef Padded<OopTaskQueue> ObjToScanQueue;
|
||||||
|
typedef GenericTaskQueueSet<ObjToScanQueue> ObjToScanQueueSet;
|
||||||
class ParallelTaskTerminator;
|
class ParallelTaskTerminator;
|
||||||
|
|
||||||
class ParScanClosure: public OopsInGenClosure {
|
class ParScanClosure: public OopsInGenClosure {
|
||||||
|
|
|
@ -90,10 +90,7 @@ void PSPromotionManager::pre_scavenge() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSPromotionManager::post_scavenge() {
|
void PSPromotionManager::post_scavenge() {
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(if (PrintGCDetails && ParallelGCVerbose) print_stats());
|
||||||
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);
|
PSPromotionManager* manager = manager_array(i);
|
||||||
if (UseDepthFirstScavengeOrder) {
|
if (UseDepthFirstScavengeOrder) {
|
||||||
|
@ -105,37 +102,58 @@ void PSPromotionManager::post_scavenge() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PS_PM_STATS
|
#if TASKQUEUE_STATS
|
||||||
|
void
|
||||||
|
PSPromotionManager::print_taskqueue_stats(uint i) const {
|
||||||
|
const TaskQueueStats& stats = depth_first() ?
|
||||||
|
_claimed_stack_depth.stats : _claimed_stack_breadth.stats;
|
||||||
|
tty->print("%3u ", i);
|
||||||
|
stats.print();
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PSPromotionManager::print_stats(uint i) {
|
PSPromotionManager::print_local_stats(uint i) const {
|
||||||
tty->print_cr("---- GC Worker %2d Stats", i);
|
#define FMT " " SIZE_FORMAT_W(10)
|
||||||
tty->print_cr(" total pushes %8d", _total_pushes);
|
tty->print_cr("%3u" FMT FMT FMT FMT, i, _masked_pushes, _masked_steals,
|
||||||
tty->print_cr(" masked pushes %8d", _masked_pushes);
|
_arrays_chunked, _array_chunks_processed);
|
||||||
tty->print_cr(" overflow pushes %8d", _overflow_pushes);
|
#undef FMT
|
||||||
tty->print_cr(" max overflow length %8d", _max_overflow_length);
|
|
||||||
tty->print_cr("");
|
|
||||||
tty->print_cr(" arrays chunked %8d", _arrays_chunked);
|
|
||||||
tty->print_cr(" array chunks processed %8d", _array_chunks_processed);
|
|
||||||
tty->print_cr("");
|
|
||||||
tty->print_cr(" total steals %8d", _total_steals);
|
|
||||||
tty->print_cr(" masked steals %8d", _masked_steals);
|
|
||||||
tty->print_cr("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* const pm_stats_hdr[] = {
|
||||||
|
" --------masked------- arrays array",
|
||||||
|
"thr push steal chunked chunks",
|
||||||
|
"--- ---------- ---------- ---------- ----------"
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
PSPromotionManager::print_stats() {
|
PSPromotionManager::print_stats() {
|
||||||
tty->print_cr("== GC Tasks Stats (%s), GC %3d",
|
const bool df = UseDepthFirstScavengeOrder;
|
||||||
(UseDepthFirstScavengeOrder) ? "Depth-First" : "Breadth-First",
|
tty->print_cr("== GC Task Stats (%s-First), GC %3d", df ? "Depth" : "Breadth",
|
||||||
Universe::heap()->total_collections());
|
Universe::heap()->total_collections());
|
||||||
|
|
||||||
for (uint i = 0; i < ParallelGCThreads+1; ++i) {
|
tty->print("thr "); TaskQueueStats::print_header(1); tty->cr();
|
||||||
PSPromotionManager* manager = manager_array(i);
|
tty->print("--- "); TaskQueueStats::print_header(2); tty->cr();
|
||||||
manager->print_stats(i);
|
for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
|
||||||
|
manager_array(i)->print_taskqueue_stats(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]);
|
||||||
|
for (uint i = 0; i < hlines; ++i) tty->print_cr(pm_stats_hdr[i]);
|
||||||
|
for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
|
||||||
|
manager_array(i)->print_local_stats(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PS_PM_STATS
|
void
|
||||||
|
PSPromotionManager::reset_stats() {
|
||||||
|
TaskQueueStats& stats = depth_first() ?
|
||||||
|
claimed_stack_depth()->stats : claimed_stack_breadth()->stats;
|
||||||
|
stats.reset();
|
||||||
|
_masked_pushes = _masked_steals = 0;
|
||||||
|
_arrays_chunked = _array_chunks_processed = 0;
|
||||||
|
}
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
PSPromotionManager::PSPromotionManager() {
|
PSPromotionManager::PSPromotionManager() {
|
||||||
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
|
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
|
||||||
|
@ -189,16 +207,7 @@ void PSPromotionManager::reset() {
|
||||||
|
|
||||||
_prefetch_queue.clear();
|
_prefetch_queue.clear();
|
||||||
|
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(reset_stats());
|
||||||
_total_pushes = 0;
|
|
||||||
_masked_pushes = 0;
|
|
||||||
_overflow_pushes = 0;
|
|
||||||
_max_overflow_length = 0;
|
|
||||||
_arrays_chunked = 0;
|
|
||||||
_array_chunks_processed = 0;
|
|
||||||
_total_steals = 0;
|
|
||||||
_masked_steals = 0;
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,14 +432,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) {
|
||||||
new_obj->is_objArray() &&
|
new_obj->is_objArray() &&
|
||||||
PSChunkLargeArrays) {
|
PSChunkLargeArrays) {
|
||||||
// we'll chunk it
|
// we'll chunk it
|
||||||
#if PS_PM_STATS
|
|
||||||
++_arrays_chunked;
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
oop* const masked_o = mask_chunked_array_oop(o);
|
oop* const masked_o = mask_chunked_array_oop(o);
|
||||||
push_depth(masked_o);
|
push_depth(masked_o);
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_masked_pushes);
|
||||||
++_masked_pushes;
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
} else {
|
} else {
|
||||||
// we'll just push its contents
|
// we'll just push its contents
|
||||||
new_obj->push_contents(this);
|
new_obj->push_contents(this);
|
||||||
|
@ -494,9 +498,7 @@ void PSPromotionManager::process_array_chunk(oop old) {
|
||||||
assert(old->is_objArray(), "invariant");
|
assert(old->is_objArray(), "invariant");
|
||||||
assert(old->is_forwarded(), "invariant");
|
assert(old->is_forwarded(), "invariant");
|
||||||
|
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(++_array_chunks_processed);
|
||||||
++_array_chunks_processed;
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
|
|
||||||
oop const obj = old->forwardee();
|
oop const obj = old->forwardee();
|
||||||
|
|
||||||
|
@ -508,9 +510,7 @@ void PSPromotionManager::process_array_chunk(oop old) {
|
||||||
assert(start > 0, "invariant");
|
assert(start > 0, "invariant");
|
||||||
arrayOop(old)->set_length(start);
|
arrayOop(old)->set_length(start);
|
||||||
push_depth(mask_chunked_array_oop(old));
|
push_depth(mask_chunked_array_oop(old));
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(++_masked_pushes);
|
||||||
++_masked_pushes;
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
} else {
|
} else {
|
||||||
// this is the final chunk for this array
|
// this is the final chunk for this array
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|
|
@ -42,8 +42,6 @@ class MutableSpace;
|
||||||
class PSOldGen;
|
class PSOldGen;
|
||||||
class ParCompactionManager;
|
class ParCompactionManager;
|
||||||
|
|
||||||
#define PS_PM_STATS 0
|
|
||||||
|
|
||||||
class PSPromotionManager : public CHeapObj {
|
class PSPromotionManager : public CHeapObj {
|
||||||
friend class PSScavenge;
|
friend class PSScavenge;
|
||||||
friend class PSRefProcTaskExecutor;
|
friend class PSRefProcTaskExecutor;
|
||||||
|
@ -54,22 +52,18 @@ class PSPromotionManager : public CHeapObj {
|
||||||
static PSOldGen* _old_gen;
|
static PSOldGen* _old_gen;
|
||||||
static MutableSpace* _young_space;
|
static MutableSpace* _young_space;
|
||||||
|
|
||||||
#if PS_PM_STATS
|
#if TASKQUEUE_STATS
|
||||||
uint _total_pushes;
|
size_t _masked_pushes;
|
||||||
uint _masked_pushes;
|
size_t _masked_steals;
|
||||||
|
size_t _arrays_chunked;
|
||||||
|
size_t _array_chunks_processed;
|
||||||
|
|
||||||
uint _overflow_pushes;
|
void print_taskqueue_stats(uint i) const;
|
||||||
uint _max_overflow_length;
|
void print_local_stats(uint i) const;
|
||||||
|
|
||||||
uint _arrays_chunked;
|
|
||||||
uint _array_chunks_processed;
|
|
||||||
|
|
||||||
uint _total_steals;
|
|
||||||
uint _masked_steals;
|
|
||||||
|
|
||||||
void print_stats(uint i);
|
|
||||||
static void print_stats();
|
static void print_stats();
|
||||||
#endif // PS_PM_STATS
|
|
||||||
|
void reset_stats();
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
PSYoungPromotionLAB _young_lab;
|
PSYoungPromotionLAB _young_lab;
|
||||||
PSOldPromotionLAB _old_lab;
|
PSOldPromotionLAB _old_lab;
|
||||||
|
@ -143,42 +137,12 @@ class PSPromotionManager : public CHeapObj {
|
||||||
|
|
||||||
template <class T> void push_depth(T* p) {
|
template <class T> void push_depth(T* p) {
|
||||||
assert(depth_first(), "pre-condition");
|
assert(depth_first(), "pre-condition");
|
||||||
|
|
||||||
#if PS_PM_STATS
|
|
||||||
++_total_pushes;
|
|
||||||
int stack_length = claimed_stack_depth()->overflow_stack()->length();
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
|
|
||||||
claimed_stack_depth()->push(p);
|
claimed_stack_depth()->push(p);
|
||||||
|
|
||||||
#if PS_PM_STATS
|
|
||||||
if (claimed_stack_depth()->overflow_stack()->length() != stack_length) {
|
|
||||||
++_overflow_pushes;
|
|
||||||
if ((uint)stack_length + 1 > _max_overflow_length) {
|
|
||||||
_max_overflow_length = (uint)stack_length + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_breadth(oop o) {
|
void push_breadth(oop o) {
|
||||||
assert(!depth_first(), "pre-condition");
|
assert(!depth_first(), "pre-condition");
|
||||||
|
|
||||||
#if PS_PM_STATS
|
|
||||||
++_total_pushes;
|
|
||||||
int stack_length = claimed_stack_breadth()->overflow_stack()->length();
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
|
|
||||||
claimed_stack_breadth()->push(o);
|
claimed_stack_breadth()->push(o);
|
||||||
|
|
||||||
#if PS_PM_STATS
|
|
||||||
if (claimed_stack_breadth()->overflow_stack()->length() != stack_length) {
|
|
||||||
++_overflow_pushes;
|
|
||||||
if ((uint)stack_length + 1 > _max_overflow_length) {
|
|
||||||
_max_overflow_length = (uint)stack_length + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -256,12 +220,5 @@ class PSPromotionManager : public CHeapObj {
|
||||||
template <class T> inline void claim_or_forward_depth(T* p);
|
template <class T> inline void claim_or_forward_depth(T* p);
|
||||||
template <class T> inline void claim_or_forward_breadth(T* p);
|
template <class T> inline void claim_or_forward_breadth(T* p);
|
||||||
|
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(inline void record_steal(StarTask& p);)
|
||||||
void increment_steals(oop* p = NULL) {
|
|
||||||
_total_steals += 1;
|
|
||||||
if (p != NULL && is_oop_masked(p)) {
|
|
||||||
_masked_steals += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -124,3 +124,11 @@ inline void PSPromotionManager::process_popped_location_depth(StarTask p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TASKQUEUE_STATS
|
||||||
|
void PSPromotionManager::record_steal(StarTask& p) {
|
||||||
|
if (is_oop_masked(p)) {
|
||||||
|
++_masked_steals;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -148,9 +148,7 @@ void StealTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
while(true) {
|
while(true) {
|
||||||
StarTask p;
|
StarTask p;
|
||||||
if (PSPromotionManager::steal_depth(which, &random_seed, p)) {
|
if (PSPromotionManager::steal_depth(which, &random_seed, p)) {
|
||||||
#if PS_PM_STATS
|
TASKQUEUE_STATS_ONLY(pm->record_steal(p));
|
||||||
pm->increment_steals(p);
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
pm->process_popped_location_depth(p);
|
pm->process_popped_location_depth(p);
|
||||||
pm->drain_stacks_depth(true);
|
pm->drain_stacks_depth(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,9 +161,6 @@ void StealTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
while(true) {
|
while(true) {
|
||||||
oop obj;
|
oop obj;
|
||||||
if (PSPromotionManager::steal_breadth(which, &random_seed, obj)) {
|
if (PSPromotionManager::steal_breadth(which, &random_seed, obj)) {
|
||||||
#if PS_PM_STATS
|
|
||||||
pm->increment_steals();
|
|
||||||
#endif // PS_PM_STATS
|
|
||||||
obj->copy_contents(pm);
|
obj->copy_contents(pm);
|
||||||
pm->drain_stacks_breadth(true);
|
pm->drain_stacks_breadth(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -86,9 +86,7 @@ class VM_GC_Operation: public VM_Operation {
|
||||||
|
|
||||||
_gc_locked = false;
|
_gc_locked = false;
|
||||||
|
|
||||||
if (full) {
|
_full_gc_count_before = full_gc_count_before;
|
||||||
_full_gc_count_before = full_gc_count_before;
|
|
||||||
}
|
|
||||||
// In ParallelScavengeHeap::mem_allocate() collections can be
|
// In ParallelScavengeHeap::mem_allocate() collections can be
|
||||||
// executed within a loop and _all_soft_refs_clear can be set
|
// executed within a loop and _all_soft_refs_clear can be set
|
||||||
// true after they have been cleared by a collection and another
|
// true after they have been cleared by a collection and another
|
||||||
|
|
|
@ -78,6 +78,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
|
||||||
case _old_generation_too_full_to_scavenge:
|
case _old_generation_too_full_to_scavenge:
|
||||||
return "Old Generation Too Full To Scavenge";
|
return "Old Generation Too Full To Scavenge";
|
||||||
|
|
||||||
|
case _g1_inc_collection_pause:
|
||||||
|
return "G1 Evacuation Pause";
|
||||||
|
|
||||||
case _last_ditch_collection:
|
case _last_ditch_collection:
|
||||||
return "Last ditch collection";
|
return "Last ditch collection";
|
||||||
|
|
||||||
|
|
|
@ -328,24 +328,35 @@ void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st)
|
||||||
constantPoolOop constants = method()->constants();
|
constantPoolOop constants = method()->constants();
|
||||||
constantTag tag = constants->tag_at(i);
|
constantTag tag = constants->tag_at(i);
|
||||||
|
|
||||||
int nt_index = -1;
|
bool has_klass = true;
|
||||||
|
|
||||||
switch (tag.value()) {
|
switch (tag.value()) {
|
||||||
case JVM_CONSTANT_InterfaceMethodref:
|
case JVM_CONSTANT_InterfaceMethodref:
|
||||||
case JVM_CONSTANT_Methodref:
|
case JVM_CONSTANT_Methodref:
|
||||||
case JVM_CONSTANT_Fieldref:
|
case JVM_CONSTANT_Fieldref:
|
||||||
|
break;
|
||||||
case JVM_CONSTANT_NameAndType:
|
case JVM_CONSTANT_NameAndType:
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
|
has_klass = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
|
|
||||||
symbolOop name = constants->uncached_name_ref_at(i);
|
symbolOop name = constants->uncached_name_ref_at(i);
|
||||||
symbolOop signature = constants->uncached_signature_ref_at(i);
|
symbolOop signature = constants->uncached_signature_ref_at(i);
|
||||||
const char* sep = (tag.is_field() ? "/" : "");
|
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());
|
if (has_klass) {
|
||||||
|
symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
|
||||||
|
st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
|
||||||
|
} else {
|
||||||
|
if (tag.is_invoke_dynamic()) {
|
||||||
|
int bsm = constants->invoke_dynamic_bootstrap_method_ref_index_at(i);
|
||||||
|
st->print(" bsm=%d", bsm);
|
||||||
|
}
|
||||||
|
st->print_cr(" %d <%s%s%s>", i, name->as_C_string(), sep, signature->as_C_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -702,10 +702,6 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
|
||||||
|
|
||||||
methodHandle caller_method(thread, method(thread));
|
methodHandle caller_method(thread, method(thread));
|
||||||
|
|
||||||
// first find the bootstrap method
|
|
||||||
KlassHandle caller_klass(thread, caller_method->method_holder());
|
|
||||||
Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, CHECK);
|
|
||||||
|
|
||||||
constantPoolHandle pool(thread, caller_method->constants());
|
constantPoolHandle pool(thread, caller_method->constants());
|
||||||
pool->set_invokedynamic(); // mark header to flag active call sites
|
pool->set_invokedynamic(); // mark header to flag active call sites
|
||||||
|
|
||||||
|
@ -726,7 +722,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
|
||||||
CallInfo info;
|
CallInfo info;
|
||||||
LinkResolver::resolve_invoke(info, Handle(), pool,
|
LinkResolver::resolve_invoke(info, Handle(), pool,
|
||||||
site_index, bytecode, CHECK);
|
site_index, bytecode, CHECK);
|
||||||
// The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves
|
// The main entry corresponds to a JVM_CONSTANT_InvokeDynamic, and serves
|
||||||
// as a common reference point for all invokedynamic call sites with
|
// as a common reference point for all invokedynamic call sites with
|
||||||
// that exact call descriptor. We will link it in the CP cache exactly
|
// that exact call descriptor. We will link it in the CP cache exactly
|
||||||
// as if it were an invokevirtual of MethodHandle.invoke.
|
// as if it were an invokevirtual of MethodHandle.invoke.
|
||||||
|
@ -734,23 +730,30 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
|
||||||
bytecode,
|
bytecode,
|
||||||
info.resolved_method(),
|
info.resolved_method(),
|
||||||
info.vtable_index());
|
info.vtable_index());
|
||||||
assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The method (f2 entry) of the main entry is the MH.invoke for the
|
// The method (f2 entry) of the main entry is the MH.invoke for the
|
||||||
// invokedynamic target call signature.
|
// invokedynamic target call signature.
|
||||||
intptr_t f2_value = pool->cache()->entry_at(main_index)->f2();
|
oop f1_value = pool->cache()->entry_at(main_index)->f1();
|
||||||
methodHandle signature_invoker(THREAD, (methodOop) f2_value);
|
methodHandle signature_invoker(THREAD, (methodOop) f1_value);
|
||||||
assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
||||||
"correct result from LinkResolver::resolve_invokedynamic");
|
"correct result from LinkResolver::resolve_invokedynamic");
|
||||||
|
|
||||||
|
Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci,
|
||||||
|
main_index, CHECK);
|
||||||
|
if (bootm.is_null()) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
|
||||||
|
"no bootstrap method found for invokedynamic");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short circuit if CallSite has been bound already:
|
||||||
|
if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null())
|
||||||
|
return;
|
||||||
|
|
||||||
symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
|
symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
|
||||||
|
|
||||||
Handle info; // NYI: Other metadata from a new kind of CP entry. (Annotations?)
|
Handle info; // NYI: Other metadata from a new kind of CP entry. (Annotations?)
|
||||||
|
|
||||||
// this is the index which gets stored on the CallSite object (as "callerPosition"):
|
|
||||||
int call_site_position = constantPoolCacheOopDesc::decode_secondary_index(site_index);
|
|
||||||
|
|
||||||
Handle call_site
|
Handle call_site
|
||||||
= SystemDictionary::make_dynamic_call_site(bootm,
|
= SystemDictionary::make_dynamic_call_site(bootm,
|
||||||
// Callee information:
|
// Callee information:
|
||||||
|
|
|
@ -67,6 +67,15 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas
|
||||||
set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK);
|
set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallInfo::set_dynamic(methodHandle resolved_method, TRAPS) {
|
||||||
|
assert(resolved_method->is_method_handle_invoke(), "");
|
||||||
|
KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||||
|
assert(resolved_klass == resolved_method->method_holder(), "");
|
||||||
|
int vtable_index = methodOopDesc::nonvirtual_vtable_index;
|
||||||
|
assert(resolved_method->vtable_index() == vtable_index, "");
|
||||||
|
set_common(resolved_klass, KlassHandle(), resolved_method, resolved_method, vtable_index, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
|
void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
|
||||||
assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond");
|
assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond");
|
||||||
_resolved_klass = resolved_klass;
|
_resolved_klass = resolved_klass;
|
||||||
|
@ -176,9 +185,20 @@ void LinkResolver::lookup_implicit_method(methodHandle& result,
|
||||||
KlassHandle klass, symbolHandle name, symbolHandle signature,
|
KlassHandle klass, symbolHandle name, symbolHandle signature,
|
||||||
KlassHandle current_klass,
|
KlassHandle current_klass,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
if (EnableMethodHandles && MethodHandles::enabled() &&
|
if (EnableMethodHandles &&
|
||||||
klass() == SystemDictionary::MethodHandle_klass() &&
|
klass() == SystemDictionary::MethodHandle_klass() &&
|
||||||
methodOopDesc::is_method_handle_invoke_name(name())) {
|
methodOopDesc::is_method_handle_invoke_name(name())) {
|
||||||
|
if (!MethodHandles::enabled()) {
|
||||||
|
// Make sure the Java part of the runtime has been booted up.
|
||||||
|
klassOop natives = SystemDictionary::MethodHandleNatives_klass();
|
||||||
|
if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) {
|
||||||
|
SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_dyn_MethodHandleNatives(),
|
||||||
|
Handle(),
|
||||||
|
Handle(),
|
||||||
|
true,
|
||||||
|
CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
methodOop result_oop = SystemDictionary::find_method_handle_invoke(name,
|
methodOop result_oop = SystemDictionary::find_method_handle_invoke(name,
|
||||||
signature,
|
signature,
|
||||||
current_klass,
|
current_klass,
|
||||||
|
@ -1065,7 +1085,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
|
||||||
if (resolved_method.is_null()) {
|
if (resolved_method.is_null()) {
|
||||||
THROW(vmSymbols::java_lang_InternalError());
|
THROW(vmSymbols::java_lang_InternalError());
|
||||||
}
|
}
|
||||||
result.set_virtual(resolved_klass, KlassHandle(), resolved_method, resolved_method, resolved_method->vtable_index(), CHECK);
|
result.set_dynamic(resolved_method, CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -73,6 +73,7 @@ class CallInfo: public LinkInfo {
|
||||||
void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
|
void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
|
||||||
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS);
|
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS);
|
||||||
void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
|
void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
|
||||||
|
void set_dynamic( methodHandle resolved_method, TRAPS);
|
||||||
void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
|
void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
|
||||||
|
|
||||||
friend class LinkResolver;
|
friend class LinkResolver;
|
||||||
|
|
|
@ -32,14 +32,17 @@
|
||||||
void Rewriter::compute_index_maps() {
|
void Rewriter::compute_index_maps() {
|
||||||
const int length = _pool->length();
|
const int length = _pool->length();
|
||||||
init_cp_map(length);
|
init_cp_map(length);
|
||||||
|
jint tag_mask = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
int tag = _pool->tag_at(i).value();
|
int tag = _pool->tag_at(i).value();
|
||||||
|
tag_mask |= (1 << tag);
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case JVM_CONSTANT_InterfaceMethodref:
|
case JVM_CONSTANT_InterfaceMethodref:
|
||||||
case JVM_CONSTANT_Fieldref : // fall through
|
case JVM_CONSTANT_Fieldref : // fall through
|
||||||
case JVM_CONSTANT_Methodref : // fall through
|
case JVM_CONSTANT_Methodref : // fall through
|
||||||
case JVM_CONSTANT_MethodHandle : // fall through
|
case JVM_CONSTANT_MethodHandle : // fall through
|
||||||
case JVM_CONSTANT_MethodType : // fall through
|
case JVM_CONSTANT_MethodType : // fall through
|
||||||
|
case JVM_CONSTANT_InvokeDynamic : // fall through
|
||||||
add_cp_cache_entry(i);
|
add_cp_cache_entry(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +50,8 @@ void Rewriter::compute_index_maps() {
|
||||||
|
|
||||||
guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1),
|
guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1),
|
||||||
"all cp cache indexes fit in a u2");
|
"all cp cache indexes fit in a u2");
|
||||||
|
|
||||||
|
_have_invoke_dynamic = ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamic)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +64,28 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
|
||||||
constantPoolCacheOop cache =
|
constantPoolCacheOop cache =
|
||||||
oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK);
|
oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK);
|
||||||
cache->initialize(_cp_cache_map);
|
cache->initialize(_cp_cache_map);
|
||||||
|
|
||||||
|
// Don't bother to the next pass if there is no JVM_CONSTANT_InvokeDynamic.
|
||||||
|
if (_have_invoke_dynamic) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int pool_index = cp_cache_entry_pool_index(i);
|
||||||
|
if (pool_index >= 0 &&
|
||||||
|
_pool->tag_at(pool_index).is_invoke_dynamic()) {
|
||||||
|
int bsm_index = _pool->invoke_dynamic_bootstrap_method_ref_index_at(pool_index);
|
||||||
|
if (bsm_index != 0) {
|
||||||
|
assert(_pool->tag_at(bsm_index).is_method_handle(), "must be a MH constant");
|
||||||
|
// There is a CP cache entry holding the BSM for these calls.
|
||||||
|
int bsm_cache_index = cp_entry_to_cp_cache(bsm_index);
|
||||||
|
cache->entry_at(i)->initialize_bootstrap_method_index_in_cache(bsm_cache_index);
|
||||||
|
} else {
|
||||||
|
// There is no CP cache entry holding the BSM for these calls.
|
||||||
|
// We will need to look for a class-global BSM, later.
|
||||||
|
guarantee(AllowTransitionalJSR292, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_pool->set_cache(cache);
|
_pool->set_cache(cache);
|
||||||
cache->set_constant_pool(_pool());
|
cache->set_constant_pool(_pool());
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ class Rewriter: public StackObj {
|
||||||
objArrayHandle _methods;
|
objArrayHandle _methods;
|
||||||
intArray _cp_map;
|
intArray _cp_map;
|
||||||
intStack _cp_cache_map;
|
intStack _cp_cache_map;
|
||||||
|
bool _have_invoke_dynamic;
|
||||||
|
|
||||||
void init_cp_map(int length) {
|
void init_cp_map(int length) {
|
||||||
_cp_map.initialize(length, -1);
|
_cp_map.initialize(length, -1);
|
||||||
|
@ -56,6 +57,22 @@ class Rewriter: public StackObj {
|
||||||
return cache_index;
|
return cache_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Access the contents of _cp_cache_map to determine CP cache layout.
|
||||||
|
int cp_cache_entry_pool_index(int cache_index) {
|
||||||
|
int cp_index = _cp_cache_map[cache_index];
|
||||||
|
if ((cp_index & _secondary_entry_tag) != 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return cp_index;
|
||||||
|
}
|
||||||
|
int cp_cache_secondary_entry_main_index(int cache_index) {
|
||||||
|
int cp_index = _cp_cache_map[cache_index];
|
||||||
|
if ((cp_index & _secondary_entry_tag) == 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (cp_index - _secondary_entry_tag);
|
||||||
|
}
|
||||||
|
|
||||||
// All the work goes in here:
|
// All the work goes in here:
|
||||||
Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
|
Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
|
||||||
|
|
||||||
|
|
|
@ -379,6 +379,10 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
|
||||||
case JVM_CONSTANT_MethodType :
|
case JVM_CONSTANT_MethodType :
|
||||||
st->print("signature_index=%d", cp->method_type_index_at(index));
|
st->print("signature_index=%d", cp->method_type_index_at(index));
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_InvokeDynamic :
|
||||||
|
st->print("bootstrap_method_index=%d", cp->invoke_dynamic_bootstrap_method_ref_index_at(index));
|
||||||
|
st->print(" name_and_type_index=%d", cp->invoke_dynamic_name_and_type_ref_index_at(index));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -264,10 +264,15 @@ symbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
|
||||||
int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
|
int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
|
||||||
int i = which;
|
int i = which;
|
||||||
if (!uncached && cache() != NULL) {
|
if (!uncached && cache() != NULL) {
|
||||||
if (constantPoolCacheOopDesc::is_secondary_index(which))
|
if (constantPoolCacheOopDesc::is_secondary_index(which)) {
|
||||||
// Invokedynamic indexes are always processed in native order
|
// Invokedynamic indexes are always processed in native order
|
||||||
// so there is no question of reading a native u2 in Java order here.
|
// so there is no question of reading a native u2 in Java order here.
|
||||||
return cache()->main_entry_at(which)->constant_pool_index();
|
int pool_index = cache()->main_entry_at(which)->constant_pool_index();
|
||||||
|
if (tag_at(pool_index).is_invoke_dynamic())
|
||||||
|
pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index);
|
||||||
|
assert(tag_at(pool_index).is_name_and_type(), "");
|
||||||
|
return pool_index;
|
||||||
|
}
|
||||||
// change byte-ordering and go via cache
|
// change byte-ordering and go via cache
|
||||||
i = remap_instruction_operand_from_cache(which);
|
i = remap_instruction_operand_from_cache(which);
|
||||||
} else {
|
} else {
|
||||||
|
@ -830,6 +835,19 @@ bool constantPoolOopDesc::compare_entry_to(int index1, constantPoolHandle cp2,
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
|
{
|
||||||
|
int k1 = invoke_dynamic_bootstrap_method_ref_index_at(index1);
|
||||||
|
int k2 = cp2->invoke_dynamic_bootstrap_method_ref_index_at(index2);
|
||||||
|
if (k1 == k2) {
|
||||||
|
int i1 = invoke_dynamic_name_and_type_ref_index_at(index1);
|
||||||
|
int i2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
|
||||||
|
if (i1 == i2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case JVM_CONSTANT_UnresolvedString:
|
case JVM_CONSTANT_UnresolvedString:
|
||||||
{
|
{
|
||||||
symbolOop s1 = unresolved_string_at(index1);
|
symbolOop s1 = unresolved_string_at(index1);
|
||||||
|
@ -1016,6 +1034,13 @@ void constantPoolOopDesc::copy_entry_to(int from_i, constantPoolHandle to_cp,
|
||||||
to_cp->method_handle_index_at_put(to_i, k1, k2);
|
to_cp->method_handle_index_at_put(to_i, k1, k2);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
|
{
|
||||||
|
int k1 = invoke_dynamic_bootstrap_method_ref_index_at(from_i);
|
||||||
|
int k2 = invoke_dynamic_name_and_type_ref_index_at(from_i);
|
||||||
|
to_cp->invoke_dynamic_at_put(to_i, k1, k2);
|
||||||
|
} break;
|
||||||
|
|
||||||
// Invalid is used as the tag for the second constant pool entry
|
// Invalid is used as the tag for the second constant pool entry
|
||||||
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
|
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
|
||||||
// not be seen by itself.
|
// not be seen by itself.
|
||||||
|
@ -1231,6 +1256,7 @@ jint constantPoolOopDesc::cpool_entry_size(jint idx) {
|
||||||
case JVM_CONSTANT_Methodref:
|
case JVM_CONSTANT_Methodref:
|
||||||
case JVM_CONSTANT_InterfaceMethodref:
|
case JVM_CONSTANT_InterfaceMethodref:
|
||||||
case JVM_CONSTANT_NameAndType:
|
case JVM_CONSTANT_NameAndType:
|
||||||
|
case JVM_CONSTANT_InvokeDynamic:
|
||||||
return 5;
|
return 5;
|
||||||
|
|
||||||
case JVM_CONSTANT_Long:
|
case JVM_CONSTANT_Long:
|
||||||
|
@ -1444,6 +1470,15 @@ int constantPoolOopDesc::copy_cpool_bytes(int cpool_size,
|
||||||
DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
|
DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case JVM_CONSTANT_InvokeDynamic: {
|
||||||
|
*bytes = JVM_CONSTANT_InvokeDynamic;
|
||||||
|
idx1 = invoke_dynamic_bootstrap_method_ref_index_at(idx);
|
||||||
|
idx2 = invoke_dynamic_name_and_type_ref_index_at(idx);
|
||||||
|
Bytes::put_Java_u2((address) (bytes+1), idx1);
|
||||||
|
Bytes::put_Java_u2((address) (bytes+3), idx2);
|
||||||
|
DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd", idx1, idx2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBG(printf("\n"));
|
DBG(printf("\n"));
|
||||||
bytes += ent_size;
|
bytes += ent_size;
|
||||||
|
|
|
@ -156,6 +156,11 @@ class constantPoolOopDesc : public oopDesc {
|
||||||
*int_at_addr(which) = ref_index;
|
*int_at_addr(which) = ref_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void invoke_dynamic_at_put(int which, int bootstrap_method_index, int name_and_type_index) {
|
||||||
|
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
|
||||||
|
*int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index;
|
||||||
|
}
|
||||||
|
|
||||||
// Temporary until actual use
|
// Temporary until actual use
|
||||||
void unresolved_string_at_put(int which, symbolOop s) {
|
void unresolved_string_at_put(int which, symbolOop s) {
|
||||||
*obj_at_addr(which) = NULL;
|
*obj_at_addr(which) = NULL;
|
||||||
|
@ -396,6 +401,16 @@ class constantPoolOopDesc : public oopDesc {
|
||||||
int sym = method_type_index_at(which);
|
int sym = method_type_index_at(which);
|
||||||
return symbol_at(sym);
|
return symbol_at(sym);
|
||||||
}
|
}
|
||||||
|
int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
|
||||||
|
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
|
||||||
|
jint ref_index = *int_at_addr(which);
|
||||||
|
return extract_low_short_from_int(ref_index);
|
||||||
|
}
|
||||||
|
int invoke_dynamic_name_and_type_ref_index_at(int which) {
|
||||||
|
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
|
||||||
|
jint ref_index = *int_at_addr(which);
|
||||||
|
return extract_high_short_from_int(ref_index);
|
||||||
|
}
|
||||||
|
|
||||||
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
|
// 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
|
// name_and_type_ref_index_at) all expect to be passed indices obtained
|
||||||
|
|
|
@ -134,7 +134,7 @@ int ConstantPoolCacheEntry::field_index() const {
|
||||||
void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||||
methodHandle method,
|
methodHandle method,
|
||||||
int vtable_index) {
|
int vtable_index) {
|
||||||
|
assert(!is_secondary_entry(), "");
|
||||||
assert(method->interpreter_entry() != NULL, "should have been set at this point");
|
assert(method->interpreter_entry() != NULL, "should have been set at this point");
|
||||||
assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
|
assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
|
||||||
bool change_to_virtual = (invoke_code == Bytecodes::_invokeinterface);
|
bool change_to_virtual = (invoke_code == Bytecodes::_invokeinterface);
|
||||||
|
@ -142,7 +142,6 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||||
int byte_no = -1;
|
int byte_no = -1;
|
||||||
bool needs_vfinal_flag = false;
|
bool needs_vfinal_flag = false;
|
||||||
switch (invoke_code) {
|
switch (invoke_code) {
|
||||||
case Bytecodes::_invokedynamic:
|
|
||||||
case Bytecodes::_invokevirtual:
|
case Bytecodes::_invokevirtual:
|
||||||
case Bytecodes::_invokeinterface: {
|
case Bytecodes::_invokeinterface: {
|
||||||
if (method->can_be_statically_bound()) {
|
if (method->can_be_statically_bound()) {
|
||||||
|
@ -155,6 +154,23 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||||
byte_no = 2;
|
byte_no = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Bytecodes::_invokedynamic: // similar to _invokevirtual
|
||||||
|
if (TraceInvokeDynamic) {
|
||||||
|
tty->print_cr("InvokeDynamic set_method%s method="PTR_FORMAT" index=%d",
|
||||||
|
(is_secondary_entry() ? " secondary" : ""),
|
||||||
|
(intptr_t)method(), vtable_index);
|
||||||
|
method->print();
|
||||||
|
this->print(tty, 0);
|
||||||
|
}
|
||||||
|
assert(method->can_be_statically_bound(), "must be a MH invoker method");
|
||||||
|
assert(AllowTransitionalJSR292 || _f2 >= constantPoolOopDesc::CPCACHE_INDEX_TAG, "BSM index initialized");
|
||||||
|
set_f1(method());
|
||||||
|
needs_vfinal_flag = false; // _f2 is not an oop
|
||||||
|
assert(!is_vfinal(), "f2 not an oop");
|
||||||
|
byte_no = 1; // coordinate this with bytecode_number & is_resolved
|
||||||
|
break;
|
||||||
|
|
||||||
case Bytecodes::_invokespecial:
|
case Bytecodes::_invokespecial:
|
||||||
// Preserve the value of the vfinal flag on invokevirtual bytecode
|
// Preserve the value of the vfinal flag on invokevirtual bytecode
|
||||||
// which may be shared with this constant pool cache entry.
|
// which may be shared with this constant pool cache entry.
|
||||||
|
@ -209,6 +225,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||||
|
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) {
|
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) {
|
||||||
|
assert(!is_secondary_entry(), "");
|
||||||
klassOop interf = method->method_holder();
|
klassOop interf = method->method_holder();
|
||||||
assert(instanceKlass::cast(interf)->is_interface(), "must be an interface");
|
assert(instanceKlass::cast(interf)->is_interface(), "must be an interface");
|
||||||
set_f1(interf);
|
set_f1(interf);
|
||||||
|
@ -218,8 +235,23 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConstantPoolCacheEntry::initialize_bootstrap_method_index_in_cache(int bsm_cache_index) {
|
||||||
|
assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry");
|
||||||
|
assert(_f2 == 0, "initialize once");
|
||||||
|
assert(bsm_cache_index == (int)(u2)bsm_cache_index, "oob");
|
||||||
|
set_f2(bsm_cache_index + constantPoolOopDesc::CPCACHE_INDEX_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConstantPoolCacheEntry::bootstrap_method_index_in_cache() {
|
||||||
|
assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry");
|
||||||
|
intptr_t bsm_cache_index = (intptr_t) _f2 - constantPoolOopDesc::CPCACHE_INDEX_TAG;
|
||||||
|
assert(bsm_cache_index == (intptr_t)(u2)bsm_cache_index, "oob");
|
||||||
|
return (int) bsm_cache_index;
|
||||||
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
|
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
|
||||||
methodHandle signature_invoker) {
|
methodHandle signature_invoker) {
|
||||||
|
assert(is_secondary_entry(), "");
|
||||||
int param_size = signature_invoker->size_of_parameters();
|
int param_size = signature_invoker->size_of_parameters();
|
||||||
assert(param_size >= 1, "method argument size must include MH.this");
|
assert(param_size >= 1, "method argument size must include MH.this");
|
||||||
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
|
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
|
||||||
|
@ -227,7 +259,6 @@ void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
|
||||||
// racing threads might be trying to install their own favorites
|
// racing threads might be trying to install their own favorites
|
||||||
set_f1(call_site());
|
set_f1(call_site());
|
||||||
}
|
}
|
||||||
//set_f2(0);
|
|
||||||
bool is_final = true;
|
bool is_final = true;
|
||||||
assert(signature_invoker->is_final_method(), "is_final");
|
assert(signature_invoker->is_final_method(), "is_final");
|
||||||
set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size);
|
set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size);
|
||||||
|
@ -417,14 +448,14 @@ void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
|
||||||
// print separator
|
// print separator
|
||||||
if (index == 0) tty->print_cr(" -------------");
|
if (index == 0) tty->print_cr(" -------------");
|
||||||
// print entry
|
// print entry
|
||||||
tty->print_cr("%3d (%08x) ", index, this);
|
tty->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
|
||||||
if (is_secondary_entry())
|
if (is_secondary_entry())
|
||||||
tty->print_cr("[%5d|secondary]", main_entry_index());
|
tty->print_cr("[%5d|secondary]", main_entry_index());
|
||||||
else
|
else
|
||||||
tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
|
tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
|
||||||
tty->print_cr(" [ %08x]", (address)(oop)_f1);
|
tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)(oop)_f1);
|
||||||
tty->print_cr(" [ %08x]", _f2);
|
tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
|
||||||
tty->print_cr(" [ %08x]", _flags);
|
tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
|
||||||
tty->print_cr(" -------------");
|
tty->print_cr(" -------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,10 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
methodHandle signature_invoker // determines signature information
|
methodHandle signature_invoker // determines signature information
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// For JVM_CONSTANT_InvokeDynamic cache entries:
|
||||||
|
void initialize_bootstrap_method_index_in_cache(int bsm_cache_index);
|
||||||
|
int bootstrap_method_index_in_cache();
|
||||||
|
|
||||||
void set_parameter_size(int value) {
|
void set_parameter_size(int value) {
|
||||||
assert(parameter_size() == 0 || parameter_size() == value,
|
assert(parameter_size() == 0 || parameter_size() == value,
|
||||||
"size must not change");
|
"size must not change");
|
||||||
|
@ -207,6 +211,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
case Bytecodes::_getfield : // fall through
|
case Bytecodes::_getfield : // fall through
|
||||||
case Bytecodes::_invokespecial : // fall through
|
case Bytecodes::_invokespecial : // fall through
|
||||||
case Bytecodes::_invokestatic : // fall through
|
case Bytecodes::_invokestatic : // fall through
|
||||||
|
case Bytecodes::_invokedynamic : // fall through
|
||||||
case Bytecodes::_invokeinterface : return 1;
|
case Bytecodes::_invokeinterface : return 1;
|
||||||
case Bytecodes::_putstatic : // fall through
|
case Bytecodes::_putstatic : // fall through
|
||||||
case Bytecodes::_putfield : // fall through
|
case Bytecodes::_putfield : // fall through
|
||||||
|
@ -234,6 +239,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); }
|
Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); }
|
||||||
Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); }
|
Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); }
|
||||||
volatile oop f1() const { return _f1; }
|
volatile oop f1() const { return _f1; }
|
||||||
|
bool is_f1_null() const { return (oop)_f1 == NULL; } // classifies a CPC entry as unbound
|
||||||
intx f2() const { return _f2; }
|
intx f2() const { return _f2; }
|
||||||
int field_index() const;
|
int field_index() const;
|
||||||
int parameter_size() const { return _flags & 0xFF; }
|
int parameter_size() const { return _flags & 0xFF; }
|
||||||
|
|
|
@ -851,9 +851,15 @@ jint* methodOopDesc::method_type_offsets_chain() {
|
||||||
// MethodHandleCompiler.
|
// MethodHandleCompiler.
|
||||||
// Must be consistent with MethodHandleCompiler::get_method_oop().
|
// Must be consistent with MethodHandleCompiler::get_method_oop().
|
||||||
bool methodOopDesc::is_method_handle_adapter() const {
|
bool methodOopDesc::is_method_handle_adapter() const {
|
||||||
return (is_method_handle_invoke_name(name()) &&
|
if (is_synthetic() &&
|
||||||
is_synthetic() &&
|
!is_native() && // has code from MethodHandleCompiler
|
||||||
MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder()));
|
is_method_handle_invoke_name(name()) &&
|
||||||
|
MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())) {
|
||||||
|
assert(!is_method_handle_invoke(), "disjoint");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||||
|
|
|
@ -1046,7 +1046,8 @@ enum {
|
||||||
JVM_CONSTANT_InterfaceMethodref,
|
JVM_CONSTANT_InterfaceMethodref,
|
||||||
JVM_CONSTANT_NameAndType,
|
JVM_CONSTANT_NameAndType,
|
||||||
JVM_CONSTANT_MethodHandle = 15, // JSR 292
|
JVM_CONSTANT_MethodHandle = 15, // JSR 292
|
||||||
JVM_CONSTANT_MethodType = 16 // JSR 292
|
JVM_CONSTANT_MethodType = 16, // JSR 292
|
||||||
|
JVM_CONSTANT_InvokeDynamic = 17 // JSR 292
|
||||||
};
|
};
|
||||||
|
|
||||||
/* JVM_CONSTANT_MethodHandle subtypes */
|
/* JVM_CONSTANT_MethodHandle subtypes */
|
||||||
|
|
|
@ -738,6 +738,12 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
|
||||||
|
|
||||||
// bi
|
// bi
|
||||||
case Bytecodes::_ldc:
|
case Bytecodes::_ldc:
|
||||||
|
assert(Bytecodes::format_bits(op, false) == (Bytecodes::_fmt_b|Bytecodes::_fmt_has_k), "wrong bytecode format");
|
||||||
|
assert((char) index == index, "index does not fit in 8-bit");
|
||||||
|
_bytecode.push(op);
|
||||||
|
_bytecode.push(index);
|
||||||
|
break;
|
||||||
|
|
||||||
case Bytecodes::_iload:
|
case Bytecodes::_iload:
|
||||||
case Bytecodes::_lload:
|
case Bytecodes::_lload:
|
||||||
case Bytecodes::_fload:
|
case Bytecodes::_fload:
|
||||||
|
@ -754,7 +760,8 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
|
||||||
_bytecode.push(index);
|
_bytecode.push(index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// bii
|
// bkk
|
||||||
|
case Bytecodes::_ldc_w:
|
||||||
case Bytecodes::_ldc2_w:
|
case Bytecodes::_ldc2_w:
|
||||||
case Bytecodes::_checkcast:
|
case Bytecodes::_checkcast:
|
||||||
assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format");
|
assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format");
|
||||||
|
|
|
@ -2475,6 +2475,10 @@ JVM_END
|
||||||
|
|
||||||
JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) {
|
JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) {
|
||||||
instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD);
|
instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD);
|
||||||
|
if (!AllowTransitionalJSR292) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||||
|
"registerBootstrapMethod is only supported in JSR 292 EDR");
|
||||||
|
}
|
||||||
ik->link_class(CHECK);
|
ik->link_class(CHECK);
|
||||||
if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) {
|
if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) {
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle");
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle");
|
||||||
|
|
|
@ -3517,6 +3517,9 @@ class CommandLineFlags {
|
||||||
experimental(bool, EnableInvokeDynamic, false, \
|
experimental(bool, EnableInvokeDynamic, false, \
|
||||||
"recognize the invokedynamic instruction") \
|
"recognize the invokedynamic instruction") \
|
||||||
\
|
\
|
||||||
|
experimental(bool, AllowTransitionalJSR292, true, \
|
||||||
|
"recognize pre-PFD formats of invokedynamic") \
|
||||||
|
\
|
||||||
develop(bool, TraceInvokeDynamic, false, \
|
develop(bool, TraceInvokeDynamic, false, \
|
||||||
"trace internal invoke dynamic operations") \
|
"trace internal invoke dynamic operations") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -159,6 +159,8 @@ void mutex_init() {
|
||||||
def(STS_init_lock , Mutex, leaf, true );
|
def(STS_init_lock , Mutex, leaf, true );
|
||||||
if (UseConcMarkSweepGC) {
|
if (UseConcMarkSweepGC) {
|
||||||
def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification
|
def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification
|
||||||
|
}
|
||||||
|
if (UseConcMarkSweepGC || UseG1GC) {
|
||||||
def(FullGCCount_lock , Monitor, leaf, true ); // in support of ExplicitGCInvokesConcurrent
|
def(FullGCCount_lock , Monitor, leaf, true ); // in support of ExplicitGCInvokesConcurrent
|
||||||
}
|
}
|
||||||
if (UseG1GC) {
|
if (UseG1GC) {
|
||||||
|
|
|
@ -91,6 +91,8 @@ const char* constantTag::internal_name() const {
|
||||||
return "MethodHandle";
|
return "MethodHandle";
|
||||||
case JVM_CONSTANT_MethodType :
|
case JVM_CONSTANT_MethodType :
|
||||||
return "MethodType";
|
return "MethodType";
|
||||||
|
case JVM_CONSTANT_InvokeDynamic :
|
||||||
|
return "InvokeDynamic";
|
||||||
case JVM_CONSTANT_Object :
|
case JVM_CONSTANT_Object :
|
||||||
return "Object";
|
return "Object";
|
||||||
case JVM_CONSTANT_Utf8 :
|
case JVM_CONSTANT_Utf8 :
|
||||||
|
|
|
@ -80,13 +80,14 @@ class constantTag VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; }
|
bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; }
|
||||||
bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; }
|
bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; }
|
||||||
|
bool is_invoke_dynamic() const { return _tag == JVM_CONSTANT_InvokeDynamic; }
|
||||||
|
|
||||||
constantTag() {
|
constantTag() {
|
||||||
_tag = JVM_CONSTANT_Invalid;
|
_tag = JVM_CONSTANT_Invalid;
|
||||||
}
|
}
|
||||||
constantTag(jbyte tag) {
|
constantTag(jbyte tag) {
|
||||||
assert((tag >= 0 && tag <= JVM_CONSTANT_NameAndType) ||
|
assert((tag >= 0 && tag <= JVM_CONSTANT_NameAndType) ||
|
||||||
(tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_MethodType) ||
|
(tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_InvokeDynamic) ||
|
||||||
(tag >= JVM_CONSTANT_InternalMin && tag <= JVM_CONSTANT_InternalMax), "Invalid constant tag");
|
(tag >= JVM_CONSTANT_InternalMin && tag <= JVM_CONSTANT_InternalMax), "Invalid constant tag");
|
||||||
_tag = tag;
|
_tag = tag;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -345,6 +345,35 @@ inline intptr_t align_object_offset(intptr_t offset) {
|
||||||
return align_size_up(offset, HeapWordsPerLong);
|
return align_size_up(offset, HeapWordsPerLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The expected size in bytes of a cache line, used to pad data structures.
|
||||||
|
#define DEFAULT_CACHE_LINE_SIZE 64
|
||||||
|
|
||||||
|
// Bytes needed to pad type to avoid cache-line sharing; alignment should be the
|
||||||
|
// expected cache line size (a power of two). The first addend avoids sharing
|
||||||
|
// when the start address is not a multiple of alignment; the second maintains
|
||||||
|
// alignment of starting addresses that happen to be a multiple.
|
||||||
|
#define PADDING_SIZE(type, alignment) \
|
||||||
|
((alignment) + align_size_up_(sizeof(type), alignment))
|
||||||
|
|
||||||
|
// Templates to create a subclass padded to avoid cache line sharing. These are
|
||||||
|
// effective only when applied to derived-most (leaf) classes.
|
||||||
|
|
||||||
|
// When no args are passed to the base ctor.
|
||||||
|
template <class T, size_t alignment = DEFAULT_CACHE_LINE_SIZE>
|
||||||
|
class Padded: public T {
|
||||||
|
private:
|
||||||
|
char _pad_buf_[PADDING_SIZE(T, alignment)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// When either 0 or 1 args may be passed to the base ctor.
|
||||||
|
template <class T, typename Arg1T, size_t alignment = DEFAULT_CACHE_LINE_SIZE>
|
||||||
|
class Padded01: public T {
|
||||||
|
public:
|
||||||
|
Padded01(): T() { }
|
||||||
|
Padded01(Arg1T arg1): T(arg1) { }
|
||||||
|
private:
|
||||||
|
char _pad_buf_[PADDING_SIZE(T, alignment)];
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Utility macros for compilers
|
// Utility macros for compilers
|
||||||
|
|
|
@ -31,6 +31,48 @@ uint ParallelTaskTerminator::_total_spins = 0;
|
||||||
uint ParallelTaskTerminator::_total_peeks = 0;
|
uint ParallelTaskTerminator::_total_peeks = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TASKQUEUE_STATS
|
||||||
|
const char * const TaskQueueStats::_names[last_stat_id] = {
|
||||||
|
"qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax"
|
||||||
|
};
|
||||||
|
|
||||||
|
void TaskQueueStats::print_header(unsigned int line, outputStream* const stream,
|
||||||
|
unsigned int width)
|
||||||
|
{
|
||||||
|
// Use a width w: 1 <= w <= max_width
|
||||||
|
const unsigned int max_width = 40;
|
||||||
|
const unsigned int w = MAX2(MIN2(width, max_width), 1U);
|
||||||
|
|
||||||
|
if (line == 0) { // spaces equal in width to the header
|
||||||
|
const unsigned int hdr_width = w * last_stat_id + last_stat_id - 1;
|
||||||
|
stream->print("%*s", hdr_width, " ");
|
||||||
|
} else if (line == 1) { // labels
|
||||||
|
stream->print("%*s", w, _names[0]);
|
||||||
|
for (unsigned int i = 1; i < last_stat_id; ++i) {
|
||||||
|
stream->print(" %*s", w, _names[i]);
|
||||||
|
}
|
||||||
|
} else if (line == 2) { // dashed lines
|
||||||
|
char dashes[max_width + 1];
|
||||||
|
memset(dashes, '-', w);
|
||||||
|
dashes[w] = '\0';
|
||||||
|
stream->print("%s", dashes);
|
||||||
|
for (unsigned int i = 1; i < last_stat_id; ++i) {
|
||||||
|
stream->print(" %s", dashes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskQueueStats::print(outputStream* stream, unsigned int width) const
|
||||||
|
{
|
||||||
|
#define FMT SIZE_FORMAT_W(*)
|
||||||
|
stream->print(FMT, width, _stats[0]);
|
||||||
|
for (unsigned int i = 1; i < last_stat_id; ++i) {
|
||||||
|
stream->print(" " FMT, width, _stats[i]);
|
||||||
|
}
|
||||||
|
#undef FMT
|
||||||
|
}
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
int TaskQueueSetSuper::randomParkAndMiller(int *seed0) {
|
int TaskQueueSetSuper::randomParkAndMiller(int *seed0) {
|
||||||
const int a = 16807;
|
const int a = 16807;
|
||||||
const int m = 2147483647;
|
const int m = 2147483647;
|
||||||
|
|
|
@ -22,6 +22,72 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Simple TaskQueue stats that are collected by default in debug builds.
|
||||||
|
|
||||||
|
#if !defined(TASKQUEUE_STATS) && defined(ASSERT)
|
||||||
|
#define TASKQUEUE_STATS 1
|
||||||
|
#elif !defined(TASKQUEUE_STATS)
|
||||||
|
#define TASKQUEUE_STATS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TASKQUEUE_STATS
|
||||||
|
#define TASKQUEUE_STATS_ONLY(code) code
|
||||||
|
#else
|
||||||
|
#define TASKQUEUE_STATS_ONLY(code)
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
|
#if TASKQUEUE_STATS
|
||||||
|
class TaskQueueStats {
|
||||||
|
public:
|
||||||
|
enum StatId {
|
||||||
|
push, // number of taskqueue pushes
|
||||||
|
pop, // number of taskqueue pops
|
||||||
|
pop_slow, // subset of taskqueue pops that were done slow-path
|
||||||
|
steal_attempt, // number of taskqueue steal attempts
|
||||||
|
steal, // number of taskqueue steals
|
||||||
|
overflow, // number of overflow pushes
|
||||||
|
overflow_max_len, // max length of overflow stack
|
||||||
|
last_stat_id
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline TaskQueueStats() { reset(); }
|
||||||
|
|
||||||
|
inline void record_push() { ++_stats[push]; }
|
||||||
|
inline void record_pop() { ++_stats[pop]; }
|
||||||
|
inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; }
|
||||||
|
inline void record_steal(bool success);
|
||||||
|
inline void record_overflow(size_t new_length);
|
||||||
|
|
||||||
|
inline size_t get(StatId id) const { return _stats[id]; }
|
||||||
|
inline const size_t* get() const { return _stats; }
|
||||||
|
|
||||||
|
inline void reset();
|
||||||
|
|
||||||
|
static void print_header(unsigned int line, outputStream* const stream = tty,
|
||||||
|
unsigned int width = 10);
|
||||||
|
void print(outputStream* const stream = tty, unsigned int width = 10) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _stats[last_stat_id];
|
||||||
|
static const char * const _names[last_stat_id];
|
||||||
|
};
|
||||||
|
|
||||||
|
void TaskQueueStats::record_steal(bool success) {
|
||||||
|
++_stats[steal_attempt];
|
||||||
|
if (success) ++_stats[steal];
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskQueueStats::record_overflow(size_t new_len) {
|
||||||
|
++_stats[overflow];
|
||||||
|
if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskQueueStats::reset() {
|
||||||
|
memset(_stats, 0, sizeof(_stats));
|
||||||
|
}
|
||||||
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
template <unsigned int N>
|
template <unsigned int N>
|
||||||
class TaskQueueSuper: public CHeapObj {
|
class TaskQueueSuper: public CHeapObj {
|
||||||
protected:
|
protected:
|
||||||
|
@ -135,6 +201,8 @@ public:
|
||||||
|
|
||||||
// Total size of queue.
|
// Total size of queue.
|
||||||
static const uint total_size() { return N; }
|
static const uint total_size() { return N; }
|
||||||
|
|
||||||
|
TASKQUEUE_STATS_ONLY(TaskQueueStats stats;)
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class E, unsigned int N = TASKQUEUE_SIZE>
|
template<class E, unsigned int N = TASKQUEUE_SIZE>
|
||||||
|
@ -152,6 +220,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
using TaskQueueSuper<N>::max_elems;
|
using TaskQueueSuper<N>::max_elems;
|
||||||
using TaskQueueSuper<N>::size;
|
using TaskQueueSuper<N>::size;
|
||||||
|
TASKQUEUE_STATS_ONLY(using TaskQueueSuper<N>::stats;)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Slow paths for push, pop_local. (pop_global has no fast path.)
|
// Slow paths for push, pop_local. (pop_global has no fast path.)
|
||||||
|
@ -224,14 +293,14 @@ bool GenericTaskQueue<E, N>::push_slow(E t, uint dirty_n_elems) {
|
||||||
// g++ complains if the volatile result of the assignment is unused.
|
// g++ complains if the volatile result of the assignment is unused.
|
||||||
const_cast<E&>(_elems[localBot] = t);
|
const_cast<E&>(_elems[localBot] = t);
|
||||||
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
||||||
|
TASKQUEUE_STATS_ONLY(stats.record_push());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class E, unsigned int N>
|
template<class E, unsigned int N>
|
||||||
bool GenericTaskQueue<E, N>::
|
bool GenericTaskQueue<E, N>::pop_local_slow(uint localBot, Age oldAge) {
|
||||||
pop_local_slow(uint localBot, Age oldAge) {
|
|
||||||
// This queue was observed to contain exactly one element; either this
|
// This queue was observed to contain exactly one element; either this
|
||||||
// thread will claim it, or a competing "pop_global". In either case,
|
// thread will claim it, or a competing "pop_global". In either case,
|
||||||
// the queue will be logically empty afterwards. Create a new Age value
|
// the queue will be logically empty afterwards. Create a new Age value
|
||||||
|
@ -251,6 +320,7 @@ pop_local_slow(uint localBot, Age oldAge) {
|
||||||
if (tempAge == oldAge) {
|
if (tempAge == oldAge) {
|
||||||
// We win.
|
// We win.
|
||||||
assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
|
assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
|
||||||
|
TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +376,8 @@ public:
|
||||||
typedef GrowableArray<E> overflow_t;
|
typedef GrowableArray<E> overflow_t;
|
||||||
typedef GenericTaskQueue<E, N> taskqueue_t;
|
typedef GenericTaskQueue<E, N> taskqueue_t;
|
||||||
|
|
||||||
|
TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;)
|
||||||
|
|
||||||
OverflowTaskQueue();
|
OverflowTaskQueue();
|
||||||
~OverflowTaskQueue();
|
~OverflowTaskQueue();
|
||||||
void initialize();
|
void initialize();
|
||||||
|
@ -356,6 +428,7 @@ bool OverflowTaskQueue<E, N>::push(E t)
|
||||||
{
|
{
|
||||||
if (!taskqueue_t::push(t)) {
|
if (!taskqueue_t::push(t)) {
|
||||||
overflow_stack()->push(t);
|
overflow_stack()->push(t);
|
||||||
|
TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->length()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -424,9 +497,13 @@ GenericTaskQueueSet<T>::queue(uint i) {
|
||||||
|
|
||||||
template<class T> bool
|
template<class T> bool
|
||||||
GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) {
|
GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) {
|
||||||
for (uint i = 0; i < 2 * _n; i++)
|
for (uint i = 0; i < 2 * _n; i++) {
|
||||||
if (steal_best_of_2(queue_num, seed, t))
|
if (steal_best_of_2(queue_num, seed, t)) {
|
||||||
|
TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,6 +651,7 @@ GenericTaskQueue<E, N>::push(E t) {
|
||||||
// g++ complains if the volatile result of the assignment is unused.
|
// g++ complains if the volatile result of the assignment is unused.
|
||||||
const_cast<E&>(_elems[localBot] = t);
|
const_cast<E&>(_elems[localBot] = t);
|
||||||
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
||||||
|
TASKQUEUE_STATS_ONLY(stats.record_push());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return push_slow(t, dirty_n_elems);
|
return push_slow(t, dirty_n_elems);
|
||||||
|
@ -603,6 +681,7 @@ GenericTaskQueue<E, N>::pop_local(E& t) {
|
||||||
idx_t tp = _age.top(); // XXX
|
idx_t tp = _age.top(); // XXX
|
||||||
if (size(localBot, tp) > 0) {
|
if (size(localBot, tp) > 0) {
|
||||||
assert(dirty_size(localBot, tp) != N - 1, "sanity");
|
assert(dirty_size(localBot, tp) != N - 1, "sanity");
|
||||||
|
TASKQUEUE_STATS_ONLY(stats.record_pop());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, the queue contained exactly one element; we take the slow
|
// Otherwise, the queue contained exactly one element; we take the slow
|
||||||
|
|
|
@ -77,3 +77,5 @@ d4adf4f2d14c7b79df0a81de884b6b57c6850802 jdk7-b98
|
||||||
d524be5ef62e8b8cb890c59a5d2c19ef0ab50d45 jdk7-b100
|
d524be5ef62e8b8cb890c59a5d2c19ef0ab50d45 jdk7-b100
|
||||||
17f62a566a2020fd908e77106ed885e0c4e7c14d jdk7-b101
|
17f62a566a2020fd908e77106ed885e0c4e7c14d jdk7-b101
|
||||||
15573625af97d01c4e24549041cba7584da7fe88 jdk7-b102
|
15573625af97d01c4e24549041cba7584da7fe88 jdk7-b102
|
||||||
|
b7722e8788644507c10bb69a137de422d0300b24 jdk7-b103
|
||||||
|
d42c4acb6424a094bdafe2ad9c8c1c7ca7fb7b7e jdk7-b104
|
||||||
|
|
|
@ -77,3 +77,5 @@ dac23846092ad4956ed41b5278f8686476ae46ef jdk7-b97
|
||||||
bd26d0ce0c3cb43e58a8e2770cc03f26d96ffe5c jdk7-b100
|
bd26d0ce0c3cb43e58a8e2770cc03f26d96ffe5c jdk7-b100
|
||||||
b55ce274490082712f5e002b38d2eed505ca863d jdk7-b101
|
b55ce274490082712f5e002b38d2eed505ca863d jdk7-b101
|
||||||
d8580443d1815d68e0035a0560634e50fa899288 jdk7-b102
|
d8580443d1815d68e0035a0560634e50fa899288 jdk7-b102
|
||||||
|
267386d6b923f724309cab855a555e2d86a15c8f jdk7-b103
|
||||||
|
bbc4cce6c20aeca4862804a6e8315a2350d43633 jdk7-b104
|
||||||
|
|
|
@ -77,3 +77,5 @@ b1903d7528d33b521df42bc9291bdcdd2f444a29 jdk7-b97
|
||||||
820b4e843d5168370a3bf166d19751a3271d8575 jdk7-b100
|
820b4e843d5168370a3bf166d19751a3271d8575 jdk7-b100
|
||||||
d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101
|
d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101
|
||||||
13029a61b16bec06535d4f0aa98229b358684128 jdk7-b102
|
13029a61b16bec06535d4f0aa98229b358684128 jdk7-b102
|
||||||
|
6488b70a23cc6dc4b7e00809bc503c2884bafb28 jdk7-b103
|
||||||
|
1a92820132a0221c5bdedd42d0888c57ce4cbb34 jdk7-b104
|
||||||
|
|
|
@ -571,6 +571,16 @@ $(NOT_RT_JAR_LIST): FRC
|
||||||
$(ECHO) "META-INF/services/com.sun.tools.xjc.Plugin" >> $@
|
$(ECHO) "META-INF/services/com.sun.tools.xjc.Plugin" >> $@
|
||||||
$(ECHO) "com/sun/tools/" >> $@
|
$(ECHO) "com/sun/tools/" >> $@
|
||||||
$(ECHO) "sun/jvmstat/" >> $@
|
$(ECHO) "sun/jvmstat/" >> $@
|
||||||
|
$(ECHO) "sun/nio/cs/ext/" >> $@
|
||||||
|
$(ECHO) "sun/awt/HKSCS.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11GB2312$Decoder.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11GB2312$Encoder.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11GB2312.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11GBK$Encoder.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11GBK.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11KSC5601$Decoder.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11KSC5601$Encoder.class" >> $@
|
||||||
|
$(ECHO) "sun/awt/motif/X11KSC5601.class" >> $@
|
||||||
$(ECHO) "sun/rmi/rmic/" >> $@
|
$(ECHO) "sun/rmi/rmic/" >> $@
|
||||||
$(ECHO) "sun/tools/asm/" >> $@
|
$(ECHO) "sun/tools/asm/" >> $@
|
||||||
$(ECHO) "sun/tools/java/" >> $@
|
$(ECHO) "sun/tools/java/" >> $@
|
||||||
|
|
|
@ -191,7 +191,7 @@ endif
|
||||||
|
|
||||||
# Generic
|
# Generic
|
||||||
REQUIRED_ANT_VER = 1.6.3
|
REQUIRED_ANT_VER = 1.6.3
|
||||||
REQUIRED_BOOT_VER = 1.5
|
REQUIRED_BOOT_VER = 1.6
|
||||||
REQUIRED_FREETYPE_VERSION = 2.3.0
|
REQUIRED_FREETYPE_VERSION = 2.3.0
|
||||||
REQUIRED_MAKE_VER = 3.78
|
REQUIRED_MAKE_VER = 3.78
|
||||||
REQUIRED_UNZIP_VER = 5.12
|
REQUIRED_UNZIP_VER = 5.12
|
||||||
|
|
|
@ -47,9 +47,9 @@ BUG_SUBMIT_LINE = <a href=\"$(BUG_SUBMIT_URL)\">Submit a bug or feature</a>
|
||||||
|
|
||||||
# Url to devdocs page
|
# Url to devdocs page
|
||||||
# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
|
# 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-5 = http://java.sun.com/j2se/1.5.0/docs/index.html
|
||||||
DEV_DOCS_URL-6 = http://download.oracle.com/docs/cd/E17409_01/javase/6/docs
|
DEV_DOCS_URL-6 = http://download.oracle.com/javase/6/docs/index.html
|
||||||
DEV_DOCS_URL-7 = http://download.oracle.com/docs/cd/E17409_01/javase/7/docs
|
DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html
|
||||||
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
|
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
|
||||||
|
|
||||||
# Url to Java Language Spec
|
# Url to Java Language Spec
|
||||||
|
@ -84,6 +84,11 @@ ALL_SOURCE_DIRS = $(SHARE_SRC)/classes \
|
||||||
$(SHARE_SRC)/../solaris/classes \
|
$(SHARE_SRC)/../solaris/classes \
|
||||||
$(SHARE_SRC)/../windows/classes \
|
$(SHARE_SRC)/../windows/classes \
|
||||||
$(SHARE_SRC)/doc/stub
|
$(SHARE_SRC)/doc/stub
|
||||||
|
|
||||||
|
# List of directories that actually exist
|
||||||
|
ALL_EXISTING_SOURCE_DIRS := $(wildcard $(ALL_SOURCE_DIRS))
|
||||||
|
|
||||||
|
# List with classpath separator between them
|
||||||
EMPTY:=
|
EMPTY:=
|
||||||
SPACE:= $(EMPTY) $(EMPTY)
|
SPACE:= $(EMPTY) $(EMPTY)
|
||||||
RELEASEDOCS_SOURCEPATH = \
|
RELEASEDOCS_SOURCEPATH = \
|
||||||
|
@ -240,7 +245,8 @@ include NON_CORE_PKGS.gmk
|
||||||
# Default target is same as docs target, create core api and all others it can
|
# Default target is same as docs target, create core api and all others it can
|
||||||
#
|
#
|
||||||
|
|
||||||
all docs: coredocs otherdocs
|
all: docs
|
||||||
|
docs: coredocs otherdocs
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Production Targets -- USE THESE TARGETS WHEN:
|
# Production Targets -- USE THESE TARGETS WHEN:
|
||||||
|
@ -1178,9 +1184,9 @@ $(TRACING_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TRACIN
|
||||||
#
|
#
|
||||||
# Get a cache of all the directories
|
# Get a cache of all the directories
|
||||||
|
|
||||||
$(DIRECTORY_CACHE): $(ALL_SOURCE_DIRS)
|
$(DIRECTORY_CACHE): $(ALL_EXISTING_SOURCE_DIRS)
|
||||||
$(prep-target)
|
$(prep-target)
|
||||||
@for cp in $(ALL_SOURCE_DIRS) ; do \
|
@for cp in $(ALL_EXISTING_SOURCE_DIRS) ; do \
|
||||||
$(ECHO) "$(FIND) $${cp} -type f >> $@"; \
|
$(ECHO) "$(FIND) $${cp} -type f >> $@"; \
|
||||||
$(FIND) $${cp} -type f >> $@; \
|
$(FIND) $${cp} -type f >> $@; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -119,6 +119,7 @@ SUNWprivate_1.1 {
|
||||||
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
|
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
|
||||||
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
|
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
|
||||||
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
|
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
|
||||||
|
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
|
||||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
|
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
|
||||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
|
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
|
||||||
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
|
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
|
||||||
|
|
|
@ -106,6 +106,7 @@ SUNWprivate_1.1 {
|
||||||
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
|
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
|
||||||
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
|
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
|
||||||
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
|
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
|
||||||
|
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
|
||||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
|
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
|
||||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
|
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
|
||||||
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
|
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
|
||||||
|
|
|
@ -57,6 +57,25 @@ CHARSETS_JAR = $(LIBDIR)/charsets.jar
|
||||||
# extcs
|
# extcs
|
||||||
FILES_genout_extcs = $(FILES_gen_extcs:%.java=$(GENSRCDIR)/%.java)
|
FILES_genout_extcs = $(FILES_gen_extcs:%.java=$(GENSRCDIR)/%.java)
|
||||||
|
|
||||||
|
#
|
||||||
|
# These sun.awt charsets use sun/nio/cs/ext charsets that only exist
|
||||||
|
# in JDK7 charsets.jar, which causes problem when build the symbol
|
||||||
|
# table for rt.jar in Release.gmk. They are now removed from the
|
||||||
|
# rt.jar when building jdk/jre image (in Release.gmk), so add them
|
||||||
|
# into charsets.jar here
|
||||||
|
#
|
||||||
|
ifeq ($(PLATFORM), windows)
|
||||||
|
FILES_src += \
|
||||||
|
sun/awt/HKSCS.java
|
||||||
|
else
|
||||||
|
# Solaris/Linux
|
||||||
|
FILES_src += \
|
||||||
|
sun/awt/HKSCS.java \
|
||||||
|
sun/awt/motif/X11GB2312.java \
|
||||||
|
sun/awt/motif/X11GBK.java \
|
||||||
|
sun/awt/motif/X11KSC5601.java
|
||||||
|
endif # PLATFORM
|
||||||
|
|
||||||
#
|
#
|
||||||
# Rules
|
# Rules
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2004, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -132,7 +132,7 @@ public class DnsContextFactory implements InitialContextFactory {
|
||||||
throw new ConfigurationException("DNS pseudo-URL required");
|
throw new ConfigurationException("DNS pseudo-URL required");
|
||||||
}
|
}
|
||||||
|
|
||||||
List servers = new ArrayList();
|
List<String> servers = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < urls.length; i++) {
|
for (int i = 0; i < urls.length; i++) {
|
||||||
String server = urls[i].getHost();
|
String server = urls[i].getHost();
|
||||||
|
@ -142,7 +142,7 @@ public class DnsContextFactory implements InitialContextFactory {
|
||||||
// No server or port given, so look to underlying platform.
|
// No server or port given, so look to underlying platform.
|
||||||
// ResolverConfiguration does some limited caching, so the
|
// ResolverConfiguration does some limited caching, so the
|
||||||
// following is reasonably efficient even if called rapid-fire.
|
// following is reasonably efficient even if called rapid-fire.
|
||||||
List platformServers =
|
List<String> platformServers =
|
||||||
ResolverConfiguration.open().nameservers();
|
ResolverConfiguration.open().nameservers();
|
||||||
if (!platformServers.isEmpty()) {
|
if (!platformServers.isEmpty()) {
|
||||||
servers.addAll(platformServers);
|
servers.addAll(platformServers);
|
||||||
|
@ -157,8 +157,7 @@ public class DnsContextFactory implements InitialContextFactory {
|
||||||
? server
|
? server
|
||||||
: server + ":" + port);
|
: server + ":" + port);
|
||||||
}
|
}
|
||||||
return (String[]) servers.toArray(
|
return servers.toArray(new String[servers.size()]);
|
||||||
new String[servers.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2009, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -658,6 +658,11 @@ public final class Connection implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nparent) {
|
if (nparent) {
|
||||||
|
LdapRequest ldr = pendingRequests;
|
||||||
|
while (ldr != null) {
|
||||||
|
ldr.notify();
|
||||||
|
ldr = ldr.next;
|
||||||
|
}
|
||||||
parent.processConnectionClosure();
|
parent.processConnectionClosure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -803,8 +803,7 @@ final class Filter {
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// private static final boolean dbg = false;
|
private static final boolean dbg = false;
|
||||||
private static final boolean dbg = true;
|
|
||||||
private static int dbgIndent = 0;
|
private static int dbgIndent = 0;
|
||||||
|
|
||||||
private static void dprint(String msg) {
|
private static void dprint(String msg) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class RegistryContext implements Context, Referenceable {
|
||||||
}
|
}
|
||||||
|
|
||||||
RMIClientSocketFactory socketFactory =
|
RMIClientSocketFactory socketFactory =
|
||||||
(RMIClientSocketFactory) env.get(SOCKET_FACTORY);
|
(RMIClientSocketFactory) environment.get(SOCKET_FACTORY);
|
||||||
registry = getRegistry(host, port, socketFactory);
|
registry = getRegistry(host, port, socketFactory);
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
|
|
@ -41,6 +41,13 @@ public interface AutoCloseable {
|
||||||
* be declared to throw more specific exceptions (or no exception
|
* be declared to throw more specific exceptions (or no exception
|
||||||
* at all, if the close cannot fail).
|
* at all, if the close cannot fail).
|
||||||
*
|
*
|
||||||
|
* <p>Note that unlike the {@link java.io.Closeable#close close}
|
||||||
|
* method of {@link java.io.Closeable}, this {@code close} method
|
||||||
|
* is <em>not</em> required to be idempotent. In other words,
|
||||||
|
* calling this {@code close} method more than once may have some
|
||||||
|
* visible side effect, unlike {@code Closeable.close} which is
|
||||||
|
* required to have no effect if called more than once.
|
||||||
|
*
|
||||||
* @throws Exception if this resource cannot be closed
|
* @throws Exception if this resource cannot be closed
|
||||||
*/
|
*/
|
||||||
void close() throws Exception;
|
void close() throws Exception;
|
||||||
|
|
|
@ -28,12 +28,12 @@ import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>Throwable</code> class is the superclass of all errors and
|
* The {@code Throwable} class is the superclass of all errors and
|
||||||
* exceptions in the Java language. Only objects that are instances of this
|
* exceptions in the Java language. Only objects that are instances of this
|
||||||
* class (or one of its subclasses) are thrown by the Java Virtual Machine or
|
* class (or one of its subclasses) are thrown by the Java Virtual Machine or
|
||||||
* can be thrown by the Java <code>throw</code> statement. Similarly, only
|
* can be thrown by the Java {@code throw} statement. Similarly, only
|
||||||
* this class or one of its subclasses can be the argument type in a
|
* this class or one of its subclasses can be the argument type in a
|
||||||
* <code>catch</code> clause.
|
* {@code catch} clause.
|
||||||
*
|
*
|
||||||
* For the purposes of compile-time checking of exceptions, {@code
|
* For the purposes of compile-time checking of exceptions, {@code
|
||||||
* Throwable} and any subclass of {@code Throwable} that is not also a
|
* Throwable} and any subclass of {@code Throwable} that is not also a
|
||||||
|
@ -73,11 +73,11 @@ import java.util.*;
|
||||||
* permit the method to throw the cause directly. For example, suppose
|
* permit the method to throw the cause directly. For example, suppose
|
||||||
* a persistent collection conforms to the {@link java.util.Collection
|
* a persistent collection conforms to the {@link java.util.Collection
|
||||||
* Collection} interface, and that its persistence is implemented atop
|
* Collection} interface, and that its persistence is implemented atop
|
||||||
* <tt>java.io</tt>. Suppose the internals of the <tt>add</tt> method
|
* {@code java.io}. Suppose the internals of the {@code add} method
|
||||||
* can throw an {@link java.io.IOException IOException}. The implementation
|
* can throw an {@link java.io.IOException IOException}. The implementation
|
||||||
* can communicate the details of the <tt>IOException</tt> to its caller
|
* can communicate the details of the {@code IOException} to its caller
|
||||||
* while conforming to the <tt>Collection</tt> interface by wrapping the
|
* while conforming to the {@code Collection} interface by wrapping the
|
||||||
* <tt>IOException</tt> in an appropriate unchecked exception. (The
|
* {@code IOException} in an appropriate unchecked exception. (The
|
||||||
* specification for the persistent collection should indicate that it is
|
* specification for the persistent collection should indicate that it is
|
||||||
* capable of throwing such exceptions.)
|
* capable of throwing such exceptions.)
|
||||||
*
|
*
|
||||||
|
@ -86,7 +86,7 @@ import java.util.*;
|
||||||
* {@link #initCause(Throwable)} method. New throwable classes that
|
* {@link #initCause(Throwable)} method. New throwable classes that
|
||||||
* wish to allow causes to be associated with them should provide constructors
|
* wish to allow causes to be associated with them should provide constructors
|
||||||
* that take a cause and delegate (perhaps indirectly) to one of the
|
* that take a cause and delegate (perhaps indirectly) to one of the
|
||||||
* <tt>Throwable</tt> constructors that takes a cause. For example:
|
* {@code Throwable} constructors that takes a cause. For example:
|
||||||
* <pre>
|
* <pre>
|
||||||
* try {
|
* try {
|
||||||
* lowLevelOp();
|
* lowLevelOp();
|
||||||
|
@ -94,10 +94,10 @@ import java.util.*;
|
||||||
* throw new HighLevelException(le); // Chaining-aware constructor
|
* throw new HighLevelException(le); // Chaining-aware constructor
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
* Because the <tt>initCause</tt> method is public, it allows a cause to be
|
* Because the {@code initCause} method is public, it allows a cause to be
|
||||||
* associated with any throwable, even a "legacy throwable" whose
|
* associated with any throwable, even a "legacy throwable" whose
|
||||||
* implementation predates the addition of the exception chaining mechanism to
|
* implementation predates the addition of the exception chaining mechanism to
|
||||||
* <tt>Throwable</tt>. For example:
|
* {@code Throwable}. For example:
|
||||||
* <pre>
|
* <pre>
|
||||||
* try {
|
* try {
|
||||||
* lowLevelOp();
|
* lowLevelOp();
|
||||||
|
@ -121,28 +121,28 @@ import java.util.*;
|
||||||
* use the standard exception chaining mechanism, while continuing to
|
* use the standard exception chaining mechanism, while continuing to
|
||||||
* implement their "legacy" chaining mechanisms for compatibility.
|
* implement their "legacy" chaining mechanisms for compatibility.
|
||||||
*
|
*
|
||||||
* <p>Further, as of release 1.4, many general purpose <tt>Throwable</tt>
|
* <p>Further, as of release 1.4, many general purpose {@code Throwable}
|
||||||
* classes (for example {@link Exception}, {@link RuntimeException},
|
* classes (for example {@link Exception}, {@link RuntimeException},
|
||||||
* {@link Error}) have been retrofitted with constructors that take
|
* {@link Error}) have been retrofitted with constructors that take
|
||||||
* a cause. This was not strictly necessary, due to the existence of the
|
* a cause. This was not strictly necessary, due to the existence of the
|
||||||
* <tt>initCause</tt> method, but it is more convenient and expressive to
|
* {@code initCause} method, but it is more convenient and expressive to
|
||||||
* delegate to a constructor that takes a cause.
|
* delegate to a constructor that takes a cause.
|
||||||
*
|
*
|
||||||
* <p>By convention, class <code>Throwable</code> and its subclasses have two
|
* <p>By convention, class {@code Throwable} and its subclasses have two
|
||||||
* constructors, one that takes no arguments and one that takes a
|
* constructors, one that takes no arguments and one that takes a
|
||||||
* <code>String</code> argument that can be used to produce a detail message.
|
* {@code String} argument that can be used to produce a detail message.
|
||||||
* Further, those subclasses that might likely have a cause associated with
|
* Further, those subclasses that might likely have a cause associated with
|
||||||
* them should have two more constructors, one that takes a
|
* them should have two more constructors, one that takes a
|
||||||
* <code>Throwable</code> (the cause), and one that takes a
|
* {@code Throwable} (the cause), and one that takes a
|
||||||
* <code>String</code> (the detail message) and a <code>Throwable</code> (the
|
* {@code String} (the detail message) and a {@code Throwable} (the
|
||||||
* cause).
|
* cause).
|
||||||
*
|
*
|
||||||
* <p>Also introduced in release 1.4 is the {@link #getStackTrace()} method,
|
* <p>Also introduced in release 1.4 is the {@link #getStackTrace()} method,
|
||||||
* which allows programmatic access to the stack trace information that was
|
* which allows programmatic access to the stack trace information that was
|
||||||
* previously available only in text form, via the various forms of the
|
* previously available only in text form, via the various forms of the
|
||||||
* {@link #printStackTrace()} method. This information has been added to the
|
* {@link #printStackTrace()} method. This information has been added to the
|
||||||
* <i>serialized representation</i> of this class so <tt>getStackTrace</tt>
|
* <i>serialized representation</i> of this class so {@code getStackTrace}
|
||||||
* and <tt>printStackTrace</tt> will operate properly on a throwable that
|
* and {@code printStackTrace} will operate properly on a throwable that
|
||||||
* was obtained by deserialization.
|
* was obtained by deserialization.
|
||||||
*
|
*
|
||||||
* @author unascribed
|
* @author unascribed
|
||||||
|
@ -162,7 +162,7 @@ public class Throwable implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific details about the Throwable. For example, for
|
* Specific details about the Throwable. For example, for
|
||||||
* <tt>FileNotFoundException</tt>, this contains the name of
|
* {@code FileNotFoundException}, this contains the name of
|
||||||
* the file that could not be found.
|
* the file that could not be found.
|
||||||
*
|
*
|
||||||
* @serial
|
* @serial
|
||||||
|
@ -212,7 +212,7 @@ public class Throwable implements Serializable {
|
||||||
private static final String SUPPRESSED_CAPTION = "Suppressed: ";
|
private static final String SUPPRESSED_CAPTION = "Suppressed: ";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new throwable with <code>null</code> as its detail message.
|
* Constructs a new throwable with {@code null} as its detail message.
|
||||||
* The cause is not initialized, and may subsequently be initialized by a
|
* The cause is not initialized, and may subsequently be initialized by a
|
||||||
* call to {@link #initCause}.
|
* call to {@link #initCause}.
|
||||||
*
|
*
|
||||||
|
@ -242,7 +242,7 @@ public class Throwable implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Constructs a new throwable with the specified detail message and
|
* Constructs a new throwable with the specified detail message and
|
||||||
* cause. <p>Note that the detail message associated with
|
* cause. <p>Note that the detail message associated with
|
||||||
* <code>cause</code> is <i>not</i> automatically incorporated in
|
* {@code cause} is <i>not</i> automatically incorporated in
|
||||||
* this throwable's detail message.
|
* this throwable's detail message.
|
||||||
*
|
*
|
||||||
* <p>The {@link #fillInStackTrace()} method is called to initialize
|
* <p>The {@link #fillInStackTrace()} method is called to initialize
|
||||||
|
@ -251,7 +251,7 @@ public class Throwable implements Serializable {
|
||||||
* @param message the detail message (which is saved for later retrieval
|
* @param message the detail message (which is saved for later retrieval
|
||||||
* by the {@link #getMessage()} method).
|
* by the {@link #getMessage()} method).
|
||||||
* @param cause the cause (which is saved for later retrieval by the
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
* {@link #getCause()} method). (A <tt>null</tt> value is
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
* permitted, and indicates that the cause is nonexistent or
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
* unknown.)
|
* unknown.)
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
|
@ -264,8 +264,8 @@ public class Throwable implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new throwable with the specified cause and a detail
|
* Constructs a new throwable with the specified cause and a detail
|
||||||
* message of <tt>(cause==null ? null : cause.toString())</tt> (which
|
* message of {@code (cause==null ? null : cause.toString())} (which
|
||||||
* typically contains the class and detail message of <tt>cause</tt>).
|
* typically contains the class and detail message of {@code cause}).
|
||||||
* This constructor is useful for throwables that are little more than
|
* This constructor is useful for throwables that are little more than
|
||||||
* wrappers for other throwables (for example, {@link
|
* wrappers for other throwables (for example, {@link
|
||||||
* java.security.PrivilegedActionException}).
|
* java.security.PrivilegedActionException}).
|
||||||
|
@ -274,7 +274,7 @@ public class Throwable implements Serializable {
|
||||||
* the stack trace data in the newly created throwable.
|
* the stack trace data in the newly created throwable.
|
||||||
*
|
*
|
||||||
* @param cause the cause (which is saved for later retrieval by the
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
* {@link #getCause()} method). (A <tt>null</tt> value is
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
* permitted, and indicates that the cause is nonexistent or
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
* unknown.)
|
* unknown.)
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
|
@ -288,8 +288,8 @@ public class Throwable implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Returns the detail message string of this throwable.
|
* Returns the detail message string of this throwable.
|
||||||
*
|
*
|
||||||
* @return the detail message string of this <tt>Throwable</tt> instance
|
* @return the detail message string of this {@code Throwable} instance
|
||||||
* (which may be <tt>null</tt>).
|
* (which may be {@code null}).
|
||||||
*/
|
*/
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return detailMessage;
|
return detailMessage;
|
||||||
|
@ -300,7 +300,7 @@ public class Throwable implements Serializable {
|
||||||
* Subclasses may override this method in order to produce a
|
* Subclasses may override this method in order to produce a
|
||||||
* locale-specific message. For subclasses that do not override this
|
* locale-specific message. For subclasses that do not override this
|
||||||
* method, the default implementation returns the same result as
|
* method, the default implementation returns the same result as
|
||||||
* <code>getMessage()</code>.
|
* {@code getMessage()}.
|
||||||
*
|
*
|
||||||
* @return The localized description of this throwable.
|
* @return The localized description of this throwable.
|
||||||
* @since JDK1.1
|
* @since JDK1.1
|
||||||
|
@ -310,22 +310,22 @@ public class Throwable implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cause of this throwable or <code>null</code> if the
|
* Returns the cause of this throwable or {@code null} if the
|
||||||
* cause is nonexistent or unknown. (The cause is the throwable that
|
* cause is nonexistent or unknown. (The cause is the throwable that
|
||||||
* caused this throwable to get thrown.)
|
* caused this throwable to get thrown.)
|
||||||
*
|
*
|
||||||
* <p>This implementation returns the cause that was supplied via one of
|
* <p>This implementation returns the cause that was supplied via one of
|
||||||
* the constructors requiring a <tt>Throwable</tt>, or that was set after
|
* the constructors requiring a {@code Throwable}, or that was set after
|
||||||
* creation with the {@link #initCause(Throwable)} method. While it is
|
* creation with the {@link #initCause(Throwable)} method. While it is
|
||||||
* typically unnecessary to override this method, a subclass can override
|
* typically unnecessary to override this method, a subclass can override
|
||||||
* it to return a cause set by some other means. This is appropriate for
|
* it to return a cause set by some other means. This is appropriate for
|
||||||
* a "legacy chained throwable" that predates the addition of chained
|
* a "legacy chained throwable" that predates the addition of chained
|
||||||
* exceptions to <tt>Throwable</tt>. Note that it is <i>not</i>
|
* exceptions to {@code Throwable}. Note that it is <i>not</i>
|
||||||
* necessary to override any of the <tt>PrintStackTrace</tt> methods,
|
* necessary to override any of the {@code PrintStackTrace} methods,
|
||||||
* all of which invoke the <tt>getCause</tt> method to determine the
|
* all of which invoke the {@code getCause} method to determine the
|
||||||
* cause of a throwable.
|
* cause of a throwable.
|
||||||
*
|
*
|
||||||
* @return the cause of this throwable or <code>null</code> if the
|
* @return the cause of this throwable or {@code null} if the
|
||||||
* cause is nonexistent or unknown.
|
* cause is nonexistent or unknown.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
@ -345,11 +345,11 @@ public class Throwable implements Serializable {
|
||||||
* even once.
|
* even once.
|
||||||
*
|
*
|
||||||
* @param cause the cause (which is saved for later retrieval by the
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
* {@link #getCause()} method). (A <tt>null</tt> value is
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
* permitted, and indicates that the cause is nonexistent or
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
* unknown.)
|
* unknown.)
|
||||||
* @return a reference to this <code>Throwable</code> instance.
|
* @return a reference to this {@code Throwable} instance.
|
||||||
* @throws IllegalArgumentException if <code>cause</code> is this
|
* @throws IllegalArgumentException if {@code cause} is this
|
||||||
* throwable. (A throwable cannot be its own cause.)
|
* throwable. (A throwable cannot be its own cause.)
|
||||||
* @throws IllegalStateException if this throwable was
|
* @throws IllegalStateException if this throwable was
|
||||||
* created with {@link #Throwable(Throwable)} or
|
* created with {@link #Throwable(Throwable)} or
|
||||||
|
@ -375,7 +375,7 @@ public class Throwable implements Serializable {
|
||||||
* <li> the result of invoking this object's {@link #getLocalizedMessage}
|
* <li> the result of invoking this object's {@link #getLocalizedMessage}
|
||||||
* method
|
* method
|
||||||
* </ul>
|
* </ul>
|
||||||
* If <tt>getLocalizedMessage</tt> returns <tt>null</tt>, then just
|
* If {@code getLocalizedMessage} returns {@code null}, then just
|
||||||
* the class name is returned.
|
* the class name is returned.
|
||||||
*
|
*
|
||||||
* @return a string representation of this throwable.
|
* @return a string representation of this throwable.
|
||||||
|
@ -389,8 +389,8 @@ public class Throwable implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Prints this throwable and its backtrace to the
|
* Prints this throwable and its backtrace to the
|
||||||
* standard error stream. This method prints a stack trace for this
|
* standard error stream. This method prints a stack trace for this
|
||||||
* <code>Throwable</code> object on the error output stream that is
|
* {@code Throwable} object on the error output stream that is
|
||||||
* the value of the field <code>System.err</code>. The first line of
|
* the value of the field {@code System.err}. The first line of
|
||||||
* output contains the result of the {@link #toString()} method for
|
* output contains the result of the {@link #toString()} method for
|
||||||
* this object. Remaining lines represent data previously recorded by
|
* this object. Remaining lines represent data previously recorded by
|
||||||
* the method {@link #fillInStackTrace()}. The format of this
|
* the method {@link #fillInStackTrace()}. The format of this
|
||||||
|
@ -435,7 +435,7 @@ public class Throwable implements Serializable {
|
||||||
* at Junk.c(Junk.java:21)
|
* at Junk.c(Junk.java:21)
|
||||||
* ... 3 more
|
* ... 3 more
|
||||||
* </pre>
|
* </pre>
|
||||||
* Note the presence of lines containing the characters <tt>"..."</tt>.
|
* Note the presence of lines containing the characters {@code "..."}.
|
||||||
* These lines indicate that the remainder of the stack trace for this
|
* These lines indicate that the remainder of the stack trace for this
|
||||||
* exception matches the indicated number of frames from the bottom of the
|
* exception matches the indicated number of frames from the bottom of the
|
||||||
* stack trace of the exception that was caused by this exception (the
|
* stack trace of the exception that was caused by this exception (the
|
||||||
|
@ -542,14 +542,17 @@ public class Throwable implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Prints this throwable and its backtrace to the specified print stream.
|
* Prints this throwable and its backtrace to the specified print stream.
|
||||||
*
|
*
|
||||||
* @param s <code>PrintStream</code> to use for output
|
* @param s {@code PrintStream} to use for output
|
||||||
*/
|
*/
|
||||||
public void printStackTrace(PrintStream s) {
|
public void printStackTrace(PrintStream s) {
|
||||||
printStackTrace(new WrappedPrintStream(s));
|
printStackTrace(new WrappedPrintStream(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printStackTrace(PrintStreamOrWriter s) {
|
private void printStackTrace(PrintStreamOrWriter s) {
|
||||||
Set<Throwable> dejaVu = new HashSet<Throwable>();
|
// Guard against malicious overrides of Throwable.equals by
|
||||||
|
// using a Set with identity equality semantics.
|
||||||
|
Set<Throwable> dejaVu =
|
||||||
|
Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
|
||||||
dejaVu.add(this);
|
dejaVu.add(this);
|
||||||
|
|
||||||
synchronized (s.lock()) {
|
synchronized (s.lock()) {
|
||||||
|
@ -616,7 +619,7 @@ public class Throwable implements Serializable {
|
||||||
* Prints this throwable and its backtrace to the specified
|
* Prints this throwable and its backtrace to the specified
|
||||||
* print writer.
|
* print writer.
|
||||||
*
|
*
|
||||||
* @param s <code>PrintWriter</code> to use for output
|
* @param s {@code PrintWriter} to use for output
|
||||||
* @since JDK1.1
|
* @since JDK1.1
|
||||||
*/
|
*/
|
||||||
public void printStackTrace(PrintWriter s) {
|
public void printStackTrace(PrintWriter s) {
|
||||||
|
@ -669,10 +672,10 @@ public class Throwable implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills in the execution stack trace. This method records within this
|
* Fills in the execution stack trace. This method records within this
|
||||||
* <code>Throwable</code> object information about the current state of
|
* {@code Throwable} object information about the current state of
|
||||||
* the stack frames for the current thread.
|
* the stack frames for the current thread.
|
||||||
*
|
*
|
||||||
* @return a reference to this <code>Throwable</code> instance.
|
* @return a reference to this {@code Throwable} instance.
|
||||||
* @see java.lang.Throwable#printStackTrace()
|
* @see java.lang.Throwable#printStackTrace()
|
||||||
*/
|
*/
|
||||||
public synchronized native Throwable fillInStackTrace();
|
public synchronized native Throwable fillInStackTrace();
|
||||||
|
@ -694,7 +697,7 @@ public class Throwable implements Serializable {
|
||||||
* this throwable is permitted to return a zero-length array from this
|
* this throwable is permitted to return a zero-length array from this
|
||||||
* method. Generally speaking, the array returned by this method will
|
* method. Generally speaking, the array returned by this method will
|
||||||
* contain one element for every frame that would be printed by
|
* contain one element for every frame that would be printed by
|
||||||
* <tt>printStackTrace</tt>.
|
* {@code printStackTrace}.
|
||||||
*
|
*
|
||||||
* @return an array of stack trace elements representing the stack trace
|
* @return an array of stack trace elements representing the stack trace
|
||||||
* pertaining to this throwable.
|
* pertaining to this throwable.
|
||||||
|
@ -727,14 +730,14 @@ public class Throwable implements Serializable {
|
||||||
* read from a serialization stream.
|
* read from a serialization stream.
|
||||||
*
|
*
|
||||||
* @param stackTrace the stack trace elements to be associated with
|
* @param stackTrace the stack trace elements to be associated with
|
||||||
* this <code>Throwable</code>. The specified array is copied by this
|
* this {@code Throwable}. The specified array is copied by this
|
||||||
* call; changes in the specified array after the method invocation
|
* call; changes in the specified array after the method invocation
|
||||||
* returns will have no affect on this <code>Throwable</code>'s stack
|
* returns will have no affect on this {@code Throwable}'s stack
|
||||||
* trace.
|
* trace.
|
||||||
*
|
*
|
||||||
* @throws NullPointerException if <code>stackTrace</code> is
|
* @throws NullPointerException if {@code stackTrace} is
|
||||||
* <code>null</code>, or if any of the elements of
|
* {@code null}, or if any of the elements of
|
||||||
* <code>stackTrace</code> are <code>null</code>
|
* {@code stackTrace} are {@code null}
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
@ -761,8 +764,8 @@ public class Throwable implements Serializable {
|
||||||
* package-protection for use by SharedSecrets.
|
* package-protection for use by SharedSecrets.
|
||||||
*
|
*
|
||||||
* @param index index of the element to return.
|
* @param index index of the element to return.
|
||||||
* @throws IndexOutOfBoundsException if <tt>index < 0 ||
|
* @throws IndexOutOfBoundsException if {@code index < 0 ||
|
||||||
* index >= getStackTraceDepth() </tt>
|
* index >= getStackTraceDepth() }
|
||||||
*/
|
*/
|
||||||
native StackTraceElement getStackTraceElement(int index);
|
native StackTraceElement getStackTraceElement(int index);
|
||||||
|
|
||||||
|
@ -794,14 +797,27 @@ public class Throwable implements Serializable {
|
||||||
* were suppressed, typically by the automatic resource management
|
* were suppressed, typically by the automatic resource management
|
||||||
* statement, in order to deliver this exception.
|
* statement, in order to deliver this exception.
|
||||||
*
|
*
|
||||||
|
* <p>Note that when one exception {@linkplain
|
||||||
|
* #initCause(Throwable) causes} another exception, the first
|
||||||
|
* exception is usually caught and then the second exception is
|
||||||
|
* thrown in response. In contrast, when one exception suppresses
|
||||||
|
* another, two exceptions are thrown in sibling code blocks, such
|
||||||
|
* as in a {@code try} block and in its {@code finally} block, and
|
||||||
|
* control flow can only continue with one exception so the second
|
||||||
|
* is recorded as a suppressed exception of the first.
|
||||||
|
*
|
||||||
* @param exception the exception to be added to the list of
|
* @param exception the exception to be added to the list of
|
||||||
* suppressed exceptions
|
* suppressed exceptions
|
||||||
* @throws NullPointerException if {@code exception} is null
|
* @throws NullPointerException if {@code exception} is null
|
||||||
|
* @throws IllegalArgumentException if {@code exception} is this
|
||||||
|
* throwable; a throwable cannot suppress itself.
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public synchronized void addSuppressedException(Throwable exception) {
|
public synchronized void addSuppressedException(Throwable exception) {
|
||||||
if (exception == null)
|
if (exception == null)
|
||||||
throw new NullPointerException(NULL_CAUSE_MESSAGE);
|
throw new NullPointerException(NULL_CAUSE_MESSAGE);
|
||||||
|
if (exception == this)
|
||||||
|
throw new IllegalArgumentException("Self-suppression not permitted");
|
||||||
|
|
||||||
if (suppressedExceptions.size() == 0)
|
if (suppressedExceptions.size() == 0)
|
||||||
suppressedExceptions = new ArrayList<Throwable>();
|
suppressedExceptions = new ArrayList<Throwable>();
|
||||||
|
|
|
@ -596,6 +596,9 @@ class Bits { // package-private
|
||||||
return pageSize;
|
return pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pageCount(long size) {
|
||||||
|
return (int)(size + (long)pageSize() - 1L) / pageSize();
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean unaligned;
|
private static boolean unaligned;
|
||||||
private static boolean unalignedKnown = false;
|
private static boolean unalignedKnown = false;
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package java.nio;
|
package java.nio;
|
||||||
|
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A direct byte buffer whose content is a memory-mapped region of a file.
|
* A direct byte buffer whose content is a memory-mapped region of a file.
|
||||||
|
@ -93,6 +95,22 @@ public abstract class MappedByteBuffer
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the distance (in bytes) of the buffer from the page aligned address
|
||||||
|
// of the mapping. Computed each time to avoid storing in every direct buffer.
|
||||||
|
private long mappingOffset() {
|
||||||
|
int ps = Bits.pageSize();
|
||||||
|
long offset = address % ps;
|
||||||
|
return (offset >= 0) ? offset : (ps + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long mappingAddress(long mappingOffset) {
|
||||||
|
return address - mappingOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long mappingLength(long mappingOffset) {
|
||||||
|
return (long)capacity() + mappingOffset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether or not this buffer's content is resident in physical
|
* Tells whether or not this buffer's content is resident in physical
|
||||||
* memory.
|
* memory.
|
||||||
|
@ -115,7 +133,9 @@ public abstract class MappedByteBuffer
|
||||||
checkMapped();
|
checkMapped();
|
||||||
if ((address == 0) || (capacity() == 0))
|
if ((address == 0) || (capacity() == 0))
|
||||||
return true;
|
return true;
|
||||||
return isLoaded0(((DirectByteBuffer)this).address(), capacity());
|
long offset = mappingOffset();
|
||||||
|
long length = mappingLength(offset);
|
||||||
|
return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,7 +152,20 @@ public abstract class MappedByteBuffer
|
||||||
checkMapped();
|
checkMapped();
|
||||||
if ((address == 0) || (capacity() == 0))
|
if ((address == 0) || (capacity() == 0))
|
||||||
return this;
|
return this;
|
||||||
load0(((DirectByteBuffer)this).address(), capacity(), Bits.pageSize());
|
long offset = mappingOffset();
|
||||||
|
long length = mappingLength(offset);
|
||||||
|
load0(mappingAddress(offset), length);
|
||||||
|
|
||||||
|
// touch each page
|
||||||
|
Unsafe unsafe = Unsafe.getUnsafe();
|
||||||
|
int ps = Bits.pageSize();
|
||||||
|
int count = Bits.pageCount(length);
|
||||||
|
long a = mappingAddress(offset);
|
||||||
|
for (int i=0; i<count; i++) {
|
||||||
|
unsafe.getByte(a);
|
||||||
|
a += ps;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,14 +189,15 @@ public abstract class MappedByteBuffer
|
||||||
*/
|
*/
|
||||||
public final MappedByteBuffer force() {
|
public final MappedByteBuffer force() {
|
||||||
checkMapped();
|
checkMapped();
|
||||||
if ((address == 0) || (capacity() == 0))
|
if ((address != 0) && (capacity() != 0)) {
|
||||||
return this;
|
long offset = mappingOffset();
|
||||||
force0(((DirectByteBuffer)this).address(), capacity());
|
force0(mappingAddress(offset), mappingLength(offset));
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean isLoaded0(long address, long length);
|
private native boolean isLoaded0(long address, long length, int pageCount);
|
||||||
private native int load0(long address, long length, int pageSize);
|
private native void load0(long address, long length);
|
||||||
private native void force0(long address, long length);
|
private native void force0(long address, long length);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -387,7 +387,7 @@ public abstract class X509CRL extends CRL implements X509Extension {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the signature algorithm name for the CRL
|
* Gets the signature algorithm name for the CRL
|
||||||
* signature algorithm. An example is the string "SHA-1/DSA".
|
* signature algorithm. An example is the string "SHA256withRSA".
|
||||||
* The ASN.1 definition for this is:
|
* The ASN.1 definition for this is:
|
||||||
* <pre>
|
* <pre>
|
||||||
* signatureAlgorithm AlgorithmIdentifier<p>
|
* signatureAlgorithm AlgorithmIdentifier<p>
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -352,7 +352,7 @@ implements X509Extension {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the signature algorithm name for the certificate
|
* Gets the signature algorithm name for the certificate
|
||||||
* signature algorithm. An example is the string "SHA-1/DSA".
|
* signature algorithm. An example is the string "SHA256withRSA".
|
||||||
* The ASN.1 definition for this is:
|
* The ASN.1 definition for this is:
|
||||||
* <pre>
|
* <pre>
|
||||||
* signatureAlgorithm AlgorithmIdentifier<p>
|
* signatureAlgorithm AlgorithmIdentifier<p>
|
||||||
|
|
|
@ -26,18 +26,9 @@
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linked list implementation of the {@code List} interface. Implements all
|
* Linked list implementation of the {@link List} and {@link Deque} interfaces.
|
||||||
* optional list operations, and permits all elements (including
|
* Implements all optional operations, and permits all elements (including
|
||||||
* {@code null}). In addition to implementing the {@code List} interface,
|
* {@code null}).
|
||||||
* the {@code LinkedList} class provides uniformly named methods to
|
|
||||||
* {@code get}, {@code remove} and {@code insert} an element at the
|
|
||||||
* beginning and end of the list. These operations allow linked lists to be
|
|
||||||
* used as a stack, {@linkplain Queue queue}, or {@linkplain Deque
|
|
||||||
* double-ended queue}.
|
|
||||||
*
|
|
||||||
* <p>The class implements the {@code Deque} interface, providing
|
|
||||||
* first-in-first-out queue operations for {@code add},
|
|
||||||
* {@code poll}, along with other stack and deque operations.
|
|
||||||
*
|
*
|
||||||
* <p>All of the operations perform as could be expected for a doubly-linked
|
* <p>All of the operations perform as could be expected for a doubly-linked
|
||||||
* list. Operations that index into the list will traverse the list from
|
* list. Operations that index into the list will traverse the list from
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -113,7 +113,6 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
previewPanelHolder.setBorder(new TitledBorder(previewString));
|
previewPanelHolder.setBorder(new TitledBorder(previewString));
|
||||||
}
|
}
|
||||||
previewPanelHolder.setInheritsPopupMenu(true);
|
previewPanelHolder.setInheritsPopupMenu(true);
|
||||||
chooser.add(previewPanelHolder, BorderLayout.SOUTH);
|
|
||||||
|
|
||||||
installPreviewPanel();
|
installPreviewPanel();
|
||||||
chooser.applyComponentOrientation(c.getComponentOrientation());
|
chooser.applyComponentOrientation(c.getComponentOrientation());
|
||||||
|
@ -126,13 +125,9 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
|
|
||||||
uninstallDefaultChoosers();
|
uninstallDefaultChoosers();
|
||||||
uninstallListeners();
|
uninstallListeners();
|
||||||
|
uninstallPreviewPanel();
|
||||||
uninstallDefaults();
|
uninstallDefaults();
|
||||||
|
|
||||||
previewPanelHolder.remove(previewPanel);
|
|
||||||
if (previewPanel instanceof UIResource) {
|
|
||||||
chooser.setPreviewPanel(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
previewPanelHolder = null;
|
previewPanelHolder = null;
|
||||||
previewPanel = null;
|
previewPanel = null;
|
||||||
defaultChoosers = null;
|
defaultChoosers = null;
|
||||||
|
@ -143,29 +138,37 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void installPreviewPanel() {
|
protected void installPreviewPanel() {
|
||||||
if (previewPanel != null) {
|
JComponent previewPanel = this.chooser.getPreviewPanel();
|
||||||
previewPanelHolder.remove(previewPanel);
|
if (previewPanel == null) {
|
||||||
previewPanel.removeMouseListener(getHandler());
|
previewPanel = ColorChooserComponentFactory.getPreviewPanel();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
previewPanel = chooser.getPreviewPanel();
|
Dimension size = new BorderLayout().minimumLayoutSize(previewPanel);
|
||||||
Dimension layoutSize = new Dimension(); // fix for bug 4759306
|
if ((size.width == 0) && (size.height == 0)) {
|
||||||
if (previewPanel != null) {
|
previewPanel = null;
|
||||||
layoutSize = new BorderLayout().minimumLayoutSize(previewPanel);
|
|
||||||
if ((previewPanelHolder != null) && (chooser != null) &&
|
|
||||||
(layoutSize.getWidth() + layoutSize.getHeight() == 0)) {
|
|
||||||
chooser.remove(previewPanelHolder);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (previewPanel == null || previewPanel instanceof UIResource) {
|
this.previewPanel = previewPanel;
|
||||||
previewPanel = ColorChooserComponentFactory.getPreviewPanel(); // get from table?
|
if (previewPanel != null) {
|
||||||
chooser.setPreviewPanel(previewPanel);
|
chooser.add(previewPanelHolder, BorderLayout.SOUTH);
|
||||||
|
previewPanel.setForeground(chooser.getColor());
|
||||||
|
previewPanelHolder.add(previewPanel);
|
||||||
|
previewPanel.addMouseListener(getHandler());
|
||||||
|
previewPanel.setInheritsPopupMenu(true);
|
||||||
}
|
}
|
||||||
previewPanel.setForeground(chooser.getColor());
|
}
|
||||||
previewPanelHolder.add(previewPanel);
|
|
||||||
previewPanel.addMouseListener(getHandler());
|
/**
|
||||||
previewPanel.setInheritsPopupMenu(true);
|
* Removes installed preview panel from the UI delegate.
|
||||||
|
*
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
protected void uninstallPreviewPanel() {
|
||||||
|
if (this.previewPanel != null) {
|
||||||
|
this.previewPanel.removeMouseListener(getHandler());
|
||||||
|
this.previewPanelHolder.remove(this.previewPanel);
|
||||||
|
}
|
||||||
|
this.chooser.remove(this.previewPanelHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
|
@ -209,7 +212,6 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
chooser.removePropertyChangeListener( propertyChangeListener );
|
chooser.removePropertyChangeListener( propertyChangeListener );
|
||||||
chooser.getSelectionModel().removeChangeListener(previewListener);
|
chooser.getSelectionModel().removeChangeListener(previewListener);
|
||||||
previewListener = null;
|
previewListener = null;
|
||||||
previewPanel.removeMouseListener(getHandler());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectionChanged(ColorSelectionModel model) {
|
private void selectionChanged(ColorSelectionModel model) {
|
||||||
|
@ -312,9 +314,8 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (prop == JColorChooser.PREVIEW_PANEL_PROPERTY) {
|
else if (prop == JColorChooser.PREVIEW_PANEL_PROPERTY) {
|
||||||
if (evt.getNewValue() != previewPanel) {
|
uninstallPreviewPanel();
|
||||||
installPreviewPanel();
|
installPreviewPanel();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (prop == JColorChooser.SELECTION_MODEL_PROPERTY) {
|
else if (prop == JColorChooser.SELECTION_MODEL_PROPERTY) {
|
||||||
ColorSelectionModel oldModel = (ColorSelectionModel) evt.getOldValue();
|
ColorSelectionModel oldModel = (ColorSelectionModel) evt.getOldValue();
|
||||||
|
@ -352,5 +353,4 @@ public class BasicColorChooserUI extends ColorChooserUI
|
||||||
super("color");
|
super("color");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,8 +202,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup {
|
||||||
* Implementation of ComboPopup.show().
|
* Implementation of ComboPopup.show().
|
||||||
*/
|
*/
|
||||||
public void show() {
|
public void show() {
|
||||||
|
comboBox.firePopupMenuWillBecomeVisible();
|
||||||
setListSelection(comboBox.getSelectedIndex());
|
setListSelection(comboBox.getSelectedIndex());
|
||||||
|
|
||||||
Point location = getPopupLocation();
|
Point location = getPopupLocation();
|
||||||
show( comboBox, location.x, location.y );
|
show( comboBox, location.x, location.y );
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup {
|
||||||
|
|
||||||
protected void firePopupMenuWillBecomeVisible() {
|
protected void firePopupMenuWillBecomeVisible() {
|
||||||
super.firePopupMenuWillBecomeVisible();
|
super.firePopupMenuWillBecomeVisible();
|
||||||
comboBox.firePopupMenuWillBecomeVisible();
|
// comboBox.firePopupMenuWillBecomeVisible() is called from BasicComboPopup.show() method
|
||||||
|
// to let the user change the popup menu from the PopupMenuListener.popupMenuWillBecomeVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void firePopupMenuWillBecomeInvisible() {
|
protected void firePopupMenuWillBecomeInvisible() {
|
||||||
|
|
|
@ -570,7 +570,9 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
|
||||||
direction = -1;
|
direction = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getOverwriteMode() && rh.text != null) {
|
if (getOverwriteMode() && rh.text != null &&
|
||||||
|
getFormattedTextField().getSelectedText() == null)
|
||||||
|
{
|
||||||
rh.length = Math.min(Math.max(rh.length, rh.text.length()),
|
rh.length = Math.min(Math.max(rh.length, rh.text.length()),
|
||||||
rh.fb.getDocument().getLength() - rh.offset);
|
rh.fb.getDocument().getLength() - rh.offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -622,18 +622,8 @@ public class InternationalFormatter extends DefaultFormatter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overriden in an attempt to honor the literals.
|
* Overriden in an attempt to honor the literals.
|
||||||
* <p>
|
* <p>If we do not allow invalid values and are in overwrite mode, this
|
||||||
* If we do
|
* {@code rh.length} is corrected as to preserve trailing literals.
|
||||||
* not allow invalid values and are in overwrite mode, this does the
|
|
||||||
* following for each character in the replacement range:
|
|
||||||
* <ol>
|
|
||||||
* <li>If the character is a literal, add it to the string to replace
|
|
||||||
* with. If there is text to insert and it doesn't match the
|
|
||||||
* literal, then insert the literal in the the middle of the insert
|
|
||||||
* text. This allows you to either paste in literals or not and
|
|
||||||
* get the same behavior.
|
|
||||||
* <li>If there is no text to insert, replace it with ' '.
|
|
||||||
* </ol>
|
|
||||||
* If not in overwrite mode, and there is text to insert it is
|
* If not in overwrite mode, and there is text to insert it is
|
||||||
* inserted at the next non literal index going forward. If there
|
* inserted at the next non literal index going forward. If there
|
||||||
* is only text to remove, it is removed from the next non literal
|
* is only text to remove, it is removed from the next non literal
|
||||||
|
@ -643,61 +633,27 @@ public class InternationalFormatter extends DefaultFormatter {
|
||||||
if (!getAllowsInvalid()) {
|
if (!getAllowsInvalid()) {
|
||||||
String text = rh.text;
|
String text = rh.text;
|
||||||
int tl = (text != null) ? text.length() : 0;
|
int tl = (text != null) ? text.length() : 0;
|
||||||
|
JTextComponent c = getFormattedTextField();
|
||||||
|
|
||||||
if (tl == 0 && rh.length == 1 && getFormattedTextField().
|
if (tl == 0 && rh.length == 1 && c.getSelectionStart() != rh.offset) {
|
||||||
getSelectionStart() != rh.offset) {
|
|
||||||
// Backspace, adjust to actually delete next non-literal.
|
// Backspace, adjust to actually delete next non-literal.
|
||||||
rh.offset = getNextNonliteralIndex(rh.offset, -1);
|
rh.offset = getNextNonliteralIndex(rh.offset, -1);
|
||||||
}
|
} else if (getOverwriteMode()) {
|
||||||
if (getOverwriteMode()) {
|
int pos = rh.offset;
|
||||||
StringBuffer replace = null;
|
int textPos = pos;
|
||||||
|
boolean overflown = false;
|
||||||
|
|
||||||
for (int counter = 0, textIndex = 0,
|
for (int i = 0; i < rh.length; i++) {
|
||||||
max = Math.max(tl, rh.length); counter < max;
|
while (isLiteral(pos)) pos++;
|
||||||
counter++) {
|
if (pos >= string.length()) {
|
||||||
if (isLiteral(rh.offset + counter)) {
|
pos = textPos;
|
||||||
if (replace != null) {
|
overflown = true;
|
||||||
replace.append(getLiteral(rh.offset +
|
break;
|
||||||
counter));
|
|
||||||
}
|
|
||||||
if (textIndex < tl && text.charAt(textIndex) ==
|
|
||||||
getLiteral(rh.offset + counter)) {
|
|
||||||
textIndex++;
|
|
||||||
}
|
|
||||||
else if (textIndex == 0) {
|
|
||||||
rh.offset++;
|
|
||||||
rh.length--;
|
|
||||||
counter--;
|
|
||||||
max--;
|
|
||||||
}
|
|
||||||
else if (replace == null) {
|
|
||||||
replace = new StringBuffer(max);
|
|
||||||
replace.append(text.substring(0, textIndex));
|
|
||||||
replace.append(getLiteral(rh.offset +
|
|
||||||
counter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (textIndex < tl) {
|
|
||||||
if (replace != null) {
|
|
||||||
replace.append(text.charAt(textIndex));
|
|
||||||
}
|
|
||||||
textIndex++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Nothing to replace it with, assume ' '
|
|
||||||
if (replace == null) {
|
|
||||||
replace = new StringBuffer(max);
|
|
||||||
if (textIndex > 0) {
|
|
||||||
replace.append(text.substring(0, textIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (replace != null) {
|
|
||||||
replace.append(' ');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
textPos = ++pos;
|
||||||
}
|
}
|
||||||
if (replace != null) {
|
if (overflown || c.getSelectedText() == null) {
|
||||||
rh.text = replace.toString();
|
rh.length = pos - rh.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tl > 0) {
|
else if (tl > 0) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,7 +26,6 @@
|
||||||
package sun.net.dns;
|
package sun.net.dns;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration of the client resolver.
|
* The configuration of the client resolver.
|
||||||
|
@ -68,7 +67,7 @@ public abstract class ResolverConfiguration {
|
||||||
*
|
*
|
||||||
* @return list of domain names
|
* @return list of domain names
|
||||||
*/
|
*/
|
||||||
public abstract List searchlist();
|
public abstract List<String> searchlist();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of name servers used for host name lookup.
|
* Returns a list of name servers used for host name lookup.
|
||||||
|
@ -78,7 +77,7 @@ public abstract class ResolverConfiguration {
|
||||||
*
|
*
|
||||||
* @return list of the name servers
|
* @return list of the name servers
|
||||||
*/
|
*/
|
||||||
public abstract List nameservers();
|
public abstract List<String> nameservers();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -45,20 +45,21 @@ import sun.security.action.*;
|
||||||
public final class DNSNameService implements NameService {
|
public final class DNSNameService implements NameService {
|
||||||
|
|
||||||
// List of domains specified by property
|
// List of domains specified by property
|
||||||
private LinkedList domainList = null;
|
private LinkedList<String> domainList = null;
|
||||||
|
|
||||||
// JNDI-DNS URL for name servers specified via property
|
// JNDI-DNS URL for name servers specified via property
|
||||||
private String nameProviderUrl = null;
|
private String nameProviderUrl = null;
|
||||||
|
|
||||||
// Per-thread soft cache of the last temporary context
|
// Per-thread soft cache of the last temporary context
|
||||||
private static ThreadLocal contextRef = new ThreadLocal();
|
private static ThreadLocal<SoftReference<ThreadContext>> contextRef =
|
||||||
|
new ThreadLocal<>();
|
||||||
|
|
||||||
// Simple class to encapsulate the temporary context
|
// Simple class to encapsulate the temporary context
|
||||||
private static class ThreadContext {
|
private static class ThreadContext {
|
||||||
private DirContext dirCtxt;
|
private DirContext dirCtxt;
|
||||||
private List nsList;
|
private List<String> nsList;
|
||||||
|
|
||||||
public ThreadContext(DirContext dirCtxt, List nsList) {
|
public ThreadContext(DirContext dirCtxt, List<String> nsList) {
|
||||||
this.dirCtxt = dirCtxt;
|
this.dirCtxt = dirCtxt;
|
||||||
this.nsList = nsList;
|
this.nsList = nsList;
|
||||||
}
|
}
|
||||||
|
@ -67,16 +68,16 @@ public final class DNSNameService implements NameService {
|
||||||
return dirCtxt;
|
return dirCtxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List nameservers() {
|
public List<String> nameservers() {
|
||||||
return nsList;
|
return nsList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a per-thread DirContext
|
// Returns a per-thread DirContext
|
||||||
private DirContext getTemporaryContext() throws NamingException {
|
private DirContext getTemporaryContext() throws NamingException {
|
||||||
SoftReference ref = (SoftReference)contextRef.get();
|
SoftReference<ThreadContext> ref = contextRef.get();
|
||||||
ThreadContext thrCtxt = null;
|
ThreadContext thrCtxt = null;
|
||||||
List nsList = null;
|
List<String> nsList = null;
|
||||||
|
|
||||||
// if no property specified we need to obtain the list of servers
|
// if no property specified we need to obtain the list of servers
|
||||||
//
|
//
|
||||||
|
@ -87,7 +88,7 @@ public final class DNSNameService implements NameService {
|
||||||
// specified then we need to check if the DNS configuration
|
// specified then we need to check if the DNS configuration
|
||||||
// has changed.
|
// has changed.
|
||||||
//
|
//
|
||||||
if ((ref != null) && ((thrCtxt = (ThreadContext)ref.get()) != null)) {
|
if ((ref != null) && ((thrCtxt = ref.get()) != null)) {
|
||||||
if (nameProviderUrl == null) {
|
if (nameProviderUrl == null) {
|
||||||
if (!thrCtxt.nameservers().equals(nsList)) {
|
if (!thrCtxt.nameservers().equals(nsList)) {
|
||||||
// DNS configuration has changed
|
// DNS configuration has changed
|
||||||
|
@ -98,7 +99,7 @@ public final class DNSNameService implements NameService {
|
||||||
|
|
||||||
// new thread context needs to be created
|
// new thread context needs to be created
|
||||||
if (thrCtxt == null) {
|
if (thrCtxt == null) {
|
||||||
final Hashtable<String,Object> env = new Hashtable<String,Object>();
|
final Hashtable<String,Object> env = new Hashtable<>();
|
||||||
env.put("java.naming.factory.initial",
|
env.put("java.naming.factory.initial",
|
||||||
"com.sun.jndi.dns.DnsContextFactory");
|
"com.sun.jndi.dns.DnsContextFactory");
|
||||||
|
|
||||||
|
@ -119,10 +120,9 @@ public final class DNSNameService implements NameService {
|
||||||
//
|
//
|
||||||
DirContext dirCtxt;
|
DirContext dirCtxt;
|
||||||
try {
|
try {
|
||||||
dirCtxt = (DirContext)
|
dirCtxt = java.security.AccessController.doPrivileged(
|
||||||
java.security.AccessController.doPrivileged(
|
new java.security.PrivilegedExceptionAction<DirContext>() {
|
||||||
new java.security.PrivilegedExceptionAction() {
|
public DirContext run() throws NamingException {
|
||||||
public Object run() throws NamingException {
|
|
||||||
// Create the DNS context using NamingManager rather than using
|
// Create the DNS context using NamingManager rather than using
|
||||||
// the initial context constructor. This avoids having the initial
|
// the initial context constructor. This avoids having the initial
|
||||||
// context constructor call itself.
|
// context constructor call itself.
|
||||||
|
@ -130,7 +130,7 @@ public final class DNSNameService implements NameService {
|
||||||
if (!(ctx instanceof DirContext)) {
|
if (!(ctx instanceof DirContext)) {
|
||||||
return null; // cannot create a DNS context
|
return null; // cannot create a DNS context
|
||||||
}
|
}
|
||||||
return ctx;
|
return (DirContext)ctx;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (java.security.PrivilegedActionException pae) {
|
} catch (java.security.PrivilegedActionException pae) {
|
||||||
|
@ -161,18 +161,18 @@ public final class DNSNameService implements NameService {
|
||||||
*
|
*
|
||||||
* @throws UnknownHostException if lookup fails or other error.
|
* @throws UnknownHostException if lookup fails or other error.
|
||||||
*/
|
*/
|
||||||
private ArrayList resolve(final DirContext ctx, final String name, final String[] ids,
|
private ArrayList<String> resolve(final DirContext ctx, final String name,
|
||||||
int depth) throws UnknownHostException
|
final String[] ids, int depth)
|
||||||
|
throws UnknownHostException
|
||||||
{
|
{
|
||||||
ArrayList results = new ArrayList();
|
ArrayList<String> results = new ArrayList<>();
|
||||||
Attributes attrs;
|
Attributes attrs;
|
||||||
|
|
||||||
// do the query
|
// do the query
|
||||||
try {
|
try {
|
||||||
attrs = (Attributes)
|
attrs = java.security.AccessController.doPrivileged(
|
||||||
java.security.AccessController.doPrivileged(
|
new java.security.PrivilegedExceptionAction<Attributes>() {
|
||||||
new java.security.PrivilegedExceptionAction() {
|
public Attributes run() throws NamingException {
|
||||||
public Object run() throws NamingException {
|
|
||||||
return ctx.getAttributes(name, ids);
|
return ctx.getAttributes(name, ids);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -181,7 +181,7 @@ public final class DNSNameService implements NameService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-requested type returned so enumeration is empty
|
// non-requested type returned so enumeration is empty
|
||||||
NamingEnumeration ne = attrs.getAll();
|
NamingEnumeration<? extends Attribute> ne = attrs.getAll();
|
||||||
if (!ne.hasMoreElements()) {
|
if (!ne.hasMoreElements()) {
|
||||||
throw new UnknownHostException("DNS record not found");
|
throw new UnknownHostException("DNS record not found");
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ public final class DNSNameService implements NameService {
|
||||||
UnknownHostException uhe = null;
|
UnknownHostException uhe = null;
|
||||||
try {
|
try {
|
||||||
while (ne.hasMoreElements()) {
|
while (ne.hasMoreElements()) {
|
||||||
Attribute attr = (Attribute)ne.next();
|
Attribute attr = ne.next();
|
||||||
String attrID = attr.getID();
|
String attrID = attr.getID();
|
||||||
|
|
||||||
for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) {
|
for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) {
|
||||||
|
@ -251,13 +251,12 @@ public final class DNSNameService implements NameService {
|
||||||
// no property specified so check host DNS resolver configured
|
// no property specified so check host DNS resolver configured
|
||||||
// with at least one nameserver in dotted notation.
|
// with at least one nameserver in dotted notation.
|
||||||
//
|
//
|
||||||
List nsList = ResolverConfiguration.open().nameservers();
|
List<String> nsList = ResolverConfiguration.open().nameservers();
|
||||||
if (nsList.size() == 0)
|
if (nsList.isEmpty()) {
|
||||||
throw new RuntimeException("no nameservers provided");
|
throw new RuntimeException("no nameservers provided");
|
||||||
|
}
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
Iterator i = nsList.iterator();
|
for (String addr: nsList) {
|
||||||
while (i.hasNext()) {
|
|
||||||
String addr = (String)i.next();
|
|
||||||
if (IPAddressUtil.isIPv4LiteralAddress(addr) ||
|
if (IPAddressUtil.isIPv4LiteralAddress(addr) ||
|
||||||
IPAddressUtil.isIPv6LiteralAddress(addr)) {
|
IPAddressUtil.isIPv6LiteralAddress(addr)) {
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -308,8 +307,8 @@ public final class DNSNameService implements NameService {
|
||||||
// suffix if the list has one entry.
|
// suffix if the list has one entry.
|
||||||
|
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
List searchList = null;
|
List<String> searchList = null;
|
||||||
Iterator i;
|
Iterator<String> i;
|
||||||
boolean usingSearchList = false;
|
boolean usingSearchList = false;
|
||||||
|
|
||||||
if (domainList != null) {
|
if (domainList != null) {
|
||||||
|
@ -324,7 +323,7 @@ public final class DNSNameService implements NameService {
|
||||||
|
|
||||||
// iterator through each domain suffix
|
// iterator through each domain suffix
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
String parentDomain = (String)i.next();
|
String parentDomain = i.next();
|
||||||
int start = 0;
|
int start = 0;
|
||||||
while ((start = parentDomain.indexOf(".")) != -1
|
while ((start = parentDomain.indexOf(".")) != -1
|
||||||
&& start < parentDomain.length() -1) {
|
&& start < parentDomain.length() -1) {
|
||||||
|
@ -407,7 +406,7 @@ public final class DNSNameService implements NameService {
|
||||||
String literalip = "";
|
String literalip = "";
|
||||||
String[] ids = { "PTR" };
|
String[] ids = { "PTR" };
|
||||||
DirContext ctx;
|
DirContext ctx;
|
||||||
ArrayList results = null;
|
ArrayList<String> results = null;
|
||||||
try {
|
try {
|
||||||
ctx = getTemporaryContext();
|
ctx = getTemporaryContext();
|
||||||
} catch (NamingException nx) {
|
} catch (NamingException nx) {
|
||||||
|
@ -420,7 +419,7 @@ public final class DNSNameService implements NameService {
|
||||||
literalip += "IN-ADDR.ARPA.";
|
literalip += "IN-ADDR.ARPA.";
|
||||||
|
|
||||||
results = resolve(ctx, literalip, ids, 0);
|
results = resolve(ctx, literalip, ids, 0);
|
||||||
host = (String)results.get(0);
|
host = results.get(0);
|
||||||
} else if (addr.length == 16) { // IPv6 Address
|
} else if (addr.length == 16) { // IPv6 Address
|
||||||
/**
|
/**
|
||||||
* Because RFC 3152 changed the root domain name for reverse
|
* Because RFC 3152 changed the root domain name for reverse
|
||||||
|
@ -437,7 +436,7 @@ public final class DNSNameService implements NameService {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
results = resolve(ctx, ip6lit, ids, 0);
|
results = resolve(ctx, ip6lit, ids, 0);
|
||||||
host = (String)results.get(0);
|
host = results.get(0);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
host = null;
|
host = null;
|
||||||
}
|
}
|
||||||
|
@ -445,7 +444,7 @@ public final class DNSNameService implements NameService {
|
||||||
// IP6.ARPA lookup failed, let's try the older IP6.INT
|
// IP6.ARPA lookup failed, let's try the older IP6.INT
|
||||||
ip6lit = literalip + "IP6.INT.";
|
ip6lit = literalip + "IP6.INT.";
|
||||||
results = resolve(ctx, ip6lit, ids, 0);
|
results = resolve(ctx, ip6lit, ids, 0);
|
||||||
host = (String)results.get(0);
|
host = results.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -478,11 +477,10 @@ public final class DNSNameService implements NameService {
|
||||||
* @return String containing the JNDI-DNS provider URL
|
* @return String containing the JNDI-DNS provider URL
|
||||||
* corresponding to the supplied List of nameservers.
|
* corresponding to the supplied List of nameservers.
|
||||||
*/
|
*/
|
||||||
private static String createProviderURL(List nsList) {
|
private static String createProviderURL(List<String> nsList) {
|
||||||
Iterator i = nsList.iterator();
|
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
while (i.hasNext()) {
|
for (String s: nsList) {
|
||||||
appendIfLiteralAddress((String)i.next(), sb);
|
appendIfLiteralAddress(s, sb);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,7 +336,12 @@ public class SocketAdaptor
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendUrgentData(int data) throws IOException {
|
public void sendUrgentData(int data) throws IOException {
|
||||||
throw new SocketException("Urgent data not supported");
|
synchronized (sc.blockingLock()) {
|
||||||
|
if (!sc.isBlocking())
|
||||||
|
throw new IllegalBlockingModeException();
|
||||||
|
int n = sc.sendOutOfBandData((byte)data);
|
||||||
|
assert n == 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOOBInline(boolean on) throws SocketException {
|
public void setOOBInline(boolean on) throws SocketException {
|
||||||
|
|
|
@ -498,6 +498,36 @@ class SocketChannelImpl
|
||||||
return write0(Util.subsequence(srcs, offset, length));
|
return write0(Util.subsequence(srcs, offset, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// package-private
|
||||||
|
int sendOutOfBandData(byte b) throws IOException {
|
||||||
|
synchronized (writeLock) {
|
||||||
|
ensureWriteOpen();
|
||||||
|
int n = 0;
|
||||||
|
try {
|
||||||
|
begin();
|
||||||
|
synchronized (stateLock) {
|
||||||
|
if (!isOpen())
|
||||||
|
return 0;
|
||||||
|
writerThread = NativeThread.current();
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
n = sendOutOfBandData(fd, b);
|
||||||
|
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||||
|
continue;
|
||||||
|
return IOStatus.normalize(n);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
writerCleanup();
|
||||||
|
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||||
|
synchronized (stateLock) {
|
||||||
|
if ((n <= 0) && (!isOutputOpen))
|
||||||
|
throw new AsynchronousCloseException();
|
||||||
|
}
|
||||||
|
assert IOStatus.check(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void implConfigureBlocking(boolean block) throws IOException {
|
protected void implConfigureBlocking(boolean block) throws IOException {
|
||||||
IOUtil.configureBlocking(fd, block);
|
IOUtil.configureBlocking(fd, block);
|
||||||
}
|
}
|
||||||
|
@ -957,6 +987,9 @@ class SocketChannelImpl
|
||||||
boolean block, boolean ready)
|
boolean block, boolean ready)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
|
private static native int sendOutOfBandData(FileDescriptor fd, byte data)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Util.load();
|
Util.load();
|
||||||
nd = new SocketDispatcher();
|
nd = new SocketDispatcher();
|
||||||
|
|
|
@ -42,6 +42,8 @@ import java.util.Enumeration;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.List;
|
||||||
|
import sun.net.dns.ResolverConfiguration;
|
||||||
import sun.security.krb5.internal.crypto.EType;
|
import sun.security.krb5.internal.crypto.EType;
|
||||||
import sun.security.krb5.internal.ktab.*;
|
import sun.security.krb5.internal.ktab.*;
|
||||||
import sun.security.krb5.internal.Krb5;
|
import sun.security.krb5.internal.Krb5;
|
||||||
|
@ -1180,6 +1182,33 @@ public class Config {
|
||||||
}
|
}
|
||||||
// get the domain realm mapping from the configuration
|
// get the domain realm mapping from the configuration
|
||||||
String mapRealm = PrincipalName.mapHostToRealm(hostName);
|
String mapRealm = PrincipalName.mapHostToRealm(hostName);
|
||||||
|
if (mapRealm == null) {
|
||||||
|
// No match. Try search and/or domain in /etc/resolv.conf
|
||||||
|
List<String> srchlist = ResolverConfiguration.open().searchlist();
|
||||||
|
for (String domain: srchlist) {
|
||||||
|
realm = checkRealm(domain);
|
||||||
|
if (realm != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
realm = checkRealm(mapRealm);
|
||||||
|
}
|
||||||
|
if (realm == null) {
|
||||||
|
throw new KrbException(Krb5.KRB_ERR_GENERIC,
|
||||||
|
"Unable to locate Kerberos realm");
|
||||||
|
}
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the provided realm is the correct realm
|
||||||
|
* @return the realm if correct, or null otherwise
|
||||||
|
*/
|
||||||
|
private static String checkRealm(String mapRealm) {
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("getRealmFromDNS: trying " + mapRealm);
|
||||||
|
}
|
||||||
String[] records = null;
|
String[] records = null;
|
||||||
String newRealm = mapRealm;
|
String newRealm = mapRealm;
|
||||||
while ((records == null) && (newRealm != null)) {
|
while ((records == null) && (newRealm != null)) {
|
||||||
|
@ -1188,23 +1217,14 @@ public class Config {
|
||||||
newRealm = Realm.parseRealmComponent(newRealm);
|
newRealm = Realm.parseRealmComponent(newRealm);
|
||||||
// if no DNS TXT records found, try again using sub-realm
|
// if no DNS TXT records found, try again using sub-realm
|
||||||
}
|
}
|
||||||
if (records == null) {
|
if (records != null) {
|
||||||
// no DNS TXT records
|
for (int i = 0; i < records.length; i++) {
|
||||||
throw new KrbException(Krb5.KRB_ERR_GENERIC,
|
if (records[i].equalsIgnoreCase(mapRealm)) {
|
||||||
"Unable to locate Kerberos realm");
|
return records[i];
|
||||||
}
|
}
|
||||||
boolean found = false;
|
|
||||||
for (int i = 0; i < records.length; i++) {
|
|
||||||
if (records[i].equals(mapRealm)) {
|
|
||||||
found = true;
|
|
||||||
realm = records[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found == false) {
|
return null;
|
||||||
throw new KrbException(Krb5.KRB_ERR_GENERIC,
|
|
||||||
"Unable to locate Kerberos realm");
|
|
||||||
}
|
|
||||||
return realm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1218,10 +1238,16 @@ public class Config {
|
||||||
String kdcs = null;
|
String kdcs = null;
|
||||||
String[] srvs = null;
|
String[] srvs = null;
|
||||||
// locate DNS SRV record using UDP
|
// locate DNS SRV record using UDP
|
||||||
srvs = KrbServiceLocator.getKerberosService(realm, "_udp.");
|
if (DEBUG) {
|
||||||
|
System.out.println("getKDCFromDNS using UDP");
|
||||||
|
}
|
||||||
|
srvs = KrbServiceLocator.getKerberosService(realm, "_udp");
|
||||||
if (srvs == null) {
|
if (srvs == null) {
|
||||||
// locate DNS SRV record using TCP
|
// locate DNS SRV record using TCP
|
||||||
srvs = KrbServiceLocator.getKerberosService(realm, "_tcp.");
|
if (DEBUG) {
|
||||||
|
System.out.println("getKDCFromDNS using UDP");
|
||||||
|
}
|
||||||
|
srvs = KrbServiceLocator.getKerberosService(realm, "_tcp");
|
||||||
}
|
}
|
||||||
if (srvs == null) {
|
if (srvs == null) {
|
||||||
// no DNS SRV records
|
// no DNS SRV records
|
||||||
|
|
|
@ -36,6 +36,7 @@ import sun.security.krb5.internal.ccache.CredentialsCache;
|
||||||
import sun.security.krb5.internal.crypto.EType;
|
import sun.security.krb5.internal.crypto.EType;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -287,7 +288,7 @@ public class Credentials {
|
||||||
// The default ticket cache on Windows is not a file.
|
// The default ticket cache on Windows is not a file.
|
||||||
String os = java.security.AccessController.doPrivileged(
|
String os = java.security.AccessController.doPrivileged(
|
||||||
new sun.security.action.GetPropertyAction("os.name"));
|
new sun.security.action.GetPropertyAction("os.name"));
|
||||||
if (os.toUpperCase().startsWith("WINDOWS")) {
|
if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS")) {
|
||||||
Credentials creds = acquireDefaultCreds();
|
Credentials creds = acquireDefaultCreds();
|
||||||
if (creds == null) {
|
if (creds == null) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@ package sun.security.pkcs;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import sun.security.x509.CertificateExtensions;
|
import sun.security.x509.CertificateExtensions;
|
||||||
|
@ -742,7 +743,7 @@ public class PKCS9Attribute implements DerEncoder {
|
||||||
* the name.
|
* the name.
|
||||||
*/
|
*/
|
||||||
public static ObjectIdentifier getOID(String name) {
|
public static ObjectIdentifier getOID(String name) {
|
||||||
return NAME_OID_TABLE.get(name.toLowerCase());
|
return NAME_OID_TABLE.get(name.toLowerCase(Locale.ENGLISH));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,6 +26,7 @@ package sun.security.pkcs11;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
@ -201,7 +202,7 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int parseMode(String mode) throws NoSuchAlgorithmException {
|
private int parseMode(String mode) throws NoSuchAlgorithmException {
|
||||||
mode = mode.toUpperCase();
|
mode = mode.toUpperCase(Locale.ENGLISH);
|
||||||
int result;
|
int result;
|
||||||
if (mode.equals("ECB")) {
|
if (mode.equals("ECB")) {
|
||||||
result = MODE_ECB;
|
result = MODE_ECB;
|
||||||
|
@ -222,7 +223,7 @@ final class P11Cipher extends CipherSpi {
|
||||||
throws NoSuchPaddingException {
|
throws NoSuchPaddingException {
|
||||||
paddingObj = null;
|
paddingObj = null;
|
||||||
padBuffer = null;
|
padBuffer = null;
|
||||||
padding = padding.toUpperCase();
|
padding = padding.toUpperCase(Locale.ENGLISH);
|
||||||
if (padding.equals("NOPADDING")) {
|
if (padding.equals("NOPADDING")) {
|
||||||
paddingType = PAD_NONE;
|
paddingType = PAD_NONE;
|
||||||
} else if (padding.equals("PKCS5PADDING")) {
|
} else if (padding.equals("PKCS5PADDING")) {
|
||||||
|
|
|
@ -29,6 +29,8 @@ import java.security.*;
|
||||||
import java.security.spec.AlgorithmParameterSpec;
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.crypto.*;
|
import javax.crypto.*;
|
||||||
import javax.crypto.spec.*;
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
@ -110,7 +112,7 @@ final class P11RSACipher extends CipherSpi {
|
||||||
|
|
||||||
protected void engineSetPadding(String padding)
|
protected void engineSetPadding(String padding)
|
||||||
throws NoSuchPaddingException {
|
throws NoSuchPaddingException {
|
||||||
String lowerPadding = padding.toLowerCase();
|
String lowerPadding = padding.toLowerCase(Locale.ENGLISH);
|
||||||
if (lowerPadding.equals("pkcs1Padding")) {
|
if (lowerPadding.equals("pkcs1Padding")) {
|
||||||
// empty
|
// empty
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,6 +52,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import sun.security.x509.AccessDescription;
|
import sun.security.x509.AccessDescription;
|
||||||
import sun.security.x509.GeneralNameInterface;
|
import sun.security.x509.GeneralNameInterface;
|
||||||
import sun.security.x509.URIName;
|
import sun.security.x509.URIName;
|
||||||
|
@ -162,7 +163,7 @@ class URICertStore extends CertStoreSpi {
|
||||||
}
|
}
|
||||||
this.uri = ((URICertStoreParameters) params).uri;
|
this.uri = ((URICertStoreParameters) params).uri;
|
||||||
// if ldap URI, use an LDAPCertStore to fetch certs and CRLs
|
// if ldap URI, use an LDAPCertStore to fetch certs and CRLs
|
||||||
if (uri.getScheme().toLowerCase().equals("ldap")) {
|
if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals("ldap")) {
|
||||||
if (LDAP.helper() == null)
|
if (LDAP.helper() == null)
|
||||||
throw new NoSuchAlgorithmException("LDAP not present");
|
throw new NoSuchAlgorithmException("LDAP not present");
|
||||||
ldap = true;
|
ldap = true;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2007, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@ package sun.security.util;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class for debuging.
|
* A utility class for debuging.
|
||||||
|
@ -262,7 +263,7 @@ public class Debug {
|
||||||
source = left;
|
source = left;
|
||||||
|
|
||||||
// convert the rest to lower-case characters
|
// convert the rest to lower-case characters
|
||||||
target.append(source.toString().toLowerCase());
|
target.append(source.toString().toLowerCase(Locale.ENGLISH));
|
||||||
|
|
||||||
return target.toString();
|
return target.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,17 +25,16 @@
|
||||||
|
|
||||||
package sun.security.util;
|
package sun.security.util;
|
||||||
|
|
||||||
import java.io.FilterOutputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -501,7 +500,7 @@ extends ByteArrayOutputStream implements DerEncoder {
|
||||||
pattern = "yyyyMMddHHmmss'Z'";
|
pattern = "yyyyMMddHHmmss'Z'";
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US);
|
||||||
sdf.setTimeZone(tz);
|
sdf.setTimeZone(tz);
|
||||||
byte[] time = (sdf.format(d)).getBytes("ISO-8859-1");
|
byte[] time = (sdf.format(d)).getBytes("ISO-8859-1");
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue