This commit is contained in:
Ioi Lam 2014-09-19 13:47:19 -07:00
commit a2e41921c1
263 changed files with 9016 additions and 2958 deletions

View file

@ -273,3 +273,4 @@ d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27
f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28 f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28
c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29 c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29
b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30 b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30
9d0e6639a4d71b63507dd94b1a028e963b27e798 jdk9-b31

View file

@ -273,3 +273,4 @@ ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27
ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28 ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28
9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29 9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29
36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30 36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30
69a84c16d9c28e0e3d504b9c8766c24bafcd58f6 jdk9-b31

View file

@ -70,8 +70,8 @@ else
# Run the makefile with an arbitrary SPEC using -p -q (quiet dry-run and dump rules) to find # Run the makefile with an arbitrary SPEC using -p -q (quiet dry-run and dump rules) to find
# available PHONY targets. Use this list as valid targets to pass on to the repeated calls. # available PHONY targets. Use this list as valid targets to pass on to the repeated calls.
all_phony_targets := $(sort $(filter-out $(global_targets), $(strip $(shell \ all_phony_targets := $(sort $(filter-out $(global_targets), $(strip $(shell \
cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) | \ cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) \
grep "^.PHONY:" | head -n 1 | cut -d " " -f 2-)))) -I $(root_dir)/make/common | grep "^.PHONY:" | head -n 1 | cut -d " " -f 2-))))
# Loop through the configurations and call the main-wrapper for each one. The wrapper # Loop through the configurations and call the main-wrapper for each one. The wrapper
# target will execute with a single configuration loaded. # target will execute with a single configuration loaded.
@ -115,12 +115,12 @@ else
main-wrapper: main-wrapper:
ifneq ($(SEQUENTIAL_TARGETS), ) ifneq ($(SEQUENTIAL_TARGETS), )
(cd $(root_dir)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \ (cd $(SRC_ROOT)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \
$(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(SEQUENTIAL_TARGETS)) $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(SEQUENTIAL_TARGETS))
endif endif
ifneq ($(PARALLEL_TARGETS), ) ifneq ($(PARALLEL_TARGETS), )
@$(call AtMakeStart) @$(call AtMakeStart)
(cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \ (cd $(SRC_ROOT)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \
$(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(PARALLEL_TARGETS) \ $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(PARALLEL_TARGETS) \
$(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC))) $(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC)))
@$(call AtMakeEnd) @$(call AtMakeEnd)

View file

@ -4327,7 +4327,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
#CUSTOM_AUTOCONF_INCLUDE #CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks: # Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1410377275 DATE_WHEN_GENERATED=1410791401
############################################################################### ###############################################################################
# #
@ -14642,7 +14642,7 @@ $as_echo "$DEBUG_LEVEL" >&6; }
FASTDEBUG="false" FASTDEBUG="false"
DEBUG_CLASSFILES="true" DEBUG_CLASSFILES="true"
BUILD_VARIANT_RELEASE="-debug" BUILD_VARIANT_RELEASE="-debug"
HOTSPOT_DEBUG_LEVEL="jvmg" HOTSPOT_DEBUG_LEVEL="debug"
HOTSPOT_EXPORT="debug" HOTSPOT_EXPORT="debug"
;; ;;
optimized ) optimized )

View file

@ -97,8 +97,6 @@ ifeq ($(JVM_INTERPRETER), cpp)
endif endif
HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@ HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@
# This is used from the libjvm build for C/C++ code.
HOTSPOT_BUILD_JOBS:=$(JOBS)
# Control wether Hotspot runs Queens test after building # Control wether Hotspot runs Queens test after building
TEST_IN_BUILD=@TEST_IN_BUILD@ TEST_IN_BUILD=@TEST_IN_BUILD@

View file

@ -234,7 +234,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL],
FASTDEBUG="false" FASTDEBUG="false"
DEBUG_CLASSFILES="true" DEBUG_CLASSFILES="true"
BUILD_VARIANT_RELEASE="-debug" BUILD_VARIANT_RELEASE="-debug"
HOTSPOT_DEBUG_LEVEL="jvmg" HOTSPOT_DEBUG_LEVEL="debug"
HOTSPOT_EXPORT="debug" HOTSPOT_EXPORT="debug"
;; ;;
optimized ) optimized )

View file

@ -245,6 +245,7 @@ JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
NASHORN_OUTPUTDIR=$(BUILD_OUTPUT)/nashorn NASHORN_OUTPUTDIR=$(BUILD_OUTPUT)/nashorn
IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist
CORBA_DIST=$(CORBA_OUTPUTDIR)/dist CORBA_DIST=$(CORBA_OUTPUTDIR)/dist

View file

@ -1216,14 +1216,13 @@ jdk/src/java.security.acl/share/classes/java/security/acl : jdk/src/share/classe
jdk/src/java.security.acl/share/classes/sun/security/acl : jdk/src/share/classes/sun/security/acl jdk/src/java.security.acl/share/classes/sun/security/acl : jdk/src/share/classes/sun/security/acl
jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c : jdk/src/share/native/sun/security/krb5/nativeccache.c jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c : jdk/src/share/native/sun/security/krb5/nativeccache.c
jdk/src/java.security.jgss/macosx/native/libosxkrb5/SCDynamicStoreConfig.m : jdk/src/macosx/native/sun/security/krb5/SCDynamicStoreConfig.m jdk/src/java.security.jgss/macosx/native/libosxkrb5/SCDynamicStoreConfig.m : jdk/src/macosx/native/sun/security/krb5/SCDynamicStoreConfig.m
jdk/src/java.security.jgss/share/classes/com/sun/security/jgss : jdk/src/share/classes/com/sun/security/jgss
jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb : jdk/src/share/classes/com/sun/security/sasl/gsskerb
jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos : jdk/src/share/classes/javax/security/auth/kerberos jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos : jdk/src/share/classes/javax/security/auth/kerberos
jdk/src/java.security.jgss/share/classes/jgss-overview.html : jdk/src/share/classes/com/sun/security/jgss/jgss-overview.html jdk/src/java.security.jgss/share/classes/jgss-overview.html : jdk/src/share/classes/com/sun/security/jgss/jgss-overview.html
jdk/src/java.security.jgss/share/classes/org/ietf/jgss : jdk/src/share/classes/org/ietf/jgss jdk/src/java.security.jgss/share/classes/org/ietf/jgss : jdk/src/share/classes/org/ietf/jgss
jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego : jdk/src/share/classes/sun/net/www/protocol/http/spnego jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego : jdk/src/share/classes/sun/net/www/protocol/http/spnego
jdk/src/java.security.jgss/share/classes/sun/security/jgss : jdk/src/share/classes/sun/security/jgss jdk/src/java.security.jgss/share/classes/sun/security/jgss : jdk/src/share/classes/sun/security/jgss
jdk/src/java.security.jgss/share/classes/sun/security/krb5 : jdk/src/share/classes/sun/security/krb5 jdk/src/java.security.jgss/share/classes/sun/security/krb5 : jdk/src/share/classes/sun/security/krb5
jdk/src/java.security.jgss/windows/classes/sun/security/krb5 : jdk/src/windows/classes/sun/security/krb5
jdk/src/java.security.jgss/share/classes/sun/security/ssl/krb5 : jdk/src/share/classes/sun/security/ssl/krb5 jdk/src/java.security.jgss/share/classes/sun/security/ssl/krb5 : jdk/src/share/classes/sun/security/ssl/krb5
jdk/src/java.security.jgss/share/native/libj2gss : jdk/src/share/native/sun/security/jgss/wrapper jdk/src/java.security.jgss/share/native/libj2gss : jdk/src/share/native/sun/security/jgss/wrapper
jdk/src/java.security.jgss/unix/native/libj2gss : jdk/src/solaris/native/sun/security/jgss/wrapper jdk/src/java.security.jgss/unix/native/libj2gss : jdk/src/solaris/native/sun/security/jgss/wrapper
@ -1477,6 +1476,8 @@ jdk/src/jdk.security.auth/share/classes/com/sun/security/auth : jdk/src/share/cl
jdk/src/jdk.security.auth/share/classes/jaas-overview.html : jdk/src/share/classes/com/sun/security/auth/jaas-overview.html jdk/src/jdk.security.auth/share/classes/jaas-overview.html : jdk/src/share/classes/com/sun/security/auth/jaas-overview.html
jdk/src/jdk.security.auth/unix/native/libjaas : jdk/src/solaris/native/com/sun/security/auth/module jdk/src/jdk.security.auth/unix/native/libjaas : jdk/src/solaris/native/com/sun/security/auth/module
jdk/src/jdk.security.auth/windows/native/libjaas : jdk/src/windows/native/com/sun/security/auth/module jdk/src/jdk.security.auth/windows/native/libjaas : jdk/src/windows/native/com/sun/security/auth/module
jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss : jdk/src/share/classes/com/sun/security/jgss
jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb : jdk/src/share/classes/com/sun/security/sasl/gsskerb
jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp : jdk/src/share/classes/com/sun/jmx/snmp jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp : jdk/src/share/classes/com/sun/jmx/snmp
jdk/src/jdk.snmp/share/classes/sun/management/snmp : jdk/src/share/classes/sun/management/snmp jdk/src/jdk.snmp/share/classes/sun/management/snmp : jdk/src/share/classes/sun/management/snmp
jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs : jdk/src/share/classes/jdk/nio/zipfs jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs : jdk/src/share/classes/jdk/nio/zipfs

View file

@ -273,3 +273,4 @@ da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25
a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28 a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28
163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29 163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29
98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30 98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30
c432b80aadd0cb2b2361b02add4d671957d4cec9 jdk9-b31

View file

@ -433,3 +433,4 @@ f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27
657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28 657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28
deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29 deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29
5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30 5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30
9f7d155d28e519f3e4645dc21cf185c25f3176ed jdk9-b31

View file

@ -107,7 +107,6 @@ public class VM {
private Runtime1 runtime1; private Runtime1 runtime1;
/** These constants come from globalDefinitions.hpp */ /** These constants come from globalDefinitions.hpp */
private int invocationEntryBCI; private int invocationEntryBCI;
private int invalidOSREntryBCI;
private ReversePtrs revPtrs; private ReversePtrs revPtrs;
private VMRegImpl vmregImpl; private VMRegImpl vmregImpl;
private int reserveForAllocationPrefetch; private int reserveForAllocationPrefetch;
@ -295,7 +294,6 @@ public class VM {
stackBias = db.lookupIntConstant("STACK_BIAS").intValue(); stackBias = db.lookupIntConstant("STACK_BIAS").intValue();
invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue();
invalidOSREntryBCI = db.lookupIntConstant("InvalidOSREntryBci").intValue();
// We infer the presence of C1 or C2 from a couple of fields we // We infer the presence of C1 or C2 from a couple of fields we
// already have present in the type database // already have present in the type database
@ -733,11 +731,6 @@ public class VM {
return invocationEntryBCI; return invocationEntryBCI;
} }
/** FIXME: figure out where to stick this */
public int getInvalidOSREntryBCI() {
return invalidOSREntryBCI;
}
// FIXME: figure out where to stick this // FIXME: figure out where to stick this
public boolean wizardMode() { public boolean wizardMode() {
return true; return true;

View file

@ -1166,9 +1166,9 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr(Register backedge_co
beq(CCR0, overflow_with_error); beq(CCR0, overflow_with_error);
// Has the nmethod been invalidated already? // Has the nmethod been invalidated already?
lwz(Rtmp, nmethod::entry_bci_offset(), R3_RET); lbz(Rtmp, nmethod::state_offset(), R3_RET);
cmpwi(CCR0, Rtmp, InvalidOSREntryBci); cmpwi(CCR0, Rtmp, nmethod::in_use);
beq(CCR0, overflow_with_error); bne(CCR0, overflow_with_error);
// Migrate the interpreter frame off of the stack. // Migrate the interpreter frame off of the stack.
// We can use all registers because we will not return to interpreter from this point. // We can use all registers because we will not return to interpreter from this point.

View file

@ -1674,9 +1674,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ beq(CCR0, Lforward); __ beq(CCR0, Lforward);
// Has the nmethod been invalidated already? // Has the nmethod been invalidated already?
__ lwz(R0, nmethod::entry_bci_offset(), R3_RET); __ lbz(R0, nmethod::state_offset(), R3_RET);
__ cmpwi(CCR0, R0, InvalidOSREntryBci); __ cmpwi(CCR0, R0, nmethod::in_use);
__ beq(CCR0, Lforward); __ bne(CCR0, Lforward);
// Migrate the interpreter frame off of the stack. // Migrate the interpreter frame off of the stack.
// We can use all registers because we will not return to interpreter from this point. // We can use all registers because we will not return to interpreter from this point.

View file

@ -2407,8 +2407,8 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_c
br_null_short(O0, Assembler::pn, overflow_with_error); br_null_short(O0, Assembler::pn, overflow_with_error);
// Has the nmethod been invalidated already? // Has the nmethod been invalidated already?
ld(O0, nmethod::entry_bci_offset(), O2); ldub(O0, nmethod::state_offset(), O2);
cmp_and_br_short(O2, InvalidOSREntryBci, Assembler::equal, Assembler::pn, overflow_with_error); cmp_and_br_short(O2, nmethod::in_use, Assembler::notEqual, Assembler::pn, overflow_with_error);
// migrate the interpreter frame off of the stack // migrate the interpreter frame off of the stack

View file

@ -1636,8 +1636,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ br_null_short(O0, Assembler::pn, Lforward); __ br_null_short(O0, Assembler::pn, Lforward);
// Has the nmethod been invalidated already? // Has the nmethod been invalidated already?
__ ld(O0, nmethod::entry_bci_offset(), O2); __ ldub(O0, nmethod::state_offset(), O2);
__ cmp_and_br_short(O2, InvalidOSREntryBci, Assembler::equal, Assembler::pn, Lforward); __ cmp_and_br_short(O2, nmethod::in_use, Assembler::notEqual, Assembler::pn, Lforward);
// migrate the interpreter frame off of the stack // migrate the interpreter frame off of the stack

View file

@ -1724,9 +1724,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ testptr(rax, rax); // test result __ testptr(rax, rax); // test result
__ jcc(Assembler::zero, dispatch); // no osr if null __ jcc(Assembler::zero, dispatch); // no osr if null
// nmethod may have been invalidated (VM may block upon call_VM return) // nmethod may have been invalidated (VM may block upon call_VM return)
__ movl(rcx, Address(rax, nmethod::entry_bci_offset())); __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use);
__ cmpl(rcx, InvalidOSREntryBci); __ jcc(Assembler::notEqual, dispatch);
__ jcc(Assembler::equal, dispatch);
// We have the address of an on stack replacement routine in rax, // We have the address of an on stack replacement routine in rax,
// We need to prepare to execute the OSR method. First we must // We need to prepare to execute the OSR method. First we must
@ -1734,8 +1733,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ mov(rbx, rax); // save the nmethod __ mov(rbx, rax); // save the nmethod
const Register thread = rcx; __ get_thread(rcx);
__ get_thread(thread);
call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin));
// rax, is OSR buffer, move it to expected parameter location // rax, is OSR buffer, move it to expected parameter location
__ mov(rcx, rax); __ mov(rcx, rax);

View file

@ -1751,9 +1751,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ testptr(rax, rax); // test result __ testptr(rax, rax); // test result
__ jcc(Assembler::zero, dispatch); // no osr if null __ jcc(Assembler::zero, dispatch); // no osr if null
// nmethod may have been invalidated (VM may block upon call_VM return) // nmethod may have been invalidated (VM may block upon call_VM return)
__ movl(rcx, Address(rax, nmethod::entry_bci_offset())); __ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use);
__ cmpl(rcx, InvalidOSREntryBci); __ jcc(Assembler::notEqual, dispatch);
__ jcc(Assembler::equal, dispatch);
// We have the address of an on stack replacement routine in eax // We have the address of an on stack replacement routine in eax
// We need to prepare to execute the OSR method. First we must // We need to prepare to execute the OSR method. First we must

View file

@ -4002,10 +4002,6 @@ bool os::check_heap(bool force) {
return true; return true;
} }
// int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) {
// return ::vsnprintf(buf, count, format, args);
// }
// Is a (classpath) directory empty? // Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) { bool os::dir_is_empty(const char* path) {
DIR *dir = NULL; DIR *dir = NULL;

View file

@ -3822,12 +3822,6 @@ bool os::check_heap(bool force) {
return true; return true;
} }
ATTRIBUTE_PRINTF(3, 0)
int local_vsnprintf(char* buf, size_t count, const char* format,
va_list args) {
return ::vsnprintf(buf, count, format, args);
}
// Is a (classpath) directory empty? // Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) { bool os::dir_is_empty(const char* path) {
DIR *dir = NULL; DIR *dir = NULL;

View file

@ -5063,11 +5063,6 @@ bool os::check_heap(bool force) {
return true; return true;
} }
int local_vsnprintf(char* buf, size_t count, const char* format,
va_list args) {
return ::vsnprintf(buf, count, format, args);
}
// Is a (classpath) directory empty? // Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) { bool os::dir_is_empty(const char* path) {
DIR *dir = NULL; DIR *dir = NULL;

View file

@ -2539,29 +2539,30 @@ void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec,
} }
} }
size_t os::Solaris::page_size_for_alignment(size_t alignment) {
assert(is_size_aligned(alignment, (size_t) vm_page_size()),
err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT,
alignment, (size_t) vm_page_size()));
for (int i = 0; _page_sizes[i] != 0; i++) {
if (is_size_aligned(alignment, _page_sizes[i])) {
return _page_sizes[i];
}
}
return (size_t) vm_page_size();
}
int os::Solaris::commit_memory_impl(char* addr, size_t bytes, int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
size_t alignment_hint, bool exec) { size_t alignment_hint, bool exec) {
int err = Solaris::commit_memory_impl(addr, bytes, exec); int err = Solaris::commit_memory_impl(addr, bytes, exec);
if (err == 0) { if (err == 0 && UseLargePages && alignment_hint > 0) {
if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) { assert(is_size_aligned(bytes, alignment_hint),
// If the large page size has been set and the VM err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint));
// is using large pages, use the large page size
// if it is smaller than the alignment hint. This is // The syscall memcntl requires an exact page size (see man memcntl for details).
// a case where the VM wants to use a larger alignment size size_t page_size = page_size_for_alignment(alignment_hint);
// for its own reasons but still want to use large pages if (page_size > (size_t) vm_page_size()) {
// (which is what matters to setting the mpss range.
size_t page_size = 0;
if (large_page_size() < alignment_hint) {
assert(UseLargePages, "Expected to be here for large page use only");
page_size = large_page_size();
} else {
// If the alignment hint is less than the large page
// size, the VM wants a particular alignment (thus the hint)
// for internal reasons. Try to set the mpss range using
// the alignment_hint.
page_size = alignment_hint;
}
// Since this is a hint, ignore any failures.
(void)Solaris::setup_large_pages(addr, bytes, page_size); (void)Solaris::setup_large_pages(addr, bytes, page_size);
} }
} }
@ -3098,8 +3099,22 @@ void os::large_page_init() {
} }
} }
bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, bool os::Solaris::is_valid_page_size(size_t bytes) {
size_t align) { for (int i = 0; _page_sizes[i] != 0; i++) {
if (_page_sizes[i] == bytes) {
return true;
}
}
return false;
}
bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
assert(is_valid_page_size(align), err_msg(SIZE_FORMAT " is not a valid page size", align));
assert(is_ptr_aligned((void*) start, align),
err_msg(PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align));
assert(is_size_aligned(bytes, align),
err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align));
// Signal to OS that we want large pages for addresses // Signal to OS that we want large pages for addresses
// from addr, addr + bytes // from addr, addr + bytes
struct memcntl_mha mpss_struct; struct memcntl_mha mpss_struct;
@ -4769,29 +4784,6 @@ void os::make_polling_page_readable(void) {
bool os::check_heap(bool force) { return true; } bool os::check_heap(bool force) { return true; }
typedef int (*vsnprintf_t)(char* buf, size_t count, const char* fmt, va_list argptr);
static vsnprintf_t sol_vsnprintf = NULL;
int local_vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) {
if (!sol_vsnprintf) {
//search for the named symbol in the objects that were loaded after libjvm
void* where = RTLD_NEXT;
if ((sol_vsnprintf = CAST_TO_FN_PTR(vsnprintf_t, dlsym(where, "__vsnprintf"))) == NULL) {
sol_vsnprintf = CAST_TO_FN_PTR(vsnprintf_t, dlsym(where, "vsnprintf"));
}
if (!sol_vsnprintf){
//search for the named symbol in the objects that were loaded before libjvm
where = RTLD_DEFAULT;
if ((sol_vsnprintf = CAST_TO_FN_PTR(vsnprintf_t, dlsym(where, "__vsnprintf"))) == NULL) {
sol_vsnprintf = CAST_TO_FN_PTR(vsnprintf_t, dlsym(where, "vsnprintf"));
}
assert(sol_vsnprintf != NULL, "vsnprintf not found");
}
}
return (*sol_vsnprintf)(buf, count, fmt, argptr);
}
// Is a (classpath) directory empty? // Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) { bool os::dir_is_empty(const char* path) {
DIR *dir = NULL; DIR *dir = NULL;

View file

@ -97,6 +97,8 @@ class Solaris {
static meminfo_func_t _meminfo; static meminfo_func_t _meminfo;
// Large Page Support // Large Page Support
static bool is_valid_page_size(size_t bytes);
static size_t page_size_for_alignment(size_t alignment);
static bool setup_large_pages(caddr_t start, size_t bytes, size_t align); static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
static void init_thread_fpu_state(void); static void init_thread_fpu_state(void);

View file

@ -39,7 +39,6 @@ class ciField : public ResourceObj {
CI_PACKAGE_ACCESS CI_PACKAGE_ACCESS
friend class ciEnv; friend class ciEnv;
friend class ciInstanceKlass; friend class ciInstanceKlass;
friend class NonStaticFieldFiller;
private: private:
ciFlags _flags; ciFlags _flags;

View file

@ -44,7 +44,7 @@
// //
// Loaded instance klass. // Loaded instance klass.
ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
ciKlass(h_k), _non_static_fields(NULL) ciKlass(h_k)
{ {
assert(get_Klass()->oop_is_instance(), "wrong type"); assert(get_Klass()->oop_is_instance(), "wrong type");
assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); assert(get_instanceKlass()->is_loaded(), "must be at least loaded");
@ -407,37 +407,6 @@ ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature,
return field; return field;
} }
// ------------------------------------------------------------------
// ciInstanceKlass::non_static_fields.
class NonStaticFieldFiller: public FieldClosure {
GrowableArray<ciField*>* _arr;
ciEnv* _curEnv;
public:
NonStaticFieldFiller(ciEnv* curEnv, GrowableArray<ciField*>* arr) :
_curEnv(curEnv), _arr(arr)
{}
void do_field(fieldDescriptor* fd) {
ciField* field = new (_curEnv->arena()) ciField(fd);
_arr->append(field);
}
};
GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
if (_non_static_fields == NULL) {
VM_ENTRY_MARK;
ciEnv* curEnv = ciEnv::current();
InstanceKlass* ik = get_instanceKlass();
int max_n_fields = ik->java_fields_count();
Arena* arena = curEnv->arena();
_non_static_fields =
new (arena) GrowableArray<ciField*>(arena, max_n_fields, 0, NULL);
NonStaticFieldFiller filler(curEnv, _non_static_fields);
ik->do_nonstatic_fields(&filler);
}
return _non_static_fields;
}
static int sort_field_by_offset(ciField** a, ciField** b) { static int sort_field_by_offset(ciField** a, ciField** b) {
return (*a)->offset_in_bytes() - (*b)->offset_in_bytes(); return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();

View file

@ -71,8 +71,6 @@ private:
// Itsef: more than one implementors. // Itsef: more than one implementors.
ciInstanceKlass* _implementor; ciInstanceKlass* _implementor;
GrowableArray<ciField*>* _non_static_fields;
protected: protected:
ciInstanceKlass(KlassHandle h_k); ciInstanceKlass(KlassHandle h_k);
ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain); ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
@ -181,8 +179,6 @@ public:
ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_offset(int field_offset, bool is_static);
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
GrowableArray<ciField*>* non_static_fields();
// total number of nonstatic fields (including inherited): // total number of nonstatic fields (including inherited):
int nof_nonstatic_fields() { int nof_nonstatic_fields() {
if (_nonstatic_fields == NULL) if (_nonstatic_fields == NULL)

View file

@ -1364,8 +1364,6 @@ void nmethod::invalidate_osr_method() {
// Remove from list of active nmethods // Remove from list of active nmethods
if (method() != NULL) if (method() != NULL)
method()->method_holder()->remove_osr_nmethod(this); method()->method_holder()->remove_osr_nmethod(this);
// Set entry as invalid
_entry_bci = InvalidOSREntryBci;
} }
void nmethod::log_state_change() const { void nmethod::log_state_change() const {

View file

@ -202,13 +202,6 @@ class nmethod : public CodeBlob {
bool _oops_are_stale; // indicates that it's no longer safe to access oops section bool _oops_are_stale; // indicates that it's no longer safe to access oops section
#endif #endif
enum { in_use = 0, // executable nmethod
not_entrant = 1, // marked for deoptimization but activations may still exist,
// will be transformed to zombie when all activations are gone
zombie = 2, // no activations exist, nmethod is ready for purge
unloaded = 3 }; // there should be no activations, should not be called,
// will be transformed to zombie immediately
jbyte _scavenge_root_state; jbyte _scavenge_root_state;
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
@ -431,6 +424,13 @@ class nmethod : public CodeBlob {
address entry_point() const { return _entry_point; } // normal entry point address entry_point() const { return _entry_point; } // normal entry point
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
enum { in_use = 0, // executable nmethod
not_entrant = 1, // marked for deoptimization but activations may still exist,
// will be transformed to zombie when all activations are gone
zombie = 2, // no activations exist, nmethod is ready for purge
unloaded = 3 }; // there should be no activations, should not be called,
// will be transformed to zombie immediately
// flag accessing and manipulation // flag accessing and manipulation
bool is_in_use() const { return _state == in_use; } bool is_in_use() const { return _state == in_use; }
bool is_alive() const { return _state == in_use || _state == not_entrant; } bool is_alive() const { return _state == in_use || _state == not_entrant; }
@ -759,7 +759,7 @@ public:
// support for code generation // support for code generation
static int verified_entry_point_offset() { return offset_of(nmethod, _verified_entry_point); } static int verified_entry_point_offset() { return offset_of(nmethod, _verified_entry_point); }
static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); } static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); }
static int entry_bci_offset() { return offset_of(nmethod, _entry_bci); } static int state_offset() { return offset_of(nmethod, _state); }
// RedefineClasses support. Mark metadata in nmethods as on_stack so that // RedefineClasses support. Mark metadata in nmethods as on_stack so that
// redefine classes doesn't purge it. // redefine classes doesn't purge it.

View file

@ -4737,7 +4737,7 @@ void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes,
} }
bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
const char* type = ""; const char* type = r->get_type_str();
HeapWord* bottom = r->bottom(); HeapWord* bottom = r->bottom();
HeapWord* end = r->end(); HeapWord* end = r->end();
size_t capacity_bytes = r->capacity(); size_t capacity_bytes = r->capacity();
@ -4748,15 +4748,7 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
size_t remset_bytes = r->rem_set()->mem_size(); size_t remset_bytes = r->rem_set()->mem_size();
size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size(); size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size();
if (r->used() == 0) { if (r->startsHumongous()) {
type = "FREE";
} else if (r->is_survivor()) {
type = "SURV";
} else if (r->is_young()) {
type = "EDEN";
} else if (r->startsHumongous()) {
type = "HUMS";
assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 && assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 &&
_hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0, _hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0,
"they should have been zeroed after the last time we used them"); "they should have been zeroed after the last time we used them");
@ -4769,12 +4761,9 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
&prev_live_bytes, &next_live_bytes); &prev_live_bytes, &next_live_bytes);
end = bottom + HeapRegion::GrainWords; end = bottom + HeapRegion::GrainWords;
} else if (r->continuesHumongous()) { } else if (r->continuesHumongous()) {
type = "HUMC";
get_hum_bytes(&used_bytes, &capacity_bytes, get_hum_bytes(&used_bytes, &capacity_bytes,
&prev_live_bytes, &next_live_bytes); &prev_live_bytes, &next_live_bytes);
assert(end == bottom + HeapRegion::GrainWords, "invariant"); assert(end == bottom + HeapRegion::GrainWords, "invariant");
} else {
type = "OLD";
} }
_total_used_bytes += used_bytes; _total_used_bytes += used_bytes;

View file

@ -211,7 +211,10 @@ void YoungList::empty_list(HeapRegion* list) {
HeapRegion* next = list->get_next_young_region(); HeapRegion* next = list->get_next_young_region();
list->set_next_young_region(NULL); list->set_next_young_region(NULL);
list->uninstall_surv_rate_group(); list->uninstall_surv_rate_group();
list->set_not_young(); // This is called before a Full GC and all the non-empty /
// non-humongous regions at the end of the Full GC will end up as
// old anyway.
list->set_old();
list = next; list = next;
} }
} }
@ -370,7 +373,7 @@ void YoungList::print() {
if (curr == NULL) if (curr == NULL)
gclog_or_tty->print_cr(" empty"); gclog_or_tty->print_cr(" empty");
while (curr != NULL) { while (curr != NULL) {
gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d", gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT ", N: "PTR_FORMAT", age: %4d",
HR_FORMAT_PARAMS(curr), HR_FORMAT_PARAMS(curr),
curr->prev_top_at_mark_start(), curr->prev_top_at_mark_start(),
curr->next_top_at_mark_start(), curr->next_top_at_mark_start(),
@ -802,6 +805,7 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
#ifdef ASSERT #ifdef ASSERT
for (uint i = first; i < first + obj_regions; ++i) { for (uint i = first; i < first + obj_regions; ++i) {
HeapRegion* hr = region_at(i); HeapRegion* hr = region_at(i);
assert(hr->is_free(), "sanity");
assert(hr->is_empty(), "sanity"); assert(hr->is_empty(), "sanity");
assert(is_on_master_free_list(hr), "sanity"); assert(is_on_master_free_list(hr), "sanity");
} }
@ -1225,21 +1229,21 @@ private:
public: public:
bool doHeapRegion(HeapRegion* hr) { bool doHeapRegion(HeapRegion* hr) {
assert(!hr->is_young(), "not expecting to find young regions"); assert(!hr->is_young(), "not expecting to find young regions");
// We only generate output for non-empty regions. if (hr->is_free()) {
if (!hr->is_empty()) { // We only generate output for non-empty regions.
if (!hr->isHumongous()) { } else if (hr->startsHumongous()) {
_hr_printer->post_compaction(hr, G1HRPrinter::Old); if (hr->region_num() == 1) {
} else if (hr->startsHumongous()) { // single humongous region
if (hr->region_num() == 1) { _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous);
// single humongous region
_hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous);
} else {
_hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous);
}
} else { } else {
assert(hr->continuesHumongous(), "only way to get here"); _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous);
_hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous);
} }
} else if (hr->continuesHumongous()) {
_hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous);
} else if (hr->is_old()) {
_hr_printer->post_compaction(hr, G1HRPrinter::Old);
} else {
ShouldNotReachHere();
} }
return false; return false;
} }
@ -1477,9 +1481,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
// Discard all rset updates // Discard all rset updates
JavaThread::dirty_card_queue_set().abandon_logs(); JavaThread::dirty_card_queue_set().abandon_logs();
assert(!G1DeferredRSUpdate assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty");
|| (G1DeferredRSUpdate &&
(dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any");
_young_list->reset_sampled_info(); _young_list->reset_sampled_info();
// At this point there should be no regions in the // At this point there should be no regions in the
@ -2090,15 +2092,13 @@ jint G1CollectedHeap::initialize() {
concurrent_g1_refine()->red_zone(), concurrent_g1_refine()->red_zone(),
Shared_DirtyCardQ_lock); Shared_DirtyCardQ_lock);
if (G1DeferredRSUpdate) { dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code DirtyCardQ_CBL_mon,
DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock,
DirtyCardQ_FL_lock, -1, // never trigger processing
-1, // never trigger processing -1, // no limit on length
-1, // no limit on length Shared_DirtyCardQ_lock,
Shared_DirtyCardQ_lock, &JavaThread::dirty_card_queue_set());
&JavaThread::dirty_card_queue_set());
}
// Initialize the card queue set used to hold cards containing // Initialize the card queue set used to hold cards containing
// references into the collection set. // references into the collection set.
@ -2121,8 +2121,8 @@ jint G1CollectedHeap::initialize() {
// We'll re-use the same region whether the alloc region will // We'll re-use the same region whether the alloc region will
// require BOT updates or not and, if it doesn't, then a non-young // require BOT updates or not and, if it doesn't, then a non-young
// region will complain that it cannot support allocations without // region will complain that it cannot support allocations without
// BOT updates. So we'll tag the dummy region as young to avoid that. // BOT updates. So we'll tag the dummy region as eden to avoid that.
dummy_region->set_young(); dummy_region->set_eden();
// Make sure it's full. // Make sure it's full.
dummy_region->set_top(dummy_region->end()); dummy_region->set_top(dummy_region->end());
G1AllocRegion::setup(this, dummy_region); G1AllocRegion::setup(this, dummy_region);
@ -4031,14 +4031,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
if (_hr_printer.is_active()) { if (_hr_printer.is_active()) {
HeapRegion* hr = g1_policy()->collection_set(); HeapRegion* hr = g1_policy()->collection_set();
while (hr != NULL) { while (hr != NULL) {
G1HRPrinter::RegionType type;
if (!hr->is_young()) {
type = G1HRPrinter::Old;
} else if (hr->is_survivor()) {
type = G1HRPrinter::Survivor;
} else {
type = G1HRPrinter::Eden;
}
_hr_printer.cset(hr); _hr_printer.cset(hr);
hr = hr->next_in_collection_set(); hr = hr->next_in_collection_set();
} }
@ -5393,7 +5385,6 @@ class G1RedirtyLoggedCardsTask : public AbstractGangTask {
}; };
void G1CollectedHeap::redirty_logged_cards() { void G1CollectedHeap::redirty_logged_cards() {
guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
double redirty_logged_cards_start = os::elapsedTime(); double redirty_logged_cards_start = os::elapsedTime();
uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
@ -5448,9 +5439,10 @@ public:
void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } void do_oop(narrowOop* p) { guarantee(false, "Not needed"); }
void do_oop(oop* p) { void do_oop(oop* p) {
oop obj = *p; oop obj = *p;
assert(obj != NULL, "the caller should have filtered out NULL values");
G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj); G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj);
if (obj == NULL || cset_state == G1CollectedHeap::InNeither) { if (cset_state == G1CollectedHeap::InNeither) {
return; return;
} }
if (cset_state == G1CollectedHeap::InCSet) { if (cset_state == G1CollectedHeap::InCSet) {
@ -6052,9 +6044,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
// RSets. // RSets.
enqueue_discovered_references(n_workers); enqueue_discovered_references(n_workers);
if (G1DeferredRSUpdate) { redirty_logged_cards();
redirty_logged_cards();
}
COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
} }
@ -6062,7 +6052,7 @@ void G1CollectedHeap::free_region(HeapRegion* hr,
FreeRegionList* free_list, FreeRegionList* free_list,
bool par, bool par,
bool locked) { bool locked) {
assert(!hr->isHumongous(), "this is only for non-humongous regions"); assert(!hr->is_free(), "the region should not be free");
assert(!hr->is_empty(), "the region should not be empty"); assert(!hr->is_empty(), "the region should not be empty");
assert(_hrm.is_available(hr->hrm_index()), "region should be committed"); assert(_hrm.is_available(hr->hrm_index()), "region should be committed");
assert(free_list != NULL, "pre-condition"); assert(free_list != NULL, "pre-condition");
@ -6092,14 +6082,14 @@ void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
// We need to read this before we make the region non-humongous, // We need to read this before we make the region non-humongous,
// otherwise the information will be gone. // otherwise the information will be gone.
uint last_index = hr->last_hc_index(); uint last_index = hr->last_hc_index();
hr->set_notHumongous(); hr->clear_humongous();
free_region(hr, free_list, par); free_region(hr, free_list, par);
uint i = hr->hrm_index() + 1; uint i = hr->hrm_index() + 1;
while (i < last_index) { while (i < last_index) {
HeapRegion* curr_hr = region_at(i); HeapRegion* curr_hr = region_at(i);
assert(curr_hr->continuesHumongous(), "invariant"); assert(curr_hr->continuesHumongous(), "invariant");
curr_hr->set_notHumongous(); curr_hr->clear_humongous();
free_region(curr_hr, free_list, par); free_region(curr_hr, free_list, par);
i += 1; i += 1;
} }
@ -6407,9 +6397,9 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& e
if (cur->is_young()) { if (cur->is_young()) {
cur->set_young_index_in_cset(-1); cur->set_young_index_in_cset(-1);
} }
cur->set_not_young();
cur->set_evacuation_failed(false); cur->set_evacuation_failed(false);
// The region is now considered to be old. // The region is now considered to be old.
cur->set_old();
_old_set.add(cur); _old_set.add(cur);
evacuation_info.increment_collectionset_used_after(cur->used()); evacuation_info.increment_collectionset_used_after(cur->used());
} }
@ -6696,16 +6686,15 @@ public:
TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { } TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { }
bool doHeapRegion(HeapRegion* r) { bool doHeapRegion(HeapRegion* r) {
if (r->is_empty()) { if (r->is_old()) {
// We ignore empty regions, we'll empty the free list afterwards
} else if (r->is_young()) {
// We ignore young regions, we'll empty the young list afterwards
} else if (r->isHumongous()) {
// We ignore humongous regions, we're not tearing down the
// humongous region set
} else {
// The rest should be old
_old_set->remove(r); _old_set->remove(r);
} else {
// We ignore free regions, we'll empty the free list afterwards.
// We ignore young regions, we'll empty the young list afterwards.
// We ignore humongous regions, we're not tearing down the
// humongous regions set.
assert(r->is_free() || r->is_young() || r->isHumongous(),
"it cannot be another type");
} }
return false; return false;
} }
@ -6755,6 +6744,7 @@ public:
if (r->is_empty()) { if (r->is_empty()) {
// Add free regions to the free list // Add free regions to the free list
r->set_free();
_hrm->insert_into_free_list(r); _hrm->insert_into_free_list(r);
} else if (!_free_list_only) { } else if (!_free_list_only) {
assert(!r->is_young(), "we should not come across young regions"); assert(!r->is_young(), "we should not come across young regions");
@ -6762,7 +6752,11 @@ public:
if (r->isHumongous()) { if (r->isHumongous()) {
// We ignore humongous regions, we left the humongous set unchanged // We ignore humongous regions, we left the humongous set unchanged
} else { } else {
// The rest should be old, add them to the old set // Objects that were compacted would have ended up on regions
// that were previously old or free.
assert(r->is_free() || r->is_old(), "invariant");
// We now consider them old, so register as such.
r->set_old();
_old_set->add(r); _old_set->add(r);
} }
_total_used += r->used(); _total_used += r->used();
@ -6829,7 +6823,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size,
void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region, void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region,
size_t allocated_bytes) { size_t allocated_bytes) {
assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
assert(alloc_region->is_young(), "all mutator alloc regions should be young"); assert(alloc_region->is_eden(), "all mutator alloc regions should be eden");
g1_policy()->add_region_to_incremental_cset_lhs(alloc_region); g1_policy()->add_region_to_incremental_cset_lhs(alloc_region);
_summary_bytes_used += allocated_bytes; _summary_bytes_used += allocated_bytes;
@ -6888,6 +6882,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size,
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor);
check_bitmaps("Survivor Region Allocation", new_alloc_region); check_bitmaps("Survivor Region Allocation", new_alloc_region);
} else { } else {
new_alloc_region->set_old();
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Old); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Old);
check_bitmaps("Old Region Allocation", new_alloc_region); check_bitmaps("Old Region Allocation", new_alloc_region);
} }
@ -6999,9 +6994,11 @@ public:
} else if (hr->is_empty()) { } else if (hr->is_empty()) {
assert(_hrm->is_free(hr), err_msg("Heap region %u is empty but not on the free list.", hr->hrm_index())); assert(_hrm->is_free(hr), err_msg("Heap region %u is empty but not on the free list.", hr->hrm_index()));
_free_count.increment(1u, hr->capacity()); _free_count.increment(1u, hr->capacity());
} else { } else if (hr->is_old()) {
assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrm_index())); assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrm_index()));
_old_count.increment(1u, hr->capacity()); _old_count.increment(1u, hr->capacity());
} else {
ShouldNotReachHere();
} }
return false; return false;
} }

View file

@ -1665,7 +1665,7 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
// Add the heap region at the head of the non-incremental collection set // Add the heap region at the head of the non-incremental collection set
void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) { void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) {
assert(_inc_cset_build_state == Active, "Precondition"); assert(_inc_cset_build_state == Active, "Precondition");
assert(!hr->is_young(), "non-incremental add of young region"); assert(hr->is_old(), "the region should be old");
assert(!hr->in_collection_set(), "should not already be in the CSet"); assert(!hr->in_collection_set(), "should not already be in the CSet");
hr->set_in_collection_set(true); hr->set_in_collection_set(true);
@ -1811,7 +1811,7 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) {
// Add the region at the RHS of the incremental cset // Add the region at the RHS of the incremental cset
void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) { void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) {
// We should only ever be appending survivors at the end of a pause // We should only ever be appending survivors at the end of a pause
assert( hr->is_survivor(), "Logic"); assert(hr->is_survivor(), "Logic");
// Do the 'common' stuff // Do the 'common' stuff
add_region_to_incremental_cset_common(hr); add_region_to_incremental_cset_common(hr);
@ -1829,7 +1829,7 @@ void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) {
// Add the region to the LHS of the incremental cset // Add the region to the LHS of the incremental cset
void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) { void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) {
// Survivors should be added to the RHS at the end of a pause // Survivors should be added to the RHS at the end of a pause
assert(!hr->is_survivor(), "Logic"); assert(hr->is_eden(), "Logic");
// Do the 'common' stuff // Do the 'common' stuff
add_region_to_incremental_cset_common(hr); add_region_to_incremental_cset_common(hr);
@ -1989,7 +1989,11 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInf
HeapRegion* hr = young_list->first_survivor_region(); HeapRegion* hr = young_list->first_survivor_region();
while (hr != NULL) { while (hr != NULL) {
assert(hr->is_survivor(), "badly formed young list"); assert(hr->is_survivor(), "badly formed young list");
hr->set_young(); // There is a convention that all the young regions in the CSet
// are tagged as "eden", so we do this for the survivors here. We
// use the special set_eden_pre_gc() as it doesn't check that the
// region is free (which is not the case here).
hr->set_eden_pre_gc();
hr = hr->get_next_young_region(); hr = hr->get_next_young_region();
} }

View file

@ -299,13 +299,13 @@ public:
// Accessors // Accessors
void set_region_eden(HeapRegion* hr, int young_index_in_cset) { void set_region_eden(HeapRegion* hr, int young_index_in_cset) {
hr->set_young(); hr->set_eden();
hr->install_surv_rate_group(_short_lived_surv_rate_group); hr->install_surv_rate_group(_short_lived_surv_rate_group);
hr->set_young_index_in_cset(young_index_in_cset); hr->set_young_index_in_cset(young_index_in_cset);
} }
void set_region_survivor(HeapRegion* hr, int young_index_in_cset) { void set_region_survivor(HeapRegion* hr, int young_index_in_cset) {
assert(hr->is_young() && hr->is_survivor(), "pre-condition"); assert(hr->is_survivor(), "pre-condition");
hr->install_surv_rate_group(_survivor_surv_rate_group); hr->install_surv_rate_group(_survivor_surv_rate_group);
hr->set_young_index_in_cset(young_index_in_cset); hr->set_young_index_in_cset(young_index_in_cset);
} }

View file

@ -176,15 +176,17 @@ public:
class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
ConcurrentMark* _cm; ConcurrentMark* _cm;
OopsInHeapRegionClosure *_update_rset_cl;
uint _worker_id; uint _worker_id;
DirtyCardQueue _dcq;
UpdateRSetDeferred _update_rset_cl;
public: public:
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
OopsInHeapRegionClosure* update_rset_cl,
uint worker_id) : uint worker_id) :
_g1h(g1h), _update_rset_cl(update_rset_cl), _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
_worker_id(worker_id), _cm(_g1h->concurrent_mark()) { } _worker_id(worker_id), _cm(_g1h->concurrent_mark()) {
}
bool doHeapRegion(HeapRegion *hr) { bool doHeapRegion(HeapRegion *hr) {
bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause(); bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
@ -195,7 +197,7 @@ public:
if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) { if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) {
if (hr->evacuation_failed()) { if (hr->evacuation_failed()) {
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, _update_rset_cl, RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
during_initial_mark, during_initial_mark,
during_conc_mark, during_conc_mark,
_worker_id); _worker_id);
@ -214,7 +216,7 @@ public:
// whenever this might be required in the future. // whenever this might be required in the future.
hr->rem_set()->reset_for_par_iteration(); hr->rem_set()->reset_for_par_iteration();
hr->reset_bot(); hr->reset_bot();
_update_rset_cl->set_region(hr); _update_rset_cl.set_region(hr);
hr->object_iterate(&rspc); hr->object_iterate(&rspc);
hr->rem_set()->clean_strong_code_roots(hr); hr->rem_set()->clean_strong_code_roots(hr);
@ -238,16 +240,7 @@ public:
_g1h(g1h) { } _g1h(g1h) { }
void work(uint worker_id) { void work(uint worker_id) {
UpdateRSetImmediate immediate_update(_g1h->g1_rem_set()); RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id);
DirtyCardQueue dcq(&_g1h->dirty_card_queue_set());
UpdateRSetDeferred deferred_update(_g1h, &dcq);
OopsInHeapRegionClosure *update_rset_cl = &deferred_update;
if (!G1DeferredRSUpdate) {
update_rset_cl = &immediate_update;
}
RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, update_rset_cl, worker_id);
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
_g1h->collection_set_iterate_from(hr, &rsfp_cl); _g1h->collection_set_iterate_from(hr, &rsfp_cl);

View file

@ -237,10 +237,8 @@ void G1GCPhaseTimes::note_gc_end() {
_last_gc_worker_times_ms.verify(); _last_gc_worker_times_ms.verify();
_last_gc_worker_other_times_ms.verify(); _last_gc_worker_other_times_ms.verify();
if (G1DeferredRSUpdate) { _last_redirty_logged_cards_time_ms.verify();
_last_redirty_logged_cards_time_ms.verify(); _last_redirty_logged_cards_processed_cards.verify();
_last_redirty_logged_cards_processed_cards.verify();
}
} }
void G1GCPhaseTimes::note_string_dedup_fixup_start() { void G1GCPhaseTimes::note_string_dedup_fixup_start() {
@ -352,12 +350,10 @@ void G1GCPhaseTimes::print(double pause_time_sec) {
_recorded_non_young_cset_choice_time_ms)); _recorded_non_young_cset_choice_time_ms));
print_stats(2, "Ref Proc", _cur_ref_proc_time_ms); print_stats(2, "Ref Proc", _cur_ref_proc_time_ms);
print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
if (G1DeferredRSUpdate) { print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms); if (G1Log::finest()) {
if (G1Log::finest()) { _last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
_last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty"); _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
_last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
}
} }
if (G1ReclaimDeadHumongousObjectsAtYoungGC) { if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);

View file

@ -27,7 +27,6 @@
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1HotCardCache.hpp" #include "gc_implementation/g1/g1HotCardCache.hpp"
#include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/heapRegion.hpp"
#include "runtime/atomic.inline.hpp" #include "runtime/atomic.inline.hpp"
G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h): G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
@ -136,7 +135,6 @@ void G1HotCardCache::drain(uint worker_i,
} }
void G1HotCardCache::reset_card_counts(HeapRegion* hr) { void G1HotCardCache::reset_card_counts(HeapRegion* hr) {
assert(!hr->isHumongous(), "Should have been cleared");
_card_counts.clear_region(hr); _card_counts.clear_region(hr);
} }

View file

@ -84,20 +84,6 @@ class G1ParScanThreadState : public StackObj {
DirtyCardQueue& dirty_card_queue() { return _dcq; } DirtyCardQueue& dirty_card_queue() { return _dcq; }
G1SATBCardTableModRefBS* ctbs() { return _ct_bs; } G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
template <class T> inline void immediate_rs_update(HeapRegion* from, T* p, int tid);
template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
// If the new value of the field points to the same region or
// is the to-space, we don't need to include it in the Rset updates.
if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
size_t card_index = ctbs()->index_for(p);
// If the card hasn't been added to the buffer, do it.
if (ctbs()->mark_card_deferred(card_index)) {
dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
}
}
}
public: public:
G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
~G1ParScanThreadState(); ~G1ParScanThreadState();
@ -124,8 +110,17 @@ class G1ParScanThreadState : public StackObj {
_refs->push(ref); _refs->push(ref);
} }
template <class T> inline void update_rs(HeapRegion* from, T* p, int tid); template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
// If the new value of the field points to the same region or
// is the to-space, we don't need to include it in the Rset updates.
if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
size_t card_index = ctbs()->index_for(p);
// If the card hasn't been added to the buffer, do it.
if (ctbs()->mark_card_deferred(card_index)) {
dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
}
}
}
private: private:
inline HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz); inline HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz);

View file

@ -29,20 +29,6 @@
#include "gc_implementation/g1/g1RemSet.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
if (!from->is_survivor()) {
_g1_rem->par_write_ref(from, p, tid);
}
}
template <class T> void G1ParScanThreadState::update_rs(HeapRegion* from, T* p, int tid) {
if (G1DeferredRSUpdate) {
deferred_rs_update(from, p, tid);
} else {
immediate_rs_update(from, p, tid);
}
}
template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) { template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) {
assert(!oopDesc::is_null(oopDesc::load_decode_heap_oop(p)), assert(!oopDesc::is_null(oopDesc::load_decode_heap_oop(p)),
"Reference should not be NULL here as such are never pushed to the task queue."); "Reference should not be NULL here as such are never pushed to the task queue.");

View file

@ -339,12 +339,8 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
// are just discarded (there's no need to update the RSets of regions // are just discarded (there's no need to update the RSets of regions
// that were in the collection set - after the pause these regions // that were in the collection set - after the pause these regions
// are wholly 'free' of live objects. In the event of an evacuation // are wholly 'free' of live objects. In the event of an evacuation
// failure the cards/buffers in this queue set are: // failure the cards/buffers in this queue set are passed to the
// * passed to the DirtyCardQueueSet that is used to manage deferred // DirtyCardQueueSet that is used to manage RSet updates
// RSet updates, or
// * scanned for references that point into the collection set
// and the RSet of the corresponding region in the collection set
// is updated immediately.
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
assert((ParallelGCThreads > 0) || worker_i == 0, "invariant"); assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
@ -358,7 +354,6 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
void G1RemSet::prepare_for_oops_into_collection_set_do() { void G1RemSet::prepare_for_oops_into_collection_set_do() {
cleanupHRRS(); cleanupHRRS();
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
_g1->set_refine_cte_cl_concurrency(false); _g1->set_refine_cte_cl_concurrency(false);
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
dcqs.concatenate_logs(); dcqs.concatenate_logs();
@ -371,66 +366,6 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() {
_total_cards_scanned = 0; _total_cards_scanned = 0;
} }
// This closure, applied to a DirtyCardQueueSet, is used to immediately
// update the RSets for the regions in the CSet. For each card it iterates
// through the oops which coincide with that card. It scans the reference
// fields in each oop; when it finds an oop that points into the collection
// set, the RSet for the region containing the referenced object is updated.
class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure {
G1CollectedHeap* _g1;
CardTableModRefBS* _ct_bs;
public:
UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
CardTableModRefBS* bs):
_g1(g1), _ct_bs(bs)
{ }
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
// Construct the region representing the card.
HeapWord* start = _ct_bs->addr_for(card_ptr);
// And find the region containing it.
HeapRegion* r = _g1->heap_region_containing(start);
// Scan oops in the card looking for references into the collection set
// Don't use addr_for(card_ptr + 1) which can ask for
// a card beyond the heap. This is not safe without a perm
// gen.
HeapWord* end = start + CardTableModRefBS::card_size_in_words;
MemRegion scanRegion(start, end);
UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
// We can pass false as the "filter_young" parameter here as:
// * we should be in a STW pause,
// * the DCQS to which this closure is applied is used to hold
// references that point into the collection set from the prior
// RSet updating,
// * the post-write barrier shouldn't be logging updates to young
// regions (but there is a situation where this can happen - see
// the comment in G1RemSet::refine_card() below -
// that should not be applicable here), and
// * during actual RSet updating, the filtering of cards in young
// regions in HeapRegion::oops_on_card_seq_iterate_careful is
// employed.
// As a result, when this closure is applied to "refs into cset"
// DCQS, we shouldn't see any cards in young regions.
update_rs_cl.set_region(r);
HeapWord* stop_point =
r->oops_on_card_seq_iterate_careful(scanRegion,
&filter_then_update_rs_cset_oop_cl,
false /* filter_young */,
NULL /* card_ptr */);
// Since this is performed in the event of an evacuation failure, we
// we shouldn't see a non-null stop point
assert(stop_point == NULL, "saw an unallocated region");
return true;
}
};
void G1RemSet::cleanup_after_oops_into_collection_set_do() { void G1RemSet::cleanup_after_oops_into_collection_set_do() {
guarantee( _cards_scanned != NULL, "invariant" ); guarantee( _cards_scanned != NULL, "invariant" );
_total_cards_scanned = 0; _total_cards_scanned = 0;
@ -451,25 +386,10 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() {
double restore_remembered_set_start = os::elapsedTime(); double restore_remembered_set_start = os::elapsedTime();
// Restore remembered sets for the regions pointing into the collection set. // Restore remembered sets for the regions pointing into the collection set.
if (G1DeferredRSUpdate) { // We just need to transfer the completed buffers from the DirtyCardQueueSet
// If deferred RS updates are enabled then we just need to transfer // used to hold cards that contain references that point into the collection set
// the completed buffers from (a) the DirtyCardQueueSet used to hold // to the DCQS used to hold the deferred RS updates.
// cards that contain references that point into the collection set _g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
// to (b) the DCQS used to hold the deferred RS updates
_g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
} else {
CardTableModRefBS* bs = (CardTableModRefBS*)_g1->barrier_set();
UpdateRSetCardTableEntryIntoCSetClosure update_rs_cset_immediate(_g1, bs);
int n_completed_buffers = 0;
while (into_cset_dcqs.apply_closure_to_completed_buffer(&update_rs_cset_immediate,
0, 0, true)) {
n_completed_buffers++;
}
assert(n_completed_buffers == into_cset_n_buffers, "missed some buffers");
}
_g1->g1_policy()->phase_times()->record_evac_fail_restore_remsets((os::elapsedTime() - restore_remembered_set_start) * 1000.0); _g1->g1_policy()->phase_times()->record_evac_fail_restore_remsets((os::elapsedTime() - restore_remembered_set_start) * 1000.0);
} }

View file

@ -193,18 +193,4 @@ public:
bool apply_to_weak_ref_discovered_field() { return true; } bool apply_to_weak_ref_discovered_field() { return true; }
}; };
class UpdateRSetImmediate: public OopsInHeapRegionClosure {
private:
G1RemSet* _g1_rem_set;
template <class T> void do_oop_work(T* p);
public:
UpdateRSetImmediate(G1RemSet* rs) :
_g1_rem_set(rs) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP

View file

@ -79,13 +79,4 @@ inline void UpdateRSOopClosure::do_oop_work(T* p) {
_rs->par_write_ref(_from, p, _worker_i); _rs->par_write_ref(_from, p, _worker_i);
} }
template <class T>
inline void UpdateRSetImmediate::do_oop_work(T* p) {
assert(_from->is_in_reserved(p), "paranoia");
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
_g1_rem_set->par_write_ref(_from, p, 0);
}
}
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP

View file

@ -259,14 +259,16 @@ public:
size_t code_root_elems = hrrs->strong_code_roots_list_length(); size_t code_root_elems = hrrs->strong_code_roots_list_length();
RegionTypeCounter* current = NULL; RegionTypeCounter* current = NULL;
if (r->is_young()) { if (r->is_free()) {
current = &_free;
} else if (r->is_young()) {
current = &_young; current = &_young;
} else if (r->isHumongous()) { } else if (r->isHumongous()) {
current = &_humonguous; current = &_humonguous;
} else if (r->is_empty()) { } else if (r->is_old()) {
current = &_free;
} else {
current = &_old; current = &_old;
} else {
ShouldNotReachHere();
} }
current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
_all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);

View file

@ -31,8 +31,6 @@
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
class DirtyCardQueueSet; class DirtyCardQueueSet;
class G1SATBCardTableLoggingModRefBS; class G1SATBCardTableLoggingModRefBS;
@ -180,7 +178,4 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS {
void write_ref_array_work(MemRegion mr) { invalidate(mr); } void write_ref_array_work(MemRegion mr) { invalidate(mr); }
}; };
#endif // INCLUDE_ALL_GCS
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP

View file

@ -108,9 +108,6 @@
develop(bool, G1RSBarrierRegionFilter, true, \ develop(bool, G1RSBarrierRegionFilter, true, \
"If true, generate region filtering code in RS barrier") \ "If true, generate region filtering code in RS barrier") \
\ \
develop(bool, G1DeferredRSUpdate, true, \
"If true, use deferred RS updates") \
\
develop(bool, G1RSLogCheckCardTable, false, \ develop(bool, G1RSLogCheckCardTable, false, \
"If true, verify that no dirty cards remain after RS log " \ "If true, verify that no dirty cards remain after RS log " \
"processing.") \ "processing.") \

View file

