mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
Merge
This commit is contained in:
commit
a2e41921c1
263 changed files with 9016 additions and 2958 deletions
1
.hgtags
1
.hgtags
|
@ -273,3 +273,4 @@ d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27
|
|||
f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28
|
||||
c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29
|
||||
b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30
|
||||
9d0e6639a4d71b63507dd94b1a028e963b27e798 jdk9-b31
|
||||
|
|
|
@ -273,3 +273,4 @@ ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27
|
|||
ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28
|
||||
9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29
|
||||
36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30
|
||||
69a84c16d9c28e0e3d504b9c8766c24bafcd58f6 jdk9-b31
|
||||
|
|
8
Makefile
8
Makefile
|
@ -70,8 +70,8 @@ else
|
|||
# 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.
|
||||
all_phony_targets := $(sort $(filter-out $(global_targets), $(strip $(shell \
|
||||
cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) | \
|
||||
grep "^.PHONY:" | head -n 1 | cut -d " " -f 2-))))
|
||||
cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) \
|
||||
-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
|
||||
# target will execute with a single configuration loaded.
|
||||
|
@ -115,12 +115,12 @@ else
|
|||
|
||||
main-wrapper:
|
||||
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))
|
||||
endif
|
||||
ifneq ($(PARALLEL_TARGETS), )
|
||||
@$(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) \
|
||||
$(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC)))
|
||||
@$(call AtMakeEnd)
|
||||
|
|
|
@ -4327,7 +4327,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
|
|||
#CUSTOM_AUTOCONF_INCLUDE
|
||||
|
||||
# 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"
|
||||
DEBUG_CLASSFILES="true"
|
||||
BUILD_VARIANT_RELEASE="-debug"
|
||||
HOTSPOT_DEBUG_LEVEL="jvmg"
|
||||
HOTSPOT_DEBUG_LEVEL="debug"
|
||||
HOTSPOT_EXPORT="debug"
|
||||
;;
|
||||
optimized )
|
||||
|
|
|
@ -97,8 +97,6 @@ ifeq ($(JVM_INTERPRETER), cpp)
|
|||
endif
|
||||
|
||||
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
|
||||
TEST_IN_BUILD=@TEST_IN_BUILD@
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL],
|
|||
FASTDEBUG="false"
|
||||
DEBUG_CLASSFILES="true"
|
||||
BUILD_VARIANT_RELEASE="-debug"
|
||||
HOTSPOT_DEBUG_LEVEL="jvmg"
|
||||
HOTSPOT_DEBUG_LEVEL="debug"
|
||||
HOTSPOT_EXPORT="debug"
|
||||
;;
|
||||
optimized )
|
||||
|
|
|
@ -245,6 +245,7 @@ JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
|
|||
NASHORN_OUTPUTDIR=$(BUILD_OUTPUT)/nashorn
|
||||
IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
|
||||
TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
|
||||
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
|
||||
|
||||
LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist
|
||||
CORBA_DIST=$(CORBA_OUTPUTDIR)/dist
|
||||
|
|
|
@ -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.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/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/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/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/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/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
|
||||
|
@ -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/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.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/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
|
||||
|
|
|
@ -273,3 +273,4 @@ da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25
|
|||
a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28
|
||||
163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29
|
||||
98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30
|
||||
c432b80aadd0cb2b2361b02add4d671957d4cec9 jdk9-b31
|
||||
|
|
|
@ -433,3 +433,4 @@ f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27
|
|||
657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28
|
||||
deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29
|
||||
5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30
|
||||
9f7d155d28e519f3e4645dc21cf185c25f3176ed jdk9-b31
|
||||
|
|
|
@ -107,7 +107,6 @@ public class VM {
|
|||
private Runtime1 runtime1;
|
||||
/** These constants come from globalDefinitions.hpp */
|
||||
private int invocationEntryBCI;
|
||||
private int invalidOSREntryBCI;
|
||||
private ReversePtrs revPtrs;
|
||||
private VMRegImpl vmregImpl;
|
||||
private int reserveForAllocationPrefetch;
|
||||
|
@ -295,7 +294,6 @@ public class VM {
|
|||
|
||||
stackBias = db.lookupIntConstant("STACK_BIAS").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
|
||||
// already have present in the type database
|
||||
|
@ -733,11 +731,6 @@ public class VM {
|
|||
return invocationEntryBCI;
|
||||
}
|
||||
|
||||
/** FIXME: figure out where to stick this */
|
||||
public int getInvalidOSREntryBCI() {
|
||||
return invalidOSREntryBCI;
|
||||
}
|
||||
|
||||
// FIXME: figure out where to stick this
|
||||
public boolean wizardMode() {
|
||||
return true;
|
||||
|
|
|
@ -1166,9 +1166,9 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr(Register backedge_co
|
|||
beq(CCR0, overflow_with_error);
|
||||
|
||||
// Has the nmethod been invalidated already?
|
||||
lwz(Rtmp, nmethod::entry_bci_offset(), R3_RET);
|
||||
cmpwi(CCR0, Rtmp, InvalidOSREntryBci);
|
||||
beq(CCR0, overflow_with_error);
|
||||
lbz(Rtmp, nmethod::state_offset(), R3_RET);
|
||||
cmpwi(CCR0, Rtmp, nmethod::in_use);
|
||||
bne(CCR0, overflow_with_error);
|
||||
|
||||
// Migrate the interpreter frame off of the stack.
|
||||
// We can use all registers because we will not return to interpreter from this point.
|
||||
|
|
|
@ -1674,9 +1674,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
|||
__ beq(CCR0, Lforward);
|
||||
|
||||
// Has the nmethod been invalidated already?
|
||||
__ lwz(R0, nmethod::entry_bci_offset(), R3_RET);
|
||||
__ cmpwi(CCR0, R0, InvalidOSREntryBci);
|
||||
__ beq(CCR0, Lforward);
|
||||
__ lbz(R0, nmethod::state_offset(), R3_RET);
|
||||
__ cmpwi(CCR0, R0, nmethod::in_use);
|
||||
__ bne(CCR0, Lforward);
|
||||
|
||||
// Migrate the interpreter frame off of the stack.
|
||||
// We can use all registers because we will not return to interpreter from this point.
|
||||
|
|
|
@ -2407,8 +2407,8 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_c
|
|||
br_null_short(O0, Assembler::pn, overflow_with_error);
|
||||
|
||||
// Has the nmethod been invalidated already?
|
||||
ld(O0, nmethod::entry_bci_offset(), O2);
|
||||
cmp_and_br_short(O2, InvalidOSREntryBci, Assembler::equal, Assembler::pn, overflow_with_error);
|
||||
ldub(O0, nmethod::state_offset(), O2);
|
||||
cmp_and_br_short(O2, nmethod::in_use, Assembler::notEqual, Assembler::pn, overflow_with_error);
|
||||
|
||||
// migrate the interpreter frame off of the stack
|
||||
|
||||
|
|
|
@ -1636,8 +1636,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
|||
__ br_null_short(O0, Assembler::pn, Lforward);
|
||||
|
||||
// Has the nmethod been invalidated already?
|
||||
__ ld(O0, nmethod::entry_bci_offset(), O2);
|
||||
__ cmp_and_br_short(O2, InvalidOSREntryBci, Assembler::equal, Assembler::pn, Lforward);
|
||||
__ ldub(O0, nmethod::state_offset(), O2);
|
||||
__ cmp_and_br_short(O2, nmethod::in_use, Assembler::notEqual, Assembler::pn, Lforward);
|
||||
|
||||
// migrate the interpreter frame off of the stack
|
||||
|
||||
|
|
|
@ -1724,9 +1724,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
|||
__ testptr(rax, rax); // test result
|
||||
__ jcc(Assembler::zero, dispatch); // no osr if null
|
||||
// nmethod may have been invalidated (VM may block upon call_VM return)
|
||||
__ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
|
||||
__ cmpl(rcx, InvalidOSREntryBci);
|
||||
__ jcc(Assembler::equal, dispatch);
|
||||
__ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use);
|
||||
__ jcc(Assembler::notEqual, dispatch);
|
||||
|
||||
// We have the address of an on stack replacement routine in rax,
|
||||
// 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
|
||||
|
||||
const Register thread = rcx;
|
||||
__ get_thread(thread);
|
||||
__ get_thread(rcx);
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin));
|
||||
// rax, is OSR buffer, move it to expected parameter location
|
||||
__ mov(rcx, rax);
|
||||
|
|
|
@ -1751,9 +1751,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
|||
__ testptr(rax, rax); // test result
|
||||
__ jcc(Assembler::zero, dispatch); // no osr if null
|
||||
// nmethod may have been invalidated (VM may block upon call_VM return)
|
||||
__ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
|
||||
__ cmpl(rcx, InvalidOSREntryBci);
|
||||
__ jcc(Assembler::equal, dispatch);
|
||||
__ cmpb(Address(rax, nmethod::state_offset()), nmethod::in_use);
|
||||
__ jcc(Assembler::notEqual, dispatch);
|
||||
|
||||
// We have the address of an on stack replacement routine in eax
|
||||
// We need to prepare to execute the OSR method. First we must
|
||||
|
|
|
@ -4002,10 +4002,6 @@ bool os::check_heap(bool force) {
|
|||
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?
|
||||
bool os::dir_is_empty(const char* path) {
|
||||
DIR *dir = NULL;
|
||||
|
|
|
@ -3822,12 +3822,6 @@ bool os::check_heap(bool force) {
|
|||
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?
|
||||
bool os::dir_is_empty(const char* path) {
|
||||
DIR *dir = NULL;
|
||||
|
|
|
@ -5063,11 +5063,6 @@ bool os::check_heap(bool force) {
|
|||
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?
|
||||
bool os::dir_is_empty(const char* path) {
|
||||
DIR *dir = NULL;
|
||||
|
|
|
@ -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,
|
||||
size_t alignment_hint, bool exec) {
|
||||
int err = Solaris::commit_memory_impl(addr, bytes, exec);
|
||||
if (err == 0) {
|
||||
if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) {
|
||||
// If the large page size has been set and the VM
|
||||
// is using large pages, use the large page size
|
||||
// if it is smaller than the alignment hint. This is
|
||||
// a case where the VM wants to use a larger alignment size
|
||||
// for its own reasons but still want to use large pages
|
||||
// (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.
|
||||
if (err == 0 && UseLargePages && alignment_hint > 0) {
|
||||
assert(is_size_aligned(bytes, alignment_hint),
|
||||
err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint));
|
||||
|
||||
// The syscall memcntl requires an exact page size (see man memcntl for details).
|
||||
size_t page_size = page_size_for_alignment(alignment_hint);
|
||||
if (page_size > (size_t) vm_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,
|
||||
size_t align) {
|
||||
bool os::Solaris::is_valid_page_size(size_t bytes) {
|
||||
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
|
||||
// from addr, addr + bytes
|
||||
struct memcntl_mha mpss_struct;
|
||||
|
@ -4769,29 +4784,6 @@ void os::make_polling_page_readable(void) {
|
|||
|
||||
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?
|
||||
bool os::dir_is_empty(const char* path) {
|
||||
DIR *dir = NULL;
|
||||
|
|
|
@ -97,6 +97,8 @@ class Solaris {
|
|||
static meminfo_func_t _meminfo;
|
||||
|
||||
// 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 void init_thread_fpu_state(void);
|
||||
|
|
|
@ -39,7 +39,6 @@ class ciField : public ResourceObj {
|
|||
CI_PACKAGE_ACCESS
|
||||
friend class ciEnv;
|
||||
friend class ciInstanceKlass;
|
||||
friend class NonStaticFieldFiller;
|
||||
|
||||
private:
|
||||
ciFlags _flags;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
//
|
||||
// Loaded instance klass.
|
||||
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_instanceKlass()->is_loaded(), "must be at least loaded");
|
||||
|
@ -407,37 +407,6 @@ ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature,
|
|||
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) {
|
||||
return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
|
||||
|
|
|
@ -71,8 +71,6 @@ private:
|
|||
// Itsef: more than one implementors.
|
||||
ciInstanceKlass* _implementor;
|
||||
|
||||
GrowableArray<ciField*>* _non_static_fields;
|
||||
|
||||
protected:
|
||||
ciInstanceKlass(KlassHandle h_k);
|
||||
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_name(ciSymbol* name, ciSymbol* signature, bool is_static);
|
||||
|
||||
GrowableArray<ciField*>* non_static_fields();
|
||||
|
||||
// total number of nonstatic fields (including inherited):
|
||||
int nof_nonstatic_fields() {
|
||||
if (_nonstatic_fields == NULL)
|
||||
|
|
|
@ -1364,8 +1364,6 @@ void nmethod::invalidate_osr_method() {
|
|||
// Remove from list of active nmethods
|
||||
if (method() != NULL)
|
||||
method()->method_holder()->remove_osr_nmethod(this);
|
||||
// Set entry as invalid
|
||||
_entry_bci = InvalidOSREntryBci;
|
||||
}
|
||||
|
||||
void nmethod::log_state_change() const {
|
||||
|
|
|
@ -202,13 +202,6 @@ class nmethod : public CodeBlob {
|
|||
bool _oops_are_stale; // indicates that it's no longer safe to access oops section
|
||||
#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;
|
||||
|
||||
#if INCLUDE_RTM_OPT
|
||||
|
@ -431,6 +424,13 @@ class nmethod : public CodeBlob {
|
|||
address entry_point() const { return _entry_point; } // normal entry point
|
||||
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
|
||||
bool is_in_use() const { return _state == in_use; }
|
||||
bool is_alive() const { return _state == in_use || _state == not_entrant; }
|
||||
|
@ -759,7 +759,7 @@ public:
|
|||
// support for code generation
|
||||
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 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
|
||||
// redefine classes doesn't purge it.
|
||||
|
|
|
@ -4737,7 +4737,7 @@ void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes,
|
|||
}
|
||||
|
||||
bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
|
||||
const char* type = "";
|
||||
const char* type = r->get_type_str();
|
||||
HeapWord* bottom = r->bottom();
|
||||
HeapWord* end = r->end();
|
||||
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 strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size();
|
||||
|
||||
if (r->used() == 0) {
|
||||
type = "FREE";
|
||||
} else if (r->is_survivor()) {
|
||||
type = "SURV";
|
||||
} else if (r->is_young()) {
|
||||
type = "EDEN";
|
||||
} else if (r->startsHumongous()) {
|
||||
type = "HUMS";
|
||||
|
||||
if (r->startsHumongous()) {
|
||||
assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 &&
|
||||
_hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0,
|
||||
"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);
|
||||
end = bottom + HeapRegion::GrainWords;
|
||||
} else if (r->continuesHumongous()) {
|
||||
type = "HUMC";
|
||||
get_hum_bytes(&used_bytes, &capacity_bytes,
|
||||
&prev_live_bytes, &next_live_bytes);
|
||||
assert(end == bottom + HeapRegion::GrainWords, "invariant");
|
||||
} else {
|
||||
type = "OLD";
|
||||
}
|
||||
|
||||
_total_used_bytes += used_bytes;
|
||||
|
|
|
@ -211,7 +211,10 @@ void YoungList::empty_list(HeapRegion* list) {
|
|||
HeapRegion* next = list->get_next_young_region();
|
||||
list->set_next_young_region(NULL);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +373,7 @@ void YoungList::print() {
|
|||
if (curr == NULL)
|
||||
gclog_or_tty->print_cr(" empty");
|
||||
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),
|
||||
curr->prev_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
|
||||
for (uint i = first; i < first + obj_regions; ++i) {
|
||||
HeapRegion* hr = region_at(i);
|
||||
assert(hr->is_free(), "sanity");
|
||||
assert(hr->is_empty(), "sanity");
|
||||
assert(is_on_master_free_list(hr), "sanity");
|
||||
}
|
||||
|
@ -1225,21 +1229,21 @@ private:
|
|||
public:
|
||||
bool doHeapRegion(HeapRegion* hr) {
|
||||
assert(!hr->is_young(), "not expecting to find young regions");
|
||||
// We only generate output for non-empty regions.
|
||||
if (!hr->is_empty()) {
|
||||
if (!hr->isHumongous()) {
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::Old);
|
||||
} else if (hr->startsHumongous()) {
|
||||
if (hr->region_num() == 1) {
|
||||
// single humongous region
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous);
|
||||
} else {
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous);
|
||||
}
|
||||
if (hr->is_free()) {
|
||||
// We only generate output for non-empty regions.
|
||||
} else if (hr->startsHumongous()) {
|
||||
if (hr->region_num() == 1) {
|
||||
// single humongous region
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous);
|
||||
} else {
|
||||
assert(hr->continuesHumongous(), "only way to get here");
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous);
|
||||
_hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
@ -1477,9 +1481,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
|||
|
||||
// Discard all rset updates
|
||||
JavaThread::dirty_card_queue_set().abandon_logs();
|
||||
assert(!G1DeferredRSUpdate
|
||||
|| (G1DeferredRSUpdate &&
|
||||
(dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any");
|
||||
assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty");
|
||||
|
||||
_young_list->reset_sampled_info();
|
||||
// At this point there should be no regions in the
|
||||
|
@ -2090,15 +2092,13 @@ jint G1CollectedHeap::initialize() {
|
|||
concurrent_g1_refine()->red_zone(),
|
||||
Shared_DirtyCardQ_lock);
|
||||
|
||||
if (G1DeferredRSUpdate) {
|
||||
dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
|
||||
DirtyCardQ_CBL_mon,
|
||||
DirtyCardQ_FL_lock,
|
||||
-1, // never trigger processing
|
||||
-1, // no limit on length
|
||||
Shared_DirtyCardQ_lock,
|
||||
&JavaThread::dirty_card_queue_set());
|
||||
}
|
||||
dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
|
||||
DirtyCardQ_CBL_mon,
|
||||
DirtyCardQ_FL_lock,
|
||||
-1, // never trigger processing
|
||||
-1, // no limit on length
|
||||
Shared_DirtyCardQ_lock,
|
||||
&JavaThread::dirty_card_queue_set());
|
||||
|
||||
// Initialize the card queue set used to hold cards containing
|
||||
// references into the collection set.
|
||||
|
@ -2121,8 +2121,8 @@ jint G1CollectedHeap::initialize() {
|
|||
// 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
|
||||
// region will complain that it cannot support allocations without
|
||||
// BOT updates. So we'll tag the dummy region as young to avoid that.
|
||||
dummy_region->set_young();
|
||||
// BOT updates. So we'll tag the dummy region as eden to avoid that.
|
||||
dummy_region->set_eden();
|
||||
// Make sure it's full.
|
||||
dummy_region->set_top(dummy_region->end());
|
||||
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()) {
|
||||
HeapRegion* hr = g1_policy()->collection_set();
|
||||
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 = hr->next_in_collection_set();
|
||||
}
|
||||
|
@ -5393,7 +5385,6 @@ class G1RedirtyLoggedCardsTask : public AbstractGangTask {
|
|||
};
|
||||
|
||||
void G1CollectedHeap::redirty_logged_cards() {
|
||||
guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
|
||||
double redirty_logged_cards_start = os::elapsedTime();
|
||||
|
||||
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(oop* 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);
|
||||
if (obj == NULL || cset_state == G1CollectedHeap::InNeither) {
|
||||
if (cset_state == G1CollectedHeap::InNeither) {
|
||||
return;
|
||||
}
|
||||
if (cset_state == G1CollectedHeap::InCSet) {
|
||||
|
@ -6052,9 +6044,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
|||
// RSets.
|
||||
enqueue_discovered_references(n_workers);
|
||||
|
||||
if (G1DeferredRSUpdate) {
|
||||
redirty_logged_cards();
|
||||
}
|
||||
redirty_logged_cards();
|
||||
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
|
||||
}
|
||||
|
||||
|
@ -6062,7 +6052,7 @@ void G1CollectedHeap::free_region(HeapRegion* hr,
|
|||
FreeRegionList* free_list,
|
||||
bool par,
|
||||
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(_hrm.is_available(hr->hrm_index()), "region should be committed");
|
||||
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,
|
||||
// otherwise the information will be gone.
|
||||
uint last_index = hr->last_hc_index();
|
||||
hr->set_notHumongous();
|
||||
hr->clear_humongous();
|
||||
free_region(hr, free_list, par);
|
||||
|
||||
uint i = hr->hrm_index() + 1;
|
||||
while (i < last_index) {
|
||||
HeapRegion* curr_hr = region_at(i);
|
||||
assert(curr_hr->continuesHumongous(), "invariant");
|
||||
curr_hr->set_notHumongous();
|
||||
curr_hr->clear_humongous();
|
||||
free_region(curr_hr, free_list, par);
|
||||
i += 1;
|
||||
}
|
||||
|
@ -6407,9 +6397,9 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& e
|
|||
if (cur->is_young()) {
|
||||
cur->set_young_index_in_cset(-1);
|
||||
}
|
||||
cur->set_not_young();
|
||||
cur->set_evacuation_failed(false);
|
||||
// The region is now considered to be old.
|
||||
cur->set_old();
|
||||
_old_set.add(cur);
|
||||
evacuation_info.increment_collectionset_used_after(cur->used());
|
||||
}
|
||||
|
@ -6696,16 +6686,15 @@ public:
|
|||
TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { }
|
||||
|
||||
bool doHeapRegion(HeapRegion* r) {
|
||||
if (r->is_empty()) {
|
||||
// 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
|
||||
if (r->is_old()) {
|
||||
_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;
|
||||
}
|
||||
|
@ -6755,6 +6744,7 @@ public:
|
|||
|
||||
if (r->is_empty()) {
|
||||
// Add free regions to the free list
|
||||
r->set_free();
|
||||
_hrm->insert_into_free_list(r);
|
||||
} else if (!_free_list_only) {
|
||||
assert(!r->is_young(), "we should not come across young regions");
|
||||
|
@ -6762,7 +6752,11 @@ public:
|
|||
if (r->isHumongous()) {
|
||||
// We ignore humongous regions, we left the humongous set unchanged
|
||||
} 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);
|
||||
}
|
||||
_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,
|
||||
size_t allocated_bytes) {
|
||||
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);
|
||||
_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);
|
||||
check_bitmaps("Survivor Region Allocation", new_alloc_region);
|
||||
} else {
|
||||
new_alloc_region->set_old();
|
||||
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Old);
|
||||
check_bitmaps("Old Region Allocation", new_alloc_region);
|
||||
}
|
||||
|
@ -6999,9 +6994,11 @@ public:
|
|||
} 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()));
|
||||
_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()));
|
||||
_old_count.increment(1u, hr->capacity());
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) {
|
||||
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");
|
||||
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
|
||||
void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) {
|
||||
// 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
|
||||
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
|
||||
void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) {
|
||||
// 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
|
||||
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();
|
||||
while (hr != NULL) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -299,13 +299,13 @@ public:
|
|||
// Accessors
|
||||
|
||||
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->set_young_index_in_cset(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->set_young_index_in_cset(young_index_in_cset);
|
||||
}
|
||||
|
|
|
@ -176,15 +176,17 @@ public:
|
|||
class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
ConcurrentMark* _cm;
|
||||
OopsInHeapRegionClosure *_update_rset_cl;
|
||||
uint _worker_id;
|
||||
|
||||
DirtyCardQueue _dcq;
|
||||
UpdateRSetDeferred _update_rset_cl;
|
||||
|
||||
public:
|
||||
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
|
||||
OopsInHeapRegionClosure* update_rset_cl,
|
||||
uint worker_id) :
|
||||
_g1h(g1h), _update_rset_cl(update_rset_cl),
|
||||
_worker_id(worker_id), _cm(_g1h->concurrent_mark()) { }
|
||||
_g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
|
||||
_worker_id(worker_id), _cm(_g1h->concurrent_mark()) {
|
||||
}
|
||||
|
||||
bool doHeapRegion(HeapRegion *hr) {
|
||||
bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
|
||||
|
@ -195,7 +197,7 @@ public:
|
|||
|
||||
if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) {
|
||||
if (hr->evacuation_failed()) {
|
||||
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, _update_rset_cl,
|
||||
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
|
||||
during_initial_mark,
|
||||
during_conc_mark,
|
||||
_worker_id);
|
||||
|
@ -214,7 +216,7 @@ public:
|
|||
// whenever this might be required in the future.
|
||||
hr->rem_set()->reset_for_par_iteration();
|
||||
hr->reset_bot();
|
||||
_update_rset_cl->set_region(hr);
|
||||
_update_rset_cl.set_region(hr);
|
||||
hr->object_iterate(&rspc);
|
||||
|
||||
hr->rem_set()->clean_strong_code_roots(hr);
|
||||
|
@ -238,16 +240,7 @@ public:
|
|||
_g1h(g1h) { }
|
||||
|
||||
void work(uint worker_id) {
|
||||
UpdateRSetImmediate immediate_update(_g1h->g1_rem_set());
|
||||
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);
|
||||
RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id);
|
||||
|
||||
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
|
||||
_g1h->collection_set_iterate_from(hr, &rsfp_cl);
|
||||
|
|
|
@ -237,10 +237,8 @@ void G1GCPhaseTimes::note_gc_end() {
|
|||
_last_gc_worker_times_ms.verify();
|
||||
_last_gc_worker_other_times_ms.verify();
|
||||
|
||||
if (G1DeferredRSUpdate) {
|
||||
_last_redirty_logged_cards_time_ms.verify();
|
||||
_last_redirty_logged_cards_processed_cards.verify();
|
||||
}
|
||||
_last_redirty_logged_cards_time_ms.verify();
|
||||
_last_redirty_logged_cards_processed_cards.verify();
|
||||
}
|
||||
|
||||
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));
|
||||
print_stats(2, "Ref Proc", _cur_ref_proc_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);
|
||||
if (G1Log::finest()) {
|
||||
_last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
|
||||
_last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
|
||||
}
|
||||
print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
|
||||
if (G1Log::finest()) {
|
||||
_last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
|
||||
_last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
|
||||
}
|
||||
if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
|
||||
print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc_implementation/g1/g1HotCardCache.hpp"
|
||||
#include "gc_implementation/g1/g1RemSet.hpp"
|
||||
#include "gc_implementation/g1/heapRegion.hpp"
|
||||
#include "runtime/atomic.inline.hpp"
|
||||
|
||||
G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
|
||||
|
@ -136,7 +135,6 @@ void G1HotCardCache::drain(uint worker_i,
|
|||
}
|
||||
|
||||
void G1HotCardCache::reset_card_counts(HeapRegion* hr) {
|
||||
assert(!hr->isHumongous(), "Should have been cleared");
|
||||
_card_counts.clear_region(hr);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,20 +84,6 @@ class G1ParScanThreadState : public StackObj {
|
|||
DirtyCardQueue& dirty_card_queue() { return _dcq; }
|
||||
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:
|
||||
G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
|
||||
~G1ParScanThreadState();
|
||||
|
@ -124,8 +110,17 @@ class G1ParScanThreadState : public StackObj {
|
|||
_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:
|
||||
|
||||
inline HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz);
|
||||
|
|
|
@ -29,20 +29,6 @@
|
|||
#include "gc_implementation/g1/g1RemSet.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) {
|
||||
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.");
|
||||
|
|
|
@ -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
|
||||
// that were in the collection set - after the pause these regions
|
||||
// are wholly 'free' of live objects. In the event of an evacuation
|
||||
// failure the cards/buffers in this queue set are:
|
||||
// * passed to the DirtyCardQueueSet that is used to manage deferred
|
||||
// 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.
|
||||
// failure the cards/buffers in this queue set are passed to the
|
||||
// DirtyCardQueueSet that is used to manage RSet updates
|
||||
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
|
||||
|
||||
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() {
|
||||
cleanupHRRS();
|
||||
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
|
||||
_g1->set_refine_cte_cl_concurrency(false);
|
||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||
dcqs.concatenate_logs();
|
||||
|
@ -371,66 +366,6 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() {
|
|||
_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() {
|
||||
guarantee( _cards_scanned != NULL, "invariant" );
|
||||
_total_cards_scanned = 0;
|
||||
|
@ -451,25 +386,10 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() {
|
|||
double restore_remembered_set_start = os::elapsedTime();
|
||||
|
||||
// Restore remembered sets for the regions pointing into the collection set.
|
||||
if (G1DeferredRSUpdate) {
|
||||
// If deferred RS updates are enabled then we just need to transfer
|
||||
// the completed buffers from (a) the DirtyCardQueueSet used to hold
|
||||
// cards that contain references that point into the collection set
|
||||
// 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");
|
||||
}
|
||||
|
||||
// We just need to transfer the completed buffers from the DirtyCardQueueSet
|
||||
// used to hold cards that contain references that point into the collection set
|
||||
// to the DCQS used to hold the deferred RS updates.
|
||||
_g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
|
||||
_g1->g1_policy()->phase_times()->record_evac_fail_restore_remsets((os::elapsedTime() - restore_remembered_set_start) * 1000.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -193,18 +193,4 @@ public:
|
|||
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
|
||||
|
|
|
@ -79,13 +79,4 @@ inline void UpdateRSOopClosure::do_oop_work(T* p) {
|
|||
_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
|
||||
|
|
|
@ -259,14 +259,16 @@ public:
|
|||
size_t code_root_elems = hrrs->strong_code_roots_list_length();
|
||||
|
||||
RegionTypeCounter* current = NULL;
|
||||
if (r->is_young()) {
|
||||
if (r->is_free()) {
|
||||
current = &_free;
|
||||
} else if (r->is_young()) {
|
||||
current = &_young;
|
||||
} else if (r->isHumongous()) {
|
||||
current = &_humonguous;
|
||||
} else if (r->is_empty()) {
|
||||
current = &_free;
|
||||
} else {
|
||||
} else if (r->is_old()) {
|
||||
current = &_old;
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include "oops/oop.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#if INCLUDE_ALL_GCS
|
||||
|
||||
class DirtyCardQueueSet;
|
||||
class G1SATBCardTableLoggingModRefBS;
|
||||
|
||||
|
@ -180,7 +178,4 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS {
|
|||
void write_ref_array_work(MemRegion mr) { invalidate(mr); }
|
||||
};
|
||||
|
||||
|
||||
#endif // INCLUDE_ALL_GCS
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP
|
||||
|
|
|
@ -108,9 +108,6 @@
|
|||
develop(bool, G1RSBarrierRegionFilter, true, \
|
||||
"If true, generate region filtering code in RS barrier") \
|
||||
\
|
||||
develop(bool, G1DeferredRSUpdate, true, \
|
||||
"If true, use deferred RS updates") \
|
||||
\
|
||||
develop(bool, G1RSLogCheckCardTable, false, \
|
||||
"If true, verify that no dirty cards remain after RS log " \
|
||||
"processing.") \
|
||||
|
|
|
@ -211,8 +211,6 @@ void HeapRegion::reset_after_compaction() {
|
|||
}
|
||||
|
||||
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,
|
||||
"we should have already filtered out humongous regions");
|
||||
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);
|
||||
uninstall_surv_rate_group();
|
||||
set_young_type(NotYoung);
|
||||
set_free();
|
||||
reset_pre_dummy_top();
|
||||
|
||||
if (!par) {
|
||||
|
@ -273,7 +271,7 @@ void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
|
|||
assert(top() == bottom(), "should be empty");
|
||||
assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
|
||||
|
||||
_humongous_type = StartsHumongous;
|
||||
_type.set_starts_humongous();
|
||||
_humongous_start_region = this;
|
||||
|
||||
set_end(new_end);
|
||||
|
@ -287,11 +285,11 @@ void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
|
|||
assert(top() == bottom(), "should be empty");
|
||||
assert(first_hr->startsHumongous(), "pre-condition");
|
||||
|
||||
_humongous_type = ContinuesHumongous;
|
||||
_type.set_continues_humongous();
|
||||
_humongous_start_region = first_hr;
|
||||
}
|
||||
|
||||
void HeapRegion::set_notHumongous() {
|
||||
void HeapRegion::clear_humongous() {
|
||||
assert(isHumongous(), "pre-condition");
|
||||
|
||||
if (startsHumongous()) {
|
||||
|
@ -307,7 +305,6 @@ void HeapRegion::set_notHumongous() {
|
|||
}
|
||||
|
||||
assert(capacity() == HeapRegion::GrainBytes, "pre-condition");
|
||||
_humongous_type = NotHumongous;
|
||||
_humongous_start_region = NULL;
|
||||
}
|
||||
|
||||
|
@ -327,12 +324,12 @@ HeapRegion::HeapRegion(uint hrm_index,
|
|||
MemRegion mr) :
|
||||
G1OffsetTableContigSpace(sharedOffsetArray, mr),
|
||||
_hrm_index(hrm_index),
|
||||
_humongous_type(NotHumongous), _humongous_start_region(NULL),
|
||||
_humongous_start_region(NULL),
|
||||
_in_collection_set(false),
|
||||
_next_in_special_set(NULL), _orig_end(NULL),
|
||||
_claimed(InitialClaimValue), _evacuation_failed(false),
|
||||
_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),
|
||||
#ifdef ASSERT
|
||||
_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_on(outputStream* st) const {
|
||||
if (isHumongous()) {
|
||||
if (startsHumongous())
|
||||
st->print(" HS");
|
||||
else
|
||||
st->print(" HC");
|
||||
} else {
|
||||
st->print(" ");
|
||||
}
|
||||
st->print(" %2s", get_short_type_str());
|
||||
if (in_collection_set())
|
||||
st->print(" CS");
|
||||
else
|
||||
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(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT,
|
||||
prev_top_at_mark_start(), next_top_at_mark_start());
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "gc_implementation/g1/g1BlockOffsetTable.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/shared/ageTable.hpp"
|
||||
#include "gc_implementation/shared/spaceDecorator.hpp"
|
||||
|
@ -34,8 +35,6 @@
|
|||
#include "memory/watermark.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#if INCLUDE_ALL_GCS
|
||||
|
||||
// A HeapRegion is the smallest piece of a G1CollectedHeap that
|
||||
// can be collected independently.
|
||||
|
||||
|
@ -55,10 +54,7 @@ class nmethod;
|
|||
#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
|
||||
#define HR_FORMAT_PARAMS(_hr_) \
|
||||
(_hr_)->hrm_index(), \
|
||||
(_hr_)->is_survivor() ? "S" : (_hr_)->is_young() ? "E" : \
|
||||
(_hr_)->startsHumongous() ? "HS" : \
|
||||
(_hr_)->continuesHumongous() ? "HC" : \
|
||||
!(_hr_)->is_empty() ? "O" : "F", \
|
||||
(_hr_)->get_short_type_str(), \
|
||||
p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end())
|
||||
|
||||
// sentinel value for hrm_index
|
||||
|
@ -215,12 +211,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||
friend class VMStructs;
|
||||
private:
|
||||
|
||||
enum HumongousType {
|
||||
NotHumongous = 0,
|
||||
StartsHumongous,
|
||||
ContinuesHumongous
|
||||
};
|
||||
|
||||
// The remembered set for this region.
|
||||
// (Might want to make this "inline" later, to avoid some alloc failure
|
||||
// issues.)
|
||||
|
@ -232,7 +222,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||
// The index of this region in the heap region sequence.
|
||||
uint _hrm_index;
|
||||
|
||||
HumongousType _humongous_type;
|
||||
HeapRegionType _type;
|
||||
|
||||
// For a humongous region, region in which it starts.
|
||||
HeapRegion* _humongous_start_region;
|
||||
// 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.
|
||||
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;
|
||||
SurvRateGroup* _surv_rate_group;
|
||||
int _age_index;
|
||||
|
@ -305,12 +289,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||
_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
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
bool isHumongous() const { return _humongous_type != NotHumongous; }
|
||||
bool startsHumongous() const { return _humongous_type == StartsHumongous; }
|
||||
bool continuesHumongous() const { return _humongous_type == ContinuesHumongous; }
|
||||
const char* get_type_str() const { return _type.get_str(); }
|
||||
const char* get_short_type_str() const { return _type.get_short_str(); }
|
||||
|
||||
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.
|
||||
HeapRegion* humongous_start_region() const {
|
||||
return _humongous_start_region;
|
||||
|
@ -496,7 +486,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||
void set_continuesHumongous(HeapRegion* first_hr);
|
||||
|
||||
// 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.
|
||||
HeapRegionRemSet* rem_set() const {
|
||||
|
@ -623,9 +613,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||
void calc_gc_efficiency(void);
|
||||
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; }
|
||||
void set_young_index_in_cset(int index) {
|
||||
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
|
||||
// mark performed by the collector. This returns true iff the object
|
||||
|
@ -809,6 +798,4 @@ class HeapRegionClosure : public StackObj {
|
|||
bool complete() { return _complete; }
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ALL_GCS
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
|
||||
|
|
|
@ -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->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->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()));
|
||||
}
|
||||
#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(" Region Assumptions");
|
||||
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(" length : %14u", length());
|
||||
out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" 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),
|
||||
_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()
|
||||
{ }
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
|
|||
friend class VMStructs;
|
||||
private:
|
||||
bool _is_humongous;
|
||||
bool _is_empty;
|
||||
bool _is_free;
|
||||
HRSMtSafeChecker* _mt_safety_checker;
|
||||
|
||||
protected:
|
||||
|
@ -102,9 +102,9 @@ protected:
|
|||
// not. Only used during verification.
|
||||
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.
|
||||
bool regions_empty() { return _is_empty; }
|
||||
bool regions_free() { return _is_free; }
|
||||
|
||||
void check_mt_safety() {
|
||||
if (_mt_safety_checker != NULL) {
|
||||
|
@ -114,7 +114,7 @@ protected:
|
|||
|
||||
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:
|
||||
const char* name() { return _name; }
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
do { \
|
||||
assert(((_set1_)->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", \
|
||||
(_set1_)->name(), (_set2_)->name())); \
|
||||
} while (0)
|
||||
|
@ -184,7 +184,7 @@ public:
|
|||
class HeapRegionSet : public HeapRegionSetBase {
|
||||
public:
|
||||
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) {
|
||||
_count.decrement(removed.length(), removed.capacity());
|
||||
|
|
69
hotspot/src/share/vm/gc_implementation/g1/heapRegionType.cpp
Normal file
69
hotspot/src/share/vm/gc_implementation/g1/heapRegionType.cpp
Normal 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;
|
||||
}
|
134
hotspot/src/share/vm/gc_implementation/g1/heapRegionType.hpp
Normal file
134
hotspot/src/share/vm/gc_implementation/g1/heapRegionType.hpp
Normal 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
|
|
@ -66,9 +66,10 @@ void GenerationSizer::initialize_flags() {
|
|||
|
||||
void GenerationSizer::initialize_size_info() {
|
||||
trace_gen_sizes("ps heap raw");
|
||||
const size_t page_sz = os::page_size_for_region(_min_heap_byte_size,
|
||||
_max_heap_byte_size,
|
||||
8);
|
||||
const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
|
||||
const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
|
||||
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?
|
||||
assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
|
||||
|
|
|
@ -41,7 +41,7 @@ ParMarkBitMap::initialize(MemRegion covered_region)
|
|||
|
||||
const size_t words = bits / BitsPerWord;
|
||||
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();
|
||||
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ PSVirtualSpace*
|
|||
ParallelCompactData::create_vspace(size_t count, size_t 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();
|
||||
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@
|
|||
if (do_OSR) { \
|
||||
nmethod* osr_nmethod; \
|
||||
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; \
|
||||
/* Call OSR migration with last java frame only, no checks. */ \
|
||||
CALL_VM_NAKED_LJF(buf=SharedRuntime::OSR_migration_begin(THREAD)); \
|
||||
|
|
|
@ -98,9 +98,13 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size,
|
|||
_log2_segment_size = exact_log2(segment_size);
|
||||
|
||||
// Reserve and initialize space for _memory.
|
||||
const size_t page_size = os::can_execute_large_page_memory() ?
|
||||
os::page_size_for_region(committed_size, reserved_size, 8) :
|
||||
os::vm_page_size();
|
||||
size_t page_size = os::vm_page_size();
|
||||
if (os::can_execute_large_page_memory()) {
|
||||
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 r_align = MAX2(page_size, granularity);
|
||||
const size_t r_size = align_size_up(reserved_size, r_align);
|
||||
|
|
|
@ -3848,6 +3848,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
|
|||
unit_test_function_call
|
||||
|
||||
// Forward declaration
|
||||
void TestOS_test();
|
||||
void TestReservedSpace_test();
|
||||
void TestReserveMemorySpecial_test();
|
||||
void TestVirtualSpace_test();
|
||||
|
@ -3871,6 +3872,7 @@ void FreeRegionList_test();
|
|||
void execute_internal_vm_tests() {
|
||||
if (ExecuteInternalVMTests) {
|
||||
tty->print_cr("Running internal VM tests");
|
||||
run_unit_test(TestOS_test());
|
||||
run_unit_test(TestReservedSpace_test());
|
||||
run_unit_test(TestReserveMemorySpecial_test());
|
||||
run_unit_test(TestVirtualSpace_test());
|
||||
|
|
|
@ -1406,24 +1406,15 @@ bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) {
|
|||
return (sp > (stack_limit + reserved_area));
|
||||
}
|
||||
|
||||
size_t os::page_size_for_region(size_t region_min_size, size_t region_max_size,
|
||||
uint min_pages)
|
||||
{
|
||||
size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
|
||||
assert(min_pages > 0, "sanity");
|
||||
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) {
|
||||
const size_t sz = _page_sizes[i];
|
||||
const size_t mask = sz - 1;
|
||||
if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0) {
|
||||
// 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;
|
||||
for (size_t i = 0; _page_sizes[i] != 0; ++i) {
|
||||
const size_t page_size = _page_sizes[i];
|
||||
if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
|
||||
return page_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1660,3 +1651,63 @@ os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::Stat
|
|||
return result;
|
||||
}
|
||||
#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
|
||||
|
|
|
@ -266,19 +266,11 @@ class os: AllStatic {
|
|||
// Return the default page size.
|
||||
static int vm_page_size();
|
||||
|
||||
// Return the page size to use for a region of memory. The min_pages argument
|
||||
// is a hint intended to limit fragmentation; it says the returned page size
|
||||
// should be <= region_max_size / min_pages. Because min_pages is a hint,
|
||||
// this routine may return a size larger than region_max_size / 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);
|
||||
// Returns the page size to use for a region of memory.
|
||||
// region_size / min_pages will always be greater than or equal to the
|
||||
// returned value.
|
||||
static size_t page_size_for_region(size_t region_size, size_t min_pages);
|
||||
|
||||
// Return the largest page size that can be used
|
||||
static size_t max_page_size() {
|
||||
// The _page_sizes array is sorted in descending order.
|
||||
|
|
|
@ -38,7 +38,7 @@ ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
|
|||
}
|
||||
|
||||
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();
|
||||
// Don't force the alignment to be large page aligned,
|
||||
// since that will waste memory.
|
||||
|
@ -357,7 +357,7 @@ VirtualSpace::VirtualSpace() {
|
|||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -992,7 +992,7 @@ class TestVirtualSpace : AllStatic {
|
|||
case Disable:
|
||||
return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2518,7 +2518,6 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
|||
/*********************************************/ \
|
||||
\
|
||||
declare_constant(InvocationEntryBci) \
|
||||
declare_constant(InvalidOSREntryBci) \
|
||||
\
|
||||
/***************/ \
|
||||
/* OopMapValue */ \
|
||||
|
|
|
@ -66,6 +66,9 @@
|
|||
#ifndef ATTRIBUTE_PRINTF
|
||||
#define ATTRIBUTE_PRINTF(fmt, vargs)
|
||||
#endif
|
||||
#ifndef ATTRIBUTE_SCANF
|
||||
#define ATTRIBUTE_SCANF(fmt, vargs)
|
||||
#endif
|
||||
|
||||
|
||||
#include "utilities/macros.hpp"
|
||||
|
@ -882,8 +885,7 @@ enum JavaThreadState {
|
|||
|
||||
// Handy constants for deciding which compiler mode to use.
|
||||
enum MethodCompilation {
|
||||
InvocationEntryBci = -1, // i.e., not a on-stack replacement compilation
|
||||
InvalidOSREntryBci = -2
|
||||
InvocationEntryBci = -1 // i.e., not a on-stack replacement compilation
|
||||
};
|
||||
|
||||
// Enumeration to distinguish tiers of compilation
|
||||
|
|
|
@ -271,15 +271,16 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
|
|||
#define PRAGMA_IMPLEMENTATION #pragma implementation
|
||||
#define VALUE_OBJ_CLASS_SPEC
|
||||
|
||||
#ifndef ATTRIBUTE_PRINTF
|
||||
// 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
|
||||
// these warnings for older versions of GCC, we simply don't decorate our printf-style
|
||||
// functions with __attribute__(format) in that case.
|
||||
#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ > 4)
|
||||
#ifndef ATTRIBUTE_PRINTF
|
||||
#define ATTRIBUTE_PRINTF(fmt,vargs) __attribute__((format(printf, fmt, vargs)))
|
||||
#else
|
||||
#define ATTRIBUTE_PRINTF(fmt,vargs)
|
||||
#endif
|
||||
#ifndef ATTRIBUTE_SCANF
|
||||
#define ATTRIBUTE_SCANF(fmt,vargs) __attribute__((format(scanf, fmt, vargs)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
||||
// 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
|
||||
#define PRAGMA_INTERFACE
|
||||
#define PRAGMA_IMPLEMENTATION
|
||||
|
|
|
@ -21,39 +21,32 @@
|
|||
* questions.
|
||||
*/
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
/*
|
||||
* @test TestRangeCheck
|
||||
* @bug 8054883
|
||||
* @summary Tests that range check is not skipped
|
||||
*/
|
||||
|
||||
class AllocateBeyondMetaspaceSize {
|
||||
public static Object dummy;
|
||||
|
||||
public static void main(String [] args) {
|
||||
if (args.length != 2) {
|
||||
throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>");
|
||||
public class TestRangeCheck {
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
test();
|
||||
throw new AssertionError("Expected ArrayIndexOutOfBoundsException was not thrown");
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println("Expected ArrayIndexOutOfBoundsException was thrown");
|
||||
}
|
||||
}
|
||||
|
||||
long metaspaceSize = Long.parseLong(args[0]);
|
||||
long youngGenSize = Long.parseLong(args[1]);
|
||||
private static void test() {
|
||||
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) {
|
||||
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||
|
||||
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];
|
||||
if (result > 0 && arr[~result] > 0) {
|
||||
arr[~result] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* @ignore 8049864
|
||||
* @test TestParallelHeapSizeFlags
|
||||
* @key gc
|
||||
* @bug 8006088
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* @key gc
|
||||
* @bug 8049831
|
||||
* @library /testlibrary /testlibrary/whitebox
|
||||
* @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize
|
||||
* @build TestCMSClassUnloadingEnabledHWM
|
||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run driver TestCMSClassUnloadingEnabledHWM
|
||||
|
@ -35,9 +35,11 @@
|
|||
|
||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||
import com.oracle.java.testlibrary.ProcessTools;
|
||||
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class TestCMSClassUnloadingEnabledHWM {
|
||||
private static long MetaspaceSize = 32 * 1024 * 1024;
|
||||
|
@ -48,15 +50,18 @@ public class TestCMSClassUnloadingEnabledHWM {
|
|||
"-Xbootclasspath/a:.",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-Xmx128m",
|
||||
"-XX:CMSMaxAbortablePrecleanTime=1",
|
||||
"-XX:CMSWaitDuration=50",
|
||||
"-XX:MetaspaceSize=" + MetaspaceSize,
|
||||
"-Xmn" + YoungGenSize,
|
||||
"-XX:+UseConcMarkSweepGC",
|
||||
"-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled",
|
||||
"-XX:+PrintHeapAtGC",
|
||||
"-XX:+PrintGCDetails",
|
||||
"AllocateBeyondMetaspaceSize",
|
||||
"" + MetaspaceSize,
|
||||
"" + YoungGenSize);
|
||||
"-XX:+PrintGCTimeStamps",
|
||||
TestCMSClassUnloadingEnabledHWM.AllocateBeyondMetaspaceSize.class.getName(),
|
||||
"" + MetaspaceSize);
|
||||
return new OutputAnalyzer(pb.start());
|
||||
}
|
||||
|
||||
|
@ -88,5 +93,37 @@ public class TestCMSClassUnloadingEnabledHWM {
|
|||
testWithCMSClassUnloading();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* @key gc
|
||||
* @bug 8049831
|
||||
* @library /testlibrary /testlibrary/whitebox
|
||||
* @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize
|
||||
* @build TestG1ClassUnloadingHWM
|
||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run driver TestG1ClassUnloadingHWM
|
||||
|
@ -35,9 +35,9 @@
|
|||
|
||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||
import com.oracle.java.testlibrary.ProcessTools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class TestG1ClassUnloadingHWM {
|
||||
private static long MetaspaceSize = 32 * 1024 * 1024;
|
||||
|
@ -54,7 +54,7 @@ public class TestG1ClassUnloadingHWM {
|
|||
"-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark",
|
||||
"-XX:+PrintHeapAtGC",
|
||||
"-XX:+PrintGCDetails",
|
||||
"AllocateBeyondMetaspaceSize",
|
||||
TestG1ClassUnloadingHWM.AllocateBeyondMetaspaceSize.class.getName(),
|
||||
"" + MetaspaceSize,
|
||||
"" + YoungGenSize);
|
||||
return new OutputAnalyzer(pb.start());
|
||||
|
@ -88,5 +88,36 @@ public class TestG1ClassUnloadingHWM {
|
|||
testWithG1ClassUnloading();
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
* @bug 8036025 8056043
|
||||
* @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects
|
||||
* @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;
|
||||
|
@ -41,12 +41,24 @@ public class TestHumongousShrinkHeap {
|
|||
public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
|
||||
public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
|
||||
|
||||
private static final ArrayList<ArrayList<byte[]>> garbage = new ArrayList<>();
|
||||
private static final int PAGE_SIZE = 1024 * 1024; // 1M
|
||||
private static final int PAGES_NUM = 5;
|
||||
private static final List<List<byte[]>> garbage = new ArrayList();
|
||||
private static final int REGION_SIZE = 1024 * 1024; // 1M
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -54,8 +66,8 @@ public class TestHumongousShrinkHeap {
|
|||
System.gc();
|
||||
MemoryUsagePrinter.printMemoryUsage("init");
|
||||
|
||||
eat();
|
||||
MemoryUsagePrinter.printMemoryUsage("eaten");
|
||||
allocate();
|
||||
MemoryUsagePrinter.printMemoryUsage("allocated");
|
||||
MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
||||
|
||||
free();
|
||||
|
@ -72,15 +84,12 @@ public class TestHumongousShrinkHeap {
|
|||
));
|
||||
}
|
||||
|
||||
private void eat() {
|
||||
int HumongousObjectSize = Math.round(.9f * PAGE_SIZE);
|
||||
System.out.println("Will allocate objects of size=" +
|
||||
MemoryUsagePrinter.humanReadableByteCount(HumongousObjectSize, true));
|
||||
private void allocate() {
|
||||
|
||||
for (int i = 0; i < PAGES_NUM; i++) {
|
||||
ArrayList<byte[]> stuff = new ArrayList<>();
|
||||
eatList(stuff, 100, HumongousObjectSize);
|
||||
MemoryUsagePrinter.printMemoryUsage("eat #" + i);
|
||||
for (int i = 0; i < LISTS_COUNT; i++) {
|
||||
List<byte[]> stuff = new ArrayList();
|
||||
allocateList(stuff, HUMON_COUNT, HUMON_SIZE);
|
||||
MemoryUsagePrinter.printMemoryUsage("allocate #" + (i+1));
|
||||
garbage.add(stuff);
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +99,12 @@ public class TestHumongousShrinkHeap {
|
|||
garbage.subList(0, garbage.size() - 1).clear();
|
||||
|
||||
// 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();
|
||||
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++) {
|
||||
garbage.add(new byte[size]);
|
||||
}
|
||||
|
@ -122,9 +131,9 @@ class MemoryUsagePrinter {
|
|||
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(), true),
|
||||
humanReadableByteCount(memusage.getUsed(), true),
|
||||
humanReadableByteCount(memusage.getCommitted(), true),
|
||||
humanReadableByteCount(memusage.getInit(), false),
|
||||
humanReadableByteCount(memusage.getUsed(), false),
|
||||
humanReadableByteCount(memusage.getCommitted(), false),
|
||||
freeratio * 100
|
||||
);
|
||||
}
|
||||
|
|
188
hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java
Normal file
188
hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -273,3 +273,4 @@ a5aea8318ae4a9c2105228568688875142d70344 jdk9-b26
|
|||
dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28
|
||||
30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29
|
||||
d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30
|
||||
292317ebc7dbaca6b3965f0bc7b38a2cee733b7a jdk9-b31
|
||||
|
|
|
@ -276,3 +276,4 @@ dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27
|
|||
5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28
|
||||
3d1a4bfb6abbf5011ba6d8896301ee3b6ef3ba72 jdk9-b29
|
||||
e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30
|
||||
7af228ae847f3c02aaafb7b01cdbb3bdc2e89e77 jdk9-b31
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* 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.tools.internal.ws.resources.WscompileMessages;
|
||||
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 javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceFeature;
|
||||
import javax.xml.namespace.QName;
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
|
@ -59,7 +56,7 @@ public final class Invoker {
|
|||
/**
|
||||
* The list of package prefixes we want the
|
||||
* {@link MaskingClassLoader} to prevent the parent
|
||||
* classLoader from loading
|
||||
* class loader from loading
|
||||
*/
|
||||
static final String[] maskedPackages = new String[]{
|
||||
"com.sun.istack.internal.tools.",
|
||||
|
@ -130,24 +127,6 @@ public final class Invoker {
|
|||
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);
|
||||
|
@ -158,8 +137,6 @@ public final class Invoker {
|
|||
Method runMethod = compileTool.getMethod("run",String[].class);
|
||||
boolean r = (Boolean)runMethod.invoke(tool,new Object[]{args});
|
||||
return r ? 0 : 1;
|
||||
} catch (ToolsJarNotFoundException e) {
|
||||
System.err.println(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw e.getCause();
|
||||
} catch(ClassNotFoundException e){
|
||||
|
@ -167,8 +144,6 @@ public final class Invoker {
|
|||
}finally {
|
||||
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,
|
||||
* and then return a classloader that can RI classes, which can see all those APIs and tools.jar.
|
||||
* Creates a class loader that can load JAXB/WS 2.2 API,
|
||||
* 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);
|
||||
if(urls.length==0)
|
||||
|
@ -223,7 +198,7 @@ public final class Invoker {
|
|||
// and everything that depends on them inside
|
||||
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);
|
||||
|
||||
// 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>();
|
||||
|
||||
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");
|
||||
if(res==null)
|
||||
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));
|
||||
}
|
||||
|
||||
findToolsJar(cl, urls);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 {
|
||||
/**
|
||||
* CLI entry point. Use {@link Invoker} to
|
||||
* load tools.jar
|
||||
* CLI entry point. Use {@link Invoker} to load proper API version
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
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
|
||||
* also doesn't play with classloaders. It's the caller's
|
||||
* 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
|
||||
* 0 if the tool runs successfully.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 {
|
||||
/**
|
||||
* CLI entry point. Use {@link Invoker} to
|
||||
* load tools.jar
|
||||
* CLI entry point. Use {@link Invoker} to load proper API version
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
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
|
||||
* also doesn't play with classloaders. It's the caller's
|
||||
* 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
|
||||
* 0 if the tool runs successfully.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 Localizer localizer = new Localizer();
|
||||
|
||||
public static Localizable localizableJAVACOMPILER_CLASSPATH_ERROR(Object arg0) {
|
||||
return messageFactory.getMessage("javacompiler.classpath.error", arg0);
|
||||
public static Localizable localizableNO_JAVACOMPILER_ERROR() {
|
||||
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) {
|
||||
return localizer.localize(localizableJAVACOMPILER_CLASSPATH_ERROR(arg0));
|
||||
}
|
||||
|
||||
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));
|
||||
public static String NO_JAVACOMPILER_ERROR() {
|
||||
return localizer.localize(localizableNO_JAVACOMPILER_ERROR());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -26,6 +26,4 @@
|
|||
#
|
||||
# Generic Messages
|
||||
#
|
||||
javacompiler.classpath.error={0} is not available in the classpath, requires Sun's JDK version 5.0 or latter.
|
||||
javacompiler.nosuchmethod.error=There is no such method {0} available, requires Sun's JDK version 5.0 or latter.
|
||||
javacompiler.error=error : {0}.
|
||||
no.javacompiler.error=No system compiler found, check your jdk.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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.tools.internal.ws.resources.JavacompilerMessages;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
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.URL;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* A helper class to invoke javac.
|
||||
|
@ -61,34 +60,17 @@ class JavaCompilerHelper{
|
|||
}
|
||||
|
||||
static boolean compile(String[] args, OutputStream out, ErrorReceiver receiver){
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
/* try to use the new compiler */
|
||||
Class comSunToolsJavacMainClass =
|
||||
cl.loadClass("com.sun.tools.javac.Main");
|
||||
try {
|
||||
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);
|
||||
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
|
||||
if (comp == null) {
|
||||
receiver.error(JavacompilerMessages.NO_JAVACOMPILER_ERROR(), null);
|
||||
return false;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
receiver.error(JavacompilerMessages.JAVACOMPILER_CLASSPATH_ERROR("com.sun.tools.javac.Main"), e);
|
||||
return 0 == comp.run(null, out, out, args);
|
||||
} catch (SecurityException e) {
|
||||
receiver.error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final Class[] compileMethodSignature = {String[].class, PrintWriter.class};
|
||||
}
|
||||
|
|
|
@ -273,3 +273,4 @@ f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27
|
|||
1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28
|
||||
2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29
|
||||
8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30
|
||||
71e99dae28f9791287b88d46e16a266b564f22be jdk9-b31
|
||||
|
|
|
@ -220,7 +220,6 @@ RT_JAR_EXCLUDES += \
|
|||
sun/tools/serialver \
|
||||
sun/tools/tree \
|
||||
sun/tools/util \
|
||||
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
|
||||
sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \
|
||||
META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \
|
||||
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, \
|
||||
$(CLDR_METAINF_SERVICES), \
|
||||
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \
|
||||
$(JDK_OUTPUTDIR)/modules/java.base \
|
||||
$(CLDR_SERVICES_DIR), \
|
||||
SUFFIXES := .class, \
|
||||
INCLUDES := sun/text/resources/cldr \
|
||||
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
|
||||
sun/util/resources/cldr, \
|
||||
EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \
|
||||
JAR := $(CLDRDATA_JAR_DST), \
|
||||
|
|
|
@ -29,14 +29,13 @@ include GensrcCommon.gmk
|
|||
include GensrcProperties.gmk
|
||||
GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES)
|
||||
|
||||
include GensrcLocaleDataMetaInfo.gmk
|
||||
include GensrcLocaleData.gmk
|
||||
include GensrcCharacterData.gmk
|
||||
include GensrcMisc.gmk
|
||||
include GensrcCharsetMapping.gmk
|
||||
include GensrcCharsetCoder.gmk
|
||||
include GensrcBuffer.gmk
|
||||
include GensrcExceptions.gmk
|
||||
include GensrcCLDR.gmk
|
||||
|
||||
java.base: $(GENSRC_JAVA_BASE)
|
||||
|
||||
|
|
38
jdk/make/gensrc/Gensrc-jdk.localedata.gmk
Normal file
38
jdk/make/gensrc/Gensrc-jdk.localedata.gmk
Normal 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
|
|
@ -27,9 +27,8 @@ CLDRVERSION := 21.0.1
|
|||
CLDRSRCDIR := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/cldr/resources/$(subst .,_,$(CLDRVERSION))
|
||||
|
||||
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) \
|
||||
$(wildcard $(CLDRSRCDIR)/common/main/*.xml) \
|
||||
|
@ -37,16 +36,6 @@ $(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \
|
|||
$(BUILD_TOOLS_JDK)
|
||||
$(MKDIR) -p $(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_JAVA_BASE += $(GENSRC_CLDR)
|
||||
GENSRC_JDK_LOCALEDATA += $(GENSRC_CLDR)
|
||||
|
|
|
@ -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
|
||||
$(SED) $(SED_NONENARGS) $< > $@
|
||||
|
||||
GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \
|
||||
$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
|
||||
GENSRC_BASELOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.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)
|
||||
NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@
|
||||
|
||||
GENSRC_LOCALEDATAMETAINFO += $(GENSRC_CRBC_DST)
|
||||
GENSRC_JAVA_BASE += $(GENSRC_LOCALEDATAMETAINFO)
|
||||
GENSRC_BASELOCALEDATA += $(GENSRC_CRBC_DST)
|
||||
GENSRC_JAVA_BASE += $(GENSRC_BASELOCALEDATA)
|
||||
GENSRC_JDK_LOCALEDATA += $(GENSRC_LOCALEDATA)
|
||||
|
||||
################################################################################
|
|
@ -217,10 +217,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
|
|||
-I$(JDK_OUTPUTDIR)/gensrc_headers/java.base \
|
||||
#
|
||||
LIBAWT_EXFILES += \
|
||||
sun/java2d/d3d/D3DPipeline.cpp \
|
||||
sun/java2d/d3d/D3DShaderGen.c \
|
||||
sun/awt/image/cvutils/img_colors.c \
|
||||
sun/windows/WBufferStrategy.cpp \
|
||||
#
|
||||
|
||||
LIBAWT_LANG := C++
|
||||
|
|
|
@ -143,8 +143,9 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||
|
||||
@Override
|
||||
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException {
|
||||
String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + File.separator
|
||||
+ "cldr" + File.separator;
|
||||
String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" +
|
||||
File.separator + "resources" + File.separator + "cldr" + File.separator +
|
||||
"provider" + File.separator ;
|
||||
File dir = new File(dirName);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
|
@ -158,7 +159,7 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||
try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
|
||||
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 sun.util.locale.provider.LocaleProviderAdapter;\n"
|
||||
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
|
||||
|
|
|
@ -25,29 +25,17 @@
|
|||
|
||||
package build.tools.module;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
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.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
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;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* GenJdepsModulesXml augments the input modules.xml file(s)
|
||||
|
@ -97,14 +85,14 @@ public final class GenJdepsModulesXml {
|
|||
Set<Module> modules = new HashSet<>();
|
||||
for (; i < args.length; i++) {
|
||||
Path p = Paths.get(args[i]);
|
||||
try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
|
||||
Set<Module> mods = gentool.load(in);
|
||||
modules.addAll(mods);
|
||||
}
|
||||
modules.addAll(ModulesXmlReader.readModules(p)
|
||||
.stream()
|
||||
.map(gentool::buildIncludes)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
Files.createDirectories(outfile.getParent());
|
||||
gentool.writeXML(modules, outfile);
|
||||
ModulesXmlWriter.writeModules(modules, outfile);
|
||||
}
|
||||
|
||||
final Path modulepath;
|
||||
|
@ -112,228 +100,21 @@ public final class GenJdepsModulesXml {
|
|||
this.modulepath = modulepath;
|
||||
}
|
||||
|
||||
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 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) {
|
||||
private static String packageName(Path p) {
|
||||
return packageName(p.toString().replace(File.separatorChar, '/'));
|
||||
}
|
||||
private String packageName(String name) {
|
||||
private static String packageName(String name) {
|
||||
int i = name.lastIndexOf('/');
|
||||
return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
|
||||
}
|
||||
|
||||
private boolean includes(String name) {
|
||||
return name.endsWith(".class") && !name.equals("module-info.class");
|
||||
private static boolean includes(String name) {
|
||||
return name.endsWith(".class");
|
||||
}
|
||||
|
||||
public void buildIncludes(Module.Builder mb, String modulename) throws IOException {
|
||||
Path mclasses = modulepath.resolve(modulename);
|
||||
public Module buildIncludes(Module module) {
|
||||
Module.Builder mb = new Module.Builder(module);
|
||||
Path mclasses = modulepath.resolve(module.name());
|
||||
try {
|
||||
Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
|
||||
-> includes(p.getFileName().toString()))
|
||||
|
@ -341,145 +122,9 @@ public final class GenJdepsModulesXml {
|
|||
.forEach(mb::include);
|
||||
} catch (NoSuchFileException e) {
|
||||
// aggregate module may not have class
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return mb.build();
|
||||
}
|
||||
}
|
||||
|
|
159
jdk/make/src/classes/build/tools/module/GenModulesList.java
Normal file
159
jdk/make/src/classes/build/tools/module/GenModulesList.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
178
jdk/make/src/classes/build/tools/module/Module.java
Normal file
178
jdk/make/src/classes/build/tools/module/Module.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
165
jdk/make/src/classes/build/tools/module/ModulesXmlReader.java
Normal file
165
jdk/make/src/classes/build/tools/module/ModulesXmlReader.java
Normal 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);
|
||||
}
|
||||
}
|
179
jdk/make/src/classes/build/tools/module/ModulesXmlWriter.java
Normal file
179
jdk/make/src/classes/build/tools/module/ModulesXmlWriter.java
Normal 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();
|
||||
}
|
||||
}
|
|
@ -62,7 +62,7 @@ class InvokerBytecodeGenerator {
|
|||
private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
|
||||
|
||||
/** Name of its super class*/
|
||||
private static final String superName = LF;
|
||||
private static final String superName = OBJ;
|
||||
|
||||
/** Name of new class */
|
||||
private final String className;
|
||||
|
@ -97,7 +97,7 @@ class InvokerBytecodeGenerator {
|
|||
if (DUMP_CLASS_FILES) {
|
||||
className = makeDumpableClassName(className);
|
||||
}
|
||||
this.className = superName + "$" + className;
|
||||
this.className = LF + "$" + className;
|
||||
this.sourceFile = "LambdaForm$" + className;
|
||||
this.lambdaForm = lambdaForm;
|
||||
this.invokerName = invokerName;
|
||||
|
|
|
@ -188,7 +188,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
|||
static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
|
||||
boolean strict, boolean monobox) {
|
||||
MethodType dstType = target.type();
|
||||
assert(dstType.parameterCount() == target.type().parameterCount());
|
||||
if (srcType == dstType)
|
||||
return target;
|
||||
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,
|
||||
boolean strict, boolean monobox) {
|
||||
assert(target.type().parameterCount() == srcType.parameterCount());
|
||||
// Calculate extra arguments (temporaries) required in the names array.
|
||||
Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
|
||||
final int INARG_COUNT = srcType.parameterCount();
|
||||
|
|
|
@ -2023,8 +2023,9 @@ return invoker;
|
|||
*/
|
||||
public static
|
||||
MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
|
||||
MethodType oldType = target.type();
|
||||
explicitCastArgumentsChecks(target, newType);
|
||||
// use the asTypeCache when possible:
|
||||
MethodType oldType = target.type();
|
||||
if (oldType == newType) return target;
|
||||
if (oldType.explicitCastEquivalentToAsType(newType)) {
|
||||
return target.asType(newType);
|
||||
|
@ -2032,6 +2033,12 @@ return invoker;
|
|||
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
|
||||
* 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
|
||||
int oldArity = reorder.length;
|
||||
target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
|
||||
reorder = Arrays.copyOf(reorder, oldArity+1);
|
||||
reorder = Arrays.copyOf(reorder, oldArity + 1);
|
||||
reorder[oldArity] = dropIdx;
|
||||
}
|
||||
assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
|
||||
|
@ -2182,9 +2189,9 @@ assert((int)twice.invokeExact(21) == 42);
|
|||
long mask = 0;
|
||||
for (int arg : reorder) {
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
@ -2193,16 +2200,18 @@ assert((int)twice.invokeExact(21) == 42);
|
|||
int zeroPos = Long.numberOfTrailingZeros(zeroBit);
|
||||
assert(zeroPos < newArity);
|
||||
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;
|
||||
for (int i = 0; i < reorder.length; i++) {
|
||||
int arg = reorder[i];
|
||||
if (arg >= newArity) return reorder.length;
|
||||
int bit = 1 << arg;
|
||||
if ((mask & bit) != 0)
|
||||
if (arg >= newArity) {
|
||||
return reorder.length;
|
||||
}
|
||||
long bit = 1L << arg;
|
||||
if ((mask & bit) != 0) {
|
||||
return i; // >0 indicates a dup
|
||||
}
|
||||
mask |= bit;
|
||||
}
|
||||
if (mask == (1 << newArity) - 1) {
|
||||
if (mask == (1L << newArity) - 1) {
|
||||
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
|
||||
return 0;
|
||||
}
|
||||
// find first zero
|
||||
long zeroBit = Long.lowestOneBit(~mask);
|
||||
int zeroPos = Long.numberOfTrailingZeros(zeroBit);
|
||||
assert(zeroPos < newArity);
|
||||
assert(zeroPos <= newArity);
|
||||
if (zeroPos == newArity) {
|
||||
return 0;
|
||||
}
|
||||
return ~zeroPos;
|
||||
} else {
|
||||
// same algorithm, different bit set
|
||||
BitSet mask = new BitSet(newArity);
|
||||
for (int i = 0; i < reorder.length; i++) {
|
||||
int arg = reorder[i];
|
||||
if (arg >= newArity) return reorder.length;
|
||||
if (mask.get(arg))
|
||||
if (arg >= newArity) {
|
||||
return reorder.length;
|
||||
}
|
||||
if (mask.get(arg)) {
|
||||
return i; // >0 indicates a dup
|
||||
}
|
||||
mask.set(arg);
|
||||
}
|
||||
int zeroPos = mask.nextClearBit(0);
|
||||
assert(zeroPos <= newArity);
|
||||
if (zeroPos == newArity) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -2479,6 +2498,7 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
|
|||
MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
|
||||
MethodType oldType = target.type(); // get NPE
|
||||
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
|
||||
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
|
||||
if (dropped == 0) return target;
|
||||
BoundMethodHandle result = target.rebind();
|
||||
LambdaForm lform = result.form;
|
||||
|
@ -2490,7 +2510,6 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
|
|||
} else {
|
||||
lform = lform.addArguments(pos, valueTypes);
|
||||
}
|
||||
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
|
||||
result = result.copyWith(newType, lform);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -869,9 +869,7 @@ class MethodType implements java.io.Serializable {
|
|||
if (dstTypes == srcTypes) {
|
||||
return true;
|
||||
}
|
||||
if (dstTypes.length != srcTypes.length) {
|
||||
return false;
|
||||
}
|
||||
assert(dstTypes.length == srcTypes.length);
|
||||
for (int i = 0; i < dstTypes.length; i++) {
|
||||
if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
|
||||
return false;
|
||||
|
|
|
@ -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}
|
||||
MutableBigInteger bShifted = new MutableBigInteger(b);
|
||||
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
|
||||
int t = (int) ((bitLength()+n32) / n32);
|
||||
// step 5: t is the number of blocks needed to accommodate a plus one additional bit
|
||||
int t = (int) ((aShifted.bitLength()+n32) / n32);
|
||||
if (t < 2) {
|
||||
t = 2;
|
||||
}
|
||||
|
||||
// step 6: conceptually split this into blocks a[t-1], ..., a[0]
|
||||
MutableBigInteger a1 = getBlock(t-1, t, n); // the most significant block of this
|
||||
// step 6: conceptually split a into blocks a[t-1], ..., a[0]
|
||||
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]]
|
||||
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]
|
||||
|
||||
// do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers
|
||||
|
@ -1284,7 +1285,7 @@ class MutableBigInteger {
|
|||
ri = z.divide2n1n(bShifted, qi);
|
||||
|
||||
// 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);
|
||||
quotient.addShifted(qi, i*n); // update q (part of step 9)
|
||||
}
|
||||
|
@ -1292,7 +1293,7 @@ class MutableBigInteger {
|
|||
ri = z.divide2n1n(bShifted, 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,8 +336,21 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
|||
return new ZipEntry(name);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* 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 {
|
||||
int n = inf.getRemaining();
|
||||
|
@ -356,7 +369,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
|||
e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
|
||||
e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
|
||||
((PushbackInputStream)in).unread(
|
||||
tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
|
||||
tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC);
|
||||
} else {
|
||||
e.crc = get32(tmpbuf, ZIP64_EXTCRC);
|
||||
e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
|
||||
|
@ -370,7 +383,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
|||
e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
|
||||
e.size = get32(tmpbuf, EXTLEN - EXTCRC);
|
||||
((PushbackInputStream)in).unread(
|
||||
tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
|
||||
tmpbuf, EXTHDR - EXTCRC, EXTCRC);
|
||||
} else {
|
||||
e.crc = get32(tmpbuf, EXTCRC);
|
||||
e.csize = get32(tmpbuf, EXTSIZ);
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
|
||||
|
@ -177,10 +181,21 @@ Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this,
|
|||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
|
||||
{
|
||||
jint fd = fdval(env, fdo);
|
||||
struct stat64 fbuf;
|
||||
|
||||
if (fstat64(fdval(env, fdo), &fbuf) < 0)
|
||||
if (fstat64(fd, &fbuf) < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -990,9 +990,11 @@ JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
|
|||
case MIB_IF_TYPE_FDDI:
|
||||
case IF_TYPE_IEEE80211:
|
||||
len = ifRowP->dwPhysAddrLen;
|
||||
ret = (*env)->NewByteArray(env, len);
|
||||
if (!IS_NULL(ret)) {
|
||||
(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
|
||||
if (len > 0) {
|
||||
ret = (*env)->NewByteArray(env, len);
|
||||
if (!IS_NULL(ret)) {
|
||||
(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue