Mon, 27 Jul 2009 06:15:29 -0700
Merge
src/share/vm/opto/library_call.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Mon Jul 20 08:20:00 2009 -0700 1.2 +++ b/.hgtags Mon Jul 27 06:15:29 2009 -0700 1.3 @@ -37,3 +37,5 @@ 1.4 a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60 1.5 27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61 1.6 a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62 1.7 +32c83fb84370a35344676991a48440378e6b6c8a jdk7-b63 1.8 +ba36394eb84b949b31212bdb32a518a8f92bab5b jdk7-b64
2.1 --- a/agent/make/saenv.sh Mon Jul 20 08:20:00 2009 -0700 2.2 +++ b/agent/make/saenv.sh Mon Jul 27 06:15:29 2009 -0700 2.3 @@ -48,6 +48,8 @@ 2.4 CPU=i386 2.5 fi 2.6 else 2.7 + LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so 2.8 + export LD_AUDIT_32 2.9 SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/solaris/`uname -p` 2.10 OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger" 2.11 CPU=sparc
3.1 --- a/agent/make/saenv64.sh Mon Jul 20 08:20:00 2009 -0700 3.2 +++ b/agent/make/saenv64.sh Mon Jul 27 06:15:29 2009 -0700 3.3 @@ -43,6 +43,8 @@ 3.4 fi 3.5 fi 3.6 3.7 +LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so 3.8 +export LD_AUDIT_64 3.9 SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/$CPU:$STARTDIR/solaris/$CPU 3.10 3.11 OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
4.1 --- a/agent/src/os/solaris/proc/Makefile Mon Jul 20 08:20:00 2009 -0700 4.2 +++ b/agent/src/os/solaris/proc/Makefile Mon Jul 27 06:15:29 2009 -0700 4.3 @@ -56,24 +56,28 @@ 4.4 @javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal 4.5 CC -G -KPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \ 4.6 -M mapfile -o $@/libsaproc.so -ldemangle 4.7 + CC -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 4.8 4.9 amd64:: javahomecheck 4.10 $(MKDIRS) $@ 4.11 @javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal 4.12 CC -G -KPIC -xarch=amd64 -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \ 4.13 -M mapfile -o $@/libsaproc.so -ldemangle 4.14 + CC -xarch=amd64 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 4.15 4.16 sparc:: javahomecheck 4.17 $(MKDIRS) $@ 4.18 @javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal 4.19 CC -G -KPIC -xarch=v8 -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \ 4.20 -M mapfile -o $@/libsaproc.so -ldemangle 4.21 + CC -xarch=v8 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 4.22 4.23 sparcv9:: javahomecheck 4.24 $(MKDIRS) $@ 4.25 @javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal 4.26 CC -G -KPIC -xarch=v9 -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \ 4.27 -M mapfile -o $@/libsaproc.so -ldemangle 4.28 + CC -xarch=v9 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 4.29 4.30 clean:: 4.31 $(RM) -rf sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal.h
5.1 --- a/agent/src/os/solaris/proc/mapfile Mon Jul 20 08:20:00 2009 -0700 5.2 +++ b/agent/src/os/solaris/proc/mapfile Mon Jul 27 06:15:29 2009 -0700 5.3 @@ -45,6 +45,8 @@ 5.4 Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_resume0; 5.5 Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_suspend0; 5.6 Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_writeBytesToProcess0; 5.7 + # this is needed by saproc_audit.c to redirect opens in libproc.so 5.8 + libsaproc_open; 5.9 local: 5.10 *; 5.11 };
6.1 --- a/agent/src/os/solaris/proc/saproc.cpp Mon Jul 20 08:20:00 2009 -0700 6.2 +++ b/agent/src/os/solaris/proc/saproc.cpp Mon Jul 27 06:15:29 2009 -0700 6.3 @@ -214,49 +214,58 @@ 6.4 } 6.5 } 6.6 6.7 -static int find_file_hook(const char * name, int elf_checksum) { 6.8 - init_alt_root(); 6.9 +// This function is a complete substitute for the open system call 6.10 +// since it's also used to override open calls from libproc to 6.11 +// implement as a pathmap style facility for the SA. If libproc 6.12 +// starts using other interfaces then this might have to extended to 6.13 +// cover other calls. 6.14 +extern "C" int libsaproc_open(const char * name, int oflag, ...) { 6.15 + if (oflag == O_RDONLY) { 6.16 + init_alt_root(); 6.17 6.18 - if (_libsaproc_debug) { 6.19 - printf("libsaproc DEBUG: find_file_hook %s 0x%x\n", name, elf_checksum); 6.20 - } 6.21 - 6.22 - if (alt_root_len > 0) { 6.23 - int fd = -1; 6.24 - char alt_path[PATH_MAX+1]; 6.25 - 6.26 - strcpy(alt_path, alt_root); 6.27 - strcat(alt_path, name); 6.28 - fd = open(alt_path, O_RDONLY); 6.29 - if (fd >= 0) { 6.30 - if (_libsaproc_debug) { 6.31 - printf("libsaproc DEBUG: find_file_hook substituted %s\n", alt_path); 6.32 - } 6.33 - return fd; 6.34 + if (_libsaproc_debug) { 6.35 + printf("libsaproc DEBUG: libsaproc_open %s\n", name); 6.36 } 6.37 6.38 - if (strrchr(name, '/')) { 6.39 + if (alt_root_len > 0) { 6.40 + int fd = -1; 6.41 + char alt_path[PATH_MAX+1]; 6.42 + 6.43 strcpy(alt_path, alt_root); 6.44 - strcat(alt_path, strrchr(name, '/')); 6.45 + strcat(alt_path, name); 6.46 fd = open(alt_path, O_RDONLY); 6.47 if (fd >= 0) { 6.48 if (_libsaproc_debug) { 6.49 - printf("libsaproc DEBUG: find_file_hook substituted %s\n", alt_path); 6.50 + printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path); 6.51 } 6.52 return fd; 6.53 } 6.54 + 6.55 + if (strrchr(name, '/')) { 6.56 + strcpy(alt_path, alt_root); 6.57 + strcat(alt_path, strrchr(name, '/')); 6.58 + fd = open(alt_path, O_RDONLY); 6.59 + if (fd >= 0) { 6.60 + if (_libsaproc_debug) { 6.61 + printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path); 6.62 + } 6.63 + return fd; 6.64 + } 6.65 + } 6.66 } 6.67 } 6.68 - return -1; 6.69 + 6.70 + { 6.71 + mode_t mode; 6.72 + va_list ap; 6.73 + va_start(ap, oflag); 6.74 + mode = va_arg(ap, mode_t); 6.75 + va_end(ap); 6.76 + 6.77 + return open(name, oflag, mode); 6.78 + } 6.79 } 6.80 6.81 -static int pathmap_open(const char* name) { 6.82 - int fd = open(name, O_RDONLY); 6.83 - if (fd < 0) { 6.84 - fd = find_file_hook(name, 0); 6.85 - } 6.86 - return fd; 6.87 -} 6.88 6.89 static void * pathmap_dlopen(const char * name, int mode) { 6.90 init_alt_root(); 6.91 @@ -608,7 +617,7 @@ 6.92 print_debug("looking for %s\n", classes_jsa); 6.93 6.94 // open the classes[_g].jsa 6.95 - int fd = pathmap_open(classes_jsa); 6.96 + int fd = libsaproc_open(classes_jsa, O_RDONLY); 6.97 if (fd < 0) { 6.98 char errMsg[ERR_MSG_SIZE]; 6.99 sprintf(errMsg, "can't open shared archive file %s", classes_jsa); 6.100 @@ -1209,8 +1218,6 @@ 6.101 return res; 6.102 } 6.103 6.104 -typedef int (*find_file_hook_t)(const char *, int elf_checksum); 6.105 - 6.106 /* 6.107 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 6.108 * Method: initIDs 6.109 @@ -1230,16 +1237,6 @@ 6.110 if (libproc_handle == 0) 6.111 THROW_NEW_DEBUGGER_EXCEPTION("can't load libproc.so, if you are using Solaris 5.7 or below, copy libproc.so from 5.8!"); 6.112 6.113 - // If possible, set shared object find file hook. 6.114 - void (*set_hook)(find_file_hook_t) = (void(*)(find_file_hook_t))dlsym(libproc_handle, "Pset_find_file_hook"); 6.115 - if (set_hook) { 6.116 - // we found find file hook symbol, set up our hook function. 6.117 - set_hook(find_file_hook); 6.118 - } else if (getenv(SA_ALTROOT)) { 6.119 - printf("libsaproc WARNING: %s set, but can't set file hook. " \ 6.120 - "Did you use right version of libproc.so?\n", SA_ALTROOT); 6.121 - } 6.122 - 6.123 p_ps_prochandle_ID = env->GetFieldID(clazz, "p_ps_prochandle", "J"); 6.124 CHECK_EXCEPTION; 6.125
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/agent/src/os/solaris/proc/saproc_audit.cpp Mon Jul 27 06:15:29 2009 -0700 7.3 @@ -0,0 +1,98 @@ 7.4 +/* 7.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 7.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 7.24 + * have any questions. 7.25 + * 7.26 + */ 7.27 + 7.28 +#include <link.h> 7.29 +#include <stdio.h> 7.30 +#include <stdlib.h> 7.31 +#include <string.h> 7.32 +#include <sys/types.h> 7.33 +#include <sys/stat.h> 7.34 +#include <fcntl.h> 7.35 +#include <limits.h> 7.36 +#include <varargs.h> 7.37 + 7.38 +// This class sets up an interposer on open calls from libproc.so to 7.39 +// support a pathmap facility in the SA. 7.40 + 7.41 +static uintptr_t* libproc_cookie; 7.42 +static uintptr_t* libc_cookie; 7.43 +static uintptr_t* libsaproc_cookie; 7.44 + 7.45 + 7.46 +uint_t 7.47 +la_version(uint_t version) 7.48 +{ 7.49 + return (LAV_CURRENT); 7.50 +} 7.51 + 7.52 + 7.53 +uint_t 7.54 +la_objopen(Link_map * lmp, Lmid_t lmid, uintptr_t * cookie) 7.55 +{ 7.56 + if (strstr(lmp->l_name, "/libproc.so") != NULL) { 7.57 + libproc_cookie = cookie; 7.58 + return LA_FLG_BINDFROM; 7.59 + } 7.60 + if (strstr(lmp->l_name, "/libc.so") != NULL) { 7.61 + libc_cookie = cookie; 7.62 + return LA_FLG_BINDTO; 7.63 + } 7.64 + if (strstr(lmp->l_name, "/libsaproc.so") != NULL) { 7.65 + libsaproc_cookie = cookie; 7.66 + return LA_FLG_BINDTO | LA_FLG_BINDFROM; 7.67 + } 7.68 + return 0; 7.69 +} 7.70 + 7.71 + 7.72 +#if defined(_LP64) 7.73 +uintptr_t 7.74 +la_symbind64(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcook, 7.75 + uintptr_t *defcook, uint_t *sb_flags, const char *sym_name) 7.76 +#else 7.77 +uintptr_t 7.78 +la_symbind32(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcook, 7.79 + uintptr_t *defcook, uint_t *sb_flags) 7.80 +#endif 7.81 +{ 7.82 +#if !defined(_LP64) 7.83 + const char *sym_name = (const char *)symp->st_name; 7.84 +#endif 7.85 + if (strcmp(sym_name, "open") == 0 && refcook == libproc_cookie) { 7.86 + // redirect all open calls from libproc.so through libsaproc_open which will 7.87 + // try the alternate library locations first. 7.88 + void* handle = dlmopen(LM_ID_BASE, "libsaproc.so", RTLD_NOLOAD); 7.89 + if (handle == NULL) { 7.90 + fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc.so during linking\n"); 7.91 + } else { 7.92 + uintptr_t libsaproc_open = (uintptr_t)dlsym(handle, "libsaproc_open"); 7.93 + if (libsaproc_open == 0) { 7.94 + fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc_open during linking\n"); 7.95 + } else { 7.96 + return libsaproc_open; 7.97 + } 7.98 + } 7.99 + } 7.100 + return symp->st_value; 7.101 +}
8.1 --- a/make/hotspot_version Mon Jul 20 08:20:00 2009 -0700 8.2 +++ b/make/hotspot_version Mon Jul 27 06:15:29 2009 -0700 8.3 @@ -35,7 +35,7 @@ 8.4 8.5 HS_MAJOR_VER=16 8.6 HS_MINOR_VER=0 8.7 -HS_BUILD_NUMBER=05 8.8 +HS_BUILD_NUMBER=06 8.9 8.10 JDK_MAJOR_VER=1 8.11 JDK_MINOR_VER=7
9.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Mon Jul 20 08:20:00 2009 -0700 9.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Mon Jul 27 06:15:29 2009 -0700 9.3 @@ -4208,6 +4208,7 @@ 9.4 PtrQueue::byte_offset_of_active()), 9.5 tmp); 9.6 } 9.7 + 9.8 // Check on whether to annul. 9.9 br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); 9.10 delayed() -> nop(); 9.11 @@ -4215,13 +4216,13 @@ 9.12 // satb_log_barrier_work1(tmp, offset); 9.13 if (index == noreg) { 9.14 if (Assembler::is_simm13(offset)) { 9.15 - ld_ptr(obj, offset, tmp); 9.16 + load_heap_oop(obj, offset, tmp); 9.17 } else { 9.18 set(offset, tmp); 9.19 - ld_ptr(obj, tmp, tmp); 9.20 + load_heap_oop(obj, tmp, tmp); 9.21 } 9.22 } else { 9.23 - ld_ptr(obj, index, tmp); 9.24 + load_heap_oop(obj, index, tmp); 9.25 } 9.26 9.27 // satb_log_barrier_work2(obj, tmp, offset);
10.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 20 08:20:00 2009 -0700 10.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 27 06:15:29 2009 -0700 10.3 @@ -6805,14 +6805,18 @@ 10.4 jcc(Assembler::equal, done); 10.5 10.6 // if (x.f == NULL) goto done; 10.7 - cmpptr(Address(obj, 0), NULL_WORD); 10.8 +#ifdef _LP64 10.9 + load_heap_oop(tmp2, Address(obj, 0)); 10.10 +#else 10.11 + movptr(tmp2, Address(obj, 0)); 10.12 +#endif 10.13 + cmpptr(tmp2, (int32_t) NULL_WORD); 10.14 jcc(Assembler::equal, done); 10.15 10.16 // Can we store original value in the thread's buffer? 10.17 10.18 - LP64_ONLY(movslq(tmp, index);) 10.19 - movptr(tmp2, Address(obj, 0)); 10.20 #ifdef _LP64 10.21 + movslq(tmp, index); 10.22 cmpq(tmp, 0); 10.23 #else 10.24 cmpl(index, 0); 10.25 @@ -6834,8 +6838,7 @@ 10.26 if(tosca_live) push(rax); 10.27 push(obj); 10.28 #ifdef _LP64 10.29 - movq(c_rarg0, Address(obj, 0)); 10.30 - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), c_rarg0, r15_thread); 10.31 + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, r15_thread); 10.32 #else 10.33 push(thread); 10.34 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, thread);
11.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Mon Jul 20 08:20:00 2009 -0700 11.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Mon Jul 27 06:15:29 2009 -0700 11.3 @@ -269,11 +269,11 @@ 11.4 11.5 #ifndef PRODUCT 11.6 void trace_method_handle_stub(const char* adaptername, 11.7 - oop mh, 11.8 + oopDesc* mh, 11.9 intptr_t* entry_sp, 11.10 intptr_t* saved_sp) { 11.11 // called as a leaf from native code: do not block the JVM! 11.12 - printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, mh, entry_sp, entry_sp - saved_sp); 11.13 + printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp); 11.14 } 11.15 #endif //PRODUCT 11.16
12.1 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Jul 20 08:20:00 2009 -0700 12.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Jul 27 06:15:29 2009 -0700 12.3 @@ -709,7 +709,7 @@ 12.4 // 12.5 // Input: 12.6 // start - starting address 12.7 - // end - element count 12.8 + // count - element count 12.9 void gen_write_ref_array_pre_barrier(Register start, Register count) { 12.10 assert_different_registers(start, count); 12.11 BarrierSet* bs = Universe::heap()->barrier_set(); 12.12 @@ -757,7 +757,6 @@ 12.13 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post))); 12.14 __ addptr(rsp, 2*wordSize); 12.15 __ popa(); 12.16 - 12.17 } 12.18 break; 12.19
13.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Jul 20 08:20:00 2009 -0700 13.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Jul 27 06:15:29 2009 -0700 13.3 @@ -1207,9 +1207,9 @@ 13.4 __ pusha(); // push registers (overkill) 13.5 // must compute element count unless barrier set interface is changed (other platforms supply count) 13.6 assert_different_registers(start, end, scratch); 13.7 - __ lea(scratch, Address(end, wordSize)); 13.8 - __ subptr(scratch, start); 13.9 - __ shrptr(scratch, LogBytesPerWord); 13.10 + __ lea(scratch, Address(end, BytesPerHeapOop)); 13.11 + __ subptr(scratch, start); // subtract start to get #bytes 13.12 + __ shrptr(scratch, LogBytesPerHeapOop); // convert to element count 13.13 __ mov(c_rarg0, start); 13.14 __ mov(c_rarg1, scratch); 13.15 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post))); 13.16 @@ -1225,6 +1225,7 @@ 13.17 Label L_loop; 13.18 13.19 __ shrptr(start, CardTableModRefBS::card_shift); 13.20 + __ addptr(end, BytesPerHeapOop); 13.21 __ shrptr(end, CardTableModRefBS::card_shift); 13.22 __ subptr(end, start); // number of bytes to copy 13.23 13.24 @@ -2251,6 +2252,7 @@ 13.25 // and report their number to the caller. 13.26 assert_different_registers(rax, r14_length, count, to, end_to, rcx); 13.27 __ lea(end_to, to_element_addr); 13.28 + __ addptr(end_to, -heapOopSize); // make an inclusive end pointer 13.29 gen_write_ref_array_post_barrier(to, end_to, rscratch1); 13.30 __ movptr(rax, r14_length); // original oops 13.31 __ addptr(rax, count); // K = (original - remaining) oops 13.32 @@ -2259,7 +2261,7 @@ 13.33 13.34 // Come here on success only. 13.35 __ BIND(L_do_card_marks); 13.36 - __ addptr(end_to, -wordSize); // make an inclusive end pointer 13.37 + __ addptr(end_to, -heapOopSize); // make an inclusive end pointer 13.38 gen_write_ref_array_post_barrier(to, end_to, rscratch1); 13.39 __ xorptr(rax, rax); // return 0 on success 13.40
14.1 --- a/src/os/solaris/vm/os_solaris.cpp Mon Jul 20 08:20:00 2009 -0700 14.2 +++ b/src/os/solaris/vm/os_solaris.cpp Mon Jul 27 06:15:29 2009 -0700 14.3 @@ -1643,7 +1643,8 @@ 14.4 inline hrtime_t getTimeNanos() { 14.5 if (VM_Version::supports_cx8()) { 14.6 const hrtime_t now = gethrtime(); 14.7 - const hrtime_t prev = max_hrtime; 14.8 + // Use atomic long load since 32-bit x86 uses 2 registers to keep long. 14.9 + const hrtime_t prev = Atomic::load((volatile jlong*)&max_hrtime); 14.10 if (now <= prev) return prev; // same or retrograde time; 14.11 const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev); 14.12 assert(obsv >= prev, "invariant"); // Monotonicity
15.1 --- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Mon Jul 20 08:20:00 2009 -0700 15.2 +++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Mon Jul 27 06:15:29 2009 -0700 15.3 @@ -46,6 +46,8 @@ 15.4 inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } 15.5 inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } 15.6 15.7 +inline jlong Atomic::load(volatile jlong* src) { return *src; } 15.8 + 15.9 #ifdef _GNU_SOURCE 15.10 15.11 inline jint Atomic::add (jint add_value, volatile jint* dest) {
16.1 --- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp Mon Jul 20 08:20:00 2009 -0700 16.2 +++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp Mon Jul 27 06:15:29 2009 -0700 16.3 @@ -99,6 +99,8 @@ 16.4 return (void*)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, (int) os::is_MP()); 16.5 } 16.6 16.7 +inline jlong Atomic::load(volatile jlong* src) { return *src; } 16.8 + 16.9 #else // !AMD64 16.10 16.11 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { 16.12 @@ -131,6 +133,15 @@ 16.13 inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { 16.14 return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); 16.15 } 16.16 + 16.17 +extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst); 16.18 + 16.19 +inline jlong Atomic::load(volatile jlong* src) { 16.20 + volatile jlong dest; 16.21 + _Atomic_load_long(src, &dest); 16.22 + return dest; 16.23 +} 16.24 + 16.25 #endif // AMD64 16.26 16.27 #ifdef _GNU_SOURCE
17.1 --- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Mon Jul 20 08:20:00 2009 -0700 17.2 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Mon Jul 27 06:15:29 2009 -0700 17.3 @@ -97,6 +97,15 @@ 17.4 popl %ebx 17.5 .end 17.6 17.7 + // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest). 17.8 + .inline _Atomic_load_long,2 17.9 + movl 0(%esp), %eax // src 17.10 + fildll (%eax) 17.11 + movl 4(%esp), %eax // dest 17.12 + fistpll (%eax) 17.13 + .end 17.14 + 17.15 + 17.16 // Support for OrderAccess::acquire() 17.17 .inline _OrderAccess_acquire,0 17.18 movl 0(%esp), %eax
18.1 --- a/src/share/vm/adlc/formssel.cpp Mon Jul 20 08:20:00 2009 -0700 18.2 +++ b/src/share/vm/adlc/formssel.cpp Mon Jul 27 06:15:29 2009 -0700 18.3 @@ -420,6 +420,13 @@ 18.4 return _matrule->is_ideal_load(); 18.5 } 18.6 18.7 +// Return 'true' if this instruction matches an ideal 'LoadKlass' node 18.8 +bool InstructForm::skip_antidep_check() const { 18.9 + if( _matrule == NULL ) return false; 18.10 + 18.11 + return _matrule->skip_antidep_check(); 18.12 +} 18.13 + 18.14 // Return 'true' if this instruction matches an ideal 'Load?' node 18.15 Form::DataType InstructForm::is_ideal_store() const { 18.16 if( _matrule == NULL ) return Form::none; 18.17 @@ -567,6 +574,8 @@ 18.18 18.19 // loads from memory, so must check for anti-dependence 18.20 bool InstructForm::needs_anti_dependence_check(FormDict &globals) const { 18.21 + if ( skip_antidep_check() ) return false; 18.22 + 18.23 // Machine independent loads must be checked for anti-dependences 18.24 if( is_ideal_load() != Form::none ) return true; 18.25 18.26 @@ -3957,6 +3966,28 @@ 18.27 } 18.28 18.29 18.30 +bool MatchRule::skip_antidep_check() const { 18.31 + // Some loads operate on what is effectively immutable memory so we 18.32 + // should skip the anti dep computations. For some of these nodes 18.33 + // the rewritable field keeps the anti dep logic from triggering but 18.34 + // for certain kinds of LoadKlass it does not since they are 18.35 + // actually reading memory which could be rewritten by the runtime, 18.36 + // though never by generated code. This disables it uniformly for 18.37 + // the nodes that behave like this: LoadKlass, LoadNKlass and 18.38 + // LoadRange. 18.39 + if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { 18.40 + const char *opType = _rChild->_opType; 18.41 + if (strcmp("LoadKlass", opType) == 0 || 18.42 + strcmp("LoadNKlass", opType) == 0 || 18.43 + strcmp("LoadRange", opType) == 0) { 18.44 + return true; 18.45 + } 18.46 + } 18.47 + 18.48 + return false; 18.49 +} 18.50 + 18.51 + 18.52 Form::DataType MatchRule::is_ideal_store() const { 18.53 Form::DataType ideal_store = Form::none; 18.54
19.1 --- a/src/share/vm/adlc/formssel.hpp Mon Jul 20 08:20:00 2009 -0700 19.2 +++ b/src/share/vm/adlc/formssel.hpp Mon Jul 27 06:15:29 2009 -0700 19.3 @@ -158,6 +158,9 @@ 19.4 19.5 virtual Form::CallType is_ideal_call() const; // matches ideal 'Call' 19.6 virtual Form::DataType is_ideal_load() const; // node matches ideal 'LoadXNode' 19.7 + // Should antidep checks be disabled for this Instruct 19.8 + // See definition of MatchRule::skip_antidep_check 19.9 + bool skip_antidep_check() const; 19.10 virtual Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode' 19.11 bool is_ideal_mem() const { return is_ideal_load() != Form::none || is_ideal_store() != Form::none; } 19.12 virtual uint two_address(FormDict &globals); // output reg must match input reg 19.13 @@ -1003,6 +1006,9 @@ 19.14 bool is_ideal_loopEnd() const; // node matches ideal 'LoopEnd' 19.15 bool is_ideal_bool() const; // node matches ideal 'Bool' 19.16 Form::DataType is_ideal_load() const;// node matches ideal 'LoadXNode' 19.17 + // Should antidep checks be disabled for this rule 19.18 + // See definition of MatchRule::skip_antidep_check 19.19 + bool skip_antidep_check() const; 19.20 Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode' 19.21 19.22 // Check if 'mRule2' is a cisc-spill variant of this MatchRule
20.1 --- a/src/share/vm/classfile/classFileParser.cpp Mon Jul 20 08:20:00 2009 -0700 20.2 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Jul 27 06:15:29 2009 -0700 20.3 @@ -3231,6 +3231,16 @@ 20.4 this_klass->set_minor_version(minor_version); 20.5 this_klass->set_major_version(major_version); 20.6 20.7 + // Set up methodOop::intrinsic_id as soon as we know the names of methods. 20.8 + // (We used to do this lazily, but now we query it in Rewriter, 20.9 + // which is eagerly done for every method, so we might as well do it now, 20.10 + // when everything is fresh in memory.) 20.11 + if (methodOopDesc::klass_id_for_intrinsics(this_klass->as_klassOop()) != vmSymbols::NO_SID) { 20.12 + for (int j = 0; j < methods->length(); j++) { 20.13 + ((methodOop)methods->obj_at(j))->init_intrinsic_id(); 20.14 + } 20.15 + } 20.16 + 20.17 if (cached_class_file_bytes != NULL) { 20.18 // JVMTI: we have an instanceKlass now, tell it about the cached bytes 20.19 this_klass->set_cached_class_file(cached_class_file_bytes,
21.1 --- a/src/share/vm/classfile/vmSymbols.hpp Mon Jul 20 08:20:00 2009 -0700 21.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jul 27 06:15:29 2009 -0700 21.3 @@ -513,9 +513,6 @@ 21.4 // 21.5 // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) 21.6 #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ 21.7 - do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ 21.8 - /* (symbol object_initializer_name defined above) */ \ 21.9 - \ 21.10 do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ 21.11 do_name( hashCode_name, "hashCode") \ 21.12 do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ 21.13 @@ -635,9 +632,6 @@ 21.14 do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ 21.15 do_signature(equalsC_signature, "([C[C)Z") \ 21.16 \ 21.17 - do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ 21.18 - /* (symbols invoke_name and invoke_signature defined above) */ \ 21.19 - \ 21.20 do_intrinsic(_compareTo, java_lang_String, compareTo_name, string_int_signature, F_R) \ 21.21 do_name( compareTo_name, "compareTo") \ 21.22 do_intrinsic(_indexOf, java_lang_String, indexOf_name, string_int_signature, F_R) \ 21.23 @@ -656,8 +650,6 @@ 21.24 do_name( attemptUpdate_name, "attemptUpdate") \ 21.25 do_signature(attemptUpdate_signature, "(JJ)Z") \ 21.26 \ 21.27 - do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ 21.28 - \ 21.29 /* support for sun.misc.Unsafe */ \ 21.30 do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ 21.31 \ 21.32 @@ -819,10 +811,22 @@ 21.33 do_name( prefetchReadStatic_name, "prefetchReadStatic") \ 21.34 do_intrinsic(_prefetchWriteStatic, sun_misc_Unsafe, prefetchWriteStatic_name, prefetch_signature, F_SN) \ 21.35 do_name( prefetchWriteStatic_name, "prefetchWriteStatic") \ 21.36 + /*== LAST_COMPILER_INLINE*/ \ 21.37 + /*the compiler does have special inlining code for these; bytecode inline is just fine */ \ 21.38 + \ 21.39 + do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ 21.40 + \ 21.41 + do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ 21.42 + /* (symbol object_initializer_name defined above) */ \ 21.43 + \ 21.44 + do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ 21.45 + /* (symbols invoke_name and invoke_signature defined above) */ \ 21.46 + \ 21.47 /*end*/ 21.48 21.49 21.50 21.51 + 21.52 // Class vmSymbols 21.53 21.54 class vmSymbols: AllStatic { 21.55 @@ -935,6 +939,7 @@ 21.56 #undef VM_INTRINSIC_ENUM 21.57 21.58 ID_LIMIT, 21.59 + LAST_COMPILER_INLINE = _prefetchWriteStatic, 21.60 FIRST_ID = _none + 1 21.61 }; 21.62 21.63 @@ -972,4 +977,7 @@ 21.64 static Flags flags_for(ID id); 21.65 21.66 static const char* short_name_as_C_string(ID id, char* buf, int size); 21.67 + 21.68 + // Access to intrinsic methods: 21.69 + static methodOop method_for(ID id); 21.70 };
22.1 --- a/src/share/vm/compiler/oopMap.cpp Mon Jul 20 08:20:00 2009 -0700 22.2 +++ b/src/share/vm/compiler/oopMap.cpp Mon Jul 27 06:15:29 2009 -0700 22.3 @@ -379,7 +379,15 @@ 22.4 if ( loc != NULL ) { 22.5 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); 22.6 oop *derived_loc = loc; 22.7 - derived_oop_fn(base_loc, derived_loc); 22.8 + oop val = *base_loc; 22.9 + if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { 22.10 + // Ignore NULL oops and decoded NULL narrow oops which 22.11 + // equal to Universe::narrow_oop_base when a narrow oop 22.12 + // implicit null check is used in compiled code. 22.13 + // The narrow_oop_base could be NULL or be the address 22.14 + // of the page below heap depending on compressed oops mode. 22.15 + } else 22.16 + derived_oop_fn(base_loc, derived_loc); 22.17 } 22.18 oms.next(); 22.19 } while (!oms.is_done()); 22.20 @@ -394,6 +402,15 @@ 22.21 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); 22.22 if ( loc != NULL ) { 22.23 if ( omv.type() == OopMapValue::oop_value ) { 22.24 + oop val = *loc; 22.25 + if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { 22.26 + // Ignore NULL oops and decoded NULL narrow oops which 22.27 + // equal to Universe::narrow_oop_base when a narrow oop 22.28 + // implicit null check is used in compiled code. 22.29 + // The narrow_oop_base could be NULL or be the address 22.30 + // of the page below heap depending on compressed oops mode. 22.31 + continue; 22.32 + } 22.33 #ifdef ASSERT 22.34 if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || 22.35 !Universe::heap()->is_in_or_null(*loc)) { 22.36 @@ -410,6 +427,8 @@ 22.37 #endif // ASSERT 22.38 oop_fn->do_oop(loc); 22.39 } else if ( omv.type() == OopMapValue::value_value ) { 22.40 + assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc), 22.41 + "found invalid value pointer"); 22.42 value_fn->do_oop(loc); 22.43 } else if ( omv.type() == OopMapValue::narrowoop_value ) { 22.44 narrowOop *nl = (narrowOop*)loc;
23.1 --- a/src/share/vm/compiler/oopMap.hpp Mon Jul 20 08:20:00 2009 -0700 23.2 +++ b/src/share/vm/compiler/oopMap.hpp Mon Jul 27 06:15:29 2009 -0700 23.3 @@ -233,6 +233,10 @@ 23.4 int heap_size() const; 23.5 void copy_to(address addr); 23.6 23.7 + // Methods oops_do() and all_do() filter out NULL oops and 23.8 + // oop == Universe::narrow_oop_base() before passing oops 23.9 + // to closures. 23.10 + 23.11 // Iterates through frame for a compiled method 23.12 static void oops_do (const frame* fr, 23.13 const RegisterMap* reg_map, OopClosure* f);
24.1 --- a/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp Mon Jul 20 08:20:00 2009 -0700 24.2 +++ b/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp Mon Jul 27 06:15:29 2009 -0700 24.3 @@ -42,35 +42,40 @@ 24.4 BufferLength = 1024 24.5 }; 24.6 24.7 - oop *_buffer[BufferLength]; 24.8 - oop **_buffer_top; 24.9 - oop **_buffer_curr; 24.10 + StarTask _buffer[BufferLength]; 24.11 + StarTask* _buffer_top; 24.12 + StarTask* _buffer_curr; 24.13 24.14 - OopClosure *_oc; 24.15 - double _closure_app_seconds; 24.16 + OopClosure* _oc; 24.17 + double _closure_app_seconds; 24.18 24.19 void process_buffer () { 24.20 - 24.21 double start = os::elapsedTime(); 24.22 - for (oop **curr = _buffer; curr < _buffer_curr; ++curr) { 24.23 - _oc->do_oop(*curr); 24.24 + for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) { 24.25 + if (curr->is_narrow()) { 24.26 + assert(UseCompressedOops, "Error"); 24.27 + _oc->do_oop((narrowOop*)(*curr)); 24.28 + } else { 24.29 + _oc->do_oop((oop*)(*curr)); 24.30 + } 24.31 } 24.32 _buffer_curr = _buffer; 24.33 _closure_app_seconds += (os::elapsedTime() - start); 24.34 } 24.35 24.36 -public: 24.37 - virtual void do_oop(narrowOop* p) { 24.38 - guarantee(false, "NYI"); 24.39 - } 24.40 - virtual void do_oop(oop *p) { 24.41 + template <class T> inline void do_oop_work(T* p) { 24.42 if (_buffer_curr == _buffer_top) { 24.43 process_buffer(); 24.44 } 24.45 - 24.46 - *_buffer_curr = p; 24.47 + StarTask new_ref(p); 24.48 + *_buffer_curr = new_ref; 24.49 ++_buffer_curr; 24.50 } 24.51 + 24.52 +public: 24.53 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 24.54 + virtual void do_oop(oop* p) { do_oop_work(p); } 24.55 + 24.56 void done () { 24.57 if (_buffer_curr > _buffer) { 24.58 process_buffer(); 24.59 @@ -88,18 +93,17 @@ 24.60 class BufferingOopsInGenClosure: public OopsInGenClosure { 24.61 BufferingOopClosure _boc; 24.62 OopsInGenClosure* _oc; 24.63 -public: 24.64 + protected: 24.65 + template <class T> inline void do_oop_work(T* p) { 24.66 + assert(generation()->is_in_reserved((void*)p), "Must be in!"); 24.67 + _boc.do_oop(p); 24.68 + } 24.69 + public: 24.70 BufferingOopsInGenClosure(OopsInGenClosure *oc) : 24.71 _boc(oc), _oc(oc) {} 24.72 24.73 - virtual void do_oop(narrowOop* p) { 24.74 - guarantee(false, "NYI"); 24.75 - } 24.76 - 24.77 - virtual void do_oop(oop* p) { 24.78 - assert(generation()->is_in_reserved(p), "Must be in!"); 24.79 - _boc.do_oop(p); 24.80 - } 24.81 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 24.82 + virtual void do_oop(oop* p) { do_oop_work(p); } 24.83 24.84 void done() { 24.85 _boc.done(); 24.86 @@ -130,14 +134,14 @@ 24.87 BufferLength = 1024 24.88 }; 24.89 24.90 - oop *_buffer[BufferLength]; 24.91 - oop **_buffer_top; 24.92 - oop **_buffer_curr; 24.93 + StarTask _buffer[BufferLength]; 24.94 + StarTask* _buffer_top; 24.95 + StarTask* _buffer_curr; 24.96 24.97 - HeapRegion *_hr_buffer[BufferLength]; 24.98 - HeapRegion **_hr_curr; 24.99 + HeapRegion* _hr_buffer[BufferLength]; 24.100 + HeapRegion** _hr_curr; 24.101 24.102 - OopsInHeapRegionClosure *_oc; 24.103 + OopsInHeapRegionClosure* _oc; 24.104 double _closure_app_seconds; 24.105 24.106 void process_buffer () { 24.107 @@ -146,15 +150,20 @@ 24.108 "the two lengths should be the same"); 24.109 24.110 double start = os::elapsedTime(); 24.111 - HeapRegion **hr_curr = _hr_buffer; 24.112 - HeapRegion *hr_prev = NULL; 24.113 - for (oop **curr = _buffer; curr < _buffer_curr; ++curr) { 24.114 - HeapRegion *region = *hr_curr; 24.115 + HeapRegion** hr_curr = _hr_buffer; 24.116 + HeapRegion* hr_prev = NULL; 24.117 + for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) { 24.118 + HeapRegion* region = *hr_curr; 24.119 if (region != hr_prev) { 24.120 _oc->set_region(region); 24.121 hr_prev = region; 24.122 } 24.123 - _oc->do_oop(*curr); 24.124 + if (curr->is_narrow()) { 24.125 + assert(UseCompressedOops, "Error"); 24.126 + _oc->do_oop((narrowOop*)(*curr)); 24.127 + } else { 24.128 + _oc->do_oop((oop*)(*curr)); 24.129 + } 24.130 ++hr_curr; 24.131 } 24.132 _buffer_curr = _buffer; 24.133 @@ -163,17 +172,16 @@ 24.134 } 24.135 24.136 public: 24.137 - virtual void do_oop(narrowOop *p) { 24.138 - guarantee(false, "NYI"); 24.139 - } 24.140 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 24.141 + virtual void do_oop( oop* p) { do_oop_work(p); } 24.142 24.143 - virtual void do_oop(oop *p) { 24.144 + template <class T> void do_oop_work(T* p) { 24.145 if (_buffer_curr == _buffer_top) { 24.146 assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr"); 24.147 process_buffer(); 24.148 } 24.149 - 24.150 - *_buffer_curr = p; 24.151 + StarTask new_ref(p); 24.152 + *_buffer_curr = new_ref; 24.153 ++_buffer_curr; 24.154 *_hr_curr = _from; 24.155 ++_hr_curr;
25.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jul 20 08:20:00 2009 -0700 25.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jul 27 06:15:29 2009 -0700 25.3 @@ -452,13 +452,10 @@ 25.4 _regionStack.allocate(G1MarkRegionStackSize); 25.5 25.6 // Create & start a ConcurrentMark thread. 25.7 - if (G1ConcMark) { 25.8 - _cmThread = new ConcurrentMarkThread(this); 25.9 - assert(cmThread() != NULL, "CM Thread should have been created"); 25.10 - assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm"); 25.11 - } else { 25.12 - _cmThread = NULL; 25.13 - } 25.14 + _cmThread = new ConcurrentMarkThread(this); 25.15 + assert(cmThread() != NULL, "CM Thread should have been created"); 25.16 + assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm"); 25.17 + 25.18 _g1h = G1CollectedHeap::heap(); 25.19 assert(CGC_lock != NULL, "Where's the CGC_lock?"); 25.20 assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency"); 25.21 @@ -783,18 +780,18 @@ 25.22 bool do_barrier) : _cm(cm), _g1h(g1h), 25.23 _do_barrier(do_barrier) { } 25.24 25.25 - virtual void do_oop(narrowOop* p) { 25.26 - guarantee(false, "NYI"); 25.27 - } 25.28 - 25.29 - virtual void do_oop(oop* p) { 25.30 - oop thisOop = *p; 25.31 - if (thisOop != NULL) { 25.32 - assert(thisOop->is_oop() || thisOop->mark() == NULL, 25.33 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 25.34 + virtual void do_oop( oop* p) { do_oop_work(p); } 25.35 + 25.36 + template <class T> void do_oop_work(T* p) { 25.37 + T heap_oop = oopDesc::load_heap_oop(p); 25.38 + if (!oopDesc::is_null(heap_oop)) { 25.39 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 25.40 + assert(obj->is_oop() || obj->mark() == NULL, 25.41 "expected an oop, possibly with mark word displaced"); 25.42 - HeapWord* addr = (HeapWord*)thisOop; 25.43 + HeapWord* addr = (HeapWord*)obj; 25.44 if (_g1h->is_in_g1_reserved(addr)) { 25.45 - _cm->grayRoot(thisOop); 25.46 + _cm->grayRoot(obj); 25.47 } 25.48 } 25.49 if (_do_barrier) { 25.50 @@ -850,16 +847,6 @@ 25.51 double start = os::elapsedTime(); 25.52 GCOverheadReporter::recordSTWStart(start); 25.53 25.54 - // If there has not been a GC[n-1] since last GC[n] cycle completed, 25.55 - // precede our marking with a collection of all 25.56 - // younger generations to keep floating garbage to a minimum. 25.57 - // YSR: we won't do this for now -- it's an optimization to be 25.58 - // done post-beta. 25.59 - 25.60 - // YSR: ignoring weak refs for now; will do at bug fixing stage 25.61 - // EVM: assert(discoveredRefsAreClear()); 25.62 - 25.63 - 25.64 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); 25.65 g1p->record_concurrent_mark_init_start(); 25.66 checkpointRootsInitialPre(); 25.67 @@ -1135,6 +1122,13 @@ 25.68 return; 25.69 } 25.70 25.71 + if (VerifyDuringGC) { 25.72 + HandleMark hm; // handle scope 25.73 + gclog_or_tty->print(" VerifyDuringGC:(before)"); 25.74 + Universe::heap()->prepare_for_verify(); 25.75 + Universe::verify(true, false, true); 25.76 + } 25.77 + 25.78 G1CollectorPolicy* g1p = g1h->g1_policy(); 25.79 g1p->record_concurrent_mark_remark_start(); 25.80 25.81 @@ -1159,10 +1153,12 @@ 25.82 JavaThread::satb_mark_queue_set().set_active_all_threads(false); 25.83 25.84 if (VerifyDuringGC) { 25.85 - g1h->prepare_for_verify(); 25.86 - g1h->verify(/* allow_dirty */ true, 25.87 - /* silent */ false, 25.88 - /* use_prev_marking */ false); 25.89 + HandleMark hm; // handle scope 25.90 + gclog_or_tty->print(" VerifyDuringGC:(after)"); 25.91 + Universe::heap()->prepare_for_verify(); 25.92 + Universe::heap()->verify(/* allow_dirty */ true, 25.93 + /* silent */ false, 25.94 + /* use_prev_marking */ false); 25.95 } 25.96 } 25.97 25.98 @@ -1658,6 +1654,15 @@ 25.99 return; 25.100 } 25.101 25.102 + if (VerifyDuringGC) { 25.103 + HandleMark hm; // handle scope 25.104 + gclog_or_tty->print(" VerifyDuringGC:(before)"); 25.105 + Universe::heap()->prepare_for_verify(); 25.106 + Universe::verify(/* allow dirty */ true, 25.107 + /* silent */ false, 25.108 + /* prev marking */ true); 25.109 + } 25.110 + 25.111 _cleanup_co_tracker.disable(); 25.112 25.113 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); 25.114 @@ -1790,10 +1795,12 @@ 25.115 g1h->increment_total_collections(); 25.116 25.117 if (VerifyDuringGC) { 25.118 - g1h->prepare_for_verify(); 25.119 - g1h->verify(/* allow_dirty */ true, 25.120 - /* silent */ false, 25.121 - /* use_prev_marking */ true); 25.122 + HandleMark hm; // handle scope 25.123 + gclog_or_tty->print(" VerifyDuringGC:(after)"); 25.124 + Universe::heap()->prepare_for_verify(); 25.125 + Universe::verify(/* allow dirty */ true, 25.126 + /* silent */ false, 25.127 + /* prev marking */ true); 25.128 } 25.129 } 25.130 25.131 @@ -1852,12 +1859,11 @@ 25.132 _g1(g1), _cm(cm), 25.133 _bitMap(bitMap) {} 25.134 25.135 - void do_oop(narrowOop* p) { 25.136 - guarantee(false, "NYI"); 25.137 - } 25.138 - 25.139 - void do_oop(oop* p) { 25.140 - oop thisOop = *p; 25.141 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 25.142 + virtual void do_oop( oop* p) { do_oop_work(p); } 25.143 + 25.144 + template <class T> void do_oop_work(T* p) { 25.145 + oop thisOop = oopDesc::load_decode_heap_oop(p); 25.146 HeapWord* addr = (HeapWord*)thisOop; 25.147 if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(thisOop)) { 25.148 _bitMap->mark(addr); 25.149 @@ -2016,12 +2022,11 @@ 25.150 ReachablePrinterOopClosure(CMBitMapRO* bitmap, outputStream* out) : 25.151 _bitmap(bitmap), _g1h(G1CollectedHeap::heap()), _out(out) { } 25.152 25.153 - void do_oop(narrowOop* p) { 25.154 - guarantee(false, "NYI"); 25.155 - } 25.156 - 25.157 - void do_oop(oop* p) { 25.158 - oop obj = *p; 25.159 + void do_oop(narrowOop* p) { do_oop_work(p); } 25.160 + void do_oop( oop* p) { do_oop_work(p); } 25.161 + 25.162 + template <class T> void do_oop_work(T* p) { 25.163 + oop obj = oopDesc::load_decode_heap_oop(p); 25.164 const char* str = NULL; 25.165 const char* str2 = ""; 25.166 25.167 @@ -2163,6 +2168,7 @@ 25.168 25.169 25.170 HeapWord* objAddr = (HeapWord*) obj; 25.171 + assert(obj->is_oop_or_null(true /* ignore mark word */), "Error"); 25.172 if (_g1h->is_in_g1_reserved(objAddr)) { 25.173 tmp_guarantee_CM( obj != NULL, "is_in_g1_reserved should ensure this" ); 25.174 HeapRegion* hr = _g1h->heap_region_containing(obj); 25.175 @@ -2380,7 +2386,7 @@ 25.176 } 25.177 } 25.178 25.179 - bool drain() { 25.180 + template <class T> bool drain() { 25.181 while (_ms_ind > 0) { 25.182 oop obj = pop(); 25.183 assert(obj != NULL, "Since index was non-zero."); 25.184 @@ -2394,9 +2400,8 @@ 25.185 } 25.186 // Now process this portion of this one. 25.187 int lim = MIN2(next_arr_ind, len); 25.188 - assert(!UseCompressedOops, "This needs to be fixed"); 25.189 for (int j = arr_ind; j < lim; j++) { 25.190 - do_oop(aobj->obj_at_addr<oop>(j)); 25.191 + do_oop(aobj->obj_at_addr<T>(j)); 25.192 } 25.193 25.194 } else { 25.195 @@ -2423,13 +2428,13 @@ 25.196 FREE_C_HEAP_ARRAY(jint, _array_ind_stack); 25.197 } 25.198 25.199 - void do_oop(narrowOop* p) { 25.200 - guarantee(false, "NYI"); 25.201 - } 25.202 - 25.203 - void do_oop(oop* p) { 25.204 - oop obj = *p; 25.205 - if (obj == NULL) return; 25.206 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 25.207 + virtual void do_oop( oop* p) { do_oop_work(p); } 25.208 + 25.209 + template <class T> void do_oop_work(T* p) { 25.210 + T heap_oop = oopDesc::load_heap_oop(p); 25.211 + if (oopDesc::is_null(heap_oop)) return; 25.212 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 25.213 if (obj->is_forwarded()) { 25.214 // If the object has already been forwarded, we have to make sure 25.215 // that it's marked. So follow the forwarding pointer. Note that 25.216 @@ -2478,7 +2483,11 @@ 25.217 oop obj = oop(addr); 25.218 if (!obj->is_forwarded()) { 25.219 if (!_oop_cl.push(obj)) return false; 25.220 - if (!_oop_cl.drain()) return false; 25.221 + if (UseCompressedOops) { 25.222 + if (!_oop_cl.drain<narrowOop>()) return false; 25.223 + } else { 25.224 + if (!_oop_cl.drain<oop>()) return false; 25.225 + } 25.226 } 25.227 // Otherwise... 25.228 return true; 25.229 @@ -2636,9 +2645,6 @@ 25.230 25.231 // abandon current marking iteration due to a Full GC 25.232 void ConcurrentMark::abort() { 25.233 - // If we're not marking, nothing to do. 25.234 - if (!G1ConcMark) return; 25.235 - 25.236 // Clear all marks to force marking thread to do nothing 25.237 _nextMarkBitMap->clearAll(); 25.238 // Empty mark stack 25.239 @@ -2814,14 +2820,14 @@ 25.240 CMTask* _task; 25.241 25.242 public: 25.243 - void do_oop(narrowOop* p) { 25.244 - guarantee(false, "NYI"); 25.245 - } 25.246 - 25.247 - void do_oop(oop* p) { 25.248 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 25.249 + virtual void do_oop( oop* p) { do_oop_work(p); } 25.250 + 25.251 + template <class T> void do_oop_work(T* p) { 25.252 tmp_guarantee_CM( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant" ); 25.253 - 25.254 - oop obj = *p; 25.255 + tmp_guarantee_CM( !_g1h->heap_region_containing((HeapWord*) p)->is_on_free_list(), "invariant" ); 25.256 + 25.257 + oop obj = oopDesc::load_decode_heap_oop(p); 25.258 if (_cm->verbose_high()) 25.259 gclog_or_tty->print_cr("[%d] we're looking at location " 25.260 "*"PTR_FORMAT" = "PTR_FORMAT, 25.261 @@ -2967,6 +2973,7 @@ 25.262 ++_refs_reached; 25.263 25.264 HeapWord* objAddr = (HeapWord*) obj; 25.265 + assert(obj->is_oop_or_null(true /* ignore mark word */), "Error"); 25.266 if (_g1h->is_in_g1_reserved(objAddr)) { 25.267 tmp_guarantee_CM( obj != NULL, "is_in_g1_reserved should ensure this" ); 25.268 HeapRegion* hr = _g1h->heap_region_containing(obj); 25.269 @@ -3030,6 +3037,7 @@ 25.270 void CMTask::push(oop obj) { 25.271 HeapWord* objAddr = (HeapWord*) obj; 25.272 tmp_guarantee_CM( _g1h->is_in_g1_reserved(objAddr), "invariant" ); 25.273 + tmp_guarantee_CM( !_g1h->heap_region_containing(objAddr)->is_on_free_list(), "invariant" ); 25.274 tmp_guarantee_CM( !_g1h->is_obj_ill(obj), "invariant" ); 25.275 tmp_guarantee_CM( _nextMarkBitMap->isMarked(objAddr), "invariant" ); 25.276 25.277 @@ -3275,6 +3283,8 @@ 25.278 25.279 tmp_guarantee_CM( _g1h->is_in_g1_reserved((HeapWord*) obj), 25.280 "invariant" ); 25.281 + tmp_guarantee_CM( !_g1h->heap_region_containing(obj)->is_on_free_list(), 25.282 + "invariant" ); 25.283 25.284 scan_object(obj); 25.285
26.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Mon Jul 20 08:20:00 2009 -0700 26.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Mon Jul 27 06:15:29 2009 -0700 26.3 @@ -763,6 +763,7 @@ 26.4 CMBitMap* _nextMarkBitMap; 26.5 // the task queue of this task 26.6 CMTaskQueue* _task_queue; 26.7 +private: 26.8 // the task queue set---needed for stealing 26.9 CMTaskQueueSet* _task_queues; 26.10 // indicates whether the task has been claimed---this is only for
27.1 --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Mon Jul 20 08:20:00 2009 -0700 27.2 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Mon Jul 27 06:15:29 2009 -0700 27.3 @@ -424,7 +424,7 @@ 27.4 while (n <= next_boundary) { 27.5 q = n; 27.6 oop obj = oop(q); 27.7 - if (obj->klass() == NULL) return q; 27.8 + if (obj->klass_or_null() == NULL) return q; 27.9 n += obj->size(); 27.10 } 27.11 assert(q <= next_boundary && n > next_boundary, "Consequence of loop"); 27.12 @@ -436,7 +436,7 @@ 27.13 while (n <= next_boundary) { 27.14 q = n; 27.15 oop obj = oop(q); 27.16 - if (obj->klass() == NULL) return q; 27.17 + if (obj->klass_or_null() == NULL) return q; 27.18 n += _sp->block_size(q); 27.19 } 27.20 assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
28.1 --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Mon Jul 20 08:20:00 2009 -0700 28.2 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Mon Jul 27 06:15:29 2009 -0700 28.3 @@ -96,14 +96,14 @@ 28.4 while (n <= addr) { 28.5 q = n; 28.6 oop obj = oop(q); 28.7 - if (obj->klass() == NULL) return q; 28.8 + if (obj->klass_or_null() == NULL) return q; 28.9 n += obj->size(); 28.10 } 28.11 } else { 28.12 while (n <= addr) { 28.13 q = n; 28.14 oop obj = oop(q); 28.15 - if (obj->klass() == NULL) return q; 28.16 + if (obj->klass_or_null() == NULL) return q; 28.17 n += _sp->block_size(q); 28.18 } 28.19 } 28.20 @@ -115,7 +115,7 @@ 28.21 inline HeapWord* 28.22 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q, 28.23 const void* addr) { 28.24 - if (oop(q)->klass() == NULL) return q; 28.25 + if (oop(q)->klass_or_null() == NULL) return q; 28.26 HeapWord* n = q + _sp->block_size(q); 28.27 // In the normal case, where the query "addr" is a card boundary, and the 28.28 // offset table chunks are the same size as cards, the block starting at
29.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Jul 20 08:20:00 2009 -0700 29.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Jul 27 06:15:29 2009 -0700 29.3 @@ -902,6 +902,10 @@ 29.4 size_t word_size) { 29.5 ResourceMark rm; 29.6 29.7 + if (PrintHeapAtGC) { 29.8 + Universe::print_heap_before_gc(); 29.9 + } 29.10 + 29.11 if (full && DisableExplicitGC) { 29.12 gclog_or_tty->print("\n\n\nDisabling Explicit GC\n\n\n"); 29.13 return; 29.14 @@ -927,7 +931,7 @@ 29.15 g1_policy()->record_full_collection_start(); 29.16 29.17 gc_prologue(true); 29.18 - increment_total_collections(); 29.19 + increment_total_collections(true /* full gc */); 29.20 29.21 size_t g1h_prev_used = used(); 29.22 assert(used() == recalculate_used(), "Should be equal"); 29.23 @@ -1066,6 +1070,10 @@ 29.24 assert( check_young_list_empty(false, false), 29.25 "young list should be empty at this point"); 29.26 } 29.27 + 29.28 + if (PrintHeapAtGC) { 29.29 + Universe::print_heap_after_gc(); 29.30 + } 29.31 } 29.32 29.33 void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { 29.34 @@ -1647,11 +1655,19 @@ 29.35 // Computes the sum of the storage used by the various regions. 29.36 29.37 size_t G1CollectedHeap::used() const { 29.38 - assert(Heap_lock->owner() != NULL, 29.39 - "Should be owned on this thread's behalf."); 29.40 + // Temporarily, until 6859911 is fixed. XXX 29.41 + // assert(Heap_lock->owner() != NULL, 29.42 + // "Should be owned on this thread's behalf."); 29.43 size_t result = _summary_bytes_used; 29.44 - if (_cur_alloc_region != NULL) 29.45 - result += _cur_alloc_region->used(); 29.46 + // Read only once in case it is set to NULL concurrently 29.47 + HeapRegion* hr = _cur_alloc_region; 29.48 + if (hr != NULL) 29.49 + result += hr->used(); 29.50 + return result; 29.51 +} 29.52 + 29.53 +size_t G1CollectedHeap::used_unlocked() const { 29.54 + size_t result = _summary_bytes_used; 29.55 return result; 29.56 } 29.57 29.58 @@ -2125,13 +2141,13 @@ 29.59 VerifyLivenessOopClosure(G1CollectedHeap* _g1h) { 29.60 g1h = _g1h; 29.61 } 29.62 - void do_oop(narrowOop *p) { 29.63 - guarantee(false, "NYI"); 29.64 - } 29.65 - void do_oop(oop *p) { 29.66 - oop obj = *p; 29.67 - assert(obj == NULL || !g1h->is_obj_dead(obj), 29.68 - "Dead object referenced by a not dead object"); 29.69 + void do_oop(narrowOop *p) { do_oop_work(p); } 29.70 + void do_oop( oop *p) { do_oop_work(p); } 29.71 + 29.72 + template <class T> void do_oop_work(T *p) { 29.73 + oop obj = oopDesc::load_decode_heap_oop(p); 29.74 + guarantee(obj == NULL || !g1h->is_obj_dead(obj), 29.75 + "Dead object referenced by a not dead object"); 29.76 } 29.77 }; 29.78 29.79 @@ -2198,8 +2214,10 @@ 29.80 // use_prev_marking == true -> use "prev" marking information, 29.81 // use_prev_marking == false -> use "next" marking information 29.82 VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) 29.83 - : _allow_dirty(allow_dirty), _par(par), 29.84 + : _allow_dirty(allow_dirty), 29.85 + _par(par), 29.86 _use_prev_marking(use_prev_marking) {} 29.87 + 29.88 bool doHeapRegion(HeapRegion* r) { 29.89 guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, 29.90 "Should be unclaimed at verify points."); 29.91 @@ -2223,18 +2241,16 @@ 29.92 // use_prev_marking == true -> use "prev" marking information, 29.93 // use_prev_marking == false -> use "next" marking information 29.94 VerifyRootsClosure(bool use_prev_marking) : 29.95 - _g1h(G1CollectedHeap::heap()), _failures(false), 29.96 + _g1h(G1CollectedHeap::heap()), 29.97 + _failures(false), 29.98 _use_prev_marking(use_prev_marking) { } 29.99 29.100 bool failures() { return _failures; } 29.101 29.102 - void do_oop(narrowOop* p) { 29.103 - guarantee(false, "NYI"); 29.104 - } 29.105 - 29.106 - void do_oop(oop* p) { 29.107 - oop obj = *p; 29.108 - if (obj != NULL) { 29.109 + template <class T> void do_oop_nv(T* p) { 29.110 + T heap_oop = oopDesc::load_heap_oop(p); 29.111 + if (!oopDesc::is_null(heap_oop)) { 29.112 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 29.113 if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { 29.114 gclog_or_tty->print_cr("Root location "PTR_FORMAT" " 29.115 "points to dead obj "PTR_FORMAT, p, (void*) obj); 29.116 @@ -2243,6 +2259,9 @@ 29.117 } 29.118 } 29.119 } 29.120 + 29.121 + void do_oop(oop* p) { do_oop_nv(p); } 29.122 + void do_oop(narrowOop* p) { do_oop_nv(p); } 29.123 }; 29.124 29.125 // This is the task used for parallel heap verification. 29.126 @@ -2259,7 +2278,8 @@ 29.127 G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, 29.128 bool use_prev_marking) : 29.129 AbstractGangTask("Parallel verify task"), 29.130 - _g1h(g1h), _allow_dirty(allow_dirty), 29.131 + _g1h(g1h), 29.132 + _allow_dirty(allow_dirty), 29.133 _use_prev_marking(use_prev_marking) { } 29.134 29.135 void work(int worker_i) { 29.136 @@ -2325,9 +2345,37 @@ 29.137 } 29.138 }; 29.139 29.140 -void G1CollectedHeap::print() const { print_on(gclog_or_tty); } 29.141 +void G1CollectedHeap::print() const { print_on(tty); } 29.142 29.143 void G1CollectedHeap::print_on(outputStream* st) const { 29.144 + print_on(st, PrintHeapAtGCExtended); 29.145 +} 29.146 + 29.147 +void G1CollectedHeap::print_on(outputStream* st, bool extended) const { 29.148 + st->print(" %-20s", "garbage-first heap"); 29.149 + st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", 29.150 + capacity()/K, used_unlocked()/K); 29.151 + st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", 29.152 + _g1_storage.low_boundary(), 29.153 + _g1_storage.high(), 29.154 + _g1_storage.high_boundary()); 29.155 + st->cr(); 29.156 + st->print(" region size " SIZE_FORMAT "K, ", 29.157 + HeapRegion::GrainBytes/K); 29.158 + size_t young_regions = _young_list->length(); 29.159 + st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ", 29.160 + young_regions, young_regions * HeapRegion::GrainBytes / K); 29.161 + size_t survivor_regions = g1_policy()->recorded_survivor_regions(); 29.162 + st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)", 29.163 + survivor_regions, survivor_regions * HeapRegion::GrainBytes / K); 29.164 + st->cr(); 29.165 + perm()->as_gen()->print_on(st); 29.166 + if (extended) { 29.167 + print_on_extended(st); 29.168 + } 29.169 +} 29.170 + 29.171 +void G1CollectedHeap::print_on_extended(outputStream* st) const { 29.172 PrintRegionClosure blk(st); 29.173 _hrs->iterate(&blk); 29.174 } 29.175 @@ -2408,10 +2456,6 @@ 29.176 } 29.177 29.178 void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { 29.179 - if (PrintHeapAtGC){ 29.180 - gclog_or_tty->print_cr(" {Heap before GC collections=%d:", total_collections()); 29.181 - Universe::print(); 29.182 - } 29.183 assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); 29.184 // Call allocation profiler 29.185 AllocationProfiler::iterate_since_last_gc(); 29.186 @@ -2425,12 +2469,6 @@ 29.187 // is set. 29.188 COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), 29.189 "derived pointer present")); 29.190 - 29.191 - if (PrintHeapAtGC){ 29.192 - gclog_or_tty->print_cr(" Heap after GC collections=%d:", total_collections()); 29.193 - Universe::print(); 29.194 - gclog_or_tty->print("} "); 29.195 - } 29.196 } 29.197 29.198 void G1CollectedHeap::do_collection_pause() { 29.199 @@ -2453,12 +2491,10 @@ 29.200 29.201 void 29.202 G1CollectedHeap::doConcurrentMark() { 29.203 - if (G1ConcMark) { 29.204 - MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); 29.205 - if (!_cmThread->in_progress()) { 29.206 - _cmThread->set_started(); 29.207 - CGC_lock->notify(); 29.208 - } 29.209 + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); 29.210 + if (!_cmThread->in_progress()) { 29.211 + _cmThread->set_started(); 29.212 + CGC_lock->notify(); 29.213 } 29.214 } 29.215 29.216 @@ -2535,9 +2571,11 @@ 29.217 "Not enough space for young surv words summary."); 29.218 } 29.219 memset(_surviving_young_words, 0, array_length * sizeof(size_t)); 29.220 +#ifdef ASSERT 29.221 for (size_t i = 0; i < array_length; ++i) { 29.222 - guarantee( _surviving_young_words[i] == 0, "invariant" ); 29.223 - } 29.224 + assert( _surviving_young_words[i] == 0, "memset above" ); 29.225 + } 29.226 +#endif // !ASSERT 29.227 } 29.228 29.229 void 29.230 @@ -2559,241 +2597,254 @@ 29.231 29.232 void 29.233 G1CollectedHeap::do_collection_pause_at_safepoint() { 29.234 - char verbose_str[128]; 29.235 - sprintf(verbose_str, "GC pause "); 29.236 - if (g1_policy()->in_young_gc_mode()) { 29.237 - if (g1_policy()->full_young_gcs()) 29.238 - strcat(verbose_str, "(young)"); 29.239 - else 29.240 - strcat(verbose_str, "(partial)"); 29.241 - } 29.242 - if (g1_policy()->should_initiate_conc_mark()) 29.243 - strcat(verbose_str, " (initial-mark)"); 29.244 - 29.245 - GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); 29.246 - 29.247 - // if PrintGCDetails is on, we'll print long statistics information 29.248 - // in the collector policy code, so let's not print this as the output 29.249 - // is messy if we do. 29.250 - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); 29.251 - TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 29.252 - TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); 29.253 - 29.254 - ResourceMark rm; 29.255 - assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); 29.256 - assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); 29.257 - guarantee(!is_gc_active(), "collection is not reentrant"); 29.258 - assert(regions_accounted_for(), "Region leakage!"); 29.259 - 29.260 - increment_gc_time_stamp(); 29.261 - 29.262 - if (g1_policy()->in_young_gc_mode()) { 29.263 - assert(check_young_list_well_formed(), 29.264 - "young list should be well formed"); 29.265 - } 29.266 - 29.267 - if (GC_locker::is_active()) { 29.268 - return; // GC is disabled (e.g. JNI GetXXXCritical operation) 29.269 - } 29.270 - 29.271 - bool abandoned = false; 29.272 - { // Call to jvmpi::post_class_unload_events must occur outside of active GC 29.273 - IsGCActiveMark x; 29.274 - 29.275 - gc_prologue(false); 29.276 - increment_total_collections(); 29.277 + if (PrintHeapAtGC) { 29.278 + Universe::print_heap_before_gc(); 29.279 + } 29.280 + 29.281 + { 29.282 + char verbose_str[128]; 29.283 + sprintf(verbose_str, "GC pause "); 29.284 + if (g1_policy()->in_young_gc_mode()) { 29.285 + if (g1_policy()->full_young_gcs()) 29.286 + strcat(verbose_str, "(young)"); 29.287 + else 29.288 + strcat(verbose_str, "(partial)"); 29.289 + } 29.290 + if (g1_policy()->should_initiate_conc_mark()) 29.291 + strcat(verbose_str, " (initial-mark)"); 29.292 + 29.293 + GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); 29.294 + 29.295 + // if PrintGCDetails is on, we'll print long statistics information 29.296 + // in the collector policy code, so let's not print this as the output 29.297 + // is messy if we do. 29.298 + gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); 29.299 + TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 29.300 + TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); 29.301 + 29.302 + ResourceMark rm; 29.303 + assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); 29.304 + assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); 29.305 + guarantee(!is_gc_active(), "collection is not reentrant"); 29.306 + assert(regions_accounted_for(), "Region leakage!"); 29.307 + 29.308 + increment_gc_time_stamp(); 29.309 + 29.310 + if (g1_policy()->in_young_gc_mode()) { 29.311 + assert(check_young_list_well_formed(), 29.312 + "young list should be well formed"); 29.313 + } 29.314 + 29.315 + if (GC_locker::is_active()) { 29.316 + return; // GC is disabled (e.g. JNI GetXXXCritical operation) 29.317 + } 29.318 + 29.319 + bool abandoned = false; 29.320 + { // Call to jvmpi::post_class_unload_events must occur outside of active GC 29.321 + IsGCActiveMark x; 29.322 + 29.323 + gc_prologue(false); 29.324 + increment_total_collections(false /* full gc */); 29.325 29.326 #if G1_REM_SET_LOGGING 29.327 - gclog_or_tty->print_cr("\nJust chose CS, heap:"); 29.328 - print(); 29.329 -#endif 29.330 - 29.331 - if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { 29.332 - HandleMark hm; // Discard invalid handles created during verification 29.333 - prepare_for_verify(); 29.334 - gclog_or_tty->print(" VerifyBeforeGC:"); 29.335 - Universe::verify(false); 29.336 - } 29.337 - 29.338 - COMPILER2_PRESENT(DerivedPointerTable::clear()); 29.339 - 29.340 - // We want to turn off ref discovery, if necessary, and turn it back on 29.341 - // on again later if we do. 29.342 - bool was_enabled = ref_processor()->discovery_enabled(); 29.343 - if (was_enabled) ref_processor()->disable_discovery(); 29.344 - 29.345 - // Forget the current alloc region (we might even choose it to be part 29.346 - // of the collection set!). 29.347 - abandon_cur_alloc_region(); 29.348 - 29.349 - // The elapsed time induced by the start time below deliberately elides 29.350 - // the possible verification above. 29.351 - double start_time_sec = os::elapsedTime(); 29.352 - GCOverheadReporter::recordSTWStart(start_time_sec); 29.353 - size_t start_used_bytes = used(); 29.354 - if (!G1ConcMark) { 29.355 - do_sync_mark(); 29.356 - } 29.357 - 29.358 - g1_policy()->record_collection_pause_start(start_time_sec, 29.359 - start_used_bytes); 29.360 - 29.361 - guarantee(_in_cset_fast_test == NULL, "invariant"); 29.362 - guarantee(_in_cset_fast_test_base == NULL, "invariant"); 29.363 - _in_cset_fast_test_length = max_regions(); 29.364 - _in_cset_fast_test_base = 29.365 - NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); 29.366 - memset(_in_cset_fast_test_base, false, 29.367 - _in_cset_fast_test_length * sizeof(bool)); 29.368 - // We're biasing _in_cset_fast_test to avoid subtracting the 29.369 - // beginning of the heap every time we want to index; basically 29.370 - // it's the same with what we do with the card table. 29.371 - _in_cset_fast_test = _in_cset_fast_test_base - 29.372 - ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); 29.373 - 29.374 -#if SCAN_ONLY_VERBOSE 29.375 - _young_list->print(); 29.376 -#endif // SCAN_ONLY_VERBOSE 29.377 - 29.378 - if (g1_policy()->should_initiate_conc_mark()) { 29.379 - concurrent_mark()->checkpointRootsInitialPre(); 29.380 - } 29.381 - save_marks(); 29.382 - 29.383 - // We must do this before any possible evacuation that should propagate 29.384 - // marks. 29.385 - if (mark_in_progress()) { 29.386 - double start_time_sec = os::elapsedTime(); 29.387 - 29.388 - _cm->drainAllSATBBuffers(); 29.389 - double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; 29.390 - g1_policy()->record_satb_drain_time(finish_mark_ms); 29.391 - 29.392 - } 29.393 - // Record the number of elements currently on the mark stack, so we 29.394 - // only iterate over these. (Since evacuation may add to the mark 29.395 - // stack, doing more exposes race conditions.) If no mark is in 29.396 - // progress, this will be zero. 29.397 - _cm->set_oops_do_bound(); 29.398 - 29.399 - assert(regions_accounted_for(), "Region leakage."); 29.400 - 29.401 - if (mark_in_progress()) 29.402 - concurrent_mark()->newCSet(); 29.403 - 29.404 - // Now choose the CS. 29.405 - g1_policy()->choose_collection_set(); 29.406 - 29.407 - // We may abandon a pause if we find no region that will fit in the MMU 29.408 - // pause. 29.409 - bool abandoned = (g1_policy()->collection_set() == NULL); 29.410 - 29.411 - // Nothing to do if we were unable to choose a collection set. 29.412 - if (!abandoned) { 29.413 -#if G1_REM_SET_LOGGING 29.414 - gclog_or_tty->print_cr("\nAfter pause, heap:"); 29.415 + gclog_or_tty->print_cr("\nJust chose CS, heap:"); 29.416 print(); 29.417 #endif 29.418 29.419 - setup_surviving_young_words(); 29.420 - 29.421 - // Set up the gc allocation regions. 29.422 - get_gc_alloc_regions(); 29.423 - 29.424 - // Actually do the work... 29.425 - evacuate_collection_set(); 29.426 - free_collection_set(g1_policy()->collection_set()); 29.427 - g1_policy()->clear_collection_set(); 29.428 - 29.429 - FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); 29.430 - // this is more for peace of mind; we're nulling them here and 29.431 - // we're expecting them to be null at the beginning of the next GC 29.432 - _in_cset_fast_test = NULL; 29.433 - _in_cset_fast_test_base = NULL; 29.434 - 29.435 - release_gc_alloc_regions(false /* totally */); 29.436 - 29.437 - cleanup_surviving_young_words(); 29.438 - 29.439 - if (g1_policy()->in_young_gc_mode()) { 29.440 - _young_list->reset_sampled_info(); 29.441 - assert(check_young_list_empty(true), 29.442 - "young list should be empty"); 29.443 + if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { 29.444 + HandleMark hm; // Discard invalid handles created during verification 29.445 + prepare_for_verify(); 29.446 + gclog_or_tty->print(" VerifyBeforeGC:"); 29.447 + Universe::verify(false); 29.448 + } 29.449 + 29.450 + COMPILER2_PRESENT(DerivedPointerTable::clear()); 29.451 + 29.452 + // We want to turn off ref discovery, if necessary, and turn it back on 29.453 + // on again later if we do. XXX Dubious: why is discovery disabled? 29.454 + bool was_enabled = ref_processor()->discovery_enabled(); 29.455 + if (was_enabled) ref_processor()->disable_discovery(); 29.456 + 29.457 + // Forget the current alloc region (we might even choose it to be part 29.458 + // of the collection set!). 29.459 + abandon_cur_alloc_region(); 29.460 + 29.461 + // The elapsed time induced by the start time below deliberately elides 29.462 + // the possible verification above. 29.463 + double start_time_sec = os::elapsedTime(); 29.464 + GCOverheadReporter::recordSTWStart(start_time_sec); 29.465 + size_t start_used_bytes = used(); 29.466 + 29.467 + g1_policy()->record_collection_pause_start(start_time_sec, 29.468 + start_used_bytes); 29.469 + 29.470 + guarantee(_in_cset_fast_test == NULL, "invariant"); 29.471 + guarantee(_in_cset_fast_test_base == NULL, "invariant"); 29.472 + _in_cset_fast_test_length = max_regions(); 29.473 + _in_cset_fast_test_base = 29.474 + NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); 29.475 + memset(_in_cset_fast_test_base, false, 29.476 + _in_cset_fast_test_length * sizeof(bool)); 29.477 + // We're biasing _in_cset_fast_test to avoid subtracting the 29.478 + // beginning of the heap every time we want to index; basically 29.479 + // it's the same with what we do with the card table. 29.480 + _in_cset_fast_test = _in_cset_fast_test_base - 29.481 + ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); 29.482 29.483 #if SCAN_ONLY_VERBOSE 29.484 - _young_list->print(); 29.485 + _young_list->print(); 29.486 #endif // SCAN_ONLY_VERBOSE 29.487 29.488 - g1_policy()->record_survivor_regions(_young_list->survivor_length(), 29.489 - _young_list->first_survivor_region(), 29.490 - _young_list->last_survivor_region()); 29.491 - _young_list->reset_auxilary_lists(); 29.492 + if (g1_policy()->should_initiate_conc_mark()) { 29.493 + concurrent_mark()->checkpointRootsInitialPre(); 29.494 } 29.495 - } else { 29.496 - COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); 29.497 + save_marks(); 29.498 + 29.499 + // We must do this before any possible evacuation that should propagate 29.500 + // marks. 29.501 + if (mark_in_progress()) { 29.502 + double start_time_sec = os::elapsedTime(); 29.503 + 29.504 + _cm->drainAllSATBBuffers(); 29.505 + double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; 29.506 + g1_policy()->record_satb_drain_time(finish_mark_ms); 29.507 + } 29.508 + // Record the number of elements currently on the mark stack, so we 29.509 + // only iterate over these. (Since evacuation may add to the mark 29.510 + // stack, doing more exposes race conditions.) If no mark is in 29.511 + // progress, this will be zero. 29.512 + _cm->set_oops_do_bound(); 29.513 + 29.514 + assert(regions_accounted_for(), "Region leakage."); 29.515 + 29.516 + if (mark_in_progress()) 29.517 + concurrent_mark()->newCSet(); 29.518 + 29.519 + // Now choose the CS. 29.520 + g1_policy()->choose_collection_set(); 29.521 + 29.522 + // We may abandon a pause if we find no region that will fit in the MMU 29.523 + // pause. 29.524 + bool abandoned = (g1_policy()->collection_set() == NULL); 29.525 + 29.526 + // Nothing to do if we were unable to choose a collection set. 29.527 + if (!abandoned) { 29.528 +#if G1_REM_SET_LOGGING 29.529 + gclog_or_tty->print_cr("\nAfter pause, heap:"); 29.530 + print(); 29.531 +#endif 29.532 + 29.533 + setup_surviving_young_words(); 29.534 + 29.535 + // Set up the gc allocation regions. 29.536 + get_gc_alloc_regions(); 29.537 + 29.538 + // Actually do the work... 29.539 + evacuate_collection_set(); 29.540 + free_collection_set(g1_policy()->collection_set()); 29.541 + g1_policy()->clear_collection_set(); 29.542 + 29.543 + FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); 29.544 + // this is more for peace of mind; we're nulling them here and 29.545 + // we're expecting them to be null at the beginning of the next GC 29.546 + _in_cset_fast_test = NULL; 29.547 + _in_cset_fast_test_base = NULL; 29.548 + 29.549 + release_gc_alloc_regions(false /* totally */); 29.550 + 29.551 + cleanup_surviving_young_words(); 29.552 + 29.553 + if (g1_policy()->in_young_gc_mode()) { 29.554 + _young_list->reset_sampled_info(); 29.555 + assert(check_young_list_empty(true), 29.556 + "young list should be empty"); 29.557 + 29.558 +#if SCAN_ONLY_VERBOSE 29.559 + _young_list->print(); 29.560 +#endif // SCAN_ONLY_VERBOSE 29.561 + 29.562 + g1_policy()->record_survivor_regions(_young_list->survivor_length(), 29.563 + _young_list->first_survivor_region(), 29.564 + _young_list->last_survivor_region()); 29.565 + _young_list->reset_auxilary_lists(); 29.566 + } 29.567 + } else { 29.568 + COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); 29.569 + } 29.570 + 29.571 + if (evacuation_failed()) { 29.572 + _summary_bytes_used = recalculate_used(); 29.573 + } else { 29.574 + // The "used" of the the collection set have already been subtracted 29.575 + // when they were freed. Add in the bytes evacuated. 29.576 + _summary_bytes_used += g1_policy()->bytes_in_to_space(); 29.577 + } 29.578 + 29.579 + if (g1_policy()->in_young_gc_mode() && 29.580 + g1_policy()->should_initiate_conc_mark()) { 29.581 + concurrent_mark()->checkpointRootsInitialPost(); 29.582 + set_marking_started(); 29.583 + // CAUTION: after the doConcurrentMark() call below, 29.584 + // the concurrent marking thread(s) could be running 29.585 + // concurrently with us. Make sure that anything after 29.586 + // this point does not assume that we are the only GC thread 29.587 + // running. Note: of course, the actual marking work will 29.588 + // not start until the safepoint itself is released in 29.589 + // ConcurrentGCThread::safepoint_desynchronize(). 29.590 + doConcurrentMark(); 29.591 + } 29.592 + 29.593 +#if SCAN_ONLY_VERBOSE 29.594 + _young_list->print(); 29.595 +#endif // SCAN_ONLY_VERBOSE 29.596 + 29.597 + double end_time_sec = os::elapsedTime(); 29.598 + double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; 29.599 + g1_policy()->record_pause_time_ms(pause_time_ms); 29.600 + GCOverheadReporter::recordSTWEnd(end_time_sec); 29.601 + g1_policy()->record_collection_pause_end(abandoned); 29.602 + 29.603 + assert(regions_accounted_for(), "Region leakage."); 29.604 + 29.605 + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { 29.606 + HandleMark hm; // Discard invalid handles created during verification 29.607 + gclog_or_tty->print(" VerifyAfterGC:"); 29.608 + prepare_for_verify(); 29.609 + Universe::verify(false); 29.610 + } 29.611 + 29.612 + if (was_enabled) ref_processor()->enable_discovery(); 29.613 + 29.614 + { 29.615 + size_t expand_bytes = g1_policy()->expansion_amount(); 29.616 + if (expand_bytes > 0) { 29.617 + size_t bytes_before = capacity(); 29.618 + expand(expand_bytes); 29.619 + } 29.620 + } 29.621 + 29.622 + if (mark_in_progress()) { 29.623 + concurrent_mark()->update_g1_committed(); 29.624 + } 29.625 + 29.626 +#ifdef TRACESPINNING 29.627 + ParallelTaskTerminator::print_termination_counts(); 29.628 +#endif 29.629 + 29.630 + gc_epilogue(false); 29.631 } 29.632 29.633 - if (evacuation_failed()) { 29.634 - _summary_bytes_used = recalculate_used(); 29.635 - } else { 29.636 - // The "used" of the the collection set have already been subtracted 29.637 - // when they were freed. Add in the bytes evacuated. 29.638 - _summary_bytes_used += g1_policy()->bytes_in_to_space(); 29.639 + assert(verify_region_lists(), "Bad region lists."); 29.640 + 29.641 + if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { 29.642 + gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); 29.643 + print_tracing_info(); 29.644 + vm_exit(-1); 29.645 } 29.646 - 29.647 - if (g1_policy()->in_young_gc_mode() && 29.648 - g1_policy()->should_initiate_conc_mark()) { 29.649 - concurrent_mark()->checkpointRootsInitialPost(); 29.650 - set_marking_started(); 29.651 - doConcurrentMark(); 29.652 - } 29.653 - 29.654 -#if SCAN_ONLY_VERBOSE 29.655 - _young_list->print(); 29.656 -#endif // SCAN_ONLY_VERBOSE 29.657 - 29.658 - double end_time_sec = os::elapsedTime(); 29.659 - double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; 29.660 - g1_policy()->record_pause_time_ms(pause_time_ms); 29.661 - GCOverheadReporter::recordSTWEnd(end_time_sec); 29.662 - g1_policy()->record_collection_pause_end(abandoned); 29.663 - 29.664 - assert(regions_accounted_for(), "Region leakage."); 29.665 - 29.666 - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { 29.667 - HandleMark hm; // Discard invalid handles created during verification 29.668 - gclog_or_tty->print(" VerifyAfterGC:"); 29.669 - prepare_for_verify(); 29.670 - Universe::verify(false); 29.671 - } 29.672 - 29.673 - if (was_enabled) ref_processor()->enable_discovery(); 29.674 - 29.675 - { 29.676 - size_t expand_bytes = g1_policy()->expansion_amount(); 29.677 - if (expand_bytes > 0) { 29.678 - size_t bytes_before = capacity(); 29.679 - expand(expand_bytes); 29.680 - } 29.681 - } 29.682 - 29.683 - if (mark_in_progress()) { 29.684 - concurrent_mark()->update_g1_committed(); 29.685 - } 29.686 - 29.687 -#ifdef TRACESPINNING 29.688 - ParallelTaskTerminator::print_termination_counts(); 29.689 -#endif 29.690 - 29.691 - gc_epilogue(false); 29.692 - } 29.693 - 29.694 - assert(verify_region_lists(), "Bad region lists."); 29.695 - 29.696 - if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { 29.697 - gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); 29.698 - print_tracing_info(); 29.699 - vm_exit(-1); 29.700 + } 29.701 + 29.702 + if (PrintHeapAtGC) { 29.703 + Universe::print_heap_after_gc(); 29.704 } 29.705 } 29.706 29.707 @@ -3088,10 +3139,8 @@ 29.708 G1CollectedHeap* _g1; 29.709 public: 29.710 G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} 29.711 - void do_oop(narrowOop* p) { 29.712 - guarantee(false, "NYI"); 29.713 - } 29.714 - void do_oop(oop* p) { 29.715 + void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } 29.716 + void do_oop( oop* p) { 29.717 oop obj = *p; 29.718 #ifdef G1_DEBUG 29.719 if (PrintGC && Verbose) { 29.720 @@ -3103,7 +3152,6 @@ 29.721 if (_g1->obj_in_cs(obj)) { 29.722 assert( obj->is_forwarded(), "invariant" ); 29.723 *p = obj->forwardee(); 29.724 - 29.725 #ifdef G1_DEBUG 29.726 gclog_or_tty->print_cr(" in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT, 29.727 (void*) obj, (void*) *p); 29.728 @@ -3120,12 +3168,12 @@ 29.729 UpdateRSetImmediate(G1CollectedHeap* g1) : 29.730 _g1(g1), _g1_rem_set(g1->g1_rem_set()) {} 29.731 29.732 - void do_oop(narrowOop* p) { 29.733 - guarantee(false, "NYI"); 29.734 - } 29.735 - void do_oop(oop* p) { 29.736 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 29.737 + virtual void do_oop( oop* p) { do_oop_work(p); } 29.738 + template <class T> void do_oop_work(T* p) { 29.739 assert(_from->is_in_reserved(p), "paranoia"); 29.740 - if (*p != NULL && !_from->is_survivor()) { 29.741 + T heap_oop = oopDesc::load_heap_oop(p); 29.742 + if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) { 29.743 _g1_rem_set->par_write_ref(_from, p, 0); 29.744 } 29.745 } 29.746 @@ -3141,12 +3189,12 @@ 29.747 UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : 29.748 _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {} 29.749 29.750 - void do_oop(narrowOop* p) { 29.751 - guarantee(false, "NYI"); 29.752 - } 29.753 - void do_oop(oop* p) { 29.754 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 29.755 + virtual void do_oop( oop* p) { do_oop_work(p); } 29.756 + template <class T> void do_oop_work(T* p) { 29.757 assert(_from->is_in_reserved(p), "paranoia"); 29.758 - if (!_from->is_in_reserved(*p) && !_from->is_survivor()) { 29.759 + if (!_from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && 29.760 + !_from->is_survivor()) { 29.761 size_t card_index = _ct_bs->index_for(p); 29.762 if (_ct_bs->mark_card_deferred(card_index)) { 29.763 _dcq->enqueue((jbyte*)_ct_bs->byte_for_index(card_index)); 29.764 @@ -3501,614 +3549,66 @@ 29.765 fill_with_object(block, free_words); 29.766 } 29.767 29.768 -#define use_local_bitmaps 1 29.769 -#define verify_local_bitmaps 0 29.770 - 29.771 #ifndef PRODUCT 29.772 - 29.773 -class GCLabBitMap; 29.774 -class GCLabBitMapClosure: public BitMapClosure { 29.775 -private: 29.776 - ConcurrentMark* _cm; 29.777 - GCLabBitMap* _bitmap; 29.778 - 29.779 -public: 29.780 - GCLabBitMapClosure(ConcurrentMark* cm, 29.781 - GCLabBitMap* bitmap) { 29.782 - _cm = cm; 29.783 - _bitmap = bitmap; 29.784 - } 29.785 - 29.786 - virtual bool do_bit(size_t offset); 29.787 -}; 29.788 - 29.789 -#endif // PRODUCT 29.790 - 29.791 -#define oop_buffer_length 256 29.792 - 29.793 -class GCLabBitMap: public BitMap { 29.794 -private: 29.795 - ConcurrentMark* _cm; 29.796 - 29.797 - int _shifter; 29.798 - size_t _bitmap_word_covers_words; 29.799 - 29.800 - // beginning of the heap 29.801 - HeapWord* _heap_start; 29.802 - 29.803 - // this is the actual start of the GCLab 29.804 - HeapWord* _real_start_word; 29.805 - 29.806 - // this is the actual end of the GCLab 29.807 - HeapWord* _real_end_word; 29.808 - 29.809 - // this is the first word, possibly located before the actual start 29.810 - // of the GCLab, that corresponds to the first bit of the bitmap 29.811 - HeapWord* _start_word; 29.812 - 29.813 - // size of a GCLab in words 29.814 - size_t _gclab_word_size; 29.815 - 29.816 - static int shifter() { 29.817 - return MinObjAlignment - 1; 29.818 - } 29.819 - 29.820 - // how many heap words does a single bitmap word corresponds to? 29.821 - static size_t bitmap_word_covers_words() { 29.822 - return BitsPerWord << shifter(); 29.823 - } 29.824 - 29.825 - static size_t gclab_word_size() { 29.826 - return G1ParallelGCAllocBufferSize / HeapWordSize; 29.827 - } 29.828 - 29.829 - static size_t bitmap_size_in_bits() { 29.830 - size_t bits_in_bitmap = gclab_word_size() >> shifter(); 29.831 - // We are going to ensure that the beginning of a word in this 29.832 - // bitmap also corresponds to the beginning of a word in the 29.833 - // global marking bitmap. To handle the case where a GCLab 29.834 - // starts from the middle of the bitmap, we need to add enough 29.835 - // space (i.e. up to a bitmap word) to ensure that we have 29.836 - // enough bits in the bitmap. 29.837 - return bits_in_bitmap + BitsPerWord - 1; 29.838 - } 29.839 -public: 29.840 - GCLabBitMap(HeapWord* heap_start) 29.841 - : BitMap(bitmap_size_in_bits()), 29.842 - _cm(G1CollectedHeap::heap()->concurrent_mark()), 29.843 - _shifter(shifter()), 29.844 - _bitmap_word_covers_words(bitmap_word_covers_words()), 29.845 - _heap_start(heap_start), 29.846 - _gclab_word_size(gclab_word_size()), 29.847 - _real_start_word(NULL), 29.848 - _real_end_word(NULL), 29.849 - _start_word(NULL) 29.850 - { 29.851 - guarantee( size_in_words() >= bitmap_size_in_words(), 29.852 - "just making sure"); 29.853 - } 29.854 - 29.855 - inline unsigned heapWordToOffset(HeapWord* addr) { 29.856 - unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter; 29.857 - assert(offset < size(), "offset should be within bounds"); 29.858 - return offset; 29.859 - } 29.860 - 29.861 - inline HeapWord* offsetToHeapWord(size_t offset) { 29.862 - HeapWord* addr = _start_word + (offset << _shifter); 29.863 - assert(_real_start_word <= addr && addr < _real_end_word, "invariant"); 29.864 - return addr; 29.865 - } 29.866 - 29.867 - bool fields_well_formed() { 29.868 - bool ret1 = (_real_start_word == NULL) && 29.869 - (_real_end_word == NULL) && 29.870 - (_start_word == NULL); 29.871 - if (ret1) 29.872 - return true; 29.873 - 29.874 - bool ret2 = _real_start_word >= _start_word && 29.875 - _start_word < _real_end_word && 29.876 - (_real_start_word + _gclab_word_size) == _real_end_word && 29.877 - (_start_word + _gclab_word_size + _bitmap_word_covers_words) 29.878 - > _real_end_word; 29.879 - return ret2; 29.880 - } 29.881 - 29.882 - inline bool mark(HeapWord* addr) { 29.883 - guarantee(use_local_bitmaps, "invariant"); 29.884 - assert(fields_well_formed(), "invariant"); 29.885 - 29.886 - if (addr >= _real_start_word && addr < _real_end_word) { 29.887 - assert(!isMarked(addr), "should not have already been marked"); 29.888 - 29.889 - // first mark it on the bitmap 29.890 - at_put(heapWordToOffset(addr), true); 29.891 - 29.892 - return true; 29.893 - } else { 29.894 - return false; 29.895 - } 29.896 - } 29.897 - 29.898 - inline bool isMarked(HeapWord* addr) { 29.899 - guarantee(use_local_bitmaps, "invariant"); 29.900 - assert(fields_well_formed(), "invariant"); 29.901 - 29.902 - return at(heapWordToOffset(addr)); 29.903 - } 29.904 - 29.905 - void set_buffer(HeapWord* start) { 29.906 - guarantee(use_local_bitmaps, "invariant"); 29.907 - clear(); 29.908 - 29.909 - assert(start != NULL, "invariant"); 29.910 - _real_start_word = start; 29.911 - _real_end_word = start + _gclab_word_size; 29.912 - 29.913 - size_t diff = 29.914 - pointer_delta(start, _heap_start) % _bitmap_word_covers_words; 29.915 - _start_word = start - diff; 29.916 - 29.917 - assert(fields_well_formed(), "invariant"); 29.918 - } 29.919 - 29.920 -#ifndef PRODUCT 29.921 - void verify() { 29.922 - // verify that the marks have been propagated 29.923 - GCLabBitMapClosure cl(_cm, this); 29.924 - iterate(&cl); 29.925 - } 29.926 -#endif // PRODUCT 29.927 - 29.928 - void retire() { 29.929 - guarantee(use_local_bitmaps, "invariant"); 29.930 - assert(fields_well_formed(), "invariant"); 29.931 - 29.932 - if (_start_word != NULL) { 29.933 - CMBitMap* mark_bitmap = _cm->nextMarkBitMap(); 29.934 - 29.935 - // this means that the bitmap was set up for the GCLab 29.936 - assert(_real_start_word != NULL && _real_end_word != NULL, "invariant"); 29.937 - 29.938 - mark_bitmap->mostly_disjoint_range_union(this, 29.939 - 0, // always start from the start of the bitmap 29.940 - _start_word, 29.941 - size_in_words()); 29.942 - _cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word)); 29.943 - 29.944 -#ifndef PRODUCT 29.945 - if (use_local_bitmaps && verify_local_bitmaps) 29.946 - verify(); 29.947 -#endif // PRODUCT 29.948 - } else { 29.949 - assert(_real_start_word == NULL && _real_end_word == NULL, "invariant"); 29.950 - } 29.951 - } 29.952 - 29.953 - static size_t bitmap_size_in_words() { 29.954 - return (bitmap_size_in_bits() + BitsPerWord - 1) / BitsPerWord; 29.955 - } 29.956 -}; 29.957 - 29.958 -#ifndef PRODUCT 29.959 - 29.960 bool GCLabBitMapClosure::do_bit(size_t offset) { 29.961 HeapWord* addr = _bitmap->offsetToHeapWord(offset); 29.962 guarantee(_cm->isMarked(oop(addr)), "it should be!"); 29.963 return true; 29.964 } 29.965 - 29.966 #endif // PRODUCT 29.967 29.968 -class G1ParGCAllocBuffer: public ParGCAllocBuffer { 29.969 -private: 29.970 - bool _retired; 29.971 - bool _during_marking; 29.972 - GCLabBitMap _bitmap; 29.973 - 29.974 -public: 29.975 - G1ParGCAllocBuffer() : 29.976 - ParGCAllocBuffer(G1ParallelGCAllocBufferSize / HeapWordSize), 29.977 - _during_marking(G1CollectedHeap::heap()->mark_in_progress()), 29.978 - _bitmap(G1CollectedHeap::heap()->reserved_region().start()), 29.979 - _retired(false) 29.980 - { } 29.981 - 29.982 - inline bool mark(HeapWord* addr) { 29.983 - guarantee(use_local_bitmaps, "invariant"); 29.984 - assert(_during_marking, "invariant"); 29.985 - return _bitmap.mark(addr); 29.986 - } 29.987 - 29.988 - inline void set_buf(HeapWord* buf) { 29.989 - if (use_local_bitmaps && _during_marking) 29.990 - _bitmap.set_buffer(buf); 29.991 - ParGCAllocBuffer::set_buf(buf); 29.992 - _retired = false; 29.993 - } 29.994 - 29.995 - inline void retire(bool end_of_gc, bool retain) { 29.996 - if (_retired) 29.997 - return; 29.998 - if (use_local_bitmaps && _during_marking) { 29.999 - _bitmap.retire(); 29.1000 - } 29.1001 - ParGCAllocBuffer::retire(end_of_gc, retain); 29.1002 - _retired = true; 29.1003 - } 29.1004 -}; 29.1005 - 29.1006 - 29.1007 -class G1ParScanThreadState : public StackObj { 29.1008 -protected: 29.1009 - G1CollectedHeap* _g1h; 29.1010 - RefToScanQueue* _refs; 29.1011 - DirtyCardQueue _dcq; 29.1012 - CardTableModRefBS* _ct_bs; 29.1013 - G1RemSet* _g1_rem; 29.1014 - 29.1015 - typedef GrowableArray<oop*> OverflowQueue; 29.1016 - OverflowQueue* _overflowed_refs; 29.1017 - 29.1018 - G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount]; 29.1019 - ageTable _age_table; 29.1020 - 29.1021 - size_t _alloc_buffer_waste; 29.1022 - size_t _undo_waste; 29.1023 - 29.1024 - OopsInHeapRegionClosure* _evac_failure_cl; 29.1025 - G1ParScanHeapEvacClosure* _evac_cl; 29.1026 - G1ParScanPartialArrayClosure* _partial_scan_cl; 29.1027 - 29.1028 - int _hash_seed; 29.1029 - int _queue_num; 29.1030 - 29.1031 - int _term_attempts; 29.1032 +G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) 29.1033 + : _g1h(g1h), 29.1034 + _refs(g1h->task_queue(queue_num)), 29.1035 + _dcq(&g1h->dirty_card_queue_set()), 29.1036 + _ct_bs((CardTableModRefBS*)_g1h->barrier_set()), 29.1037 + _g1_rem(g1h->g1_rem_set()), 29.1038 + _hash_seed(17), _queue_num(queue_num), 29.1039 + _term_attempts(0), 29.1040 + _age_table(false), 29.1041 #if G1_DETAILED_STATS 29.1042 - int _pushes, _pops, _steals, _steal_attempts; 29.1043 - int _overflow_pushes; 29.1044 + _pushes(0), _pops(0), _steals(0), 29.1045 + _steal_attempts(0), _overflow_pushes(0), 29.1046 #endif 29.1047 - 29.1048 - double _start; 29.1049 - double _start_strong_roots; 29.1050 - double _strong_roots_time; 29.1051 - double _start_term; 29.1052 - double _term_time; 29.1053 - 29.1054 - // Map from young-age-index (0 == not young, 1 is youngest) to 29.1055 - // surviving words. base is what we get back from the malloc call 29.1056 - size_t* _surviving_young_words_base; 29.1057 - // this points into the array, as we use the first few entries for padding 29.1058 - size_t* _surviving_young_words; 29.1059 - 29.1060 -#define PADDING_ELEM_NUM (64 / sizeof(size_t)) 29.1061 - 29.1062 - void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } 29.1063 - 29.1064 - void add_to_undo_waste(size_t waste) { _undo_waste += waste; } 29.1065 - 29.1066 - DirtyCardQueue& dirty_card_queue() { return _dcq; } 29.1067 - CardTableModRefBS* ctbs() { return _ct_bs; } 29.1068 - 29.1069 - void immediate_rs_update(HeapRegion* from, oop* p, int tid) { 29.1070 - if (!from->is_survivor()) { 29.1071 - _g1_rem->par_write_ref(from, p, tid); 29.1072 - } 29.1073 - } 29.1074 - 29.1075 - void deferred_rs_update(HeapRegion* from, oop* p, int tid) { 29.1076 - // If the new value of the field points to the same region or 29.1077 - // is the to-space, we don't need to include it in the Rset updates. 29.1078 - if (!from->is_in_reserved(*p) && !from->is_survivor()) { 29.1079 - size_t card_index = ctbs()->index_for(p); 29.1080 - // If the card hasn't been added to the buffer, do it. 29.1081 - if (ctbs()->mark_card_deferred(card_index)) { 29.1082 - dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index)); 29.1083 - } 29.1084 - } 29.1085 - } 29.1086 - 29.1087 -public: 29.1088 - G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) 29.1089 - : _g1h(g1h), 29.1090 - _refs(g1h->task_queue(queue_num)), 29.1091 - _dcq(&g1h->dirty_card_queue_set()), 29.1092 - _ct_bs((CardTableModRefBS*)_g1h->barrier_set()), 29.1093 - _g1_rem(g1h->g1_rem_set()), 29.1094 - _hash_seed(17), _queue_num(queue_num), 29.1095 - _term_attempts(0), 29.1096 - _age_table(false), 29.1097 -#if G1_DETAILED_STATS 29.1098 - _pushes(0), _pops(0), _steals(0), 29.1099 - _steal_attempts(0), _overflow_pushes(0), 29.1100 -#endif 29.1101 - _strong_roots_time(0), _term_time(0), 29.1102 - _alloc_buffer_waste(0), _undo_waste(0) 29.1103 - { 29.1104 - // we allocate G1YoungSurvRateNumRegions plus one entries, since 29.1105 - // we "sacrifice" entry 0 to keep track of surviving bytes for 29.1106 - // non-young regions (where the age is -1) 29.1107 - // We also add a few elements at the beginning and at the end in 29.1108 - // an attempt to eliminate cache contention 29.1109 - size_t real_length = 1 + _g1h->g1_policy()->young_cset_length(); 29.1110 - size_t array_length = PADDING_ELEM_NUM + 29.1111 - real_length + 29.1112 - PADDING_ELEM_NUM; 29.1113 - _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length); 29.1114 - if (_surviving_young_words_base == NULL) 29.1115 - vm_exit_out_of_memory(array_length * sizeof(size_t), 29.1116 - "Not enough space for young surv histo."); 29.1117 - _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; 29.1118 - memset(_surviving_young_words, 0, real_length * sizeof(size_t)); 29.1119 - 29.1120 - _overflowed_refs = new OverflowQueue(10); 29.1121 - 29.1122 - _start = os::elapsedTime(); 29.1123 - } 29.1124 - 29.1125 - ~G1ParScanThreadState() { 29.1126 - FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); 29.1127 - } 29.1128 - 29.1129 - RefToScanQueue* refs() { return _refs; } 29.1130 - OverflowQueue* overflowed_refs() { return _overflowed_refs; } 29.1131 - ageTable* age_table() { return &_age_table; } 29.1132 - 29.1133 - G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 29.1134 - return &_alloc_buffers[purpose]; 29.1135 - } 29.1136 - 29.1137 - size_t alloc_buffer_waste() { return _alloc_buffer_waste; } 29.1138 - size_t undo_waste() { return _undo_waste; } 29.1139 - 29.1140 - void push_on_queue(oop* ref) { 29.1141 - assert(ref != NULL, "invariant"); 29.1142 - assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), "invariant"); 29.1143 - 29.1144 - if (!refs()->push(ref)) { 29.1145 - overflowed_refs()->push(ref); 29.1146 - IF_G1_DETAILED_STATS(note_overflow_push()); 29.1147 - } else { 29.1148 - IF_G1_DETAILED_STATS(note_push()); 29.1149 - } 29.1150 - } 29.1151 - 29.1152 - void pop_from_queue(oop*& ref) { 29.1153 - if (!refs()->pop_local(ref)) { 29.1154 - ref = NULL; 29.1155 - } else { 29.1156 - assert(ref != NULL, "invariant"); 29.1157 - assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), 29.1158 - "invariant"); 29.1159 - 29.1160 - IF_G1_DETAILED_STATS(note_pop()); 29.1161 - } 29.1162 - } 29.1163 - 29.1164 - void pop_from_overflow_queue(oop*& ref) { 29.1165 - ref = overflowed_refs()->pop(); 29.1166 - } 29.1167 - 29.1168 - int refs_to_scan() { return refs()->size(); } 29.1169 - int overflowed_refs_to_scan() { return overflowed_refs()->length(); } 29.1170 - 29.1171 - void update_rs(HeapRegion* from, oop* p, int tid) { 29.1172 - if (G1DeferredRSUpdate) { 29.1173 - deferred_rs_update(from, p, tid); 29.1174 - } else { 29.1175 - immediate_rs_update(from, p, tid); 29.1176 - } 29.1177 - } 29.1178 - 29.1179 - HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) { 29.1180 - 29.1181 - HeapWord* obj = NULL; 29.1182 - if (word_sz * 100 < 29.1183 - (size_t)(G1ParallelGCAllocBufferSize / HeapWordSize) * 29.1184 - ParallelGCBufferWastePct) { 29.1185 - G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); 29.1186 - add_to_alloc_buffer_waste(alloc_buf->words_remaining()); 29.1187 - alloc_buf->retire(false, false); 29.1188 - 29.1189 - HeapWord* buf = 29.1190 - _g1h->par_allocate_during_gc(purpose, G1ParallelGCAllocBufferSize / HeapWordSize); 29.1191 - if (buf == NULL) return NULL; // Let caller handle allocation failure. 29.1192 - // Otherwise. 29.1193 - alloc_buf->set_buf(buf); 29.1194 - 29.1195 - obj = alloc_buf->allocate(word_sz); 29.1196 - assert(obj != NULL, "buffer was definitely big enough..."); 29.1197 - } else { 29.1198 - obj = _g1h->par_allocate_during_gc(purpose, word_sz); 29.1199 - } 29.1200 - return obj; 29.1201 - } 29.1202 - 29.1203 - HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) { 29.1204 - HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz); 29.1205 - if (obj != NULL) return obj; 29.1206 - return allocate_slow(purpose, word_sz); 29.1207 - } 29.1208 - 29.1209 - void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) { 29.1210 - if (alloc_buffer(purpose)->contains(obj)) { 29.1211 - guarantee(alloc_buffer(purpose)->contains(obj + word_sz - 1), 29.1212 - "should contain whole object"); 29.1213 - alloc_buffer(purpose)->undo_allocation(obj, word_sz); 29.1214 - } else { 29.1215 - CollectedHeap::fill_with_object(obj, word_sz); 29.1216 - add_to_undo_waste(word_sz); 29.1217 - } 29.1218 - } 29.1219 - 29.1220 - void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) { 29.1221 - _evac_failure_cl = evac_failure_cl; 29.1222 - } 29.1223 - OopsInHeapRegionClosure* evac_failure_closure() { 29.1224 - return _evac_failure_cl; 29.1225 - } 29.1226 - 29.1227 - void set_evac_closure(G1ParScanHeapEvacClosure* evac_cl) { 29.1228 - _evac_cl = evac_cl; 29.1229 - } 29.1230 - 29.1231 - void set_partial_scan_closure(G1ParScanPartialArrayClosure* partial_scan_cl) { 29.1232 - _partial_scan_cl = partial_scan_cl; 29.1233 - } 29.1234 - 29.1235 - int* hash_seed() { return &_hash_seed; } 29.1236 - int queue_num() { return _queue_num; } 29.1237 - 29.1238 - int term_attempts() { return _term_attempts; } 29.1239 - void note_term_attempt() { _term_attempts++; } 29.1240 - 29.1241 -#if G1_DETAILED_STATS 29.1242 - int pushes() { return _pushes; } 29.1243 - int pops() { return _pops; } 29.1244 - int steals() { return _steals; } 29.1245 - int steal_attempts() { return _steal_attempts; } 29.1246 - int overflow_pushes() { return _overflow_pushes; } 29.1247 - 29.1248 - void note_push() { _pushes++; } 29.1249 - void note_pop() { _pops++; } 29.1250 - void note_steal() { _steals++; } 29.1251 - void note_steal_attempt() { _steal_attempts++; } 29.1252 - void note_overflow_push() { _overflow_pushes++; } 29.1253 -#endif 29.1254 - 29.1255 - void start_strong_roots() { 29.1256 - _start_strong_roots = os::elapsedTime(); 29.1257 - } 29.1258 - void end_strong_roots() { 29.1259 - _strong_roots_time += (os::elapsedTime() - _start_strong_roots); 29.1260 - } 29.1261 - double strong_roots_time() { return _strong_roots_time; } 29.1262 - 29.1263 - void start_term_time() { 29.1264 - note_term_attempt(); 29.1265 - _start_term = os::elapsedTime(); 29.1266 - } 29.1267 - void end_term_time() { 29.1268 - _term_time += (os::elapsedTime() - _start_term); 29.1269 - } 29.1270 - double term_time() { return _term_time; } 29.1271 - 29.1272 - double elapsed() { 29.1273 - return os::elapsedTime() - _start; 29.1274 - } 29.1275 - 29.1276 - size_t* surviving_young_words() { 29.1277 - // We add on to hide entry 0 which accumulates surviving words for 29.1278 - // age -1 regions (i.e. non-young ones) 29.1279 - return _surviving_young_words; 29.1280 - } 29.1281 - 29.1282 - void retire_alloc_buffers() { 29.1283 - for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { 29.1284 - size_t waste = _alloc_buffers[ap].words_remaining(); 29.1285 - add_to_alloc_buffer_waste(waste); 29.1286 - _alloc_buffers[ap].retire(true, false); 29.1287 - } 29.1288 - } 29.1289 - 29.1290 -private: 29.1291 - void deal_with_reference(oop* ref_to_scan) { 29.1292 - if (has_partial_array_mask(ref_to_scan)) { 29.1293 - _partial_scan_cl->do_oop_nv(ref_to_scan); 29.1294 - } else { 29.1295 - // Note: we can use "raw" versions of "region_containing" because 29.1296 - // "obj_to_scan" is definitely in the heap, and is not in a 29.1297 - // humongous region. 29.1298 - HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); 29.1299 - _evac_cl->set_region(r); 29.1300 - _evac_cl->do_oop_nv(ref_to_scan); 29.1301 - } 29.1302 - } 29.1303 - 29.1304 -public: 29.1305 - void trim_queue() { 29.1306 - // I've replicated the loop twice, first to drain the overflow 29.1307 - // queue, second to drain the task queue. This is better than 29.1308 - // having a single loop, which checks both conditions and, inside 29.1309 - // it, either pops the overflow queue or the task queue, as each 29.1310 - // loop is tighter. Also, the decision to drain the overflow queue 29.1311 - // first is not arbitrary, as the overflow queue is not visible 29.1312 - // to the other workers, whereas the task queue is. So, we want to 29.1313 - // drain the "invisible" entries first, while allowing the other 29.1314 - // workers to potentially steal the "visible" entries. 29.1315 - 29.1316 - while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) { 29.1317 - while (overflowed_refs_to_scan() > 0) { 29.1318 - oop *ref_to_scan = NULL; 29.1319 - pop_from_overflow_queue(ref_to_scan); 29.1320 - assert(ref_to_scan != NULL, "invariant"); 29.1321 - // We shouldn't have pushed it on the queue if it was not 29.1322 - // pointing into the CSet. 29.1323 - assert(ref_to_scan != NULL, "sanity"); 29.1324 - assert(has_partial_array_mask(ref_to_scan) || 29.1325 - _g1h->obj_in_cs(*ref_to_scan), "sanity"); 29.1326 - 29.1327 - deal_with_reference(ref_to_scan); 29.1328 - } 29.1329 - 29.1330 - while (refs_to_scan() > 0) { 29.1331 - oop *ref_to_scan = NULL; 29.1332 - pop_from_queue(ref_to_scan); 29.1333 - 29.1334 - if (ref_to_scan != NULL) { 29.1335 - // We shouldn't have pushed it on the queue if it was not 29.1336 - // pointing into the CSet. 29.1337 - assert(has_partial_array_mask(ref_to_scan) || 29.1338 - _g1h->obj_in_cs(*ref_to_scan), "sanity"); 29.1339 - 29.1340 - deal_with_reference(ref_to_scan); 29.1341 - } 29.1342 - } 29.1343 - } 29.1344 - } 29.1345 -}; 29.1346 + _strong_roots_time(0), _term_time(0), 29.1347 + _alloc_buffer_waste(0), _undo_waste(0) 29.1348 +{ 29.1349 + // we allocate G1YoungSurvRateNumRegions plus one entries, since 29.1350 + // we "sacrifice" entry 0 to keep track of surviving bytes for 29.1351 + // non-young regions (where the age is -1) 29.1352 + // We also add a few elements at the beginning and at the end in 29.1353 + // an attempt to eliminate cache contention 29.1354 + size_t real_length = 1 + _g1h->g1_policy()->young_cset_length(); 29.1355 + size_t array_length = PADDING_ELEM_NUM + 29.1356 + real_length + 29.1357 + PADDING_ELEM_NUM; 29.1358 + _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length); 29.1359 + if (_surviving_young_words_base == NULL) 29.1360 + vm_exit_out_of_memory(array_length * sizeof(size_t), 29.1361 + "Not enough space for young surv histo."); 29.1362 + _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; 29.1363 + memset(_surviving_young_words, 0, real_length * sizeof(size_t)); 29.1364 + 29.1365 + _overflowed_refs = new OverflowQueue(10); 29.1366 + 29.1367 + _start = os::elapsedTime(); 29.1368 +} 29.1369 29.1370 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 29.1371 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), 29.1372 _par_scan_state(par_scan_state) { } 29.1373 29.1374 -// This closure is applied to the fields of the objects that have just been copied. 29.1375 -// Should probably be made inline and moved in g1OopClosures.inline.hpp. 29.1376 -void G1ParScanClosure::do_oop_nv(oop* p) { 29.1377 - oop obj = *p; 29.1378 - 29.1379 - if (obj != NULL) { 29.1380 - if (_g1->in_cset_fast_test(obj)) { 29.1381 - // We're not going to even bother checking whether the object is 29.1382 - // already forwarded or not, as this usually causes an immediate 29.1383 - // stall. We'll try to prefetch the object (for write, given that 29.1384 - // we might need to install the forwarding reference) and we'll 29.1385 - // get back to it when pop it from the queue 29.1386 - Prefetch::write(obj->mark_addr(), 0); 29.1387 - Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); 29.1388 - 29.1389 - // slightly paranoid test; I'm trying to catch potential 29.1390 - // problems before we go into push_on_queue to know where the 29.1391 - // problem is coming from 29.1392 - assert(obj == *p, "the value of *p should not have changed"); 29.1393 - _par_scan_state->push_on_queue(p); 29.1394 - } else { 29.1395 - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 29.1396 - } 29.1397 - } 29.1398 -} 29.1399 - 29.1400 -void G1ParCopyHelper::mark_forwardee(oop* p) { 29.1401 +template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { 29.1402 // This is called _after_ do_oop_work has been called, hence after 29.1403 // the object has been relocated to its new location and *p points 29.1404 // to its new location. 29.1405 29.1406 - oop thisOop = *p; 29.1407 - if (thisOop != NULL) { 29.1408 - assert((_g1->evacuation_failed()) || (!_g1->obj_in_cs(thisOop)), 29.1409 + T heap_oop = oopDesc::load_heap_oop(p); 29.1410 + if (!oopDesc::is_null(heap_oop)) { 29.1411 + oop obj = oopDesc::decode_heap_oop(heap_oop); 29.1412 + assert((_g1->evacuation_failed()) || (!_g1->obj_in_cs(obj)), 29.1413 "shouldn't still be in the CSet if evacuation didn't fail."); 29.1414 - HeapWord* addr = (HeapWord*)thisOop; 29.1415 + HeapWord* addr = (HeapWord*)obj; 29.1416 if (_g1->is_in_g1_reserved(addr)) 29.1417 _cm->grayRoot(oop(addr)); 29.1418 } 29.1419 @@ -4191,7 +3691,8 @@ 29.1420 29.1421 if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { 29.1422 arrayOop(old)->set_length(0); 29.1423 - _par_scan_state->push_on_queue(set_partial_array_mask(old)); 29.1424 + oop* old_p = set_partial_array_mask(old); 29.1425 + _par_scan_state->push_on_queue(old_p); 29.1426 } else { 29.1427 // No point in using the slower heap_region_containing() method, 29.1428 // given that we know obj is in the heap. 29.1429 @@ -4205,11 +3706,11 @@ 29.1430 return obj; 29.1431 } 29.1432 29.1433 -template<bool do_gen_barrier, G1Barrier barrier, 29.1434 - bool do_mark_forwardee, bool skip_cset_test> 29.1435 -void G1ParCopyClosure<do_gen_barrier, barrier, 29.1436 - do_mark_forwardee, skip_cset_test>::do_oop_work(oop* p) { 29.1437 - oop obj = *p; 29.1438 +template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test> 29.1439 +template <class T> 29.1440 +void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test> 29.1441 +::do_oop_work(T* p) { 29.1442 + oop obj = oopDesc::load_decode_heap_oop(p); 29.1443 assert(barrier != G1BarrierRS || obj != NULL, 29.1444 "Precondition: G1BarrierRS implies obj is nonNull"); 29.1445 29.1446 @@ -4226,9 +3727,10 @@ 29.1447 "into CS.", p, (void*) obj); 29.1448 #endif 29.1449 if (obj->is_forwarded()) { 29.1450 - *p = obj->forwardee(); 29.1451 + oopDesc::encode_store_heap_oop(p, obj->forwardee()); 29.1452 } else { 29.1453 - *p = copy_to_survivor_space(obj); 29.1454 + oop copy_oop = copy_to_survivor_space(obj); 29.1455 + oopDesc::encode_store_heap_oop(p, copy_oop); 29.1456 } 29.1457 // When scanning the RS, we only care about objs in CS. 29.1458 if (barrier == G1BarrierRS) { 29.1459 @@ -4247,21 +3749,9 @@ 29.1460 } 29.1461 29.1462 template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p); 29.1463 - 29.1464 -template<class T> void G1ParScanPartialArrayClosure::process_array_chunk( 29.1465 - oop obj, int start, int end) { 29.1466 - // process our set of indices (include header in first chunk) 29.1467 - assert(start < end, "invariant"); 29.1468 - T* const base = (T*)objArrayOop(obj)->base(); 29.1469 - T* const start_addr = (start == 0) ? (T*) obj : base + start; 29.1470 - T* const end_addr = base + end; 29.1471 - MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); 29.1472 - _scanner.set_region(_g1->heap_region_containing(obj)); 29.1473 - obj->oop_iterate(&_scanner, mr); 29.1474 -} 29.1475 - 29.1476 -void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) { 29.1477 - assert(!UseCompressedOops, "Needs to be fixed to work with compressed oops"); 29.1478 +template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p); 29.1479 + 29.1480 +template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { 29.1481 assert(has_partial_array_mask(p), "invariant"); 29.1482 oop old = clear_partial_array_mask(p); 29.1483 assert(old->is_objArray(), "must be obj array"); 29.1484 @@ -4281,19 +3771,19 @@ 29.1485 end = start + ParGCArrayScanChunk; 29.1486 arrayOop(old)->set_length(end); 29.1487 // Push remainder. 29.1488 - _par_scan_state->push_on_queue(set_partial_array_mask(old)); 29.1489 + oop* old_p = set_partial_array_mask(old); 29.1490 + assert(arrayOop(old)->length() < obj->length(), "Empty push?"); 29.1491 + _par_scan_state->push_on_queue(old_p); 29.1492 } else { 29.1493 // Restore length so that the heap remains parsable in 29.1494 // case of evacuation failure. 29.1495 arrayOop(old)->set_length(end); 29.1496 } 29.1497 - 29.1498 + _scanner.set_region(_g1->heap_region_containing_raw(obj)); 29.1499 // process our set of indices (include header in first chunk) 29.1500 - process_array_chunk<oop>(obj, start, end); 29.1501 + obj->oop_iterate_range(&_scanner, start, end); 29.1502 } 29.1503 29.1504 -int G1ScanAndBalanceClosure::_nq = 0; 29.1505 - 29.1506 class G1ParEvacuateFollowersClosure : public VoidClosure { 29.1507 protected: 29.1508 G1CollectedHeap* _g1h; 29.1509 @@ -4316,21 +3806,28 @@ 29.1510 void do_void() { 29.1511 G1ParScanThreadState* pss = par_scan_state(); 29.1512 while (true) { 29.1513 - oop* ref_to_scan; 29.1514 pss->trim_queue(); 29.1515 IF_G1_DETAILED_STATS(pss->note_steal_attempt()); 29.1516 - if (queues()->steal(pss->queue_num(), 29.1517 - pss->hash_seed(), 29.1518 - ref_to_scan)) { 29.1519 + 29.1520 + StarTask stolen_task; 29.1521 + if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) { 29.1522 IF_G1_DETAILED_STATS(pss->note_steal()); 29.1523 29.1524 // slightly paranoid tests; I'm trying to catch potential 29.1525 // problems before we go into push_on_queue to know where the 29.1526 // problem is coming from 29.1527 - assert(ref_to_scan != NULL, "invariant"); 29.1528 - assert(has_partial_array_mask(ref_to_scan) || 29.1529 - _g1h->obj_in_cs(*ref_to_scan), "invariant"); 29.1530 - pss->push_on_queue(ref_to_scan); 29.1531 + assert((oop*)stolen_task != NULL, "Error"); 29.1532 + if (stolen_task.is_narrow()) { 29.1533 + assert(UseCompressedOops, "Error"); 29.1534 + narrowOop* p = (narrowOop*) stolen_task; 29.1535 + assert(has_partial_array_mask(p) || 29.1536 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error"); 29.1537 + pss->push_on_queue(p); 29.1538 + } else { 29.1539 + oop* p = (oop*) stolen_task; 29.1540 + assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error"); 29.1541 + pss->push_on_queue(p); 29.1542 + } 29.1543 continue; 29.1544 } 29.1545 pss->start_term_time(); 29.1546 @@ -4347,6 +3844,7 @@ 29.1547 G1CollectedHeap* _g1h; 29.1548 RefToScanQueueSet *_queues; 29.1549 ParallelTaskTerminator _terminator; 29.1550 + int _n_workers; 29.1551 29.1552 Mutex _stats_lock; 29.1553 Mutex* stats_lock() { return &_stats_lock; } 29.1554 @@ -4362,7 +3860,8 @@ 29.1555 _g1h(g1h), 29.1556 _queues(task_queues), 29.1557 _terminator(workers, _queues), 29.1558 - _stats_lock(Mutex::leaf, "parallel G1 stats lock", true) 29.1559 + _stats_lock(Mutex::leaf, "parallel G1 stats lock", true), 29.1560 + _n_workers(workers) 29.1561 {} 29.1562 29.1563 RefToScanQueueSet* queues() { return _queues; } 29.1564 @@ -4372,6 +3871,7 @@ 29.1565 } 29.1566 29.1567 void work(int i) { 29.1568 + if (i >= _n_workers) return; // no work needed this round 29.1569 ResourceMark rm; 29.1570 HandleMark hm; 29.1571 29.1572 @@ -4469,23 +3969,6 @@ 29.1573 29.1574 // *** Common G1 Evacuation Stuff 29.1575 29.1576 -class G1CountClosure: public OopsInHeapRegionClosure { 29.1577 -public: 29.1578 - int n; 29.1579 - G1CountClosure() : n(0) {} 29.1580 - void do_oop(narrowOop* p) { 29.1581 - guarantee(false, "NYI"); 29.1582 - } 29.1583 - void do_oop(oop* p) { 29.1584 - oop obj = *p; 29.1585 - assert(obj != NULL && G1CollectedHeap::heap()->obj_in_cs(obj), 29.1586 - "Rem set closure called on non-rem-set pointer."); 29.1587 - n++; 29.1588 - } 29.1589 -}; 29.1590 - 29.1591 -static G1CountClosure count_closure; 29.1592 - 29.1593 void 29.1594 G1CollectedHeap:: 29.1595 g1_process_strong_roots(bool collecting_perm_gen, 29.1596 @@ -5357,7 +4840,7 @@ 29.1597 assert(_free_region_list == NULL, "Postcondition of loop."); 29.1598 if (_free_region_list_size != 0) { 29.1599 gclog_or_tty->print_cr("Size is %d.", _free_region_list_size); 29.1600 - print(); 29.1601 + print_on(gclog_or_tty, true /* extended */); 29.1602 } 29.1603 assert(_free_region_list_size == 0, "Postconditions of loop."); 29.1604 } 29.1605 @@ -5535,8 +5018,3 @@ 29.1606 void G1CollectedHeap::g1_unimplemented() { 29.1607 // Unimplemented(); 29.1608 } 29.1609 - 29.1610 - 29.1611 -// Local Variables: *** 29.1612 -// c-indentation-style: gnu *** 29.1613 -// End: ***
30.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Jul 20 08:20:00 2009 -0700 30.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Jul 27 06:15:29 2009 -0700 30.3 @@ -56,8 +56,8 @@ 30.4 # define IF_G1_DETAILED_STATS(code) 30.5 #endif 30.6 30.7 -typedef GenericTaskQueue<oop*> RefToScanQueue; 30.8 -typedef GenericTaskQueueSet<oop*> RefToScanQueueSet; 30.9 +typedef GenericTaskQueue<StarTask> RefToScanQueue; 30.10 +typedef GenericTaskQueueSet<StarTask> RefToScanQueueSet; 30.11 30.12 typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) 30.13 typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) 30.14 @@ -700,6 +700,9 @@ 30.15 size_t g1_reserved_obj_bytes() { return _g1_reserved.byte_size(); } 30.16 virtual size_t capacity() const; 30.17 virtual size_t used() const; 30.18 + // This should be called when we're not holding the heap lock. The 30.19 + // result might be a bit inaccurate. 30.20 + size_t used_unlocked() const; 30.21 size_t recalculate_used() const; 30.22 #ifndef PRODUCT 30.23 size_t recalculate_used_regions() const; 30.24 @@ -1061,8 +1064,14 @@ 30.25 30.26 // Override; it uses the "prev" marking information 30.27 virtual void verify(bool allow_dirty, bool silent); 30.28 + // Default behavior by calling print(tty); 30.29 virtual void print() const; 30.30 + // This calls print_on(st, PrintHeapAtGCExtended). 30.31 virtual void print_on(outputStream* st) const; 30.32 + // If extended is true, it will print out information for all 30.33 + // regions in the heap by calling print_on_extended(st). 30.34 + virtual void print_on(outputStream* st, bool extended) const; 30.35 + virtual void print_on_extended(outputStream* st) const; 30.36 30.37 virtual void print_gc_threads_on(outputStream* st) const; 30.38 virtual void gc_threads_do(ThreadClosure* tc) const; 30.39 @@ -1265,6 +1274,552 @@ 30.40 30.41 }; 30.42 30.43 -// Local Variables: *** 30.44 -// c-indentation-style: gnu *** 30.45 -// End: *** 30.46 +#define use_local_bitmaps 1 30.47 +#define verify_local_bitmaps 0 30.48 +#define oop_buffer_length 256 30.49 + 30.50 +#ifndef PRODUCT 30.51 +class GCLabBitMap; 30.52 +class GCLabBitMapClosure: public BitMapClosure { 30.53 +private: 30.54 + ConcurrentMark* _cm; 30.55 + GCLabBitMap* _bitmap; 30.56 + 30.57 +public: 30.58 + GCLabBitMapClosure(ConcurrentMark* cm, 30.59 + GCLabBitMap* bitmap) { 30.60 + _cm = cm; 30.61 + _bitmap = bitmap; 30.62 + } 30.63 + 30.64 + virtual bool do_bit(size_t offset); 30.65 +}; 30.66 +#endif // !PRODUCT 30.67 + 30.68 +class GCLabBitMap: public BitMap { 30.69 +private: 30.70 + ConcurrentMark* _cm; 30.71 + 30.72 + int _shifter; 30.73 + size_t _bitmap_word_covers_words; 30.74 + 30.75 + // beginning of the heap 30.76 + HeapWord* _heap_start; 30.77 + 30.78 + // this is the actual start of the GCLab 30.79 + HeapWord* _real_start_word; 30.80 + 30.81 + // this is the actual end of the GCLab 30.82 + HeapWord* _real_end_word; 30.83 + 30.84 + // this is the first word, possibly located before the actual start 30.85 + // of the GCLab, that corresponds to the first bit of the bitmap 30.86 + HeapWord* _start_word; 30.87 + 30.88 + // size of a GCLab in words 30.89 + size_t _gclab_word_size; 30.90 + 30.91 + static int shifter() { 30.92 + return MinObjAlignment - 1; 30.93 + } 30.94 + 30.95 + // how many heap words does a single bitmap word corresponds to? 30.96 + static size_t bitmap_word_covers_words() { 30.97 + return BitsPerWord << shifter(); 30.98 + } 30.99 + 30.100 + static size_t gclab_word_size() { 30.101 + return G1ParallelGCAllocBufferSize / HeapWordSize; 30.102 + } 30.103 + 30.104 + static size_t bitmap_size_in_bits() { 30.105 + size_t bits_in_bitmap = gclab_word_size() >> shifter(); 30.106 + // We are going to ensure that the beginning of a word in this 30.107 + // bitmap also corresponds to the beginning of a word in the 30.108 + // global marking bitmap. To handle the case where a GCLab 30.109 + // starts from the middle of the bitmap, we need to add enough 30.110 + // space (i.e. up to a bitmap word) to ensure that we have 30.111 + // enough bits in the bitmap. 30.112 + return bits_in_bitmap + BitsPerWord - 1; 30.113 + } 30.114 +public: 30.115 + GCLabBitMap(HeapWord* heap_start) 30.116 + : BitMap(bitmap_size_in_bits()), 30.117 + _cm(G1CollectedHeap::heap()->concurrent_mark()), 30.118 + _shifter(shifter()), 30.119 + _bitmap_word_covers_words(bitmap_word_covers_words()), 30.120 + _heap_start(heap_start), 30.121 + _gclab_word_size(gclab_word_size()), 30.122 + _real_start_word(NULL), 30.123 + _real_end_word(NULL), 30.124 + _start_word(NULL) 30.125 + { 30.126 + guarantee( size_in_words() >= bitmap_size_in_words(), 30.127 + "just making sure"); 30.128 + } 30.129 + 30.130 + inline unsigned heapWordToOffset(HeapWord* addr) { 30.131 + unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter; 30.132 + assert(offset < size(), "offset should be within bounds"); 30.133 + return offset; 30.134 + } 30.135 + 30.136 + inline HeapWord* offsetToHeapWord(size_t offset) { 30.137 + HeapWord* addr = _start_word + (offset << _shifter); 30.138 + assert(_real_start_word <= addr && addr < _real_end_word, "invariant"); 30.139 + return addr; 30.140 + } 30.141 + 30.142 + bool fields_well_formed() { 30.143 + bool ret1 = (_real_start_word == NULL) && 30.144 + (_real_end_word == NULL) && 30.145 + (_start_word == NULL); 30.146 + if (ret1) 30.147 + return true; 30.148 + 30.149 + bool ret2 = _real_start_word >= _start_word && 30.150 + _start_word < _real_end_word && 30.151 + (_real_start_word + _gclab_word_size) == _real_end_word && 30.152 + (_start_word + _gclab_word_size + _bitmap_word_covers_words) 30.153 + > _real_end_word; 30.154 + return ret2; 30.155 + } 30.156 + 30.157 + inline bool mark(HeapWord* addr) { 30.158 + guarantee(use_local_bitmaps, "invariant"); 30.159 + assert(fields_well_formed(), "invariant"); 30.160 + 30.161 + if (addr >= _real_start_word && addr < _real_end_word) { 30.162 + assert(!isMarked(addr), "should not have already been marked"); 30.163 + 30.164 + // first mark it on the bitmap 30.165 + at_put(heapWordToOffset(addr), true); 30.166 + 30.167 + return true; 30.168 + } else { 30.169 + return false; 30.170 + } 30.171 + } 30.172 + 30.173 + inline bool isMarked(HeapWord* addr) { 30.174 + guarantee(use_local_bitmaps, "invariant"); 30.175 + assert(fields_well_formed(), "invariant"); 30.176 + 30.177 + return at(heapWordToOffset(addr)); 30.178 + } 30.179 + 30.180 + void set_buffer(HeapWord* start) { 30.181 + guarantee(use_local_bitmaps, "invariant"); 30.182 + clear(); 30.183 + 30.184 + assert(start != NULL, "invariant"); 30.185 + _real_start_word = start; 30.186 + _real_end_word = start + _gclab_word_size; 30.187 + 30.188 + size_t diff = 30.189 + pointer_delta(start, _heap_start) % _bitmap_word_covers_words; 30.190 + _start_word = start - diff; 30.191 + 30.192 + assert(fields_well_formed(), "invariant"); 30.193 + } 30.194 + 30.195 +#ifndef PRODUCT 30.196 + void verify() { 30.197 + // verify that the marks have been propagated 30.198 + GCLabBitMapClosure cl(_cm, this); 30.199 + iterate(&cl); 30.200 + } 30.201 +#endif // PRODUCT 30.202 + 30.203 + void retire() { 30.204 + guarantee(use_local_bitmaps, "invariant"); 30.205 + assert(fields_well_formed(), "invariant"); 30.206 + 30.207 + if (_start_word != NULL) { 30.208 + CMBitMap* mark_bitmap = _cm->nextMarkBitMap(); 30.209 + 30.210 + // this means that the bitmap was set up for the GCLab 30.211 + assert(_real_start_word != NULL && _real_end_word != NULL, "invariant"); 30.212 + 30.213 + mark_bitmap->mostly_disjoint_range_union(this, 30.214 + 0, // always start from the start of the bitmap 30.215 + _start_word, 30.216 + size_in_words()); 30.217 + _cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word)); 30.218 + 30.219 +#ifndef PRODUCT 30.220 + if (use_local_bitmaps && verify_local_bitmaps) 30.221 + verify(); 30.222 +#endif // PRODUCT 30.223 + } else { 30.224 + assert(_real_start_word == NULL && _real_end_word == NULL, "invariant"); 30.225 + } 30.226 + } 30.227 + 30.228 + static size_t bitmap_size_in_words() { 30.229 + return (bitmap_size_in_bits() + BitsPerWord - 1) / BitsPerWord; 30.230 + } 30.231 +}; 30.232 + 30.233 +class G1ParGCAllocBuffer: public ParGCAllocBuffer { 30.234 +private: 30.235 + bool _retired; 30.236 + bool _during_marking; 30.237 + GCLabBitMap _bitmap; 30.238 + 30.239 +public: 30.240 + G1ParGCAllocBuffer() : 30.241 + ParGCAllocBuffer(G1ParallelGCAllocBufferSize / HeapWordSize), 30.242 + _during_marking(G1CollectedHeap::heap()->mark_in_progress()), 30.243 + _bitmap(G1CollectedHeap::heap()->reserved_region().start()), 30.244 + _retired(false) 30.245 + { } 30.246 + 30.247 + inline bool mark(HeapWord* addr) { 30.248 + guarantee(use_local_bitmaps, "invariant"); 30.249 + assert(_during_marking, "invariant"); 30.250 + return _bitmap.mark(addr); 30.251 + } 30.252 + 30.253 + inline void set_buf(HeapWord* buf) { 30.254 + if (use_local_bitmaps && _during_marking) 30.255 + _bitmap.set_buffer(buf); 30.256 + ParGCAllocBuffer::set_buf(buf); 30.257 + _retired = false; 30.258 + } 30.259 + 30.260 + inline void retire(bool end_of_gc, bool retain) { 30.261 + if (_retired) 30.262 + return; 30.263 + if (use_local_bitmaps && _during_marking) { 30.264 + _bitmap.retire(); 30.265 + } 30.266 + ParGCAllocBuffer::retire(end_of_gc, retain); 30.267 + _retired = true; 30.268 + } 30.269 +}; 30.270 + 30.271 +class G1ParScanThreadState : public StackObj { 30.272 +protected: 30.273 + G1CollectedHeap* _g1h; 30.274 + RefToScanQueue* _refs; 30.275 + DirtyCardQueue _dcq; 30.276 + CardTableModRefBS* _ct_bs; 30.277 + G1RemSet* _g1_rem; 30.278 + 30.279 + typedef GrowableArray<StarTask> OverflowQueue; 30.280 + OverflowQueue* _overflowed_refs; 30.281 + 30.282 + G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount]; 30.283 + ageTable _age_table; 30.284 + 30.285 + size_t _alloc_buffer_waste; 30.286 + size_t _undo_waste; 30.287 + 30.288 + OopsInHeapRegionClosure* _evac_failure_cl; 30.289 + G1ParScanHeapEvacClosure* _evac_cl; 30.290 + G1ParScanPartialArrayClosure* _partial_scan_cl; 30.291 + 30.292 + int _hash_seed; 30.293 + int _queue_num; 30.294 + 30.295 + int _term_attempts; 30.296 +#if G1_DETAILED_STATS 30.297 + int _pushes, _pops, _steals, _steal_attempts; 30.298 + int _overflow_pushes; 30.299 +#endif 30.300 + 30.301 + double _start; 30.302 + double _start_strong_roots; 30.303 + double _strong_roots_time; 30.304 + double _start_term; 30.305 + double _term_time; 30.306 + 30.307 + // Map from young-age-index (0 == not young, 1 is youngest) to 30.308 + // surviving words. base is what we get back from the malloc call 30.309 + size_t* _surviving_young_words_base; 30.310 + // this points into the array, as we use the first few entries for padding 30.311 + size_t* _surviving_young_words; 30.312 + 30.313 +#define PADDING_ELEM_NUM (64 / sizeof(size_t)) 30.314 + 30.315 + void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } 30.316 + 30.317 + void add_to_undo_waste(size_t waste) { _undo_waste += waste; } 30.318 + 30.319 + DirtyCardQueue& dirty_card_queue() { return _dcq; } 30.320 + CardTableModRefBS* ctbs() { return _ct_bs; } 30.321 + 30.322 + template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) { 30.323 + if (!from->is_survivor()) { 30.324 + _g1_rem->par_write_ref(from, p, tid); 30.325 + } 30.326 + } 30.327 + 30.328 + template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) { 30.329 + // If the new value of the field points to the same region or 30.330 + // is the to-space, we don't need to include it in the Rset updates. 30.331 + if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) { 30.332 + size_t card_index = ctbs()->index_for(p); 30.333 + // If the card hasn't been added to the buffer, do it. 30.334 + if (ctbs()->mark_card_deferred(card_index)) { 30.335 + dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index)); 30.336 + } 30.337 + } 30.338 + } 30.339 + 30.340 +public: 30.341 + G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num); 30.342 + 30.343 + ~G1ParScanThreadState() { 30.344 + FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); 30.345 + } 30.346 + 30.347 + RefToScanQueue* refs() { return _refs; } 30.348 + OverflowQueue* overflowed_refs() { return _overflowed_refs; } 30.349 + ageTable* age_table() { return &_age_table; } 30.350 + 30.351 + G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 30.352 + return &_alloc_buffers[purpose]; 30.353 + } 30.354 + 30.355 + size_t alloc_buffer_waste() { return _alloc_buffer_waste; } 30.356 + size_t undo_waste() { return _undo_waste; } 30.357 + 30.358 + template <class T> void push_on_queue(T* ref) { 30.359 + assert(ref != NULL, "invariant"); 30.360 + assert(has_partial_array_mask(ref) || 30.361 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(ref)), "invariant"); 30.362 +#ifdef ASSERT 30.363 + if (has_partial_array_mask(ref)) { 30.364 + oop p = clear_partial_array_mask(ref); 30.365 + // Verify that we point into the CS 30.366 + assert(_g1h->obj_in_cs(p), "Should be in CS"); 30.367 + } 30.368 +#endif 30.369 + if (!refs()->push(ref)) { 30.370 + overflowed_refs()->push(ref); 30.371 + IF_G1_DETAILED_STATS(note_overflow_push()); 30.372 + } else { 30.373 + IF_G1_DETAILED_STATS(note_push()); 30.374 + } 30.375 + } 30.376 + 30.377 + void pop_from_queue(StarTask& ref) { 30.378 + if (refs()->pop_local(ref)) { 30.379 + assert((oop*)ref != NULL, "pop_local() returned true"); 30.380 + assert(UseCompressedOops || !ref.is_narrow(), "Error"); 30.381 + assert(has_partial_array_mask((oop*)ref) || 30.382 + _g1h->obj_in_cs(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref) 30.383 + : oopDesc::load_decode_heap_oop((oop*)ref)), 30.384 + "invariant"); 30.385 + IF_G1_DETAILED_STATS(note_pop()); 30.386 + } else { 30.387 + StarTask null_task; 30.388 + ref = null_task; 30.389 + } 30.390 + } 30.391 + 30.392 + void pop_from_overflow_queue(StarTask& ref) { 30.393 + StarTask new_ref = overflowed_refs()->pop(); 30.394 + assert((oop*)new_ref != NULL, "pop() from a local non-empty stack"); 30.395 + assert(UseCompressedOops || !new_ref.is_narrow(), "Error"); 30.396 + assert(has_partial_array_mask((oop*)new_ref) || 30.397 + _g1h->obj_in_cs(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref) 30.398 + : oopDesc::load_decode_heap_oop((oop*)new_ref)), 30.399 + "invariant"); 30.400 + ref = new_ref; 30.401 + } 30.402 + 30.403 + int refs_to_scan() { return refs()->size(); } 30.404 + int overflowed_refs_to_scan() { return overflowed_refs()->length(); } 30.405 + 30.406 + template <class T> void update_rs(HeapRegion* from, T* p, int tid) { 30.407 + if (G1DeferredRSUpdate) { 30.408 + deferred_rs_update(from, p, tid); 30.409 + } else { 30.410 + immediate_rs_update(from, p, tid); 30.411 + } 30.412 + } 30.413 + 30.414 + HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) { 30.415 + 30.416 + HeapWord* obj = NULL; 30.417 + if (word_sz * 100 < 30.418 + (size_t)(G1ParallelGCAllocBufferSize / HeapWordSize) * 30.419 + ParallelGCBufferWastePct) { 30.420 + G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); 30.421 + add_to_alloc_buffer_waste(alloc_buf->words_remaining()); 30.422 + alloc_buf->retire(false, false); 30.423 + 30.424 + HeapWord* buf = 30.425 + _g1h->par_allocate_during_gc(purpose, G1ParallelGCAllocBufferSize / HeapWordSize); 30.426 + if (buf == NULL) return NULL; // Let caller handle allocation failure. 30.427 + // Otherwise. 30.428 + alloc_buf->set_buf(buf); 30.429 + 30.430 + obj = alloc_buf->allocate(word_sz); 30.431 + assert(obj != NULL, "buffer was definitely big enough..."); 30.432 + } else { 30.433 + obj = _g1h->par_allocate_during_gc(purpose, word_sz); 30.434 + } 30.435 + return obj; 30.436 + } 30.437 + 30.438 + HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) { 30.439 + HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz); 30.440 + if (obj != NULL) return obj; 30.441 + return allocate_slow(purpose, word_sz); 30.442 + } 30.443 + 30.444 + void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) { 30.445 + if (alloc_buffer(purpose)->contains(obj)) { 30.446 + assert(alloc_buffer(purpose)->contains(obj + word_sz - 1), 30.447 + "should contain whole object"); 30.448 + alloc_buffer(purpose)->undo_allocation(obj, word_sz); 30.449 + } else { 30.450 + CollectedHeap::fill_with_object(obj, word_sz); 30.451 + add_to_undo_waste(word_sz); 30.452 + } 30.453 + } 30.454 + 30.455 + void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) { 30.456 + _evac_failure_cl = evac_failure_cl; 30.457 + } 30.458 + OopsInHeapRegionClosure* evac_failure_closure() { 30.459 + return _evac_failure_cl; 30.460 + } 30.461 + 30.462 + void set_evac_closure(G1ParScanHeapEvacClosure* evac_cl) { 30.463 + _evac_cl = evac_cl; 30.464 + } 30.465 + 30.466 + void set_partial_scan_closure(G1ParScanPartialArrayClosure* partial_scan_cl) { 30.467 + _partial_scan_cl = partial_scan_cl; 30.468 + } 30.469 + 30.470 + int* hash_seed() { return &_hash_seed; } 30.471 + int queue_num() { return _queue_num; } 30.472 + 30.473 + int term_attempts() { return _term_attempts; } 30.474 + void note_term_attempt() { _term_attempts++; } 30.475 + 30.476 +#if G1_DETAILED_STATS 30.477 + int pushes() { return _pushes; } 30.478 + int pops() { return _pops; } 30.479 + int steals() { return _steals; } 30.480 + int steal_attempts() { return _steal_attempts; } 30.481 + int overflow_pushes() { return _overflow_pushes; } 30.482 + 30.483 + void note_push() { _pushes++; } 30.484 + void note_pop() { _pops++; } 30.485 + void note_steal() { _steals++; } 30.486 + void note_steal_attempt() { _steal_attempts++; } 30.487 + void note_overflow_push() { _overflow_pushes++; } 30.488 +#endif 30.489 + 30.490 + void start_strong_roots() { 30.491 + _start_strong_roots = os::elapsedTime(); 30.492 + } 30.493 + void end_strong_roots() { 30.494 + _strong_roots_time += (os::elapsedTime() - _start_strong_roots); 30.495 + } 30.496 + double strong_roots_time() { return _strong_roots_time; } 30.497 + 30.498 + void start_term_time() { 30.499 + note_term_attempt(); 30.500 + _start_term = os::elapsedTime(); 30.501 + } 30.502 + void end_term_time() { 30.503 + _term_time += (os::elapsedTime() - _start_term); 30.504 + } 30.505 + double term_time() { return _term_time; } 30.506 + 30.507 + double elapsed() { 30.508 + return os::elapsedTime() - _start; 30.509 + } 30.510 + 30.511 + size_t* surviving_young_words() { 30.512 + // We add on to hide entry 0 which accumulates surviving words for 30.513 + // age -1 regions (i.e. non-young ones) 30.514 + return _surviving_young_words; 30.515 + } 30.516 + 30.517 + void retire_alloc_buffers() { 30.518 + for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { 30.519 + size_t waste = _alloc_buffers[ap].words_remaining(); 30.520 + add_to_alloc_buffer_waste(waste); 30.521 + _alloc_buffers[ap].retire(true, false); 30.522 + } 30.523 + } 30.524 + 30.525 +private: 30.526 + template <class T> void deal_with_reference(T* ref_to_scan) { 30.527 + if (has_partial_array_mask(ref_to_scan)) { 30.528 + _partial_scan_cl->do_oop_nv(ref_to_scan); 30.529 + } else { 30.530 + // Note: we can use "raw" versions of "region_containing" because 30.531 + // "obj_to_scan" is definitely in the heap, and is not in a 30.532 + // humongous region. 30.533 + HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); 30.534 + _evac_cl->set_region(r); 30.535 + _evac_cl->do_oop_nv(ref_to_scan); 30.536 + } 30.537 + } 30.538 + 30.539 +public: 30.540 + void trim_queue() { 30.541 + // I've replicated the loop twice, first to drain the overflow 30.542 + // queue, second to drain the task queue. This is better than 30.543 + // having a single loop, which checks both conditions and, inside 30.544 + // it, either pops the overflow queue or the task queue, as each 30.545 + // loop is tighter. Also, the decision to drain the overflow queue 30.546 + // first is not arbitrary, as the overflow queue is not visible 30.547 + // to the other workers, whereas the task queue is. So, we want to 30.548 + // drain the "invisible" entries first, while allowing the other 30.549 + // workers to potentially steal the "visible" entries. 30.550 + 30.551 + while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) { 30.552 + while (overflowed_refs_to_scan() > 0) { 30.553 + StarTask ref_to_scan; 30.554 + assert((oop*)ref_to_scan == NULL, "Constructed above"); 30.555 + pop_from_overflow_queue(ref_to_scan); 30.556 + // We shouldn't have pushed it on the queue if it was not 30.557 + // pointing into the CSet. 30.558 + assert((oop*)ref_to_scan != NULL, "Follows from inner loop invariant"); 30.559 + if (ref_to_scan.is_narrow()) { 30.560 + assert(UseCompressedOops, "Error"); 30.561 + narrowOop* p = (narrowOop*)ref_to_scan; 30.562 + assert(!has_partial_array_mask(p) && 30.563 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); 30.564 + deal_with_reference(p); 30.565 + } else { 30.566 + oop* p = (oop*)ref_to_scan; 30.567 + assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) || 30.568 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); 30.569 + deal_with_reference(p); 30.570 + } 30.571 + } 30.572 + 30.573 + while (refs_to_scan() > 0) { 30.574 + StarTask ref_to_scan; 30.575 + assert((oop*)ref_to_scan == NULL, "Constructed above"); 30.576 + pop_from_queue(ref_to_scan); 30.577 + if ((oop*)ref_to_scan != NULL) { 30.578 + if (ref_to_scan.is_narrow()) { 30.579 + assert(UseCompressedOops, "Error"); 30.580 + narrowOop* p = (narrowOop*)ref_to_scan; 30.581 + assert(!has_partial_array_mask(p) && 30.582 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); 30.583 + deal_with_reference(p); 30.584 + } else { 30.585 + oop* p = (oop*)ref_to_scan; 30.586 + assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) || 30.587 + _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); 30.588 + deal_with_reference(p); 30.589 + } 30.590 + } 30.591 + } 30.592 + } 30.593 + } 30.594 +};
31.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Jul 20 08:20:00 2009 -0700 31.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Jul 27 06:15:29 2009 -0700 31.3 @@ -293,10 +293,6 @@ 31.4 if (G1SteadyStateUsed < 50) { 31.5 vm_exit_during_initialization("G1SteadyStateUsed must be at least 50%."); 31.6 } 31.7 - if (UseConcMarkSweepGC) { 31.8 - vm_exit_during_initialization("-XX:+UseG1GC is incompatible with " 31.9 - "-XX:+UseConcMarkSweepGC."); 31.10 - } 31.11 31.12 initialize_gc_policy_counters(); 31.13
32.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Mon Jul 20 08:20:00 2009 -0700 32.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Mon Jul 27 06:15:29 2009 -0700 32.3 @@ -1097,6 +1097,10 @@ 32.4 _recorded_survivor_tail = tail; 32.5 } 32.6 32.7 + size_t recorded_survivor_regions() { 32.8 + return _recorded_survivor_regions; 32.9 + } 32.10 + 32.11 void record_thread_age_table(ageTable* age_table) 32.12 { 32.13 _survivors_age_table.merge_par(age_table);
33.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Mon Jul 20 08:20:00 2009 -0700 33.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Mon Jul 27 06:15:29 2009 -0700 33.3 @@ -42,18 +42,6 @@ 33.4 virtual void set_region(HeapRegion* from) { _from = from; } 33.5 }; 33.6 33.7 - 33.8 -class G1ScanAndBalanceClosure : public OopClosure { 33.9 - G1CollectedHeap* _g1; 33.10 - static int _nq; 33.11 -public: 33.12 - G1ScanAndBalanceClosure(G1CollectedHeap* g1) : _g1(g1) { } 33.13 - inline void do_oop_nv(oop* p); 33.14 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.15 - virtual void do_oop(oop* p); 33.16 - virtual void do_oop(narrowOop* p) { guarantee(false, "NYI"); } 33.17 -}; 33.18 - 33.19 class G1ParClosureSuper : public OopsInHeapRegionClosure { 33.20 protected: 33.21 G1CollectedHeap* _g1; 33.22 @@ -69,34 +57,32 @@ 33.23 public: 33.24 G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 33.25 G1ParClosureSuper(g1, par_scan_state) { } 33.26 - void do_oop_nv(oop* p); // should be made inline 33.27 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.28 + template <class T> void do_oop_nv(T* p); 33.29 virtual void do_oop(oop* p) { do_oop_nv(p); } 33.30 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.31 }; 33.32 33.33 -#define G1_PARTIAL_ARRAY_MASK 1 33.34 +#define G1_PARTIAL_ARRAY_MASK 0x2 33.35 33.36 -inline bool has_partial_array_mask(oop* ref) { 33.37 - return (intptr_t) ref & G1_PARTIAL_ARRAY_MASK; 33.38 +template <class T> inline bool has_partial_array_mask(T* ref) { 33.39 + return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK; 33.40 } 33.41 33.42 -inline oop* set_partial_array_mask(oop obj) { 33.43 - return (oop*) ((intptr_t) obj | G1_PARTIAL_ARRAY_MASK); 33.44 +template <class T> inline T* set_partial_array_mask(T obj) { 33.45 + assert(((uintptr_t)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!"); 33.46 + return (T*) ((uintptr_t)obj | G1_PARTIAL_ARRAY_MASK); 33.47 } 33.48 33.49 -inline oop clear_partial_array_mask(oop* ref) { 33.50 - return oop((intptr_t) ref & ~G1_PARTIAL_ARRAY_MASK); 33.51 +template <class T> inline oop clear_partial_array_mask(T* ref) { 33.52 + return oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK); 33.53 } 33.54 33.55 class G1ParScanPartialArrayClosure : public G1ParClosureSuper { 33.56 G1ParScanClosure _scanner; 33.57 - template <class T> void process_array_chunk(oop obj, int start, int end); 33.58 public: 33.59 G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 33.60 G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state) { } 33.61 - void do_oop_nv(oop* p); 33.62 - void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.63 + template <class T> void do_oop_nv(T* p); 33.64 virtual void do_oop(oop* p) { do_oop_nv(p); } 33.65 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.66 }; 33.67 @@ -105,7 +91,7 @@ 33.68 class G1ParCopyHelper : public G1ParClosureSuper { 33.69 G1ParScanClosure *_scanner; 33.70 protected: 33.71 - void mark_forwardee(oop* p); 33.72 + template <class T> void mark_forwardee(T* p); 33.73 oop copy_to_survivor_space(oop obj); 33.74 public: 33.75 G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, 33.76 @@ -117,36 +103,35 @@ 33.77 bool do_mark_forwardee, bool skip_cset_test> 33.78 class G1ParCopyClosure : public G1ParCopyHelper { 33.79 G1ParScanClosure _scanner; 33.80 - void do_oop_work(oop* p); 33.81 - void do_oop_work(narrowOop* p) { guarantee(false, "NYI"); } 33.82 + template <class T> void do_oop_work(T* p); 33.83 public: 33.84 G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 33.85 _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } 33.86 - inline void do_oop_nv(oop* p) { 33.87 + template <class T> void do_oop_nv(T* p) { 33.88 do_oop_work(p); 33.89 if (do_mark_forwardee) 33.90 mark_forwardee(p); 33.91 } 33.92 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.93 virtual void do_oop(oop* p) { do_oop_nv(p); } 33.94 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.95 }; 33.96 33.97 typedef G1ParCopyClosure<false, G1BarrierNone, false, false> G1ParScanExtRootClosure; 33.98 typedef G1ParCopyClosure<true, G1BarrierNone, false, false> G1ParScanPermClosure; 33.99 +typedef G1ParCopyClosure<false, G1BarrierRS, false, false> G1ParScanHeapRSClosure; 33.100 typedef G1ParCopyClosure<false, G1BarrierNone, true, false> G1ParScanAndMarkExtRootClosure; 33.101 typedef G1ParCopyClosure<true, G1BarrierNone, true, false> G1ParScanAndMarkPermClosure; 33.102 -typedef G1ParCopyClosure<false, G1BarrierRS, false, false> G1ParScanHeapRSClosure; 33.103 typedef G1ParCopyClosure<false, G1BarrierRS, true, false> G1ParScanAndMarkHeapRSClosure; 33.104 // This is the only case when we set skip_cset_test. Basically, this 33.105 // closure is (should?) only be called directly while we're draining 33.106 // the overflow and task queues. In that case we know that the 33.107 // reference in question points into the collection set, otherwise we 33.108 -// would not have pushed it on the queue. 33.109 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure; 33.110 +// would not have pushed it on the queue. The following is defined in 33.111 +// g1_specialized_oop_closures.hpp. 33.112 +// typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure; 33.113 // We need a separate closure to handle references during evacuation 33.114 -// failure processing, as it cannot asume that the reference already 33.115 - // points to the collection set (like G1ParScanHeapEvacClosure does). 33.116 +// failure processing, as we cannot asume that the reference already 33.117 +// points into the collection set (like G1ParScanHeapEvacClosure does). 33.118 typedef G1ParCopyClosure<false, G1BarrierEvac, false, false> G1ParScanHeapEvacFailureClosure; 33.119 33.120 class FilterIntoCSClosure: public OopClosure { 33.121 @@ -158,10 +143,9 @@ 33.122 G1CollectedHeap* g1, OopClosure* oc) : 33.123 _dcto_cl(dcto_cl), _g1(g1), _oc(oc) 33.124 {} 33.125 - inline void do_oop_nv(oop* p); 33.126 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.127 - virtual void do_oop(oop* p); 33.128 - virtual void do_oop(narrowOop* p) { guarantee(false, "NYI"); } 33.129 + template <class T> void do_oop_nv(T* p); 33.130 + virtual void do_oop(oop* p) { do_oop_nv(p); } 33.131 + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.132 bool apply_to_weak_ref_discovered_field() { return true; } 33.133 bool do_header() { return false; } 33.134 }; 33.135 @@ -174,10 +158,9 @@ 33.136 OopsInHeapRegionClosure* oc) : 33.137 _g1(g1), _oc(oc) 33.138 {} 33.139 - inline void do_oop_nv(oop* p); 33.140 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.141 - virtual void do_oop(oop* p); 33.142 - virtual void do_oop(narrowOop* p) { guarantee(false, "NYI"); } 33.143 + template <class T> void do_oop_nv(T* p); 33.144 + virtual void do_oop(oop* p) { do_oop_nv(p); } 33.145 + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.146 bool apply_to_weak_ref_discovered_field() { return true; } 33.147 bool do_header() { return false; } 33.148 void set_region(HeapRegion* from) { 33.149 @@ -195,10 +178,9 @@ 33.150 ConcurrentMark* cm) 33.151 : _g1(g1), _oc(oc), _cm(cm) { } 33.152 33.153 - inline void do_oop_nv(oop* p); 33.154 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.155 - virtual void do_oop(oop* p); 33.156 - virtual void do_oop(narrowOop* p) { guarantee(false, "NYI"); } 33.157 + template <class T> void do_oop_nv(T* p); 33.158 + virtual void do_oop(oop* p) { do_oop_nv(p); } 33.159 + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.160 bool apply_to_weak_ref_discovered_field() { return true; } 33.161 bool do_header() { return false; } 33.162 void set_region(HeapRegion* from) { 33.163 @@ -213,10 +195,9 @@ 33.164 int _out_of_region; 33.165 public: 33.166 FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc); 33.167 - inline void do_oop_nv(oop* p); 33.168 - inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); } 33.169 - virtual void do_oop(oop* p); 33.170 - virtual void do_oop(narrowOop* p) { guarantee(false, "NYI"); } 33.171 + template <class T> void do_oop_nv(T* p); 33.172 + virtual void do_oop(oop* p) { do_oop_nv(p); } 33.173 + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 33.174 bool apply_to_weak_ref_discovered_field() { return true; } 33.175 bool do_header() { return false; } 33.176 int out_of_region() { return _out_of_region; }
34.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Mon Jul 20 08:20:00 2009 -0700 34.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Mon Jul 27 06:15:29 2009 -0700 34.3 @@ -31,9 +31,10 @@ 34.4 // perf-critical inner loop. 34.5 #define FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT 0 34.6 34.7 -inline void FilterIntoCSClosure::do_oop_nv(oop* p) { 34.8 - oop obj = *p; 34.9 - if (obj != NULL && _g1->obj_in_cs(obj)) { 34.10 +template <class T> inline void FilterIntoCSClosure::do_oop_nv(T* p) { 34.11 + T heap_oop = oopDesc::load_heap_oop(p); 34.12 + if (!oopDesc::is_null(heap_oop) && 34.13 + _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) { 34.14 _oc->do_oop(p); 34.15 #if FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT 34.16 _dcto_cl->incr_count(); 34.17 @@ -41,44 +42,32 @@ 34.18 } 34.19 } 34.20 34.21 -inline void FilterIntoCSClosure::do_oop(oop* p) 34.22 -{ 34.23 - do_oop_nv(p); 34.24 -} 34.25 - 34.26 #define FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT 0 34.27 34.28 -inline void FilterOutOfRegionClosure::do_oop_nv(oop* p) { 34.29 - oop obj = *p; 34.30 - HeapWord* obj_hw = (HeapWord*)obj; 34.31 - if (obj_hw != NULL && (obj_hw < _r_bottom || obj_hw >= _r_end)) { 34.32 - _oc->do_oop(p); 34.33 +template <class T> inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { 34.34 + T heap_oop = oopDesc::load_heap_oop(p); 34.35 + if (!oopDesc::is_null(heap_oop)) { 34.36 + HeapWord* obj_hw = (HeapWord*)oopDesc::decode_heap_oop_not_null(heap_oop); 34.37 + if (obj_hw < _r_bottom || obj_hw >= _r_end) { 34.38 + _oc->do_oop(p); 34.39 #if FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT 34.40 - _out_of_region++; 34.41 + _out_of_region++; 34.42 #endif 34.43 + } 34.44 } 34.45 } 34.46 34.47 -inline void FilterOutOfRegionClosure::do_oop(oop* p) 34.48 -{ 34.49 - do_oop_nv(p); 34.50 -} 34.51 - 34.52 -inline void FilterInHeapRegionAndIntoCSClosure::do_oop_nv(oop* p) { 34.53 - oop obj = *p; 34.54 - if (obj != NULL && _g1->obj_in_cs(obj)) 34.55 +template <class T> inline void FilterInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) { 34.56 + T heap_oop = oopDesc::load_heap_oop(p); 34.57 + if (!oopDesc::is_null(heap_oop) && 34.58 + _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) 34.59 _oc->do_oop(p); 34.60 } 34.61 34.62 -inline void FilterInHeapRegionAndIntoCSClosure::do_oop(oop* p) 34.63 -{ 34.64 - do_oop_nv(p); 34.65 -} 34.66 - 34.67 - 34.68 -inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop_nv(oop* p) { 34.69 - oop obj = *p; 34.70 - if (obj != NULL) { 34.71 +template <class T> inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) { 34.72 + T heap_oop = oopDesc::load_heap_oop(p); 34.73 + if (!oopDesc::is_null(heap_oop)) { 34.74 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 34.75 HeapRegion* hr = _g1->heap_region_containing((HeapWord*) obj); 34.76 if (hr != NULL) { 34.77 if (hr->in_collection_set()) 34.78 @@ -89,24 +78,29 @@ 34.79 } 34.80 } 34.81 34.82 -inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop(oop* p) 34.83 -{ 34.84 - do_oop_nv(p); 34.85 +// This closure is applied to the fields of the objects that have just been copied. 34.86 +template <class T> inline void G1ParScanClosure::do_oop_nv(T* p) { 34.87 + T heap_oop = oopDesc::load_heap_oop(p); 34.88 + 34.89 + if (!oopDesc::is_null(heap_oop)) { 34.90 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 34.91 + if (_g1->in_cset_fast_test(obj)) { 34.92 + // We're not going to even bother checking whether the object is 34.93 + // already forwarded or not, as this usually causes an immediate 34.94 + // stall. We'll try to prefetch the object (for write, given that 34.95 + // we might need to install the forwarding reference) and we'll 34.96 + // get back to it when pop it from the queue 34.97 + Prefetch::write(obj->mark_addr(), 0); 34.98 + Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); 34.99 + 34.100 + // slightly paranoid test; I'm trying to catch potential 34.101 + // problems before we go into push_on_queue to know where the 34.102 + // problem is coming from 34.103 + assert(obj == oopDesc::load_decode_heap_oop(p), 34.104 + "p should still be pointing to obj"); 34.105 + _par_scan_state->push_on_queue(p); 34.106 + } else { 34.107 + _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 34.108 + } 34.109 + } 34.110 } 34.111 - 34.112 -inline void G1ScanAndBalanceClosure::do_oop_nv(oop* p) { 34.113 - RefToScanQueue* q; 34.114 - if (ParallelGCThreads > 0) { 34.115 - // Deal the work out equally. 34.116 - _nq = (_nq + 1) % ParallelGCThreads; 34.117 - q = _g1->task_queue(_nq); 34.118 - } else { 34.119 - q = _g1->task_queue(0); 34.120 - } 34.121 - bool nooverflow = q->push(p); 34.122 - guarantee(nooverflow, "Overflow during poplularity region processing"); 34.123 -} 34.124 - 34.125 -inline void G1ScanAndBalanceClosure::do_oop(oop* p) { 34.126 - do_oop_nv(p); 34.127 -}
35.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Mon Jul 20 08:20:00 2009 -0700 35.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Mon Jul 27 06:15:29 2009 -0700 35.3 @@ -65,11 +65,10 @@ 35.4 void set_region(HeapRegion* from) { 35.5 _blk->set_region(from); 35.6 } 35.7 - virtual void do_oop(narrowOop* p) { 35.8 - guarantee(false, "NYI"); 35.9 - } 35.10 - virtual void do_oop(oop* p) { 35.11 - oop obj = *p; 35.12 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 35.13 + virtual void do_oop( oop* p) { do_oop_work(p); } 35.14 + template <class T> void do_oop_work(T* p) { 35.15 + oop obj = oopDesc::load_decode_heap_oop(p); 35.16 if (_g1->obj_in_cs(obj)) _blk->do_oop(p); 35.17 } 35.18 bool apply_to_weak_ref_discovered_field() { return true; } 35.19 @@ -110,11 +109,10 @@ 35.20 public: 35.21 VerifyRSCleanCardOopClosure(G1CollectedHeap* g1) : _g1(g1) {} 35.22 35.23 - virtual void do_oop(narrowOop* p) { 35.24 - guarantee(false, "NYI"); 35.25 - } 35.26 - virtual void do_oop(oop* p) { 35.27 - oop obj = *p; 35.28 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 35.29 + virtual void do_oop( oop* p) { do_oop_work(p); } 35.30 + template <class T> void do_oop_work(T* p) { 35.31 + oop obj = oopDesc::load_decode_heap_oop(p); 35.32 HeapRegion* to = _g1->heap_region_containing(obj); 35.33 guarantee(to == NULL || !to->in_collection_set(), 35.34 "Missed a rem set member."); 35.35 @@ -129,9 +127,9 @@ 35.36 { 35.37 _seq_task = new SubTasksDone(NumSeqTasks); 35.38 guarantee(n_workers() > 0, "There should be some workers"); 35.39 - _new_refs = NEW_C_HEAP_ARRAY(GrowableArray<oop*>*, n_workers()); 35.40 + _new_refs = NEW_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, n_workers()); 35.41 for (uint i = 0; i < n_workers(); i++) { 35.42 - _new_refs[i] = new (ResourceObj::C_HEAP) GrowableArray<oop*>(8192,true); 35.43 + _new_refs[i] = new (ResourceObj::C_HEAP) GrowableArray<OopOrNarrowOopStar>(8192,true); 35.44 } 35.45 } 35.46 35.47 @@ -140,7 +138,7 @@ 35.48 for (uint i = 0; i < n_workers(); i++) { 35.49 delete _new_refs[i]; 35.50 } 35.51 - FREE_C_HEAP_ARRAY(GrowableArray<oop*>*, _new_refs); 35.52 + FREE_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, _new_refs); 35.53 } 35.54 35.55 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) { 35.56 @@ -428,15 +426,15 @@ 35.57 } 35.58 }; 35.59 35.60 -void 35.61 -HRInto_G1RemSet::scanNewRefsRS(OopsInHeapRegionClosure* oc, 35.62 - int worker_i) { 35.63 +template <class T> void 35.64 +HRInto_G1RemSet::scanNewRefsRS_work(OopsInHeapRegionClosure* oc, 35.65 + int worker_i) { 35.66 double scan_new_refs_start_sec = os::elapsedTime(); 35.67 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 35.68 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set()); 35.69 for (int i = 0; i < _new_refs[worker_i]->length(); i++) { 35.70 - oop* p = _new_refs[worker_i]->at(i); 35.71 - oop obj = *p; 35.72 + T* p = (T*) _new_refs[worker_i]->at(i); 35.73 + oop obj = oopDesc::load_decode_heap_oop(p); 35.74 // *p was in the collection set when p was pushed on "_new_refs", but 35.75 // another thread may have processed this location from an RS, so it 35.76 // might not point into the CS any longer. If so, it's obviously been 35.77 @@ -549,11 +547,10 @@ 35.78 G1CollectedHeap* _g1; 35.79 public: 35.80 UpdateRSetOopsIntoCSImmediate(G1CollectedHeap* g1) : _g1(g1) { } 35.81 - virtual void do_oop(narrowOop* p) { 35.82 - guarantee(false, "NYI"); 35.83 - } 35.84 - virtual void do_oop(oop* p) { 35.85 - HeapRegion* to = _g1->heap_region_containing(*p); 35.86 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 35.87 + virtual void do_oop( oop* p) { do_oop_work(p); } 35.88 + template <class T> void do_oop_work(T* p) { 35.89 + HeapRegion* to = _g1->heap_region_containing(oopDesc::load_decode_heap_oop(p)); 35.90 if (to->in_collection_set()) { 35.91 to->rem_set()->add_reference(p, 0); 35.92 } 35.93 @@ -567,11 +564,10 @@ 35.94 public: 35.95 UpdateRSetOopsIntoCSDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : 35.96 _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) { } 35.97 - virtual void do_oop(narrowOop* p) { 35.98 - guarantee(false, "NYI"); 35.99 - } 35.100 - virtual void do_oop(oop* p) { 35.101 - oop obj = *p; 35.102 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 35.103 + virtual void do_oop( oop* p) { do_oop_work(p); } 35.104 + template <class T> void do_oop_work(T* p) { 35.105 + oop obj = oopDesc::load_decode_heap_oop(p); 35.106 if (_g1->obj_in_cs(obj)) { 35.107 size_t card_index = _ct_bs->index_for(p); 35.108 if (_ct_bs->mark_card_deferred(card_index)) { 35.109 @@ -581,10 +577,10 @@ 35.110 } 35.111 }; 35.112 35.113 -void HRInto_G1RemSet::new_refs_iterate(OopClosure* cl) { 35.114 +template <class T> void HRInto_G1RemSet::new_refs_iterate_work(OopClosure* cl) { 35.115 for (size_t i = 0; i < n_workers(); i++) { 35.116 for (int j = 0; j < _new_refs[i]->length(); j++) { 35.117 - oop* p = _new_refs[i]->at(j); 35.118 + T* p = (T*) _new_refs[i]->at(j); 35.119 cl->do_oop(p); 35.120 } 35.121 }
36.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp Mon Jul 20 08:20:00 2009 -0700 36.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp Mon Jul 27 06:15:29 2009 -0700 36.3 @@ -62,10 +62,12 @@ 36.4 // If "this" is of the given subtype, return "this", else "NULL". 36.5 virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; } 36.6 36.7 - // Record, if necessary, the fact that *p (where "p" is in region "from") 36.8 - // has changed to its new value. 36.9 + // Record, if necessary, the fact that *p (where "p" is in region "from", 36.10 + // and is, a fortiori, required to be non-NULL) has changed to its new value. 36.11 virtual void write_ref(HeapRegion* from, oop* p) = 0; 36.12 + virtual void write_ref(HeapRegion* from, narrowOop* p) = 0; 36.13 virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0; 36.14 + virtual void par_write_ref(HeapRegion* from, narrowOop* p, int tid) = 0; 36.15 36.16 // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region 36.17 // or card, respectively, such that a region or card with a corresponding 36.18 @@ -105,7 +107,9 @@ 36.19 36.20 // Nothing is necessary in the version below. 36.21 void write_ref(HeapRegion* from, oop* p) {} 36.22 + void write_ref(HeapRegion* from, narrowOop* p) {} 36.23 void par_write_ref(HeapRegion* from, oop* p, int tid) {} 36.24 + void par_write_ref(HeapRegion* from, narrowOop* p, int tid) {} 36.25 36.26 void scrub(BitMap* region_bm, BitMap* card_bm) {} 36.27 void scrub_par(BitMap* region_bm, BitMap* card_bm, 36.28 @@ -143,8 +147,19 @@ 36.29 // their references into the collection summarized in "_new_refs". 36.30 bool _par_traversal_in_progress; 36.31 void set_par_traversal(bool b) { _par_traversal_in_progress = b; } 36.32 - GrowableArray<oop*>** _new_refs; 36.33 - void new_refs_iterate(OopClosure* cl); 36.34 + GrowableArray<OopOrNarrowOopStar>** _new_refs; 36.35 + template <class T> void new_refs_iterate_work(OopClosure* cl); 36.36 + void new_refs_iterate(OopClosure* cl) { 36.37 + if (UseCompressedOops) { 36.38 + new_refs_iterate_work<narrowOop>(cl); 36.39 + } else { 36.40 + new_refs_iterate_work<oop>(cl); 36.41 + } 36.42 + } 36.43 + 36.44 +protected: 36.45 + template <class T> void write_ref_nv(HeapRegion* from, T* p); 36.46 + template <class T> void par_write_ref_nv(HeapRegion* from, T* p, int tid); 36.47 36.48 public: 36.49 // This is called to reset dual hash tables after the gc pause 36.50 @@ -161,7 +176,14 @@ 36.51 void prepare_for_oops_into_collection_set_do(); 36.52 void cleanup_after_oops_into_collection_set_do(); 36.53 void scanRS(OopsInHeapRegionClosure* oc, int worker_i); 36.54 - void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i); 36.55 + template <class T> void scanNewRefsRS_work(OopsInHeapRegionClosure* oc, int worker_i); 36.56 + void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i) { 36.57 + if (UseCompressedOops) { 36.58 + scanNewRefsRS_work<narrowOop>(oc, worker_i); 36.59 + } else { 36.60 + scanNewRefsRS_work<oop>(oc, worker_i); 36.61 + } 36.62 + } 36.63 void updateRS(int worker_i); 36.64 HeapRegion* calculateStartRegion(int i); 36.65 36.66 @@ -172,12 +194,22 @@ 36.67 36.68 // Record, if necessary, the fact that *p (where "p" is in region "from", 36.69 // which is required to be non-NULL) has changed to a new non-NULL value. 36.70 - inline void write_ref(HeapRegion* from, oop* p); 36.71 - // The "_nv" version is the same; it exists just so that it is not virtual. 36.72 - inline void write_ref_nv(HeapRegion* from, oop* p); 36.73 + // [Below the virtual version calls a non-virtual protected 36.74 + // workhorse that is templatified for narrow vs wide oop.] 36.75 + inline void write_ref(HeapRegion* from, oop* p) { 36.76 + write_ref_nv(from, p); 36.77 + } 36.78 + inline void write_ref(HeapRegion* from, narrowOop* p) { 36.79 + write_ref_nv(from, p); 36.80 + } 36.81 + inline void par_write_ref(HeapRegion* from, oop* p, int tid) { 36.82 + par_write_ref_nv(from, p, tid); 36.83 + } 36.84 + inline void par_write_ref(HeapRegion* from, narrowOop* p, int tid) { 36.85 + par_write_ref_nv(from, p, tid); 36.86 + } 36.87 36.88 - inline bool self_forwarded(oop obj); 36.89 - inline void par_write_ref(HeapRegion* from, oop* p, int tid); 36.90 + bool self_forwarded(oop obj); 36.91 36.92 void scrub(BitMap* region_bm, BitMap* card_bm); 36.93 void scrub_par(BitMap* region_bm, BitMap* card_bm, 36.94 @@ -208,6 +240,9 @@ 36.95 HeapRegion* _from; 36.96 HRInto_G1RemSet* _rs; 36.97 int _worker_i; 36.98 + 36.99 + template <class T> void do_oop_work(T* p); 36.100 + 36.101 public: 36.102 UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) : 36.103 _from(NULL), _rs(rs), _worker_i(worker_i) { 36.104 @@ -219,11 +254,10 @@ 36.105 _from = from; 36.106 } 36.107 36.108 - virtual void do_oop(narrowOop* p); 36.109 - virtual void do_oop(oop* p); 36.110 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 36.111 + virtual void do_oop(oop* p) { do_oop_work(p); } 36.112 36.113 // Override: this closure is idempotent. 36.114 // bool idempotent() { return true; } 36.115 bool apply_to_weak_ref_discovered_field() { return true; } 36.116 }; 36.117 -
37.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Mon Jul 20 08:20:00 2009 -0700 37.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Mon Jul 27 06:15:29 2009 -0700 37.3 @@ -30,12 +30,8 @@ 37.4 } 37.5 } 37.6 37.7 -inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, oop* p) { 37.8 - par_write_ref(from, p, 0); 37.9 -} 37.10 - 37.11 -inline void HRInto_G1RemSet::write_ref(HeapRegion* from, oop* p) { 37.12 - write_ref_nv(from, p); 37.13 +template <class T> inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, T* p) { 37.14 + par_write_ref_nv(from, p, 0); 37.15 } 37.16 37.17 inline bool HRInto_G1RemSet::self_forwarded(oop obj) { 37.18 @@ -43,8 +39,8 @@ 37.19 return result; 37.20 } 37.21 37.22 -inline void HRInto_G1RemSet::par_write_ref(HeapRegion* from, oop* p, int tid) { 37.23 - oop obj = *p; 37.24 +template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) { 37.25 + oop obj = oopDesc::load_decode_heap_oop(p); 37.26 #ifdef ASSERT 37.27 // can't do because of races 37.28 // assert(obj == NULL || obj->is_oop(), "expected an oop"); 37.29 @@ -71,7 +67,7 @@ 37.30 // false during the evacuation failure handing. 37.31 if (_par_traversal_in_progress && 37.32 to->in_collection_set() && !self_forwarded(obj)) { 37.33 - _new_refs[tid]->push(p); 37.34 + _new_refs[tid]->push((void*)p); 37.35 // Deferred updates to the Cset are either discarded (in the normal case), 37.36 // or processed (if an evacuation failure occurs) at the end 37.37 // of the collection. 37.38 @@ -89,11 +85,7 @@ 37.39 } 37.40 } 37.41 37.42 -inline void UpdateRSOopClosure::do_oop(narrowOop* p) { 37.43 - guarantee(false, "NYI"); 37.44 -} 37.45 - 37.46 -inline void UpdateRSOopClosure::do_oop(oop* p) { 37.47 +template <class T> inline void UpdateRSOopClosure::do_oop_work(T* p) { 37.48 assert(_from != NULL, "from region must be non-NULL"); 37.49 _rs->par_write_ref(_from, p, _worker_i); 37.50 }
38.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Mon Jul 20 08:20:00 2009 -0700 38.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Mon Jul 27 06:15:29 2009 -0700 38.3 @@ -34,6 +34,7 @@ 38.4 38.5 38.6 void G1SATBCardTableModRefBS::enqueue(oop pre_val) { 38.7 + assert(pre_val->is_oop_or_null(true), "Error"); 38.8 if (!JavaThread::satb_mark_queue_set().active()) return; 38.9 Thread* thr = Thread::current(); 38.10 if (thr->is_Java_thread()) { 38.11 @@ -46,32 +47,31 @@ 38.12 } 38.13 38.14 // When we know the current java thread: 38.15 -void 38.16 -G1SATBCardTableModRefBS::write_ref_field_pre_static(void* field, 38.17 - oop newVal, 38.18 +template <class T> void 38.19 +G1SATBCardTableModRefBS::write_ref_field_pre_static(T* field, 38.20 + oop new_val, 38.21 JavaThread* jt) { 38.22 if (!JavaThread::satb_mark_queue_set().active()) return; 38.23 - assert(!UseCompressedOops, "Else will need to modify this to deal with narrowOop"); 38.24 - oop preVal = *(oop*)field; 38.25 - if (preVal != NULL) { 38.26 - jt->satb_mark_queue().enqueue(preVal); 38.27 + T heap_oop = oopDesc::load_heap_oop(field); 38.28 + if (!oopDesc::is_null(heap_oop)) { 38.29 + oop pre_val = oopDesc::decode_heap_oop_not_null(heap_oop); 38.30 + assert(pre_val->is_oop(true /* ignore mark word */), "Error"); 38.31 + jt->satb_mark_queue().enqueue(pre_val); 38.32 } 38.33 } 38.34 38.35 -void 38.36 -G1SATBCardTableModRefBS::write_ref_array_pre(MemRegion mr) { 38.37 +template <class T> void 38.38 +G1SATBCardTableModRefBS::write_ref_array_pre_work(T* dst, int count) { 38.39 if (!JavaThread::satb_mark_queue_set().active()) return; 38.40 - assert(!UseCompressedOops, "Else will need to modify this to deal with narrowOop"); 38.41 - oop* elem_ptr = (oop*)mr.start(); 38.42 - while ((HeapWord*)elem_ptr < mr.end()) { 38.43 - oop elem = *elem_ptr; 38.44 - if (elem != NULL) enqueue(elem); 38.45 - elem_ptr++; 38.46 + T* elem_ptr = dst; 38.47 + for (int i = 0; i < count; i++, elem_ptr++) { 38.48 + T heap_oop = oopDesc::load_heap_oop(elem_ptr); 38.49 + if (!oopDesc::is_null(heap_oop)) { 38.50 + enqueue(oopDesc::decode_heap_oop_not_null(heap_oop)); 38.51 + } 38.52 } 38.53 } 38.54 38.55 - 38.56 - 38.57 G1SATBCardTableLoggingModRefBS:: 38.58 G1SATBCardTableLoggingModRefBS(MemRegion whole_heap, 38.59 int max_covered_regions) :
39.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Mon Jul 20 08:20:00 2009 -0700 39.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Mon Jul 27 06:15:29 2009 -0700 39.3 @@ -47,31 +47,41 @@ 39.4 39.5 // This notes that we don't need to access any BarrierSet data 39.6 // structures, so this can be called from a static context. 39.7 - static void write_ref_field_pre_static(void* field, oop newVal) { 39.8 - assert(!UseCompressedOops, "Else needs to be templatized"); 39.9 - oop preVal = *((oop*)field); 39.10 - if (preVal != NULL) { 39.11 - enqueue(preVal); 39.12 + template <class T> static void write_ref_field_pre_static(T* field, oop newVal) { 39.13 + T heap_oop = oopDesc::load_heap_oop(field); 39.14 + if (!oopDesc::is_null(heap_oop)) { 39.15 + enqueue(oopDesc::decode_heap_oop(heap_oop)); 39.16 } 39.17 } 39.18 39.19 // When we know the current java thread: 39.20 - static void write_ref_field_pre_static(void* field, oop newVal, 39.21 - JavaThread* jt); 39.22 + template <class T> static void write_ref_field_pre_static(T* field, oop newVal, 39.23 + JavaThread* jt); 39.24 39.25 // We export this to make it available in cases where the static 39.26 // type of the barrier set is known. Note that it is non-virtual. 39.27 - inline void inline_write_ref_field_pre(void* field, oop newVal) { 39.28 + template <class T> inline void inline_write_ref_field_pre(T* field, oop newVal) { 39.29 write_ref_field_pre_static(field, newVal); 39.30 } 39.31 39.32 - // This is the more general virtual version. 39.33 - void write_ref_field_pre_work(void* field, oop new_val) { 39.34 + // These are the more general virtual versions. 39.35 + virtual void write_ref_field_pre_work(oop* field, oop new_val) { 39.36 inline_write_ref_field_pre(field, new_val); 39.37 } 39.38 + virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) { 39.39 + inline_write_ref_field_pre(field, new_val); 39.40 + } 39.41 + virtual void write_ref_field_pre_work(void* field, oop new_val) { 39.42 + guarantee(false, "Not needed"); 39.43 + } 39.44 39.45 - virtual void write_ref_array_pre(MemRegion mr); 39.46 - 39.47 + template <class T> void write_ref_array_pre_work(T* dst, int count); 39.48 + virtual void write_ref_array_pre(oop* dst, int count) { 39.49 + write_ref_array_pre_work(dst, count); 39.50 + } 39.51 + virtual void write_ref_array_pre(narrowOop* dst, int count) { 39.52 + write_ref_array_pre_work(dst, count); 39.53 + } 39.54 }; 39.55 39.56 // Adds card-table logging to the post-barrier.
40.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Mon Jul 20 08:20:00 2009 -0700 40.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Mon Jul 27 06:15:29 2009 -0700 40.3 @@ -80,9 +80,6 @@ 40.4 develop(bool, G1TraceConcurrentRefinement, false, \ 40.5 "Trace G1 concurrent refinement") \ 40.6 \ 40.7 - develop(bool, G1ConcMark, true, \ 40.8 - "If true, run concurrent marking for G1") \ 40.9 - \ 40.10 product(intx, G1MarkStackSize, 2 * 1024 * 1024, \ 40.11 "Size of the mark stack for concurrent marking.") \ 40.12 \
41.1 --- a/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Mon Jul 20 08:20:00 2009 -0700 41.2 +++ b/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Mon Jul 27 06:15:29 2009 -0700 41.3 @@ -37,14 +37,12 @@ 41.4 class G1ParCopyClosure; 41.5 class G1ParScanClosure; 41.6 41.7 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> 41.8 - G1ParScanHeapEvacClosure; 41.9 +typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure; 41.10 41.11 class FilterIntoCSClosure; 41.12 class FilterOutOfRegionClosure; 41.13 class FilterInHeapRegionAndIntoCSClosure; 41.14 class FilterAndMarkInHeapRegionAndIntoCSClosure; 41.15 -class G1ScanAndBalanceClosure; 41.16 41.17 #ifdef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES 41.18 #error "FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES already defined." 41.19 @@ -56,8 +54,7 @@ 41.20 f(FilterIntoCSClosure,_nv) \ 41.21 f(FilterOutOfRegionClosure,_nv) \ 41.22 f(FilterInHeapRegionAndIntoCSClosure,_nv) \ 41.23 - f(FilterAndMarkInHeapRegionAndIntoCSClosure,_nv) \ 41.24 - f(G1ScanAndBalanceClosure,_nv) 41.25 + f(FilterAndMarkInHeapRegionAndIntoCSClosure,_nv) 41.26 41.27 #ifdef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES 41.28 #error "FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES already defined."
42.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Mon Jul 20 08:20:00 2009 -0700 42.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Mon Jul 27 06:15:29 2009 -0700 42.3 @@ -66,16 +66,16 @@ 42.4 bool failures() { return _failures; } 42.5 int n_failures() { return _n_failures; } 42.6 42.7 - virtual void do_oop(narrowOop* p) { 42.8 - guarantee(false, "NYI"); 42.9 - } 42.10 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 42.11 + virtual void do_oop( oop* p) { do_oop_work(p); } 42.12 42.13 - void do_oop(oop* p) { 42.14 + template <class T> void do_oop_work(T* p) { 42.15 assert(_containing_obj != NULL, "Precondition"); 42.16 assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking), 42.17 "Precondition"); 42.18 - oop obj = *p; 42.19 - if (obj != NULL) { 42.20 + T heap_oop = oopDesc::load_heap_oop(p); 42.21 + if (!oopDesc::is_null(heap_oop)) { 42.22 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 42.23 bool failed = false; 42.24 if (!_g1h->is_in_closed_subset(obj) || 42.25 _g1h->is_obj_dead_cond(obj, _use_prev_marking)) { 42.26 @@ -106,8 +106,8 @@ 42.27 } 42.28 42.29 if (!_g1h->full_collection()) { 42.30 - HeapRegion* from = _g1h->heap_region_containing(p); 42.31 - HeapRegion* to = _g1h->heap_region_containing(*p); 42.32 + HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); 42.33 + HeapRegion* to = _g1h->heap_region_containing(obj); 42.34 if (from != NULL && to != NULL && 42.35 from != to && 42.36 !to->isHumongous()) { 42.37 @@ -534,13 +534,13 @@ 42.38 // Otherwise, find the obj that extends onto mr.start(). 42.39 42.40 assert(cur <= mr.start() 42.41 - && (oop(cur)->klass() == NULL || 42.42 + && (oop(cur)->klass_or_null() == NULL || 42.43 cur + oop(cur)->size() > mr.start()), 42.44 "postcondition of block_start"); 42.45 oop obj; 42.46 while (cur < mr.end()) { 42.47 obj = oop(cur); 42.48 - if (obj->klass() == NULL) { 42.49 + if (obj->klass_or_null() == NULL) { 42.50 // Ran into an unparseable point. 42.51 return cur; 42.52 } else if (!g1h->is_obj_dead(obj)) { 42.53 @@ -577,7 +577,7 @@ 42.54 assert(cur <= mr.start(), "Postcondition"); 42.55 42.56 while (cur <= mr.start()) { 42.57 - if (oop(cur)->klass() == NULL) { 42.58 + if (oop(cur)->klass_or_null() == NULL) { 42.59 // Ran into an unparseable point. 42.60 return cur; 42.61 } 42.62 @@ -591,7 +591,7 @@ 42.63 obj = oop(cur); 42.64 // If we finish this loop... 42.65 assert(cur <= mr.start() 42.66 - && obj->klass() != NULL 42.67 + && obj->klass_or_null() != NULL 42.68 && cur + obj->size() > mr.start(), 42.69 "Loop postcondition"); 42.70 if (!g1h->is_obj_dead(obj)) { 42.71 @@ -601,7 +601,7 @@ 42.72 HeapWord* next; 42.73 while (cur < mr.end()) { 42.74 obj = oop(cur); 42.75 - if (obj->klass() == NULL) { 42.76 + if (obj->klass_or_null() == NULL) { 42.77 // Ran into an unparseable point. 42.78 return cur; 42.79 }; 42.80 @@ -703,7 +703,7 @@ 42.81 } 42.82 if (vl_cl.failures()) { 42.83 gclog_or_tty->print_cr("Heap:"); 42.84 - G1CollectedHeap::heap()->print(); 42.85 + G1CollectedHeap::heap()->print_on(gclog_or_tty, true /* extended */); 42.86 gclog_or_tty->print_cr(""); 42.87 } 42.88 if (VerifyDuringGC && 42.89 @@ -781,8 +781,13 @@ 42.90 // will pick up the right saved_mark_word() as the high water mark 42.91 // of the region. Either way, the behaviour will be correct. 42.92 ContiguousSpace::set_saved_mark(); 42.93 + OrderAccess::storestore(); 42.94 _gc_time_stamp = curr_gc_time_stamp; 42.95 - OrderAccess::fence(); 42.96 + // The following fence is to force a flush of the writes above, but 42.97 + // is strictly not needed because when an allocating worker thread 42.98 + // calls set_saved_mark() it does so under the ParGCRareEvent_lock; 42.99 + // when the lock is released, the write will be flushed. 42.100 + // OrderAccess::fence(); 42.101 } 42.102 } 42.103
43.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Jul 20 08:20:00 2009 -0700 43.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Jul 27 06:15:29 2009 -0700 43.3 @@ -126,7 +126,7 @@ 43.4 } 43.5 } 43.6 43.7 - void add_reference_work(oop* from, bool par) { 43.8 + void add_reference_work(OopOrNarrowOopStar from, bool par) { 43.9 // Must make this robust in case "from" is not in "_hr", because of 43.10 // concurrency. 43.11 43.12 @@ -173,11 +173,11 @@ 43.13 _bm.clear(); 43.14 } 43.15 43.16 - void add_reference(oop* from) { 43.17 + void add_reference(OopOrNarrowOopStar from) { 43.18 add_reference_work(from, /*parallel*/ true); 43.19 } 43.20 43.21 - void seq_add_reference(oop* from) { 43.22 + void seq_add_reference(OopOrNarrowOopStar from) { 43.23 add_reference_work(from, /*parallel*/ false); 43.24 } 43.25 43.26 @@ -220,7 +220,7 @@ 43.27 } 43.28 43.29 // Requires "from" to be in "hr()". 43.30 - bool contains_reference(oop* from) const { 43.31 + bool contains_reference(OopOrNarrowOopStar from) const { 43.32 assert(hr()->is_in_reserved(from), "Precondition."); 43.33 size_t card_ind = pointer_delta(from, hr()->bottom(), 43.34 CardTableModRefBS::card_size); 43.35 @@ -394,7 +394,7 @@ 43.36 void set_next(PosParPRT* nxt) { _next = nxt; } 43.37 PosParPRT** next_addr() { return &_next; } 43.38 43.39 - void add_reference(oop* from, int tid) { 43.40 + void add_reference(OopOrNarrowOopStar from, int tid) { 43.41 // Expand if necessary. 43.42 PerRegionTable** pt = par_tables(); 43.43 if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) { 43.44 @@ -447,7 +447,7 @@ 43.45 return res; 43.46 } 43.47 43.48 - bool contains_reference(oop* from) const { 43.49 + bool contains_reference(OopOrNarrowOopStar from) const { 43.50 if (PerRegionTable::contains_reference(from)) return true; 43.51 if (_par_tables != NULL) { 43.52 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) { 43.53 @@ -564,12 +564,15 @@ 43.54 } 43.55 #endif 43.56 43.57 -void OtherRegionsTable::add_reference(oop* from, int tid) { 43.58 +void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { 43.59 size_t cur_hrs_ind = hr()->hrs_index(); 43.60 43.61 #if HRRS_VERBOSE 43.62 gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", 43.63 - from, *from); 43.64 + from, 43.65 + UseCompressedOops 43.66 + ? oopDesc::load_decode_heap_oop((narrowOop*)from) 43.67 + : oopDesc::load_decode_heap_oop((oop*)from)); 43.68 #endif 43.69 43.70 int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); 43.71 @@ -1021,13 +1024,13 @@ 43.72 } 43.73 } 43.74 43.75 -bool OtherRegionsTable::contains_reference(oop* from) const { 43.76 +bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const { 43.77 // Cast away const in this case. 43.78 MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag); 43.79 return contains_reference_locked(from); 43.80 } 43.81 43.82 -bool OtherRegionsTable::contains_reference_locked(oop* from) const { 43.83 +bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const { 43.84 HeapRegion* hr = _g1h->heap_region_containing_raw(from); 43.85 if (hr == NULL) return false; 43.86 RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index(); 43.87 @@ -1288,24 +1291,24 @@ 43.88 43.89 43.90 43.91 -oop** HeapRegionRemSet::_recorded_oops = NULL; 43.92 -HeapWord** HeapRegionRemSet::_recorded_cards = NULL; 43.93 -HeapRegion** HeapRegionRemSet::_recorded_regions = NULL; 43.94 -int HeapRegionRemSet::_n_recorded = 0; 43.95 +OopOrNarrowOopStar* HeapRegionRemSet::_recorded_oops = NULL; 43.96 +HeapWord** HeapRegionRemSet::_recorded_cards = NULL; 43.97 +HeapRegion** HeapRegionRemSet::_recorded_regions = NULL; 43.98 +int HeapRegionRemSet::_n_recorded = 0; 43.99 43.100 HeapRegionRemSet::Event* HeapRegionRemSet::_recorded_events = NULL; 43.101 int* HeapRegionRemSet::_recorded_event_index = NULL; 43.102 int HeapRegionRemSet::_n_recorded_events = 0; 43.103 43.104 -void HeapRegionRemSet::record(HeapRegion* hr, oop* f) { 43.105 +void HeapRegionRemSet::record(HeapRegion* hr, OopOrNarrowOopStar f) { 43.106 if (_recorded_oops == NULL) { 43.107 assert(_n_recorded == 0 43.108 && _recorded_cards == NULL 43.109 && _recorded_regions == NULL, 43.110 "Inv"); 43.111 - _recorded_oops = NEW_C_HEAP_ARRAY(oop*, MaxRecorded); 43.112 - _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded); 43.113 - _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded); 43.114 + _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded); 43.115 + _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded); 43.116 + _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded); 43.117 } 43.118 if (_n_recorded == MaxRecorded) { 43.119 gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded); 43.120 @@ -1408,21 +1411,21 @@ 43.121 HeapRegionRemSet* hrrs = hr0->rem_set(); 43.122 43.123 // Make three references from region 0x101... 43.124 - hrrs->add_reference((oop*)hr1_start); 43.125 - hrrs->add_reference((oop*)hr1_mid); 43.126 - hrrs->add_reference((oop*)hr1_last); 43.127 + hrrs->add_reference((OopOrNarrowOopStar)hr1_start); 43.128 + hrrs->add_reference((OopOrNarrowOopStar)hr1_mid); 43.129 + hrrs->add_reference((OopOrNarrowOopStar)hr1_last); 43.130 43.131 - hrrs->add_reference((oop*)hr2_start); 43.132 - hrrs->add_reference((oop*)hr2_mid); 43.133 - hrrs->add_reference((oop*)hr2_last); 43.134 + hrrs->add_reference((OopOrNarrowOopStar)hr2_start); 43.135 + hrrs->add_reference((OopOrNarrowOopStar)hr2_mid); 43.136 + hrrs->add_reference((OopOrNarrowOopStar)hr2_last); 43.137 43.138 - hrrs->add_reference((oop*)hr3_start); 43.139 - hrrs->add_reference((oop*)hr3_mid); 43.140 - hrrs->add_reference((oop*)hr3_last); 43.141 + hrrs->add_reference((OopOrNarrowOopStar)hr3_start); 43.142 + hrrs->add_reference((OopOrNarrowOopStar)hr3_mid); 43.143 + hrrs->add_reference((OopOrNarrowOopStar)hr3_last); 43.144 43.145 // Now cause a coarsening. 43.146 - hrrs->add_reference((oop*)hr4->bottom()); 43.147 - hrrs->add_reference((oop*)hr5->bottom()); 43.148 + hrrs->add_reference((OopOrNarrowOopStar)hr4->bottom()); 43.149 + hrrs->add_reference((OopOrNarrowOopStar)hr5->bottom()); 43.150 43.151 // Now, does iteration yield these three? 43.152 HeapRegionRemSetIterator iter;
44.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Jul 20 08:20:00 2009 -0700 44.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Jul 27 06:15:29 2009 -0700 44.3 @@ -116,9 +116,9 @@ 44.4 44.5 // For now. Could "expand" some tables in the future, so that this made 44.6 // sense. 44.7 - void add_reference(oop* from, int tid); 44.8 + void add_reference(OopOrNarrowOopStar from, int tid); 44.9 44.10 - void add_reference(oop* from) { 44.11 + void add_reference(OopOrNarrowOopStar from) { 44.12 return add_reference(from, 0); 44.13 } 44.14 44.15 @@ -140,8 +140,8 @@ 44.16 static size_t static_mem_size(); 44.17 static size_t fl_mem_size(); 44.18 44.19 - bool contains_reference(oop* from) const; 44.20 - bool contains_reference_locked(oop* from) const; 44.21 + bool contains_reference(OopOrNarrowOopStar from) const; 44.22 + bool contains_reference_locked(OopOrNarrowOopStar from) const; 44.23 44.24 void clear(); 44.25 44.26 @@ -192,10 +192,10 @@ 44.27 // Unused unless G1RecordHRRSOops is true. 44.28 44.29 static const int MaxRecorded = 1000000; 44.30 - static oop** _recorded_oops; 44.31 - static HeapWord** _recorded_cards; 44.32 - static HeapRegion** _recorded_regions; 44.33 - static int _n_recorded; 44.34 + static OopOrNarrowOopStar* _recorded_oops; 44.35 + static HeapWord** _recorded_cards; 44.36 + static HeapRegion** _recorded_regions; 44.37 + static int _n_recorded; 44.38 44.39 static const int MaxRecordedEvents = 1000; 44.40 static Event* _recorded_events; 44.41 @@ -231,13 +231,13 @@ 44.42 44.43 /* Used in the sequential case. Returns "true" iff this addition causes 44.44 the size limit to be reached. */ 44.45 - void add_reference(oop* from) { 44.46 + void add_reference(OopOrNarrowOopStar from) { 44.47 _other_regions.add_reference(from); 44.48 } 44.49 44.50 /* Used in the parallel case. Returns "true" iff this addition causes 44.51 the size limit to be reached. */ 44.52 - void add_reference(oop* from, int tid) { 44.53 + void add_reference(OopOrNarrowOopStar from, int tid) { 44.54 _other_regions.add_reference(from, tid); 44.55 } 44.56 44.57 @@ -301,7 +301,7 @@ 44.58 return OtherRegionsTable::fl_mem_size(); 44.59 } 44.60 44.61 - bool contains_reference(oop* from) const { 44.62 + bool contains_reference(OopOrNarrowOopStar from) const { 44.63 return _other_regions.contains_reference(from); 44.64 } 44.65 void print() const; 44.66 @@ -329,7 +329,7 @@ 44.67 } 44.68 #endif 44.69 44.70 - static void record(HeapRegion* hr, oop* f); 44.71 + static void record(HeapRegion* hr, OopOrNarrowOopStar f); 44.72 static void print_recorded(); 44.73 static void record_event(Event evnt); 44.74
45.1 --- a/src/share/vm/gc_implementation/g1/satbQueue.cpp Mon Jul 20 08:20:00 2009 -0700 45.2 +++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp Mon Jul 27 06:15:29 2009 -0700 45.3 @@ -43,6 +43,18 @@ 45.4 } 45.5 } 45.6 } 45.7 + 45.8 +#ifdef ASSERT 45.9 +void ObjPtrQueue::verify_oops_in_buffer() { 45.10 + if (_buf == NULL) return; 45.11 + for (size_t i = _index; i < _sz; i += oopSize) { 45.12 + oop obj = (oop)_buf[byte_index_to_index((int)i)]; 45.13 + assert(obj != NULL && obj->is_oop(true /* ignore mark word */), 45.14 + "Not an oop"); 45.15 + } 45.16 +} 45.17 +#endif 45.18 + 45.19 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away 45.20 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list 45.21 #endif // _MSC_VER 45.22 @@ -66,6 +78,7 @@ 45.23 45.24 45.25 void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) { 45.26 + DEBUG_ONLY(t->satb_mark_queue().verify_oops_in_buffer();) 45.27 t->satb_mark_queue().handle_zero_index(); 45.28 } 45.29 45.30 @@ -143,7 +156,7 @@ 45.31 } 45.32 _completed_buffers_tail = NULL; 45.33 _n_completed_buffers = 0; 45.34 - debug_only(assert_completed_buffer_list_len_correct_locked()); 45.35 + DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); 45.36 } 45.37 while (buffers_to_delete != NULL) { 45.38 CompletedBufferNode* nd = buffers_to_delete;
46.1 --- a/src/share/vm/gc_implementation/g1/satbQueue.hpp Mon Jul 20 08:20:00 2009 -0700 46.2 +++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp Mon Jul 27 06:15:29 2009 -0700 46.3 @@ -39,6 +39,7 @@ 46.4 static void apply_closure_to_buffer(ObjectClosure* cl, 46.5 void** buf, size_t index, size_t sz); 46.6 46.7 + void verify_oops_in_buffer() NOT_DEBUG_RETURN; 46.8 }; 46.9 46.10
47.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1 Mon Jul 20 08:20:00 2009 -0700 47.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1 Mon Jul 27 06:15:29 2009 -0700 47.3 @@ -27,6 +27,7 @@ 47.4 bufferingOopClosure.hpp genOopClosures.hpp 47.5 bufferingOopClosure.hpp generation.hpp 47.6 bufferingOopClosure.hpp os.hpp 47.7 +bufferingOopClosure.hpp taskqueue.hpp 47.8 47.9 cardTableRS.cpp concurrentMark.hpp 47.10 cardTableRS.cpp g1SATBCardTableModRefBS.hpp 47.11 @@ -139,7 +140,7 @@ 47.12 g1CollectedHeap.cpp g1CollectedHeap.inline.hpp 47.13 g1CollectedHeap.cpp g1CollectorPolicy.hpp 47.14 g1CollectedHeap.cpp g1MarkSweep.hpp 47.15 -g1CollectedHeap.cpp g1RemSet.hpp 47.16 +g1CollectedHeap.cpp g1RemSet.inline.hpp 47.17 g1CollectedHeap.cpp g1OopClosures.inline.hpp 47.18 g1CollectedHeap.cpp genOopClosures.inline.hpp 47.19 g1CollectedHeap.cpp gcLocker.inline.hpp 47.20 @@ -151,13 +152,14 @@ 47.21 g1CollectedHeap.cpp isGCActiveMark.hpp 47.22 g1CollectedHeap.cpp oop.inline.hpp 47.23 g1CollectedHeap.cpp oop.pcgc.inline.hpp 47.24 -g1CollectedHeap.cpp parGCAllocBuffer.hpp 47.25 g1CollectedHeap.cpp vm_operations_g1.hpp 47.26 g1CollectedHeap.cpp vmThread.hpp 47.27 47.28 g1CollectedHeap.hpp barrierSet.hpp 47.29 +g1CollectedHeap.hpp g1RemSet.hpp 47.30 g1CollectedHeap.hpp heapRegion.hpp 47.31 g1CollectedHeap.hpp memRegion.hpp 47.32 +g1CollectedHeap.hpp parGCAllocBuffer.hpp 47.33 g1CollectedHeap.hpp sharedHeap.hpp 47.34 47.35 g1CollectedHeap.inline.hpp concurrentMark.hpp 47.36 @@ -245,6 +247,7 @@ 47.37 g1RemSet.cpp iterator.hpp 47.38 g1RemSet.cpp oop.inline.hpp 47.39 47.40 +g1RemSet.inline.hpp oop.inline.hpp 47.41 g1RemSet.inline.hpp g1RemSet.hpp 47.42 g1RemSet.inline.hpp heapRegionRemSet.hpp 47.43 47.44 @@ -255,6 +258,7 @@ 47.45 g1SATBCardTableModRefBS.cpp thread_<os_family>.inline.hpp 47.46 g1SATBCardTableModRefBS.cpp satbQueue.hpp 47.47 47.48 +g1SATBCardTableModRefBS.hpp oop.inline.hpp 47.49 g1SATBCardTableModRefBS.hpp cardTableModRefBS.hpp 47.50 g1SATBCardTableModRefBS.hpp memRegion.hpp 47.51
48.1 --- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Mon Jul 20 08:20:00 2009 -0700 48.2 +++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Mon Jul 27 06:15:29 2009 -0700 48.3 @@ -31,9 +31,10 @@ 48.4 bool clear, 48.5 int n_threads) { 48.6 if (n_threads > 0) { 48.7 - assert(n_threads == (int)ParallelGCThreads, "# worker threads != # requested!"); 48.8 - 48.9 - // Make sure the LNC array is valid for the space. 48.10 + assert((n_threads == 1 && ParallelGCThreads == 0) || 48.11 + n_threads <= (int)ParallelGCThreads, 48.12 + "# worker threads != # requested!"); 48.13 + // Make sure the LNC array is valid for the space. 48.14 jbyte** lowest_non_clean; 48.15 uintptr_t lowest_non_clean_base_chunk_index; 48.16 size_t lowest_non_clean_chunk_size;
49.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Mon Jul 20 08:20:00 2009 -0700 49.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Mon Jul 27 06:15:29 2009 -0700 49.3 @@ -885,7 +885,7 @@ 49.4 } 49.5 49.6 49.7 -void ParallelScavengeHeap::verify(bool allow_dirty, bool silent) { 49.8 +void ParallelScavengeHeap::verify(bool allow_dirty, bool silent, bool option /* ignored */) { 49.9 // Why do we need the total_collections()-filter below? 49.10 if (total_collections() > 0) { 49.11 if (!silent) {
50.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Mon Jul 20 08:20:00 2009 -0700 50.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Mon Jul 27 06:15:29 2009 -0700 50.3 @@ -217,7 +217,7 @@ 50.4 virtual void gc_threads_do(ThreadClosure* tc) const; 50.5 virtual void print_tracing_info() const; 50.6 50.7 - void verify(bool allow_dirty, bool silent); 50.8 + void verify(bool allow_dirty, bool silent, bool /* option */); 50.9 50.10 void print_heap_change(size_t prev_used); 50.11
51.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Mon Jul 20 08:20:00 2009 -0700 51.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Mon Jul 27 06:15:29 2009 -0700 51.3 @@ -117,6 +117,7 @@ 51.4 process_array_chunk(old); 51.5 } else { 51.6 if (p.is_narrow()) { 51.7 + assert(UseCompressedOops, "Error"); 51.8 PSScavenge::copy_and_push_safe_barrier(this, (narrowOop*)p); 51.9 } else { 51.10 PSScavenge::copy_and_push_safe_barrier(this, (oop*)p);
52.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp Mon Jul 20 08:20:00 2009 -0700 52.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Mon Jul 27 06:15:29 2009 -0700 52.3 @@ -533,7 +533,7 @@ 52.4 virtual void print_tracing_info() const = 0; 52.5 52.6 // Heap verification 52.7 - virtual void verify(bool allow_dirty, bool silent) = 0; 52.8 + virtual void verify(bool allow_dirty, bool silent, bool option) = 0; 52.9 52.10 // Non product verification and debugging. 52.11 #ifndef PRODUCT
53.1 --- a/src/share/vm/includeDB_core Mon Jul 20 08:20:00 2009 -0700 53.2 +++ b/src/share/vm/includeDB_core Mon Jul 27 06:15:29 2009 -0700 53.3 @@ -554,7 +554,6 @@ 53.4 ciEnv.cpp linkResolver.hpp 53.5 ciEnv.cpp methodDataOop.hpp 53.6 ciEnv.cpp objArrayKlass.hpp 53.7 -ciEnv.cpp oop.hpp 53.8 ciEnv.cpp oop.inline.hpp 53.9 ciEnv.cpp oop.inline2.hpp 53.10 ciEnv.cpp oopFactory.hpp 53.11 @@ -785,7 +784,6 @@ 53.12 ciSignature.cpp allocation.inline.hpp 53.13 ciSignature.cpp ciSignature.hpp 53.14 ciSignature.cpp ciUtilities.hpp 53.15 -ciSignature.cpp oop.hpp 53.16 ciSignature.cpp oop.inline.hpp 53.17 ciSignature.cpp signature.hpp 53.18 53.19 @@ -950,7 +948,6 @@ 53.20 classify.cpp classify.hpp 53.21 classify.cpp systemDictionary.hpp 53.22 53.23 -classify.hpp oop.hpp 53.24 classify.hpp oop.inline.hpp 53.25 53.26 codeBlob.cpp allocation.inline.hpp 53.27 @@ -1185,7 +1182,6 @@ 53.28 compilerOracle.cpp jniHandles.hpp 53.29 compilerOracle.cpp klass.hpp 53.30 compilerOracle.cpp methodOop.hpp 53.31 -compilerOracle.cpp oop.hpp 53.32 compilerOracle.cpp oop.inline.hpp 53.33 compilerOracle.cpp oopFactory.hpp 53.34 compilerOracle.cpp resourceArea.hpp 53.35 @@ -1629,7 +1625,6 @@ 53.36 frame.cpp methodOop.hpp 53.37 frame.cpp monitorChunk.hpp 53.38 frame.cpp nativeInst_<arch>.hpp 53.39 -frame.cpp oop.hpp 53.40 frame.cpp oop.inline.hpp 53.41 frame.cpp oop.inline2.hpp 53.42 frame.cpp oopMapCache.hpp 53.43 @@ -1797,7 +1792,6 @@ 53.44 generation.cpp generation.hpp 53.45 generation.cpp generation.inline.hpp 53.46 generation.cpp java.hpp 53.47 -generation.cpp oop.hpp 53.48 generation.cpp oop.inline.hpp 53.49 generation.cpp spaceDecorator.hpp 53.50 generation.cpp space.inline.hpp 53.51 @@ -2270,7 +2264,6 @@ 53.52 java.cpp memprofiler.hpp 53.53 java.cpp methodOop.hpp 53.54 java.cpp objArrayOop.hpp 53.55 -java.cpp oop.hpp 53.56 java.cpp oop.inline.hpp 53.57 java.cpp oopFactory.hpp 53.58 java.cpp sharedRuntime.hpp 53.59 @@ -2947,7 +2940,7 @@ 53.60 nativeInst_<arch>.cpp assembler_<arch>.inline.hpp 53.61 nativeInst_<arch>.cpp handles.hpp 53.62 nativeInst_<arch>.cpp nativeInst_<arch>.hpp 53.63 -nativeInst_<arch>.cpp oop.hpp 53.64 +nativeInst_<arch>.cpp oop.inline.hpp 53.65 nativeInst_<arch>.cpp ostream.hpp 53.66 nativeInst_<arch>.cpp resourceArea.hpp 53.67 nativeInst_<arch>.cpp sharedRuntime.hpp 53.68 @@ -3842,7 +3835,7 @@ 53.69 stackValue.cpp debugInfo.hpp 53.70 stackValue.cpp frame.inline.hpp 53.71 stackValue.cpp handles.inline.hpp 53.72 -stackValue.cpp oop.hpp 53.73 +stackValue.cpp oop.inline.hpp 53.74 stackValue.cpp stackValue.hpp 53.75 53.76 stackValue.hpp handles.hpp 53.77 @@ -4329,7 +4322,6 @@ 53.78 unhandledOops.cpp collectedHeap.hpp 53.79 unhandledOops.cpp gcLocker.inline.hpp 53.80 unhandledOops.cpp globalDefinitions.hpp 53.81 -unhandledOops.cpp oop.hpp 53.82 unhandledOops.cpp oop.inline.hpp 53.83 unhandledOops.cpp thread.hpp 53.84 unhandledOops.cpp unhandledOops.hpp 53.85 @@ -4465,7 +4457,6 @@ 53.86 vframe.cpp nmethod.hpp 53.87 vframe.cpp objectMonitor.hpp 53.88 vframe.cpp objectMonitor.inline.hpp 53.89 -vframe.cpp oop.hpp 53.90 vframe.cpp oop.inline.hpp 53.91 vframe.cpp oopMapCache.hpp 53.92 vframe.cpp pcDesc.hpp 53.93 @@ -4577,7 +4568,6 @@ 53.94 vmThread.cpp interfaceSupport.hpp 53.95 vmThread.cpp methodOop.hpp 53.96 vmThread.cpp mutexLocker.hpp 53.97 -vmThread.cpp oop.hpp 53.98 vmThread.cpp oop.inline.hpp 53.99 vmThread.cpp os.hpp 53.100 vmThread.cpp resourceArea.hpp
54.1 --- a/src/share/vm/includeDB_features Mon Jul 20 08:20:00 2009 -0700 54.2 +++ b/src/share/vm/includeDB_features Mon Jul 27 06:15:29 2009 -0700 54.3 @@ -47,7 +47,7 @@ 54.4 dump.cpp javaClasses.hpp 54.5 dump.cpp loaderConstraints.hpp 54.6 dump.cpp methodDataOop.hpp 54.7 -dump.cpp oop.hpp 54.8 +dump.cpp oop.inline.hpp 54.9 dump.cpp oopFactory.hpp 54.10 dump.cpp resourceArea.hpp 54.11 dump.cpp signature.hpp 54.12 @@ -237,7 +237,7 @@ 54.13 serialize.cpp compiledICHolderOop.hpp 54.14 serialize.cpp methodDataOop.hpp 54.15 serialize.cpp objArrayOop.hpp 54.16 -serialize.cpp oop.hpp 54.17 +serialize.cpp oop.inline.hpp 54.18 serialize.cpp symbolTable.hpp 54.19 serialize.cpp systemDictionary.hpp 54.20 54.21 @@ -295,7 +295,7 @@ 54.22 vmStructs.cpp objArrayKlass.hpp 54.23 vmStructs.cpp objArrayKlassKlass.hpp 54.24 vmStructs.cpp objArrayOop.hpp 54.25 -vmStructs.cpp oop.hpp 54.26 +vmStructs.cpp oop.inline.hpp 54.27 vmStructs.cpp oopMap.hpp 54.28 vmStructs.cpp pcDesc.hpp 54.29 vmStructs.cpp perfMemory.hpp
55.1 --- a/src/share/vm/interpreter/rewriter.cpp Mon Jul 20 08:20:00 2009 -0700 55.2 +++ b/src/share/vm/interpreter/rewriter.cpp Mon Jul 27 06:15:29 2009 -0700 55.3 @@ -273,6 +273,7 @@ 55.4 compute_index_maps(); 55.5 55.6 if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) { 55.7 + bool did_rewrite = false; 55.8 int i = _methods->length(); 55.9 while (i-- > 0) { 55.10 methodOop method = (methodOop)_methods->obj_at(i); 55.11 @@ -281,9 +282,11 @@ 55.12 // object for finalization if needed. 55.13 methodHandle m(THREAD, method); 55.14 rewrite_Object_init(m, CHECK); 55.15 + did_rewrite = true; 55.16 break; 55.17 } 55.18 } 55.19 + assert(did_rewrite, "must find Object::<init> to rewrite it"); 55.20 } 55.21 55.22 // rewrite methods, in two passes
56.1 --- a/src/share/vm/memory/barrierSet.cpp Mon Jul 20 08:20:00 2009 -0700 56.2 +++ b/src/share/vm/memory/barrierSet.cpp Mon Jul 27 06:15:29 2009 -0700 56.3 @@ -25,12 +25,27 @@ 56.4 # include "incls/_precompiled.incl" 56.5 # include "incls/_barrierSet.cpp.incl" 56.6 56.7 -// count is in HeapWord's 56.8 +// count is number of array elements being written 56.9 void BarrierSet::static_write_ref_array_pre(HeapWord* start, size_t count) { 56.10 - Universe::heap()->barrier_set()->write_ref_array_pre(MemRegion(start, start + count)); 56.11 + assert(count <= (size_t)max_intx, "count too large"); 56.12 +#if 0 56.13 + warning("Pre: \t" INTPTR_FORMAT "[" SIZE_FORMAT "]\t", 56.14 + start, count); 56.15 +#endif 56.16 + if (UseCompressedOops) { 56.17 + Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count); 56.18 + } else { 56.19 + Universe::heap()->barrier_set()->write_ref_array_pre( (oop*)start, (int)count); 56.20 + } 56.21 } 56.22 56.23 -// count is in HeapWord's 56.24 +// count is number of array elements being written 56.25 void BarrierSet::static_write_ref_array_post(HeapWord* start, size_t count) { 56.26 - Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, start + count)); 56.27 + assert(count <= (size_t)max_intx, "count too large"); 56.28 + HeapWord* end = start + objArrayOopDesc::array_size((int)count); 56.29 +#if 0 56.30 + warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t", 56.31 + start, count, start, end); 56.32 +#endif 56.33 + Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, end)); 56.34 }
57.1 --- a/src/share/vm/memory/barrierSet.hpp Mon Jul 20 08:20:00 2009 -0700 57.2 +++ b/src/share/vm/memory/barrierSet.hpp Mon Jul 27 06:15:29 2009 -0700 57.3 @@ -81,9 +81,13 @@ 57.4 // barrier types. Semantically, it should be thought of as a call to the 57.5 // virtual "_work" function below, which must implement the barrier.) 57.6 // First the pre-write versions... 57.7 - inline void write_ref_field_pre(void* field, oop new_val); 57.8 + template <class T> inline void write_ref_field_pre(T* field, oop new_val); 57.9 +private: 57.10 + // Keep this private so as to catch violations at build time. 57.11 + virtual void write_ref_field_pre_work( void* field, oop new_val) { guarantee(false, "Not needed"); }; 57.12 protected: 57.13 - virtual void write_ref_field_pre_work(void* field, oop new_val) {}; 57.14 + virtual void write_ref_field_pre_work( oop* field, oop new_val) {}; 57.15 + virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) {}; 57.16 public: 57.17 57.18 // ...then the post-write version. 57.19 @@ -117,12 +121,17 @@ 57.20 virtual void read_ref_array(MemRegion mr) = 0; 57.21 virtual void read_prim_array(MemRegion mr) = 0; 57.22 57.23 - virtual void write_ref_array_pre(MemRegion mr) {} 57.24 + virtual void write_ref_array_pre( oop* dst, int length) {} 57.25 + virtual void write_ref_array_pre(narrowOop* dst, int length) {} 57.26 inline void write_ref_array(MemRegion mr); 57.27 57.28 // Static versions, suitable for calling from generated code. 57.29 static void static_write_ref_array_pre(HeapWord* start, size_t count); 57.30 static void static_write_ref_array_post(HeapWord* start, size_t count); 57.31 + // Narrow oop versions of the above; count is # of array elements being written, 57.32 + // starting with "start", which is HeapWord-aligned. 57.33 + static void static_write_ref_array_pre_narrow(HeapWord* start, size_t count); 57.34 + static void static_write_ref_array_post_narrow(HeapWord* start, size_t count); 57.35 57.36 protected: 57.37 virtual void write_ref_array_work(MemRegion mr) = 0;
58.1 --- a/src/share/vm/memory/barrierSet.inline.hpp Mon Jul 20 08:20:00 2009 -0700 58.2 +++ b/src/share/vm/memory/barrierSet.inline.hpp Mon Jul 27 06:15:29 2009 -0700 58.3 @@ -23,10 +23,10 @@ 58.4 */ 58.5 58.6 // Inline functions of BarrierSet, which de-virtualize certain 58.7 -// performance-critical calls when when the barrier is the most common 58.8 +// performance-critical calls when the barrier is the most common 58.9 // card-table kind. 58.10 58.11 -void BarrierSet::write_ref_field_pre(void* field, oop new_val) { 58.12 +template <class T> void BarrierSet::write_ref_field_pre(T* field, oop new_val) { 58.13 if (kind() == CardTableModRef) { 58.14 ((CardTableModRefBS*)this)->inline_write_ref_field_pre(field, new_val); 58.15 } else {
59.1 --- a/src/share/vm/memory/cardTableModRefBS.hpp Mon Jul 20 08:20:00 2009 -0700 59.2 +++ b/src/share/vm/memory/cardTableModRefBS.hpp Mon Jul 27 06:15:29 2009 -0700 59.3 @@ -287,7 +287,7 @@ 59.4 // these functions here for performance. 59.5 protected: 59.6 void write_ref_field_work(oop obj, size_t offset, oop newVal); 59.7 - void write_ref_field_work(void* field, oop newVal); 59.8 + virtual void write_ref_field_work(void* field, oop newVal); 59.9 public: 59.10 59.11 bool has_write_ref_array_opt() { return true; } 59.12 @@ -317,10 +317,10 @@ 59.13 59.14 // *** Card-table-barrier-specific things. 59.15 59.16 - inline void inline_write_ref_field_pre(void* field, oop newVal) {} 59.17 + template <class T> inline void inline_write_ref_field_pre(T* field, oop newVal) {} 59.18 59.19 - inline void inline_write_ref_field(void* field, oop newVal) { 59.20 - jbyte* byte = byte_for(field); 59.21 + template <class T> inline void inline_write_ref_field(T* field, oop newVal) { 59.22 + jbyte* byte = byte_for((void*)field); 59.23 *byte = dirty_card; 59.24 } 59.25
60.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Mon Jul 20 08:20:00 2009 -0700 60.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Mon Jul 27 06:15:29 2009 -0700 60.3 @@ -1194,7 +1194,7 @@ 60.4 return _gens[level]->gc_stats(); 60.5 } 60.6 60.7 -void GenCollectedHeap::verify(bool allow_dirty, bool silent) { 60.8 +void GenCollectedHeap::verify(bool allow_dirty, bool silent, bool option /* ignored */) { 60.9 if (!silent) { 60.10 gclog_or_tty->print("permgen "); 60.11 }
61.1 --- a/src/share/vm/memory/genCollectedHeap.hpp Mon Jul 20 08:20:00 2009 -0700 61.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp Mon Jul 27 06:15:29 2009 -0700 61.3 @@ -325,7 +325,7 @@ 61.4 void prepare_for_verify(); 61.5 61.6 // Override. 61.7 - void verify(bool allow_dirty, bool silent); 61.8 + void verify(bool allow_dirty, bool silent, bool /* option */); 61.9 61.10 // Override. 61.11 void print() const;
62.1 --- a/src/share/vm/memory/genOopClosures.hpp Mon Jul 20 08:20:00 2009 -0700 62.2 +++ b/src/share/vm/memory/genOopClosures.hpp Mon Jul 27 06:15:29 2009 -0700 62.3 @@ -57,7 +57,7 @@ 62.4 template <class T> void do_barrier(T* p); 62.5 62.6 // Version for use by closures that may be called in parallel code. 62.7 - void par_do_barrier(oop* p); 62.8 + template <class T> void par_do_barrier(T* p); 62.9 62.10 public: 62.11 OopsInGenClosure() : OopClosure(NULL),
63.1 --- a/src/share/vm/memory/genOopClosures.inline.hpp Mon Jul 20 08:20:00 2009 -0700 63.2 +++ b/src/share/vm/memory/genOopClosures.inline.hpp Mon Jul 27 06:15:29 2009 -0700 63.3 @@ -40,18 +40,20 @@ 63.4 63.5 template <class T> inline void OopsInGenClosure::do_barrier(T* p) { 63.6 assert(generation()->is_in_reserved(p), "expected ref in generation"); 63.7 - assert(!oopDesc::is_null(*p), "expected non-null object"); 63.8 - oop obj = oopDesc::load_decode_heap_oop_not_null(p); 63.9 + T heap_oop = oopDesc::load_heap_oop(p); 63.10 + assert(!oopDesc::is_null(heap_oop), "expected non-null oop"); 63.11 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 63.12 // If p points to a younger generation, mark the card. 63.13 if ((HeapWord*)obj < _gen_boundary) { 63.14 _rs->inline_write_ref_field_gc(p, obj); 63.15 } 63.16 } 63.17 63.18 -inline void OopsInGenClosure::par_do_barrier(oop* p) { 63.19 +template <class T> inline void OopsInGenClosure::par_do_barrier(T* p) { 63.20 assert(generation()->is_in_reserved(p), "expected ref in generation"); 63.21 - oop obj = *p; 63.22 - assert(obj != NULL, "expected non-null object"); 63.23 + T heap_oop = oopDesc::load_heap_oop(p); 63.24 + assert(!oopDesc::is_null(heap_oop), "expected non-null oop"); 63.25 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 63.26 // If p points to a younger generation, mark the card. 63.27 if ((HeapWord*)obj < gen_boundary()) { 63.28 rs()->write_ref_field_gc_par(p, obj);
64.1 --- a/src/share/vm/memory/referenceProcessor.cpp Mon Jul 20 08:20:00 2009 -0700 64.2 +++ b/src/share/vm/memory/referenceProcessor.cpp Mon Jul 27 06:15:29 2009 -0700 64.3 @@ -1013,12 +1013,19 @@ 64.4 // discovered_addr. 64.5 oop current_head = refs_list.head(); 64.6 64.7 - // Note: In the case of G1, this pre-barrier is strictly 64.8 + // Note: In the case of G1, this specific pre-barrier is strictly 64.9 // not necessary because the only case we are interested in 64.10 - // here is when *discovered_addr is NULL, so this will expand to 64.11 - // nothing. As a result, I am just manually eliding this out for G1. 64.12 + // here is when *discovered_addr is NULL (see the CAS further below), 64.13 + // so this will expand to nothing. As a result, we have manually 64.14 + // elided this out for G1, but left in the test for some future 64.15 + // collector that might have need for a pre-barrier here. 64.16 if (_discovered_list_needs_barrier && !UseG1GC) { 64.17 - _bs->write_ref_field_pre((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); 64.18 + if (UseCompressedOops) { 64.19 + _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); 64.20 + } else { 64.21 + _bs->write_ref_field_pre((oop*)discovered_addr, current_head); 64.22 + } 64.23 + guarantee(false, "Need to check non-G1 collector"); 64.24 } 64.25 oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr, 64.26 NULL); 64.27 @@ -1029,9 +1036,8 @@ 64.28 refs_list.set_head(obj); 64.29 refs_list.inc_length(1); 64.30 if (_discovered_list_needs_barrier) { 64.31 - _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); 64.32 + _bs->write_ref_field((void*)discovered_addr, current_head); 64.33 } 64.34 - 64.35 } else { 64.36 // If retest was non NULL, another thread beat us to it: 64.37 // The reference has already been discovered... 64.38 @@ -1177,11 +1183,16 @@ 64.39 // pre-value, we can safely elide the pre-barrier here for the case of G1. 64.40 assert(discovered == NULL, "control point invariant"); 64.41 if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1 64.42 - _bs->write_ref_field_pre((oop*)discovered_addr, current_head); 64.43 + if (UseCompressedOops) { 64.44 + _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); 64.45 + } else { 64.46 + _bs->write_ref_field_pre((oop*)discovered_addr, current_head); 64.47 + } 64.48 + guarantee(false, "Need to check non-G1 collector"); 64.49 } 64.50 oop_store_raw(discovered_addr, current_head); 64.51 if (_discovered_list_needs_barrier) { 64.52 - _bs->write_ref_field((oop*)discovered_addr, current_head); 64.53 + _bs->write_ref_field((void*)discovered_addr, current_head); 64.54 } 64.55 list->set_head(obj); 64.56 list->inc_length(1);
65.1 --- a/src/share/vm/memory/space.hpp Mon Jul 20 08:20:00 2009 -0700 65.2 +++ b/src/share/vm/memory/space.hpp Mon Jul 27 06:15:29 2009 -0700 65.3 @@ -106,6 +106,7 @@ 65.4 virtual void set_end(HeapWord* value) { _end = value; } 65.5 65.6 virtual HeapWord* saved_mark_word() const { return _saved_mark_word; } 65.7 + 65.8 void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; } 65.9 65.10 MemRegionClosure* preconsumptionDirtyCardClosure() const {
66.1 --- a/src/share/vm/memory/universe.cpp Mon Jul 20 08:20:00 2009 -0700 66.2 +++ b/src/share/vm/memory/universe.cpp Mon Jul 27 06:15:29 2009 -0700 66.3 @@ -1170,7 +1170,7 @@ 66.4 st->print_cr("}"); 66.5 } 66.6 66.7 -void Universe::verify(bool allow_dirty, bool silent) { 66.8 +void Universe::verify(bool allow_dirty, bool silent, bool option) { 66.9 if (SharedSkipVerify) { 66.10 return; 66.11 } 66.12 @@ -1194,7 +1194,7 @@ 66.13 if (!silent) gclog_or_tty->print("[Verifying "); 66.14 if (!silent) gclog_or_tty->print("threads "); 66.15 Threads::verify(); 66.16 - heap()->verify(allow_dirty, silent); 66.17 + heap()->verify(allow_dirty, silent, option); 66.18 66.19 if (!silent) gclog_or_tty->print("syms "); 66.20 SymbolTable::verify();
67.1 --- a/src/share/vm/memory/universe.hpp Mon Jul 20 08:20:00 2009 -0700 67.2 +++ b/src/share/vm/memory/universe.hpp Mon Jul 27 06:15:29 2009 -0700 67.3 @@ -343,6 +343,7 @@ 67.4 // For UseCompressedOops 67.5 static address* narrow_oop_base_addr() { return &_narrow_oop._base; } 67.6 static address narrow_oop_base() { return _narrow_oop._base; } 67.7 + static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); } 67.8 static int narrow_oop_shift() { return _narrow_oop._shift; } 67.9 static void set_narrow_oop_base(address base) { _narrow_oop._base = base; } 67.10 static void set_narrow_oop_shift(int shift) { _narrow_oop._shift = shift; } 67.11 @@ -398,7 +399,7 @@ 67.12 67.13 // Debugging 67.14 static bool verify_in_progress() { return _verify_in_progress; } 67.15 - static void verify(bool allow_dirty = true, bool silent = false); 67.16 + static void verify(bool allow_dirty = true, bool silent = false, bool option = true); 67.17 static int verify_count() { return _verify_count; } 67.18 static void print(); 67.19 static void print_on(outputStream* st);
68.1 --- a/src/share/vm/oops/instanceRefKlass.cpp Mon Jul 20 08:20:00 2009 -0700 68.2 +++ b/src/share/vm/oops/instanceRefKlass.cpp Mon Jul 27 06:15:29 2009 -0700 68.3 @@ -28,13 +28,14 @@ 68.4 template <class T> 68.5 static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { 68.6 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); 68.7 - oop referent = oopDesc::load_decode_heap_oop(referent_addr); 68.8 + T heap_oop = oopDesc::load_heap_oop(referent_addr); 68.9 debug_only( 68.10 if(TraceReferenceGC && PrintGCDetails) { 68.11 gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj); 68.12 } 68.13 ) 68.14 - if (referent != NULL) { 68.15 + if (!oopDesc::is_null(heap_oop)) { 68.16 + oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); 68.17 if (!referent->is_gc_marked() && 68.18 MarkSweep::ref_processor()-> 68.19 discover_reference(obj, ref->reference_type())) { 68.20 @@ -81,13 +82,14 @@ 68.21 ParCompactionManager* cm, 68.22 oop obj) { 68.23 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); 68.24 - oop referent = oopDesc::load_decode_heap_oop(referent_addr); 68.25 + T heap_oop = oopDesc::load_heap_oop(referent_addr); 68.26 debug_only( 68.27 if(TraceReferenceGC && PrintGCDetails) { 68.28 gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj); 68.29 } 68.30 ) 68.31 - if (referent != NULL) { 68.32 + if (!oopDesc::is_null(heap_oop)) { 68.33 + oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); 68.34 if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) && 68.35 PSParallelCompact::ref_processor()-> 68.36 discover_reference(obj, ref->reference_type())) { 68.37 @@ -182,9 +184,10 @@ 68.38 } \ 68.39 \ 68.40 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \ 68.41 - oop referent = oopDesc::load_decode_heap_oop(referent_addr); \ 68.42 - if (referent != NULL && contains(referent_addr)) { \ 68.43 + T heap_oop = oopDesc::load_heap_oop(referent_addr); \ 68.44 + if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) { \ 68.45 ReferenceProcessor* rp = closure->_ref_processor; \ 68.46 + oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \ 68.47 if (!referent->is_gc_marked() && (rp != NULL) && \ 68.48 rp->discover_reference(obj, reference_type())) { \ 68.49 return size; \
69.1 --- a/src/share/vm/oops/methodKlass.cpp Mon Jul 20 08:20:00 2009 -0700 69.2 +++ b/src/share/vm/oops/methodKlass.cpp Mon Jul 27 06:15:29 2009 -0700 69.3 @@ -68,7 +68,7 @@ 69.4 m->set_constants(NULL); 69.5 m->set_max_stack(0); 69.6 m->set_max_locals(0); 69.7 - m->clear_intrinsic_id_cache(); 69.8 + m->set_intrinsic_id(vmIntrinsics::_none); 69.9 m->set_method_data(NULL); 69.10 m->set_interpreter_throwout_count(0); 69.11 m->set_vtable_index(methodOopDesc::garbage_vtable_index);
70.1 --- a/src/share/vm/oops/methodOop.cpp Mon Jul 20 08:20:00 2009 -0700 70.2 +++ b/src/share/vm/oops/methodOop.cpp Mon Jul 27 06:15:29 2009 -0700 70.3 @@ -962,26 +962,39 @@ 70.4 return newm; 70.5 } 70.6 70.7 -vmIntrinsics::ID methodOopDesc::compute_intrinsic_id() const { 70.8 - assert(vmIntrinsics::_none == 0, "correct coding of default case"); 70.9 - const uintptr_t max_cache_uint = right_n_bits((int)(sizeof(_intrinsic_id_cache) * BitsPerByte)); 70.10 - assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_cache_uint, "else fix cache size"); 70.11 +vmSymbols::SID methodOopDesc::klass_id_for_intrinsics(klassOop holder) { 70.12 // if loader is not the default loader (i.e., != NULL), we can't know the intrinsics 70.13 // because we are not loading from core libraries 70.14 - if (instanceKlass::cast(method_holder())->class_loader() != NULL) return vmIntrinsics::_none; 70.15 + if (instanceKlass::cast(holder)->class_loader() != NULL) 70.16 + return vmSymbols::NO_SID; // regardless of name, no intrinsics here 70.17 70.18 // see if the klass name is well-known: 70.19 - symbolOop klass_name = instanceKlass::cast(method_holder())->name(); 70.20 - vmSymbols::SID klass_id = vmSymbols::find_sid(klass_name); 70.21 - if (klass_id == vmSymbols::NO_SID) return vmIntrinsics::_none; 70.22 + symbolOop klass_name = instanceKlass::cast(holder)->name(); 70.23 + return vmSymbols::find_sid(klass_name); 70.24 +} 70.25 + 70.26 +void methodOopDesc::init_intrinsic_id() { 70.27 + assert(_intrinsic_id == vmIntrinsics::_none, "do this just once"); 70.28 + const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte)); 70.29 + assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_id_uint, "else fix size"); 70.30 + 70.31 + // the klass name is well-known: 70.32 + vmSymbols::SID klass_id = klass_id_for_intrinsics(method_holder()); 70.33 + assert(klass_id != vmSymbols::NO_SID, "caller responsibility"); 70.34 70.35 // ditto for method and signature: 70.36 vmSymbols::SID name_id = vmSymbols::find_sid(name()); 70.37 - if (name_id == vmSymbols::NO_SID) return vmIntrinsics::_none; 70.38 + if (name_id == vmSymbols::NO_SID) return; 70.39 vmSymbols::SID sig_id = vmSymbols::find_sid(signature()); 70.40 - if (sig_id == vmSymbols::NO_SID) return vmIntrinsics::_none; 70.41 + if (sig_id == vmSymbols::NO_SID) return; 70.42 jshort flags = access_flags().as_short(); 70.43 70.44 + vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); 70.45 + if (id != vmIntrinsics::_none) { 70.46 + set_intrinsic_id(id); 70.47 + return; 70.48 + } 70.49 + 70.50 // A few slightly irregular cases: 70.51 switch (klass_id) { 70.52 case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_StrictMath): 70.53 @@ -992,15 +1005,18 @@ 70.54 case vmSymbols::VM_SYMBOL_ENUM_NAME(sqrt_name): 70.55 // pretend it is the corresponding method in the non-strict class: 70.56 klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_Math); 70.57 + id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); 70.58 break; 70.59 } 70.60 } 70.61 70.62 - // return intrinsic id if any 70.63 - return vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); 70.64 + if (id != vmIntrinsics::_none) { 70.65 + // Set up its iid. It is an alias method. 70.66 + set_intrinsic_id(id); 70.67 + return; 70.68 + } 70.69 } 70.70 70.71 - 70.72 // These two methods are static since a GC may move the methodOopDesc 70.73 bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) { 70.74 bool sig_is_loaded = true;
71.1 --- a/src/share/vm/oops/methodOop.hpp Mon Jul 20 08:20:00 2009 -0700 71.2 +++ b/src/share/vm/oops/methodOop.hpp Mon Jul 27 06:15:29 2009 -0700 71.3 @@ -104,7 +104,7 @@ 71.4 u2 _max_stack; // Maximum number of entries on the expression stack 71.5 u2 _max_locals; // Number of local variables used by this method 71.6 u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words 71.7 - u1 _intrinsic_id_cache; // Cache for intrinsic_id; 0 or 1+vmInt::ID 71.8 + u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) 71.9 u1 _highest_tier_compile; // Highest compile level this method has ever seen. 71.10 u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting 71.11 u2 _number_of_breakpoints; // fullspeed debugging support 71.12 @@ -224,8 +224,6 @@ 71.13 int highest_tier_compile() { return _highest_tier_compile;} 71.14 void set_highest_tier_compile(int level) { _highest_tier_compile = level;} 71.15 71.16 - void clear_intrinsic_id_cache() { _intrinsic_id_cache = 0; } 71.17 - 71.18 // Count of times method was exited via exception while interpreting 71.19 void interpreter_throwout_increment() { 71.20 if (_interpreter_throwout_count < 65534) { 71.21 @@ -571,18 +569,12 @@ 71.22 void set_cached_itable_index(int index) { instanceKlass::cast(method_holder())->set_cached_itable_index(method_idnum(), index); } 71.23 71.24 // Support for inlining of intrinsic methods 71.25 - vmIntrinsics::ID intrinsic_id() const { // returns zero if not an intrinsic 71.26 - const u1& cache = _intrinsic_id_cache; 71.27 - if (cache != 0) { 71.28 - return (vmIntrinsics::ID)(cache - 1); 71.29 - } else { 71.30 - vmIntrinsics::ID id = compute_intrinsic_id(); 71.31 - *(u1*)&cache = ((u1) id) + 1; // force the cache to be non-const 71.32 - vmIntrinsics::verify_method(id, (methodOop) this); 71.33 - assert((vmIntrinsics::ID)(cache - 1) == id, "proper conversion"); 71.34 - return id; 71.35 - } 71.36 - } 71.37 + vmIntrinsics::ID intrinsic_id() const { return (vmIntrinsics::ID) _intrinsic_id; } 71.38 + void set_intrinsic_id(vmIntrinsics::ID id) { _intrinsic_id = (u1) id; } 71.39 + 71.40 + // Helper routines for intrinsic_id() and vmIntrinsics::method(). 71.41 + void init_intrinsic_id(); // updates from _none if a match 71.42 + static vmSymbols::SID klass_id_for_intrinsics(klassOop holder); 71.43 71.44 // On-stack replacement support 71.45 bool has_osr_nmethod() { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci) != NULL; } 71.46 @@ -635,9 +627,6 @@ 71.47 void set_size_of_parameters(int size) { _size_of_parameters = size; } 71.48 private: 71.49 71.50 - // Helper routine for intrinsic_id(). 71.51 - vmIntrinsics::ID compute_intrinsic_id() const; 71.52 - 71.53 // Inlined elements 71.54 address* native_function_addr() const { assert(is_native(), "must be native"); return (address*) (this+1); } 71.55 address* signature_handler_addr() const { return native_function_addr() + 1; }
72.1 --- a/src/share/vm/oops/objArrayKlass.cpp Mon Jul 20 08:20:00 2009 -0700 72.2 +++ b/src/share/vm/oops/objArrayKlass.cpp Mon Jul 27 06:15:29 2009 -0700 72.3 @@ -84,8 +84,6 @@ 72.4 template <class T> void objArrayKlass::do_copy(arrayOop s, T* src, 72.5 arrayOop d, T* dst, int length, TRAPS) { 72.6 72.7 - const size_t word_len = objArrayOopDesc::array_size(length); 72.8 - 72.9 BarrierSet* bs = Universe::heap()->barrier_set(); 72.10 // For performance reasons, we assume we are that the write barrier we 72.11 // are using has optimized modes for arrays of references. At least one 72.12 @@ -93,11 +91,10 @@ 72.13 assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); 72.14 assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well."); 72.15 72.16 - MemRegion dst_mr = MemRegion((HeapWord*)dst, word_len); 72.17 if (s == d) { 72.18 // since source and destination are equal we do not need conversion checks. 72.19 assert(length > 0, "sanity check"); 72.20 - bs->write_ref_array_pre(dst_mr); 72.21 + bs->write_ref_array_pre(dst, length); 72.22 Copy::conjoint_oops_atomic(src, dst, length); 72.23 } else { 72.24 // We have to make sure all elements conform to the destination array 72.25 @@ -105,7 +102,7 @@ 72.26 klassOop stype = objArrayKlass::cast(s->klass())->element_klass(); 72.27 if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { 72.28 // elements are guaranteed to be subtypes, so no check necessary 72.29 - bs->write_ref_array_pre(dst_mr); 72.30 + bs->write_ref_array_pre(dst, length); 72.31 Copy::conjoint_oops_atomic(src, dst, length); 72.32 } else { 72.33 // slow case: need individual subtype checks 72.34 @@ -137,6 +134,7 @@ 72.35 } 72.36 } 72.37 } 72.38 + const size_t word_len = objArrayOopDesc::array_size(length); 72.39 bs->write_ref_array(MemRegion((HeapWord*)dst, word_len)); 72.40 } 72.41
73.1 --- a/src/share/vm/oops/oop.inline.hpp Mon Jul 20 08:20:00 2009 -0700 73.2 +++ b/src/share/vm/oops/oop.inline.hpp Mon Jul 27 06:15:29 2009 -0700 73.3 @@ -148,12 +148,14 @@ 73.4 73.5 inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { 73.6 assert(!is_null(v), "oop value can never be zero"); 73.7 + assert(Universe::heap()->is_in_reserved(v), "Address not in heap"); 73.8 address base = Universe::narrow_oop_base(); 73.9 int shift = Universe::narrow_oop_shift(); 73.10 uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); 73.11 assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); 73.12 uint64_t result = pd >> shift; 73.13 assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow"); 73.14 + assert(decode_heap_oop(result) == v, "reversibility"); 73.15 return (narrowOop)result; 73.16 } 73.17 73.18 @@ -449,7 +451,7 @@ 73.19 oopDesc::bs()->write_ref_field(p, v); 73.20 } 73.21 73.22 -inline void update_barrier_set_pre(void* p, oop v) { 73.23 +template <class T> inline void update_barrier_set_pre(T* p, oop v) { 73.24 oopDesc::bs()->write_ref_field_pre(p, v); 73.25 } 73.26 73.27 @@ -459,15 +461,15 @@ 73.28 } else { 73.29 update_barrier_set_pre(p, v); 73.30 oopDesc::encode_store_heap_oop(p, v); 73.31 - update_barrier_set(p, v); 73.32 + update_barrier_set((void*)p, v); // cast away type 73.33 } 73.34 } 73.35 73.36 template <class T> inline void oop_store(volatile T* p, oop v) { 73.37 - update_barrier_set_pre((void*)p, v); 73.38 + update_barrier_set_pre((T*)p, v); // cast away volatile 73.39 // Used by release_obj_field_put, so use release_store_ptr. 73.40 oopDesc::release_encode_store_heap_oop(p, v); 73.41 - update_barrier_set((void*)p, v); 73.42 + update_barrier_set((void*)p, v); // cast away type 73.43 } 73.44 73.45 template <class T> inline void oop_store_without_check(T* p, oop v) {
74.1 --- a/src/share/vm/oops/oopsHierarchy.hpp Mon Jul 20 08:20:00 2009 -0700 74.2 +++ b/src/share/vm/oops/oopsHierarchy.hpp Mon Jul 27 06:15:29 2009 -0700 74.3 @@ -29,6 +29,7 @@ 74.4 typedef juint narrowOop; // Offset instead of address for an oop within a java object 74.5 typedef class klassOopDesc* wideKlassOop; // to keep SA happy and unhandled oop 74.6 // detector happy. 74.7 +typedef void* OopOrNarrowOopStar; 74.8 74.9 #ifndef CHECK_UNHANDLED_OOPS 74.10
75.1 --- a/src/share/vm/opto/block.cpp Mon Jul 20 08:20:00 2009 -0700 75.2 +++ b/src/share/vm/opto/block.cpp Mon Jul 27 06:15:29 2009 -0700 75.3 @@ -910,7 +910,16 @@ 75.4 !(b->head()->is_Loop() && n->is_Phi()) && 75.5 // See (+++) comment in reg_split.cpp 75.6 !(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) { 75.7 - assert( b->find_node(def) < j, "uses must follow definitions" ); 75.8 + bool is_loop = false; 75.9 + if (n->is_Phi()) { 75.10 + for( uint l = 1; l < def->req(); l++ ) { 75.11 + if (n == def->in(l)) { 75.12 + is_loop = true; 75.13 + break; // Some kind of loop 75.14 + } 75.15 + } 75.16 + } 75.17 + assert( is_loop || b->find_node(def) < j, "uses must follow definitions" ); 75.18 } 75.19 if( def->is_SafePointScalarObject() ) { 75.20 assert(_bbs[def->_idx] == b, "SafePointScalarObject Node should be at the same block as its SafePoint node");
76.1 --- a/src/share/vm/opto/compile.cpp Mon Jul 20 08:20:00 2009 -0700 76.2 +++ b/src/share/vm/opto/compile.cpp Mon Jul 27 06:15:29 2009 -0700 76.3 @@ -101,7 +101,8 @@ 76.4 } 76.5 } 76.6 // Lazily create intrinsics for intrinsic IDs well-known in the runtime. 76.7 - if (m->intrinsic_id() != vmIntrinsics::_none) { 76.8 + if (m->intrinsic_id() != vmIntrinsics::_none && 76.9 + m->intrinsic_id() <= vmIntrinsics::LAST_COMPILER_INLINE) { 76.10 CallGenerator* cg = make_vm_intrinsic(m, is_virtual); 76.11 if (cg != NULL) { 76.12 // Save it for next time: 76.13 @@ -440,6 +441,8 @@ 76.14 _orig_pc_slot_offset_in_bytes(0), 76.15 _node_bundling_limit(0), 76.16 _node_bundling_base(NULL), 76.17 + _java_calls(0), 76.18 + _inner_loops(0), 76.19 #ifndef PRODUCT 76.20 _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), 76.21 _printer(IdealGraphPrinter::printer()), 76.22 @@ -710,6 +713,8 @@ 76.23 _code_buffer("Compile::Fill_buffer"), 76.24 _node_bundling_limit(0), 76.25 _node_bundling_base(NULL), 76.26 + _java_calls(0), 76.27 + _inner_loops(0), 76.28 #ifndef PRODUCT 76.29 _trace_opto_output(TraceOptoOutput), 76.30 _printer(NULL), 76.31 @@ -1850,22 +1855,26 @@ 76.32 int _float_count; // count float ops requiring 24-bit precision 76.33 int _double_count; // count double ops requiring more precision 76.34 int _java_call_count; // count non-inlined 'java' calls 76.35 + int _inner_loop_count; // count loops which need alignment 76.36 VectorSet _visited; // Visitation flags 76.37 Node_List _tests; // Set of IfNodes & PCTableNodes 76.38 76.39 Final_Reshape_Counts() : 76.40 - _call_count(0), _float_count(0), _double_count(0), _java_call_count(0), 76.41 + _call_count(0), _float_count(0), _double_count(0), 76.42 + _java_call_count(0), _inner_loop_count(0), 76.43 _visited( Thread::current()->resource_area() ) { } 76.44 76.45 void inc_call_count () { _call_count ++; } 76.46 void inc_float_count () { _float_count ++; } 76.47 void inc_double_count() { _double_count++; } 76.48 void inc_java_call_count() { _java_call_count++; } 76.49 + void inc_inner_loop_count() { _inner_loop_count++; } 76.50 76.51 int get_call_count () const { return _call_count ; } 76.52 int get_float_count () const { return _float_count ; } 76.53 int get_double_count() const { return _double_count; } 76.54 int get_java_call_count() const { return _java_call_count; } 76.55 + int get_inner_loop_count() const { return _inner_loop_count; } 76.56 }; 76.57 76.58 static bool oop_offset_is_sane(const TypeInstPtr* tp) { 76.59 @@ -1877,7 +1886,7 @@ 76.60 76.61 //------------------------------final_graph_reshaping_impl---------------------- 76.62 // Implement items 1-5 from final_graph_reshaping below. 76.63 -static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { 76.64 +static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { 76.65 76.66 if ( n->outcnt() == 0 ) return; // dead node 76.67 uint nop = n->Opcode(); 76.68 @@ -1919,13 +1928,13 @@ 76.69 case Op_CmpF: 76.70 case Op_CmpF3: 76.71 // case Op_ConvL2F: // longs are split into 32-bit halves 76.72 - fpu.inc_float_count(); 76.73 + frc.inc_float_count(); 76.74 break; 76.75 76.76 case Op_ConvF2D: 76.77 case Op_ConvD2F: 76.78 - fpu.inc_float_count(); 76.79 - fpu.inc_double_count(); 76.80 + frc.inc_float_count(); 76.81 + frc.inc_double_count(); 76.82 break; 76.83 76.84 // Count all double operations that may use FPU 76.85 @@ -1942,7 +1951,7 @@ 76.86 case Op_ConD: 76.87 case Op_CmpD: 76.88 case Op_CmpD3: 76.89 - fpu.inc_double_count(); 76.90 + frc.inc_double_count(); 76.91 break; 76.92 case Op_Opaque1: // Remove Opaque Nodes before matching 76.93 case Op_Opaque2: // Remove Opaque Nodes before matching 76.94 @@ -1951,7 +1960,7 @@ 76.95 case Op_CallStaticJava: 76.96 case Op_CallJava: 76.97 case Op_CallDynamicJava: 76.98 - fpu.inc_java_call_count(); // Count java call site; 76.99 + frc.inc_java_call_count(); // Count java call site; 76.100 case Op_CallRuntime: 76.101 case Op_CallLeaf: 76.102 case Op_CallLeafNoFP: { 76.103 @@ -1962,7 +1971,7 @@ 76.104 // uncommon_trap, _complete_monitor_locking, _complete_monitor_unlocking, 76.105 // _new_Java, _new_typeArray, _new_objArray, _rethrow_Java, ... 76.106 if( !call->is_CallStaticJava() || !call->as_CallStaticJava()->_name ) { 76.107 - fpu.inc_call_count(); // Count the call site 76.108 + frc.inc_call_count(); // Count the call site 76.109 } else { // See if uncommon argument is shared 76.110 Node *n = call->in(TypeFunc::Parms); 76.111 int nop = n->Opcode(); 76.112 @@ -1983,11 +1992,11 @@ 76.113 case Op_StoreD: 76.114 case Op_LoadD: 76.115 case Op_LoadD_unaligned: 76.116 - fpu.inc_double_count(); 76.117 + frc.inc_double_count(); 76.118 goto handle_mem; 76.119 case Op_StoreF: 76.120 case Op_LoadF: 76.121 - fpu.inc_float_count(); 76.122 + frc.inc_float_count(); 76.123 goto handle_mem; 76.124 76.125 case Op_StoreB: 76.126 @@ -2324,6 +2333,12 @@ 76.127 n->subsume_by(btp); 76.128 } 76.129 break; 76.130 + case Op_Loop: 76.131 + case Op_CountedLoop: 76.132 + if (n->as_Loop()->is_inner_loop()) { 76.133 + frc.inc_inner_loop_count(); 76.134 + } 76.135 + break; 76.136 default: 76.137 assert( !n->is_Call(), "" ); 76.138 assert( !n->is_Mem(), "" ); 76.139 @@ -2332,17 +2347,17 @@ 76.140 76.141 // Collect CFG split points 76.142 if (n->is_MultiBranch()) 76.143 - fpu._tests.push(n); 76.144 + frc._tests.push(n); 76.145 } 76.146 76.147 //------------------------------final_graph_reshaping_walk--------------------- 76.148 // Replacing Opaque nodes with their input in final_graph_reshaping_impl(), 76.149 // requires that the walk visits a node's inputs before visiting the node. 76.150 -static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &fpu ) { 76.151 +static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) { 76.152 ResourceArea *area = Thread::current()->resource_area(); 76.153 Unique_Node_List sfpt(area); 76.154 76.155 - fpu._visited.set(root->_idx); // first, mark node as visited 76.156 + frc._visited.set(root->_idx); // first, mark node as visited 76.157 uint cnt = root->req(); 76.158 Node *n = root; 76.159 uint i = 0; 76.160 @@ -2351,7 +2366,7 @@ 76.161 // Place all non-visited non-null inputs onto stack 76.162 Node* m = n->in(i); 76.163 ++i; 76.164 - if (m != NULL && !fpu._visited.test_set(m->_idx)) { 76.165 + if (m != NULL && !frc._visited.test_set(m->_idx)) { 76.166 if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL) 76.167 sfpt.push(m); 76.168 cnt = m->req(); 76.169 @@ -2361,7 +2376,7 @@ 76.170 } 76.171 } else { 76.172 // Now do post-visit work 76.173 - final_graph_reshaping_impl( n, fpu ); 76.174 + final_graph_reshaping_impl( n, frc ); 76.175 if (nstack.is_empty()) 76.176 break; // finished 76.177 n = nstack.node(); // Get node from stack 76.178 @@ -2442,16 +2457,16 @@ 76.179 return true; 76.180 } 76.181 76.182 - Final_Reshape_Counts fpu; 76.183 + Final_Reshape_Counts frc; 76.184 76.185 // Visit everybody reachable! 76.186 // Allocate stack of size C->unique()/2 to avoid frequent realloc 76.187 Node_Stack nstack(unique() >> 1); 76.188 - final_graph_reshaping_walk(nstack, root(), fpu); 76.189 + final_graph_reshaping_walk(nstack, root(), frc); 76.190 76.191 // Check for unreachable (from below) code (i.e., infinite loops). 76.192 - for( uint i = 0; i < fpu._tests.size(); i++ ) { 76.193 - MultiBranchNode *n = fpu._tests[i]->as_MultiBranch(); 76.194 + for( uint i = 0; i < frc._tests.size(); i++ ) { 76.195 + MultiBranchNode *n = frc._tests[i]->as_MultiBranch(); 76.196 // Get number of CFG targets. 76.197 // Note that PCTables include exception targets after calls. 76.198 uint required_outcnt = n->required_outcnt(); 76.199 @@ -2497,7 +2512,7 @@ 76.200 // Check that I actually visited all kids. Unreached kids 76.201 // must be infinite loops. 76.202 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) 76.203 - if (!fpu._visited.test(n->fast_out(j)->_idx)) { 76.204 + if (!frc._visited.test(n->fast_out(j)->_idx)) { 76.205 record_method_not_compilable("infinite loop"); 76.206 return true; // Found unvisited kid; must be unreach 76.207 } 76.208 @@ -2506,13 +2521,14 @@ 76.209 // If original bytecodes contained a mixture of floats and doubles 76.210 // check if the optimizer has made it homogenous, item (3). 76.211 if( Use24BitFPMode && Use24BitFP && 76.212 - fpu.get_float_count() > 32 && 76.213 - fpu.get_double_count() == 0 && 76.214 - (10 * fpu.get_call_count() < fpu.get_float_count()) ) { 76.215 + frc.get_float_count() > 32 && 76.216 + frc.get_double_count() == 0 && 76.217 + (10 * frc.get_call_count() < frc.get_float_count()) ) { 76.218 set_24_bit_selection_and_mode( false, true ); 76.219 } 76.220 76.221 - set_has_java_calls(fpu.get_java_call_count() > 0); 76.222 + set_java_calls(frc.get_java_call_count()); 76.223 + set_inner_loops(frc.get_inner_loop_count()); 76.224 76.225 // No infinite loops, no reason to bail out. 76.226 return false;
77.1 --- a/src/share/vm/opto/compile.hpp Mon Jul 20 08:20:00 2009 -0700 77.2 +++ b/src/share/vm/opto/compile.hpp Mon Jul 27 06:15:29 2009 -0700 77.3 @@ -223,7 +223,8 @@ 77.4 PhaseCFG* _cfg; // Results of CFG finding 77.5 bool _select_24_bit_instr; // We selected an instruction with a 24-bit result 77.6 bool _in_24_bit_fp_mode; // We are emitting instructions with 24-bit results 77.7 - bool _has_java_calls; // True if the method has java calls 77.8 + int _java_calls; // Number of java calls in the method 77.9 + int _inner_loops; // Number of inner loops in the method 77.10 Matcher* _matcher; // Engine to map ideal to machine instructions 77.11 PhaseRegAlloc* _regalloc; // Results of register allocation. 77.12 int _frame_slots; // Size of total frame in stack slots 77.13 @@ -505,7 +506,9 @@ 77.14 PhaseCFG* cfg() { return _cfg; } 77.15 bool select_24_bit_instr() const { return _select_24_bit_instr; } 77.16 bool in_24_bit_fp_mode() const { return _in_24_bit_fp_mode; } 77.17 - bool has_java_calls() const { return _has_java_calls; } 77.18 + bool has_java_calls() const { return _java_calls > 0; } 77.19 + int java_calls() const { return _java_calls; } 77.20 + int inner_loops() const { return _inner_loops; } 77.21 Matcher* matcher() { return _matcher; } 77.22 PhaseRegAlloc* regalloc() { return _regalloc; } 77.23 int frame_slots() const { return _frame_slots; } 77.24 @@ -532,7 +535,8 @@ 77.25 _in_24_bit_fp_mode = mode; 77.26 } 77.27 77.28 - void set_has_java_calls(bool z) { _has_java_calls = z; } 77.29 + void set_java_calls(int z) { _java_calls = z; } 77.30 + void set_inner_loops(int z) { _inner_loops = z; } 77.31 77.32 // Instruction bits passed off to the VM 77.33 int code_size() { return _method_size; }
78.1 --- a/src/share/vm/opto/library_call.cpp Mon Jul 20 08:20:00 2009 -0700 78.2 +++ b/src/share/vm/opto/library_call.cpp Mon Jul 27 06:15:29 2009 -0700 78.3 @@ -310,11 +310,6 @@ 78.4 if (!InlineAtomicLong) return NULL; 78.5 break; 78.6 78.7 - case vmIntrinsics::_Object_init: 78.8 - case vmIntrinsics::_invoke: 78.9 - // We do not intrinsify these; they are marked for other purposes. 78.10 - return NULL; 78.11 - 78.12 case vmIntrinsics::_getCallerClass: 78.13 if (!UseNewReflection) return NULL; 78.14 if (!InlineReflectionGetCallerClass) return NULL; 78.15 @@ -327,6 +322,8 @@ 78.16 break; 78.17 78.18 default: 78.19 + assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); 78.20 + assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); 78.21 break; 78.22 } 78.23 78.24 @@ -394,18 +391,11 @@ 78.25 } 78.26 78.27 if (PrintIntrinsics) { 78.28 - switch (intrinsic_id()) { 78.29 - case vmIntrinsics::_invoke: 78.30 - case vmIntrinsics::_Object_init: 78.31 - // We do not expect to inline these, so do not produce any noise about them. 78.32 - break; 78.33 - default: 78.34 - tty->print("Did not inline intrinsic %s%s at bci:%d in", 78.35 - vmIntrinsics::name_at(intrinsic_id()), 78.36 - (is_virtual() ? " (virtual)" : ""), kit.bci()); 78.37 - kit.caller()->print_short_name(tty); 78.38 - tty->print_cr(" (%d bytes)", kit.caller()->code_size()); 78.39 - } 78.40 + tty->print("Did not inline intrinsic %s%s at bci:%d in", 78.41 + vmIntrinsics::name_at(intrinsic_id()), 78.42 + (is_virtual() ? " (virtual)" : ""), kit.bci()); 78.43 + kit.caller()->print_short_name(tty); 78.44 + tty->print_cr(" (%d bytes)", kit.caller()->code_size()); 78.45 } 78.46 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); 78.47 return NULL;
79.1 --- a/src/share/vm/opto/output.cpp Mon Jul 20 08:20:00 2009 -0700 79.2 +++ b/src/share/vm/opto/output.cpp Mon Jul 27 06:15:29 2009 -0700 79.3 @@ -50,6 +50,13 @@ 79.4 init_scratch_buffer_blob(); 79.5 if (failing()) return; // Out of memory 79.6 79.7 + // The number of new nodes (mostly MachNop) is proportional to 79.8 + // the number of java calls and inner loops which are aligned. 79.9 + if ( C->check_node_count((NodeLimitFudgeFactor + C->java_calls()*3 + 79.10 + C->inner_loops()*(OptoLoopAlignment-1)), 79.11 + "out of nodes before code generation" ) ) { 79.12 + return; 79.13 + } 79.14 // Make sure I can find the Start Node 79.15 Block_Array& bbs = _cfg->_bbs; 79.16 Block *entry = _cfg->_blocks[1]; 79.17 @@ -1105,7 +1112,7 @@ 79.18 uint *call_returns = NEW_RESOURCE_ARRAY(uint, _cfg->_num_blocks+1); 79.19 79.20 uint return_offset = 0; 79.21 - MachNode *nop = new (this) MachNopNode(); 79.22 + int nop_size = (new (this) MachNopNode())->size(_regalloc); 79.23 79.24 int previous_offset = 0; 79.25 int current_offset = 0; 79.26 @@ -1188,7 +1195,6 @@ 79.27 } 79.28 79.29 // align the instruction if necessary 79.30 - int nop_size = nop->size(_regalloc); 79.31 int padding = mach->compute_padding(current_offset); 79.32 // Make sure safepoint node for polling is distinct from a call's 79.33 // return by adding a nop if needed. 79.34 @@ -1372,7 +1378,6 @@ 79.35 79.36 // If the next block is the top of a loop, pad this block out to align 79.37 // the loop top a little. Helps prevent pipe stalls at loop back branches. 79.38 - int nop_size = (new (this) MachNopNode())->size(_regalloc); 79.39 if( i<_cfg->_num_blocks-1 ) { 79.40 Block *nb = _cfg->_blocks[i+1]; 79.41 uint padding = nb->alignment_padding(current_offset);
80.1 --- a/src/share/vm/prims/unsafe.cpp Mon Jul 20 08:20:00 2009 -0700 80.2 +++ b/src/share/vm/prims/unsafe.cpp Mon Jul 27 06:15:29 2009 -0700 80.3 @@ -1048,7 +1048,11 @@ 80.4 oop e = JNIHandles::resolve(e_h); 80.5 oop p = JNIHandles::resolve(obj); 80.6 HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); 80.7 - update_barrier_set_pre((void*)addr, e); 80.8 + if (UseCompressedOops) { 80.9 + update_barrier_set_pre((narrowOop*)addr, e); 80.10 + } else { 80.11 + update_barrier_set_pre((oop*)addr, e); 80.12 + } 80.13 oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e); 80.14 jboolean success = (res == e); 80.15 if (success)
81.1 --- a/src/share/vm/runtime/arguments.cpp Mon Jul 20 08:20:00 2009 -0700 81.2 +++ b/src/share/vm/runtime/arguments.cpp Mon Jul 27 06:15:29 2009 -0700 81.3 @@ -1202,18 +1202,13 @@ 81.4 } 81.5 81.6 #ifdef _LP64 81.7 - // Compressed Headers do not work with CMS, which uses a bit in the klass 81.8 - // field offset to determine free list chunk markers. 81.9 // Check that UseCompressedOops can be set with the max heap size allocated 81.10 // by ergonomics. 81.11 if (MaxHeapSize <= max_heap_for_compressed_oops()) { 81.12 - if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) { 81.13 + if (FLAG_IS_DEFAULT(UseCompressedOops)) { 81.14 // Turn off until bug is fixed. 81.15 // the following line to return it to default status. 81.16 // FLAG_SET_ERGO(bool, UseCompressedOops, true); 81.17 - } else if (UseCompressedOops && UseG1GC) { 81.18 - warning(" UseCompressedOops does not currently work with UseG1GC; switching off UseCompressedOops. "); 81.19 - FLAG_SET_DEFAULT(UseCompressedOops, false); 81.20 } 81.21 #ifdef _WIN64 81.22 if (UseLargePages && UseCompressedOops) { 81.23 @@ -1454,6 +1449,7 @@ 81.24 if (UseSerialGC) i++; 81.25 if (UseConcMarkSweepGC || UseParNewGC) i++; 81.26 if (UseParallelGC || UseParallelOldGC) i++; 81.27 + if (UseG1GC) i++; 81.28 if (i > 1) { 81.29 jio_fprintf(defaultStream::error_stream(), 81.30 "Conflicting collector combinations in option list; " 81.31 @@ -2603,22 +2599,6 @@ 81.32 return result; 81.33 } 81.34 81.35 - // These are hacks until G1 is fully supported and tested 81.36 - // but lets you force -XX:+UseG1GC in PRT and get it where it (mostly) works 81.37 - if (UseG1GC) { 81.38 - if (UseConcMarkSweepGC || UseParNewGC || UseParallelGC || UseParallelOldGC || UseSerialGC) { 81.39 -#ifndef PRODUCT 81.40 - tty->print_cr("-XX:+UseG1GC is incompatible with other collectors, using UseG1GC"); 81.41 -#endif // PRODUCT 81.42 - UseConcMarkSweepGC = false; 81.43 - UseParNewGC = false; 81.44 - UseParallelGC = false; 81.45 - UseParallelOldGC = false; 81.46 - UseSerialGC = false; 81.47 - } 81.48 - no_shared_spaces(); 81.49 - } 81.50 - 81.51 #ifndef PRODUCT 81.52 if (TraceBytecodesAt != 0) { 81.53 TraceBytecodes = true; 81.54 @@ -2676,10 +2656,7 @@ 81.55 } else if (UseParNewGC) { 81.56 // Set some flags for ParNew 81.57 set_parnew_gc_flags(); 81.58 - } 81.59 - // Temporary; make the "if" an "else-if" before 81.60 - // we integrate G1. XXX 81.61 - if (UseG1GC) { 81.62 + } else if (UseG1GC) { 81.63 // Set some flags for garbage-first, if needed. 81.64 set_g1_gc_flags(); 81.65 }
82.1 --- a/src/share/vm/runtime/atomic.hpp Mon Jul 20 08:20:00 2009 -0700 82.2 +++ b/src/share/vm/runtime/atomic.hpp Mon Jul 27 06:15:29 2009 -0700 82.3 @@ -39,6 +39,8 @@ 82.4 static void store_ptr(intptr_t store_value, volatile intptr_t* dest); 82.5 static void store_ptr(void* store_value, volatile void* dest); 82.6 82.7 + static jlong load(volatile jlong* src); 82.8 + 82.9 // Atomically add to a location, return updated value 82.10 static jint add (jint add_value, volatile jint* dest); 82.11 static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
83.1 --- a/src/share/vm/runtime/globals.hpp Mon Jul 20 08:20:00 2009 -0700 83.2 +++ b/src/share/vm/runtime/globals.hpp Mon Jul 27 06:15:29 2009 -0700 83.3 @@ -1994,6 +1994,10 @@ 83.4 product_rw(bool, PrintHeapAtGC, false, \ 83.5 "Print heap layout before and after each GC") \ 83.6 \ 83.7 + product_rw(bool, PrintHeapAtGCExtended, false, \ 83.8 + "Prints extended information about the layout of the heap " \ 83.9 + "when -XX:+PrintHeapAtGC is set") \ 83.10 + \ 83.11 product(bool, PrintHeapAtSIGBREAK, true, \ 83.12 "Print heap layout in response to SIGBREAK") \ 83.13 \
84.1 --- a/src/share/vm/runtime/safepoint.cpp Mon Jul 20 08:20:00 2009 -0700 84.2 +++ b/src/share/vm/runtime/safepoint.cpp Mon Jul 27 06:15:29 2009 -0700 84.3 @@ -49,7 +49,7 @@ 84.4 // In the future we should investigate whether CMS can use the 84.5 // more-general mechanism below. DLD (01/05). 84.6 ConcurrentMarkSweepThread::synchronize(false); 84.7 - } else { 84.8 + } else if (UseG1GC) { 84.9 ConcurrentGCThread::safepoint_synchronize(); 84.10 } 84.11 #endif // SERIALGC 84.12 @@ -400,7 +400,7 @@ 84.13 // If there are any concurrent GC threads resume them. 84.14 if (UseConcMarkSweepGC) { 84.15 ConcurrentMarkSweepThread::desynchronize(false); 84.16 - } else { 84.17 + } else if (UseG1GC) { 84.18 ConcurrentGCThread::safepoint_desynchronize(); 84.19 } 84.20 #endif // SERIALGC
85.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Mon Jul 20 08:20:00 2009 -0700 85.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Mon Jul 27 06:15:29 2009 -0700 85.3 @@ -119,6 +119,7 @@ 85.4 assert(false, "should be optimized out"); 85.5 return; 85.6 } 85.7 + assert(orig->is_oop(true /* ignore mark word */), "Error"); 85.8 // store the original value that was in the field reference 85.9 thread->satb_mark_queue().enqueue(orig); 85.10 JRT_END
86.1 --- a/src/share/vm/runtime/stackValue.cpp Mon Jul 20 08:20:00 2009 -0700 86.2 +++ b/src/share/vm/runtime/stackValue.cpp Mon Jul 27 06:15:29 2009 -0700 86.3 @@ -104,7 +104,17 @@ 86.4 } 86.5 #endif 86.6 case Location::oop: { 86.7 - Handle h(*(oop *)value_addr); // Wrap a handle around the oop 86.8 + oop val = *(oop *)value_addr; 86.9 +#ifdef _LP64 86.10 + if (Universe::is_narrow_oop_base(val)) { 86.11 + // Compiled code may produce decoded oop = narrow_oop_base 86.12 + // when a narrow oop implicit null check is used. 86.13 + // The narrow_oop_base could be NULL or be the address 86.14 + // of the page below heap. Use NULL value for both cases. 86.15 + val = (oop)NULL; 86.16 + } 86.17 +#endif 86.18 + Handle h(val); // Wrap a handle around the oop 86.19 return new StackValue(h); 86.20 } 86.21 case Location::addr: {
87.1 --- a/src/share/vm/utilities/taskqueue.cpp Mon Jul 20 08:20:00 2009 -0700 87.2 +++ b/src/share/vm/utilities/taskqueue.cpp Mon Jul 27 06:15:29 2009 -0700 87.3 @@ -64,15 +64,18 @@ 87.4 } 87.5 87.6 void ParallelTaskTerminator::yield() { 87.7 + assert(_offered_termination <= _n_threads, "Invariant"); 87.8 os::yield(); 87.9 } 87.10 87.11 void ParallelTaskTerminator::sleep(uint millis) { 87.12 + assert(_offered_termination <= _n_threads, "Invariant"); 87.13 os::sleep(Thread::current(), millis, false); 87.14 } 87.15 87.16 bool 87.17 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { 87.18 + assert(_offered_termination < _n_threads, "Invariant"); 87.19 Atomic::inc(&_offered_termination); 87.20 87.21 uint yield_count = 0; 87.22 @@ -96,6 +99,7 @@ 87.23 // Loop waiting for all threads to offer termination or 87.24 // more work. 87.25 while (true) { 87.26 + assert(_offered_termination <= _n_threads, "Invariant"); 87.27 // Are all threads offering termination? 87.28 if (_offered_termination == _n_threads) { 87.29 return true; 87.30 @@ -151,6 +155,7 @@ 87.31 if (peek_in_queue_set() || 87.32 (terminator != NULL && terminator->should_exit_termination())) { 87.33 Atomic::dec(&_offered_termination); 87.34 + assert(_offered_termination < _n_threads, "Invariant"); 87.35 return false; 87.36 } 87.37 }
88.1 --- a/src/share/vm/utilities/taskqueue.hpp Mon Jul 20 08:20:00 2009 -0700 88.2 +++ b/src/share/vm/utilities/taskqueue.hpp Mon Jul 27 06:15:29 2009 -0700 88.3 @@ -560,8 +560,14 @@ 88.4 class StarTask { 88.5 void* _holder; // either union oop* or narrowOop* 88.6 public: 88.7 - StarTask(narrowOop *p) { _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); } 88.8 - StarTask(oop *p) { _holder = (void*)p; } 88.9 + StarTask(narrowOop* p) { 88.10 + assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); 88.11 + _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); 88.12 + } 88.13 + StarTask(oop* p) { 88.14 + assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); 88.15 + _holder = (void*)p; 88.16 + } 88.17 StarTask() { _holder = NULL; } 88.18 operator oop*() { return (oop*)_holder; } 88.19 operator narrowOop*() {
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 89.2 +++ b/test/compiler/6826736/Test.java Mon Jul 27 06:15:29 2009 -0700 89.3 @@ -0,0 +1,75 @@ 89.4 +/* 89.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 89.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 89.7 + * 89.8 + * This code is free software; you can redistribute it and/or modify it 89.9 + * under the terms of the GNU General Public License version 2 only, as 89.10 + * published by the Free Software Foundation. 89.11 + * 89.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 89.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 89.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 89.15 + * version 2 for more details (a copy is included in the LICENSE file that 89.16 + * accompanied this code). 89.17 + * 89.18 + * You should have received a copy of the GNU General Public License version 89.19 + * 2 along with this work; if not, write to the Free Software Foundation, 89.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 89.21 + * 89.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 89.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 89.24 + * have any questions. 89.25 + * 89.26 + */ 89.27 + 89.28 +/** 89.29 + * @test 89.30 + * @bug 6826736 89.31 + * @summary CMS: core dump with -XX:+UseCompressedOops 89.32 + * 89.33 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:CompileThreshold=100 -XX:CompileOnly=Test.test -XX:-BlockLayoutRotateLoops -XX:LoopUnrollLimit=0 Test 89.34 + */ 89.35 + 89.36 +public class Test { 89.37 + int[] arr; 89.38 + int[] arr2; 89.39 + int test(int r) { 89.40 + for (int i = 0; i < 100; i++) { 89.41 + for (int j = i; j < 100; j++) { 89.42 + int a = 0; 89.43 + for (long k = 0; k < 100; k++) { 89.44 + a += k; 89.45 + } 89.46 + if (arr != null) 89.47 + a = arr[j]; 89.48 + r += a; 89.49 + } 89.50 + } 89.51 + return r; 89.52 + } 89.53 + 89.54 + public static void main(String[] args) { 89.55 + int r = 0; 89.56 + Test t = new Test(); 89.57 + for (int i = 0; i < 100; i++) { 89.58 + t.arr = new int[100]; 89.59 + r = t.test(r); 89.60 + } 89.61 + System.out.println("Warmup 1 is done."); 89.62 + for (int i = 0; i < 100; i++) { 89.63 + t.arr = null; 89.64 + r = t.test(r); 89.65 + } 89.66 + System.out.println("Warmup 2 is done."); 89.67 + for (int i = 0; i < 100; i++) { 89.68 + t.arr = new int[100]; 89.69 + r = t.test(r); 89.70 + } 89.71 + System.out.println("Warmup is done."); 89.72 + for (int i = 0; i < 100; i++) { 89.73 + t.arr = new int[1000000]; 89.74 + t.arr = null; 89.75 + r = t.test(r); 89.76 + } 89.77 + } 89.78 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 90.2 +++ b/test/compiler/6857159/Test6857159.java Mon Jul 27 06:15:29 2009 -0700 90.3 @@ -0,0 +1,68 @@ 90.4 +/* 90.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 90.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 90.7 + * 90.8 + * This code is free software; you can redistribute it and/or modify it 90.9 + * under the terms of the GNU General Public License version 2 only, as 90.10 + * published by the Free Software Foundation. 90.11 + * 90.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 90.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 90.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 90.15 + * version 2 for more details (a copy is included in the LICENSE file that 90.16 + * accompanied this code). 90.17 + * 90.18 + * You should have received a copy of the GNU General Public License version 90.19 + * 2 along with this work; if not, write to the Free Software Foundation, 90.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 90.21 + * 90.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 90.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 90.24 + * have any questions. 90.25 + * 90.26 + */ 90.27 + 90.28 +/** 90.29 + * @test 90.30 + * @bug 6857159 90.31 + * @summary local schedule failed with checkcast of Thread.currentThread() 90.32 + * 90.33 + * @run shell Test6857159.sh 90.34 + */ 90.35 + 90.36 +public class Test6857159 extends Thread { 90.37 + static class ct0 extends Test6857159 { 90.38 + public void message() { 90.39 + // System.out.println("message"); 90.40 + } 90.41 + 90.42 + public void run() { 90.43 + message(); 90.44 + ct0 ct = (ct0) Thread.currentThread(); 90.45 + ct.message(); 90.46 + } 90.47 + } 90.48 + static class ct1 extends ct0 { 90.49 + public void message() { 90.50 + // System.out.println("message"); 90.51 + } 90.52 + } 90.53 + static class ct2 extends ct0 { 90.54 + public void message() { 90.55 + // System.out.println("message"); 90.56 + } 90.57 + } 90.58 + 90.59 + public static void main(String[] args) throws Exception { 90.60 + for (int i = 0; i < 100000; i++) { 90.61 + Thread t = null; 90.62 + switch (i % 3) { 90.63 + case 0: t = new ct0(); break; 90.64 + case 1: t = new ct1(); break; 90.65 + case 2: t = new ct2(); break; 90.66 + } 90.67 + t.start(); 90.68 + t.join(); 90.69 + } 90.70 + } 90.71 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 91.2 +++ b/test/compiler/6857159/Test6857159.sh Mon Jul 27 06:15:29 2009 -0700 91.3 @@ -0,0 +1,65 @@ 91.4 +#!/bin/sh 91.5 +# 91.6 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 91.7 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 91.8 +# 91.9 +# This code is free software; you can redistribute it and/or modify it 91.10 +# under the terms of the GNU General Public License version 2 only, as 91.11 +# published by the Free Software Foundation. 91.12 +# 91.13 +# This code is distributed in the hope that it will be useful, but WITHOUT 91.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 91.15 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 91.16 +# version 2 for more details (a copy is included in the LICENSE file that 91.17 +# accompanied this code). 91.18 +# 91.19 +# You should have received a copy of the GNU General Public License version 91.20 +# 2 along with this work; if not, write to the Free Software Foundation, 91.21 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 91.22 +# 91.23 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 91.24 +# CA 95054 USA or visit www.sun.com if you need additional information or 91.25 +# have any questions. 91.26 +# 91.27 +# 91.28 + 91.29 +if [ "${TESTSRC}" = "" ] 91.30 +then 91.31 + echo "TESTSRC not set. Test cannot execute. Failed." 91.32 + exit 1 91.33 +fi 91.34 +echo "TESTSRC=${TESTSRC}" 91.35 +if [ "${TESTJAVA}" = "" ] 91.36 +then 91.37 + echo "TESTJAVA not set. Test cannot execute. Failed." 91.38 + exit 1 91.39 +fi 91.40 +echo "TESTJAVA=${TESTJAVA}" 91.41 +if [ "${TESTCLASSES}" = "" ] 91.42 +then 91.43 + echo "TESTCLASSES not set. Test cannot execute. Failed." 91.44 + exit 1 91.45 +fi 91.46 +echo "TESTCLASSES=${TESTCLASSES}" 91.47 +echo "CLASSPATH=${CLASSPATH}" 91.48 + 91.49 +set -x 91.50 + 91.51 +cp ${TESTSRC}/Test6857159.java . 91.52 +cp ${TESTSRC}/Test6857159.sh . 91.53 + 91.54 +${TESTJAVA}/bin/javac -d . Test6857159.java 91.55 + 91.56 +${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1 91.57 + 91.58 +grep "COMPILE SKIPPED" test.out 91.59 + 91.60 +result=$? 91.61 +if [ $result -eq 1 ] 91.62 +then 91.63 + echo "Passed" 91.64 + exit 0 91.65 +else 91.66 + echo "Failed" 91.67 + exit 1 91.68 +fi
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 92.2 +++ b/test/compiler/6863420/Test.java Mon Jul 27 06:15:29 2009 -0700 92.3 @@ -0,0 +1,91 @@ 92.4 +/* 92.5 + * Copyright 2009 D.E. Shaw. All Rights Reserved. 92.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 92.7 + * 92.8 + * This code is free software; you can redistribute it and/or modify it 92.9 + * under the terms of the GNU General Public License version 2 only, as 92.10 + * published by the Free Software Foundation. 92.11 + * 92.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 92.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 92.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 92.15 + * version 2 for more details (a copy is included in the LICENSE file that 92.16 + * accompanied this code). 92.17 + * 92.18 + * You should have received a copy of the GNU General Public License version 92.19 + * 2 along with this work; if not, write to the Free Software Foundation, 92.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 92.21 + * 92.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 92.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 92.24 + * have any questions. 92.25 + * 92.26 + */ 92.27 + 92.28 +/** 92.29 + * @test 92.30 + * @bug 6863420 92.31 + * @summary os::javaTimeNanos() go backward on Solaris x86 92.32 + * 92.33 + * @run main/othervm Test 92.34 + */ 92.35 + 92.36 +public class Test { 92.37 + static long value = 0; 92.38 + static boolean got_backward_time = false; 92.39 + 92.40 + public static void main(String args[]) { 92.41 + final int count = 100000; 92.42 + 92.43 + for (int numThreads = 1; numThreads <= 32; numThreads++) { 92.44 + final int numRuns = 1; 92.45 + for (int t=1; t <= numRuns; t++) { 92.46 + final int curRun = t; 92.47 + 92.48 + System.out.println("Spawning " + numThreads + " threads"); 92.49 + final Thread threads[] = new Thread[numThreads]; 92.50 + for (int i = 0; i < threads.length; i++) { 92.51 + Runnable thread = 92.52 + new Runnable() { 92.53 + public void run() { 92.54 + for (long l = 0; l < 100000; l++) { 92.55 + final long start = System.nanoTime(); 92.56 + if (value == 12345678) { 92.57 + System.out.println("Wow!"); 92.58 + } 92.59 + final long end = System.nanoTime(); 92.60 + final long time = end - start; 92.61 + value += time; 92.62 + if (time < 0) { 92.63 + System.out.println( 92.64 + "Backwards: " + 92.65 + "start=" + start + " " + 92.66 + "end=" + end + " " + 92.67 + "time= " + time 92.68 + ); 92.69 + got_backward_time = true; 92.70 + } 92.71 + } 92.72 + } 92.73 + }; 92.74 + threads[i] = new Thread(thread, "Thread" + i); 92.75 + } 92.76 + for (int i = 0; i < threads.length; i++) { 92.77 + threads[i].start(); 92.78 + } 92.79 + for (int i = 0; i < threads.length; i++) { 92.80 + try { 92.81 + threads[i].join(); 92.82 + } 92.83 + catch (InterruptedException e) { 92.84 + continue; 92.85 + } 92.86 + } 92.87 + } 92.88 + } 92.89 + 92.90 + if (got_backward_time) { 92.91 + System.exit(97); 92.92 + } 92.93 + } 92.94 +}