@ -211,8 +211,6 @@ void HeapRegion::reset_after_compaction() {
} }
void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) {
assert(_humongous_type == NotHumongous,
"we should have already filtered out humongous regions");
assert(_humongous_start_region == NULL, assert(_humongous_start_region == NULL,
"we should have already filtered out humongous regions"); "we should have already filtered out humongous regions");
assert(_end == _orig_end, assert(_end == _orig_end,
@ -222,7 +220,7 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) {
set_young_index_in_cset(-1); set_young_index_in_cset(-1);
uninstall_surv_rate_group(); uninstall_surv_rate_group();
set_young_type(NotYoung); set_free();
reset_pre_dummy_top(); reset_pre_dummy_top();
if (!par) { if (!par) {
@ -273,7 +271,7 @@ void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
assert(top() == bottom(), "should be empty"); assert(top() == bottom(), "should be empty");
assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
_humongous_type = StartsHumongous; _type.set_starts_humongous();
_humongous_start_region = this; _humongous_start_region = this;
set_end(new_end); set_end(new_end);
@ -287,11 +285,11 @@ void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
assert(top() == bottom(), "should be empty"); assert(top() == bottom(), "should be empty");
assert(first_hr->startsHumongous(), "pre-condition"); assert(first_hr->startsHumongous(), "pre-condition");
_humongous_type = ContinuesHumongous; _type.set_continues_humongous();
_humongous_start_region = first_hr; _humongous_start_region = first_hr;
} }
void HeapRegion::set_notHumongous() { void HeapRegion::clear_humongous() {
assert(isHumongous(), "pre-condition"); assert(isHumongous(), "pre-condition");
if (startsHumongous()) { if (startsHumongous()) {
@ -307,7 +305,6 @@ void HeapRegion::set_notHumongous() {
} }
assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); assert(capacity() == HeapRegion::GrainBytes, "pre-condition");
_humongous_type = NotHumongous;
_humongous_start_region = NULL; _humongous_start_region = NULL;
} }
@ -327,12 +324,12 @@ HeapRegion::HeapRegion(uint hrm_index,
MemRegion mr) : MemRegion mr) :
G1OffsetTableContigSpace(sharedOffsetArray, mr), G1OffsetTableContigSpace(sharedOffsetArray, mr),
_hrm_index(hrm_index), _hrm_index(hrm_index),
_humongous_type(NotHumongous), _humongous_start_region(NULL), _humongous_start_region(NULL),
_in_collection_set(false), _in_collection_set(false),
_next_in_special_set(NULL), _orig_end(NULL), _next_in_special_set(NULL), _orig_end(NULL),
_claimed(InitialClaimValue), _evacuation_failed(false), _claimed(InitialClaimValue), _evacuation_failed(false),
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
_young_type(NotYoung), _next_young_region(NULL), _next_young_region(NULL),
_next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
#ifdef ASSERT #ifdef ASSERT
_containing_set(NULL), _containing_set(NULL),
@ -686,26 +683,11 @@ void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const
void HeapRegion::print() const { print_on(gclog_or_tty); } void HeapRegion::print() const { print_on(gclog_or_tty); }
void HeapRegion::print_on(outputStream* st) const { void HeapRegion::print_on(outputStream* st) const {
if (isHumongous()) { st->print(" %2s", get_short_type_str());
if (startsHumongous())
st->print(" HS");
else
st->print(" HC");
} else {
st->print(" ");
}
if (in_collection_set()) if (in_collection_set())
st->print(" CS"); st->print(" CS");
else else
st->print(" "); st->print(" ");
if (is_young())
st->print(is_survivor() ? " SU" : " Y ");
else
st->print(" ");
if (is_empty())
st->print(" F");
else
st->print(" ");
st->print(" TS %5d", _gc_time_stamp); st->print(" TS %5d", _gc_time_stamp);
st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT, st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT,
prev_top_at_mark_start(), next_top_at_mark_start()); prev_top_at_mark_start(), next_top_at_mark_start());

View file

@ -27,6 +27,7 @@
#include "gc_implementation/g1/g1BlockOffsetTable.hpp" #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
#include "gc_implementation/g1/g1_specialized_oop_closures.hpp" #include "gc_implementation/g1/g1_specialized_oop_closures.hpp"
#include "gc_implementation/g1/heapRegionType.hpp"
#include "gc_implementation/g1/survRateGroup.hpp" #include "gc_implementation/g1/survRateGroup.hpp"
#include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/ageTable.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/shared/spaceDecorator.hpp"
@ -34,8 +35,6 @@
#include "memory/watermark.hpp" #include "memory/watermark.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
// A HeapRegion is the smallest piece of a G1CollectedHeap that // A HeapRegion is the smallest piece of a G1CollectedHeap that
// can be collected independently. // can be collected independently.
@ -55,10 +54,7 @@ class nmethod;
#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" #define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
#define HR_FORMAT_PARAMS(_hr_) \ #define HR_FORMAT_PARAMS(_hr_) \
(_hr_)->hrm_index(), \ (_hr_)->hrm_index(), \
(_hr_)->is_survivor() ? "S" : (_hr_)->is_young() ? "E" : \ (_hr_)->get_short_type_str(), \
(_hr_)->startsHumongous() ? "HS" : \
(_hr_)->continuesHumongous() ? "HC" : \
!(_hr_)->is_empty() ? "O" : "F", \
p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end()) p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end())
// sentinel value for hrm_index // sentinel value for hrm_index
@ -215,12 +211,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
friend class VMStructs; friend class VMStructs;
private: private:
enum HumongousType {
NotHumongous = 0,
StartsHumongous,
ContinuesHumongous
};
// The remembered set for this region. // The remembered set for this region.
// (Might want to make this "inline" later, to avoid some alloc failure // (Might want to make this "inline" later, to avoid some alloc failure
// issues.) // issues.)
@ -232,7 +222,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
// The index of this region in the heap region sequence. // The index of this region in the heap region sequence.
uint _hrm_index; uint _hrm_index;
HumongousType _humongous_type; HeapRegionType _type;
// For a humongous region, region in which it starts. // For a humongous region, region in which it starts.
HeapRegion* _humongous_start_region; HeapRegion* _humongous_start_region;
// For the start region of a humongous sequence, it's original end(). // For the start region of a humongous sequence, it's original end().
@ -274,13 +265,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
// The calculated GC efficiency of the region. // The calculated GC efficiency of the region.
double _gc_efficiency; double _gc_efficiency;
enum YoungType {
NotYoung, // a region is not young
Young, // a region is young
Survivor // a region is young and it contains survivors
};
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;
@ -305,12 +289,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
_next_top_at_mark_start = bot; _next_top_at_mark_start = bot;
} }
void set_young_type(YoungType new_type) {
//assert(_young_type != new_type, "setting the same type" );
// TODO: add more assertions here
_young_type = new_type;
}
// Cached attributes used in the collection set policy information // Cached attributes used in the collection set policy information
// The RSet length that was added to the total value // The RSet length that was added to the total value
@ -430,9 +408,21 @@ class HeapRegion: public G1OffsetTableContigSpace {
_prev_marked_bytes = _next_marked_bytes = 0; _prev_marked_bytes = _next_marked_bytes = 0;
} }
bool isHumongous() const { return _humongous_type != NotHumongous; } const char* get_type_str() const { return _type.get_str(); }
bool startsHumongous() const { return _humongous_type == StartsHumongous; } const char* get_short_type_str() const { return _type.get_short_str(); }
bool continuesHumongous() const { return _humongous_type == ContinuesHumongous; }
bool is_free() const { return _type.is_free(); }
bool is_young() const { return _type.is_young(); }
bool is_eden() const { return _type.is_eden(); }
bool is_survivor() const { return _type.is_survivor(); }
bool isHumongous() const { return _type.is_humongous(); }
bool startsHumongous() const { return _type.is_starts_humongous(); }
bool continuesHumongous() const { return _type.is_continues_humongous(); }
bool is_old() const { return _type.is_old(); }
// For a humongous region, region in which it starts. // For a humongous region, region in which it starts.
HeapRegion* humongous_start_region() const { HeapRegion* humongous_start_region() const {
return _humongous_start_region; return _humongous_start_region;
@ -496,7 +486,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
void set_continuesHumongous(HeapRegion* first_hr); void set_continuesHumongous(HeapRegion* first_hr);
// Unsets the humongous-related fields on the region. // Unsets the humongous-related fields on the region.
void set_notHumongous(); void clear_humongous();
// If the region has a remembered set, return a pointer to it. // If the region has a remembered set, return a pointer to it.
HeapRegionRemSet* rem_set() const { HeapRegionRemSet* rem_set() const {
@ -623,9 +613,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
void calc_gc_efficiency(void); void calc_gc_efficiency(void);
double gc_efficiency() { return _gc_efficiency;} double gc_efficiency() { return _gc_efficiency;}
bool is_young() const { return _young_type != NotYoung; }
bool is_survivor() const { return _young_type == Survivor; }
int young_index_in_cset() const { return _young_index_in_cset; } int young_index_in_cset() const { return _young_index_in_cset; }
void set_young_index_in_cset(int index) { void set_young_index_in_cset(int index) {
assert( (index == -1) || is_young(), "pre-condition" ); assert( (index == -1) || is_young(), "pre-condition" );
@ -677,11 +664,13 @@ class HeapRegion: public G1OffsetTableContigSpace {
} }
} }
void set_young() { set_young_type(Young); } void set_free() { _type.set_free(); }
void set_survivor() { set_young_type(Survivor); } void set_eden() { _type.set_eden(); }
void set_eden_pre_gc() { _type.set_eden_pre_gc(); }
void set_survivor() { _type.set_survivor(); }
void set_not_young() { set_young_type(NotYoung); } void set_old() { _type.set_old(); }
// Determine if an object has been allocated since the last // Determine if an object has been allocated since the last
// mark performed by the collector. This returns true iff the object // mark performed by the collector. This returns true iff the object
@ -809,6 +798,4 @@ class HeapRegionClosure : public StackObj {
bool complete() { return _complete; } bool complete() { return _complete; }
}; };
#endif // INCLUDE_ALL_GCS
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP

View file

@ -42,7 +42,9 @@ void HeapRegionSetBase::verify_region(HeapRegion* hr) {
assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrm_index())); assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrm_index()));
assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrm_index())); // currently we don't use these sets for young regions assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrm_index())); // currently we don't use these sets for young regions
assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrm_index(), name())); assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrm_index(), name()));
assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrm_index(), name())); assert(hr->is_free() == regions_free(), err_msg("Wrong free state for region %u and set %s", hr->hrm_index(), name()));
assert(!hr->is_free() || hr->is_empty(), err_msg("Free region %u is not empty for set %s", hr->hrm_index(), name()));
assert(!hr->is_empty() || hr->is_free(), err_msg("Empty region %u is not free for set %s", hr->hrm_index(), name()));
assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index())); assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index()));
} }
#endif #endif
@ -85,16 +87,16 @@ void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
out->print_cr(" Region Assumptions"); out->print_cr(" Region Assumptions");
out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); out->print_cr(" free : %s", BOOL_TO_STR(regions_free()));
out->print_cr(" Attributes"); out->print_cr(" Attributes");
out->print_cr(" length : %14u", length()); out->print_cr(" length : %14u", length());
out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
total_capacity_bytes()); total_capacity_bytes());
} }
HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker) HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker)
: _name(name), _verify_in_progress(false), : _name(name), _verify_in_progress(false),
_is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker), _is_humongous(humongous), _is_free(free), _mt_safety_checker(mt_safety_checker),
_count() _count()
{ } { }

View file

@ -81,7 +81,7 @@ class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
friend class VMStructs; friend class VMStructs;
private: private:
bool _is_humongous; bool _is_humongous;
bool _is_empty; bool _is_free;
HRSMtSafeChecker* _mt_safety_checker; HRSMtSafeChecker* _mt_safety_checker;
protected: protected:
@ -102,9 +102,9 @@ protected:
// not. Only used during verification. // not. Only used during verification.
bool regions_humongous() { return _is_humongous; } bool regions_humongous() { return _is_humongous; }
// Indicates whether all regions in the set should be empty or // Indicates whether all regions in the set should be free or
// not. Only used during verification. // not. Only used during verification.
bool regions_empty() { return _is_empty; } bool regions_free() { return _is_free; }
void check_mt_safety() { void check_mt_safety() {
if (_mt_safety_checker != NULL) { if (_mt_safety_checker != NULL) {
@ -114,7 +114,7 @@ protected:
virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { }
HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker); HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker);
public: public:
const char* name() { return _name; } const char* name() { return _name; }
@ -171,7 +171,7 @@ public:
do { \ do { \
assert(((_set1_)->regions_humongous() == \ assert(((_set1_)->regions_humongous() == \
(_set2_)->regions_humongous()) && \ (_set2_)->regions_humongous()) && \
((_set1_)->regions_empty() == (_set2_)->regions_empty()), \ ((_set1_)->regions_free() == (_set2_)->regions_free()), \
hrs_err_msg("the contents of set %s and set %s should match", \ hrs_err_msg("the contents of set %s and set %s should match", \
(_set1_)->name(), (_set2_)->name())); \ (_set1_)->name(), (_set2_)->name())); \
} while (0) } while (0)
@ -184,7 +184,7 @@ public:
class HeapRegionSet : public HeapRegionSetBase { class HeapRegionSet : public HeapRegionSetBase {
public: public:
HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker): HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
HeapRegionSetBase(name, humongous, false /* empty */, mt_safety_checker) { } HeapRegionSetBase(name, humongous, false /* free */, mt_safety_checker) { }
void bulk_remove(const HeapRegionSetCount& removed) { void bulk_remove(const HeapRegionSetCount& removed) {
_count.decrement(removed.length(), removed.capacity()); _count.decrement(removed.length(), removed.capacity());

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/heapRegionType.hpp"
bool HeapRegionType::is_valid(Tag tag) {
switch (tag) {
case FreeTag:
case EdenTag:
case SurvTag:
case HumStartsTag:
case HumContTag:
case OldTag:
return true;
}
return false;
}
const char* HeapRegionType::get_str() const {
hrt_assert_is_valid(_tag);
switch (_tag) {
case FreeTag: return "FREE";
case EdenTag: return "EDEN";
case SurvTag: return "SURV";
case HumStartsTag: return "HUMS";
case HumContTag: return "HUMC";
case OldTag: return "OLD";
}
ShouldNotReachHere();
// keep some compilers happy
return NULL;
}
const char* HeapRegionType::get_short_str() const {
hrt_assert_is_valid(_tag);
switch (_tag) {
case FreeTag: return "F";
case EdenTag: return "E";
case SurvTag: return "S";
case HumStartsTag: return "HS";
case HumContTag: return "HC";
case OldTag: return "O";
}
ShouldNotReachHere();
// keep some compilers happy
return NULL;
}

View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP
#include "memory/allocation.hpp"
#define hrt_assert_is_valid(tag) \
assert(is_valid((tag)), err_msg("invalid HR type: %u", (uint) (tag)))
class HeapRegionType VALUE_OBJ_CLASS_SPEC {
private:
// We encode the value of the heap region type so the generation can be
// determined quickly. The tag is split into two parts:
//
// major type (young, humongous) : top N-1 bits
// minor type (eden / survivor, starts / cont hum, etc.) : bottom 1 bit
//
// If there's need to increase the number of minor types in the
// future, we'll have to increase the size of the latter and hence
// decrease the size of the former.
//
// 0000 0 [ 0] Free
//
// 0001 0 Young Mask
// 0001 0 [ 2] Eden
// 0001 1 [ 3] Survivor
//
// 0010 0 Humongous Mask
// 0010 0 [ 4] Humongous Starts
// 0010 1 [ 5] Humongous Continues
//
// 01000 [ 8] Old
typedef enum {
FreeTag = 0,
YoungMask = 2,
EdenTag = YoungMask,
SurvTag = YoungMask + 1,
HumMask = 4,
HumStartsTag = HumMask,
HumContTag = HumMask + 1,
OldTag = 8
} Tag;
volatile Tag _tag;
static bool is_valid(Tag tag);
Tag get() const {
hrt_assert_is_valid(_tag);
return _tag;
}
// Sets the type to 'tag'.
void set(Tag tag) {
hrt_assert_is_valid(tag);
hrt_assert_is_valid(_tag);
_tag = tag;
}
// Sets the type to 'tag', expecting the type to be 'before'. This
// is available for when we want to add sanity checking to the type
// transition.
void set_from(Tag tag, Tag before) {
hrt_assert_is_valid(tag);
hrt_assert_is_valid(before);
hrt_assert_is_valid(_tag);
assert(_tag == before,
err_msg("HR tag: %u, expected: %u new tag; %u", _tag, before, tag));
_tag = tag;
}
public:
// Queries
bool is_free() const { return get() == FreeTag; }
bool is_young() const { return (get() & YoungMask) != 0; }
bool is_eden() const { return get() == EdenTag; }
bool is_survivor() const { return get() == SurvTag; }
bool is_humongous() const { return (get() & HumMask) != 0; }
bool is_starts_humongous() const { return get() == HumStartsTag; }
bool is_continues_humongous() const { return get() == HumContTag; }
bool is_old() const { return get() == OldTag; }
// Setters
void set_free() { set(FreeTag); }
void set_eden() { set_from(EdenTag, FreeTag); }
void set_eden_pre_gc() { set_from(EdenTag, SurvTag); }
void set_survivor() { set_from(SurvTag, FreeTag); }
void set_starts_humongous() { set_from(HumStartsTag, FreeTag); }
void set_continues_humongous() { set_from(HumContTag, FreeTag); }
void set_old() { set(OldTag); }
// Misc
const char* get_str() const;
const char* get_short_str() const;
HeapRegionType() : _tag(FreeTag) { hrt_assert_is_valid(_tag); }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP

View file

@ -66,9 +66,10 @@ void GenerationSizer::initialize_flags() {
void GenerationSizer::initialize_size_info() { void GenerationSizer::initialize_size_info() {
trace_gen_sizes("ps heap raw"); trace_gen_sizes("ps heap raw");
const size_t page_sz = os::page_size_for_region(_min_heap_byte_size, const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
_max_heap_byte_size, const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
8); const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages);
const size_t page_sz = MIN2(max_page_sz, min_page_sz);
// Can a page size be something else than a power of two? // Can a page size be something else than a power of two?
assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2"); assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");

View file

@ -41,7 +41,7 @@ ParMarkBitMap::initialize(MemRegion covered_region)
const size_t words = bits / BitsPerWord; const size_t words = bits / BitsPerWord;
const size_t raw_bytes = words * sizeof(idx_t); const size_t raw_bytes = words * sizeof(idx_t);
const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10); const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity(); const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));

View file

@ -403,7 +403,7 @@ PSVirtualSpace*
ParallelCompactData::create_vspace(size_t count, size_t element_size) ParallelCompactData::create_vspace(size_t count, size_t element_size)
{ {
const size_t raw_bytes = count * element_size; const size_t raw_bytes = count * element_size;
const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10); const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity(); const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));

View file

@ -330,7 +330,7 @@
if (do_OSR) { \ if (do_OSR) { \
nmethod* osr_nmethod; \ nmethod* osr_nmethod; \
OSR_REQUEST(osr_nmethod, branch_pc); \ OSR_REQUEST(osr_nmethod, branch_pc); \
if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \ if (osr_nmethod != NULL && osr_nmethod->is_in_use()) { \
intptr_t* buf; \ intptr_t* buf; \
/* Call OSR migration with last java frame only, no checks. */ \ /* Call OSR migration with last java frame only, no checks. */ \
CALL_VM_NAKED_LJF(buf=SharedRuntime::OSR_migration_begin(THREAD)); \ CALL_VM_NAKED_LJF(buf=SharedRuntime::OSR_migration_begin(THREAD)); \

View file

@ -98,9 +98,13 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size,
_log2_segment_size = exact_log2(segment_size); _log2_segment_size = exact_log2(segment_size);
// Reserve and initialize space for _memory. // Reserve and initialize space for _memory.
const size_t page_size = os::can_execute_large_page_memory() ? size_t page_size = os::vm_page_size();
os::page_size_for_region(committed_size, reserved_size, 8) : if (os::can_execute_large_page_memory()) {
os::vm_page_size(); const size_t min_pages = 8;
page_size = MIN2(os::page_size_for_region(committed_size, min_pages),
os::page_size_for_region(reserved_size, min_pages));
}
const size_t granularity = os::vm_allocation_granularity(); const size_t granularity = os::vm_allocation_granularity();
const size_t r_align = MAX2(page_size, granularity); const size_t r_align = MAX2(page_size, granularity);
const size_t r_size = align_size_up(reserved_size, r_align); const size_t r_size = align_size_up(reserved_size, r_align);

View file

@ -3848,6 +3848,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
unit_test_function_call unit_test_function_call
// Forward declaration // Forward declaration
void TestOS_test();
void TestReservedSpace_test(); void TestReservedSpace_test();
void TestReserveMemorySpecial_test(); void TestReserveMemorySpecial_test();
void TestVirtualSpace_test(); void TestVirtualSpace_test();
@ -3871,6 +3872,7 @@ void FreeRegionList_test();
void execute_internal_vm_tests() { void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) { if (ExecuteInternalVMTests) {
tty->print_cr("Running internal VM tests"); tty->print_cr("Running internal VM tests");
run_unit_test(TestOS_test());
run_unit_test(TestReservedSpace_test()); run_unit_test(TestReservedSpace_test());
run_unit_test(TestReserveMemorySpecial_test()); run_unit_test(TestReserveMemorySpecial_test());
run_unit_test(TestVirtualSpace_test()); run_unit_test(TestVirtualSpace_test());

View file

@ -1406,24 +1406,15 @@ bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) {
return (sp > (stack_limit + reserved_area)); return (sp > (stack_limit + reserved_area));
} }
size_t os::page_size_for_region(size_t region_min_size, size_t region_max_size, size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
uint min_pages)
{
assert(min_pages > 0, "sanity"); assert(min_pages > 0, "sanity");
if (UseLargePages) { if (UseLargePages) {
const size_t max_page_size = region_max_size / min_pages; const size_t max_page_size = region_size / min_pages;
for (unsigned int i = 0; _page_sizes[i] != 0; ++i) { for (size_t i = 0; _page_sizes[i] != 0; ++i) {
const size_t sz = _page_sizes[i]; const size_t page_size = _page_sizes[i];
const size_t mask = sz - 1; if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0) { return page_size;
// The largest page size with no fragmentation.
return sz;
}
if (sz <= max_page_size) {
// The largest page size that satisfies the min_pages requirement.
return sz;
} }
} }
} }
@ -1660,3 +1651,63 @@ os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::Stat
return result; return result;
} }
#endif #endif
/////////////// Unit tests ///////////////
#ifndef PRODUCT
#define assert_eq(a,b) assert(a == b, err_msg(SIZE_FORMAT " != " SIZE_FORMAT, a, b))
class TestOS : AllStatic {
static size_t small_page_size() {
return os::vm_page_size();
}
static size_t large_page_size() {
const size_t large_page_size_example = 4 * M;
return os::page_size_for_region(large_page_size_example, 1);
}
static void test_page_size_for_region() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
size_t num_small_pages_in_large = large_page / small_page;
size_t page = os::page_size_for_region(large_page, num_small_pages_in_large);
assert_eq(page, small_page);
}
}
}
static void test_page_size_for_region_alignment() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
const size_t unaligned_region = large_page + 17;
size_t page = os::page_size_for_region(unaligned_region, 1);
assert_eq(page, small_page);
const size_t num_pages = 5;
const size_t aligned_region = large_page * num_pages;
page = os::page_size_for_region(aligned_region, num_pages);
assert_eq(page, large_page);
}
}
}
public:
static void run_tests() {
test_page_size_for_region();
test_page_size_for_region_alignment();
}
};
void TestOS_test() {
TestOS::run_tests();
}
#endif // PRODUCT

View file

@ -266,19 +266,11 @@ class os: AllStatic {
// Return the default page size. // Return the default page size.
static int vm_page_size(); static int vm_page_size();
// Return the page size to use for a region of memory. The min_pages argument // Returns the page size to use for a region of memory.
// is a hint intended to limit fragmentation; it says the returned page size // region_size / min_pages will always be greater than or equal to the
// should be <= region_max_size / min_pages. Because min_pages is a hint, // returned value.
// this routine may return a size larger than region_max_size / min_pages. static size_t page_size_for_region(size_t region_size, size_t min_pages);
//
// The current implementation ignores min_pages if a larger page size is an
// exact multiple of both region_min_size and region_max_size. This allows
// larger pages to be used when doing so would not cause fragmentation; in
// particular, a single page can be used when region_min_size ==
// region_max_size == a supported page size.
static size_t page_size_for_region(size_t region_min_size,
size_t region_max_size,
uint min_pages);
// Return the largest page size that can be used // Return the largest page size that can be used
static size_t max_page_size() { static size_t max_page_size() {
// The _page_sizes array is sorted in descending order. // The _page_sizes array is sorted in descending order.

View file

@ -38,7 +38,7 @@ ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
} }
ReservedSpace::ReservedSpace(size_t size) { ReservedSpace::ReservedSpace(size_t size) {
size_t page_size = os::page_size_for_region(size, size, 1); size_t page_size = os::page_size_for_region(size, 1);
bool large_pages = page_size != (size_t)os::vm_page_size(); bool large_pages = page_size != (size_t)os::vm_page_size();
// Don't force the alignment to be large page aligned, // Don't force the alignment to be large page aligned,
// since that will waste memory. // since that will waste memory.
@ -357,7 +357,7 @@ VirtualSpace::VirtualSpace() {
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) { bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
const size_t max_commit_granularity = os::page_size_for_region(rs.size(), rs.size(), 1); const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1);
return initialize_with_granularity(rs, committed_size, max_commit_granularity); return initialize_with_granularity(rs, committed_size, max_commit_granularity);
} }
@ -992,7 +992,7 @@ class TestVirtualSpace : AllStatic {
case Disable: case Disable:
return vs.initialize_with_granularity(rs, 0, os::vm_page_size()); return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
case Commit: case Commit:
return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), rs.size(), 1)); return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1));
} }
} }

