--- a/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
126f365cec6c3c2c72de934fa1c64b5f082b55b5 jdk7-b39
3c53424bbe3bb77e01b468b4b0140deec33e11fc jdk7-b40
3cb2a607c347934f8e7e86f840a094c28b08d9ea jdk7-b41
+caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42
--- a/.hgtags-top-repo Mon Dec 22 19:28:49 2008 +0000
+++ b/.hgtags-top-repo Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39
44be42de6693063fb191989bf0e188de2fa51e7c jdk7-b40
541bdc5ad32fc33255944d0a044ad992f3d915e8 jdk7-b41
+94052b87287303527125026fe4b2698cf867ea83 jdk7-b42
--- a/corba/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/corba/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39
184e21992f47a8d730df1adc5b21a108f3125489 jdk7-b40
c90eeda9594ed2983403e2049aed8d503126c62e jdk7-b41
+ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42
--- a/hotspot/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39
81a0cbe3b28460ce836109934ece03db7afaf9cc jdk7-b40
f9d938ede1960d18cb7cf23c645b026519c1a678 jdk7-b41
+ad8c8ca4ab0f4c86e74c061958f44a8f4a930f2c jdk7-b42
--- a/hotspot/make/hotspot_version Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/make/hotspot_version Fri Jan 09 21:54:17 2009 -0800
@@ -35,7 +35,7 @@
HS_MAJOR_VER=14
HS_MINOR_VER=0
-HS_BUILD_NUMBER=09
+HS_BUILD_NUMBER=10
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
--- a/hotspot/make/linux/adlc_updater Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/make/linux/adlc_updater Fri Jan 09 21:54:17 2009 -0800
@@ -7,5 +7,13 @@
#
# adlc-updater <file> <source-dir> <target-dir>
#
-[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
-( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
+fix_lines() {
+ # repair bare #line directives in $1 to refer to $2
+ awk < $1 > $1+ '
+ /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
+ {print}
+ ' F2=$2
+ mv $1+ $1
+}
+[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
+( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/linux/makefiles/adlc.make Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/make/linux/makefiles/adlc.make Fri Jan 09 21:54:17 2009 -0800
@@ -54,9 +54,11 @@
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
INCLUDES += $(Src_Dirs_I:%=-I%)
+# set flags for adlc compilation
+CPPFLAGS = $(SYSDEFS) $(INCLUDES)
+
# Force assertions on.
-SYSDEFS += -DASSERT
-CPPFLAGS = $(SYSDEFS) $(INCLUDES)
+CPPFLAGS += -DASSERT
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
# Suppress warnings (for now)
@@ -125,7 +127,15 @@
# Note that product files are updated via "mv", which is atomic.
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
-ADLCFLAGS = -q -T
+# Pass -D flags into ADLC.
+ADLCFLAGS += $(SYSDEFS)
+
+# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
+ADLCFLAGS += -q -T
+
+# Normally, debugging is done directly on the ad_<arch>*.cpp files.
+# But -g will put #line directives in those files pointing back to <arch>.ad.
+#ADLCFLAGS += -g
ifdef LP64
ADLCFLAGS += -D_LP64
@@ -140,6 +150,8 @@
#
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
ADLC_UPDATER = adlc_updater
+$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
+ $(QUIETLY) cp $< $@; chmod +x $@
# This action refreshes all generated adlc files simultaneously.
# The way it works is this:
@@ -149,9 +161,8 @@
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
# 5) If we actually updated any files, echo a notice.
#
-refresh_adfiles: $(EXEC) $(SOURCE.AD)
+refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
- $(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|| { rm -rf $(TEMPDIR); exit 1; }
@@ -174,7 +185,15 @@
# #########################################################################
$(SOURCE.AD): $(SOURCES.AD)
- $(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
+ $(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
+
+#PROCESS_AD_FILES = cat
+# Pass through #line directives, in case user enables -g option above:
+PROCESS_AD_FILES = awk '{ \
+ if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
+ if (need_lineno && $$0 !~ /\/\//) \
+ { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
+ print }'
$(OUTDIR)/%.o: %.cpp
@echo Compiling $<
--- a/hotspot/make/solaris/adlc_updater Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/make/solaris/adlc_updater Fri Jan 09 21:54:17 2009 -0800
@@ -7,5 +7,13 @@
#
# adlc-updater <file> <source-dir> <target-dir>
#
-[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
-( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
+fix_lines() {
+ # repair bare #line directives in $1 to refer to $2
+ awk < $1 > $1+ '
+ /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
+ {print}
+ ' F2=$2
+ mv $1+ $1
+}
+[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
+( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/solaris/makefiles/adlc.make Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/make/solaris/makefiles/adlc.make Fri Jan 09 21:54:17 2009 -0800
@@ -54,9 +54,11 @@
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
INCLUDES += $(Src_Dirs_I:%=-I%)
+# set flags for adlc compilation
+CPPFLAGS = $(SYSDEFS) $(INCLUDES)
+
# Force assertions on.
-SYSDEFS += -DASSERT
-CPPFLAGS = $(SYSDEFS) $(INCLUDES)
+CPPFLAGS += -DASSERT
ifndef USE_GCC
# We need libCstd.so for adlc
@@ -141,7 +143,15 @@
# Note that product files are updated via "mv", which is atomic.
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
-ADLCFLAGS = -q -T
+# Pass -D flags into ADLC.
+ADLCFLAGS += $(SYSDEFS)
+
+# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
+ADLCFLAGS += -q -T
+
+# Normally, debugging is done directly on the ad_<arch>*.cpp files.
+# But -g will put #line directives in those files pointing back to <arch>.ad.
+#ADLCFLAGS += -g
ifdef LP64
ADLCFLAGS += -D_LP64
@@ -156,6 +166,8 @@
#
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
ADLC_UPDATER = adlc_updater
+$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
+ $(QUIETLY) cp $< $@; chmod +x $@
# This action refreshes all generated adlc files simultaneously.
# The way it works is this:
@@ -165,9 +177,8 @@
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
# 5) If we actually updated any files, echo a notice.
#
-refresh_adfiles: $(EXEC) $(SOURCE.AD)
+refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
- $(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|| { rm -rf $(TEMPDIR); exit 1; }
@@ -190,7 +201,15 @@
# #########################################################################
$(SOURCE.AD): $(SOURCES.AD)
- $(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
+ $(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
+
+#PROCESS_AD_FILES = cat
+# Pass through #line directives, in case user enables -g option above:
+PROCESS_AD_FILES = awk '{ \
+ if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
+ if (need_lineno && $$0 !~ /\/\//) \
+ { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
+ print }'
$(OUTDIR)/%.o: %.cpp
@echo Compiling $<
--- a/hotspot/src/os/linux/vm/os_linux.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -2500,7 +2500,7 @@
}
bool os::unguard_memory(char* addr, size_t size) {
- return linux_mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC);
+ return linux_mprotect(addr, size, PROT_READ|PROT_WRITE);
}
// Large page support
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -1638,16 +1638,24 @@
// getTimeNanos is guaranteed to not move backward on Solaris
inline hrtime_t getTimeNanos() {
if (VM_Version::supports_cx8()) {
- bool retry = false;
- hrtime_t newtime = gethrtime();
- hrtime_t oldmaxtime = max_hrtime;
- hrtime_t retmaxtime = oldmaxtime;
- while ((newtime > retmaxtime) && (retry == false || retmaxtime != oldmaxtime)) {
- oldmaxtime = retmaxtime;
- retmaxtime = Atomic::cmpxchg(newtime, (volatile jlong *)&max_hrtime, oldmaxtime);
- retry = true;
- }
- return (newtime > retmaxtime) ? newtime : retmaxtime;
+ const hrtime_t now = gethrtime();
+ const hrtime_t prev = max_hrtime;
+ if (now <= prev) return prev; // same or retrograde time;
+ const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
+ assert(obsv >= prev, "invariant"); // Monotonicity
+ // If the CAS succeeded then we're done and return "now".
+ // If the CAS failed and the observed value "obs" is >= now then
+ // we should return "obs". If the CAS failed and now > obs > prv then
+ // some other thread raced this thread and installed a new value, in which case
+ // we could either (a) retry the entire operation, (b) retry trying to install now
+ // or (c) just return obs. We use (c). No loop is required although in some cases
+ // we might discard a higher "now" value in deference to a slightly lower but freshly
+ // installed obs value. That's entirely benign -- it admits no new orderings compared
+ // to (a) or (b) -- and greatly reduces coherence traffic.
+ // We might also condition (c) on the magnitude of the delta between obs and now.
+ // Avoiding excessive CAS operations to hot RW locations is critical.
+ // See http://blogs.sun.com/dave/entry/cas_and_cache_trivia_invalidate
+ return (prev == obsv) ? now : obsv ;
} else {
return oldgetTimeNanos();
}
@@ -3026,6 +3034,8 @@
// Protect memory (Used to pass readonly pages through
// JNI GetArray<type>Elements with empty arrays.)
+// Also, used for serialization page and for compressed oops null pointer
+// checking.
bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed) {
unsigned int p = 0;
@@ -3049,7 +3059,7 @@
}
bool os::unguard_memory(char* addr, size_t bytes) {
- return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE|PROT_EXEC);
+ return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE);
}
// Large page support
--- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -2020,10 +2020,11 @@
if (UnguardOnExecutionViolation > 0 && addr != last_addr &&
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
- // Unguard and retry
+ // Set memory to RWX and retry
address page_start =
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
- bool res = os::unguard_memory((char*) page_start, page_size);
+ bool res = os::protect_memory((char*) page_start, page_size,
+ os::MEM_PROT_RWX);
if (PrintMiscellaneous && Verbose) {
char buf[256];
@@ -2755,12 +2756,12 @@
bool os::guard_memory(char* addr, size_t bytes) {
DWORD old_status;
- return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_status) != 0;
+ return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0;
}
bool os::unguard_memory(char* addr, size_t bytes) {
DWORD old_status;
- return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &old_status) != 0;
+ return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;
}
void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -422,10 +422,11 @@
if (addr != last_addr &&
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
- // Unguard and retry
+ // Set memory to RWX and retry
address page_start =
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
- bool res = os::unguard_memory((char*) page_start, page_size);
+ bool res = os::protect_memory((char*) page_start, page_size,
+ os::MEM_PROT_RWX);
if (PrintMiscellaneous && Verbose) {
char buf[256];
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -203,10 +203,10 @@
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
-extern "C" intptr_t *_get_previous_fp(); // in .il file.
+extern "C" intptr_t *_get_current_fp(); // in .il file
frame os::current_frame() {
- intptr_t* fp = _get_previous_fp();
+ intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
frame myframe((intptr_t*)os::current_stack_pointer(),
(intptr_t*)fp,
CAST_FROM_FN_PTR(address, os::current_frame));
@@ -576,10 +576,11 @@
if (addr != last_addr &&
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
- // Unguard and retry
+ // Make memory rwx and retry
address page_start =
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
- bool res = os::unguard_memory((char*) page_start, page_size);
+ bool res = os::protect_memory((char*) page_start, page_size,
+ os::MEM_PROT_RWX);
if (PrintMiscellaneous && Verbose) {
char buf[256];
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Fri Jan 09 21:54:17 2009 -0800
@@ -37,10 +37,10 @@
movl %gs:0, %eax
.end
- // Get callers fp
- .inline _get_previous_fp,0
+ // Get current fp
+ .inline _get_current_fp,0
+ .volatile
movl %ebp, %eax
- movl %eax, %eax
.end
// Support for jint Atomic::add(jint inc, volatile jint* dest)
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Fri Jan 09 21:54:17 2009 -0800
@@ -30,10 +30,10 @@
movq %fs:0, %rax
.end
- // Get the frame pointer from previous frame.
- .inline _get_previous_fp,0
+ // Get the frame pointer from current frame.
+ .inline _get_current_fp,0
+ .volatile
movq %rbp, %rax
- movq %rax, %rax
.end
// Support for jint Atomic::add(jint add_value, volatile jint* dest)
--- a/hotspot/src/share/vm/adlc/adlparse.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -108,6 +108,7 @@
else if (!strcmp(ident, "pipeline")) pipe_parse();
else if (!strcmp(ident, "definitions")) definitions_parse();
else if (!strcmp(ident, "peephole")) peep_parse();
+ else if (!strcmp(ident, "#line")) preproc_line();
else if (!strcmp(ident, "#define")) preproc_define();
else if (!strcmp(ident, "#undef")) preproc_undef();
else {
@@ -786,9 +787,11 @@
parse_err(SYNERR, "missing identifier inside register block.\n");
return;
}
- if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
- if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
- if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
+ if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
+ else if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
+ else if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
+ else if (strcmp(token,"#define")==0) { preproc_define(); }
+ else { parse_err(SYNERR, "bad token %s inside register block.\n", token); break; }
skipws();
}
}
@@ -903,11 +906,7 @@
skipws_no_preproc(); // Skip leading whitespace
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
- const char* file = _AD._ADL_file._name;
- int line = linenum();
- char* location = (char *)malloc(strlen(file) + 100);
- sprintf(location, "#line %d \"%s\"\n", line, file);
- encoding->add_code(location);
+ encoding->add_code(get_line_string());
}
// Collect the parts of the encode description
@@ -948,6 +947,10 @@
skipws();
+ if (_AD._adlocation_debug) {
+ encoding->add_code(end_line_marker());
+ }
+
// Debug Stuff
if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
}
@@ -2349,7 +2352,11 @@
return;
}
RegDef *regDef = _AD._register->getRegDef(rname);
- reg_class->addReg(regDef); // add regDef to regClass
+ if (!regDef) {
+ parse_err(SEMERR, "unknown identifier %s inside reg_class list.\n", rname);
+ } else {
+ reg_class->addReg(regDef); // add regDef to regClass
+ }
// Check for ',' and position to next token.
skipws();
@@ -2746,7 +2753,8 @@
char *rule = NULL; // String representation of predicate
skipws(); // Skip leading whitespace
- if ( (rule = get_paren_expr("pred expression")) == NULL ) {
+ int line = linenum();
+ if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
return NULL;
}
@@ -3407,7 +3415,12 @@
// Check if there is a string to pass through to output
char *start = _ptr; // Record start of the next string
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
- if (_curchar == '\\') next_char(); // superquote
+ if (_curchar == '\\') {
+ next_char(); // superquote
+ if ((_curchar == '$') || (_curchar == '%'))
+ // hack to avoid % escapes and warnings about undefined \ escapes
+ *(_ptr-1) = _curchar;
+ }
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
next_char();
}
@@ -3942,8 +3955,7 @@
next_char(); // Skip block delimiter
skipws_no_preproc(); // Skip leading whitespace
cppBlock = _ptr; // Point to start of expression
- const char* file = _AD._ADL_file._name;
- int line = linenum();
+ int line = linenum();
next = _ptr + 1;
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
next_char_or_line();
@@ -3958,15 +3970,16 @@
_curchar = *_ptr; // Maintain invariant
// Prepend location descriptor, for debugging.
- char* location = (char *)malloc(strlen(file) + 100);
- *location = '\0';
- if (_AD._adlocation_debug)
- sprintf(location, "#line %d \"%s\"\n", line, file);
- char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1);
- strcpy(result, location);
- strcat(result, cppBlock);
- cppBlock = result;
- free(location);
+ if (_AD._adlocation_debug) {
+ char* location = get_line_string(line);
+ char* end_loc = end_line_marker();
+ char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1);
+ strcpy(result, location);
+ strcat(result, cppBlock);
+ strcat(result, end_loc);
+ cppBlock = result;
+ free(location);
+ }
}
return cppBlock;
@@ -4036,13 +4049,26 @@
// Helper function around get_expr
// Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
-char *ADLParser::get_paren_expr(const char *description) {
+char *ADLParser::get_paren_expr(const char *description, bool include_location) {
+ int line = linenum();
if (_curchar != '(') // Escape if not valid starting position
return NULL;
next_char(); // Skip the required initial paren.
char *token2 = get_expr(description, ")");
if (_curchar == ')')
next_char(); // Skip required final paren.
+ int junk = 0;
+ if (include_location && _AD._adlocation_debug && !is_int_token(token2, junk)) {
+ // Prepend location descriptor, for debugging.
+ char* location = get_line_string(line);
+ char* end_loc = end_line_marker();
+ char* result = (char *)malloc(strlen(location) + strlen(token2) + strlen(end_loc) + 1);
+ strcpy(result, location);
+ strcat(result, token2);
+ strcat(result, end_loc);
+ token2 = result;
+ free(location);
+ }
return token2;
}
@@ -4082,10 +4108,16 @@
if (do_preproc && start != NULL) {
const char* def = _AD.get_preproc_def(start);
if (def != NULL && strcmp(def, start)) {
- const char* def2 = _AD.get_preproc_def(def);
- if (def2 != NULL && strcmp(def2, def)) {
- parse_err(SYNERR, "unimplemented: using %s defined as %s => %s",
- start, def, def2);
+ const char* def1 = def;
+ const char* def2 = _AD.get_preproc_def(def1);
+ // implement up to 2 levels of #define
+ if (def2 != NULL && strcmp(def2, def1)) {
+ def = def2;
+ const char* def3 = _AD.get_preproc_def(def2);
+ if (def3 != NULL && strcmp(def3, def2) && strcmp(def3, def1)) {
+ parse_err(SYNERR, "unimplemented: using %s defined as %s => %s => %s",
+ start, def1, def2, def3);
+ }
}
start = strdup(def);
}
@@ -4431,6 +4463,35 @@
}
+//-------------------------------preproc_line----------------------------------
+// A "#line" keyword has been seen, so parse the rest of the line.
+void ADLParser::preproc_line(void) {
+ int line = get_int();
+ skipws_no_preproc();
+ const char* file = NULL;
+ if (_curchar == '"') {
+ next_char(); // Move past the initial '"'
+ file = _ptr;
+ while (true) {
+ if (_curchar == '\n') {
+ parse_err(SYNERR, "missing '\"' at end of #line directive");
+ return;
+ }
+ if (_curchar == '"') {
+ *_ptr = '\0'; // Terminate the string
+ next_char();
+ skipws_no_preproc();
+ break;
+ }
+ next_char();
+ }
+ }
+ ensure_end_of_line();
+ if (file != NULL)
+ _AD._ADL_file._name = file;
+ _buf.set_linenum(line);
+}
+
//------------------------------preproc_define---------------------------------
// A "#define" keyword has been seen, so parse the rest of the line.
void ADLParser::preproc_define(void) {
@@ -4494,6 +4555,7 @@
// A preprocessor directive has been encountered. Be sure it has fallen at
// the begining of a line, or else report an error.
void ADLParser::ensure_start_of_line(void) {
+ if (_curchar == '\n') { next_line(); return; }
assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
"Must be able to find which line we are in" );
@@ -4662,6 +4724,7 @@
//---------------------------next_char-----------------------------------------
void ADLParser::next_char() {
+ if (_curchar == '\n') parse_err(WARN, "must call next_line!");
_curchar = *++_ptr;
// if ( _curchar == '\n' ) {
// next_line();
@@ -4682,6 +4745,18 @@
//---------------------------next_line-----------------------------------------
void ADLParser::next_line() {
_curline = _buf.get_line();
+ _curchar = ' ';
+}
+
+//------------------------get_line_string--------------------------------------
+// Prepended location descriptor, for debugging.
+// Must return a malloced string (that can be freed if desired).
+char* ADLParser::get_line_string(int linenum) {
+ const char* file = _AD._ADL_file._name;
+ int line = linenum ? linenum : this->linenum();
+ char* location = (char *)malloc(strlen(file) + 100);
+ sprintf(location, "\n#line %d \"%s\"\n", line, file);
+ return location;
}
//-------------------------is_literal_constant---------------------------------
@@ -4722,6 +4797,66 @@
return true;
}
+static const char* skip_expr_ws(const char* str) {
+ const char * cp = str;
+ while (cp[0]) {
+ if (cp[0] <= ' ') {
+ ++cp;
+ } else if (cp[0] == '#') {
+ ++cp;
+ while (cp[0] == ' ') ++cp;
+ assert(0 == strncmp(cp, "line", 4), "must be a #line directive");
+ const char* eol = strchr(cp, '\n');
+ assert(eol != NULL, "must find end of line");
+ if (eol == NULL) eol = cp + strlen(cp);
+ cp = eol;
+ } else {
+ break;
+ }
+ }
+ return cp;
+}
+
+//-----------------------equivalent_expressions--------------------------------
+bool ADLParser::equivalent_expressions(const char* str1, const char* str2) {
+ if (str1 == str2)
+ return true;
+ else if (str1 == NULL || str2 == NULL)
+ return false;
+ const char* cp1 = str1;
+ const char* cp2 = str2;
+ char in_quote = '\0';
+ while (cp1[0] && cp2[0]) {
+ if (!in_quote) {
+ // skip spaces and/or cpp directives
+ const char* cp1a = skip_expr_ws(cp1);
+ const char* cp2a = skip_expr_ws(cp2);
+ if (cp1a > cp1 && cp2a > cp2) {
+ cp1 = cp1a; cp2 = cp2a;
+ continue;
+ }
+ if (cp1a > cp1 || cp2a > cp2) break; // fail
+ }
+ // match one non-space char
+ if (cp1[0] != cp2[0]) break; // fail
+ char ch = cp1[0];
+ cp1++; cp2++;
+ // watch for quotes
+ if (in_quote && ch == '\\') {
+ if (cp1[0] != cp2[0]) break; // fail
+ if (!cp1[0]) break;
+ cp1++; cp2++;
+ }
+ if (in_quote && ch == in_quote) {
+ in_quote = '\0';
+ } else if (!in_quote && (ch == '"' || ch == '\'')) {
+ in_quote = ch;
+ }
+ }
+ return (!cp1[0] && !cp2[0]);
+}
+
+
//-------------------------------trim------------------------------------------
void ADLParser::trim(char* &token) {
while (*token <= ' ') token++;
--- a/hotspot/src/share/vm/adlc/adlparse.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/adlparse.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -93,6 +93,7 @@
void pipe_parse(void); // Parse pipeline section
void definitions_parse(void); // Parse definitions section
void peep_parse(void); // Parse peephole rule definitions
+ void preproc_line(void); // Parse a #line statement
void preproc_define(void); // Parse a #define statement
void preproc_undef(void); // Parse an #undef statement
@@ -226,7 +227,7 @@
void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs
// Return the contents of a parenthesized expression.
// Requires initial '(' and consumes final ')', which is replaced by '\0'.
- char *get_paren_expr(const char *description);
+ char *get_paren_expr(const char *description, bool include_location = false);
// Return expression up to next stop-char, which terminator replaces.
// Does not require initial '('. Does not consume final stop-char.
// Final stop-char is left in _curchar, but is also is replaced by '\0'.
@@ -234,6 +235,11 @@
char *find_cpp_block(const char *description); // Parse a C++ code block
// Issue parser error message & go to EOL
void parse_err(int flag, const char *fmt, ...);
+ // Create a location marker for this file and line.
+ char *get_line_string(int linenum = 0);
+ // Return a location marker which tells the C preprocessor to
+ // forget the previous location marker. (Requires awk postprocessing.)
+ char *end_line_marker() { return (char*)"\n#line 999999\n"; }
// Return pointer to current character
inline char cur_char(void);
@@ -268,5 +274,6 @@
static bool is_literal_constant(const char *hex_string);
static bool is_hex_digit(char digit);
static bool is_int_token(const char* token, int& intval);
+ static bool equivalent_expressions(const char* str1, const char* str2);
static void trim(char* &token); // trim leading & trailing spaces
};
--- a/hotspot/src/share/vm/adlc/archDesc.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/archDesc.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -140,7 +140,7 @@
if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {
char * predStr = get_pred();
char * prStr = pr?pr->_pred:NULL;
- if ((prStr == predStr) || (prStr && predStr && !strcmp(prStr, predStr))) {
+ if (ADLParser::equivalent_expressions(prStr, predStr)) {
return true;
}
}
--- a/hotspot/src/share/vm/adlc/dfa.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/dfa.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -458,7 +458,7 @@
class dfa_shared_preds {
- enum { count = 2 };
+ enum { count = 4 };
static bool _found[count];
static const char* _type [count];
@@ -479,12 +479,15 @@
char c = *prev;
switch( c ) {
case ' ':
+ case '\n':
return dfa_shared_preds::valid_loc(pred, prev);
case '!':
case '(':
case '<':
case '=':
return true;
+ case '"': // such as: #line 10 "myfile.ad"\n mypredicate
+ return true;
case '|':
if( prev != pred && *(prev-1) == '|' ) return true;
case '&':
@@ -564,10 +567,14 @@
}
};
// shared predicates, _var and _pred entry should be the same length
-bool dfa_shared_preds::_found[dfa_shared_preds::count] = { false, false };
-const char* dfa_shared_preds::_type[dfa_shared_preds::count] = { "int", "bool" };
-const char* dfa_shared_preds::_var [dfa_shared_preds::count] = { "_n_get_int__", "Compile__current____select_24_bit_instr__" };
-const char* dfa_shared_preds::_pred[dfa_shared_preds::count] = { "n->get_int()", "Compile::current()->select_24_bit_instr()" };
+bool dfa_shared_preds::_found[dfa_shared_preds::count]
+ = { false, false, false, false };
+const char* dfa_shared_preds::_type[dfa_shared_preds::count]
+ = { "int", "jlong", "intptr_t", "bool" };
+const char* dfa_shared_preds::_var [dfa_shared_preds::count]
+ = { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__", "Compile__current____select_24_bit_instr__" };
+const char* dfa_shared_preds::_pred[dfa_shared_preds::count]
+ = { "n->get_int()", "n->get_long()", "n->get_intptr_t()", "Compile::current()->select_24_bit_instr()" };
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) {
--- a/hotspot/src/share/vm/adlc/filebuff.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/filebuff.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -68,6 +68,7 @@
// and increments bufeol and filepos to point at the end of that line.
char *get_line(void);
int linenum() const { return _linenum; }
+ void set_linenum(int line) { _linenum = line; }
// This converts a pointer into the buffer to a file offset. It only works
// when the pointer is valid (i.e. just obtained from getline()).
--- a/hotspot/src/share/vm/adlc/formssel.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -1102,10 +1102,7 @@
}
if( pred1 != NULL && pred2 != NULL ) {
// compare the predicates
- const char *str1 = pred1->_pred;
- const char *str2 = pred2->_pred;
- if( (str1 == NULL && str2 == NULL)
- || (str1 != NULL && str2 != NULL && strcmp(str1,str2) == 0) ) {
+ if (ADLParser::equivalent_expressions(pred1->_pred, pred2->_pred)) {
return true;
}
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -1210,8 +1210,8 @@
break;
case T_LONG:
case T_DOUBLE:
- if (c->as_jint_hi_bits() != other->as_jint_lo_bits()) continue;
- if (c->as_jint_lo_bits() != other->as_jint_hi_bits()) continue;
+ if (c->as_jint_hi_bits() != other->as_jint_hi_bits()) continue;
+ if (c->as_jint_lo_bits() != other->as_jint_lo_bits()) continue;
break;
case T_OBJECT:
if (c->as_jobject() != other->as_jobject()) continue;
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -327,8 +327,6 @@
BlockBegin* fsux = if_->fsux();
if (swapped) {
cond = Instruction::mirror(cond);
- tsux = if_->fsux();
- fsux = if_->tsux();
}
BlockBegin* tblock = tval->compare(cond, con, tsux, fsux);
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -842,6 +842,13 @@
if (TracePatching) {
tty->print_cr("Deoptimizing for patching volatile field reference");
}
+ // It's possible the nmethod was invalidated in the last
+ // safepoint, but if it's still alive then make it not_entrant.
+ nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
+ if (nm != NULL) {
+ nm->make_not_entrant();
+ }
+
VM_DeoptimizeFrame deopt(thread, caller_frame.id());
VMThread::execute(&deopt);
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -581,7 +581,8 @@
interf = KlassHandle(THREAD, k);
vmtimer->resume();
- cp->klass_at_put(interface_index, interf()); // eagerly resolve
+ if (LinkWellKnownClasses) // my super type is well known to me
+ cp->klass_at_put(interface_index, interf()); // eagerly resolve
}
if (!Klass::cast(interf())->is_interface()) {
@@ -2699,7 +2700,8 @@
CHECK_(nullHandle));
KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh());
- cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
+ if (LinkWellKnownClasses) // my super class is well known to me
+ cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
}
if (super_klass.not_null()) {
if (super_klass->is_interface()) {
@@ -3128,7 +3130,8 @@
this_klass->set_method_ordering(method_ordering());
this_klass->set_initial_method_idnum(methods->length());
this_klass->set_name(cp->klass_name_at(this_class_index));
- cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
+ if (LinkWellKnownClasses) // I am well known to myself
+ cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
this_klass->set_protection_domain(protection_domain());
this_klass->set_fields_annotations(fields_annotations());
this_klass->set_methods_annotations(methods_annotations());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -2954,7 +2954,7 @@
// The object has been either evacuated or is dead. Fill it with a
// dummy object.
MemRegion mr((HeapWord*)obj, obj->size());
- SharedHeap::fill_region_with_object(mr);
+ CollectedHeap::fill_with_object(mr);
_cm->clearRangeBothMaps(mr);
}
}
@@ -3225,7 +3225,7 @@
// Otherwise, try to claim it.
block = r->par_allocate(free_words);
} while (block == NULL);
- SharedHeap::fill_region_with_object(MemRegion(block, free_words));
+ fill_with_object(block, free_words);
}
#define use_local_bitmaps 1
@@ -3619,9 +3619,8 @@
guarantee(alloc_buffer(purpose)->contains(obj + word_sz - 1),
"should contain whole object");
alloc_buffer(purpose)->undo_allocation(obj, word_sz);
- }
- else {
- SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
+ } else {
+ CollectedHeap::fill_with_object(obj, word_sz);
add_to_undo_waste(word_sz);
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -181,7 +181,7 @@
void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) {
HeapWord* hr_bot = hr()->bottom();
- int hr_first_card_index = ctbs->index_for(hr_bot);
+ size_t hr_first_card_index = ctbs->index_for(hr_bot);
bm()->set_intersection_at_offset(*card_bm, hr_first_card_index);
#if PRT_COUNT_OCCUPIED
recount_occupied();
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -102,7 +102,7 @@
HeapWord* tmp = hr->allocate(sz);
assert(tmp != NULL, "Humongous allocation failure");
MemRegion mr = MemRegion(tmp, sz);
- SharedHeap::fill_region_with_object(mr);
+ CollectedHeap::fill_with_object(mr);
hr->declare_filled_region_to_BOT(mr);
if (i == first) {
first_hr->set_startsHumongous();
--- a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -51,14 +51,14 @@
if (_retained) {
// If the buffer had been retained shorten the previous filler object.
assert(_retained_filler.end() <= _top, "INVARIANT");
- SharedHeap::fill_region_with_object(_retained_filler);
+ CollectedHeap::fill_with_object(_retained_filler);
// Wasted space book-keeping, otherwise (normally) done in invalidate()
_wasted += _retained_filler.word_size();
_retained = false;
}
assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained.");
if (_top < _hard_end) {
- SharedHeap::fill_region_with_object(MemRegion(_top, _hard_end));
+ CollectedHeap::fill_with_object(_top, _hard_end);
if (!retain) {
invalidate();
} else {
@@ -155,7 +155,7 @@
// modifying the _next_threshold state in the BOT.
void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr,
bool contig) {
- SharedHeap::fill_region_with_object(mr);
+ CollectedHeap::fill_with_object(mr);
if (contig) {
_bt.alloc_block(mr.start(), mr.end());
} else {
@@ -171,7 +171,7 @@
"or else _true_end should be equal to _hard_end");
assert(_retained, "or else _true_end should be equal to _hard_end");
assert(_retained_filler.end() <= _top, "INVARIANT");
- SharedHeap::fill_region_with_object(_retained_filler);
+ CollectedHeap::fill_with_object(_retained_filler);
if (_top < _hard_end) {
fill_region_with_block(MemRegion(_top, _hard_end), true);
}
@@ -316,11 +316,9 @@
while (_top <= chunk_boundary) {
assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve,
"Consequence of last card handling above.");
- MemRegion chunk_portion(chunk_boundary, _hard_end);
- _bt.BlockOffsetArray::alloc_block(chunk_portion.start(),
- chunk_portion.end());
- SharedHeap::fill_region_with_object(chunk_portion);
- _hard_end = chunk_portion.start();
+ _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end);
+ CollectedHeap::fill_with_object(chunk_boundary, _hard_end);
+ _hard_end = chunk_boundary;
chunk_boundary -= ChunkSizeInWords;
}
_end = _hard_end - AlignmentReserve;
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -201,7 +201,7 @@
"Should contain whole object.");
to_space_alloc_buffer()->undo_allocation(obj, word_sz);
} else {
- SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
+ CollectedHeap::fill_with_object(obj, word_sz);
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -389,7 +389,7 @@
// full GC.
const size_t alignment = old_gen->virtual_space()->alignment();
const size_t eden_used = eden_space->used_in_bytes();
- const size_t promoted = (size_t)(size_policy->avg_promoted()->padded_average());
+ const size_t promoted = (size_t)size_policy->avg_promoted()->padded_average();
const size_t absorb_size = align_size_up(eden_used + promoted, alignment);
const size_t eden_capacity = eden_space->capacity_in_bytes();
@@ -416,16 +416,14 @@
// Fill the unused part of the old gen.
MutableSpace* const old_space = old_gen->object_space();
- MemRegion old_gen_unused(old_space->top(), old_space->end());
+ HeapWord* const unused_start = old_space->top();
+ size_t const unused_words = pointer_delta(old_space->end(), unused_start);
- // If the unused part of the old gen cannot be filled, skip
- // absorbing eden.
- if (old_gen_unused.word_size() < SharedHeap::min_fill_size()) {
- return false;
- }
-
- if (!old_gen_unused.is_empty()) {
- SharedHeap::fill_region_with_object(old_gen_unused);
+ if (unused_words > 0) {
+ if (unused_words < CollectedHeap::min_fill_size()) {
+ return false; // If the old gen cannot be filled, must give up.
+ }
+ CollectedHeap::fill_with_objects(unused_start, unused_words);
}
// Take the live data from eden and set both top and end in the old gen to
@@ -441,9 +439,8 @@
// Update the object start array for the filler object and the data from eden.
ObjectStartArray* const start_array = old_gen->start_array();
- HeapWord* const start = old_gen_unused.start();
- for (HeapWord* addr = start; addr < new_top; addr += oop(addr)->size()) {
- start_array->allocate_block(addr);
+ for (HeapWord* p = unused_start; p < new_top; p += oop(p)->size()) {
+ start_array->allocate_block(p);
}
// Could update the promoted average here, but it is not typically updated at
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -275,22 +275,9 @@
HeapWord* q, size_t deadlength) {
if (allowed_deadspace_words >= deadlength) {
allowed_deadspace_words -= deadlength;
- oop(q)->set_mark(markOopDesc::prototype()->set_marked());
- const size_t aligned_min_int_array_size =
- align_object_size(typeArrayOopDesc::header_size(T_INT));
- if (deadlength >= aligned_min_int_array_size) {
- oop(q)->set_klass(Universe::intArrayKlassObj());
- assert(((deadlength - aligned_min_int_array_size) * (HeapWordSize/sizeof(jint))) < (size_t)max_jint,
- "deadspace too big for Arrayoop");
- typeArrayOop(q)->set_length((int)((deadlength - aligned_min_int_array_size)
- * (HeapWordSize/sizeof(jint))));
- } else {
- assert((int) deadlength == instanceOopDesc::header_size(),
- "size for smallest fake dead object doesn't match");
- oop(q)->set_klass(SystemDictionary::object_klass());
- }
- assert((int) deadlength == oop(q)->size(),
- "make sure size for fake dead object match");
+ CollectedHeap::fill_with_object(q, deadlength);
+ oop(q)->set_mark(oop(q)->mark()->set_marked());
+ assert((int) deadlength == oop(q)->size(), "bad filler object size");
// Recall that we required "q == compaction_top".
return true;
} else {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -88,6 +88,72 @@
GrowableArray<size_t> * PSParallelCompact::_last_gc_live_oops_size = NULL;
#endif
+void SplitInfo::record(size_t src_region_idx, size_t partial_obj_size,
+ HeapWord* destination)
+{
+ assert(src_region_idx != 0, "invalid src_region_idx");
+ assert(partial_obj_size != 0, "invalid partial_obj_size argument");
+ assert(destination != NULL, "invalid destination argument");
+
+ _src_region_idx = src_region_idx;
+ _partial_obj_size = partial_obj_size;
+ _destination = destination;
+
+ // These fields may not be updated below, so make sure they're clear.
+ assert(_dest_region_addr == NULL, "should have been cleared");
+ assert(_first_src_addr == NULL, "should have been cleared");
+
+ // Determine the number of destination regions for the partial object.
+ HeapWord* const last_word = destination + partial_obj_size - 1;
+ const ParallelCompactData& sd = PSParallelCompact::summary_data();
+ HeapWord* const beg_region_addr = sd.region_align_down(destination);
+ HeapWord* const end_region_addr = sd.region_align_down(last_word);
+
+ if (beg_region_addr == end_region_addr) {
+ // One destination region.
+ _destination_count = 1;
+ if (end_region_addr == destination) {
+ // The destination falls on a region boundary, thus the first word of the
+ // partial object will be the first word copied to the destination region.
+ _dest_region_addr = end_region_addr;
+ _first_src_addr = sd.region_to_addr(src_region_idx);
+ }
+ } else {
+ // Two destination regions. When copied, the partial object will cross a
+ // destination region boundary, so a word somewhere within the partial
+ // object will be the first word copied to the second destination region.
+ _destination_count = 2;
+ _dest_region_addr = end_region_addr;
+ const size_t ofs = pointer_delta(end_region_addr, destination);
+ assert(ofs < _partial_obj_size, "sanity");
+ _first_src_addr = sd.region_to_addr(src_region_idx) + ofs;
+ }
+}
+
+void SplitInfo::clear()
+{
+ _src_region_idx = 0;
+ _partial_obj_size = 0;
+ _destination = NULL;
+ _destination_count = 0;
+ _dest_region_addr = NULL;
+ _first_src_addr = NULL;
+ assert(!is_valid(), "sanity");
+}
+
+#ifdef ASSERT
+void SplitInfo::verify_clear()
+{
+ assert(_src_region_idx == 0, "not clear");
+ assert(_partial_obj_size == 0, "not clear");
+ assert(_destination == NULL, "not clear");
+ assert(_destination_count == 0, "not clear");
+ assert(_dest_region_addr == NULL, "not clear");
+ assert(_first_src_addr == NULL, "not clear");
+}
+#endif // #ifdef ASSERT
+
+
#ifndef PRODUCT
const char* PSParallelCompact::space_names[] = {
"perm", "old ", "eden", "from", "to "
@@ -416,21 +482,134 @@
}
}
-bool ParallelCompactData::summarize(HeapWord* target_beg, HeapWord* target_end,
- HeapWord* source_beg, HeapWord* source_end,
- HeapWord** target_next,
- HeapWord** source_next) {
- // This is too strict.
- // assert(region_offset(source_beg) == 0, "not RegionSize aligned");
+// Find the point at which a space can be split and, if necessary, record the
+// split point.
+//
+// If the current src region (which overflowed the destination space) doesn't
+// have a partial object, the split point is at the beginning of the current src
+// region (an "easy" split, no extra bookkeeping required).
+//
+// If the current src region has a partial object, the split point is in the
+// region where that partial object starts (call it the split_region). If
+// split_region has a partial object, then the split point is just after that
+// partial object (a "hard" split where we have to record the split data and
+// zero the partial_obj_size field). With a "hard" split, we know that the
+// partial_obj ends within split_region because the partial object that caused
+// the overflow starts in split_region. If split_region doesn't have a partial
+// obj, then the split is at the beginning of split_region (another "easy"
+// split).
+HeapWord*
+ParallelCompactData::summarize_split_space(size_t src_region,
+ SplitInfo& split_info,
+ HeapWord* destination,
+ HeapWord* target_end,
+ HeapWord** target_next)
+{
+ assert(destination <= target_end, "sanity");
+ assert(destination + _region_data[src_region].data_size() > target_end,
+ "region should not fit into target space");
+
+ size_t split_region = src_region;
+ HeapWord* split_destination = destination;
+ size_t partial_obj_size = _region_data[src_region].partial_obj_size();
+
+ if (destination + partial_obj_size > target_end) {
+ // The split point is just after the partial object (if any) in the
+ // src_region that contains the start of the object that overflowed the
+ // destination space.
+ //
+ // Find the start of the "overflow" object and set split_region to the
+ // region containing it.
+ HeapWord* const overflow_obj = _region_data[src_region].partial_obj_addr();
+ split_region = addr_to_region_idx(overflow_obj);
+
+ // Clear the source_region field of all destination regions whose first word
+ // came from data after the split point (a non-null source_region field
+ // implies a region must be filled).
+ //
+ // An alternative to the simple loop below: clear during post_compact(),
+ // which uses memcpy instead of individual stores, and is easy to
+ // parallelize. (The downside is that it clears the entire RegionData
+ // object as opposed to just one field.)
+ //
+ // post_compact() would have to clear the summary data up to the highest
+ // address that was written during the summary phase, which would be
+ //
+ // max(top, max(new_top, clear_top))
+ //
+ // where clear_top is a new field in SpaceInfo. Would have to set clear_top
+ // to destination + partial_obj_size, where both have the values passed to
+ // this routine.
+ const RegionData* const sr = region(split_region);
+ const size_t beg_idx =
+ addr_to_region_idx(region_align_up(sr->destination() +
+ sr->partial_obj_size()));
+ const size_t end_idx =
+ addr_to_region_idx(region_align_up(destination + partial_obj_size));
+
+ if (TraceParallelOldGCSummaryPhase) {
+ gclog_or_tty->print_cr("split: clearing source_region field in ["
+ SIZE_FORMAT ", " SIZE_FORMAT ")",
+ beg_idx, end_idx);
+ }
+ for (size_t idx = beg_idx; idx < end_idx; ++idx) {
+ _region_data[idx].set_source_region(0);
+ }
+
+ // Set split_destination and partial_obj_size to reflect the split region.
+ split_destination = sr->destination();
+ partial_obj_size = sr->partial_obj_size();
+ }
+
+ // The split is recorded only if a partial object extends onto the region.
+ if (partial_obj_size != 0) {
+ _region_data[split_region].set_partial_obj_size(0);
+ split_info.record(split_region, partial_obj_size, split_destination);
+ }
+
+ // Setup the continuation addresses.
+ *target_next = split_destination + partial_obj_size;
+ HeapWord* const source_next = region_to_addr(split_region) + partial_obj_size;
if (TraceParallelOldGCSummaryPhase) {
- tty->print_cr("tb=" PTR_FORMAT " te=" PTR_FORMAT " "
- "sb=" PTR_FORMAT " se=" PTR_FORMAT " "
- "tn=" PTR_FORMAT " sn=" PTR_FORMAT,
- target_beg, target_end,
- source_beg, source_end,
- target_next != 0 ? *target_next : (HeapWord*) 0,
- source_next != 0 ? *source_next : (HeapWord*) 0);
+ const char * split_type = partial_obj_size == 0 ? "easy" : "hard";
+ gclog_or_tty->print_cr("%s split: src=" PTR_FORMAT " src_c=" SIZE_FORMAT
+ " pos=" SIZE_FORMAT,
+ split_type, source_next, split_region,
+ partial_obj_size);
+ gclog_or_tty->print_cr("%s split: dst=" PTR_FORMAT " dst_c=" SIZE_FORMAT
+ " tn=" PTR_FORMAT,
+ split_type, split_destination,
+ addr_to_region_idx(split_destination),
+ *target_next);
+
+ if (partial_obj_size != 0) {
+ HeapWord* const po_beg = split_info.destination();
+ HeapWord* const po_end = po_beg + split_info.partial_obj_size();
+ gclog_or_tty->print_cr("%s split: "
+ "po_beg=" PTR_FORMAT " " SIZE_FORMAT " "
+ "po_end=" PTR_FORMAT " " SIZE_FORMAT,
+ split_type,
+ po_beg, addr_to_region_idx(po_beg),
+ po_end, addr_to_region_idx(po_end));
+ }
+ }
+
+ return source_next;
+}
+
+bool ParallelCompactData::summarize(SplitInfo& split_info,
+ HeapWord* source_beg, HeapWord* source_end,
+ HeapWord** source_next,
+ HeapWord* target_beg, HeapWord* target_end,
+ HeapWord** target_next)
+{
+ if (TraceParallelOldGCSummaryPhase) {
+ HeapWord* const source_next_val = source_next == NULL ? NULL : *source_next;
+ tty->print_cr("sb=" PTR_FORMAT " se=" PTR_FORMAT " sn=" PTR_FORMAT
+ "tb=" PTR_FORMAT " te=" PTR_FORMAT " tn=" PTR_FORMAT,
+ source_beg, source_end, source_next_val,
+ target_beg, target_end, *target_next);
}
size_t cur_region = addr_to_region_idx(source_beg);
@@ -438,45 +617,53 @@
HeapWord *dest_addr = target_beg;
while (cur_region < end_region) {
+ // The destination must be set even if the region has no data.
+ _region_data[cur_region].set_destination(dest_addr);
+
size_t words = _region_data[cur_region].data_size();
-
-#if 1
- assert(pointer_delta(target_end, dest_addr) >= words,
- "source region does not fit into target region");
-#else
- // XXX - need some work on the corner cases here. If the region does not
- // fit, then must either make sure any partial_obj from the region fits, or
- // "undo" the initial part of the partial_obj that is in the previous
- // region.
- if (dest_addr + words >= target_end) {
- // Let the caller know where to continue.
- *target_next = dest_addr;
- *source_next = region_to_addr(cur_region);
- return false;
- }
-#endif // #if 1
-
- _region_data[cur_region].set_destination(dest_addr);
-
- // Set the destination_count for cur_region, and if necessary, update
- // source_region for a destination region. The source_region field is
- // updated if cur_region is the first (left-most) region to be copied to a
- // destination region.
- //
- // The destination_count calculation is a bit subtle. A region that has
- // data that compacts into itself does not count itself as a destination.
- // This maintains the invariant that a zero count means the region is
- // available and can be claimed and then filled.
if (words > 0) {
+ // If cur_region does not fit entirely into the target space, find a point
+ // at which the source space can be 'split' so that part is copied to the
+ // target space and the rest is copied elsewhere.
+ if (dest_addr + words > target_end) {
+ assert(source_next != NULL, "source_next is NULL when splitting");
+ *source_next = summarize_split_space(cur_region, split_info, dest_addr,
+ target_end, target_next);
+ return false;
+ }
+
+ // Compute the destination_count for cur_region, and if necessary, update
+ // source_region for a destination region. The source_region field is
+ // updated if cur_region is the first (left-most) region to be copied to a
+ // destination region.
+ //
+ // The destination_count calculation is a bit subtle. A region that has
+ // data that compacts into itself does not count itself as a destination.
+ // This maintains the invariant that a zero count means the region is
+ // available and can be claimed and then filled.
+ uint destination_count = 0;
+ if (split_info.is_split(cur_region)) {
+ // The current region has been split: the partial object will be copied
+ // to one destination space and the remaining data will be copied to
+ // another destination space. Adjust the initial destination_count and,
+ // if necessary, set the source_region field if the partial object will
+ // cross a destination region boundary.
+ destination_count = split_info.destination_count();
+ if (destination_count == 2) {
+ size_t dest_idx = addr_to_region_idx(split_info.dest_region_addr());
+ _region_data[dest_idx].set_source_region(cur_region);
+ }
+ }
+
HeapWord* const last_addr = dest_addr + words - 1;
const size_t dest_region_1 = addr_to_region_idx(dest_addr);
const size_t dest_region_2 = addr_to_region_idx(last_addr);
-#if 0
+
// Initially assume that the destination regions will be the same and
// adjust the value below if necessary. Under this assumption, if
// cur_region == dest_region_2, then cur_region will be compacted
// completely into itself.
- uint destination_count = cur_region == dest_region_2 ? 0 : 1;
+ destination_count += cur_region == dest_region_2 ? 0 : 1;
if (dest_region_1 != dest_region_2) {
// Destination regions differ; adjust destination_count.
destination_count += 1;
@@ -487,25 +674,6 @@
// region.
_region_data[dest_region_1].set_source_region(cur_region);
}
-#else
- // Initially assume that the destination regions will be different and
- // adjust the value below if necessary. Under this assumption, if
- // cur_region == dest_region2, then cur_region will be compacted partially
- // into dest_region_1 and partially into itself.
- uint destination_count = cur_region == dest_region_2 ? 1 : 2;
- if (dest_region_1 != dest_region_2) {
- // Data from cur_region will be copied to the start of dest_region_2.
- _region_data[dest_region_2].set_source_region(cur_region);
- } else {
- // Destination regions are the same; adjust destination_count.
- destination_count -= 1;
- if (region_offset(dest_addr) == 0) {
- // Data from cur_region will be copied to the start of the destination
- // region.
- _region_data[dest_region_1].set_source_region(cur_region);
- }
- }
-#endif // #if 0
_region_data[cur_region].set_destination_count(destination_count);
_region_data[cur_region].set_data_location(region_to_addr(cur_region));
@@ -558,7 +726,7 @@
size_t live_to_left = bitmap->live_words_in_range(search_start, oop(addr));
result += partial_obj_size + live_to_left;
- assert(result <= addr, "object cannot move to the right");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result);)
return result;
}
@@ -749,6 +917,13 @@
const size_t end_region =
_summary_data.addr_to_region_idx(_summary_data.region_align_up(max_top));
_summary_data.clear_range(beg_region, end_region);
+
+ // Clear the data used to 'split' regions.
+ SplitInfo& split_info = _space_info[id].split_info();
+ if (split_info.is_valid()) {
+ split_info.clear();
+ }
+ DEBUG_ONLY(split_info.verify_clear();)
}
void PSParallelCompact::pre_compact(PreGCValues* pre_gc_values)
@@ -807,10 +982,11 @@
{
TraceTime tm("post compact", print_phases(), true, gclog_or_tty);
- // Clear the marking bitmap and summary data and update top() in each space.
for (unsigned int id = perm_space_id; id < last_space_id; ++id) {
+ // Clear the marking bitmap, summary data and split info.
clear_data_covering_space(SpaceId(id));
- _space_info[id].space()->set_top(_space_info[id].new_top());
+ // Update top(). Must be done after clearing the bitmap and summary data.
+ _space_info[id].publish_new_top();
}
MutableSpace* const eden_space = _space_info[eden_space_id].space();
@@ -1151,6 +1327,13 @@
PSParallelCompact::compute_dense_prefix(const SpaceId id,
bool maximum_compaction)
{
+ if (ParallelOldGCSplitALot) {
+ if (_space_info[id].dense_prefix() != _space_info[id].space()->bottom()) {
+ // The value was chosen to provoke splitting a young gen space; use it.
+ return _space_info[id].dense_prefix();
+ }
+ }
+
const size_t region_size = ParallelCompactData::RegionSize;
const ParallelCompactData& sd = summary_data();
@@ -1239,16 +1422,221 @@
return sd.region_to_addr(best_cp);
}
+#ifndef PRODUCT
+void
+PSParallelCompact::fill_with_live_objects(SpaceId id, HeapWord* const start,
+ size_t words)
+{
+ if (TraceParallelOldGCSummaryPhase) {
+ tty->print_cr("fill_with_live_objects [" PTR_FORMAT " " PTR_FORMAT ") "
+ SIZE_FORMAT, start, start + words, words);
+ }
+
+ ObjectStartArray* const start_array = _space_info[id].start_array();
+ CollectedHeap::fill_with_objects(start, words);
+ for (HeapWord* p = start; p < start + words; p += oop(p)->size()) {
+ _mark_bitmap.mark_obj(p, words);
+ _summary_data.add_obj(p, words);
+ start_array->allocate_block(p);
+ }
+}
+
+void
+PSParallelCompact::summarize_new_objects(SpaceId id, HeapWord* start)
+{
+ ParallelCompactData& sd = summary_data();
+ MutableSpace* space = _space_info[id].space();
+
+ // Find the source and destination start addresses.
+ HeapWord* const src_addr = sd.region_align_down(start);
+ HeapWord* dst_addr;
+ if (src_addr < start) {
+ dst_addr = sd.addr_to_region_ptr(src_addr)->destination();
+ } else if (src_addr > space->bottom()) {
+ // The start (the original top() value) is aligned to a region boundary so
+ // the associated region does not have a destination. Compute the
+ // destination from the previous region.
+ RegionData* const cp = sd.addr_to_region_ptr(src_addr) - 1;
+ dst_addr = cp->destination() + cp->data_size();
+ } else {
+ // Filling the entire space.
+ dst_addr = space->bottom();
+ }
+ assert(dst_addr != NULL, "sanity");
+
+ // Update the summary data.
+ bool result = _summary_data.summarize(_space_info[id].split_info(),
+ src_addr, space->top(), NULL,
+ dst_addr, space->end(),
+ _space_info[id].new_top_addr());
+ assert(result, "should not fail: bad filler object size");
+}
+
+void
+PSParallelCompact::provoke_split_fill_survivor(SpaceId id)
+{
+ if (total_invocations() % (ParallelOldGCSplitInterval * 3) != 0) {
+ return;
+ }
+
+ MutableSpace* const space = _space_info[id].space();
+ if (space->is_empty()) {
+ HeapWord* b = space->bottom();
+ HeapWord* t = b + space->capacity_in_words() / 2;
+ space->set_top(t);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+
+ size_t obj_len = 8;
+ while (b + obj_len <= t) {
+ CollectedHeap::fill_with_object(b, obj_len);
+ mark_bitmap()->mark_obj(b, obj_len);
+ summary_data().add_obj(b, obj_len);
+ b += obj_len;
+ obj_len = (obj_len & 0x18) + 8; // 8 16 24 32 8 16 24 32 ...
+ }
+ if (b < t) {
+ // The loop didn't completely fill to t (top); adjust top downward.
+ space->set_top(b);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+ }
+
+ HeapWord** nta = _space_info[id].new_top_addr();
+ bool result = summary_data().summarize(_space_info[id].split_info(),
+ space->bottom(), space->top(), NULL,
+ space->bottom(), space->end(), nta);
+ assert(result, "space must fit into itself");
+ }
+}
+
+void
+PSParallelCompact::provoke_split(bool & max_compaction)
+{
+ if (total_invocations() % ParallelOldGCSplitInterval != 0) {
+ return;
+ }
+
+ const size_t region_size = ParallelCompactData::RegionSize;
+ ParallelCompactData& sd = summary_data();
+
+ MutableSpace* const eden_space = _space_info[eden_space_id].space();
+ MutableSpace* const from_space = _space_info[from_space_id].space();
+ const size_t eden_live = pointer_delta(eden_space->top(),
+ _space_info[eden_space_id].new_top());
+ const size_t from_live = pointer_delta(from_space->top(),
+ _space_info[from_space_id].new_top());
+
+ const size_t min_fill_size = CollectedHeap::min_fill_size();
+ const size_t eden_free = pointer_delta(eden_space->end(), eden_space->top());
+ const size_t eden_fillable = eden_free >= min_fill_size ? eden_free : 0;
+ const size_t from_free = pointer_delta(from_space->end(), from_space->top());
+ const size_t from_fillable = from_free >= min_fill_size ? from_free : 0;
+
+ // Choose the space to split; need at least 2 regions live (or fillable).
+ SpaceId id;
+ MutableSpace* space;
+ size_t live_words;
+ size_t fill_words;
+ if (eden_live + eden_fillable >= region_size * 2) {
+ id = eden_space_id;
+ space = eden_space;
+ live_words = eden_live;
+ fill_words = eden_fillable;
+ } else if (from_live + from_fillable >= region_size * 2) {
+ id = from_space_id;
+ space = from_space;
+ live_words = from_live;
+ fill_words = from_fillable;
+ } else {
+ return; // Give up.
+ }
+ assert(fill_words == 0 || fill_words >= min_fill_size, "sanity");
+
+ if (live_words < region_size * 2) {
+ // Fill from top() to end() w/live objects of mixed sizes.
+ HeapWord* const fill_start = space->top();
+ live_words += fill_words;
+
+ space->set_top(fill_start + fill_words);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+
+ HeapWord* cur_addr = fill_start;
+ while (fill_words > 0) {
+ const size_t r = (size_t)os::random() % (region_size / 2) + min_fill_size;
+ size_t cur_size = MIN2(align_object_size_(r), fill_words);
+ if (fill_words - cur_size < min_fill_size) {
+ cur_size = fill_words; // Avoid leaving a fragment too small to fill.
+ }
+
+ CollectedHeap::fill_with_object(cur_addr, cur_size);
+ mark_bitmap()->mark_obj(cur_addr, cur_size);
+ sd.add_obj(cur_addr, cur_size);
+
+ cur_addr += cur_size;
+ fill_words -= cur_size;
+ }
+
+ summarize_new_objects(id, fill_start);
+ }
+
+ max_compaction = false;
+
+ // Manipulate the old gen so that it has room for about half of the live data
+ // in the target young gen space (live_words / 2).
+ id = old_space_id;
+ space = _space_info[id].space();
+ const size_t free_at_end = space->free_in_words();
+ const size_t free_target = align_object_size(live_words / 2);
+ const size_t dead = pointer_delta(space->top(), _space_info[id].new_top());
+
+ if (free_at_end >= free_target + min_fill_size) {
+ // Fill space above top() and set the dense prefix so everything survives.
+ HeapWord* const fill_start = space->top();
+ const size_t fill_size = free_at_end - free_target;
+ space->set_top(space->top() + fill_size);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+ fill_with_live_objects(id, fill_start, fill_size);
+ summarize_new_objects(id, fill_start);
+ _space_info[id].set_dense_prefix(sd.region_align_down(space->top()));
+ } else if (dead + free_at_end > free_target) {
+ // Find a dense prefix that makes the right amount of space available.
+ HeapWord* cur = sd.region_align_down(space->top());
+ HeapWord* cur_destination = sd.addr_to_region_ptr(cur)->destination();
+ size_t dead_to_right = pointer_delta(space->end(), cur_destination);
+ while (dead_to_right < free_target) {
+ cur -= region_size;
+ cur_destination = sd.addr_to_region_ptr(cur)->destination();
+ dead_to_right = pointer_delta(space->end(), cur_destination);
+ }
+ _space_info[id].set_dense_prefix(cur);
+ }
+}
+#endif // #ifndef PRODUCT
+
void PSParallelCompact::summarize_spaces_quick()
{
for (unsigned int i = 0; i < last_space_id; ++i) {
const MutableSpace* space = _space_info[i].space();
- bool result = _summary_data.summarize(space->bottom(), space->end(),
- space->bottom(), space->top(),
- _space_info[i].new_top_addr());
- assert(result, "should never fail");
+ HeapWord** nta = _space_info[i].new_top_addr();
+ bool result = _summary_data.summarize(_space_info[i].split_info(),
+ space->bottom(), space->top(), NULL,
+ space->bottom(), space->end(), nta);
+ assert(result, "space must fit into itself");
_space_info[i].set_dense_prefix(space->bottom());
}
+
+#ifndef PRODUCT
+ if (ParallelOldGCSplitALot) {
+ provoke_split_fill_survivor(to_space_id);
+ }
+#endif // #ifndef PRODUCT
}
void PSParallelCompact::fill_dense_prefix_end(SpaceId id)
@@ -1308,8 +1696,7 @@
}
#endif // #ifdef _LP64
- MemRegion region(obj_beg, obj_len);
- SharedHeap::fill_region_with_object(region);
+ CollectedHeap::fill_with_object(obj_beg, obj_len);
_mark_bitmap.mark_obj(obj_beg, obj_len);
_summary_data.add_obj(obj_beg, obj_len);
assert(start_array(id) != NULL, "sanity");
@@ -1318,11 +1705,23 @@
}
void
+PSParallelCompact::clear_source_region(HeapWord* beg_addr, HeapWord* end_addr)
+{
+ RegionData* const beg_ptr = _summary_data.addr_to_region_ptr(beg_addr);
+ HeapWord* const end_aligned_up = _summary_data.region_align_up(end_addr);
+ RegionData* const end_ptr = _summary_data.addr_to_region_ptr(end_aligned_up);
+ for (RegionData* cur = beg_ptr; cur < end_ptr; ++cur) {
+ cur->set_source_region(0);
+ }
+}
+
+void
PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction)
{
assert(id < last_space_id, "id out of range");
- assert(_space_info[id].dense_prefix() == _space_info[id].space()->bottom(),
- "should have been set in summarize_spaces_quick()");
+ assert(_space_info[id].dense_prefix() == _space_info[id].space()->bottom() ||
+ ParallelOldGCSplitALot && id == old_space_id,
+ "should have been reset in summarize_spaces_quick()");
const MutableSpace* space = _space_info[id].space();
if (_space_info[id].new_top() != space->bottom()) {
@@ -1338,20 +1737,24 @@
}
#endif // #ifndef PRODUCT
- // If dead space crosses the dense prefix boundary, it is (at least
- // partially) filled with a dummy object, marked live and added to the
- // summary data. This simplifies the copy/update phase and must be done
- // before the final locations of objects are determined, to prevent leaving
- // a fragment of dead space that is too small to fill with an object.
+ // Recompute the summary data, taking into account the dense prefix. If
+ // every last byte will be reclaimed, then the existing summary data which
+ // compacts everything can be left in place.
if (!maximum_compaction && dense_prefix_end != space->bottom()) {
+ // If dead space crosses the dense prefix boundary, it is (at least
+ // partially) filled with a dummy object, marked live and added to the
+ // summary data. This simplifies the copy/update phase and must be done
+ // before the final locations of objects are determined, to prevent
+ // leaving a fragment of dead space that is too small to fill.
fill_dense_prefix_end(id);
+
+ // Compute the destination of each Region, and thus each object.
+ _summary_data.summarize_dense_prefix(space->bottom(), dense_prefix_end);
+ _summary_data.summarize(_space_info[id].split_info(),
+ dense_prefix_end, space->top(), NULL,
+ dense_prefix_end, space->end(),
+ _space_info[id].new_top_addr());
}
-
- // Compute the destination of each Region, and thus each object.
- _summary_data.summarize_dense_prefix(space->bottom(), dense_prefix_end);
- _summary_data.summarize(dense_prefix_end, space->end(),
- dense_prefix_end, space->top(),
- _space_info[id].new_top_addr());
}
if (TraceParallelOldGCSummaryPhase) {
@@ -1371,6 +1774,30 @@
}
}
+#ifndef PRODUCT
+void PSParallelCompact::summary_phase_msg(SpaceId dst_space_id,
+ HeapWord* dst_beg, HeapWord* dst_end,
+ SpaceId src_space_id,
+ HeapWord* src_beg, HeapWord* src_end)
+{
+ if (TraceParallelOldGCSummaryPhase) {
+ tty->print_cr("summarizing %d [%s] into %d [%s]: "
+ "src=" PTR_FORMAT "-" PTR_FORMAT " "
+ SIZE_FORMAT "-" SIZE_FORMAT " "
+ "dst=" PTR_FORMAT "-" PTR_FORMAT " "
+ SIZE_FORMAT "-" SIZE_FORMAT,
+ src_space_id, space_names[src_space_id],
+ dst_space_id, space_names[dst_space_id],
+ src_beg, src_end,
+ _summary_data.addr_to_region_idx(src_beg),
+ _summary_data.addr_to_region_idx(src_end),
+ dst_beg, dst_end,
+ _summary_data.addr_to_region_idx(dst_beg),
+ _summary_data.addr_to_region_idx(dst_end));
+ }
+}
+#endif // #ifndef PRODUCT
+
void PSParallelCompact::summary_phase(ParCompactionManager* cm,
bool maximum_compaction)
{
@@ -1403,57 +1830,80 @@
// The amount of live data that will end up in old space (assuming it fits).
size_t old_space_total_live = 0;
- unsigned int id;
- for (id = old_space_id; id < last_space_id; ++id) {
+ assert(perm_space_id < old_space_id, "should not count perm data here");
+ for (unsigned int id = old_space_id; id < last_space_id; ++id) {
old_space_total_live += pointer_delta(_space_info[id].new_top(),
_space_info[id].space()->bottom());
}
- const MutableSpace* old_space = _space_info[old_space_id].space();
- if (old_space_total_live > old_space->capacity_in_words()) {
+ MutableSpace* const old_space = _space_info[old_space_id].space();
+ const size_t old_capacity = old_space->capacity_in_words();
+ if (old_space_total_live > old_capacity) {
// XXX - should also try to expand
maximum_compaction = true;
- } else if (!UseParallelOldGCDensePrefix) {
- maximum_compaction = true;
}
+#ifndef PRODUCT
+ if (ParallelOldGCSplitALot && old_space_total_live < old_capacity) {
+ provoke_split(maximum_compaction);
+ }
+#endif // #ifndef PRODUCT
// Permanent and Old generations.
summarize_space(perm_space_id, maximum_compaction);
summarize_space(old_space_id, maximum_compaction);
- // Summarize the remaining spaces (those in the young gen) into old space. If
- // the live data from a space doesn't fit, the existing summarization is left
- // intact, so the data is compacted down within the space itself.
- HeapWord** new_top_addr = _space_info[old_space_id].new_top_addr();
- HeapWord* const target_space_end = old_space->end();
- for (id = eden_space_id; id < last_space_id; ++id) {
+ // Summarize the remaining spaces in the young gen. The initial target space
+ // is the old gen. If a space does not fit entirely into the target, then the
+ // remainder is compacted into the space itself and that space becomes the new
+ // target.
+ SpaceId dst_space_id = old_space_id;
+ HeapWord* dst_space_end = old_space->end();
+ HeapWord** new_top_addr = _space_info[dst_space_id].new_top_addr();
+ for (unsigned int id = eden_space_id; id < last_space_id; ++id) {
const MutableSpace* space = _space_info[id].space();
const size_t live = pointer_delta(_space_info[id].new_top(),
space->bottom());
- const size_t available = pointer_delta(target_space_end, *new_top_addr);
+ const size_t available = pointer_delta(dst_space_end, *new_top_addr);
+
+ NOT_PRODUCT(summary_phase_msg(dst_space_id, *new_top_addr, dst_space_end,
+ SpaceId(id), space->bottom(), space->top());)
if (live > 0 && live <= available) {
// All the live data will fit.
- if (TraceParallelOldGCSummaryPhase) {
- tty->print_cr("summarizing %d into old_space @ " PTR_FORMAT,
- id, *new_top_addr);
- }
- _summary_data.summarize(*new_top_addr, target_space_end,
- space->bottom(), space->top(),
- new_top_addr);
-
- // Clear the source_region field for each region in the space.
- HeapWord* const new_top = _space_info[id].new_top();
- HeapWord* const clear_end = _summary_data.region_align_up(new_top);
- RegionData* beg_region =
- _summary_data.addr_to_region_ptr(space->bottom());
- RegionData* end_region = _summary_data.addr_to_region_ptr(clear_end);
- while (beg_region < end_region) {
- beg_region->set_source_region(0);
- ++beg_region;
- }
+ bool done = _summary_data.summarize(_space_info[id].split_info(),
+ space->bottom(), space->top(),
+ NULL,
+ *new_top_addr, dst_space_end,
+ new_top_addr);
+ assert(done, "space must fit into old gen");
// Reset the new_top value for the space.
_space_info[id].set_new_top(space->bottom());
+ } else if (live > 0) {
+ // Attempt to fit part of the source space into the target space.
+ HeapWord* next_src_addr = NULL;
+ bool done = _summary_data.summarize(_space_info[id].split_info(),
+ space->bottom(), space->top(),
+ &next_src_addr,
+ *new_top_addr, dst_space_end,
+ new_top_addr);
+ assert(!done, "space should not fit into old gen");
+ assert(next_src_addr != NULL, "sanity");
+
+ // The source space becomes the new target, so the remainder is compacted
+ // within the space itself.
+ dst_space_id = SpaceId(id);
+ dst_space_end = space->end();
+ new_top_addr = _space_info[id].new_top_addr();
+ NOT_PRODUCT(summary_phase_msg(dst_space_id,
+ space->bottom(), dst_space_end,
+ SpaceId(id), next_src_addr, space->top());)
+ done = _summary_data.summarize(_space_info[id].split_info(),
+ next_src_addr, space->top(),
+ NULL,
+ space->bottom(), dst_space_end,
+ new_top_addr);
+ assert(done, "space must fit when compacted into itself");
+ assert(*new_top_addr <= space->top(), "usage should not grow");
}
}
@@ -1807,9 +2257,14 @@
// Fill the unused part of the old gen.
MutableSpace* const old_space = old_gen->object_space();
- MemRegion old_gen_unused(old_space->top(), old_space->end());
- if (!old_gen_unused.is_empty()) {
- SharedHeap::fill_region_with_object(old_gen_unused);
+ HeapWord* const unused_start = old_space->top();
+ size_t const unused_words = pointer_delta(old_space->end(), unused_start);
+
+ if (unused_words > 0) {
+ if (unused_words < CollectedHeap::min_fill_size()) {
+ return false; // If the old gen cannot be filled, must give up.
+ }
+ CollectedHeap::fill_with_objects(unused_start, unused_words);
}
// Take the live data from eden and set both top and end in the old gen to
@@ -1825,9 +2280,8 @@
// Update the object start array for the filler object and the data from eden.
ObjectStartArray* const start_array = old_gen->start_array();
- HeapWord* const start = old_gen_unused.start();
- for (HeapWord* addr = start; addr < new_top; addr += oop(addr)->size()) {
- start_array->allocate_block(addr);
+ for (HeapWord* p = unused_start; p < new_top; p += oop(p)->size()) {
+ start_array->allocate_block(p);
}
// Could update the promoted average here, but it is not typically updated at
@@ -2048,14 +2502,13 @@
// regions in the dense prefix. Assume that 1 gc thread
// will work on opening the gaps and the remaining gc threads
// will work on the dense prefix.
- SpaceId space_id = old_space_id;
- while (space_id != last_space_id) {
+ unsigned int space_id;
+ for (space_id = old_space_id; space_id < last_space_id; ++ space_id) {
HeapWord* const dense_prefix_end = _space_info[space_id].dense_prefix();
const MutableSpace* const space = _space_info[space_id].space();
if (dense_prefix_end == space->bottom()) {
// There is no dense prefix for this space.
- space_id = next_compaction_space_id(space_id);
continue;
}
@@ -2105,23 +2558,20 @@
// region_index_end is not processed
size_t region_index_end = MIN2(region_index_start + regions_per_thread,
region_index_end_dense_prefix);
- q->enqueue(new UpdateDensePrefixTask(
- space_id,
- region_index_start,
- region_index_end));
+ q->enqueue(new UpdateDensePrefixTask(SpaceId(space_id),
+ region_index_start,
+ region_index_end));
region_index_start = region_index_end;
}
}
// This gets any part of the dense prefix that did not
// fit evenly.
if (region_index_start < region_index_end_dense_prefix) {
- q->enqueue(new UpdateDensePrefixTask(
- space_id,
- region_index_start,
- region_index_end_dense_prefix));
+ q->enqueue(new UpdateDensePrefixTask(SpaceId(space_id),
+ region_index_start,
+ region_index_end_dense_prefix));
}
- space_id = next_compaction_space_id(space_id);
- } // End tasks for dense prefix
+ }
}
void PSParallelCompact::enqueue_region_stealing_tasks(
@@ -2567,16 +3017,24 @@
return m->bit_to_addr(cur_beg);
}
-HeapWord*
-PSParallelCompact::first_src_addr(HeapWord* const dest_addr,
- size_t src_region_idx)
+HeapWord* PSParallelCompact::first_src_addr(HeapWord* const dest_addr,
+ SpaceId src_space_id,
+ size_t src_region_idx)
{
+ assert(summary_data().is_region_aligned(dest_addr), "not aligned");
+
+ const SplitInfo& split_info = _space_info[src_space_id].split_info();
+ if (split_info.dest_region_addr() == dest_addr) {
+ // The partial object ending at the split point contains the first word to
+ // be copied to dest_addr.
+ return split_info.first_src_addr();
+ }
+
+ const ParallelCompactData& sd = summary_data();
ParMarkBitMap* const bitmap = mark_bitmap();
- const ParallelCompactData& sd = summary_data();
const size_t RegionSize = ParallelCompactData::RegionSize;
assert(sd.is_region_aligned(dest_addr), "not aligned");
-
const RegionData* const src_region_ptr = sd.region(src_region_idx);
const size_t partial_obj_size = src_region_ptr->partial_obj_size();
HeapWord* const src_region_destination = src_region_ptr->destination();
@@ -2625,19 +3083,34 @@
}
void PSParallelCompact::decrement_destination_counts(ParCompactionManager* cm,
+ SpaceId src_space_id,
size_t beg_region,
HeapWord* end_addr)
{
ParallelCompactData& sd = summary_data();
+
+#ifdef ASSERT
+ MutableSpace* const src_space = _space_info[src_space_id].space();
+ HeapWord* const beg_addr = sd.region_to_addr(beg_region);
+ assert(src_space->contains(beg_addr) || beg_addr == src_space->end(),
+ "src_space_id does not match beg_addr");
+ assert(src_space->contains(end_addr) || end_addr == src_space->end(),
+ "src_space_id does not match end_addr");
+#endif // #ifdef ASSERT
+
RegionData* const beg = sd.region(beg_region);
- HeapWord* const end_addr_aligned_up = sd.region_align_up(end_addr);
- RegionData* const end = sd.addr_to_region_ptr(end_addr_aligned_up);
- size_t cur_idx = beg_region;
- for (RegionData* cur = beg; cur < end; ++cur, ++cur_idx) {
+ RegionData* const end = sd.addr_to_region_ptr(sd.region_align_up(end_addr));
+
+ // Regions up to new_top() are enqueued if they become available.
+ HeapWord* const new_top = _space_info[src_space_id].new_top();
+ RegionData* const enqueue_end =
+ sd.addr_to_region_ptr(sd.region_align_up(new_top));
+
+ for (RegionData* cur = beg; cur < end; ++cur) {
assert(cur->data_size() > 0, "region must have live data");
cur->decrement_destination_count();
- if (cur_idx <= cur->source_region() && cur->available() && cur->claim()) {
- cm->save_for_processing(cur_idx);
+ if (cur < enqueue_end && cur->available() && cur->claim()) {
+ cm->save_for_processing(sd.region(cur));
}
}
}
@@ -2737,7 +3210,7 @@
HeapWord* src_space_top = _space_info[src_space_id].space()->top();
MoveAndUpdateClosure closure(bitmap, cm, start_array, dest_addr, words);
- closure.set_source(first_src_addr(dest_addr, src_region_idx));
+ closure.set_source(first_src_addr(dest_addr, src_space_id, src_region_idx));
// Adjust src_region_idx to prepare for decrementing destination counts (the
// destination count is not decremented when a region is copied to itself).
@@ -2752,7 +3225,8 @@
HeapWord* const old_src_addr = closure.source();
closure.copy_partial_obj();
if (closure.is_full()) {
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_deferred_obj_addr(NULL);
region_ptr->set_completed();
return;
@@ -2761,7 +3235,7 @@
HeapWord* const end_addr = sd.region_align_down(closure.source());
if (sd.region_align_down(old_src_addr) != end_addr) {
// The partial object was copied from more than one source region.
- decrement_destination_counts(cm, src_region_idx, end_addr);
+ decrement_destination_counts(cm, src_space_id, src_region_idx, end_addr);
// Move to the next source region, possibly switching spaces as well. All
// args except end_addr may be modified.
@@ -2801,19 +3275,21 @@
region_ptr->set_deferred_obj_addr(closure.destination());
status = closure.copy_until_full(); // copies from closure.source()
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_completed();
return;
}
if (status == ParMarkBitMap::full) {
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_deferred_obj_addr(NULL);
region_ptr->set_completed();
return;
}
- decrement_destination_counts(cm, src_region_idx, end_addr);
+ decrement_destination_counts(cm, src_space_id, src_region_idx, end_addr);
// Move to the next source region, possibly switching spaces as well. All
// args except end_addr may be modified.
@@ -2892,7 +3368,7 @@
ParMarkBitMap::IterationStatus MoveAndUpdateClosure::copy_until_full()
{
if (source() != destination()) {
- assert(source() > destination(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words_remaining());
}
update_state(words_remaining());
@@ -2913,7 +3389,7 @@
// This test is necessary; if omitted, the pointer updates to a partial object
// that crosses the dense prefix boundary could be overwritten.
if (source() != destination()) {
- assert(source() > destination(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words);
}
update_state(words);
@@ -2938,7 +3414,7 @@
}
if (destination() != source()) {
- assert(destination() < source(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words);
}
@@ -3008,34 +3484,3 @@
summary_data().calc_new_pointer(Universe::intArrayKlassObj());
}
-// The initial implementation of this method created a field
-// _next_compaction_space_id in SpaceInfo and initialized
-// that field in SpaceInfo::initialize_space_info(). That
-// required that _next_compaction_space_id be declared a
-// SpaceId in SpaceInfo and that would have required that
-// either SpaceId be declared in a separate class or that
-// it be declared in SpaceInfo. It didn't seem consistent
-// to declare it in SpaceInfo (didn't really fit logically).
-// Alternatively, defining a separate class to define SpaceId
-// seem excessive. This implementation is simple and localizes
-// the knowledge.
-
-PSParallelCompact::SpaceId
-PSParallelCompact::next_compaction_space_id(SpaceId id) {
- assert(id < last_space_id, "id out of range");
- switch (id) {
- case perm_space_id :
- return last_space_id;
- case old_space_id :
- return eden_space_id;
- case eden_space_id :
- return from_space_id;
- case from_space_id :
- return to_space_id;
- case to_space_id :
- return last_space_id;
- default:
- assert(false, "Bad space id");
- return last_space_id;
- }
-}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -36,6 +36,123 @@
class MoveAndUpdateClosure;
class RefProcTaskExecutor;
+// The SplitInfo class holds the information needed to 'split' a source region
+// so that the live data can be copied to two destination *spaces*. Normally,
+// all the live data in a region is copied to a single destination space (e.g.,
+// everything live in a region in eden is copied entirely into the old gen).
+// However, when the heap is nearly full, all the live data in eden may not fit
+// into the old gen. Copying only some of the regions from eden to old gen
+// requires finding a region that does not contain a partial object (i.e., no
+// live object crosses the region boundary) somewhere near the last object that
+// does fit into the old gen. Since it's not always possible to find such a
+// region, splitting is necessary for predictable behavior.
+//
+// A region is always split at the end of the partial object. This avoids
+// additional tests when calculating the new location of a pointer, which is a
+// very hot code path. The partial object and everything to its left will be
+// copied to another space (call it dest_space_1). The live data to the right
+// of the partial object will be copied either within the space itself, or to a
+// different destination space (distinct from dest_space_1).
+//
+// Split points are identified during the summary phase, when region
+// destinations are computed: data about the split, including the
+// partial_object_size, is recorded in a SplitInfo record and the
+// partial_object_size field in the summary data is set to zero. The zeroing is
+// possible (and necessary) since the partial object will move to a different
+// destination space than anything to its right, thus the partial object should
+// not affect the locations of any objects to its right.
+//
+// The recorded data is used during the compaction phase, but only rarely: when
+// the partial object on the split region will be copied across a destination
+// region boundary. This test is made once each time a region is filled, and is
+// a simple address comparison, so the overhead is negligible (see
+// PSParallelCompact::first_src_addr()).
+//
+// Notes:
+//
+// Only regions with partial objects are split; a region without a partial
+// object does not need any extra bookkeeping.
+//
+// At most one region is split per space, so the amount of data required is
+// constant.
+//
+// A region is split only when the destination space would overflow. Once that
+// happens, the destination space is abandoned and no other data (even from
+// other source spaces) is targeted to that destination space. Abandoning the
+// destination space may leave a somewhat large unused area at the end, if a
+// large object caused the overflow.
+//
+// Future work:
+//
+// More bookkeeping would be required to continue to use the destination space.
+// The most general solution would allow data from regions in two different
+// source spaces to be "joined" in a single destination region. At the very
+// least, additional code would be required in next_src_region() to detect the
+// join and skip to an out-of-order source region. If the join region was also
+// the last destination region to which a split region was copied (the most
+// likely case), then additional work would be needed to get fill_region() to
+// stop iteration and switch to a new source region at the right point. Basic
+// idea would be to use a fake value for the top of the source space. It is
+// doable, if a bit tricky.
+//
+// A simpler (but less general) solution would fill the remainder of the
+// destination region with a dummy object and continue filling the next
+// destination region.
+
+class SplitInfo
+{
+public:
+ // Return true if this split info is valid (i.e., if a split has been
+ // recorded). The very first region cannot have a partial object and thus is
+ // never split, so 0 is the 'invalid' value.
+ bool is_valid() const { return _src_region_idx > 0; }
+
+ // Return true if this split holds data for the specified source region.
+ inline bool is_split(size_t source_region) const;
+
+ // The index of the split region, the size of the partial object on that
+ // region and the destination of the partial object.
+ size_t src_region_idx() const { return _src_region_idx; }
+ size_t partial_obj_size() const { return _partial_obj_size; }
+ HeapWord* destination() const { return _destination; }
+
+ // The destination count of the partial object referenced by this split
+ // (either 1 or 2). This must be added to the destination count of the
+ // remainder of the source region.
+ unsigned int destination_count() const { return _destination_count; }
+
+ // If a word within the partial object will be written to the first word of a
+ // destination region, this is the address of the destination region;
+ // otherwise this is NULL.
+ HeapWord* dest_region_addr() const { return _dest_region_addr; }
+
+ // If a word within the partial object will be written to the first word of a
+ // destination region, this is the address of that word within the partial
+ // object; otherwise this is NULL.
+ HeapWord* first_src_addr() const { return _first_src_addr; }
+
+ // Record the data necessary to split the region src_region_idx.
+ void record(size_t src_region_idx, size_t partial_obj_size,
+ HeapWord* destination);
+
+ void clear();
+
+ DEBUG_ONLY(void verify_clear();)
+
+private:
+ size_t _src_region_idx;
+ size_t _partial_obj_size;
+ HeapWord* _destination;
+ unsigned int _destination_count;
+ HeapWord* _dest_region_addr;
+ HeapWord* _first_src_addr;
+};
+
+inline bool SplitInfo::is_split(size_t region_idx) const
+{
+ return _src_region_idx == region_idx && is_valid();
+}
+
class SpaceInfo
{
public:
@@ -58,18 +175,23 @@
// is no start array.
ObjectStartArray* start_array() const { return _start_array; }
+ SplitInfo& split_info() { return _split_info; }
+
void set_space(MutableSpace* s) { _space = s; }
void set_new_top(HeapWord* addr) { _new_top = addr; }
void set_min_dense_prefix(HeapWord* addr) { _min_dense_prefix = addr; }
void set_dense_prefix(HeapWord* addr) { _dense_prefix = addr; }
void set_start_array(ObjectStartArray* s) { _start_array = s; }
+ void publish_new_top() const { _space->set_top(_new_top); }
+
private:
MutableSpace* _space;
HeapWord* _new_top;
HeapWord* _min_dense_prefix;
HeapWord* _dense_prefix;
ObjectStartArray* _start_array;
+ SplitInfo _split_info;
};
class ParallelCompactData
@@ -230,9 +352,14 @@
// must be region-aligned; end need not be.
void summarize_dense_prefix(HeapWord* beg, HeapWord* end);
- bool summarize(HeapWord* target_beg, HeapWord* target_end,
+ HeapWord* summarize_split_space(size_t src_region, SplitInfo& split_info,
+ HeapWord* destination, HeapWord* target_end,
+ HeapWord** target_next);
+ bool summarize(SplitInfo& split_info,
HeapWord* source_beg, HeapWord* source_end,
- HeapWord** target_next, HeapWord** source_next = 0);
+ HeapWord** source_next,
+ HeapWord* target_beg, HeapWord* target_end,
+ HeapWord** target_next);
void clear();
void clear_range(size_t beg_region, size_t end_region);
@@ -838,13 +965,31 @@
// non-empty.
static void fill_dense_prefix_end(SpaceId id);
+ // Clear the summary data source_region field for the specified addresses.
+ static void clear_source_region(HeapWord* beg_addr, HeapWord* end_addr);
+
+#ifndef PRODUCT
+ // Routines to provoke splitting a young gen space (ParallelOldGCSplitALot).
+
+ // Fill the region [start, start + words) with live object(s). Only usable
+ // for the old and permanent generations.
+ static void fill_with_live_objects(SpaceId id, HeapWord* const start,
+ size_t words);
+ // Include the new objects in the summary data.
+ static void summarize_new_objects(SpaceId id, HeapWord* start);
+
+ // Add live objects to a survivor space since it's rare that both survivors
+ // are non-empty.
+ static void provoke_split_fill_survivor(SpaceId id);
+
+ // Add live objects and/or choose the dense prefix to provoke splitting.
+ static void provoke_split(bool & maximum_compaction);
+#endif
+
static void summarize_spaces_quick();
static void summarize_space(SpaceId id, bool maximum_compaction);
static void summary_phase(ParCompactionManager* cm, bool maximum_compaction);
- // The space that is compacted after space_id.
- static SpaceId next_compaction_space_id(SpaceId space_id);
-
// Adjust addresses in roots. Does not adjust addresses in heap.
static void adjust_roots();
@@ -999,6 +1144,7 @@
// Return the address of the word to be copied to dest_addr, which must be
// aligned to a region boundary.
static HeapWord* first_src_addr(HeapWord* const dest_addr,
+ SpaceId src_space_id,
size_t src_region_idx);
// Determine the next source region, set closure.source() to the start of the
@@ -1012,8 +1158,10 @@
HeapWord* end_addr);
// Decrement the destination count for each non-empty source region in the
- // range [beg_region, region(region_align_up(end_addr))).
+ // range [beg_region, region(region_align_up(end_addr))). If the destination
+ // count for a region goes to 0 and it needs to be filled, enqueue it.
static void decrement_destination_counts(ParCompactionManager* cm,
+ SpaceId src_space_id,
size_t beg_region,
HeapWord* end_addr);
@@ -1081,9 +1229,15 @@
const SpaceId id,
const bool maximum_compaction,
HeapWord* const addr);
+ static void summary_phase_msg(SpaceId dst_space_id,
+ HeapWord* dst_beg, HeapWord* dst_end,
+ SpaceId src_space_id,
+ HeapWord* src_beg, HeapWord* src_end);
#endif // #ifndef PRODUCT
#ifdef ASSERT
+ // Sanity check the new location of a word in the heap.
+ static inline void check_new_location(HeapWord* old_addr, HeapWord* new_addr);
// Verify that all the regions have been emptied.
static void verify_complete(SpaceId space_id);
#endif // #ifdef ASSERT
@@ -1251,6 +1405,15 @@
}
}
+#ifdef ASSERT
+inline void
+PSParallelCompact::check_new_location(HeapWord* old_addr, HeapWord* new_addr)
+{
+ assert(old_addr >= new_addr || space_id(old_addr) != space_id(new_addr),
+ "must move left or to a different space");
+}
+#endif // ASSERT
+
class MoveAndUpdateClosure: public ParMarkBitMapClosure {
public:
inline MoveAndUpdateClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm,
@@ -1324,31 +1487,28 @@
oop(addr)->update_contents(compaction_manager());
}
-class FillClosure: public ParMarkBitMapClosure {
- public:
+class FillClosure: public ParMarkBitMapClosure
+{
+public:
FillClosure(ParCompactionManager* cm, PSParallelCompact::SpaceId space_id) :
ParMarkBitMapClosure(PSParallelCompact::mark_bitmap(), cm),
- _space_id(space_id),
- _start_array(PSParallelCompact::start_array(space_id)) {
- assert(_space_id == PSParallelCompact::perm_space_id ||
- _space_id == PSParallelCompact::old_space_id,
+ _start_array(PSParallelCompact::start_array(space_id))
+ {
+ assert(space_id == PSParallelCompact::perm_space_id ||
+ space_id == PSParallelCompact::old_space_id,
"cannot use FillClosure in the young gen");
- assert(bitmap() != NULL, "need a bitmap");
- assert(_start_array != NULL, "need a start array");
- }
-
- void fill_region(HeapWord* addr, size_t size) {
- MemRegion region(addr, size);
- SharedHeap::fill_region_with_object(region);
- _start_array->allocate_block(addr);
}
virtual IterationStatus do_addr(HeapWord* addr, size_t size) {
- fill_region(addr, size);
+ CollectedHeap::fill_with_objects(addr, size);
+ HeapWord* const end = addr + size;
+ do {
+ _start_array->allocate_block(addr);
+ addr += oop(addr)->size();
+ } while (addr < end);
return ParMarkBitMap::incomplete;
}
private:
- const PSParallelCompact::SpaceId _space_id;
- ObjectStartArray* const _start_array;
+ ObjectStartArray* const _start_array;
};
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -499,26 +499,15 @@
// We lost, someone else "owns" this object
guarantee(o->is_forwarded(), "Object must be forwarded if the cas failed.");
- // Unallocate the space used. NOTE! We may have directly allocated
- // the object. If so, we cannot deallocate it, so we have to test!
+ // Try to deallocate the space. If it was directly allocated we cannot
+ // deallocate it, so we have to test. If the deallocation fails,
+ // overwrite with a filler object.
if (new_obj_is_tenured) {
if (!_old_lab.unallocate_object(new_obj)) {
- // The promotion lab failed to unallocate the object.
- // We need to overwrite the object with a filler that
- // contains no interior pointers.
- MemRegion mr((HeapWord*)new_obj, new_obj_size);
- // Clean this up and move to oopFactory (see bug 4718422)
- SharedHeap::fill_region_with_object(mr);
+ CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);
}
- } else {
- if (!_young_lab.unallocate_object(new_obj)) {
- // The promotion lab failed to unallocate the object.
- // We need to overwrite the object with a filler that
- // contains no interior pointers.
- MemRegion mr((HeapWord*)new_obj, new_obj_size);
- // Clean this up and move to oopFactory (see bug 4718422)
- SharedHeap::fill_region_with_object(mr);
- }
+ } else if (!_young_lab.unallocate_object(new_obj)) {
+ CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);
}
// don't update this before the unallocation!
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -76,8 +76,8 @@
MutableSpace *s = ls->space();
if (s->top() < top()) { // For all spaces preceeding the one containing top()
if (s->free_in_words() > 0) {
- SharedHeap::fill_region_with_object(MemRegion(s->top(), s->end()));
size_t area_touched_words = pointer_delta(s->end(), s->top());
+ CollectedHeap::fill_with_object(s->top(), area_touched_words);
#ifndef ASSERT
if (!ZapUnusedHeapArea) {
area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
@@ -686,11 +686,11 @@
// a minimal object; assuming that's not the last chunk in which case we don't care.
if (i < lgrp_spaces()->length() - 1) {
size_t remainder = pointer_delta(s->end(), value);
- const size_t minimal_object_size = oopDesc::header_size();
- if (remainder < minimal_object_size && remainder > 0) {
- // Add a filler object of a minimal size, it will cross the chunk boundary.
- SharedHeap::fill_region_with_object(MemRegion(value, minimal_object_size));
- value += minimal_object_size;
+ const size_t min_fill_size = CollectedHeap::min_fill_size();
+ if (remainder < min_fill_size && remainder > 0) {
+ // Add a minimum size filler object; it will cross the chunk boundary.
+ CollectedHeap::fill_with_object(value, min_fill_size);
+ value += min_fill_size;
assert(!s->contains(value), "Should be in the next chunk");
// Restart the loop from the same chunk, since the value has moved
// to the next one.
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -30,12 +30,21 @@
int CollectedHeap::_fire_out_of_memory_count = 0;
#endif
+size_t CollectedHeap::_filler_array_max_size = 0;
+
// Memory state functions.
-CollectedHeap::CollectedHeap() :
- _reserved(), _barrier_set(NULL), _is_gc_active(false),
- _total_collections(0), _total_full_collections(0),
- _gc_cause(GCCause::_no_gc), _gc_lastcause(GCCause::_no_gc) {
+CollectedHeap::CollectedHeap()
+{
+ const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
+ const size_t elements_per_word = HeapWordSize / sizeof(jint);
+ _filler_array_max_size = align_object_size(filler_array_hdr_size() +
+ max_len * elements_per_word);
+
+ _barrier_set = NULL;
+ _is_gc_active = false;
+ _total_collections = _total_full_collections = 0;
+ _gc_cause = _gc_lastcause = GCCause::_no_gc;
NOT_PRODUCT(_promotion_failure_alot_count = 0;)
NOT_PRODUCT(_promotion_failure_alot_gc_number = 0;)
@@ -128,6 +137,94 @@
return obj;
}
+size_t CollectedHeap::filler_array_hdr_size() {
+ return size_t(arrayOopDesc::header_size(T_INT));
+}
+
+size_t CollectedHeap::filler_array_min_size() {
+ return align_object_size(filler_array_hdr_size());
+}
+
+size_t CollectedHeap::filler_array_max_size() {
+ return _filler_array_max_size;
+}
+
+#ifdef ASSERT
+void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
+{
+ assert(words >= min_fill_size(), "too small to fill");
+ assert(words % MinObjAlignment == 0, "unaligned size");
+ assert(Universe::heap()->is_in_reserved(start), "not in heap");
+ assert(Universe::heap()->is_in_reserved(start + words - 1), "not in heap");
+}
+
+void CollectedHeap::zap_filler_array(HeapWord* start, size_t words)
+{
+ if (ZapFillerObjects) {
+ Copy::fill_to_words(start + filler_array_hdr_size(),
+ words - filler_array_hdr_size(), 0XDEAFBABE);
+ }
+}
+#endif // ASSERT
+
+void
+CollectedHeap::fill_with_array(HeapWord* start, size_t words)
+{
+ assert(words >= filler_array_min_size(), "too small for an array");
+ assert(words <= filler_array_max_size(), "too big for a single object");
+
+ const size_t payload_size = words - filler_array_hdr_size();
+ const size_t len = payload_size * HeapWordSize / sizeof(jint);
+
+ // Set the length first for concurrent GC.
+ ((arrayOop)start)->set_length((int)len);
+ post_allocation_setup_common(Universe::intArrayKlassObj(), start, words);
+ DEBUG_ONLY(zap_filler_array(start, words);)
+}
+
+void
+CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words)
+{
+ assert(words <= filler_array_max_size(), "too big for a single object");
+
+ if (words >= filler_array_min_size()) {
+ fill_with_array(start, words);
+ } else if (words > 0) {
+ assert(words == min_fill_size(), "unaligned size");
+ post_allocation_setup_common(SystemDictionary::object_klass(), start,
+ words);
+ }
+}
+
+void CollectedHeap::fill_with_object(HeapWord* start, size_t words)
+{
+ DEBUG_ONLY(fill_args_check(start, words);)
+ HandleMark hm; // Free handles before leaving.
+ fill_with_object_impl(start, words);
+}
+
+void CollectedHeap::fill_with_objects(HeapWord* start, size_t words)
+{
+ DEBUG_ONLY(fill_args_check(start, words);)
+ HandleMark hm; // Free handles before leaving.
+
+#ifdef LP64
+ // A single array can fill ~8G, so multiple objects are needed only in 64-bit.
+ // First fill with arrays, ensuring that any remaining space is big enough to
+ // fill. The remainder is filled with a single object.
+ const size_t min = min_fill_size();
+ const size_t max = filler_array_max_size();
+ while (words > max) {
+ const size_t cur = words - max >= min ? max : max - min;
+ fill_with_array(start, cur);
+ start += cur;
+ words -= cur;
+ }
+#endif
+
+ fill_with_object_impl(start, words);
+}
+
oop CollectedHeap::new_store_barrier(oop new_obj) {
// %%% This needs refactoring. (It was imported from the server compiler.)
guarantee(can_elide_tlab_store_barriers(), "store barrier elision not supported");
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -47,6 +47,9 @@
static int _fire_out_of_memory_count;
#endif
+ // Used for filler objects (static, but initialized in ctor).
+ static size_t _filler_array_max_size;
+
protected:
MemRegion _reserved;
BarrierSet* _barrier_set;
@@ -119,6 +122,21 @@
// Clears an allocated object.
inline static void init_obj(HeapWord* obj, size_t size);
+ // Filler object utilities.
+ static inline size_t filler_array_hdr_size();
+ static inline size_t filler_array_min_size();
+ static inline size_t filler_array_max_size();
+
+ DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);)
+ DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words);)
+
+ // Fill with a single array; caller must ensure filler_array_min_size() <=
+ // words <= filler_array_max_size().
+ static inline void fill_with_array(HeapWord* start, size_t words);
+
+ // Fill with a single object (either an int array or a java.lang.Object).
+ static inline void fill_with_object_impl(HeapWord* start, size_t words);
+
// Verification functions
virtual void check_for_bad_heap_word_value(HeapWord* addr, size_t size)
PRODUCT_RETURN;
@@ -294,6 +312,27 @@
// The boundary between a "large" and "small" array of primitives, in words.
virtual size_t large_typearray_limit() = 0;
+ // Utilities for turning raw memory into filler objects.
+ //
+ // min_fill_size() is the smallest region that can be filled.
+ // fill_with_objects() can fill arbitrary-sized regions of the heap using
+ // multiple objects. fill_with_object() is for regions known to be smaller
+ // than the largest array of integers; it uses a single object to fill the
+ // region and has slightly less overhead.
+ static size_t min_fill_size() {
+ return size_t(align_object_size(oopDesc::header_size()));
+ }
+
+ static void fill_with_objects(HeapWord* start, size_t words);
+
+ static void fill_with_object(HeapWord* start, size_t words);
+ static void fill_with_object(MemRegion region) {
+ fill_with_object(region.start(), region.word_size());
+ }
+ static void fill_with_object(HeapWord* start, HeapWord* end) {
+ fill_with_object(start, pointer_delta(end, start));
+ }
+
// Some heaps may offer a contiguous region for shared non-blocking
// allocation, via inlined code (by exporting the address of the top and
// end fields defining the extent of the contiguous allocation region.)
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -34,7 +34,6 @@
void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
HeapWord* objPtr,
size_t size) {
-
oop obj = (oop)objPtr;
assert(obj != NULL, "NULL object pointer");
@@ -44,9 +43,6 @@
// May be bootstrapping
obj->set_mark(markOopDesc::prototype());
}
-
- // support low memory notifications (no-op if not enabled)
- LowMemoryDetector::detect_low_memory_for_collected_pools();
}
void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
@@ -65,6 +61,9 @@
// Support for jvmti and dtrace
inline void post_allocation_notify(KlassHandle klass, oop obj) {
+ // support low memory notifications (no-op if not enabled)
+ LowMemoryDetector::detect_low_memory_for_collected_pools();
+
// support for JVMTI VMObjectAlloc event (no-op if not enabled)
JvmtiExport::vm_object_alloc_event_collector(obj);
--- a/hotspot/src/share/vm/includeDB_gc Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/includeDB_gc Fri Jan 09 21:54:17 2009 -0800
@@ -28,21 +28,22 @@
collectedHeap.cpp collectedHeap.inline.hpp
collectedHeap.cpp init.hpp
collectedHeap.cpp oop.inline.hpp
+collectedHeap.cpp systemDictionary.hpp
collectedHeap.cpp thread_<os_family>.inline.hpp
collectedHeap.hpp allocation.hpp
collectedHeap.hpp barrierSet.hpp
collectedHeap.hpp gcCause.hpp
collectedHeap.hpp handles.hpp
-collectedHeap.hpp perfData.hpp
+collectedHeap.hpp perfData.hpp
collectedHeap.hpp safepoint.hpp
collectedHeap.inline.hpp arrayOop.hpp
collectedHeap.inline.hpp collectedHeap.hpp
collectedHeap.inline.hpp copy.hpp
collectedHeap.inline.hpp jvmtiExport.hpp
-collectedHeap.inline.hpp lowMemoryDetector.hpp
-collectedHeap.inline.hpp sharedRuntime.hpp
+collectedHeap.inline.hpp lowMemoryDetector.hpp
+collectedHeap.inline.hpp sharedRuntime.hpp
collectedHeap.inline.hpp thread.hpp
collectedHeap.inline.hpp threadLocalAllocBuffer.inline.hpp
collectedHeap.inline.hpp universe.hpp
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -283,7 +283,7 @@
} else {
entry = byte_after(old_region.last());
}
- assert(index_for(new_region.last()) < (int) _guard_index,
+ assert(index_for(new_region.last()) < _guard_index,
"The guard card will be overwritten");
// This line commented out cleans the newly expanded region and
// not the aligned up expanded region.
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -428,7 +428,7 @@
}
// Mapping from address to card marking array index.
- int index_for(void* p) {
+ size_t index_for(void* p) {
assert(_whole_heap.contains(p),
"out of bounds access to card marking array");
return byte_for(p) - _byte_map;
--- a/hotspot/src/share/vm/memory/permGen.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/permGen.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -26,20 +26,24 @@
#include "incls/_permGen.cpp.incl"
HeapWord* PermGen::mem_allocate_in_gen(size_t size, Generation* gen) {
- MutexLocker ml(Heap_lock);
GCCause::Cause next_cause = GCCause::_permanent_generation_full;
GCCause::Cause prev_cause = GCCause::_no_gc;
+ unsigned int gc_count_before, full_gc_count_before;
+ HeapWord* obj;
for (;;) {
- HeapWord* obj = gen->allocate(size, false);
- if (obj != NULL) {
- return obj;
- }
- if (gen->capacity() < _capacity_expansion_limit ||
- prev_cause != GCCause::_no_gc) {
- obj = gen->expand_and_allocate(size, false);
- }
- if (obj == NULL && prev_cause != GCCause::_last_ditch_collection) {
+ {
+ MutexLocker ml(Heap_lock);
+ if ((obj = gen->allocate(size, false)) != NULL) {
+ return obj;
+ }
+ if (gen->capacity() < _capacity_expansion_limit ||
+ prev_cause != GCCause::_no_gc) {
+ obj = gen->expand_and_allocate(size, false);
+ }
+ if (obj != NULL || prev_cause == GCCause::_last_ditch_collection) {
+ return obj;
+ }
if (GC_locker::is_active_and_needs_gc()) {
// If this thread is not in a jni critical section, we stall
// the requestor until the critical section has cleared and
@@ -61,31 +65,27 @@
return NULL;
}
}
+ // Read the GC count while holding the Heap_lock
+ gc_count_before = SharedHeap::heap()->total_collections();
+ full_gc_count_before = SharedHeap::heap()->total_full_collections();
+ }
- // Read the GC count while holding the Heap_lock
- unsigned int gc_count_before = SharedHeap::heap()->total_collections();
- unsigned int full_gc_count_before = SharedHeap::heap()->total_full_collections();
- {
- MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
- VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before,
- next_cause);
- VMThread::execute(&op);
- if (!op.prologue_succeeded() || op.gc_locked()) {
- assert(op.result() == NULL, "must be NULL if gc_locked() is true");
- continue; // retry and/or stall as necessary
- }
- obj = op.result();
- assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj),
- "result not in heap");
- if (obj != NULL) {
- return obj;
- }
- }
- prev_cause = next_cause;
- next_cause = GCCause::_last_ditch_collection;
- } else {
+ // Give up heap lock above, VMThread::execute below gets it back
+ VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before,
+ next_cause);
+ VMThread::execute(&op);
+ if (!op.prologue_succeeded() || op.gc_locked()) {
+ assert(op.result() == NULL, "must be NULL if gc_locked() is true");
+ continue; // retry and/or stall as necessary
+ }
+ obj = op.result();
+ assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj),
+ "result not in heap");
+ if (obj != NULL) {
return obj;
}
+ prev_cause = next_cause;
+ next_cause = GCCause::_last_ditch_collection;
}
}
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -248,46 +248,6 @@
perm_gen()->ref_processor_init();
}
-void SharedHeap::fill_region_with_object(MemRegion mr) {
- // Disable the posting of JVMTI VMObjectAlloc events as we
- // don't want the filling of tlabs with filler arrays to be
- // reported to the profiler.
- NoJvmtiVMObjectAllocMark njm;
-
- // Disable low memory detector because there is no real allocation.
- LowMemoryDetectorDisabler lmd_dis;
-
- // It turns out that post_allocation_setup_array takes a handle, so the
- // call below contains an implicit conversion. Best to free that handle
- // as soon as possible.
- HandleMark hm;
-
- size_t word_size = mr.word_size();
- size_t aligned_array_header_size =
- align_object_size(typeArrayOopDesc::header_size(T_INT));
-
- if (word_size >= aligned_array_header_size) {
- const size_t array_length =
- pointer_delta(mr.end(), mr.start()) -
- typeArrayOopDesc::header_size(T_INT);
- const size_t array_length_words =
- array_length * (HeapWordSize/sizeof(jint));
- post_allocation_setup_array(Universe::intArrayKlassObj(),
- mr.start(),
- mr.word_size(),
- (int)array_length_words);
-#ifdef ASSERT
- HeapWord* elt_words = (mr.start() + typeArrayOopDesc::header_size(T_INT));
- Copy::fill_to_words(elt_words, array_length, 0xDEAFBABE);
-#endif
- } else {
- assert(word_size == (size_t)oopDesc::header_size(), "Unaligned?");
- post_allocation_setup_obj(SystemDictionary::object_klass(),
- mr.start(),
- mr.word_size());
- }
-}
-
// Some utilities.
void SharedHeap::print_size_transition(outputStream* out,
size_t bytes_before,
--- a/hotspot/src/share/vm/memory/sharedHeap.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -108,14 +108,6 @@
void set_perm(PermGen* perm_gen) { _perm_gen = perm_gen; }
- // A helper function that fills a region of the heap with
- // with a single object.
- static void fill_region_with_object(MemRegion mr);
-
- // Minimum garbage fill object size
- static size_t min_fill_size() { return (size_t)align_object_size(oopDesc::header_size()); }
- static size_t min_fill_size_in_bytes() { return min_fill_size() * HeapWordSize; }
-
// This function returns the "GenRemSet" object that allows us to scan
// generations; at least the perm gen, possibly more in a fully
// generational heap.
--- a/hotspot/src/share/vm/memory/space.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/space.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -409,19 +409,9 @@
HeapWord* q, size_t deadlength) {
if (allowed_deadspace_words >= deadlength) {
allowed_deadspace_words -= deadlength;
- oop(q)->set_mark(markOopDesc::prototype()->set_marked());
- const size_t min_int_array_size = typeArrayOopDesc::header_size(T_INT);
- if (deadlength >= min_int_array_size) {
- oop(q)->set_klass(Universe::intArrayKlassObj());
- typeArrayOop(q)->set_length((int)((deadlength - min_int_array_size)
- * (HeapWordSize/sizeof(jint))));
- } else {
- assert((int) deadlength == instanceOopDesc::header_size(),
- "size for smallest fake dead object doesn't match");
- oop(q)->set_klass(SystemDictionary::object_klass());
- }
- assert((int) deadlength == oop(q)->size(),
- "make sure size for fake dead object match");
+ CollectedHeap::fill_with_object(q, deadlength);
+ oop(q)->set_mark(oop(q)->mark()->set_marked());
+ assert((int) deadlength == oop(q)->size(), "bad filler object size");
// Recall that we required "q == compaction_top".
return true;
} else {
--- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -387,7 +387,7 @@
"should contain whole object");
buf->undo_allocation(obj, word_sz);
} else {
- SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
+ CollectedHeap::fill_with_object(obj, word_sz);
}
}
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -100,8 +100,7 @@
void ThreadLocalAllocBuffer::make_parsable(bool retire) {
if (end() != NULL) {
invariants();
- MemRegion mr(top(), hard_end());
- SharedHeap::fill_region_with_object(mr);
+ CollectedHeap::fill_with_object(top(), hard_end());
if (retire || ZeroTLAB) { // "Reset" the TLAB
set_start(NULL);
--- a/hotspot/src/share/vm/memory/universe.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/universe.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -49,16 +49,16 @@
klassOop Universe::_constantPoolCacheKlassObj = NULL;
klassOop Universe::_compiledICHolderKlassObj = NULL;
klassOop Universe::_systemObjArrayKlassObj = NULL;
-oop Universe::_int_mirror = NULL;
-oop Universe::_float_mirror = NULL;
-oop Universe::_double_mirror = NULL;
-oop Universe::_byte_mirror = NULL;
-oop Universe::_bool_mirror = NULL;
-oop Universe::_char_mirror = NULL;
-oop Universe::_long_mirror = NULL;
-oop Universe::_short_mirror = NULL;
-oop Universe::_void_mirror = NULL;
-oop Universe::_mirrors[T_VOID+1] = { NULL /*, NULL...*/ };
+oop Universe::_int_mirror = NULL;
+oop Universe::_float_mirror = NULL;
+oop Universe::_double_mirror = NULL;
+oop Universe::_byte_mirror = NULL;
+oop Universe::_bool_mirror = NULL;
+oop Universe::_char_mirror = NULL;
+oop Universe::_long_mirror = NULL;
+oop Universe::_short_mirror = NULL;
+oop Universe::_void_mirror = NULL;
+oop Universe::_mirrors[T_VOID+1] = { NULL /*, NULL...*/ };
oop Universe::_main_thread_group = NULL;
oop Universe::_system_thread_group = NULL;
typeArrayOop Universe::_the_empty_byte_array = NULL;
@@ -257,16 +257,16 @@
_typeArrayKlassObjs[T_INT] = _intArrayKlassObj;
_typeArrayKlassObjs[T_LONG] = _longArrayKlassObj;
- _methodKlassObj = methodKlass::create_klass(CHECK);
- _constMethodKlassObj = constMethodKlass::create_klass(CHECK);
- _methodDataKlassObj = methodDataKlass::create_klass(CHECK);
+ _methodKlassObj = methodKlass::create_klass(CHECK);
+ _constMethodKlassObj = constMethodKlass::create_klass(CHECK);
+ _methodDataKlassObj = methodDataKlass::create_klass(CHECK);
_constantPoolKlassObj = constantPoolKlass::create_klass(CHECK);
_constantPoolCacheKlassObj = constantPoolCacheKlass::create_klass(CHECK);
_compiledICHolderKlassObj = compiledICHolderKlass::create_klass(CHECK);
_systemObjArrayKlassObj = objArrayKlassKlass::cast(objArrayKlassKlassObj())->allocate_system_objArray_klass(CHECK);
- _the_empty_byte_array = oopFactory::new_permanent_byteArray(0, CHECK);
+ _the_empty_byte_array = oopFactory::new_permanent_byteArray(0, CHECK);
_the_empty_short_array = oopFactory::new_permanent_shortArray(0, CHECK);
_the_empty_int_array = oopFactory::new_permanent_intArray(0, CHECK);
_the_empty_system_obj_array = oopFactory::new_system_objArray(0, CHECK);
@@ -274,7 +274,6 @@
_the_array_interfaces_array = oopFactory::new_system_objArray(2, CHECK);
_vm_exception = oopFactory::new_symbol("vm exception holder", CHECK);
} else {
-
FileMapInfo *mapinfo = FileMapInfo::current_info();
char* buffer = mapinfo->region_base(CompactingPermGenGen::md);
void** vtbl_list = (void**)buffer;
--- a/hotspot/src/share/vm/memory/universe.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/memory/universe.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -92,6 +92,7 @@
class Universe: AllStatic {
+ // Ugh. Universe is much too friendly.
friend class MarkSweep;
friend class oopDesc;
friend class ClassLoader;
--- a/hotspot/src/share/vm/oops/arrayOop.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/oops/arrayOop.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -96,19 +96,20 @@
: typesize_in_bytes/HeapWordSize);
}
- // This method returns the maximum length that can passed into
- // typeArrayOop::object_size(scale, length, header_size) without causing an
- // overflow. We substract an extra 2*wordSize to guard against double word
- // alignments. It gets the scale from the type2aelembytes array.
+ // Return the maximum length of an array of BasicType. The length can passed
+ // to typeArrayOop::object_size(scale, length, header_size) without causing an
+ // overflow.
static int32_t max_array_length(BasicType type) {
assert(type >= 0 && type < T_CONFLICT, "wrong type");
assert(type2aelembytes(type) != 0, "wrong type");
- // We use max_jint, since object_size is internally represented by an 'int'
- // This gives us an upper bound of max_jint words for the size of the oop.
- int32_t max_words = (max_jint - header_size(type) - 2);
- int elembytes = type2aelembytes(type);
- jlong len = ((jlong)max_words * HeapWordSize) / elembytes;
- return (len > max_jint) ? max_jint : (int32_t)len;
+ const int bytes_per_element = type2aelembytes(type);
+ if (bytes_per_element < HeapWordSize) {
+ return max_jint;
+ }
+
+ const int32_t max_words = align_size_down(max_jint, MinObjAlignment);
+ const int32_t max_element_words = max_words - header_size(type);
+ const int32_t words_per_element = bytes_per_element >> LogHeapWordSize;
+ return max_element_words / words_per_element;
}
-
};
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -36,13 +36,14 @@
return element_type() == tak->element_type();
}
-klassOop typeArrayKlass::create_klass(BasicType type, int scale, TRAPS) {
+klassOop typeArrayKlass::create_klass(BasicType type, int scale,
+ const char* name_str, TRAPS) {
typeArrayKlass o;
symbolHandle sym(symbolOop(NULL));
// bootstrapping: don't create sym if symbolKlass not created yet
- if (Universe::symbolKlassObj() != NULL) {
- sym = oopFactory::new_symbol_handle(external_name(type), CHECK_NULL);
+ if (Universe::symbolKlassObj() != NULL && name_str != NULL) {
+ sym = oopFactory::new_symbol_handle(name_str, CHECK_NULL);
}
KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
--- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -39,7 +39,11 @@
// klass allocation
DEFINE_ALLOCATE_PERMANENT(typeArrayKlass);
- static klassOop create_klass(BasicType type, int scale, TRAPS);
+ static klassOop create_klass(BasicType type, int scale, const char* name_str,
+ TRAPS);
+ static inline klassOop create_klass(BasicType type, int scale, TRAPS) {
+ return create_klass(type, scale, external_name(type), CHECK_NULL);
+ }
int oop_size(oop obj) const;
int klass_oop_size() const { return object_size(); }
--- a/hotspot/src/share/vm/opto/compile.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -2192,6 +2192,9 @@
case Op_DecodeN:
assert(!n->in(1)->is_EncodeP(), "should be optimized out");
+ // DecodeN could be pinned on Sparc where it can't be fold into
+ // an address expression, see the code for Op_CastPP above.
+ assert(n->in(0) == NULL || !Matcher::clone_shift_expressions, "no control except on sparc");
break;
case Op_EncodeP: {
--- a/hotspot/src/share/vm/opto/macro.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/opto/macro.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -1724,6 +1724,13 @@
if (klass_node == NULL) {
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
+#ifdef _LP64
+ if (UseCompressedOops && klass_node->is_DecodeN()) {
+ assert(klass_node->in(1)->Opcode() == Op_LoadNKlass, "sanity");
+ klass_node->in(1)->init_req(0, ctrl);
+ } else
+#endif
+ klass_node->init_req(0, ctrl);
}
Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type());
--- a/hotspot/src/share/vm/prims/jni.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -2173,7 +2173,8 @@
size_t size = os::vm_allocation_granularity();
bad_address = os::reserve_memory(size);
if (bad_address != NULL) {
- os::protect_memory(bad_address, size, os::MEM_PROT_READ);
+ os::protect_memory(bad_address, size, os::MEM_PROT_READ,
+ /*is_committed*/false);
}
}
return bad_address;
--- a/hotspot/src/share/vm/runtime/arguments.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -444,9 +444,9 @@
}
// Parses a memory size specification string.
-static bool atomll(const char *s, jlong* result) {
- jlong n = 0;
- int args_read = sscanf(s, os::jlong_format_specifier(), &n);
+static bool atomull(const char *s, julong* result) {
+ julong n = 0;
+ int args_read = sscanf(s, os::julong_format_specifier(), &n);
if (args_read != 1) {
return false;
}
@@ -460,15 +460,20 @@
switch (*s) {
case 'T': case 't':
*result = n * G * K;
+ // Check for overflow.
+ if (*result/((julong)G * K) != n) return false;
return true;
case 'G': case 'g':
*result = n * G;
+ if (*result/G != n) return false;
return true;
case 'M': case 'm':
*result = n * M;
+ if (*result/M != n) return false;
return true;
case 'K': case 'k':
*result = n * K;
+ if (*result/K != n) return false;
return true;
case '\0':
*result = n;
@@ -478,10 +483,10 @@
}
}
-Arguments::ArgsRange Arguments::check_memory_size(jlong size, jlong min_size) {
+Arguments::ArgsRange Arguments::check_memory_size(julong size, julong min_size) {
if (size < min_size) return arg_too_small;
// Check that size will fit in a size_t (only relevant on 32-bit)
- if ((julong) size > max_uintx) return arg_too_big;
+ if (size > max_uintx) return arg_too_big;
return arg_in_range;
}
@@ -522,10 +527,10 @@
static bool set_numeric_flag(char* name, char* value, FlagValueOrigin origin) {
- jlong v;
+ julong v;
intx intx_v;
bool is_neg = false;
- // Check the sign first since atomll() parses only unsigned values.
+ // Check the sign first since atomull() parses only unsigned values.
if (*value == '-') {
if (!CommandLineFlags::intxAt(name, &intx_v)) {
return false;
@@ -533,7 +538,7 @@
value++;
is_neg = true;
}
- if (!atomll(value, &v)) {
+ if (!atomull(value, &v)) {
return false;
}
intx_v = (intx) v;
@@ -1517,6 +1522,16 @@
MarkSweepAlwaysCompactCount = 1; // Move objects every gc.
}
+ if (UseParallelOldGC && ParallelOldGCSplitALot) {
+ // Settings to encourage splitting.
+ if (!FLAG_IS_CMDLINE(NewRatio)) {
+ FLAG_SET_CMDLINE(intx, NewRatio, 2);
+ }
+ if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) {
+ FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
+ }
+ }
+
status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
status = status && verify_percentage(GCTimeLimit, "GCTimeLimit");
if (GCTimeLimit == 100) {
@@ -1667,9 +1682,9 @@
}
Arguments::ArgsRange Arguments::parse_memory_size(const char* s,
- jlong* long_arg,
- jlong min_size) {
- if (!atomll(s, long_arg)) return arg_unreadable;
+ julong* long_arg,
+ julong min_size) {
+ if (!atomull(s, long_arg)) return arg_unreadable;
return check_memory_size(*long_arg, min_size);
}
@@ -1847,7 +1862,7 @@
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
// -Xmn for compatibility with other JVM vendors
} else if (match_option(option, "-Xmn", &tail)) {
- jlong long_initial_eden_size = 0;
+ julong long_initial_eden_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_initial_eden_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -1859,7 +1874,7 @@
FLAG_SET_CMDLINE(uintx, NewSize, (size_t) long_initial_eden_size);
// -Xms
} else if (match_option(option, "-Xms", &tail)) {
- jlong long_initial_heap_size = 0;
+ julong long_initial_heap_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_initial_heap_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -1872,7 +1887,7 @@
set_min_heap_size(initial_heap_size());
// -Xmx
} else if (match_option(option, "-Xmx", &tail)) {
- jlong long_max_heap_size = 0;
+ julong long_max_heap_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_max_heap_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -1905,7 +1920,7 @@
}
// -Xss
} else if (match_option(option, "-Xss", &tail)) {
- jlong long_ThreadStackSize = 0;
+ julong long_ThreadStackSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ThreadStackSize, 1000);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -1921,9 +1936,9 @@
// HotSpot does not have separate native and Java stacks, ignore silently for compatibility
// -Xmaxjitcodesize
} else if (match_option(option, "-Xmaxjitcodesize", &tail)) {
- jlong long_ReservedCodeCacheSize = 0;
+ julong long_ReservedCodeCacheSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize,
- InitialCodeCacheSize);
+ (size_t)InitialCodeCacheSize);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
"Invalid maximum code cache size: %s\n",
@@ -2228,7 +2243,7 @@
} else if (match_option(option, "-XX:TLEFragmentationRatio=", &tail)) {
// No longer used.
} else if (match_option(option, "-XX:TLESize=", &tail)) {
- jlong long_tlab_size = 0;
+ julong long_tlab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_tlab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -2283,7 +2298,7 @@
"-XX:ParCMSPromoteBlocksToClaim in the future\n");
} else
if (match_option(option, "-XX:ParallelGCOldGenAllocBufferSize=", &tail)) {
- jlong old_plab_size = 0;
+ julong old_plab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &old_plab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -2291,13 +2306,13 @@
describe_range_error(errcode);
return JNI_EINVAL;
}
- FLAG_SET_CMDLINE(uintx, OldPLABSize, (julong)old_plab_size);
+ FLAG_SET_CMDLINE(uintx, OldPLABSize, old_plab_size);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:OldPLABSize in place of "
"-XX:ParallelGCOldGenAllocBufferSize in the future\n");
} else
if (match_option(option, "-XX:ParallelGCToSpaceAllocBufferSize=", &tail)) {
- jlong young_plab_size = 0;
+ julong young_plab_size = 0;
ArgsRange errcode = parse_memory_size(tail, &young_plab_size, 1);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
@@ -2305,7 +2320,7 @@
describe_range_error(errcode);
return JNI_EINVAL;
}
- FLAG_SET_CMDLINE(uintx, YoungPLABSize, (julong)young_plab_size);
+ FLAG_SET_CMDLINE(uintx, YoungPLABSize, young_plab_size);
jio_fprintf(defaultStream::error_stream(),
"Please use -XX:YoungPLABSize in place of "
"-XX:ParallelGCToSpaceAllocBufferSize in the future\n");
--- a/hotspot/src/share/vm/runtime/arguments.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -339,9 +339,9 @@
}
static bool verify_percentage(uintx value, const char* name);
static void describe_range_error(ArgsRange errcode);
- static ArgsRange check_memory_size(jlong size, jlong min_size);
- static ArgsRange parse_memory_size(const char* s, jlong* long_arg,
- jlong min_size);
+ static ArgsRange check_memory_size(julong size, julong min_size);
+ static ArgsRange parse_memory_size(const char* s, julong* long_arg,
+ julong min_size);
// methods to build strings from individual args
static void build_jvm_args(const char* arg);
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -625,6 +625,9 @@
develop(bool, CheckZapUnusedHeapArea, false, \
"Check zapping of unused heap space") \
\
+ develop(bool, ZapFillerObjects, trueInDebug, \
+ "Zap filler objects with 0xDEAFBABE") \
+ \
develop(bool, PrintVMMessages, true, \
"Print vm messages on console") \
\
@@ -818,7 +821,7 @@
product(bool, ClassUnloading, true, \
"Do unloading of classes") \
\
- diagnostic(bool, LinkWellKnownClasses, true, \
+ diagnostic(bool, LinkWellKnownClasses, false, \
"Resolve a well known class as soon as its name is seen") \
\
develop(bool, DisableStartThread, false, \
@@ -1200,11 +1203,12 @@
product(uintx, ParallelCMSThreads, 0, \
"Max number of threads CMS will use for concurrent work") \
\
- develop(bool, ParallelOldMTUnsafeMarkBitMap, false, \
- "Use the Parallel Old MT unsafe in marking the bitmap") \
- \
- develop(bool, ParallelOldMTUnsafeUpdateLiveData, false, \
- "Use the Parallel Old MT unsafe in update of live size") \
+ develop(bool, ParallelOldGCSplitALot, false, \
+ "Provoke splitting (copying data from a young gen space to" \
+ "multiple destination spaces)") \
+ \
+ develop(uintx, ParallelOldGCSplitInterval, 3, \
+ "How often to provoke splitting a young gen space") \
\
develop(bool, TraceRegionTasksQueuing, false, \
"Trace the queuing of the region tasks") \
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -504,7 +504,7 @@
intptr_t v = _value[p];
if (v != 0 ) {
size_t t = (size_t)v;
- bad = (t < (size_t)os::vm_page_size() ) || !(*(oop*)v)->is_oop_or_null(true);
+ bad = (t < (size_t)os::vm_page_size() ) || !Handle::raw_resolve((oop *)v)->is_oop_or_null(true);
if (CheckJNICalls && bad) {
ReportJNIFatalError((JavaThread*)_thread, "Bad JNI oop argument");
}
--- a/hotspot/src/share/vm/runtime/os.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/os.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -932,8 +932,9 @@
// the mutator thread if such case is encountered. See bug 6546278 for details.
Thread::muxAcquire(&SerializePageLock, "serialize_thread_states");
os::protect_memory((char *)os::get_memory_serialize_page(),
- os::vm_page_size(), MEM_PROT_READ, /*is_committed*/true );
- os::unguard_memory((char *)os::get_memory_serialize_page(), os::vm_page_size());
+ os::vm_page_size(), MEM_PROT_READ);
+ os::protect_memory((char *)os::get_memory_serialize_page(),
+ os::vm_page_size(), MEM_PROT_RW);
Thread::muxRelease(&SerializePageLock);
}
--- a/hotspot/src/share/vm/runtime/os.hpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/os.hpp Fri Jan 09 21:54:17 2009 -0800
@@ -208,7 +208,7 @@
enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX };
static bool protect_memory(char* addr, size_t bytes, ProtType prot,
- bool is_committed = false);
+ bool is_committed = true);
static bool guard_memory(char* addr, size_t bytes);
static bool unguard_memory(char* addr, size_t bytes);
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -3363,13 +3363,13 @@
// If the wakee is cold then transiently setting it's affinity
// to the current CPU is a good idea.
// See http://j2se.east/~dice/PERSIST/050624-PullAffinity.txt
+ DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
Trigger->unpark() ;
// Maintain stats and report events to JVMTI
if (ObjectSynchronizer::_sync_Parks != NULL) {
ObjectSynchronizer::_sync_Parks->inc() ;
}
- DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
}
--- a/hotspot/src/share/vm/services/management.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/services/management.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -694,10 +694,10 @@
-1);
}
- if (threshold > max_intx) {
- THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
- "Invalid threshold value > max value of size_t",
- -1);
+ if ((size_t)threshold > max_uintx) {
+ stringStream st;
+ st.print("Invalid valid threshold value. Threshold value (" UINT64_FORMAT ") > max value of size_t (" SIZE_FORMAT ")", (size_t)threshold, max_uintx);
+ THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), st.as_string(), -1);
}
MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L));
--- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -332,6 +332,8 @@
// VM version
st->print_cr("#");
+ JDK_Version::current().to_string(buf, sizeof(buf));
+ st->print_cr("# JRE version: %s", buf);
st->print_cr("# Java VM: %s (%s %s %s %s)",
Abstract_VM_Version::vm_name(),
Abstract_VM_Version::vm_release(),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6757316/Test6757316.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6757316
+ * @summary load_constant() produces a wrong long constant, with high a low words swapped
+ * @run main/othervm -Xcomp Test6757316
+ */
+
+public class Test6757316 {
+ public static void main(String[] args) {
+ long[] arr = {
+ 0x11111111aaaaaaaaL,
+ 0xaaaaaaaa11111111L,
+ 0x11111111aaaaaaaaL,
+ 0xaaaaaaaa11111111L
+ };
+ if (arr[0] == arr[1]) {
+ throw new InternalError();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6758234/Test6758234.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6758234
+ * @summary if (k cond (a ? : b: c)) returns reversed answer if k is constant and b and c are longs
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test6758234.main Test6758234
+ */
+
+public class Test6758234 {
+ static int x = 0;
+ static int y = 1;
+
+ public static void main(String[] args) {
+ if (1 != ((x < y) ? 1L : 0)) {
+ throw new InternalError();
+ }
+ }
+}
--- a/jaxp/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/jaxp/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39
54946f466e2c047c44c903f1bec400b685c2508e jdk7-b40
0758bd3e2852e4f931ba211cc4d48f589450eeb4 jdk7-b41
+036e0dca841a5a17f784d15c86a9da88d2a6f1e6 jdk7-b42
--- a/jaxws/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/jaxws/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39
70a6ac6dd737fe45c2fadb57646195b2b4fe269d jdk7-b40
a8379d24aa03386610169cb0f4e4b8ed266a2e8d jdk7-b41
+621c02d83abc850c170fb6726d57b19f1eaf5033 jdk7-b42
--- a/jdk/make/sun/awt/mapfile-mawt-vers Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/make/sun/awt/mapfile-mawt-vers Fri Jan 09 21:54:17 2009 -0800
@@ -407,6 +407,7 @@
Java_sun_java2d_x11_X11SurfaceData_initSurface;
Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
+ Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
Java_sun_java2d_x11_X11SurfaceData_setInvalid;
Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
--- a/jdk/make/sun/xawt/mapfile-vers Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/make/sun/xawt/mapfile-vers Fri Jan 09 21:54:17 2009 -0800
@@ -337,6 +337,7 @@
Java_sun_java2d_x11_X11SurfaceData_initIDs;
Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
+ Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
Java_sun_java2d_x11_X11SurfaceData_initOps;
Java_sun_java2d_x11_X11SurfaceData_initSurface;
Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Fri Jan 09 21:54:17 2009 -0800
@@ -44,7 +44,6 @@
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
-import java.util.List;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import javax.imageio.IIOException;
@@ -57,6 +56,7 @@
import com.sun.imageio.plugins.common.InputStreamAdapter;
import com.sun.imageio.plugins.common.ReaderUtil;
import com.sun.imageio.plugins.common.SubImageInputStream;
+import java.io.ByteArrayOutputStream;
import sun.awt.image.ByteInterleavedRaster;
class PNGImageDataEnumeration implements Enumeration {
@@ -207,6 +207,15 @@
resetStreamSettings();
}
+ private String readNullTerminatedString(String charset) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int b;
+ while ((b = stream.read()) != 0) {
+ baos.write(b);
+ }
+ return new String(baos.toByteArray(), charset);
+ }
+
private String readNullTerminatedString() throws IOException {
StringBuilder b = new StringBuilder();
int c;
@@ -445,26 +454,27 @@
metadata.iTXt_keyword.add(keyword);
int compressionFlag = stream.readUnsignedByte();
- metadata.iTXt_compressionFlag.add(new Integer(compressionFlag));
+ metadata.iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag == 1));
int compressionMethod = stream.readUnsignedByte();
- metadata.iTXt_compressionMethod.add(new Integer(compressionMethod));
+ metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
- String languageTag = readNullTerminatedString();
+ String languageTag = readNullTerminatedString("UTF8");
metadata.iTXt_languageTag.add(languageTag);
- String translatedKeyword = stream.readUTF();
+ String translatedKeyword =
+ readNullTerminatedString("UTF8");
metadata.iTXt_translatedKeyword.add(translatedKeyword);
- stream.skipBytes(1); // Null separator
String text;
+ long pos = stream.getStreamPosition();
+ byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
+ stream.readFully(b);
+
if (compressionFlag == 1) { // Decompress the text
- long pos = stream.getStreamPosition();
- byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
- stream.readFully(b);
- text = inflate(b);
+ text = new String(inflate(b), "UTF8");
} else {
- text = stream.readUTF();
+ text = new String(b, "UTF8");
}
metadata.iTXt_text.add(text);
}
@@ -613,15 +623,20 @@
metadata.tRNS_present = true;
}
- private static String inflate(byte[] b) throws IOException {
+ private static byte[] inflate(byte[] b) throws IOException {
InputStream bais = new ByteArrayInputStream(b);
InputStream iis = new InflaterInputStream(bais);
- StringBuilder sb = new StringBuilder(80);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
int c;
- while ((c = iis.read()) != -1) {
- sb.append((char)c);
+ try {
+ while ((c = iis.read()) != -1) {
+ baos.write(c);
+ }
+ } finally {
+ iis.close();
}
- return sb.toString();
+ return baos.toByteArray();
}
private void parse_zTXt_chunk(int chunkLength) throws IOException {
@@ -633,7 +648,7 @@
byte[] b = new byte[chunkLength - keyword.length() - 2];
stream.readFully(b);
- metadata.zTXt_text.add(inflate(b));
+ metadata.zTXt_text.add(new String(inflate(b)));
}
private void readMetadata() throws IIOException {
@@ -1244,13 +1259,26 @@
destinationBands = param.getDestinationBands();
destinationOffset = param.getDestinationOffset();
}
-
+ Inflater inf = null;
try {
stream.seek(imageStartPosition);
Enumeration e = new PNGImageDataEnumeration(stream);
InputStream is = new SequenceInputStream(e);
- is = new InflaterInputStream(is, new Inflater());
+
+ /* InflaterInputStream uses an Inflater instance which consumes
+ * native (non-GC visible) resources. This is normally implicitly
+ * freed when the stream is closed. However since the
+ * InflaterInputStream wraps a client-supplied input stream,
+ * we cannot close it.
+ * But the app may depend on GC finalization to close the stream.
+ * Therefore to ensure timely freeing of native resources we
+ * explicitly create the Inflater instance and free its resources
+ * when we are done with the InflaterInputStream by calling
+ * inf.end();
+ */
+ inf = new Inflater();
+ is = new InflaterInputStream(is, inf);
is = new BufferedInputStream(is);
this.pixelStream = new DataInputStream(is);
@@ -1283,6 +1311,10 @@
}
} catch (IOException e) {
throw new IIOException("Error reading PNG image data", e);
+ } finally {
+ if (inf != null) {
+ inf.end();
+ }
}
}
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java Fri Jan 09 21:54:17 2009 -0800
@@ -244,13 +244,17 @@
}
public void finish() throws IOException {
- if (!def.finished()) {
- def.finish();
- while (!def.finished()) {
- deflate();
+ try {
+ if (!def.finished()) {
+ def.finish();
+ while (!def.finished()) {
+ deflate();
+ }
}
+ finishChunk();
+ } finally {
+ def.end();
}
- finishChunk();
}
protected void finalize() throws Throwable {
@@ -667,13 +671,13 @@
}
}
- private byte[] deflate(String s) throws IOException {
+ private byte[] deflate(byte[] b) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos);
- int len = s.length();
+ int len = b.length;
for (int i = 0; i < len; i++) {
- dos.write((int)s.charAt(i));
+ dos.write((int)(0xff & b[i]));
}
dos.close();
@@ -681,38 +685,37 @@
}
private void write_iTXt() throws IOException {
- Iterator keywordIter = metadata.iTXt_keyword.iterator();
- Iterator flagIter = metadata.iTXt_compressionFlag.iterator();
- Iterator methodIter = metadata.iTXt_compressionMethod.iterator();
- Iterator languageIter = metadata.iTXt_languageTag.iterator();
- Iterator translatedKeywordIter =
+ Iterator<String> keywordIter = metadata.iTXt_keyword.iterator();
+ Iterator<Boolean> flagIter = metadata.iTXt_compressionFlag.iterator();
+ Iterator<Integer> methodIter = metadata.iTXt_compressionMethod.iterator();
+ Iterator<String> languageIter = metadata.iTXt_languageTag.iterator();
+ Iterator<String> translatedKeywordIter =
metadata.iTXt_translatedKeyword.iterator();
- Iterator textIter = metadata.iTXt_text.iterator();
+ Iterator<String> textIter = metadata.iTXt_text.iterator();
while (keywordIter.hasNext()) {
ChunkStream cs = new ChunkStream(PNGImageReader.iTXt_TYPE, stream);
- String keyword = (String)keywordIter.next();
- cs.writeBytes(keyword);
+
+ cs.writeBytes(keywordIter.next());
cs.writeByte(0);
- int flag = ((Integer)flagIter.next()).intValue();
- cs.writeByte(flag);
- int method = ((Integer)methodIter.next()).intValue();
- cs.writeByte(method);
+ Boolean compressed = flagIter.next();
+ cs.writeByte(compressed ? 1 : 0);
- String languageTag = (String)languageIter.next();
- cs.writeBytes(languageTag);
+ cs.writeByte(methodIter.next().intValue());
+
+ cs.writeBytes(languageIter.next());
cs.writeByte(0);
- String translatedKeyword = (String)translatedKeywordIter.next();
- cs.writeBytes(translatedKeyword);
+
+ cs.write(translatedKeywordIter.next().getBytes("UTF8"));
cs.writeByte(0);
- String text = (String)textIter.next();
- if (flag == 1) {
- cs.write(deflate(text));
+ String text = textIter.next();
+ if (compressed) {
+ cs.write(deflate(text.getBytes("UTF8")));
} else {
- cs.writeUTF(text);
+ cs.write(text.getBytes("UTF8"));
}
cs.finish();
}
@@ -733,7 +736,7 @@
cs.writeByte(compressionMethod);
String text = (String)textIter.next();
- cs.write(deflate(text));
+ cs.write(deflate(text.getBytes()));
cs.finish();
}
}
@@ -928,23 +931,24 @@
// Use sourceXOffset, etc.
private void write_IDAT(RenderedImage image) throws IOException {
IDATOutputStream ios = new IDATOutputStream(stream, 32768);
-
- if (metadata.IHDR_interlaceMethod == 1) {
- for (int i = 0; i < 7; i++) {
- encodePass(ios, image,
- PNGImageReader.adam7XOffset[i],
- PNGImageReader.adam7YOffset[i],
- PNGImageReader.adam7XSubsampling[i],
- PNGImageReader.adam7YSubsampling[i]);
- if (abortRequested()) {
- break;
+ try {
+ if (metadata.IHDR_interlaceMethod == 1) {
+ for (int i = 0; i < 7; i++) {
+ encodePass(ios, image,
+ PNGImageReader.adam7XOffset[i],
+ PNGImageReader.adam7YOffset[i],
+ PNGImageReader.adam7XSubsampling[i],
+ PNGImageReader.adam7YSubsampling[i]);
+ if (abortRequested()) {
+ break;
+ }
}
+ } else {
+ encodePass(ios, image, 0, 0, 1, 1);
}
- } else {
- encodePass(ios, image, 0, 0, 1, 1);
+ } finally {
+ ios.finish();
}
-
- ios.finish();
}
private void writeIEND() throws IOException {
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java Fri Jan 09 21:54:17 2009 -0800
@@ -174,12 +174,12 @@
public byte[] iCCP_compressedProfile;
// iTXt chunk
- public ArrayList iTXt_keyword = new ArrayList(); // Strings
- public ArrayList iTXt_compressionFlag = new ArrayList(); // Integers
- public ArrayList iTXt_compressionMethod = new ArrayList(); // Integers
- public ArrayList iTXt_languageTag = new ArrayList(); // Strings
- public ArrayList iTXt_translatedKeyword = new ArrayList(); // Strings
- public ArrayList iTXt_text = new ArrayList(); // Strings
+ public ArrayList<String> iTXt_keyword = new ArrayList<String>();
+ public ArrayList<Boolean> iTXt_compressionFlag = new ArrayList<Boolean>();
+ public ArrayList<Integer> iTXt_compressionMethod = new ArrayList<Integer>();
+ public ArrayList<String> iTXt_languageTag = new ArrayList<String>();
+ public ArrayList<String> iTXt_translatedKeyword = new ArrayList<String>();
+ public ArrayList<String> iTXt_text = new ArrayList<String>();
// pHYs chunk
public boolean pHYs_present;
@@ -597,19 +597,17 @@
if (iTXt_keyword.size() > 0) {
IIOMetadataNode iTXt_parent = new IIOMetadataNode("iTXt");
for (int i = 0; i < iTXt_keyword.size(); i++) {
- Integer val;
-
IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
- iTXt_node.setAttribute("keyword", (String)iTXt_keyword.get(i));
- val = (Integer)iTXt_compressionFlag.get(i);
- iTXt_node.setAttribute("compressionFlag", val.toString());
- val = (Integer)iTXt_compressionMethod.get(i);
- iTXt_node.setAttribute("compressionMethod", val.toString());
+ iTXt_node.setAttribute("keyword", iTXt_keyword.get(i));
+ iTXt_node.setAttribute("compressionFlag",
+ iTXt_compressionFlag.get(i) ? "1" : "0");
+ iTXt_node.setAttribute("compressionMethod",
+ iTXt_compressionMethod.get(i).toString());
iTXt_node.setAttribute("languageTag",
- (String)iTXt_languageTag.get(i));
+ iTXt_languageTag.get(i));
iTXt_node.setAttribute("translatedKeyword",
- (String)iTXt_translatedKeyword.get(i));
- iTXt_node.setAttribute("text", (String)iTXt_text.get(i));
+ iTXt_translatedKeyword.get(i));
+ iTXt_node.setAttribute("text", iTXt_text.get(i));
iTXt_parent.appendChild(iTXt_node);
}
@@ -1037,11 +1035,11 @@
for (int i = 0; i < iTXt_keyword.size(); i++) {
node = new IIOMetadataNode("TextEntry");
- node.setAttribute("keyword", (String)iTXt_keyword.get(i));
- node.setAttribute("value", (String)iTXt_text.get(i));
+ node.setAttribute("keyword", iTXt_keyword.get(i));
+ node.setAttribute("value", iTXt_text.get(i));
node.setAttribute("language",
- (String)iTXt_languageTag.get(i));
- if (((Integer)iTXt_compressionFlag.get(i)).intValue() == 1) {
+ iTXt_languageTag.get(i));
+ if (iTXt_compressionFlag.get(i)) {
node.setAttribute("compression", "deflate");
} else {
node.setAttribute("compression", "none");
@@ -1427,11 +1425,11 @@
boolean compressionFlag =
getBooleanAttribute(iTXt_node, "compressionFlag");
- iTXt_compressionFlag.add(new Boolean(compressionFlag));
+ iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
String compressionMethod =
getAttribute(iTXt_node, "compressionMethod");
- iTXt_compressionMethod.add(compressionMethod);
+ iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
String languageTag =
getAttribute(iTXt_node, "languageTag");
@@ -1950,13 +1948,10 @@
tEXt_text.add(value);
}
} else {
- int flag = compression.equals("zip") ?
- 1 : 0;
-
// Use an iTXt node
iTXt_keyword.add(keyword);
- iTXt_compressionFlag.add(new Integer(flag));
- iTXt_compressionMethod.add(new Integer(0));
+ iTXt_compressionFlag.add(Boolean.valueOf(compression.equals("zip")));
+ iTXt_compressionMethod.add(Integer.valueOf(0));
iTXt_languageTag.add(language);
iTXt_translatedKeyword.add(keyword); // fake it
iTXt_text.add(value);
@@ -1993,12 +1988,12 @@
gAMA_present = false;
hIST_present = false;
iCCP_present = false;
- iTXt_keyword = new ArrayList();
- iTXt_compressionFlag = new ArrayList();
- iTXt_compressionMethod = new ArrayList();
- iTXt_languageTag = new ArrayList();
- iTXt_translatedKeyword = new ArrayList();
- iTXt_text = new ArrayList();
+ iTXt_keyword = new ArrayList<String>();
+ iTXt_compressionFlag = new ArrayList<Boolean>();
+ iTXt_compressionMethod = new ArrayList<Integer>();
+ iTXt_languageTag = new ArrayList<String>();
+ iTXt_translatedKeyword = new ArrayList<String>();
+ iTXt_text = new ArrayList<String>();
pHYs_present = false;
sBIT_present = false;
sPLT_present = false;
--- a/jdk/src/share/classes/java/awt/print/PrinterJob.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/java/awt/print/PrinterJob.java Fri Jan 09 21:54:17 2009 -0800
@@ -117,15 +117,18 @@
* FileOutputStream outstream;
* StreamPrintService psPrinter;
* String psMimeType = "application/postscript";
+ * PrinterJob pj = PrinterJob.getPrinterJob();
*
* StreamPrintServiceFactory[] factories =
* PrinterJob.lookupStreamPrintServices(psMimeType);
* if (factories.length > 0) {
* try {
* outstream = new File("out.ps");
- * psPrinter = factories[0].getPrintService(fos);
+ * psPrinter = factories[0].getPrintService(outstream);
* // psPrinter can now be set as the service on a PrinterJob
- * } catch (FileNotFoundException e) {
+ * pj.setPrintService(psPrinter)
+ * } catch (Exception e) {
+ * e.printStackTrace();
* }
* }
* </pre>
--- a/jdk/src/share/classes/javax/print/Doc.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/Doc.java Fri Jan 09 21:54:17 2009 -0800
@@ -28,9 +28,7 @@
import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import javax.print.attribute.AttributeSet;
import javax.print.attribute.DocAttributeSet;
--- a/jdk/src/share/classes/javax/print/DocFlavor.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/DocFlavor.java Fri Jan 09 21:54:17 2009 -0800
@@ -30,7 +30,6 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
-import java.util.Map;
/**
* Class <code>DocFlavor</code> encapsulates an object that specifies the
--- a/jdk/src/share/classes/javax/print/DocPrintJob.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/DocPrintJob.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,7 +25,6 @@
package javax.print;
-import javax.print.attribute.AttributeSet;
import javax.print.attribute.PrintJobAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.event.PrintJobAttributeListener;
--- a/jdk/src/share/classes/javax/print/MultiDocPrintService.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/MultiDocPrintService.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,11 +25,6 @@
package javax.print;
-import java.util.Map;
-
-import javax.print.attribute.Attribute;
-import javax.print.event.PrintServiceAttributeListener;
-
/** Interface MultiPrintService is the factory for a MultiDocPrintJob.
* A MultiPrintService
--- a/jdk/src/share/classes/javax/print/PrintServiceLookup.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/PrintServiceLookup.java Fri Jan 09 21:54:17 2009 -0800
@@ -28,7 +28,6 @@
import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
import javax.print.attribute.AttributeSet;
import sun.awt.AppContext;
--- a/jdk/src/share/classes/javax/print/attribute/URISyntax.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/attribute/URISyntax.java Fri Jan 09 21:54:17 2009 -0800
@@ -28,7 +28,6 @@
import java.io.Serializable;
import java.net.URI;
-import java.net.URISyntaxException;
/**
* Class URISyntax is an abstract base class providing the common
--- a/jdk/src/share/classes/javax/print/event/PrintServiceAttributeEvent.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/javax/print/event/PrintServiceAttributeEvent.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,7 +25,6 @@
package javax.print.event;
-import java.util.List;
import javax.print.PrintService;
import javax.print.attribute.AttributeSetUtilities;
import javax.print.attribute.PrintServiceAttributeSet;
--- a/jdk/src/share/classes/sun/font/Decoration.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/font/Decoration.java Fri Jan 09 21:54:17 2009 -0800
@@ -267,7 +267,9 @@
CoreMetrics cm = label.getCoreMetrics();
if (strikethrough) {
Stroke savedStroke = g2d.getStroke();
- g2d.setStroke(new BasicStroke(cm.strikethroughThickness));
+ g2d.setStroke(new BasicStroke(cm.strikethroughThickness,
+ BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER));
float strikeY = y + cm.strikethroughOffset;
g2d.draw(new Line2D.Float(x1, strikeY, x2, strikeY));
g2d.setStroke(savedStroke);
@@ -341,7 +343,7 @@
Rectangle2D visBounds = label.handleGetVisualBounds();
- if (swapColors || bgPaint != null
+ if (swapColors || bgPaint != null || strikethrough
|| stdUnderline != null || imUnderline != null) {
float minX = 0;
@@ -377,6 +379,7 @@
// NOTE: The performace of the following code may
// be very poor.
float ulThickness = cm.underlineThickness;
+ float ulOffset = cm.underlineOffset;
Rectangle2D lb = label.getLogicalBounds();
float x1 = x;
@@ -385,12 +388,15 @@
Area area = null;
if (stdUnderline != null) {
- Shape ul = stdUnderline.getUnderlineShape(ulThickness, x1, x2, y);
+ Shape ul = stdUnderline.getUnderlineShape(ulThickness,
+ x1, x2, y+ulOffset);
area = new Area(ul);
}
if (strikethrough) {
- Stroke stStroke = new BasicStroke(cm.strikethroughThickness);
+ Stroke stStroke = new BasicStroke(cm.strikethroughThickness,
+ BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER);
float shiftY = y + cm.strikethroughOffset;
Line2D line = new Line2D.Float(x1, shiftY, x2, shiftY);
Area slArea = new Area(stStroke.createStrokedShape(line));
@@ -402,7 +408,8 @@
}
if (imUnderline != null) {
- Shape ul = imUnderline.getUnderlineShape(ulThickness, x1, x2, y);
+ Shape ul = imUnderline.getUnderlineShape(ulThickness,
+ x1, x2, y+ulOffset);
Area ulArea = new Area(ul);
if (area == null) {
area = ulArea;
--- a/jdk/src/share/classes/sun/font/FontManager.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/font/FontManager.java Fri Jan 09 21:54:17 2009 -0800
@@ -3344,7 +3344,7 @@
int fontFormat = FONTFORMAT_NONE;
int fontRank = Font2D.UNKNOWN_RANK;
- if (ext.equals(".ttf") || isTTC) {
+ if (ext.equals(".ttf") || ext.equals(".otf") || isTTC) {
fontFormat = FONTFORMAT_TRUETYPE;
fontRank = Font2D.TTF_RANK;
} else if (ext.equals(".pfa") || ext.equals(".pfb")) {
--- a/jdk/src/share/classes/sun/font/TrueTypeFont.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/font/TrueTypeFont.java Fri Jan 09 21:54:17 2009 -0800
@@ -90,6 +90,7 @@
public static final int ttcfTag = 0x74746366; // 'ttcf' - TTC file
public static final int v1ttTag = 0x00010000; // 'v1tt' - Version 1 TT font
public static final int trueTag = 0x74727565; // 'true' - Version 2 TT font
+ public static final int ottoTag = 0x4f54544f; // 'otto' - OpenType font
/* -- ID's used in the 'name' table */
public static final int MS_PLATFORM_ID = 3;
@@ -490,6 +491,7 @@
case v1ttTag:
case trueTag:
+ case ottoTag:
break;
default:
--- a/jdk/src/share/classes/sun/font/Underline.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/font/Underline.java Fri Jan 09 21:54:17 2009 -0800
@@ -126,7 +126,9 @@
private BasicStroke createStroke(float lineThickness) {
if (dashPattern == null) {
- return new BasicStroke(lineThickness);
+ return new BasicStroke(lineThickness,
+ BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER);
}
else {
return new BasicStroke(lineThickness,
--- a/jdk/src/share/classes/sun/java2d/SunGraphicsEnvironment.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/java2d/SunGraphicsEnvironment.java Fri Jan 09 21:54:17 2009 -0800
@@ -812,7 +812,9 @@
return(name.startsWith(".ttf", offset) ||
name.startsWith(".TTF", offset) ||
name.startsWith(".ttc", offset) ||
- name.startsWith(".TTC", offset));
+ name.startsWith(".TTC", offset) ||
+ name.startsWith(".otf", offset) ||
+ name.startsWith(".OTF", offset));
}
}
}
@@ -835,31 +837,11 @@
}
}
- public static class TTorT1Filter implements FilenameFilter {
- public boolean accept(File dir, String name) {
-
- /* all conveniently have the same suffix length */
- int offset = name.length()-4;
- if (offset <= 0) { /* must be at least A.ttf or A.pfa */
- return false;
- } else {
- boolean isTT =
- name.startsWith(".ttf", offset) ||
- name.startsWith(".TTF", offset) ||
- name.startsWith(".ttc", offset) ||
- name.startsWith(".TTC", offset);
- if (isTT) {
- return true;
- } else if (noType1Font) {
- return false;
- } else {
- return(name.startsWith(".pfa", offset) ||
- name.startsWith(".pfb", offset) ||
- name.startsWith(".PFA", offset) ||
- name.startsWith(".PFB", offset));
- }
- }
- }
+ public static class TTorT1Filter implements FilenameFilter {
+ public boolean accept(File dir, String name) {
+ return SunGraphicsEnvironment.ttFilter.accept(dir, name) ||
+ SunGraphicsEnvironment.t1Filter.accept(dir, name);
+ }
}
/* No need to keep consing up new instances - reuse a singleton.
@@ -1290,6 +1272,13 @@
displayChanger.notifyPaletteChanged();
}
+ /**
+ * Returns true when the display is local, false for remote displays.
+ *
+ * @return true when the display is local, false for remote displays
+ */
+ public abstract boolean isDisplayLocal();
+
/*
* ----DISPLAY CHANGE SUPPORT----
*/
--- a/jdk/src/share/classes/sun/java2d/SurfaceData.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/java2d/SurfaceData.java Fri Jan 09 21:54:17 2009 -0800
@@ -449,7 +449,8 @@
// For now the answer can only be true in the following cases:
if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
- sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR)
+ sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
+ sg2d.surfaceData.getTransparency() == Transparency.OPAQUE)
{
if (haveLCDLoop == LCDLOOP_UNKNOWN) {
DrawGlyphListLCD loop =
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,17 +25,13 @@
package sun.java2d.opengl;
-import java.awt.AlphaComposite;
-import java.awt.Color;
import java.awt.Composite;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
import java.lang.ref.WeakReference;
-import sun.awt.image.BufImgSurfaceData;
import sun.java2d.SurfaceData;
import sun.java2d.loops.Blit;
import sun.java2d.loops.CompositeType;
@@ -84,6 +80,8 @@
OGLSurfaceData.PF_INT_BGR),
new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
OGLSurfaceData.PF_INT_BGRX),
+ new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+ OGLSurfaceData.PF_3BYTE_BGR),
new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
OGLSurfaceData.PF_USHORT_565_RGB),
new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
@@ -106,6 +104,8 @@
OGLSurfaceData.PF_INT_BGR),
new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
OGLSurfaceData.PF_INT_BGRX),
+ new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+ OGLSurfaceData.PF_3BYTE_BGR),
new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
OGLSurfaceData.PF_USHORT_565_RGB),
new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
@@ -127,6 +127,8 @@
OGLSurfaceData.PF_INT_BGR),
new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
OGLSurfaceData.PF_INT_BGRX),
+ new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+ OGLSurfaceData.PF_3BYTE_BGR),
new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
OGLSurfaceData.PF_USHORT_565_RGB),
new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
@@ -155,6 +157,8 @@
OGLSurfaceData.PF_INT_BGR),
new OGLSwToTextureBlit(SurfaceType.IntBgrx,
OGLSurfaceData.PF_INT_BGRX),
+ new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
+ OGLSurfaceData.PF_3BYTE_BGR),
new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
OGLSurfaceData.PF_USHORT_565_RGB),
new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java Fri Jan 09 21:54:17 2009 -0800
@@ -120,6 +120,7 @@
public static final int PF_USHORT_555_RGBX = 8;
public static final int PF_BYTE_GRAY = 9;
public static final int PF_USHORT_GRAY = 10;
+ public static final int PF_3BYTE_BGR = 11;
/**
* SurfaceTypes
@@ -401,6 +402,7 @@
* - the fragment shader extension is available, and
* - blending is disabled, and
* - the source color is opaque
+ * - and the destination is opaque
*
* Eventually, we could enhance the native OGL text rendering code
* and remove the above restrictions, but that would require significantly
@@ -410,7 +412,8 @@
return
graphicsConfig.isCapPresent(CAPS_EXT_LCD_SHADER) &&
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
- sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR;
+ sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
+ sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
}
public void validatePipe(SunGraphics2D sg2d) {
--- a/jdk/src/share/classes/sun/java2d/pipe/BufferedContext.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/java2d/pipe/BufferedContext.java Fri Jan 09 21:54:17 2009 -0800
@@ -90,7 +90,8 @@
private Region validatedClip;
private Composite validatedComp;
private Paint validatedPaint;
- private boolean isValidatedPaintAColor;
+ // renamed from isValidatedPaintAColor as part of a work around for 6764257
+ private boolean isValidatedPaintJustAColor;
private int validatedRGB;
private int validatedFlags;
private boolean xformInUse;
@@ -182,7 +183,7 @@
if (paint instanceof Color) {
// REMIND: not 30-bit friendly
int newRGB = ((Color)paint).getRGB();
- if (isValidatedPaintAColor) {
+ if (isValidatedPaintJustAColor) {
if (newRGB != validatedRGB) {
validatedRGB = newRGB;
updatePaint = true;
@@ -190,13 +191,13 @@
} else {
validatedRGB = newRGB;
updatePaint = true;
- isValidatedPaintAColor = true;
+ isValidatedPaintJustAColor = true;
}
} else if (validatedPaint != paint) {
updatePaint = true;
// this should be set when we are switching from paint to color
// in which case this condition will be true
- isValidatedPaintAColor = false;
+ isValidatedPaintJustAColor = false;
}
if ((currentContext != this) ||
@@ -281,7 +282,7 @@
txChanged = true;
}
// non-Color paints may require paint revalidation
- if (!isValidatedPaintAColor && txChanged) {
+ if (!isValidatedPaintJustAColor && txChanged) {
updatePaint = true;
}
@@ -427,10 +428,12 @@
resetTransform();
resetComposite();
resetClip();
+ BufferedPaints.resetPaint(rq);
invalidateSurfaces();
validatedComp = null;
validatedClip = null;
validatedPaint = null;
+ isValidatedPaintJustAColor = false;
xformInUse = false;
}
--- a/jdk/src/share/classes/sun/print/PSPathGraphics.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/print/PSPathGraphics.java Fri Jan 09 21:54:17 2009 -0800
@@ -30,7 +30,6 @@
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
-import java.awt.Paint;
import java.awt.Shape;
import java.awt.Transparency;
--- a/jdk/src/share/classes/sun/print/PrintJobAttributeException.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/print/PrintJobAttributeException.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,7 +25,6 @@
package sun.print;
-import javax.print.DocFlavor;
import javax.print.AttributeException;
import javax.print.PrintException;
import javax.print.attribute.Attribute;
--- a/jdk/src/share/classes/sun/print/SunMinMaxPage.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/print/SunMinMaxPage.java Fri Jan 09 21:54:17 2009 -0800
@@ -25,7 +25,6 @@
package sun.print;
-import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintRequestAttribute;
/*
--- a/jdk/src/share/classes/sun/print/SunPageSelection.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/print/SunPageSelection.java Fri Jan 09 21:54:17 2009 -0800
@@ -26,7 +26,6 @@
package sun.print;
import javax.print.attribute.PrintRequestAttribute;
-import javax.print.attribute.standard.Media;
/*
* A class used to determine the range of pages to be printed.
--- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java Fri Jan 09 21:54:17 2009 -0800
@@ -55,6 +55,7 @@
import java.util.*;
import sun.font.FontDesignMetrics;
import sun.font.FontManager;
+import sun.java2d.SunGraphicsEnvironment;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -1478,22 +1479,14 @@
* appear capable of performing gamma correction needed for LCD text.
*/
public static boolean isLocalDisplay() {
- try {
- // On Windows just return true. Permission to read os.name
- // is granted to all code but wrapped in try to be safe.
- if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) {
- return true;
- }
- // Else probably Solaris or Linux in which case may be remote X11
- Class<?> x11Class = Class.forName("sun.awt.X11GraphicsEnvironment");
- Method isDisplayLocalMethod = x11Class.getMethod(
- "isDisplayLocal", new Class[0]);
- return (Boolean)isDisplayLocalMethod.invoke(null, (Object[])null);
- } catch (Throwable t) {
+ boolean isLocal;
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ if (ge instanceof SunGraphicsEnvironment) {
+ isLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal();
+ } else {
+ isLocal = true;
}
- // If we get here we're most likely being run on some other O/S
- // or we didn't properly detect Windows.
- return true;
+ return isLocal;
}
/**
--- a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java Fri Jan 09 21:54:17 2009 -0800
@@ -60,6 +60,9 @@
import java.awt.image.WritableRaster;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
import java.util.ArrayList;
import javax.swing.JComponent;
@@ -84,6 +87,7 @@
static Group.EnableSet bufimgsrcroot;
static Group imgtestroot;
+ static Group imgoptionsroot;
static Group imageOpRoot;
static Group imageOpOptRoot;
@@ -92,6 +96,7 @@
static Group bufImgOpTestRoot;
static Group rasterOpTestRoot;
static Option opList;
+ static Option doTouchSrc;
static String transNodeNames[] = {
null, "opaque", "bitmask", "translucent",
@@ -105,9 +110,19 @@
imageroot = new Group(graphicsroot, "imaging",
"Imaging Benchmarks");
imageroot.setTabbed();
+
imgsrcroot = new Group.EnableSet(imageroot, "src",
"Image Rendering Sources");
imgsrcroot.setBordered(true);
+
+ imgoptionsroot = new Group(imgsrcroot, "options",
+ "Image Source Options");
+ imgoptionsroot.setBordered(true);
+ doTouchSrc =
+ new Option.Toggle(imgoptionsroot, "touchsrc",
+ "Touch src image before every operation",
+ Option.Toggle.Off);
+
imgtestroot = new Group(imageroot, "tests",
"Image Rendering Tests");
imgtestroot.setBordered(true);
@@ -131,7 +146,11 @@
new BufImg(BufferedImage.TYPE_INT_RGB);
new BufImg(BufferedImage.TYPE_INT_ARGB);
new BufImg(BufferedImage.TYPE_BYTE_GRAY);
+ new BufImg(BufferedImage.TYPE_3BYTE_BGR);
new BmByteIndexBufImg();
+ new BufImg(BufferedImage.TYPE_INT_RGB, true);
+ new BufImg(BufferedImage.TYPE_INT_ARGB, true);
+ new BufImg(BufferedImage.TYPE_3BYTE_BGR, true);
imageOpRoot = new Group(imageroot, "imageops",
"Image Op Benchmarks");
@@ -193,6 +212,7 @@
}
public static class Context extends GraphicsTests.Context {
+ boolean touchSrc;
Image src;
AffineTransform tx;
}
@@ -206,6 +226,7 @@
{
super(parent, nodeName, description);
addDependency(imgsrcroot, srcFilter);
+ addDependency(doTouchSrc);
}
public GraphicsTests.Context createContext() {
@@ -217,6 +238,7 @@
ImageTests.Context ictx = (ImageTests.Context) ctx;
ictx.src = env.getSrcImage();
+ ictx.touchSrc = env.isEnabled(doTouchSrc);
}
public abstract static class TriStateImageType extends Group {
@@ -272,13 +294,6 @@
public static class CompatImg extends TriStateImageType {
int transparency;
- public static String Descriptions[] = {
- "Default Compatible Image",
- "Opaque Compatible Image",
- "Bitmask Compatible Image",
- "Translucent Compatible Image",
- };
-
public CompatImg(int transparency) {
super(imgsrcroot,
Destinations.CompatImg.ShortNames[transparency],
@@ -296,6 +311,7 @@
public static class BufImg extends TriStateImageType {
int type;
+ boolean unmanaged;
static int Transparencies[] = {
Transparency.TRANSLUCENT, // "custom",
@@ -315,15 +331,37 @@
};
public BufImg(int type) {
+ this(type, false);
+ }
+
+ public BufImg(int type, boolean unmanaged) {
super(bufimgsrcroot,
+ (unmanaged ? "unmanaged" : "") +
Destinations.BufImg.ShortNames[type],
+ (unmanaged ? "Unmanaged " : "") +
Destinations.BufImg.Descriptions[type],
Transparencies[type]);
this.type = type;
+ this.unmanaged = unmanaged;
}
public Image makeImage(TestEnvironment env, int w, int h) {
- return new BufferedImage(w, h, type);
+ BufferedImage img = new BufferedImage(w, h, type);
+ if (unmanaged) {
+ DataBuffer db = img.getRaster().getDataBuffer();
+ if (db instanceof DataBufferInt) {
+ ((DataBufferInt)db).getData();
+ } else if (db instanceof DataBufferShort) {
+ ((DataBufferShort)db).getData();
+ } else if (db instanceof DataBufferByte) {
+ ((DataBufferByte)db).getData();
+ } else {
+ try {
+ img.setAccelerationPriority(0.0f);
+ } catch (Throwable e) {}
+ }
+ }
+ return img;
}
}
@@ -471,15 +509,33 @@
g.translate(ictx.orgX, ictx.orgY);
Image src = ictx.src;
if (ictx.animate) {
- do {
- g.drawImage(src, x, y, null);
- if ((x -= 3) < 0) x += ictx.maxX;
- if ((y -= 1) < 0) y += ictx.maxY;
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ }
} else {
- do {
- g.drawImage(src, x, y, null);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, null);
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, null);
+ } while (--numReps > 0);
+ }
}
g.translate(-ictx.orgX, -ictx.orgY);
}
@@ -505,15 +561,33 @@
Image src = ictx.src;
Color bg = Color.orange;
if (ictx.animate) {
- do {
- g.drawImage(src, x, y, bg, null);
- if ((x -= 3) < 0) x += ictx.maxX;
- if ((y -= 1) < 0) y += ictx.maxY;
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, bg, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, bg, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ }
} else {
- do {
- g.drawImage(src, x, y, bg, null);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, bg, null);
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, bg, null);
+ } while (--numReps > 0);
+ }
}
g.translate(-ictx.orgX, -ictx.orgY);
}
@@ -524,7 +598,7 @@
public DrawImageScale(String dir, float scale) {
super(imgtestroot, "drawimagescale"+dir,
- "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
+ "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
this.scale = scale;
}
@@ -546,15 +620,33 @@
g.translate(ictx.orgX, ictx.orgY);
Image src = ictx.src;
if (ictx.animate) {
- do {
- g.drawImage(src, x, y, w, h, null);
- if ((x -= 3) < 0) x += ictx.maxX;
- if ((y -= 1) < 0) y += ictx.maxY;
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, w, h, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, w, h, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ }
} else {
- do {
- g.drawImage(src, x, y, w, h, null);
- } while (--numReps > 0);
+ Graphics srcG = src.getGraphics();
+ if (ictx.touchSrc) {
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, x, y, w, h, null);
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, x, y, w, h, null);
+ } while (--numReps > 0);
+ }
}
g.translate(-ictx.orgX, -ictx.orgY);
}
@@ -588,17 +680,36 @@
Image src = ictx.src;
AffineTransform tx = ictx.tx;
if (ictx.animate) {
- do {
- tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
- g.drawImage(src, tx, null);
- if ((x -= 3) < 0) x += ictx.maxX;
- if ((y -= 1) < 0) y += ictx.maxY;
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, tx, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ } else {
+ do {
+ tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
+ g.drawImage(src, tx, null);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ }
} else {
tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
- do {
- g.drawImage(src, tx, null);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics srcG = src.getGraphics();
+ do {
+ srcG.fillRect(0, 0, 1, 1);
+ g.drawImage(src, tx, null);
+ } while (--numReps > 0);
+ } else {
+ do {
+ g.drawImage(src, tx, null);
+ } while (--numReps > 0);
+ }
}
g.translate(-ictx.orgX, -ictx.orgY);
}
@@ -736,15 +847,33 @@
Graphics2D g2 = (Graphics2D)ictx.graphics;
g2.translate(ictx.orgX, ictx.orgY);
if (ictx.animate) {
- do {
- g2.drawImage(src, op, x, y);
- if ((x -= 3) < 0) x += ictx.maxX;
- if ((y -= 1) < 0) y += ictx.maxY;
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics gSrc = src.getGraphics();
+ do {
+ gSrc.fillRect(0, 0, 1, 1);
+ g2.drawImage(src, op, x, y);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ } else {
+ do {
+ g2.drawImage(src, op, x, y);
+ if ((x -= 3) < 0) x += ictx.maxX;
+ if ((y -= 1) < 0) y += ictx.maxY;
+ } while (--numReps > 0);
+ }
} else {
- do {
- g2.drawImage(src, op, x, y);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics gSrc = src.getGraphics();
+ do {
+ gSrc.fillRect(0, 0, 1, 1);
+ g2.drawImage(src, op, x, y);
+ } while (--numReps > 0);
+ } else {
+ do {
+ g2.drawImage(src, op, x, y);
+ } while (--numReps > 0);
+ }
}
g2.translate(-ictx.orgX, -ictx.orgY);
}
@@ -778,9 +907,17 @@
BufferedImageOp op = ictx.bufImgOp;
BufferedImage src = ictx.bufSrc;
BufferedImage dst = ictx.bufDst;
- do {
- op.filter(src, dst);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics gSrc = src.getGraphics();
+ do {
+ gSrc.fillRect(0, 0, 1, 1);
+ op.filter(src, dst);
+ } while (--numReps > 0);
+ } else {
+ do {
+ op.filter(src, dst);
+ } while (--numReps > 0);
+ }
}
}
@@ -814,9 +951,17 @@
RasterOp op = ictx.rasterOp;
Raster src = ictx.rasSrc;
WritableRaster dst = ictx.rasDst;
- do {
- op.filter(src, dst);
- } while (--numReps > 0);
+ if (ictx.touchSrc) {
+ Graphics gSrc = ictx.bufSrc.getGraphics();
+ do {
+ gSrc.fillRect(0, 0, 1, 1);
+ op.filter(src, dst);
+ } while (--numReps > 0);
+ } else {
+ do {
+ op.filter(src, dst);
+ } while (--numReps > 0);
+ }
}
}
}
--- a/jdk/src/share/native/sun/font/freetypeScaler.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c Fri Jan 09 21:54:17 2009 -0800
@@ -1281,7 +1281,7 @@
sunFontIDs.rect2DFloatClass,
sunFontIDs.rect2DFloatCtr4,
F26Dot6ToFloat(bbox.xMin),
- F26Dot6ToFloat(bbox.yMax),
+ F26Dot6ToFloat(-bbox.yMax),
F26Dot6ToFloat(bbox.xMax-bbox.xMin),
F26Dot6ToFloat(bbox.yMax-bbox.yMin));
}
--- a/jdk/src/share/native/sun/java2d/opengl/OGLBlitLoops.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/native/sun/java2d/opengl/OGLBlitLoops.c Fri Jan 09 21:54:17 2009 -0800
@@ -203,7 +203,24 @@
j2d_glBitmap(0, 0, 0, 0, (GLfloat)dx1, (GLfloat)-dy1, NULL);
j2d_glPixelZoom(scalex, -scaley);
- j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, srcInfo->rasBase);
+
+ // in case pixel stride is not a multiple of scanline stride the copy
+ // has to be done line by line (see 6207877)
+ if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
+ jint width = sx2-sx1;
+ jint height = sy2-sy1;
+ GLvoid *pSrc = srcInfo->rasBase;
+
+ while (height > 0) {
+ j2d_glDrawPixels(width, 1, pf->format, pf->type, pSrc);
+ j2d_glBitmap(0, 0, 0, 0, (GLfloat)0, (GLfloat)-1, NULL);
+ pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+ height--;
+ }
+ } else {
+ j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, srcInfo->rasBase);
+ }
+
j2d_glPixelZoom(1.0, 1.0);
if (oglc->extraAlpha != 1.0f) {
@@ -250,6 +267,7 @@
jint sx, sy, sw, sh;
GLint glhint = (hint == OGLSD_XFORM_BILINEAR) ? GL_LINEAR : GL_NEAREST;
jboolean adjustAlpha = (pf != NULL && !pf->hasAlpha);
+ jboolean slowPath;
if (oglc->blitTextureID == 0) {
if (!OGLContext_InitBlitTileTexture(oglc)) {
@@ -279,6 +297,10 @@
j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0f);
}
+ // in case pixel stride is not a multiple of scanline stride the copy
+ // has to be done line by line (see 6207877)
+ slowPath = srcInfo->scanStride % srcInfo->pixelStride != 0;
+
for (sy = sy1, dy = dy1; sy < sy2; sy += th, dy += cdh) {
sh = ((sy + th) > sy2) ? (sy2 - sy) : th;
dh = ((dy + cdh) > dy2) ? (dy2 - dy) : cdh;
@@ -291,13 +313,29 @@
ty2 = ((GLdouble)sh) / th;
if (swsurface) {
- j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
- j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
+ if (slowPath) {
+ jint tmph = sh;
+ GLvoid *pSrc = PtrCoord(srcInfo->rasBase,
+ sx, srcInfo->pixelStride,
+ sy, srcInfo->scanStride);
- j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, 0, sw, sh,
- pf->format, pf->type,
- srcInfo->rasBase);
+ while (tmph > 0) {
+ j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, sh - tmph, sw, 1,
+ pf->format, pf->type,
+ pSrc);
+ pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+ tmph--;
+ }
+ } else {
+ j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
+ j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
+
+ j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, 0, sw, sh,
+ pf->format, pf->type,
+ srcInfo->rasBase);
+ }
// the texture image is "right side up", so we align the
// upper-left texture corner with the upper-left quad corner
@@ -356,9 +394,25 @@
jint dx1, jint dy1, jint dx2, jint dy2)
{
j2d_glBindTexture(dstOps->textureTarget, dstOps->textureID);
- j2d_glTexSubImage2D(dstOps->textureTarget, 0,
- dx1, dy1, dx2-dx1, dy2-dy1,
- pf->format, pf->type, srcInfo->rasBase);
+ // in case pixel stride is not a multiple of scanline stride the copy
+ // has to be done line by line (see 6207877)
+ if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
+ jint width = dx2 - dx1;
+ jint height = dy2 - dy1;
+ GLvoid *pSrc = srcInfo->rasBase;
+
+ while (height > 0) {
+ j2d_glTexSubImage2D(dstOps->textureTarget, 0,
+ dx1, dy2 - height, width, 1,
+ pf->format, pf->type, pSrc);
+ pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+ height--;
+ }
+ } else {
+ j2d_glTexSubImage2D(dstOps->textureTarget, 0,
+ dx1, dy1, dx2-dx1, dy2-dy1,
+ pf->format, pf->type, srcInfo->rasBase);
+ }
}
/**
--- a/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c Fri Jan 09 21:54:17 2009 -0800
@@ -73,7 +73,8 @@
1, 0, 1, }, /* 9 - ByteGray */
{ GL_LUMINANCE, GL_UNSIGNED_SHORT,
2, 0, 1, }, /*10 - UshortGray */
-};
+ { GL_BGR, GL_UNSIGNED_BYTE,
+ 1, 0, 1, }, /*11 - ThreeByteBgr */};
/**
* Given a starting value and a maximum limit, returns the first power-of-two
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Fri Jan 09 21:54:17 2009 -0800
@@ -209,7 +209,7 @@
private static native int checkShmExt();
private static native String getDisplayString();
- private static Boolean isDisplayLocal;
+ private Boolean isDisplayLocal;
/**
* This should only be called from the static initializer, so no need for
@@ -234,7 +234,8 @@
return getScreenDevices()[getDefaultScreenNum()];
}
- public static boolean isDisplayLocal() {
+ @Override
+ public boolean isDisplayLocal() {
if (isDisplayLocal == null) {
SunToolkit.awtLock();
try {
--- a/jdk/src/solaris/classes/sun/java2d/opengl/GLXGraphicsConfig.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/opengl/GLXGraphicsConfig.java Fri Jan 09 21:54:17 2009 -0800
@@ -120,12 +120,14 @@
new GLXGetConfigInfo(device.getScreen(), visualnum);
rq.flushAndInvokeNow(action);
cfginfo = action.getConfigInfo();
- OGLContext.setScratchSurface(cfginfo);
- rq.flushAndInvokeNow(new Runnable() {
- public void run() {
- ids[0] = OGLContext.getOGLIdString();
- }
- });
+ if (cfginfo != 0L) {
+ OGLContext.setScratchSurface(cfginfo);
+ rq.flushAndInvokeNow(new Runnable() {
+ public void run() {
+ ids[0] = OGLContext.getOGLIdString();
+ }
+ });
+ }
} finally {
rq.unlock();
}
--- a/jdk/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java Fri Jan 09 21:54:17 2009 -0800
@@ -50,6 +50,7 @@
import sun.font.X11TextRenderer;
import sun.java2d.InvalidPipeException;
import sun.java2d.SunGraphics2D;
+import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.loops.SurfaceType;
@@ -240,6 +241,11 @@
*/
public static native boolean isDgaAvailable();
+ /**
+ * Returns true if shared memory pixmaps are available
+ */
+ private static native boolean isShmPMAvailable();
+
public static boolean isAccelerationEnabled() {
if (accelerationEnabled == null) {
@@ -253,8 +259,17 @@
// true iff prop==true, false otherwise
accelerationEnabled = Boolean.valueOf(prop);
} else {
- // use pixmaps if there is no dga, no matter local or remote
- accelerationEnabled = Boolean.valueOf(!isDgaAvailable());
+ boolean isDisplayLocal = false;
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ if (ge instanceof SunGraphicsEnvironment) {
+ isDisplayLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal();
+ }
+
+ // EXA based drivers tend to place pixmaps in VRAM, slowing down readbacks.
+ // Don't use pixmaps if dga is available,
+ // or we are local and shared memory Pixmaps are not available.
+ accelerationEnabled =
+ !(isDgaAvailable() || (isDisplayLocal && !isShmPMAvailable()));
}
}
}
--- a/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Fri Jan 09 21:54:17 2009 -0800
@@ -46,9 +46,9 @@
public class CUPSPrinter {
-
+ private static final String debugPrefix = "CUPSPrinter>> ";
private static final double PRINTER_DPI = 72.0;
- private static boolean initialized;
+ private boolean initialized;
private static native String getCupsServer();
private static native int getCupsPort();
private static native boolean canConnect(String server, int port);
@@ -156,7 +156,7 @@
/**
* Initialize media by translating PPD info to PrintService attributes.
*/
- private void initMedia() {
+ private synchronized void initMedia() {
if (initialized) {
return;
} else {
@@ -392,9 +392,9 @@
* Detects if CUPS is running.
*/
public static boolean isCupsRunning() {
- IPPPrintService.debug_println("libFound "+libFound);
+ IPPPrintService.debug_println(debugPrefix+"libFound "+libFound);
if (libFound) {
- IPPPrintService.debug_println("CUPS server "+getServer()+
+ IPPPrintService.debug_println(debugPrefix+"CUPS server "+getServer()+
" port "+getPort());
return canConnect(getServer(), getPort());
} else {
--- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java Fri Jan 09 21:54:17 2009 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,18 +57,28 @@
import java.nio.charset.Charset;
import java.util.Iterator;
+import java.util.HashSet;
public class IPPPrintService implements PrintService, SunPrinterJobService {
- public static boolean debugPrint = false;
- private static String debugPrefix = "IPPPrintService>> ";
+ public static final boolean debugPrint;
+ private static final String debugPrefix = "IPPPrintService>> ";
protected static void debug_println(String str) {
if (debugPrint) {
System.out.println(str);
}
}
+ private static final String FORCE_PIPE_PROP = "sun.print.ippdebug";
+
+ static {
+ String debugStr =
+ (String)java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP));
+
+ debugPrint = "true".equalsIgnoreCase(debugStr);
+ }
private String printer;
private URI myURI;
@@ -382,7 +392,7 @@
if ((urlConnection = getIPPConnection(myURL)) == null) {
mediaSizeNames = new MediaSizeName[0];
mediaTrays = new MediaTray[0];
- debug_println("NULL urlConnection ");
+ debug_println(debugPrefix+"initAttributes, NULL urlConnection ");
init = true;
return;
}
@@ -407,7 +417,7 @@
return;
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
- " error creating CUPSPrinter e="+e);
+ "initAttributes, error creating CUPSPrinter e="+e);
}
}
@@ -486,28 +496,26 @@
/* Test if the flavor is compatible with the category */
if ((category == Copies.class) ||
(category == CopiesSupported.class)) {
- CopiesSupported cs = new CopiesSupported(1, MAXCOPIES);
- AttributeClass attribClass = (getAttMap != null) ?
- (AttributeClass)getAttMap.get(cs.getName()) : null;
- if (attribClass != null) {
- int[] range = attribClass.getIntRangeValue();
- cs = new CopiesSupported(range[0], range[1]);
+ if (flavor == null ||
+ !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
+ CopiesSupported cs = new CopiesSupported(1, MAXCOPIES);
+ AttributeClass attribClass = (getAttMap != null) ?
+ (AttributeClass)getAttMap.get(cs.getName()) : null;
+ if (attribClass != null) {
+ int[] range = attribClass.getIntRangeValue();
+ cs = new CopiesSupported(range[0], range[1]);
+ }
+ return cs;
+ } else {
+ return null;
}
- return cs;
} else if (category == Chromaticity.class) {
if (flavor == null ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
- flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
- flavor.equals(DocFlavor.URL.GIF) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
- flavor.equals(DocFlavor.URL.JPEG) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
- flavor.equals(DocFlavor.URL.PNG)) {
-
+ !isIPPSupportedImages(flavor.getMimeType())) {
Chromaticity[]arr = new Chromaticity[1];
arr[0] = Chromaticity.COLOR;
return (arr);
@@ -822,7 +830,7 @@
boolean psSupported = false;
String[] docFlavors = attribClass.getArrayOfStringValues();
DocFlavor[] flavors;
- ArrayList docList = new ArrayList();
+ HashSet docList = new HashSet();
int j;
String hostEnc = DocFlavor.hostEncoding.
toLowerCase(Locale.ENGLISH);
@@ -839,18 +847,6 @@
docList.addAll(Arrays.asList(flavors));
- if (isCupsPrinter) {
- /*
- Always add Pageable and Printable for CUPS
- since it uses Filters to convert from Postscript
- to device printer language.
- */
- docList.add(
- DocFlavor.SERVICE_FORMATTED.PAGEABLE);
- docList.add(
- DocFlavor.SERVICE_FORMATTED.PRINTABLE);
- }
-
if (mimeType.equals("text/plain") &&
addHostEncoding) {
docList.add(Arrays.asList(textPlainHost));
@@ -880,16 +876,19 @@
}
// check if we need to add image DocFlavors
+ // and Pageable/Printable flavors
if (psSupported || isCupsPrinter) {
- if (!jpgImagesAdded) {
- docList.addAll(Arrays.asList(imageJPG));
- }
- if (!pngImagesAdded) {
- docList.addAll(Arrays.asList(imagePNG));
- }
- if (!gifImagesAdded) {
- docList.addAll(Arrays.asList(imageGIF));
- }
+ /*
+ Always add Pageable and Printable for CUPS
+ since it uses Filters to convert from Postscript
+ to device printer language.
+ */
+ docList.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE);
+ docList.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
+
+ docList.addAll(Arrays.asList(imageJPG));
+ docList.addAll(Arrays.asList(imagePNG));
+ docList.addAll(Arrays.asList(imageGIF));
}
supportedDocFlavors = new DocFlavor[docList.size()];
docList.toArray(supportedDocFlavors);
@@ -922,6 +921,9 @@
* Finds matching CustomMediaSizeName of given media.
*/
public CustomMediaSizeName findCustomMedia(MediaSizeName media) {
+ if (customMediaSizeNames == null) {
+ return null;
+ }
for (int i=0; i< customMediaSizeNames.length; i++) {
CustomMediaSizeName custom =
(CustomMediaSizeName)customMediaSizeNames[i];
@@ -1203,7 +1205,7 @@
return true;
}
for (int i=0; i<mediaSizeNames.length; i++) {
- debug_println("mediaSizeNames[i] "+mediaSizeNames[i]);
+ debug_println(debugPrefix+"isSupportedMedia, mediaSizeNames[i] "+mediaSizeNames[i]);
if (msn.equals(mediaSizeNames[i])) {
return true;
}
@@ -1228,7 +1230,7 @@
}
- public boolean isAttributeValueSupported(Attribute attr,
+ public boolean isAttributeValueSupported(Attribute attr,
DocFlavor flavor,
AttributeSet attributes) {
if (attr == null) {
@@ -1257,21 +1259,18 @@
if ((flavor == null) ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
- flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
- flavor.equals(DocFlavor.URL.GIF) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
- flavor.equals(DocFlavor.URL.JPEG) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
- flavor.equals(DocFlavor.URL.PNG)) {
+ !isIPPSupportedImages(flavor.getMimeType())) {
return attr == Chromaticity.COLOR;
} else {
return false;
}
} else if (attr.getCategory() == Copies.class) {
- return isSupportedCopies((Copies)attr);
+ return (flavor == null ||
+ !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) &&
+ isSupportedCopies((Copies)attr);
+
} else if (attr.getCategory() == Destination.class) {
if (flavor == null ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
@@ -1667,9 +1666,10 @@
try {
osw = new OutputStreamWriter(os, "UTF-8");
} catch (java.io.UnsupportedEncodingException exc) {
- debug_println("UTF-8 not supported? Exception: "+exc);
+ debug_println(debugPrefix+"writeIPPRequest, UTF-8 not supported? Exception: "+exc);
return false;
}
+ debug_println(debugPrefix+"writeIPPRequest, op code= "+operCode);
char[] opCode = new char[2];
opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16);
opCode[1] = (char)Byte.parseByte(operCode.substring(2,4), 16);
@@ -1710,7 +1710,7 @@
osw.flush();
osw.close();
} catch (java.io.IOException ioe) {
- debug_println(debugPrefix+"IPPPrintService Exception in writeIPPRequest: "+ioe);
+ debug_println(debugPrefix+"writeIPPRequest, IPPPrintService Exception in writeIPPRequest: "+ioe);
return false;
}
return true;
@@ -1747,7 +1747,7 @@
while ((response[0] >= GRPTAG_OP_ATTRIBUTES) &&
(response[0] <= GRPTAG_PRINTER_ATTRIBUTES)
&& (response[0] != GRPTAG_END_ATTRIBUTES)) {
- debug_println(debugPrefix+"checking group tag, response[0]= "+
+ debug_println(debugPrefix+"readIPPResponse, checking group tag, response[0]= "+
response[0]);
outObj = new ByteArrayOutputStream();
@@ -1786,6 +1786,7 @@
outArray);
responseMap.put(ac.getName(), ac);
+ debug_println(debugPrefix+ "readIPPResponse "+ac);
}
outObj = new ByteArrayOutputStream();
@@ -1858,6 +1859,9 @@
} catch (java.io.IOException e) {
debug_println(debugPrefix+"readIPPResponse: "+e);
+ if (debugPrint) {
+ e.printStackTrace();
+ }
return null;
}
}
@@ -1872,4 +1876,8 @@
(obj instanceof IPPPrintService &&
((IPPPrintService)obj).getName().equals(getName())));
}
+
+ public int hashCode() {
+ return this.getClass().hashCode()+getName().hashCode();
+ }
}
--- a/jdk/src/solaris/classes/sun/print/UnixPrintService.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintService.java Fri Jan 09 21:54:17 2009 -0800
@@ -686,19 +686,7 @@
}
if (category == Chromaticity.class) {
- if (flavor == null ||
- flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
- flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
- flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
- flavor.equals(DocFlavor.URL.GIF) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
- flavor.equals(DocFlavor.URL.JPEG) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
- flavor.equals(DocFlavor.URL.PNG)) {
-
+ if (flavor == null || isServiceFormattedFlavor(flavor)) {
Chromaticity[]arr = new Chromaticity[1];
arr[0] = Chromaticity.COLOR;
return (arr);
@@ -730,18 +718,7 @@
}
return new RequestingUserName(userName, null);
} else if (category == OrientationRequested.class) {
- if (flavor == null ||
- flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
- flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
- flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
- flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
- flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
- flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
- flavor.equals(DocFlavor.URL.GIF) ||
- flavor.equals(DocFlavor.URL.JPEG) ||
- flavor.equals(DocFlavor.URL.PNG)) {
+ if (flavor == null || isServiceFormattedFlavor(flavor)) {
OrientationRequested []arr = new OrientationRequested[3];
arr[0] = OrientationRequested.PORTRAIT;
arr[1] = OrientationRequested.LANDSCAPE;
@@ -752,7 +729,14 @@
}
} else if ((category == Copies.class) ||
(category == CopiesSupported.class)) {
- return new CopiesSupported(1, MAXCOPIES);
+ if (flavor == null ||
+ !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
+ return new CopiesSupported(1, MAXCOPIES);
+ } else {
+ return null;
+ }
} else if (category == Media.class) {
Media []arr = new Media[mediaSizes.length];
System.arraycopy(mediaSizes, 0, arr, 0, mediaSizes.length);
@@ -917,8 +901,10 @@
}
}
else if (attr.getCategory() == Copies.class) {
- return
- (flavor == null || isServiceFormattedFlavor(flavor)) &&
+ return (flavor == null ||
+ !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
+ flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) &&
isSupportedCopies((Copies)attr);
} else if (attr.getCategory() == Destination.class) {
URI uri = ((Destination)attr).getURI();
--- a/jdk/src/solaris/native/sun/awt/fontpath.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/native/sun/awt/fontpath.c Fri Jan 09 21:54:17 2009 -0800
@@ -156,7 +156,7 @@
isLocal = JNU_CallStaticMethodByName(env, NULL,
"sun/awt/X11GraphicsEnvironment",
- "isDisplayLocal",
+ "_isDisplayLocal",
"()Z").z;
isLocalSet = True;
return isLocal;
@@ -1233,7 +1233,7 @@
for (j=0; j<nfonts; j++) {
FcPattern *fontPattern = fontset->fonts[j];
FcChar8 *fontformat;
- FcCharSet *unionCharset, *charset;
+ FcCharSet *unionCharset = NULL, *charset;
fontformat = NULL;
(*FcPatternGetString)(fontPattern, FC_FONTFORMAT, 0, &fontformat);
@@ -1256,7 +1256,7 @@
if (nfonts==10) {
minGlyphs = 50;
}
- if (j == 0) {
+ if (unionCharset == NULL) {
unionCharset = charset;
} else {
if ((*FcCharSetSubtractCount)(charset, unionCharset)
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Fri Jan 09 21:54:17 2009 -0800
@@ -208,6 +208,23 @@
#endif /* HEADLESS */
}
+
+/*
+ * Class: sun_java2d_x11_X11SurfaceData
+ * Method: isShmPMAvailable
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
+{
+#if defined(HEADLESS) || !defined(MITSHM)
+ return JNI_FALSE;
+#else
+ return useMitShmPixmaps;
+#endif /* HEADLESS, MITSHM */
+}
+
+
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: initOps
--- a/jdk/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Fri Jan 09 21:54:17 2009 -0800
@@ -393,4 +393,9 @@
private static void dwmCompositionChanged(boolean enabled) {
isDWMCompositionEnabled = enabled;
}
+
+ @Override
+ public boolean isDisplayLocal() {
+ return true;
+ }
}
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java Fri Jan 09 21:54:17 2009 -0800
@@ -85,6 +85,8 @@
D3DSurfaceData.ST_INT_RGB),
new D3DSwToSurfaceBlit(SurfaceType.IntBgr,
D3DSurfaceData.ST_INT_BGR),
+ new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+ D3DSurfaceData.ST_3BYTE_BGR),
new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
D3DSurfaceData.ST_USHORT_565_RGB),
new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
@@ -106,6 +108,8 @@
D3DSurfaceData.ST_INT_RGB),
new D3DSwToSurfaceScale(SurfaceType.IntBgr,
D3DSurfaceData.ST_INT_BGR),
+ new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+ D3DSurfaceData.ST_3BYTE_BGR),
new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb,
D3DSurfaceData.ST_USHORT_565_RGB),
new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb,
@@ -124,6 +128,8 @@
D3DSurfaceData.ST_INT_RGB),
new D3DSwToSurfaceTransform(SurfaceType.IntBgr,
D3DSurfaceData.ST_INT_BGR),
+ new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+ D3DSurfaceData.ST_3BYTE_BGR),
new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
D3DSurfaceData.ST_USHORT_565_RGB),
new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
@@ -147,6 +153,8 @@
D3DSurfaceData.ST_INT_ARGB),
new D3DSwToTextureBlit(SurfaceType.IntBgr,
D3DSurfaceData.ST_INT_BGR),
+ new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr,
+ D3DSurfaceData.ST_3BYTE_BGR),
new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb,
D3DSurfaceData.ST_USHORT_565_RGB),
new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb,
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Fri Jan 09 21:54:17 2009 -0800
@@ -135,6 +135,7 @@
public static final int ST_USHORT_555_RGB = 6;
public static final int ST_BYTE_INDEXED = 7;
public static final int ST_BYTE_INDEXED_BM = 8;
+ public static final int ST_3BYTE_BGR = 9;
/** Equals to D3DSWAPEFFECT_DISCARD */
public static final int SWAP_DISCARD = 1;
@@ -501,12 +502,14 @@
* - the pixel shaders are available, and
* - blending is disabled, and
* - the source color is opaque
+ * - and the destination is opaque
*/
public boolean canRenderLCDText(SunGraphics2D sg2d) {
return
graphicsDevice.isCapPresent(CAPS_LCD_SHADER) &&
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
- sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR;
+ sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
+ sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
}
public void validatePipe(SunGraphics2D sg2d) {
--- a/jdk/src/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java Fri Jan 09 21:54:17 2009 -0800
@@ -127,12 +127,14 @@
new WGLGetConfigInfo(device.getScreen(), pixfmt);
rq.flushAndInvokeNow(action);
cfginfo = action.getConfigInfo();
- OGLContext.setScratchSurface(cfginfo);
- rq.flushAndInvokeNow(new Runnable() {
- public void run() {
- ids[0] = OGLContext.getOGLIdString();
- }
- });
+ if (cfginfo != 0L) {
+ OGLContext.setScratchSurface(cfginfo);
+ rq.flushAndInvokeNow(new Runnable() {
+ public void run() {
+ ids[0] = OGLContext.getOGLIdString();
+ }
+ });
+ }
} finally {
rq.unlock();
}
--- a/jdk/src/windows/native/sun/font/fontpath.c Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/native/sun/font/fontpath.c Fri Jan 09 21:54:17 2009 -0800
@@ -153,7 +153,8 @@
JNIEnv *env = fmi->env;
jstring fullname, fullnameLC;
- if (FontType != TRUETYPE_FONTTYPE) {
+ /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
+ if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
return 1;
}
@@ -227,7 +228,8 @@
JNIEnv *env = fmi->env;
jstring fullname, fullnameLC;
- if (FontType != TRUETYPE_FONTTYPE) {
+ /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
+ if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
return 1;
}
@@ -274,7 +276,8 @@
jstring familyLC;
LOGFONTA lfa;
- if (FontType != TRUETYPE_FONTTYPE) {
+ /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
+ if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
return 1;
}
@@ -323,7 +326,8 @@
int slen;
LOGFONTW lfw;
- if (FontType != TRUETYPE_FONTTYPE) {
+ /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
+ if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
return 1;
}
/* wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */
@@ -383,15 +387,16 @@
* Also if a Font has a name for this locale that name also
* exists in the registry using the appropriate platform encoding.
* What do we do then?
+ *
+ * Note: OpenType fonts seems to have " (TrueType)" suffix on Vista
+ * but " (OpenType)" on XP.
*/
-/* static const wchar_t W_TTSUFFIX[] = L" (TrueType)"; */
-/* static const char C_TTSUFFIX[] = " (TrueType)"; */
-/* static int TTSLEN = 11; hard-coded - be careful */
-static BOOL RegistryToBaseTTNameA(LPCSTR name) {
+static BOOL RegistryToBaseTTNameA(LPSTR name) {
static const char TTSUFFIX[] = " (TrueType)";
+ static const char OTSUFFIX[] = " (OpenType)";
int TTSLEN = strlen(TTSUFFIX);
- char *match;
+ char *suffix;
int len = strlen(name);
if (len == 0) {
@@ -403,19 +408,21 @@
if (len <= TTSLEN) {
return FALSE;
}
- match = strstr(name, TTSUFFIX);
- if ((match != NULL) && (match == name+(len-TTSLEN))) {
- match[0] = '\0'; /* truncate name */
+
+ /* suffix length is the same for truetype and opentype fonts */
+ suffix = name + len - TTSLEN;
+ if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) {
+ suffix[0] = '\0'; /* truncate name */
return TRUE;
- } else {
- return FALSE;
}
+ return FALSE;
}
static BOOL RegistryToBaseTTNameW(LPWSTR name) {
static const wchar_t TTSUFFIX[] = L" (TrueType)";
+ static const wchar_t OTSUFFIX[] = L" (OpenType)";
int TTSLEN = wcslen(TTSUFFIX);
- wchar_t *match;
+ wchar_t *suffix;
int len = wcslen(name);
if (len == 0) {
@@ -427,13 +434,13 @@
if (len <= TTSLEN) {
return FALSE;
}
- match = wcsstr(name, TTSUFFIX);
- if ((match != NULL) && (match == name+(len-TTSLEN))) {
- match[0] = L'\0'; /* truncate name */
+ /* suffix length is the same for truetype and opentype fonts */
+ suffix = name + (len - TTSLEN);
+ if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) {
+ suffix[0] = L'\0'; /* truncate name */
return TRUE;
- } else {
- return FALSE;
}
+ return FALSE;
}
static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,
@@ -675,18 +682,19 @@
}
if (IS_NT) {
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
- /* If the filename ends with ".ttf" also accept it.
+ /* If the filename ends with ".ttf" or ".otf" also accept it.
* Not expecting to need to do this for .ttc files.
* Also note this code is not mirrored in the "A" (win9x) path.
*/
LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
- if (dot == NULL || (wcsicmp(dot, L".ttf") != 0)) {
+ if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
+ && (wcsicmp(dot, L".otf") != 0))) {
continue; /* not a TT font... */
}
}
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
} else {
- if (!RegistryToBaseTTNameA(cname) ) {
+ if (!RegistryToBaseTTNameA((LPSTR)cname)) {
continue; /* not a TT font... */
}
registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data);
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DBadHardware.h Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DBadHardware.h Fri Jan 09 21:54:17 2009 -0800
@@ -85,6 +85,19 @@
{ 0x1002, 0x71C5, D_VERSION(6,14,10,6706), OS_WINXP },
{ 0x1002, 0x71C5, D_VERSION(7,14,10,0567), OS_VISTA },
+ // ATI Mobility Radeon 9700
+ // Reason: workaround for 6773336
+ { 0x1002, 0x4E50, D_VERSION(6,14,10,6561), OS_WINXP },
+
+ // Nvidia FX 5200
+ // Reason: workaround for 6717988
+ { 0x10DE, 0x0322, D_VERSION(6,14,11,6921), OS_WINXP },
+
+ // Nvidia FX Go5600, Go5700
+ // Reason: workaround for 6714579
+ { 0x10DE, 0x031A, D_VERSION(6,14,11,6921), OS_WINXP },
+ { 0x10DE, 0x0347, D_VERSION(6,14,11,6921), OS_WINXP },
+
// Nvidia Quadro NVS 110M
// Reason: workaround for 6629891
{ 0x10DE, 0x01D7, D_VERSION(6,14,11,5665), OS_WINXP },
@@ -93,6 +106,32 @@
// Reason: workaround for 6653860
{ 0x10DE, 0x00FD, D_VERSION(6,14,10,6573), OS_WINXP },
+ // Nvidia Quadro FX family
+ // Reason: workaround for 6772137
+ { 0x10DE, 0x00F8, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x009D, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x029C, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x029D, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x029E, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x029F, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x01DE, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x039E, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x019D, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x019E, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x040A, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x040E, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x040F, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x061A, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x06F9, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x05FD, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x05FE, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x004E, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x00CD, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x00CE, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x014C, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x014D, D_VERSION(6,14,10,9381), OS_WINXP },
+ { 0x10DE, 0x014E, D_VERSION(6,14,10,9381), OS_WINXP },
+
// Nvidia GeForce 6200 TurboCache(TM)
// Reason: workaround for 6588384
{ 0x10DE, 0x0161, NO_VERSION, OS_VISTA },
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DBlitLoops.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DBlitLoops.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -47,6 +47,7 @@
extern "C" BlitFunc IntArgbPreToIntArgbConvert;
extern "C" BlitFunc IntArgbBmToIntArgbConvert;
extern "C" BlitFunc IntRgbToIntArgbConvert;
+extern "C" BlitFunc ThreeByteBgrToIntArgbConvert;
extern "C" BlitFunc Ushort565RgbToIntArgbConvert;
extern "C" BlitFunc Ushort555RgbToIntArgbConvert;
extern "C" BlitFunc IntBgrToIntArgbConvert;
@@ -220,12 +221,17 @@
" srctype=%d rect={%-4d, %-4d, %-4d, %-4d}",
srctype, r.left, r.top, r.right, r.bottom);
- if (pDesc->Usage == D3DUSAGE_DYNAMIC &&
- dstx == 0 && dstx == 0 &&
- srcWidth == pDesc->Width && srcHeight == pDesc->Height)
- {
+ if (pDesc->Usage == D3DUSAGE_DYNAMIC) {
+ // it is safe to lock with discard because we don't care about the
+ // contents of dynamic textures, and some drivers are happier if
+ // dynamic textures are always locked with DISCARD
dwLockFlags |= D3DLOCK_DISCARD;
pR = NULL;
+ } else {
+ // in non-DYNAMIC case we lock the exact rect so there's no need to
+ // offset the destination pointer
+ dstx = 0;
+ dsty = 0;
}
res = pDstSurface->LockRect(&lockedRect, pR, dwLockFlags);
@@ -242,7 +248,9 @@
void *pSrcBase = PtrCoord(pSrcInfo->rasBase,
srcx, pSrcInfo->pixelStride,
srcy, pSrcInfo->scanStride);
- void *pDstBase = lockedRect.pBits;
+ void *pDstBase = PtrCoord(lockedRect.pBits,
+ dstx, dstInfo.pixelStride,
+ dsty, dstInfo.scanStride);
switch (srctype) {
case ST_INT_ARGB:
@@ -251,11 +259,15 @@
pSrcInfo, &dstInfo, NULL, NULL);
break;
case ST_INT_ARGB_PRE:
- case ST_INT_RGB:
AnyIntIsomorphicCopy(pSrcBase, pDstBase,
srcWidth, srcHeight,
pSrcInfo, &dstInfo, NULL, NULL);
break;
+ case ST_INT_RGB:
+ IntRgbToIntArgbConvert(pSrcBase, pDstBase,
+ srcWidth, srcHeight,
+ pSrcInfo, &dstInfo, NULL, NULL);
+ break;
case ST_INT_ARGB_BM:
// REMIND: we don't have such sw loop
// so this path is disabled for now on java level
@@ -268,6 +280,11 @@
srcWidth, srcHeight,
pSrcInfo, &dstInfo, NULL, NULL);
break;
+ case ST_3BYTE_BGR:
+ ThreeByteBgrToIntArgbConvert(pSrcBase, pDstBase,
+ srcWidth, srcHeight,
+ pSrcInfo, &dstInfo, NULL, NULL);
+ break;
case ST_USHORT_555_RGB:
Ushort555RgbToIntArgbConvert(pSrcBase, pDstBase,
srcWidth, srcHeight,
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DContext.cpp Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DContext.cpp Fri Jan 09 21:54:17 2009 -0800
@@ -1174,11 +1174,10 @@
" rect={%-4d, %-4d, %-4d, %-4d}",
r.left, r.top, r.right, r.bottom);
- // REMIND: we should also check for dstx, dsty being 0 here,
- // but they're always 0 in dynamic texture case
- if (pDesc->Usage == D3DUSAGE_DYNAMIC &&
- srcWidth == pDesc->Width && srcHeight == pDesc->Height)
- {
+ if (pDesc->Usage == D3DUSAGE_DYNAMIC) {
+ // it is safe to lock with discard because we don't care about the
+ // contents of dynamic textures and dstx,dsty for this case is
+ // always 0,0 because we are uploading into a tile texture
dwLockFlags |= D3DLOCK_DISCARD;
pR = NULL;
}
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.h Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.h Fri Jan 09 21:54:17 2009 -0800
@@ -68,6 +68,7 @@
#define ST_USHORT_555_RGB sun_java2d_d3d_D3DSurfaceData_ST_USHORT_555_RGB
#define ST_BYTE_INDEXED sun_java2d_d3d_D3DSurfaceData_ST_BYTE_INDEXED
#define ST_BYTE_INDEXED_BM sun_java2d_d3d_D3DSurfaceData_ST_BYTE_INDEXED_BM
+#define ST_3BYTE_BGR sun_java2d_d3d_D3DSurfaceData_ST_3BYTE_BGR
/**
* These are defined to be the same as ExtendedBufferCapabilities.VSyncType
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/UninitializedDisplayModeChangeTest/DisplayModeChanger.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.awt.DisplayMode;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Used by the UninitializedDisplayModeChangeTest to change the
+ * display mode.
+ */
+public class DisplayModeChanger {
+
+ public static void main(String[] args)
+ throws InterruptedException, InvocationTargetException
+ {
+ final GraphicsDevice gd =
+ GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getDefaultScreenDevice();
+
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ Frame f = null;
+ if (gd.isFullScreenSupported()) {
+ try {
+ f = new Frame("DisplayChanger Frame");
+ gd.setFullScreenWindow(f);
+ if (gd.isDisplayChangeSupported()) {
+ DisplayMode dm = findDisplayMode(gd);
+ if (gd != null) {
+ gd.setDisplayMode(dm);
+ }
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ gd.setFullScreenWindow(null);
+ } finally {
+ if (f != null) {
+ f.dispose();
+ }
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Finds a display mode that is different from the current display
+ * mode and is likely to cause a display change event.
+ */
+ private static DisplayMode findDisplayMode(GraphicsDevice gd) {
+ DisplayMode dms[] = gd.getDisplayModes();
+ DisplayMode currentDM = gd.getDisplayMode();
+ for (DisplayMode dm : dms) {
+ if (!dm.equals(currentDM) &&
+ dm.getRefreshRate() == currentDM.getRefreshRate())
+ {
+ // different from the current dm and refresh rate is the same
+ // means that something else is different => more likely to
+ // cause a DM change event
+ return dm;
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/TextLayout/DecorationBoundsTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary verify bounds enclose rendering of decorations.
+ * @bug 6751621
+ */
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import java.util.*;
+
+public class DecorationBoundsTest {
+
+ public static void main(String[] args) {
+ BufferedImage bi =
+ new BufferedImage(600, 300, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = bi.createGraphics();
+ g2d.setColor(Color.white);
+ g2d.fillRect(0, 0, 600, 300);
+
+ float x = 10;
+ float y = 90;
+ Map map = new HashMap();
+ map.put(TextAttribute.STRIKETHROUGH,
+ TextAttribute.STRIKETHROUGH_ON);
+ map.put(TextAttribute.SIZE, new Float(80));
+
+ FontRenderContext frc = g2d.getFontRenderContext();
+
+ String text = "Welcome to ";
+ TextLayout tl = new TextLayout(text, map, frc);
+ g2d.translate(x, y);
+ g2d.setColor(Color.RED);
+ tl.draw(g2d, 0, 0);
+ g2d.setColor(Color.GREEN);
+ Rectangle2D bds = tl.getBounds();
+ /* Since due to pixelisation the glyphs may touch above
+ * or below the theoretical outline bounds, pad in the
+ * y direction to avoid spurious failures.
+ */
+ bds.setRect(bds.getX(), bds.getY()-1,
+ bds.getWidth(), bds.getHeight()+2);
+ g2d.fill(bds);
+
+ map = new HashMap();
+ map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
+ map.put(TextAttribute.SIZE, new Float(80));
+ tl = new TextLayout(text, map, frc);
+ g2d.translate(0, 100);
+ g2d.setColor(Color.RED);
+ tl.draw(g2d, 0, 0);
+
+ g2d.setColor(Color.GREEN);
+ bds = tl.getBounds();
+ bds.setRect(bds.getX(), bds.getY()-1,
+ bds.getWidth(), bds.getHeight()+2);
+ g2d.fill(bds);
+
+ checkBI(bi, Color.RED);
+ }
+
+ static void checkBI(BufferedImage bi, Color badColor) {
+ int badrgb = badColor.getRGB();
+ int w = bi.getWidth(null);
+ int h = bi.getHeight(null);
+ for (int x=0; x<w; x++) {
+ for (int y=0; y<h; y++) {
+ int col = bi.getRGB(x, y);
+ if (col == badrgb) {
+ throw new RuntimeException("Got " + col);
+ }
+ }
+ }
+ }
+}
--- a/jdk/test/java/awt/font/TextLayout/TextLayoutBounds.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/test/java/awt/font/TextLayout/TextLayoutBounds.java Fri Jan 09 21:54:17 2009 -0800
@@ -22,7 +22,7 @@
*/
/* @test
* @summary verify TextLayout.getBounds() return visual bounds
- * @bug 6323611
+ * @bug 6323611 6761856
*/
import java.awt.*;
@@ -39,10 +39,15 @@
Rectangle2D tlBounds = tl.getBounds();
GlyphVector gv = f.createGlyphVector(frc, s);
Rectangle2D gvvBounds = gv.getVisualBounds();
+ Rectangle2D oBounds = tl.getOutline(null).getBounds2D();
System.out.println("tlbounds="+tlBounds);
System.out.println("gvbounds="+gvvBounds);
+ System.out.println("outlineBounds="+oBounds);
if (!gvvBounds.equals(tlBounds)) {
- throw new RuntimeException("Bounds differ");
+ throw new RuntimeException("Bounds differ [gvv != tl]");
+ }
+ if (!tlBounds.equals(oBounds)) {
+ throw new RuntimeException("Bounds differ [tl != outline]");
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/TextLayout/UnderlinePositionTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary verify outline and stroking of underline match.
+ * @bug 6751616
+ */
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import java.util.*;
+
+public class UnderlinePositionTest {
+
+ public static void main(String[] args) {
+ BufferedImage bi =
+ new BufferedImage(600, 150, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = bi.createGraphics();
+ g2d.setColor(Color.white);
+ g2d.fillRect(0, 0, 600, 150);
+
+ float x = 10;
+ float y = 90;
+ Map map = new HashMap();
+ map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
+ map.put(TextAttribute.SIZE, new Float(80));
+
+ FontRenderContext frc = g2d.getFontRenderContext();
+
+ // Use all spaces for the text so we know we are dealing
+ // only with pixels from the underline.
+ String text = " ";
+ TextLayout tl = new TextLayout(text, map, frc);
+ Shape outline = tl.getOutline(null);
+ Rectangle2D bounds = outline.getBounds();
+
+ g2d.translate(x, y);
+ g2d.setColor(Color.RED);
+ tl.draw(g2d, 0, 0);
+
+ /* By getting the outline, then its bounds, then filling
+ * according to the same pixelisation rules, this ought to
+ * match the position of the original underline. If any
+ * red pixels are left, then the test will fail.
+ */
+ g2d.setColor(Color.BLUE);
+ g2d.fill(bounds);
+ g2d.dispose();
+
+ checkBI(bi, Color.RED);
+ }
+
+ static void checkBI(BufferedImage bi, Color badColor) {
+ int badrgb = badColor.getRGB();
+ int w = bi.getWidth(null);
+ int h = bi.getHeight(null);
+ for (int x=0; x<w; x++) {
+ for (int y=0; y<h; y++) {
+ int col = bi.getRGB(x, y);
+ if (col == badrgb) {
+ throw new RuntimeException("Got " + col);
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/GetMediasTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6653384
+ * @summary No exception should be thrown.
+ * @run main GetMediasTest
+ */
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.attribute.standard.Media;
+
+public class GetMediasTest {
+ public static void main(String[] args) {
+ PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
+ for(final PrintService service: services) {
+ Thread thread = new Thread() {
+ public void run() {
+ service.getSupportedAttributeValues(Media.class, null, null);
+ }
+ };
+ thread.start();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/png/ITXtTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6541476
+ * @summary Test verifies that ImageIO PNG plugin correcly handles the
+ * iTxt chunk (International textual data).
+ *
+ * @run main ITXtTest
+ */
+
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.stream.ImageOutputStream;
+import javax.imageio.stream.ImageInputStream;
+
+import org.w3c.dom.Node;
+
+public class ITXtTest {
+ static public void main(String args[]) {
+ ITXtTest t_en = new ITXtTest();
+ t_en.description = "xml - en";
+ t_en.keyword = "XML:com.adobe.xmp";
+ t_en.isCompressed = false;
+ t_en.compression = 0;
+ t_en.language = "en";
+ t_en.trasKeyword = "XML:com.adobe.xmp";
+ t_en.text = "<xml>Something</xml>";
+
+ doTest(t_en);
+
+ // check compression case
+ t_en.isCompressed = true;
+ t_en.description = "xml - en - compressed";
+
+ doTest(t_en);
+
+ ITXtTest t_ru = new ITXtTest();
+ t_ru.description = "xml - ru";
+ t_ru.keyword = "XML:com.adobe.xmp";
+ t_ru.isCompressed = false;
+ t_ru.compression = 0;
+ t_ru.language = "ru";
+ t_ru.trasKeyword = "\u0410\u0410\u0410\u0410\u0410 XML";
+ t_ru.text = "<xml>\u042A\u042F\u042F\u042F\u042F\u042F\u042F</xml>";
+
+ doTest(t_ru);
+
+ t_ru.isCompressed = true;
+ t_ru.description = "xml - ru - compressed";
+
+ doTest(t_ru);
+ }
+
+
+ String description;
+
+ String keyword;
+ boolean isCompressed;
+ int compression;
+ String language;
+ String trasKeyword;
+ String text;
+
+
+ public IIOMetadataNode getNode() {
+ IIOMetadataNode iTXt = new IIOMetadataNode("iTXt");
+ IIOMetadataNode iTXtEntry = new IIOMetadataNode("iTXtEntry");
+ iTXtEntry.setAttribute("keyword", keyword);
+ iTXtEntry.setAttribute("compressionFlag",
+ isCompressed ? "true" : "false");
+ iTXtEntry.setAttribute("compressionMethod",
+ Integer.toString(compression));
+ iTXtEntry.setAttribute("languageTag", language);
+ iTXtEntry.setAttribute("translatedKeyword",
+ trasKeyword);
+ iTXtEntry.setAttribute("text", text);
+ iTXt.appendChild(iTXtEntry);
+ return iTXt;
+ }
+
+ public static ITXtTest getFromNode(IIOMetadataNode n) {
+ ITXtTest t = new ITXtTest();
+
+ if (!"iTXt".equals(n.getNodeName())) {
+ throw new RuntimeException("Invalid node");
+ }
+ IIOMetadataNode e = (IIOMetadataNode)n.getFirstChild();
+ if (!"iTXtEntry".equals(e.getNodeName())) {
+ throw new RuntimeException("Invalid entry node");
+ }
+ t.keyword = e.getAttribute("keyword");
+ t.isCompressed =
+ (Integer.valueOf(e.getAttribute("compressionFlag")).intValue() == 1);
+ t.compression =
+ Integer.valueOf(e.getAttribute("compressionMethod")).intValue();
+ t.language = e.getAttribute("languageTag");
+ t.trasKeyword = e.getAttribute("translatedKeyword");
+ t.text = e.getAttribute("text");
+
+ return t;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (! (o instanceof ITXtTest)) {
+ return false;
+ }
+ ITXtTest t = (ITXtTest)o;
+ if (!keyword.equals(t.keyword)) { return false; }
+ if (isCompressed != t.isCompressed) { return false; }
+ if (compression != t.compression) { return false; }
+ if (!language.equals(t.language)) { return false; }
+ if (!trasKeyword.equals(t.trasKeyword)) { return false; }
+ if (!text.equals(t.text)) { return false; }
+
+ return true;
+ }
+
+
+
+ private static void doTest(ITXtTest src) {
+
+ System.out.println("Test: " + src.description);
+
+ File file = new File("test.png");
+
+ writeTo(file, src);
+ ITXtTest dst = readFrom(file);
+
+ if (dst == null || !dst.equals(src)) {
+ throw new RuntimeException("Test failed.");
+ }
+
+ System.out.println("Test passed.");
+ }
+
+ private static void writeTo(File f, ITXtTest t) {
+ BufferedImage src = createBufferedImage();
+ try {
+ ImageOutputStream imageOutputStream =
+ ImageIO.createImageOutputStream(f);
+
+ ImageTypeSpecifier imageTypeSpecifier =
+ new ImageTypeSpecifier(src);
+ ImageWriter imageWriter =
+ ImageIO.getImageWritersByFormatName("PNG").next();
+
+ imageWriter.setOutput(imageOutputStream);
+
+ IIOMetadata m =
+ imageWriter.getDefaultImageMetadata(imageTypeSpecifier, null);
+
+ String format = m.getNativeMetadataFormatName();
+ Node root = m.getAsTree(format);
+
+ IIOMetadataNode iTXt = t.getNode();
+ root.appendChild(iTXt);
+ m.setFromTree(format, root);
+
+ imageWriter.write(new IIOImage(src, null, m));
+ imageOutputStream.close();
+ System.out.println("Writing done.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Writing test failed.", e);
+ }
+ }
+
+ private static ITXtTest readFrom(File f) {
+ try {
+ ImageInputStream iis = ImageIO.createImageInputStream(f);
+ ImageReader r = ImageIO.getImageReaders(iis).next();
+ r.setInput(iis);
+
+ IIOImage dst = r.readAll(0, null);
+
+ // look for iTXt node
+ IIOMetadata m = dst.getMetadata();
+ Node root = m.getAsTree(m.getNativeMetadataFormatName());
+ Node n = root.getFirstChild();
+ while (n != null && !"iTXt".equals(n.getNodeName())) {
+ n = n.getNextSibling();
+ }
+ if (n == null) {
+ throw new RuntimeException("No iTXt node!");
+ }
+ ITXtTest t = ITXtTest.getFromNode((IIOMetadataNode)n);
+ return t;
+ } catch (Throwable e) {
+ throw new RuntimeException("Reading test failed.", e);
+ }
+ }
+
+ private static BufferedImage createBufferedImage() {
+ BufferedImage image = new BufferedImage(128, 128,
+ BufferedImage.TYPE_4BYTE_ABGR_PRE);
+ Graphics2D graph = image.createGraphics();
+ graph.setPaintMode();
+ graph.setColor(Color.orange);
+ graph.fillRect(32, 32, 64, 64);
+ graph.dispose();
+ return image;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/CheckDupFlavor.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4996318 6731937
+ * @summary There should be no duplicates returned by getSupportedDocFlavors.
+ * @run main CheckDupFlavor
+ */
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+import java.util.ArrayList;
+
+
+public class CheckDupFlavor {
+ public static void main(String[] args){
+ PrintService pservice =
+ PrintServiceLookup.lookupDefaultPrintService();
+
+ if (pservice == null) {
+ System.out.println("No default PrintService found. Test ABORTED.");
+ return;
+ }
+
+ System.out.println("Default service = "+pservice);
+
+ DocFlavor[] flavors = pservice.getSupportedDocFlavors();
+ if (flavors==null) {
+ System.out.println("No flavors supported. Test PASSED.");
+ return;
+ }
+
+
+ ArrayList flavorList = new ArrayList();
+ for (int i=0; i<flavors.length; i++) {
+ if (flavors[i] == null) {
+ throw new RuntimeException("Null flavor. Test FAILED.");
+ } else if (flavorList.contains(flavors[i])) {
+ throw new RuntimeException("\n\tDuplicate flavor found : "+flavors[i]+" : Test FAILED.");
+ } else {
+ flavorList.add(flavors[i]);
+ }
+ }
+ System.out.println("No duplicate found. Test PASSED.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/TestRaceCond.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6731826
+ * @summary There should be no RuntimeException.
+ * @run main TestRaceCond
+ */
+
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+
+
+public class TestRaceCond {
+
+ public static void main(String argv[]) {
+ trial();
+ }
+
+ static void trial() {
+ PrintService pserv1 = PrintServiceLookup.lookupDefaultPrintService();
+ PrintService[] pservs = PrintServiceLookup.lookupPrintServices(null, null);
+ PrintService pserv2 = PrintServiceLookup.lookupDefaultPrintService();
+
+ if (pserv1.hashCode() != pserv2.hashCode()) {
+ throw new RuntimeException("Different hashCodes for equal print "
+ + "services: " + pserv1.hashCode() + " "
+ + pserv2.hashCode());
+ }
+ }
+}
+
--- a/jdk/test/javax/print/attribute/PSCopiesFlavorTest.java Mon Dec 22 19:28:49 2008 +0000
+++ b/jdk/test/javax/print/attribute/PSCopiesFlavorTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6527316
+ * @bug 6527316 6732647
* @summary Copies isn't supported for PS flavors.
* @run main PSCopiesFlavorTest
*/
@@ -50,5 +50,13 @@
if (suppVal || us == null) {
throw new RuntimeException("Copies should be unsupported value");
}
+
+ Object value = ps.getSupportedAttributeValues(Copies.class, flavor, null);
+
+ //Copies Supported
+ if(value instanceof CopiesSupported) {
+ throw new RuntimeException("Copies should have no supported values.");
+ }
+
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/DirectX/NonOpaqueDestLCDAATest/NonOpaqueDestLCDAATest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6728834 6749060
+ * @summary Tests that LCD AA text rendering works properly with destinations
+ * being VolatileImage of all transparency types
+ * @author Dmitri.Trembovetski: area=Graphics
+ * @run main/manual/othervm -Dsun.java2d.d3d=false NonOpaqueDestLCDAATest
+ * @run main/manual/othervm NonOpaqueDestLCDAATest
+ * @run main/manual/othervm -Dsun.java2d.opengl=True NonOpaqueDestLCDAATest
+ */
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import java.io.File;
+import java.util.concurrent.CountDownLatch;
+import javax.imageio.ImageIO;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import static java.awt.Transparency.*;
+
+public class NonOpaqueDestLCDAATest extends JFrame implements ActionListener {
+ private static volatile boolean passed = true;
+ private static CountDownLatch complete = new CountDownLatch(1);
+
+ public NonOpaqueDestLCDAATest() {
+ JTextArea desc = new JTextArea();
+ desc.setText(
+ "\n Instructions: the three text strings below should appear" +
+ " readable, without smudges or misshapen bold glyphs.\n" +
+ " You may need a magnifier to notice some bad colorfringing in "+
+ " in SW Translucent case, especially in vertical stems.\n\n"+
+ " Basically text rendered to TRANSLUCENT destination should look"+
+ " similar to one rendered to OPAQUE - it may differ in whether or" +
+ " not it's LCD, but it should look 'correct'\n\n"+
+ "If the text looks fine the test PASSED otherwise it FAILED.\n");
+ desc.setEditable(false);
+ desc.setBackground(Color.black);
+ desc.setForeground(Color.green);
+ add("North", desc);
+ JPanel renderPanel = new JPanel() {
+ @Override
+ public void paintComponent(Graphics g) {
+ render(g, getWidth(), getHeight());
+ }
+ };
+ renderPanel.setPreferredSize(new Dimension(1024, 650));
+ renderPanel.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ images = null;
+ }
+ });
+ add("Center", renderPanel);
+
+ JButton passedBtn = new JButton("Passed");
+ JButton failedBtn = new JButton("Failed");
+ passedBtn.addActionListener(this);
+ failedBtn.addActionListener(this);
+ JPanel p = new JPanel();
+ p.add(passedBtn);
+ p.add(failedBtn);
+ add("South", p);
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ complete.countDown();
+ }
+ });
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ }
+
+ public void render(Graphics g, int w, int h) {
+ initImages(w, h);
+
+ g.setColor(new Color(0xAD, 0xD8, 0xE6));
+ g.fillRect(0, 0, w, h);
+
+ Graphics2D g2d = (Graphics2D) g.create();
+ for (Image im : images) {
+ g2d.drawImage(im, 0, 0, null);
+ g2d.translate(0, im.getHeight(null));
+ }
+ }
+
+ String tr[] = { "OPAQUE", "BITMASK", "TRANSLUCENT" };
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("Passed")) {
+ passed = true;
+ System.out.println("Test Passed");
+ } else if (e.getActionCommand().equals("Failed")) {
+ System.out.println("Test Failed");
+ for (int i = 0; i < images.length; i++) {
+ String f = "NonOpaqueDestLCDAATest_"+tr[i];
+ try {
+ if (images[i] instanceof VolatileImage) {
+ f += "_vi.png";
+ ImageIO.write(((VolatileImage)images[i]).
+ getSnapshot(), "png", new File(f));
+ } else {
+ f += "_bi.png";
+ ImageIO.write((BufferedImage)images[i],
+ "png", new File(f));
+ }
+ System.out.printf("Dumped %s image to %s\n", tr[i], f);
+ } catch (Throwable t) {}
+ }
+ passed = false;
+ }
+ dispose();
+ complete.countDown();
+ }
+
+ static void clear(Graphics2D g, int type, int w, int h) {
+ Graphics2D gg = (Graphics2D) g.create();
+ if (type > OPAQUE) {
+ gg.setColor(new Color(0, 0, 0, 0));
+ gg.setComposite(AlphaComposite.Src);
+ } else {
+ gg.setColor(new Color(0xAD, 0xD8, 0xE6));
+ }
+ gg.fillRect(0, 0, w, h);
+ }
+
+ private void render(Image im, int type, String s) {
+ Graphics2D g2d = (Graphics2D) im.getGraphics();
+ clear(g2d, type, im.getWidth(null), im.getHeight(null));
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
+ Font f = new Font("Dialog", Font.BOLD, 40);// g2d.getFont().deriveFont(32.0f);
+ g2d.setColor(Color.white);
+ g2d.setFont(g2d.getFont().deriveFont(36.0f));
+ g2d.drawString(s, 10, im.getHeight(null) / 2);
+ }
+
+ Image images[];
+ private void initImages(int w, int h) {
+ if (images == null) {
+ images = new Image[6];
+ GraphicsConfiguration gc = getGraphicsConfiguration();
+ for (int i = OPAQUE; i <= TRANSLUCENT; i++) {
+ VolatileImage vi =
+ gc.createCompatibleVolatileImage(w,h/images.length,i);
+ images[i-1] = vi;
+ vi.validate(gc);
+ String s = "LCD AA Text rendered to " + tr[i - 1] + " HW destination";
+ render(vi, i, s);
+
+ s = "LCD AA Text rendered to " + tr[i - 1] + " SW destination";
+ images[i-1+3] = gc.createCompatibleImage(w, h/images.length, i);
+ render(images[i-1+3], i, s);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ NonOpaqueDestLCDAATest t = new NonOpaqueDestLCDAATest();
+ t.pack();
+ t.setVisible(true);
+ }
+ });
+
+ complete.await();
+ if (!passed) {
+ throw new RuntimeException("Test Failed!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/DirectX/OpaqueImageToSurfaceBlitTest/OpaqueImageToSurfaceBlitTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6764257
+ * @summary Tests that the alpha in opaque images doesn't affect result of alpha
+ * compositing
+ * @author Dmitri.Trembovetski@sun.com: area=Graphics
+ * @run main/othervm OpaqueImageToSurfaceBlitTest
+ * @run main/othervm -Dsun.java2d.noddraw=true OpaqueImageToSurfaceBlitTest
+ * @run main/othervm -Dsun.java2d.opengl=True OpaqueImageToSurfaceBlitTest
+ */
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.VolatileImage;
+
+public class OpaqueImageToSurfaceBlitTest {
+
+ public static void main(String[] args) {
+
+ GraphicsEnvironment ge =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gd.getDefaultConfiguration();
+ VolatileImage vi = gc.createCompatibleVolatileImage(16, 16);
+ vi.validate(gc);
+
+ BufferedImage bi =
+ new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);
+ int data[] = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
+ data[0] = 0x0000007f;
+ data[1] = 0x0000007f;
+ data[2] = 0xff00007f;
+ data[3] = 0xff00007f;
+ Graphics2D g = vi.createGraphics();
+ g.setComposite(AlphaComposite.SrcOver.derive(0.999f));
+ g.drawImage(bi, 0, 0, null);
+
+ bi = vi.getSnapshot();
+ if (bi.getRGB(0, 0) != bi.getRGB(1, 1)) {
+ throw new RuntimeException("Test FAILED: color at 0x0 ="+
+ Integer.toHexString(bi.getRGB(0, 0))+" differs from 1x1 ="+
+ Integer.toHexString(bi.getRGB(1,1)));
+ }
+
+ System.out.println("Test PASSED.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/pipe/hw/RSLContextInvalidationTest/RSLContextInvalidationTest.java Fri Jan 09 21:54:17 2009 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6764257
+ * @summary Tests that the color is reset properly after save/restore context
+ * @author Dmitri.Trembovetski@sun.com: area=Graphics
+ * @compile -XDignore.symbol.file=true RSLContextInvalidationTest.java
+ * @run main/othervm RSLContextInvalidationTest
+ * @run main/othervm -Dsun.java2d.noddraw=true RSLContextInvalidationTest
+ * @run main/othervm -Dsun.java2d.opengl=True RSLContextInvalidationTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import sun.java2d.DestSurfaceProvider;
+import sun.java2d.Surface;
+import sun.java2d.pipe.RenderQueue;
+import sun.java2d.pipe.hw.*;
+
+public class RSLContextInvalidationTest {
+
+ public static void main(String[] args) {
+ GraphicsEnvironment ge =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gd.getDefaultConfiguration();
+ VolatileImage vi = gc.createCompatibleVolatileImage(100, 100);
+ vi.validate(gc);
+ VolatileImage vi1 = gc.createCompatibleVolatileImage(100, 100);
+ vi1.validate(gc);
+
+ if (!(vi instanceof DestSurfaceProvider)) {
+ System.out.println("Test considered PASSED: no HW acceleration");
+ return;
+ }
+
+ DestSurfaceProvider p = (DestSurfaceProvider)vi;
+ Surface s = p.getDestSurface();
+ if (!(s instanceof AccelSurface)) {
+ System.out.println("Test considered PASSED: no HW acceleration");
+ return;
+ }
+ AccelSurface dst = (AccelSurface)s;
+
+ Graphics g = vi.createGraphics();
+ g.drawImage(vi1, 95, 95, null);
+ g.setColor(Color.red);
+ g.fillRect(0, 0, 100, 100);
+ g.setColor(Color.black);
+ g.fillRect(0, 0, 100, 100);
+ // after this the validated context color is black
+
+ RenderQueue rq = dst.getContext().getRenderQueue();
+ rq.lock();
+ try {
+ dst.getContext().saveState();
+ dst.getContext().restoreState();
+ } finally {
+ rq.unlock();
+ }
+
+ // this will cause ResetPaint (it will set color to extended EA=ff,
+ // which is ffffffff==Color.white)
+ g.drawImage(vi1, 95, 95, null);
+
+ // now try filling with black again, but it will come up as white
+ // because this fill rect won't validate the color properly
+ g.setColor(Color.black);
+ g.fillRect(0, 0, 100, 100);
+
+ BufferedImage bi = vi.getSnapshot();
+ if (bi.getRGB(50, 50) != Color.black.getRGB()) {
+ throw new RuntimeException("Test FAILED: found color="+
+ Integer.toHexString(bi.getRGB(50, 50))+" instead of "+
+ Integer.toHexString(Color.black.getRGB()));
+ }
+
+ System.out.println("Test PASSED.");
+ }
+}
--- a/langtools/.hgtags Mon Dec 22 19:28:49 2008 +0000
+++ b/langtools/.hgtags Fri Jan 09 21:54:17 2009 -0800
@@ -16,3 +16,4 @@
3fb51e47622bb771571680bc6a7b64c6172b482d jdk7-b39
32e30988324601d08b87989f0821d99aa8534511 jdk7-b40
ded6b40f558e8d19b3c17715b3d67ee001606645 jdk7-b41
+5e5567c2db56a931cf07768218c20903d9828b5f jdk7-b42
--- a/langtools/test/com/sun/javadoc/testSourceTab/DoubleTab/C.java Mon Dec 22 19:28:49 2008 +0000
+++ b/langtools/test/com/sun/javadoc/testSourceTab/DoubleTab/C.java Fri Jan 09 21:54:17 2009 -0800
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -23,15 +23,15 @@
/**
* <pre>
- * This source
- * is indented
- * with tabs.
+ * \t\tThis source
+ * \t\tis indented
+ * \t\twith tabs.
* </pre>
*/
public class C {
-
- //This source
- //is indented
- //with tabs.
-
+
+\t\t//This source
+\t\t//is indented
+\t\t//with tabs.
+
}
--- a/langtools/test/com/sun/javadoc/testSourceTab/SingleTab/C.java Mon Dec 22 19:28:49 2008 +0000
+++ b/langtools/test/com/sun/javadoc/testSourceTab/SingleTab/C.java Fri Jan 09 21:54:17 2009 -0800
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -23,15 +23,15 @@
/**
* <pre>
- * This source
- * is indented
- * with tabs.
+ *\tThis source
+ * \tis indented
+ * \twith tabs.
* </pre>
*/
public class C {
-
- //This source
- //is indented
- //with tabs.
-
+
+\t//This source
+\t//is indented
+\t//with tabs.
+
}
--- a/langtools/test/com/sun/javadoc/testSourceTab/TestSourceTab.java Mon Dec 22 19:28:49 2008 +0000
+++ b/langtools/test/com/sun/javadoc/testSourceTab/TestSourceTab.java Fri Jan 09 21:54:17 2009 -0800
@@ -1,5 +1,5 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
+/*
+ * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,59 +33,102 @@
* @run main TestSourceTab
*/
+import java.io.*;
+
public class TestSourceTab extends JavadocTester {
-
+
private static final String BUG_ID = "4510979";
+ private static final String TMP_SRC_DIR = "tmpSrc";
private static final String OUTPUT_DIR1 = BUG_ID + "-tabLengthEight";
private static final String OUTPUT_DIR2 = BUG_ID + "-tabLengthFour";
private static final String[][] TEST = NO_TEST;
private static final String[][] NEGATED_TEST = NO_TEST;
-
+
//Run Javadoc on a source file with that is indented with a single tab per line
private static final String[] ARGS1 =
new String[] {
- "-d", OUTPUT_DIR1, "-sourcepath", SRC_DIR,
- "-notimestamp", "-linksource", SRC_DIR + FS + "SingleTab" + FS + "C.java"
+ "-d", OUTPUT_DIR1, "-sourcepath", TMP_SRC_DIR,
+ "-notimestamp", "-linksource", TMP_SRC_DIR + FS + "SingleTab" + FS + "C.java"
};
-
+
//Run Javadoc on a source file with that is indented with a two tab per line
//If we double the tabs and decrease the tab length by a half, the output should
//be the same as the one generated above.
private static final String[] ARGS2 =
new String[] {
- "-d", OUTPUT_DIR2, "-sourcepath", SRC_DIR,
- "-notimestamp", "-sourcetab", "4", SRC_DIR + FS + "DoubleTab" + FS + "C.java"
+ "-d", OUTPUT_DIR2, "-sourcepath", TMP_SRC_DIR,
+ "-notimestamp", "-sourcetab", "4", TMP_SRC_DIR + FS + "DoubleTab" + FS + "C.java"
};
-
+
//Files to diff
private static final String[][] FILES_TO_DIFF = {
{OUTPUT_DIR1 + FS + "src-html" + FS + "C.html",
OUTPUT_DIR2 + FS + "src-html" + FS + "C.html"
- },
+ },
{OUTPUT_DIR1 + FS + "C.html",
OUTPUT_DIR2 + FS + "C.html"
}
-
+
};
-
+
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
- public static void main(String[] args) {
+ public static void main(String[] args) throws IOException {
TestSourceTab tester = new TestSourceTab();
run(tester, ARGS1, TEST, NEGATED_TEST);
run(tester, ARGS2, TEST, NEGATED_TEST);
tester.runDiffs(FILES_TO_DIFF);
}
-
+
+ TestSourceTab() throws IOException {
+ initTabs(new File(SRC_DIR), new File(TMP_SRC_DIR));
+ }
+
+ void initTabs(File from, File to) throws IOException {
+ for (File f: from.listFiles()) {
+ File t = new File(to, f.getName());
+ if (f.isDirectory()) {
+ initTabs(f, t);
+ } else if (f.getName().endsWith(".java")) {
+ write(t, read(f).replace("\\t", "\t"));
+ }
+ }
+ }
+
+ String read(File f) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ BufferedReader in = new BufferedReader(new FileReader(f));
+ try {
+ String line;
+ while ((line = in.readLine()) != null) {
+ sb.append(line);
+ sb.append("\n");
+ }
+ } finally {
+ in.close();
+ }
+ return sb.toString();
+ }
+
+ void write(File f, String s) throws IOException {
+ f.getParentFile().mkdirs();
+ Writer out = new FileWriter(f);
+ try {
+ out.write(s);
+ } finally {
+ out.close();
+ }
+ }
+
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
-
+
/**
* {@inheritDoc}
*/