View file

@ -2518,7 +2518,6 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
/*********************************************/ \ /*********************************************/ \
\ \
declare_constant(InvocationEntryBci) \ declare_constant(InvocationEntryBci) \
declare_constant(InvalidOSREntryBci) \
\ \
/***************/ \ /***************/ \
/* OopMapValue */ \ /* OopMapValue */ \

View file

@ -66,6 +66,9 @@
#ifndef ATTRIBUTE_PRINTF #ifndef ATTRIBUTE_PRINTF
#define ATTRIBUTE_PRINTF(fmt, vargs) #define ATTRIBUTE_PRINTF(fmt, vargs)
#endif #endif
#ifndef ATTRIBUTE_SCANF
#define ATTRIBUTE_SCANF(fmt, vargs)
#endif
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
@ -882,8 +885,7 @@ enum JavaThreadState {
// Handy constants for deciding which compiler mode to use. // Handy constants for deciding which compiler mode to use.
enum MethodCompilation { enum MethodCompilation {
InvocationEntryBci = -1, // i.e., not a on-stack replacement compilation InvocationEntryBci = -1 // i.e., not a on-stack replacement compilation
InvalidOSREntryBci = -2
}; };
// Enumeration to distinguish tiers of compilation // Enumeration to distinguish tiers of compilation

View file

@ -271,15 +271,16 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
#define PRAGMA_IMPLEMENTATION #pragma implementation #define PRAGMA_IMPLEMENTATION #pragma implementation
#define VALUE_OBJ_CLASS_SPEC #define VALUE_OBJ_CLASS_SPEC
#ifndef ATTRIBUTE_PRINTF
// Diagnostic pragmas like the ones defined below in PRAGMA_FORMAT_NONLITERAL_IGNORED // Diagnostic pragmas like the ones defined below in PRAGMA_FORMAT_NONLITERAL_IGNORED
// were only introduced in GCC 4.2. Because we have no other possibility to ignore // were only introduced in GCC 4.2. Because we have no other possibility to ignore
// these warnings for older versions of GCC, we simply don't decorate our printf-style // these warnings for older versions of GCC, we simply don't decorate our printf-style
// functions with __attribute__(format) in that case. // functions with __attribute__(format) in that case.
#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ > 4) #if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ > 4)
#ifndef ATTRIBUTE_PRINTF
#define ATTRIBUTE_PRINTF(fmt,vargs) __attribute__((format(printf, fmt, vargs))) #define ATTRIBUTE_PRINTF(fmt,vargs) __attribute__((format(printf, fmt, vargs)))
#else #endif
#define ATTRIBUTE_PRINTF(fmt,vargs) #ifndef ATTRIBUTE_SCANF
#define ATTRIBUTE_SCANF(fmt,vargs) __attribute__((format(scanf, fmt, vargs)))
#endif #endif
#endif #endif

View file

@ -265,14 +265,6 @@ inline int g_isfinite(jdouble f) { return finite(f); }
inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
// Misc
// NOTE: This one leads to an infinite recursion on Linux
#ifndef LINUX
int local_vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr);
#define vsnprintf local_vsnprintf
#endif
// Portability macros // Portability macros
#define PRAGMA_INTERFACE #define PRAGMA_INTERFACE
#define PRAGMA_IMPLEMENTATION #define PRAGMA_IMPLEMENTATION

View file

@ -21,39 +21,32 @@
* questions. * questions.
*/ */
import sun.hotspot.WhiteBox; /*
* @test TestRangeCheck
* @bug 8054883
* @summary Tests that range check is not skipped
*/
class AllocateBeyondMetaspaceSize { public class TestRangeCheck {
public static Object dummy; public static void main(String args[]) {
try {
public static void main(String [] args) { test();
if (args.length != 2) { throw new AssertionError("Expected ArrayIndexOutOfBoundsException was not thrown");
throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>"); } catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Expected ArrayIndexOutOfBoundsException was thrown");
}
} }
long metaspaceSize = Long.parseLong(args[0]); private static void test() {
long youngGenSize = Long.parseLong(args[1]); int arr[] = new int[1];
int result = 1;
run(metaspaceSize, youngGenSize); // provoke OSR compilation
} for (int i = 0; i < Integer.MAX_VALUE; i++) {
}
private static void run(long metaspaceSize, long youngGenSize) { if (result > 0 && arr[~result] > 0) {
WhiteBox wb = WhiteBox.getWhiteBox(); arr[~result] = 0;
}
long allocationBeyondMetaspaceSize = metaspaceSize * 2;
long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize);
triggerYoungGC(youngGenSize);
wb.freeMetaspace(null, metaspace, metaspace);
}
private static void triggerYoungGC(long youngGenSize) {
long approxAllocSize = 32 * 1024;
long numAllocations = 2 * youngGenSize / approxAllocSize;
for (long i = 0; i < numAllocations; i++) {
dummy = new byte[(int)approxAllocSize];
} }
}
} }

View file

@ -22,7 +22,6 @@
*/ */
/* /*
* @ignore 8049864
* @test TestParallelHeapSizeFlags * @test TestParallelHeapSizeFlags
* @key gc * @key gc
* @bug 8006088 * @bug 8006088

View file

@ -26,7 +26,7 @@
* @key gc * @key gc
* @bug 8049831 * @bug 8049831
* @library /testlibrary /testlibrary/whitebox * @library /testlibrary /testlibrary/whitebox
* @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize * @build TestCMSClassUnloadingEnabledHWM
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission * sun.hotspot.WhiteBox$WhiteBoxPermission
* @run driver TestCMSClassUnloadingEnabledHWM * @run driver TestCMSClassUnloadingEnabledHWM
@ -35,9 +35,11 @@
import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools; import com.oracle.java.testlibrary.ProcessTools;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import sun.hotspot.WhiteBox;
public class TestCMSClassUnloadingEnabledHWM { public class TestCMSClassUnloadingEnabledHWM {
private static long MetaspaceSize = 32 * 1024 * 1024; private static long MetaspaceSize = 32 * 1024 * 1024;
@ -48,15 +50,18 @@ public class TestCMSClassUnloadingEnabledHWM {
"-Xbootclasspath/a:.", "-Xbootclasspath/a:.",
"-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI", "-XX:+WhiteBoxAPI",
"-Xmx128m",
"-XX:CMSMaxAbortablePrecleanTime=1",
"-XX:CMSWaitDuration=50",
"-XX:MetaspaceSize=" + MetaspaceSize, "-XX:MetaspaceSize=" + MetaspaceSize,
"-Xmn" + YoungGenSize, "-Xmn" + YoungGenSize,
"-XX:+UseConcMarkSweepGC", "-XX:+UseConcMarkSweepGC",
"-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled", "-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled",
"-XX:+PrintHeapAtGC", "-XX:+PrintHeapAtGC",
"-XX:+PrintGCDetails", "-XX:+PrintGCDetails",
"AllocateBeyondMetaspaceSize", "-XX:+PrintGCTimeStamps",
"" + MetaspaceSize, TestCMSClassUnloadingEnabledHWM.AllocateBeyondMetaspaceSize.class.getName(),
"" + YoungGenSize); "" + MetaspaceSize);
return new OutputAnalyzer(pb.start()); return new OutputAnalyzer(pb.start());
} }
@ -88,5 +93,37 @@ public class TestCMSClassUnloadingEnabledHWM {
testWithCMSClassUnloading(); testWithCMSClassUnloading();
testWithoutCMSClassUnloading(); testWithoutCMSClassUnloading();
} }
public static class AllocateBeyondMetaspaceSize {
public static void main(String [] args) throws Exception {
if (args.length != 1) {
throw new IllegalArgumentException("Usage: <MetaspaceSize>");
}
WhiteBox wb = WhiteBox.getWhiteBox();
// Allocate past the MetaspaceSize limit.
long metaspaceSize = Long.parseLong(args[0]);
long allocationBeyondMetaspaceSize = metaspaceSize * 2;
long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize);
// Wait for at least one GC to occur. The caller will parse the log files produced.
GarbageCollectorMXBean cmsGCBean = getCMSGCBean();
while (cmsGCBean.getCollectionCount() == 0) {
Thread.sleep(100);
}
wb.freeMetaspace(null, metaspace, metaspace);
}
private static GarbageCollectorMXBean getCMSGCBean() {
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
if (gcBean.getObjectName().toString().equals("java.lang:type=GarbageCollector,name=ConcurrentMarkSweep")) {
return gcBean;
}
}
return null;
}
}
} }

View file

@ -26,7 +26,7 @@
* @key gc * @key gc
* @bug 8049831 * @bug 8049831
* @library /testlibrary /testlibrary/whitebox * @library /testlibrary /testlibrary/whitebox
* @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize * @build TestG1ClassUnloadingHWM
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission * sun.hotspot.WhiteBox$WhiteBoxPermission
* @run driver TestG1ClassUnloadingHWM * @run driver TestG1ClassUnloadingHWM
@ -35,9 +35,9 @@
import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools; import com.oracle.java.testlibrary.ProcessTools;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import sun.hotspot.WhiteBox;
public class TestG1ClassUnloadingHWM { public class TestG1ClassUnloadingHWM {
private static long MetaspaceSize = 32 * 1024 * 1024; private static long MetaspaceSize = 32 * 1024 * 1024;
@ -54,7 +54,7 @@ public class TestG1ClassUnloadingHWM {
"-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark", "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark",
"-XX:+PrintHeapAtGC", "-XX:+PrintHeapAtGC",
"-XX:+PrintGCDetails", "-XX:+PrintGCDetails",
"AllocateBeyondMetaspaceSize", TestG1ClassUnloadingHWM.AllocateBeyondMetaspaceSize.class.getName(),
"" + MetaspaceSize, "" + MetaspaceSize,
"" + YoungGenSize); "" + YoungGenSize);
return new OutputAnalyzer(pb.start()); return new OutputAnalyzer(pb.start());
@ -88,5 +88,36 @@ public class TestG1ClassUnloadingHWM {
testWithG1ClassUnloading(); testWithG1ClassUnloading();
testWithoutG1ClassUnloading(); testWithoutG1ClassUnloading();
} }
public static class AllocateBeyondMetaspaceSize {
public static Object dummy;
public static void main(String [] args) throws Exception {
if (args.length != 2) {
throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>");
}
WhiteBox wb = WhiteBox.getWhiteBox();
// Allocate past the MetaspaceSize limit
long metaspaceSize = Long.parseLong(args[0]);
long allocationBeyondMetaspaceSize = metaspaceSize * 2;
long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize);
long youngGenSize = Long.parseLong(args[1]);
triggerYoungGCs(youngGenSize);
wb.freeMetaspace(null, metaspace, metaspace);
}
public static void triggerYoungGCs(long youngGenSize) {
long approxAllocSize = 32 * 1024;
long numAllocations = 2 * youngGenSize / approxAllocSize;
for (long i = 0; i < numAllocations; i++) {
dummy = new byte[(int)approxAllocSize];
}
}
}
} }

View file

@ -1,79 +0,0 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test TestDeferredRSUpdate
* @bug 8040977 8052170
* @summary Ensure that running with -XX:-G1DeferredRSUpdate does not crash the VM
* @key gc
* @library /testlibrary
*/
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
public class TestDeferredRSUpdate {
public static void main(String[] args) throws Exception {
GCTest.main(args);
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-Xmx10M",
"-XX:+PrintGCDetails",
// G1DeferredRSUpdate is a develop option, but we cannot limit execution of this test to only debug VMs.
"-XX:+IgnoreUnrecognizedVMOptions",
"-XX:-G1DeferredRSUpdate",
GCTest.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
}
static class GCTest {
private static Object[] garbage = new Object[32];
public static void main(String [] args) {
System.out.println("Creating garbage");
// Create 128MB of garbage. This should result in at least one minor GC, with
// some objects copied to old gen. As references from old to young are installed,
// the crash due to the use before initialize occurs.
Object prev = null;
Object prevPrev = null;
for (int i = 0; i < 1024; i++) {
Object[] next = new Object[32 * 1024];
next[0] = prev;
next[1] = prevPrev;
Object[] cur = (Object[]) garbage[i % garbage.length];
if (cur != null) {
cur[0] = null;
cur[1] = null;
}
garbage[i % garbage.length] = next;
prevPrev = prev;
prev = next;
}
System.out.println("Done");
}
}
}

View file

@ -26,7 +26,7 @@
* @bug 8036025 8056043 * @bug 8036025 8056043
* @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects * @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects
* @library /testlibrary * @library /testlibrary
* @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:+UseG1GC -XX:G1HeapRegionSize=1M -verbose:gc TestHumongousShrinkHeap * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=12 -XX:+UseG1GC -XX:G1HeapRegionSize=1M -verbose:gc TestHumongousShrinkHeap
*/ */
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
@ -41,12 +41,24 @@ public class TestHumongousShrinkHeap {
public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio"; public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio"; public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
private static final ArrayList<ArrayList<byte[]>> garbage = new ArrayList<>(); private static final List<List<byte[]>> garbage = new ArrayList();
private static final int PAGE_SIZE = 1024 * 1024; // 1M private static final int REGION_SIZE = 1024 * 1024; // 1M
private static final int PAGES_NUM = 5; private static final int LISTS_COUNT = 10;
private static final int HUMON_SIZE = Math.round(.9f * REGION_SIZE);
private static final long AVAILABLE_MEMORY
= Runtime.getRuntime().freeMemory();
private static final int HUMON_COUNT
= (int) ((AVAILABLE_MEMORY / HUMON_SIZE)
/ LISTS_COUNT);
public static void main(String[] args) { public static void main(String[] args) {
System.out.format("Running with %s max heap size. "
+ "Will allocate humongous object of %s size %d times.%n",
MemoryUsagePrinter.humanReadableByteCount(AVAILABLE_MEMORY, false),
MemoryUsagePrinter.humanReadableByteCount(HUMON_SIZE, false),
HUMON_COUNT
);
new TestHumongousShrinkHeap().test(); new TestHumongousShrinkHeap().test();
} }
@ -54,8 +66,8 @@ public class TestHumongousShrinkHeap {
System.gc(); System.gc();
MemoryUsagePrinter.printMemoryUsage("init"); MemoryUsagePrinter.printMemoryUsage("init");
eat(); allocate();
MemoryUsagePrinter.printMemoryUsage("eaten"); MemoryUsagePrinter.printMemoryUsage("allocated");
MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
free(); free();
@ -72,15 +84,12 @@ public class TestHumongousShrinkHeap {
)); ));
} }
private void eat() { private void allocate() {
int HumongousObjectSize = Math.round(.9f * PAGE_SIZE);
System.out.println("Will allocate objects of size=" +
MemoryUsagePrinter.humanReadableByteCount(HumongousObjectSize, true));
for (int i = 0; i < PAGES_NUM; i++) { for (int i = 0; i < LISTS_COUNT; i++) {
ArrayList<byte[]> stuff = new ArrayList<>(); List<byte[]> stuff = new ArrayList();
eatList(stuff, 100, HumongousObjectSize); allocateList(stuff, HUMON_COUNT, HUMON_SIZE);
MemoryUsagePrinter.printMemoryUsage("eat #" + i); MemoryUsagePrinter.printMemoryUsage("allocate #" + (i+1));
garbage.add(stuff); garbage.add(stuff);
} }
} }
@ -90,12 +99,12 @@ public class TestHumongousShrinkHeap {
garbage.subList(0, garbage.size() - 1).clear(); garbage.subList(0, garbage.size() - 1).clear();
// do not free last one element from last list // do not free last one element from last list
ArrayList stuff = garbage.get(garbage.size() - 1); List stuff = garbage.get(garbage.size() - 1);
stuff.subList(0, stuff.size() - 1).clear(); stuff.subList(0, stuff.size() - 1).clear();
System.gc(); System.gc();
} }
private static void eatList(List garbage, int count, int size) { private static void allocateList(List garbage, int count, int size) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
garbage.add(new byte[size]); garbage.add(new byte[size]);
} }
@ -122,9 +131,9 @@ class MemoryUsagePrinter {
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted(); float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n", System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
label, label,
humanReadableByteCount(memusage.getInit(), true), humanReadableByteCount(memusage.getInit(), false),
humanReadableByteCount(memusage.getUsed(), true), humanReadableByteCount(memusage.getUsed(), false),
humanReadableByteCount(memusage.getCommitted(), true), humanReadableByteCount(memusage.getCommitted(), false),
freeratio * 100 freeratio * 100
); );
} }

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test TestShrinkDefragmentedHeap
* @bug 8038423
* @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects
* 1. allocate small objects mixed with humongous ones
* "ssssHssssHssssHssssHssssHssssHssssH"
* 2. release all allocated object except the last humongous one
* "..................................H"
* 3. invoke gc and check that memory returned to the system (amount of committed memory got down)
*
* @library /testlibrary
*/
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import sun.management.ManagementFactoryHelper;
import static com.oracle.java.testlibrary.Asserts.*;
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
public class TestShrinkDefragmentedHeap {
// Since we store all the small objects, they become old and old regions are also allocated at the bottom of the heap
// together with humongous regions. So if there are a lot of old regions in the lower part of the heap,
// the humongous regions will be allocated in the upper part of the heap anyway.
// To avoid this the Eden needs to be big enough to fit all the small objects.
private static final int INITIAL_HEAP_SIZE = 200 * 1024 * 1024;
private static final int MINIMAL_YOUNG_SIZE = 190 * 1024 * 1024;
private static final int REGION_SIZE = 1 * 1024 * 1024;
public static void main(String[] args) throws Exception, Throwable {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:InitialHeapSize=" + INITIAL_HEAP_SIZE,
"-Xmn" + MINIMAL_YOUNG_SIZE,
"-XX:MinHeapFreeRatio=10",
"-XX:MaxHeapFreeRatio=11",
"-XX:+UseG1GC",
"-XX:G1HeapRegionSize=" + REGION_SIZE,
"-verbose:gc",
GCTest.class.getName()
);
OutputAnalyzer output = ProcessTools.executeProcess(pb);
output.shouldHaveExitValue(0);
}
static class GCTest {
private static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
private static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
private static final String NEW_SIZE_FLAG_NAME = "NewSize";
private static final ArrayList<ArrayList<byte[]>> garbage = new ArrayList<>();
private static final int SMALL_OBJS_SIZE = 10 * 1024; // 10kB
private static final int SMALL_OBJS_COUNT = MINIMAL_YOUNG_SIZE / (SMALL_OBJS_SIZE-1);
private static final int ALLOCATE_COUNT = 3;
// try to put all humongous object into gap between min young size and initial heap size
// to avoid implicit GCs
private static final int HUMONG_OBJS_SIZE = (int) Math.max(
(INITIAL_HEAP_SIZE - MINIMAL_YOUNG_SIZE) / ALLOCATE_COUNT / 4,
REGION_SIZE * 1.1
);
private static final long initialHeapSize = getHeapMemoryUsage().getUsed();
public static void main(String[] args) throws InterruptedException {
new GCTest().test();
}
private void test() throws InterruptedException {
MemoryUsagePrinter.printMemoryUsage("init");
allocate();
System.gc();
MemoryUsage muFull = getHeapMemoryUsage();
MemoryUsagePrinter.printMemoryUsage("allocated");
free();
//Thread.sleep(1000); // sleep before measures due lags in JMX
MemoryUsage muFree = getHeapMemoryUsage();
MemoryUsagePrinter.printMemoryUsage("free");
assertLessThan(muFree.getCommitted(), muFull.getCommitted(), prepareMessageCommittedIsNotLess() );
}
private void allocate() {
System.out.format("Will allocate objects of small size = %s and humongous size = %s",
MemoryUsagePrinter.humanReadableByteCount(SMALL_OBJS_SIZE, false),
MemoryUsagePrinter.humanReadableByteCount(HUMONG_OBJS_SIZE, false)
);
for (int i = 0; i < ALLOCATE_COUNT; i++) {
ArrayList<byte[]> stuff = new ArrayList<>();
allocateList(stuff, SMALL_OBJS_COUNT / ALLOCATE_COUNT, SMALL_OBJS_SIZE);
garbage.add(stuff);
ArrayList<byte[]> humongousStuff = new ArrayList<>();
allocateList(humongousStuff, 4, HUMONG_OBJS_SIZE);
garbage.add(humongousStuff);
}
}
private void free() {
// do not free last one list
garbage.subList(0, garbage.size() - 1).clear();
// do not free last one element from last list
ArrayList stuff = garbage.get(garbage.size() - 1);
if (stuff.size() > 1) {
stuff.subList(0, stuff.size() - 1).clear();
}
System.gc();
}
private String prepareMessageCommittedIsNotLess() {
return String.format(
"committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n"
+ "%s = %s%n%s = %s",
MIN_FREE_RATIO_FLAG_NAME,
ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(),
MAX_FREE_RATIO_FLAG_NAME,
ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue()
);
}
private static void allocateList(List garbage, int count, int size) {
for (int i = 0; i < count; i++) {
garbage.add(new byte[size]);
}
}
}
static MemoryUsage getHeapMemoryUsage() {
return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
}
/**
* Prints memory usage to standard output
*/
static class MemoryUsagePrinter {
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) {
return bytes + " B";
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
public static void printMemoryUsage(String label) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
label,
humanReadableByteCount(memusage.getInit(), false),
humanReadableByteCount(memusage.getUsed(), false),
humanReadableByteCount(memusage.getCommitted(), false),
freeratio * 100
);
}
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test TestLargePageSizeInBytes
* @summary Tests that the flag -XX:LargePageSizeInBytes does not cause warnings on Solaris
* @bug 8049536
* @library /testlibrary
* @run driver TestLargePageSizeInBytes
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.Platform;
import com.oracle.java.testlibrary.ProcessTools;
public class TestLargePageSizeInBytes {
private static long M = 1024L * 1024L;
private static long G = 1024L * M;
public static void main(String[] args) throws Exception {
if (!Platform.isSolaris()) {
// We only use the syscall mencntl on Solaris
return;
}
testLargePageSizeInBytes(4 * M);
testLargePageSizeInBytes(256 * M);
testLargePageSizeInBytes(512 * M);
testLargePageSizeInBytes(2 * G);
}
private static void testLargePageSizeInBytes(long size) throws Exception {
ProcessBuilder pb =
ProcessTools.createJavaProcessBuilder("-XX:+UseLargePages",
"-XX:LargePageSizeInBytes=" + size,
"-version");
OutputAnalyzer out = new OutputAnalyzer(pb.start());
out.shouldNotContain("Attempt to use MPSS failed.");
out.shouldHaveExitValue(0);
}
}

View file

@ -273,3 +273,4 @@ a5aea8318ae4a9c2105228568688875142d70344 jdk9-b26
dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28 dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28
30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29 30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29
d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30 d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30
292317ebc7dbaca6b3965f0bc7b38a2cee733b7a jdk9-b31

View file

@ -276,3 +276,4 @@ dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27
5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28 5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28
3d1a4bfb6abbf5011ba6d8896301ee3b6ef3ba72 jdk9-b29 3d1a4bfb6abbf5011ba6d8896301ee3b6ef3ba72 jdk9-b29
e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30 e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30
7af228ae847f3c02aaafb7b01cdbb3bdc2e89e77 jdk9-b31

View file

@ -1,152 +0,0 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.api.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import com.sun.istack.internal.Nullable;
/**
* {@link ClassLoader} that loads Annotation Processing and specified classes
* both into the same classloader, so that they can reference each other.
*
* @author Bhakti Mehta
* @since 2.0 beta
*/
public final class ApClassLoader extends URLClassLoader {
/**
* List of package prefixes we want to mask the
* parent classLoader from loading
*/
private final String[] packagePrefixes;
/**
*
* @param packagePrefixes
* The package prefixes that are forced to resolve within this class loader.
* @param parent
* The parent class loader to delegate to. Null to indicate bootstrap classloader.
*/
public ApClassLoader(@Nullable ClassLoader parent, String[] packagePrefixes) throws ToolsJarNotFoundException {
super(getToolsJar(parent),parent);
if(getURLs().length==0)
// if tools.jar was found in our classloader, no need to create
// a parallel classes
this.packagePrefixes = new String[0];
else
this.packagePrefixes = packagePrefixes;
}
public Class loadClass(String className) throws ClassNotFoundException {
for( String prefix : packagePrefixes ) {
if (className.startsWith(prefix) ) {
// we need to load those classes in this class loader
// without delegation.
return findClass(className);
}
}
return super.loadClass(className);
}
protected Class findClass(String name) throws ClassNotFoundException {
StringBuilder sb = new StringBuilder(name.length() + 6);
sb.append(name.replace('.','/')).append(".class");
InputStream is = getResourceAsStream(sb.toString());
if (is==null)
throw new ClassNotFoundException("Class not found" + sb);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while((len=is.read(buf))>=0)
baos.write(buf,0,len);
buf = baos.toByteArray();
// define package if not defined yet
int i = name.lastIndexOf('.');
if (i != -1) {
String pkgname = name.substring(0, i);
Package pkg = getPackage(pkgname);
if(pkg==null)
definePackage(pkgname, null, null, null, null, null, null, null);
}
return defineClass(name,buf,0,buf.length);
} catch (IOException e) {
throw new ClassNotFoundException(name,e);
} finally {
try {
is.close();
} catch (IOException ioe) {
//ignore
}
}
}
/**
* Returns a class loader that can load classes from JDK tools.jar.
* @param parent
*/
private static URL[] getToolsJar(@Nullable ClassLoader parent) throws ToolsJarNotFoundException {
try {
Class.forName("com.sun.tools.javac.Main", false, parent);
return new URL[0];
// we can already load them in the parent class loader.
// so no need to look for tools.jar.
// this happens when we are run inside IDE/Ant, or
// in Mac OS.
} catch (ClassNotFoundException e) {
// otherwise try to find tools.jar
}
File jreHome = new File(System.getProperty("java.home"));
File toolsJar = new File( jreHome.getParent(), "lib/tools.jar" );
if (!toolsJar.exists()) {
throw new ToolsJarNotFoundException(toolsJar);
}
try {
return new URL[]{toolsJar.toURL()};
} catch (MalformedURLException e) {
// impossible
throw new AssertionError(e);
}
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, 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
@ -29,19 +29,16 @@ import com.sun.istack.internal.tools.MaskingClassLoader;
import com.sun.istack.internal.tools.ParallelWorldClassLoader; import com.sun.istack.internal.tools.ParallelWorldClassLoader;
import com.sun.tools.internal.ws.resources.WscompileMessages; import com.sun.tools.internal.ws.resources.WscompileMessages;
import com.sun.tools.internal.ws.wscompile.Options; import com.sun.tools.internal.ws.wscompile.Options;
import com.sun.tools.internal.xjc.api.util.ToolsJarNotFoundException;
import com.sun.xml.internal.bind.util.Which; import com.sun.xml.internal.bind.util.Which;
import javax.xml.ws.Service; import javax.xml.ws.Service;
import javax.xml.ws.WebServiceFeature; import javax.xml.ws.WebServiceFeature;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import java.io.File;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
@ -59,7 +56,7 @@ public final class Invoker {
/** /**
* The list of package prefixes we want the * The list of package prefixes we want the
* {@link MaskingClassLoader} to prevent the parent * {@link MaskingClassLoader} to prevent the parent
* classLoader from loading * class loader from loading
*/ */
static final String[] maskedPackages = new String[]{ static final String[] maskedPackages = new String[]{
"com.sun.istack.internal.tools.", "com.sun.istack.internal.tools.",
@ -130,24 +127,6 @@ public final class Invoker {
return -1; return -1;
} }
//find and load tools.jar
List<URL> urls = new ArrayList<URL>();
findToolsJar(cl, urls);
if(urls.size() > 0){
List<String> mask = new ArrayList<String>(Arrays.asList(maskedPackages));
// first create a protected area so that we load JAXB/WS 2.1 API
// and everything that depends on them inside
cl = new MaskingClassLoader(cl,mask);
// then this classloader loads the API and tools.jar
cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), cl);
// finally load the rest of the RI. The actual class files are loaded from ancestors
cl = new ParallelWorldClassLoader(cl,"");
}
} }
Thread.currentThread().setContextClassLoader(cl); Thread.currentThread().setContextClassLoader(cl);
@ -158,8 +137,6 @@ public final class Invoker {
Method runMethod = compileTool.getMethod("run",String[].class); Method runMethod = compileTool.getMethod("run",String[].class);
boolean r = (Boolean)runMethod.invoke(tool,new Object[]{args}); boolean r = (Boolean)runMethod.invoke(tool,new Object[]{args});
return r ? 0 : 1; return r ? 0 : 1;
} catch (ToolsJarNotFoundException e) {
System.err.println(e.getMessage());
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
throw e.getCause(); throw e.getCause();
} catch(ClassNotFoundException e){ } catch(ClassNotFoundException e){
@ -167,8 +144,6 @@ public final class Invoker {
}finally { }finally {
Thread.currentThread().setContextClassLoader(oldcc); Thread.currentThread().setContextClassLoader(oldcc);
} }
return -1;
} }
/** /**
@ -203,10 +178,10 @@ public final class Invoker {
/** /**
* Creates a classloader that can load JAXB/WS 2.2 API and tools.jar, * Creates a class loader that can load JAXB/WS 2.2 API,
* and then return a classloader that can RI classes, which can see all those APIs and tools.jar. * and then return a class loader that can RI classes, which can see all those APIs.
*/ */
public static ClassLoader createClassLoader(ClassLoader cl) throws ClassNotFoundException, IOException, ToolsJarNotFoundException { public static ClassLoader createClassLoader(ClassLoader cl) throws ClassNotFoundException, IOException {
URL[] urls = findIstack22APIs(cl); URL[] urls = findIstack22APIs(cl);
if(urls.length==0) if(urls.length==0)
@ -223,7 +198,7 @@ public final class Invoker {
// and everything that depends on them inside // and everything that depends on them inside
cl = new MaskingClassLoader(cl,mask); cl = new MaskingClassLoader(cl,mask);
// then this classloader loads the API and tools.jar // then this class loader loads the API
cl = new URLClassLoader(urls, cl); cl = new URLClassLoader(urls, cl);
// finally load the rest of the RI. The actual class files are loaded from ancestors // finally load the rest of the RI. The actual class files are loaded from ancestors
@ -233,13 +208,13 @@ public final class Invoker {
} }
/** /**
* Creates a classloader for loading JAXB/WS 2.2 jar and tools.jar * Creates a class loader for loading JAXB/WS 2.2 jar
*/ */
private static URL[] findIstack22APIs(ClassLoader cl) throws ClassNotFoundException, IOException, ToolsJarNotFoundException { private static URL[] findIstack22APIs(ClassLoader cl) throws ClassNotFoundException, IOException {
List<URL> urls = new ArrayList<URL>(); List<URL> urls = new ArrayList<URL>();
if(Service.class.getClassLoader()==null) { if(Service.class.getClassLoader()==null) {
// JAX-WS API is loaded from bootstrap classloader // JAX-WS API is loaded from bootstrap class loader
URL res = cl.getResource("javax/xml/ws/EndpointContext.class"); URL res = cl.getResource("javax/xml/ws/EndpointContext.class");
if(res==null) if(res==null)
throw new ClassNotFoundException("There's no JAX-WS 2.2 API in the classpath"); throw new ClassNotFoundException("There's no JAX-WS 2.2 API in the classpath");
@ -250,28 +225,7 @@ public final class Invoker {
urls.add(ParallelWorldClassLoader.toJarUrl(res)); urls.add(ParallelWorldClassLoader.toJarUrl(res));
} }
findToolsJar(cl, urls);
return urls.toArray(new URL[urls.size()]); return urls.toArray(new URL[urls.size()]);
} }
private static void findToolsJar(ClassLoader cl, List<URL> urls) throws ToolsJarNotFoundException, MalformedURLException {
try {
Class.forName("com.sun.tools.javac.Main",false,cl);
// we can already load them in the parent class loader.
// so no need to look for tools.jar.
// this happens when we are run inside IDE/Ant, or
// in Mac OS.
} catch (ClassNotFoundException e) {
// otherwise try to find tools.jar
File jreHome = new File(System.getProperty("java.home"));
File toolsJar = new File( jreHome.getParent(), "lib/tools.jar" );
if (!toolsJar.exists()) {
throw new ToolsJarNotFoundException(toolsJar);
}
urls.add(toolsJar.toURL());
}
}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, 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
@ -35,8 +35,7 @@ import com.sun.tools.internal.ws.wscompile.WsgenTool;
*/ */
public class WsGen { public class WsGen {
/** /**
* CLI entry point. Use {@link Invoker} to * CLI entry point. Use {@link Invoker} to load proper API version
* load tools.jar
*/ */
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
System.exit(Invoker.invoke("com.sun.tools.internal.ws.wscompile.WsgenTool", args)); System.exit(Invoker.invoke("com.sun.tools.internal.ws.wscompile.WsgenTool", args));
@ -50,7 +49,7 @@ public class WsGen {
* it doesn't invoke {@link System#exit(int)}. This method * it doesn't invoke {@link System#exit(int)}. This method
* also doesn't play with classloaders. It's the caller's * also doesn't play with classloaders. It's the caller's
* responsibility to set up the classloader to load all jars * responsibility to set up the classloader to load all jars
* needed to run the tool, including <tt>$JAVA_HOME/lib/tools.jar</tt> * needed to run the tool.
* *
* @return * @return
* 0 if the tool runs successfully. * 0 if the tool runs successfully.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, 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
@ -35,8 +35,7 @@ import com.sun.tools.internal.ws.wscompile.WsimportTool;
*/ */
public class WsImport { public class WsImport {
/** /**
* CLI entry point. Use {@link Invoker} to * CLI entry point. Use {@link Invoker} to load proper API version
* load tools.jar
*/ */
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
System.exit(Invoker.invoke("com.sun.tools.internal.ws.wscompile.WsimportTool", args)); System.exit(Invoker.invoke("com.sun.tools.internal.ws.wscompile.WsimportTool", args));
@ -50,7 +49,7 @@ public class WsImport {
* it doesn't invoke {@link System#exit(int)}. This method * it doesn't invoke {@link System#exit(int)}. This method
* also doesn't play with classloaders. It's the caller's * also doesn't play with classloaders. It's the caller's
* responsibility to set up the classloader to load all jars * responsibility to set up the classloader to load all jars
* needed to run the tool, including <tt>$JAVA_HOME/lib/tools.jar</tt> * needed to run the tool.
* *
* @return * @return
* 0 if the tool runs successfully. * 0 if the tool runs successfully.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, 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
@ -39,40 +39,16 @@ public final class JavacompilerMessages {
private final static LocalizableMessageFactory messageFactory = new LocalizableMessageFactory("com.sun.tools.internal.ws.resources.javacompiler"); private final static LocalizableMessageFactory messageFactory = new LocalizableMessageFactory("com.sun.tools.internal.ws.resources.javacompiler");
private final static Localizer localizer = new Localizer(); private final static Localizer localizer = new Localizer();
public static Localizable localizableJAVACOMPILER_CLASSPATH_ERROR(Object arg0) { public static Localizable localizableNO_JAVACOMPILER_ERROR() {
return messageFactory.getMessage("javacompiler.classpath.error", arg0); return messageFactory.getMessage("no.javacompiler.error");
} }
/** /**
* {0} is not available in the classpath, requires Sun's JDK version 5.0 or latter. * No system compiler found, check your jdk.
* *
*/ */
public static String JAVACOMPILER_CLASSPATH_ERROR(Object arg0) { public static String NO_JAVACOMPILER_ERROR() {
return localizer.localize(localizableJAVACOMPILER_CLASSPATH_ERROR(arg0)); return localizer.localize(localizableNO_JAVACOMPILER_ERROR());
}
public static Localizable localizableJAVACOMPILER_NOSUCHMETHOD_ERROR(Object arg0) {
return messageFactory.getMessage("javacompiler.nosuchmethod.error", arg0);
}
/**
* There is no such method {0} available, requires Sun's JDK version 5.0 or latter.
*
*/
public static String JAVACOMPILER_NOSUCHMETHOD_ERROR(Object arg0) {
return localizer.localize(localizableJAVACOMPILER_NOSUCHMETHOD_ERROR(arg0));
}
public static Localizable localizableJAVACOMPILER_ERROR(Object arg0) {
return messageFactory.getMessage("javacompiler.error", arg0);
}
/**
* error : {0}.
*
*/
public static String JAVACOMPILER_ERROR(Object arg0) {
return localizer.localize(localizableJAVACOMPILER_ERROR(arg0));
} }
} }

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2005, 2014, 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,6 +26,4 @@
# #
# Generic Messages # Generic Messages
# #
javacompiler.classpath.error={0} is not available in the classpath, requires Sun's JDK version 5.0 or latter. no.javacompiler.error=No system compiler found, check your jdk.
javacompiler.nosuchmethod.error=There is no such method {0} available, requires Sun's JDK version 5.0 or latter.
javacompiler.error=error : {0}.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, 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,14 +28,13 @@ package com.sun.tools.internal.ws.wscompile;
import com.sun.istack.internal.tools.ParallelWorldClassLoader; import com.sun.istack.internal.tools.ParallelWorldClassLoader;
import com.sun.tools.internal.ws.resources.JavacompilerMessages; import com.sun.tools.internal.ws.resources.JavacompilerMessages;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File; import java.io.File;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL;
/** /**
* A helper class to invoke javac. * A helper class to invoke javac.
@ -61,34 +60,17 @@ class JavaCompilerHelper{
} }
static boolean compile(String[] args, OutputStream out, ErrorReceiver receiver){ static boolean compile(String[] args, OutputStream out, ErrorReceiver receiver){
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try { try {
/* try to use the new compiler */ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
Class comSunToolsJavacMainClass = if (comp == null) {
cl.loadClass("com.sun.tools.javac.Main"); receiver.error(JavacompilerMessages.NO_JAVACOMPILER_ERROR(), null);
try { return false;
Method compileMethod =
comSunToolsJavacMainClass.getMethod(
"compile",
compileMethodSignature);
Object result =
compileMethod.invoke(
null, args, new PrintWriter(out));
return result instanceof Integer && (Integer) result == 0;
} catch (NoSuchMethodException e2) {
receiver.error(JavacompilerMessages.JAVACOMPILER_NOSUCHMETHOD_ERROR("getMethod(\"compile\", Class[])"), e2);
} catch (IllegalAccessException e) {
receiver.error(e);
} catch (InvocationTargetException e) {
receiver.error(e);
} }
} catch (ClassNotFoundException e) { return 0 == comp.run(null, out, out, args);
receiver.error(JavacompilerMessages.JAVACOMPILER_CLASSPATH_ERROR("com.sun.tools.javac.Main"), e);
} catch (SecurityException e) { } catch (SecurityException e) {
receiver.error(e); receiver.error(e);
} }
return false; return false;
} }
private static final Class[] compileMethodSignature = {String[].class, PrintWriter.class};
} }

View file

@ -273,3 +273,4 @@ f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27
1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28 1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28
2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29 2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29
8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30 8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30
71e99dae28f9791287b88d46e16a266b564f22be jdk9-b31

View file

@ -220,7 +220,6 @@ RT_JAR_EXCLUDES += \
sun/tools/serialver \ sun/tools/serialver \
sun/tools/tree \ sun/tools/tree \
sun/tools/util \ sun/tools/util \
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \ sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \
META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \ META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \
sun/util/resources/cldr \ sun/util/resources/cldr \
@ -452,11 +451,9 @@ $(CLDR_METAINF_SERVICES): $(JDK_TOPDIR)/src/jdk.localedata/META-INF/cldrdata-ser
$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \ $(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \
$(CLDR_METAINF_SERVICES), \ $(CLDR_METAINF_SERVICES), \
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \ SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \
$(JDK_OUTPUTDIR)/modules/java.base \
$(CLDR_SERVICES_DIR), \ $(CLDR_SERVICES_DIR), \
SUFFIXES := .class, \ SUFFIXES := .class, \
INCLUDES := sun/text/resources/cldr \ INCLUDES := sun/text/resources/cldr \
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/cldr, \ sun/util/resources/cldr, \
EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \ EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \
JAR := $(CLDRDATA_JAR_DST), \ JAR := $(CLDRDATA_JAR_DST), \

View file

@ -29,14 +29,13 @@ include GensrcCommon.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES) GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES)
include GensrcLocaleDataMetaInfo.gmk include GensrcLocaleData.gmk
include GensrcCharacterData.gmk include GensrcCharacterData.gmk
include GensrcMisc.gmk include GensrcMisc.gmk
include GensrcCharsetMapping.gmk include GensrcCharsetMapping.gmk
include GensrcCharsetCoder.gmk include GensrcCharsetCoder.gmk
include GensrcBuffer.gmk include GensrcBuffer.gmk
include GensrcExceptions.gmk include GensrcExceptions.gmk
include GensrcCLDR.gmk
java.base: $(GENSRC_JAVA_BASE) java.base: $(GENSRC_JAVA_BASE)

View file

@ -0,0 +1,38 @@
#
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
include GensrcCommon.gmk
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-jdk.localedata.gmk))
include GensrcLocaleData.gmk
include GensrcCLDR.gmk
jdk.localedata: $(GENSRC_JDK_LOCALEDATA)
all: jdk.localedata
.PHONY: all jdk.localedata

View file

@ -27,9 +27,8 @@ CLDRVERSION := 21.0.1
CLDRSRCDIR := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/cldr/resources/$(subst .,_,$(CLDRVERSION)) CLDRSRCDIR := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/cldr/resources/$(subst .,_,$(CLDRVERSION))
GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata
BASE_GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/java.base
CLDR_METAINFO_FILE := $(BASE_GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java
$(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \ $(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \
$(wildcard $(CLDRSRCDIR)/common/main/*.xml) \ $(wildcard $(CLDRSRCDIR)/common/main/*.xml) \
@ -37,16 +36,6 @@ $(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \
$(BUILD_TOOLS_JDK) $(BUILD_TOOLS_JDK)
$(MKDIR) -p $(GENSRC_DIR) $(MKDIR) -p $(GENSRC_DIR)
$(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) -o $(GENSRC_DIR) $(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) -o $(GENSRC_DIR)
$(MKDIR) -p $(BASE_GENSRC_DIR)/sun/text/resources/cldr
$(MKDIR) -p $(BASE_GENSRC_DIR)/sun/util/resources/cldr
$(RM) -r $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en \
$(BASE_GENSRC_DIR)/sun/util/resources/cldr/en
$(MV) $(GENSRC_DIR)/sun/text/resources/cldr/en $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en
$(MV) $(GENSRC_DIR)/sun/util/resources/cldr/en $(BASE_GENSRC_DIR)/sun/util/resources/cldr/en
$(MV) $(GENSRC_DIR)/sun/text/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/text/resources/cldr
$(MV) $(GENSRC_DIR)/sun/util/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/util/resources/cldr
$(MKDIR) -p $(@D)
$(MV) $(GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java $@
GENSRC_CLDR := $(CLDR_METAINFO_FILE) GENSRC_CLDR := $(CLDR_METAINFO_FILE)
GENSRC_JAVA_BASE += $(GENSRC_CLDR) GENSRC_JDK_LOCALEDATA += $(GENSRC_CLDR)

View file

@ -130,8 +130,8 @@ $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDa
$(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
$(SED) $(SED_NONENARGS) $< > $@ $(SED) $(SED_NONENARGS) $< > $@
GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \ GENSRC_BASELOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java
$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java GENSRC_LOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
################################################################################ ################################################################################
@ -145,7 +145,8 @@ $(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResou
$(MKDIR) -p $(@D) $(MKDIR) -p $(@D)
NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@ NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@
GENSRC_LOCALEDATAMETAINFO += $(GENSRC_CRBC_DST) GENSRC_BASELOCALEDATA += $(GENSRC_CRBC_DST)
GENSRC_JAVA_BASE += $(GENSRC_LOCALEDATAMETAINFO) GENSRC_JAVA_BASE += $(GENSRC_BASELOCALEDATA)
GENSRC_JDK_LOCALEDATA += $(GENSRC_LOCALEDATA)
################################################################################ ################################################################################

View file

@ -217,10 +217,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
-I$(JDK_OUTPUTDIR)/gensrc_headers/java.base \ -I$(JDK_OUTPUTDIR)/gensrc_headers/java.base \
# #
LIBAWT_EXFILES += \ LIBAWT_EXFILES += \
sun/java2d/d3d/D3DPipeline.cpp \
sun/java2d/d3d/D3DShaderGen.c \ sun/java2d/d3d/D3DShaderGen.c \
sun/awt/image/cvutils/img_colors.c \ sun/awt/image/cvutils/img_colors.c \
sun/windows/WBufferStrategy.cpp \
# #
LIBAWT_LANG := C++ LIBAWT_LANG := C++

View file

@ -143,8 +143,9 @@ class ResourceBundleGenerator implements BundleGenerator {
@Override @Override
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException { public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException {
String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + File.separator String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" +
+ "cldr" + File.separator; File.separator + "resources" + File.separator + "cldr" + File.separator +
"provider" + File.separator ;
File dir = new File(dirName); File dir = new File(dirName);
if (!dir.exists()) { if (!dir.exists()) {
dir.mkdirs(); dir.mkdirs();
@ -158,7 +159,7 @@ class ResourceBundleGenerator implements BundleGenerator {
try (PrintWriter out = new PrintWriter(file, "us-ascii")) { try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
out.println(CopyrightHeaders.getOpenJDKCopyright()); out.println(CopyrightHeaders.getOpenJDKCopyright());
out.println("package sun.util.cldr;\n\n" out.println("package sun.util.resources.cldr.provider;\n\n"
+ "import java.util.ListResourceBundle;\n" + "import java.util.ListResourceBundle;\n"
+ "import sun.util.locale.provider.LocaleProviderAdapter;\n" + "import sun.util.locale.provider.LocaleProviderAdapter;\n"
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n"); + "import sun.util.locale.provider.LocaleDataMetaInfo;\n");

View file

@ -25,29 +25,17 @@
package build.tools.module; package build.tools.module;
import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.UncheckedIOException;
import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.jar.JarEntry; import java.util.stream.Collectors;
import java.util.jar.JarFile;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;
/** /**
* GenJdepsModulesXml augments the input modules.xml file(s) * GenJdepsModulesXml augments the input modules.xml file(s)
@ -97,14 +85,14 @@ public final class GenJdepsModulesXml {
Set<Module> modules = new HashSet<>(); Set<Module> modules = new HashSet<>();
for (; i < args.length; i++) { for (; i < args.length; i++) {
Path p = Paths.get(args[i]); Path p = Paths.get(args[i]);
try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) { modules.addAll(ModulesXmlReader.readModules(p)
Set<Module> mods = gentool.load(in); .stream()
modules.addAll(mods); .map(gentool::buildIncludes)
} .collect(Collectors.toSet()));
} }
Files.createDirectories(outfile.getParent()); Files.createDirectories(outfile.getParent());
gentool.writeXML(modules, outfile); ModulesXmlWriter.writeModules(modules, outfile);
} }
final Path modulepath; final Path modulepath;
@ -112,228 +100,21 @@ public final class GenJdepsModulesXml {
this.modulepath = modulepath; this.modulepath = modulepath;
} }
private static final String MODULES = "modules"; private static String packageName(Path p) {
private static final String MODULE = "module";
private static final String NAME = "name";
private static final String DEPEND = "depend";
private static final String EXPORT = "export";
private static final String TO = "to";
private static final String INCLUDE = "include";
private static final QName REEXPORTS = new QName("re-exports");
private Set<Module> load(InputStream in) throws XMLStreamException, IOException {
Set<Module> modules = new HashSet<>();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader stream = factory.createXMLEventReader(in);
Module.Builder mb = null;
String modulename = null;
String pkg = null;
Set<String> permits = new HashSet<>();
while (stream.hasNext()) {
XMLEvent event = stream.nextEvent();
if (event.isStartElement()) {
String startTag = event.asStartElement().getName().getLocalPart();
switch (startTag) {
case MODULES:
break;
case MODULE:
if (mb != null) {
throw new RuntimeException("end tag for module is missing");
}
modulename = getNextTag(stream, NAME);
mb = new Module.Builder();
mb.name(modulename);
break;
case NAME:
throw new RuntimeException(event.toString());
case DEPEND:
boolean reexports = false;
Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
if (attr != null) {
String value = attr.getValue();
if (value.equals("true") || value.equals("false")) {
reexports = Boolean.parseBoolean(value);
} else {
throw new RuntimeException("unexpected attribute " + attr.toString());
}
}
mb.require(getData(stream), reexports);
break;
case INCLUDE:
throw new RuntimeException("unexpected " + event);
case EXPORT:
pkg = getNextTag(stream, NAME);
break;
case TO:
permits.add(getData(stream));
break;
default:
}
} else if (event.isEndElement()) {
String endTag = event.asEndElement().getName().getLocalPart();
switch (endTag) {
case MODULE:
buildIncludes(mb, modulename);
modules.add(mb.build());
mb = null;
break;
case EXPORT:
if (pkg == null) {
throw new RuntimeException("export-to is malformed");
}
mb.exportTo(pkg, permits);
pkg = null;
permits.clear();
break;
default:
}
} else if (event.isCharacters()) {
String s = event.asCharacters().getData();
if (!s.trim().isEmpty()) {
throw new RuntimeException("export-to is malformed");
}
}
}
return modules;
}
private String getData(XMLEventReader reader) throws XMLStreamException {
XMLEvent e = reader.nextEvent();
if (e.isCharacters()) {
return e.asCharacters().getData();
}
throw new RuntimeException(e.toString());
}
private String getNextTag(XMLEventReader reader, String tag) throws XMLStreamException {
XMLEvent e = reader.nextTag();
if (e.isStartElement()) {
String t = e.asStartElement().getName().getLocalPart();
if (!tag.equals(t)) {
throw new RuntimeException(e + " expected: " + tag);
}
return getData(reader);
}
throw new RuntimeException("export-to name is missing:" + e);
}
private void writeXML(Set<Module> modules, Path path)
throws IOException, XMLStreamException
{
XMLOutputFactory xof = XMLOutputFactory.newInstance();
try (OutputStream out = Files.newOutputStream(path)) {
int depth = 0;
XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8");
xtw.writeStartDocument("utf-8","1.0");
writeStartElement(xtw, MODULES, depth);
modules.stream()
.sorted(Comparator.comparing(Module::name))
.forEach(m -> writeModuleElement(xtw, m, depth+1));
writeEndElement(xtw, depth);
xtw.writeCharacters("\n");
xtw.writeEndDocument();
xtw.flush();
xtw.close();
}
}
private void writeElement(XMLStreamWriter xtw, String element, String value, int depth) {
try {
writeStartElement(xtw, element, depth);
xtw.writeCharacters(value);
xtw.writeEndElement();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private void writeDependElement(XMLStreamWriter xtw, Module.Dependence d, int depth) {
try {
writeStartElement(xtw, DEPEND, depth);
if (d.reexport) {
xtw.writeAttribute("re-exports", "true");
}
xtw.writeCharacters(d.name);
xtw.writeEndElement();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private void writeExportElement(XMLStreamWriter xtw, String pkg, int depth) {
writeExportElement(xtw, pkg, Collections.emptySet(), depth);
}
private void writeExportElement(XMLStreamWriter xtw, String pkg,
Set<String> permits, int depth) {
try {
writeStartElement(xtw, EXPORT, depth);
writeElement(xtw, NAME, pkg, depth+1);
if (!permits.isEmpty()) {
permits.stream().sorted()
.forEach(m -> writeElement(xtw, TO, m, depth + 1));
}
writeEndElement(xtw, depth);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private void writeModuleElement(XMLStreamWriter xtw, Module m, int depth) {
try {
writeStartElement(xtw, MODULE, depth);
writeElement(xtw, NAME, m.name(), depth+1);
m.requires().stream().sorted(Comparator.comparing(d -> d.name))
.forEach(d -> writeDependElement(xtw, d, depth+1));
m.exports().keySet().stream()
.filter(pn -> m.exports().get(pn).isEmpty())
.sorted()
.forEach(pn -> writeExportElement(xtw, pn, depth+1));
m.exports().entrySet().stream()
.filter(e -> !e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1));
m.packages().stream().sorted()
.forEach(p -> writeElement(xtw, INCLUDE, p, depth+1));
writeEndElement(xtw, depth);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
/** Two spaces; the default indentation. */
public static final String DEFAULT_INDENT = " ";
/** stack[depth] indicates what's been written into the current scope. */
private static String[] stack = new String[] { "\n",
"\n" + DEFAULT_INDENT,
"\n" + DEFAULT_INDENT + DEFAULT_INDENT,
"\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT};
private void writeStartElement(XMLStreamWriter xtw, String name, int depth)
throws XMLStreamException
{
xtw.writeCharacters(stack[depth]);
xtw.writeStartElement(name);
}
private void writeEndElement(XMLStreamWriter xtw, int depth) throws XMLStreamException {
xtw.writeCharacters(stack[depth]);
xtw.writeEndElement();
}
private String packageName(Path p) {
return packageName(p.toString().replace(File.separatorChar, '/')); return packageName(p.toString().replace(File.separatorChar, '/'));
} }
private String packageName(String name) { private static String packageName(String name) {
int i = name.lastIndexOf('/'); int i = name.lastIndexOf('/');
return (i > 0) ? name.substring(0, i).replace('/', '.') : ""; return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
} }
private boolean includes(String name) { private static boolean includes(String name) {
return name.endsWith(".class") && !name.equals("module-info.class"); return name.endsWith(".class");
} }
public void buildIncludes(Module.Builder mb, String modulename) throws IOException { public Module buildIncludes(Module module) {
Path mclasses = modulepath.resolve(modulename); Module.Builder mb = new Module.Builder(module);
Path mclasses = modulepath.resolve(module.name());
try { try {
Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr) Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
-> includes(p.getFileName().toString())) -> includes(p.getFileName().toString()))
@ -341,145 +122,9 @@ public final class GenJdepsModulesXml {
.forEach(mb::include); .forEach(mb::include);
} catch (NoSuchFileException e) { } catch (NoSuchFileException e) {
// aggregate module may not have class // aggregate module may not have class
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
} }
} return mb.build();
static class Module {
static class Dependence {
final String name;
final boolean reexport;
Dependence(String name) {
this(name, false);
}
Dependence(String name, boolean reexport) {
this.name = name;
this.reexport = reexport;
}
@Override
public int hashCode() {
int hash = 5;
hash = 11 * hash + Objects.hashCode(this.name);
hash = 11 * hash + (this.reexport ? 1 : 0);
return hash;
}
public boolean equals(Object o) {
Dependence d = (Dependence)o;
return this.name.equals(d.name) && this.reexport == d.reexport;
}
}
private final String moduleName;
private final Set<Dependence> requires;
private final Map<String, Set<String>> exports;
private final Set<String> packages;
private Module(String name,
Set<Dependence> requires,
Map<String, Set<String>> exports,
Set<String> packages) {
this.moduleName = name;
this.requires = Collections.unmodifiableSet(requires);
this.exports = Collections.unmodifiableMap(exports);
this.packages = Collections.unmodifiableSet(packages);
}
public String name() {
return moduleName;
}
public Set<Dependence> requires() {
return requires;
}
public Map<String, Set<String>> exports() {
return exports;
}
public Set<String> packages() {
return packages;
}
@Override
public boolean equals(Object ob) {
if (!(ob instanceof Module)) {
return false;
}
Module that = (Module) ob;
return (moduleName.equals(that.moduleName)
&& requires.equals(that.requires)
&& exports.equals(that.exports)
&& packages.equals(that.packages));
}
@Override
public int hashCode() {
int hc = moduleName.hashCode();
hc = hc * 43 + requires.hashCode();
hc = hc * 43 + exports.hashCode();
hc = hc * 43 + packages.hashCode();
return hc;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("module ").append(moduleName).append(" {").append("\n");
requires.stream().sorted().forEach(d ->
sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name)));
exports.entrySet().stream().filter(e -> e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> sb.append(String.format(" exports %s%n", e.getKey())));
exports.entrySet().stream().filter(e -> !e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue())));
packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn)));
sb.append("}");
return sb.toString();
}
static class Builder {
private String name;
private final Set<Dependence> requires = new HashSet<>();
private final Map<String, Set<String>> exports = new HashMap<>();
private final Set<String> packages = new HashSet<>();
public Builder() {
}
public Builder name(String n) {
name = n;
return this;
}
public Builder require(String d, boolean reexport) {
requires.add(new Dependence(d, reexport));
return this;
}
public Builder include(String p) {
packages.add(p);
return this;
}
public Builder export(String p) {
return exportTo(p, Collections.emptySet());
}
public Builder exportTo(String p, Set<String> ms) {
Objects.requireNonNull(p);
Objects.requireNonNull(ms);
if (exports.containsKey(p)) {
throw new RuntimeException(name + " already exports " + p);
}
exports.put(p, new HashSet<>(ms));
return this;
}
public Module build() {
Module m = new Module(name, requires, exports, packages);
return m;
}
}
} }
} }

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.module;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
/**
* $ java build.tools.module.GenModulesList \
* -o modules.list \
* top/modules.xml ...
*/
public final class GenModulesList {
private final static String USAGE =
"Usage: GenModulesList -o <output file> path-to-modules-xml";
private Set<Module> modules = new HashSet<>();
private HashMap<String,Module> nameToModule = new HashMap<>();
public static void main(String[] args) throws Exception {
GenModulesList gen = new GenModulesList();
gen.run(args);
}
void run(String[] args) throws Exception {
Path outfile = null;
int i = 0;
while (i < args.length) {
String arg = args[i];
if (arg.equals("-o")) {
outfile = Paths.get(args[i+1]);
i = i+2;
} else {
break;
}
}
if (outfile == null || i >= args.length) {
System.err.println(USAGE);
System.exit(-1);
}
for (; i < args.length; i++) {
Path p = Paths.get(args[i]);
modules.addAll(ModulesXmlReader.readModules(p));
}
modules.stream()
.forEach(m -> nameToModule.put(m.name(), m));
Path parent = outfile.getParent();
if (parent != null)
Files.createDirectories(parent);
Iterable<Module> sortedModules = (new TopoSorter(modules)).result();
try (PrintWriter writer = new PrintWriter(outfile.toFile())) {
for (Module m : sortedModules) {
if (isNotAggregator(m)) {
String deps = getModuleDependences(m).stream()
.filter(GenModulesList::isNotAggregator)
.map(Module::name)
.collect(Collectors.joining(" "));
writer.format("%s: %s%n", m.name(), deps);
}
}
}
}
private Module nameToModule(String name) {
return nameToModule.get(name);
}
private Set<Module> getModuleDependences(Module m) {
return m.requires().stream()
.map(d -> d.name())
.map(this::nameToModule)
.collect(Collectors.toSet());
}
static boolean isNotAggregator(Module m) {
return isNotAggregator(m.name());
}
static boolean isNotAggregator(String name) {
return AGGREGATORS.contains(name) ? false : true;
}
static final List<String> AGGREGATORS = Arrays.asList(new String[] {
"java.se", "java.compact1", "java.compact2",
"java.compact3", "jdk.compact3"});
class TopoSorter {
final Deque<Module> result = new LinkedList<>();
final Deque<Module> nodes = new LinkedList<>();
TopoSorter(Collection<Module> nodes) {
nodes.stream()
.forEach(m -> this.nodes.add(m));
sort();
}
public Iterable<Module> result() {
return result;
}
private void sort() {
Deque<Module> visited = new LinkedList<>();
Deque<Module> done = new LinkedList<>();
Module node;
while ((node = nodes.poll()) != null) {
if (!visited.contains(node)) {
visit(node, visited, done);
}
}
}
private void visit(Module m, Deque<Module> visited, Deque<Module> done) {
if (visited.contains(m)) {
if (!done.contains(m)) {
throw new IllegalArgumentException("Cyclic detected: " +
m + " " + getModuleDependences(m));
}
return;
}
visited.add(m);
getModuleDependences(m).stream()
.forEach(x -> visit(x, visited, done));
done.add(m);
result.addLast(m);
}
}
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.module;
import java.util.*;
public class Module {
static class Dependence {
final String name;
final boolean reexport;
Dependence(String name) {
this(name, false);
}
Dependence(String name, boolean reexport) {
this.name = name;
this.reexport = reexport;
}
public String name() {
return name;
}
@Override
public int hashCode() {
int hash = 5;
hash = 11 * hash + Objects.hashCode(this.name);
hash = 11 * hash + (this.reexport ? 1 : 0);
return hash;
}
public boolean equals(Object o) {
Dependence d = (Dependence)o;
return this.name.equals(d.name) && this.reexport == d.reexport;
}
}
private final String moduleName;
private final Set<Dependence> requires;
private final Map<String, Set<String>> exports;
private final Set<String> packages;
private Module(String name,
Set<Dependence> requires,
Map<String, Set<String>> exports,
Set<String> packages) {
this.moduleName = name;
this.requires = Collections.unmodifiableSet(requires);
this.exports = Collections.unmodifiableMap(exports);
this.packages = Collections.unmodifiableSet(packages);
}
public String name() {
return moduleName;
}
public Set<Dependence> requires() {
return requires;
}
public Map<String, Set<String>> exports() {
return exports;
}
public Set<String> packages() {
return packages;
}
@Override
public boolean equals(Object ob) {
if (!(ob instanceof Module)) {
return false;
}
Module that = (Module) ob;
return (moduleName.equals(that.moduleName)
&& requires.equals(that.requires)
&& exports.equals(that.exports)
&& packages.equals(that.packages));
}
@Override
public int hashCode() {
int hc = moduleName.hashCode();
hc = hc * 43 + requires.hashCode();
hc = hc * 43 + exports.hashCode();
hc = hc * 43 + packages.hashCode();
return hc;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("module ").append(moduleName).append(" {").append("\n");
requires.stream().sorted().forEach(d ->
sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name)));
exports.entrySet().stream().filter(e -> e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> sb.append(String.format(" exports %s%n", e.getKey())));
exports.entrySet().stream().filter(e -> !e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue())));
packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn)));
sb.append("}");
return sb.toString();
}
static class Builder {
private String name;
private final Set<Dependence> requires = new HashSet<>();
private final Map<String, Set<String>> exports = new HashMap<>();
private final Set<String> packages = new HashSet<>();
public Builder() {
}
public Builder(Module module) {
name = module.name();
requires.addAll(module.requires());
exports.putAll(module.exports());
packages.addAll(module.packages());
}
public Builder name(String n) {
name = n;
return this;
}
public Builder require(String d, boolean reexport) {
requires.add(new Dependence(d, reexport));
return this;
}
public Builder include(String p) {
packages.add(p);
return this;
}
public Builder export(String p) {
return exportTo(p, Collections.emptySet());
}
public Builder exportTo(String p, Set<String> ms) {
Objects.requireNonNull(p);
Objects.requireNonNull(ms);
if (exports.containsKey(p)) {
throw new RuntimeException(name + " already exports " + p);
}
exports.put(p, new HashSet<>(ms));
return this;
}
public Module build() {
Module m = new Module(name, requires, exports, packages);
return m;
}
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.module;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
public class ModulesXmlReader {
private ModulesXmlReader() {}
public static Set<Module> readModules(Path modulesXml)
throws XMLStreamException, IOException
{
Set<Module> modules = new HashSet<>();
try (InputStream in = new BufferedInputStream(Files.newInputStream(modulesXml))) {
Set<Module> mods = ModulesXmlReader.load(in);
modules.addAll(mods);
}
return modules;
}
private static final String MODULES = "modules";
private static final String MODULE = "module";
private static final String NAME = "name";
private static final String DEPEND = "depend";
private static final String EXPORT = "export";
private static final String TO = "to";
private static final String INCLUDE = "include";
private static final QName REEXPORTS = new QName("re-exports");
private static Set<Module> load(InputStream in)
throws XMLStreamException, IOException
{
Set<Module> modules = new HashSet<>();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader stream = factory.createXMLEventReader(in);
Module.Builder mb = null;
String modulename = null;
String pkg = null;
Set<String> permits = new HashSet<>();
while (stream.hasNext()) {
XMLEvent event = stream.nextEvent();
if (event.isStartElement()) {
String startTag = event.asStartElement().getName().getLocalPart();
switch (startTag) {
case MODULES:
break;
case MODULE:
if (mb != null) {
throw new RuntimeException("end tag for module is missing");
}
modulename = getNextTag(stream, NAME);
mb = new Module.Builder();
mb.name(modulename);
break;
case NAME:
throw new RuntimeException(event.toString());
case DEPEND:
boolean reexports = false;
Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
if (attr != null) {
String value = attr.getValue();
if (value.equals("true") || value.equals("false")) {
reexports = Boolean.parseBoolean(value);
} else {
throw new RuntimeException("unexpected attribute " + attr.toString());
}
}
mb.require(getData(stream), reexports);
break;
case INCLUDE:
throw new RuntimeException("unexpected " + event);
case EXPORT:
pkg = getNextTag(stream, NAME);
break;
case TO:
permits.add(getData(stream));
break;
default:
}
} else if (event.isEndElement()) {
String endTag = event.asEndElement().getName().getLocalPart();
switch (endTag) {
case MODULE:
modules.add(mb.build());
mb = null;
break;
case EXPORT:
if (pkg == null) {
throw new RuntimeException("export-to is malformed");
}
mb.exportTo(pkg, permits);
pkg = null;
permits.clear();
break;
default:
}
} else if (event.isCharacters()) {
String s = event.asCharacters().getData();
if (!s.trim().isEmpty()) {
throw new RuntimeException("export-to is malformed");
}
}
}
return modules;
}
private static String getData(XMLEventReader reader)
throws XMLStreamException
{
XMLEvent e = reader.nextEvent();
if (e.isCharacters())
return e.asCharacters().getData();
throw new RuntimeException(e.toString());
}
private static String getNextTag(XMLEventReader reader, String tag)
throws XMLStreamException
{
XMLEvent e = reader.nextTag();
if (e.isStartElement()) {
String t = e.asStartElement().getName().getLocalPart();
if (!tag.equals(t)) {
throw new RuntimeException(e + " expected: " + tag);
}
return getData(reader);
}
throw new RuntimeException("export-to name is missing:" + e);
}
}

View file

@ -0,0 +1,179 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.module;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
public final class ModulesXmlWriter {
private ModulesXmlWriter() {}
public static void writeModules(Set<Module> modules, Path path)
throws IOException, XMLStreamException
{
writeXML(modules, path);
}
private static final String MODULES = "modules";
private static final String MODULE = "module";
private static final String NAME = "name";
private static final String DEPEND = "depend";
private static final String EXPORT = "export";
private static final String TO = "to";
private static final String INCLUDE = "include";
private static final QName REEXPORTS = new QName("re-exports");
private static void writeXML(Set<Module> modules, Path path)
throws IOException, XMLStreamException
{
XMLOutputFactory xof = XMLOutputFactory.newInstance();
try (OutputStream out = Files.newOutputStream(path)) {
int depth = 0;
XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8");
xtw.writeStartDocument("utf-8","1.0");
writeStartElement(xtw, MODULES, depth);
modules.stream()
.sorted(Comparator.comparing(Module::name))
.forEach(m -> writeModuleElement(xtw, m, depth+1));
writeEndElement(xtw, depth);
xtw.writeCharacters("\n");
xtw.writeEndDocument();
xtw.flush();
xtw.close();
}
}
private static void writeElement(XMLStreamWriter xtw,
String element,
String value,
int depth) {
try {
writeStartElement(xtw, element, depth);
xtw.writeCharacters(value);
xtw.writeEndElement();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private static void writeDependElement(XMLStreamWriter xtw,
Module.Dependence d,
int depth) {
try {
writeStartElement(xtw, DEPEND, depth);
if (d.reexport) {
xtw.writeAttribute("re-exports", "true");
}
xtw.writeCharacters(d.name);
xtw.writeEndElement();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private static void writeExportElement(XMLStreamWriter xtw,
String pkg,
int depth) {
writeExportElement(xtw, pkg, Collections.emptySet(), depth);
}
private static void writeExportElement(XMLStreamWriter xtw,
String pkg,
Set<String> permits,
int depth) {
try {
writeStartElement(xtw, EXPORT, depth);
writeElement(xtw, NAME, pkg, depth+1);
if (!permits.isEmpty()) {
permits.stream().sorted()
.forEach(m -> writeElement(xtw, TO, m, depth + 1));
}
writeEndElement(xtw, depth);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
private static void writeModuleElement(XMLStreamWriter xtw,
Module m,
int depth) {
try {
writeStartElement(xtw, MODULE, depth);
writeElement(xtw, NAME, m.name(), depth+1);
m.requires().stream().sorted(Comparator.comparing(d -> d.name))
.forEach(d -> writeDependElement(xtw, d, depth+1));
m.exports().keySet().stream()
.filter(pn -> m.exports().get(pn).isEmpty())
.sorted()
.forEach(pn -> writeExportElement(xtw, pn, depth+1));
m.exports().entrySet().stream()
.filter(e -> !e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1));
m.packages().stream().sorted()
.forEach(p -> writeElement(xtw, INCLUDE, p, depth+1));
writeEndElement(xtw, depth);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
/** Two spaces; the default indentation. */
public static final String DEFAULT_INDENT = " ";
/** stack[depth] indicates what's been written into the current scope. */
private static String[] stack = new String[] { "\n",
"\n" + DEFAULT_INDENT,
"\n" + DEFAULT_INDENT + DEFAULT_INDENT,
"\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT};
private static void writeStartElement(XMLStreamWriter xtw,
String name,
int depth)
throws XMLStreamException
{
xtw.writeCharacters(stack[depth]);
xtw.writeStartElement(name);
}
private static void writeEndElement(XMLStreamWriter xtw, int depth)
throws XMLStreamException
{
xtw.writeCharacters(stack[depth]);
xtw.writeEndElement();
}
}

View file

@ -62,7 +62,7 @@ class InvokerBytecodeGenerator {
private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
/** Name of its super class*/ /** Name of its super class*/
private static final String superName = LF; private static final String superName = OBJ;
/** Name of new class */ /** Name of new class */
private final String className; private final String className;
@ -97,7 +97,7 @@ class InvokerBytecodeGenerator {
if (DUMP_CLASS_FILES) { if (DUMP_CLASS_FILES) {
className = makeDumpableClassName(className); className = makeDumpableClassName(className);
} }
this.className = superName + "$" + className; this.className = LF + "$" + className;
this.sourceFile = "LambdaForm$" + className; this.sourceFile = "LambdaForm$" + className;
this.lambdaForm = lambdaForm; this.lambdaForm = lambdaForm;
this.invokerName = invokerName; this.invokerName = invokerName;

View file

@ -188,7 +188,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
boolean strict, boolean monobox) { boolean strict, boolean monobox) {
MethodType dstType = target.type(); MethodType dstType = target.type();
assert(dstType.parameterCount() == target.type().parameterCount());
if (srcType == dstType) if (srcType == dstType)
return target; return target;
if (USE_LAMBDA_FORM_EDITOR) { if (USE_LAMBDA_FORM_EDITOR) {
@ -265,6 +264,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
boolean strict, boolean monobox) { boolean strict, boolean monobox) {
assert(target.type().parameterCount() == srcType.parameterCount());
// Calculate extra arguments (temporaries) required in the names array. // Calculate extra arguments (temporaries) required in the names array.
Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
final int INARG_COUNT = srcType.parameterCount(); final int INARG_COUNT = srcType.parameterCount();

View file

@ -2023,8 +2023,9 @@ return invoker;
*/ */
public static public static
MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
MethodType oldType = target.type(); explicitCastArgumentsChecks(target, newType);
// use the asTypeCache when possible: // use the asTypeCache when possible:
MethodType oldType = target.type();
if (oldType == newType) return target; if (oldType == newType) return target;
if (oldType.explicitCastEquivalentToAsType(newType)) { if (oldType.explicitCastEquivalentToAsType(newType)) {
return target.asType(newType); return target.asType(newType);
@ -2032,6 +2033,12 @@ return invoker;
return MethodHandleImpl.makePairwiseConvert(target, newType, false); return MethodHandleImpl.makePairwiseConvert(target, newType, false);
} }
private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) {
if (target.type().parameterCount() != newType.parameterCount()) {
throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType);
}
}
/** /**
* Produces a method handle which adapts the calling sequence of the * Produces a method handle which adapts the calling sequence of the
* given method handle to a new type, by reordering the arguments. * given method handle to a new type, by reordering the arguments.
@ -2164,7 +2171,7 @@ assert((int)twice.invokeExact(21) == 42);
// dropIdx is missing from reorder; add it in at the end // dropIdx is missing from reorder; add it in at the end
int oldArity = reorder.length; int oldArity = reorder.length;
target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
reorder = Arrays.copyOf(reorder, oldArity+1); reorder = Arrays.copyOf(reorder, oldArity + 1);
reorder[oldArity] = dropIdx; reorder[oldArity] = dropIdx;
} }
assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
@ -2182,9 +2189,9 @@ assert((int)twice.invokeExact(21) == 42);
long mask = 0; long mask = 0;
for (int arg : reorder) { for (int arg : reorder) {
assert(arg < newArity); assert(arg < newArity);
mask |= (1 << arg); mask |= (1L << arg);
} }
if (mask == (1 << newArity) - 1) { if (mask == (1L << newArity) - 1) {
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
return -1; return -1;
} }
@ -2193,16 +2200,18 @@ assert((int)twice.invokeExact(21) == 42);
int zeroPos = Long.numberOfTrailingZeros(zeroBit); int zeroPos = Long.numberOfTrailingZeros(zeroBit);
assert(zeroPos < newArity); assert(zeroPos < newArity);
return zeroPos; return zeroPos;
} else {
BitSet mask = new BitSet(newArity);
for (int arg : reorder) {
assert (arg < newArity);
mask.set(arg);
}
int zeroPos = mask.nextClearBit(0);
assert(zeroPos <= newArity);
if (zeroPos == newArity)
return -1;
return zeroPos;
} }
BitSet mask = new BitSet(newArity);
for (int arg : reorder) {
assert(arg < newArity);
mask.set(arg);
}
int zeroPos = mask.nextClearBit(0);
if (zeroPos == newArity)
return -1;
return zeroPos;
} }
/** /**
@ -2218,32 +2227,42 @@ assert((int)twice.invokeExact(21) == 42);
long mask = 0; long mask = 0;
for (int i = 0; i < reorder.length; i++) { for (int i = 0; i < reorder.length; i++) {
int arg = reorder[i]; int arg = reorder[i];
if (arg >= newArity) return reorder.length; if (arg >= newArity) {
int bit = 1 << arg; return reorder.length;
if ((mask & bit) != 0) }
long bit = 1L << arg;
if ((mask & bit) != 0) {
return i; // >0 indicates a dup return i; // >0 indicates a dup
}
mask |= bit; mask |= bit;
} }
if (mask == (1 << newArity) - 1) { if (mask == (1L << newArity) - 1) {
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
return 0; return 0;
} }
// find first zero // find first zero
long zeroBit = Long.lowestOneBit(~mask); long zeroBit = Long.lowestOneBit(~mask);
int zeroPos = Long.numberOfTrailingZeros(zeroBit); int zeroPos = Long.numberOfTrailingZeros(zeroBit);
assert(zeroPos < newArity); assert(zeroPos <= newArity);
if (zeroPos == newArity) {
return 0;
}
return ~zeroPos; return ~zeroPos;
} else { } else {
// same algorithm, different bit set // same algorithm, different bit set
BitSet mask = new BitSet(newArity); BitSet mask = new BitSet(newArity);
for (int i = 0; i < reorder.length; i++) { for (int i = 0; i < reorder.length; i++) {
int arg = reorder[i]; int arg = reorder[i];
if (arg >= newArity) return reorder.length; if (arg >= newArity) {
if (mask.get(arg)) return reorder.length;
}
if (mask.get(arg)) {
return i; // >0 indicates a dup return i; // >0 indicates a dup
}
mask.set(arg); mask.set(arg);
} }
int zeroPos = mask.nextClearBit(0); int zeroPos = mask.nextClearBit(0);
assert(zeroPos <= newArity);
if (zeroPos == newArity) { if (zeroPos == newArity) {
return 0; return 0;
} }
@ -2479,6 +2498,7 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
MethodType oldType = target.type(); // get NPE MethodType oldType = target.type(); // get NPE
int dropped = dropArgumentChecks(oldType, pos, valueTypes); int dropped = dropArgumentChecks(oldType, pos, valueTypes);
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
if (dropped == 0) return target; if (dropped == 0) return target;
BoundMethodHandle result = target.rebind(); BoundMethodHandle result = target.rebind();
LambdaForm lform = result.form; LambdaForm lform = result.form;
@ -2490,7 +2510,6 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
} else { } else {
lform = lform.addArguments(pos, valueTypes); lform = lform.addArguments(pos, valueTypes);
} }
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
result = result.copyWith(newType, lform); result = result.copyWith(newType, lform);
return result; return result;
} }

View file

@ -869,9 +869,7 @@ class MethodType implements java.io.Serializable {
if (dstTypes == srcTypes) { if (dstTypes == srcTypes) {
return true; return true;
} }
if (dstTypes.length != srcTypes.length) { assert(dstTypes.length == srcTypes.length);
return false;
}
for (int i = 0; i < dstTypes.length; i++) { for (int i = 0; i < dstTypes.length; i++) {
if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) { if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
return false; return false;

View file

@ -1261,19 +1261,20 @@ class MutableBigInteger {
int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
MutableBigInteger bShifted = new MutableBigInteger(b); MutableBigInteger bShifted = new MutableBigInteger(b);
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
safeLeftShift(sigma); // step 4b: shift this by the same amount MutableBigInteger aShifted = new MutableBigInteger (this);
aShifted.safeLeftShift(sigma); // step 4b: shift a by the same amount
// step 5: t is the number of blocks needed to accommodate this plus one additional bit // step 5: t is the number of blocks needed to accommodate a plus one additional bit
int t = (int) ((bitLength()+n32) / n32); int t = (int) ((aShifted.bitLength()+n32) / n32);
if (t < 2) { if (t < 2) {
t = 2; t = 2;
} }
// step 6: conceptually split this into blocks a[t-1], ..., a[0] // step 6: conceptually split a into blocks a[t-1], ..., a[0]
MutableBigInteger a1 = getBlock(t-1, t, n); // the most significant block of this MutableBigInteger a1 = aShifted.getBlock(t-1, t, n); // the most significant block of a
// step 7: z[t-2] = [a[t-1], a[t-2]] // step 7: z[t-2] = [a[t-1], a[t-2]]
MutableBigInteger z = getBlock(t-2, t, n); // the second to most significant block MutableBigInteger z = aShifted.getBlock(t-2, t, n); // the second to most significant block
z.addDisjoint(a1, n); // z[t-2] z.addDisjoint(a1, n); // z[t-2]
// do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers // do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers
@ -1284,7 +1285,7 @@ class MutableBigInteger {
ri = z.divide2n1n(bShifted, qi); ri = z.divide2n1n(bShifted, qi);
// step 8b: z = [ri, a[i-1]] // step 8b: z = [ri, a[i-1]]
z = getBlock(i-1, t, n); // a[i-1] z = aShifted.getBlock(i-1, t, n); // a[i-1]
z.addDisjoint(ri, n); z.addDisjoint(ri, n);
quotient.addShifted(qi, i*n); // update q (part of step 9) quotient.addShifted(qi, i*n); // update q (part of step 9)
} }
@ -1292,7 +1293,7 @@ class MutableBigInteger {
ri = z.divide2n1n(bShifted, qi); ri = z.divide2n1n(bShifted, qi);
quotient.add(qi); quotient.add(qi);
ri.rightShift(sigma); // step 9: this and b were shifted, so shift back ri.rightShift(sigma); // step 9: a and b were shifted, so shift back
return ri; return ri;
} }
} }

View file

@ -336,8 +336,21 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
return new ZipEntry(name); return new ZipEntry(name);
} }
/* /**
* Reads end of deflated entry as well as EXT descriptor if present. * Reads end of deflated entry as well as EXT descriptor if present.
*
* Local headers for DEFLATED entries may optionally be followed by a
* data descriptor, and that data descriptor may optionally contain a
* leading signature (EXTSIG).
*
* From the zip spec http://www.pkware.com/documents/casestudies/APPNOTE.TXT
*
* """Although not originally assigned a signature, the value 0x08074b50
* has commonly been adopted as a signature value for the data descriptor
* record. Implementers should be aware that ZIP files may be
* encountered with or without this signature marking data descriptors
* and should account for either case when reading ZIP files to ensure
* compatibility."""
*/ */
private void readEnd(ZipEntry e) throws IOException { private void readEnd(ZipEntry e) throws IOException {
int n = inf.getRemaining(); int n = inf.getRemaining();
@ -356,7 +369,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
((PushbackInputStream)in).unread( ((PushbackInputStream)in).unread(
tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC); tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC);
} else { } else {
e.crc = get32(tmpbuf, ZIP64_EXTCRC); e.crc = get32(tmpbuf, ZIP64_EXTCRC);
e.csize = get64(tmpbuf, ZIP64_EXTSIZ); e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
@ -370,7 +383,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
e.csize = get32(tmpbuf, EXTSIZ - EXTCRC); e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
e.size = get32(tmpbuf, EXTLEN - EXTCRC); e.size = get32(tmpbuf, EXTLEN - EXTCRC);
((PushbackInputStream)in).unread( ((PushbackInputStream)in).unread(
tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC); tmpbuf, EXTHDR - EXTCRC, EXTCRC);
} else { } else {
e.crc = get32(tmpbuf, EXTCRC); e.crc = get32(tmpbuf, EXTCRC);
e.csize = get32(tmpbuf, EXTSIZ); e.csize = get32(tmpbuf, EXTSIZ);

View file

@ -34,6 +34,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#if defined(__linux__)
#include <linux/fs.h>
#include <sys/ioctl.h>
#endif
#include "nio.h" #include "nio.h"
#include "nio_util.h" #include "nio_util.h"
@ -177,10 +181,21 @@ Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this,
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
{ {
jint fd = fdval(env, fdo);
struct stat64 fbuf; struct stat64 fbuf;
if (fstat64(fdval(env, fdo), &fbuf) < 0) if (fstat64(fd, &fbuf) < 0)
return handle(env, -1, "Size failed"); return handle(env, -1, "Size failed");
#ifdef BLKGETSIZE64
if (S_ISBLK(fbuf.st_mode)) {
uint64_t size;
if (ioctl(fd, BLKGETSIZE64, &size) < 0)
return handle(env, -1, "Size failed");
return (jlong)size;
}
#endif
return fbuf.st_size; return fbuf.st_size;
} }

View file

@ -990,9 +990,11 @@ JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
case MIB_IF_TYPE_FDDI: case MIB_IF_TYPE_FDDI:
case IF_TYPE_IEEE80211: case IF_TYPE_IEEE80211:
len = ifRowP->dwPhysAddrLen; len = ifRowP->dwPhysAddrLen;
ret = (*env)->NewByteArray(env, len); if (len > 0) {
if (!IS_NULL(ret)) { ret = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); if (!IS_NULL(ret)) {
(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
}
} }
break; break;
} }

Some files were not shown because too many files have changed in this diff Show more