Fri, 27 Feb 2009 15:13:00 -0800
Merge
1.1 --- a/.hgtags Sat Jan 31 17:19:42 2009 -0800 1.2 +++ b/.hgtags Fri Feb 27 15:13:00 2009 -0800 1.3 @@ -18,3 +18,9 @@ 1.4 f9d938ede1960d18cb7cf23c645b026519c1a678 jdk7-b41 1.5 ad8c8ca4ab0f4c86e74c061958f44a8f4a930f2c jdk7-b42 1.6 fc6a5ae3fef5ebacfa896dbb3ae37715e388e282 jdk7-b43 1.7 +809e899c638bd9b21836abf9d09ab2a30ff3900b jdk7-b44 1.8 +945bf754069766e76873c53102fae48abf04cf5b jdk7-b45 1.9 +16bb38eeda35b46268eefa4c1f829eb086e0ca46 jdk7-b46 1.10 +fcb923bad68e2b10380a030ea83a723f4dc3d4d6 jdk7-b47 1.11 +bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 1.12 +8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49
2.1 --- a/agent/src/os/linux/ps_core.c Sat Jan 31 17:19:42 2009 -0800 2.2 +++ b/agent/src/os/linux/ps_core.c Fri Feb 27 15:13:00 2009 -0800 2.3 @@ -238,8 +238,8 @@ 2.4 // Ignore the rest of the FileMapHeader. We don't need those fields here. 2.5 }; 2.6 2.7 -static bool read_int(struct ps_prochandle* ph, uintptr_t addr, int* pvalue) { 2.8 - int i; 2.9 +static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) { 2.10 + jboolean i; 2.11 if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) { 2.12 *pvalue = i; 2.13 return true; 2.14 @@ -295,7 +295,7 @@ 2.15 int fd = -1, m = 0; 2.16 uintptr_t base = 0, useSharedSpacesAddr = 0; 2.17 uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; 2.18 - int useSharedSpaces = 0; 2.19 + jboolean useSharedSpaces = 0; 2.20 map_info* mi = 0; 2.21 2.22 memset(classes_jsa, 0, sizeof(classes_jsa)); 2.23 @@ -306,12 +306,15 @@ 2.24 return false; 2.25 } 2.26 2.27 - if (read_int(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { 2.28 + // Hotspot vm types are not exported to build this library. So 2.29 + // using equivalent type jboolean to read the value of 2.30 + // UseSharedSpaces which is same as hotspot type "bool". 2.31 + if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { 2.32 print_debug("can't read the value of 'UseSharedSpaces' flag\n"); 2.33 return false; 2.34 } 2.35 2.36 - if (useSharedSpaces == 0) { 2.37 + if ((int)useSharedSpaces == 0) { 2.38 print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); 2.39 return true; 2.40 }
3.1 --- a/agent/src/os/solaris/proc/saproc.cpp Sat Jan 31 17:19:42 2009 -0800 3.2 +++ b/agent/src/os/solaris/proc/saproc.cpp Fri Feb 27 15:13:00 2009 -0800 3.3 @@ -502,8 +502,8 @@ 3.4 }; 3.5 3.6 static bool 3.7 -read_int(struct ps_prochandle* ph, psaddr_t addr, int* pvalue) { 3.8 - int i; 3.9 +read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) { 3.10 + jboolean i; 3.11 if (ps_pread(ph, addr, &i, sizeof(i)) == PS_OK) { 3.12 *pvalue = i; 3.13 return true; 3.14 @@ -575,10 +575,13 @@ 3.15 } 3.16 3.17 // read the value of the flag "UseSharedSpaces" 3.18 - int value = 0; 3.19 - if (read_int(ph, useSharedSpacesAddr, &value) != true) { 3.20 + // Since hotspot types are not available to build this library. So 3.21 + // equivalent type "jboolean" is used to read the value of "UseSharedSpaces" 3.22 + // which is same as hotspot type "bool". 3.23 + jboolean value = 0; 3.24 + if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) { 3.25 THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1); 3.26 - } else if (value == 0) { 3.27 + } else if ((int)value == 0) { 3.28 print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); 3.29 return 1; 3.30 }
4.1 --- a/make/hotspot_version Sat Jan 31 17:19:42 2009 -0800 4.2 +++ b/make/hotspot_version Fri Feb 27 15:13:00 2009 -0800 4.3 @@ -33,9 +33,9 @@ 4.4 # Don't put quotes (fail windows build). 4.5 HOTSPOT_VM_COPYRIGHT=Copyright 2008 4.6 4.7 -HS_MAJOR_VER=14 4.8 +HS_MAJOR_VER=15 4.9 HS_MINOR_VER=0 4.10 -HS_BUILD_NUMBER=10 4.11 +HS_BUILD_NUMBER=02 4.12 4.13 JDK_MAJOR_VER=1 4.14 JDK_MINOR_VER=7
5.1 --- a/src/cpu/sparc/vm/jni_sparc.h Sat Jan 31 17:19:42 2009 -0800 5.2 +++ b/src/cpu/sparc/vm/jni_sparc.h Fri Feb 27 15:13:00 2009 -0800 5.3 @@ -28,5 +28,11 @@ 5.4 #define JNICALL 5.5 5.6 typedef int jint; 5.7 -typedef long long jlong; 5.8 + 5.9 +#ifdef _LP64 5.10 + typedef long jlong; 5.11 +#else 5.12 + typedef long long jlong; 5.13 +#endif 5.14 + 5.15 typedef signed char jbyte;
6.1 --- a/src/cpu/sparc/vm/sparc.ad Sat Jan 31 17:19:42 2009 -0800 6.2 +++ b/src/cpu/sparc/vm/sparc.ad Fri Feb 27 15:13:00 2009 -0800 6.3 @@ -762,7 +762,7 @@ 6.4 case Assembler::stdf_op3: st_op = Op_StoreD; break; 6.5 6.6 case Assembler::ldsb_op3: ld_op = Op_LoadB; break; 6.7 - case Assembler::lduh_op3: ld_op = Op_LoadC; break; 6.8 + case Assembler::lduh_op3: ld_op = Op_LoadUS; break; 6.9 case Assembler::ldsh_op3: ld_op = Op_LoadS; break; 6.10 case Assembler::ldx_op3: // may become LoadP or stay LoadI 6.11 case Assembler::ldsw_op3: // may become LoadP or stay LoadI 6.12 @@ -3869,6 +3869,8 @@ 6.13 constraint(ALLOC_IN_RC(dflt_reg)); 6.14 match(RegD); 6.15 6.16 + match(regD_low); 6.17 + 6.18 format %{ %} 6.19 interface(REG_INTER); 6.20 %} 6.21 @@ -3883,7 +3885,7 @@ 6.22 6.23 operand regD_low() %{ 6.24 constraint(ALLOC_IN_RC(dflt_low_reg)); 6.25 - match(RegD); 6.26 + match(regD); 6.27 6.28 format %{ %} 6.29 interface(REG_INTER); 6.30 @@ -5314,9 +5316,9 @@ 6.31 ins_pipe(iload_mask_mem); 6.32 %} 6.33 6.34 -// Load Char (16bit UNsigned) into a Long Register 6.35 -instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{ 6.36 - match(Set dst (AndL (ConvI2L (LoadC mem)) bytemask)); 6.37 +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register 6.38 +instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{ 6.39 + match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask)); 6.40 ins_cost(MEMORY_REF_COST); 6.41 6.42 size(4); 6.43 @@ -5326,9 +5328,9 @@ 6.44 ins_pipe(iload_mask_mem); 6.45 %} 6.46 6.47 -// Load Char (16bit unsigned) 6.48 -instruct loadC(iRegI dst, memory mem) %{ 6.49 - match(Set dst (LoadC mem)); 6.50 +// Load Unsigned Short/Char (16bit unsigned) 6.51 +instruct loadUS(iRegI dst, memory mem) %{ 6.52 + match(Set dst (LoadUS mem)); 6.53 ins_cost(MEMORY_REF_COST); 6.54 6.55 size(4);
7.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Sat Jan 31 17:19:42 2009 -0800 7.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Feb 27 15:13:00 2009 -0800 7.3 @@ -5212,15 +5212,15 @@ 7.4 void MacroAssembler::reset_last_Java_frame(bool clear_fp, 7.5 bool clear_pc) { 7.6 // we must set sp to zero to clear frame 7.7 - movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), (int32_t)NULL_WORD); 7.8 + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); 7.9 // must clear fp, so that compiled frames are not confused; it is 7.10 // possible that we need it only for debugging 7.11 if (clear_fp) { 7.12 - movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), (int32_t)NULL_WORD); 7.13 + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); 7.14 } 7.15 7.16 if (clear_pc) { 7.17 - movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), (int32_t)NULL_WORD); 7.18 + movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); 7.19 } 7.20 } 7.21 7.22 @@ -5670,7 +5670,7 @@ 7.23 // get oop result if there is one and reset the value in the thread 7.24 if (oop_result->is_valid()) { 7.25 movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); 7.26 - movptr(Address(java_thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 7.27 + movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); 7.28 verify_oop(oop_result, "broken oop in call_VM_base"); 7.29 } 7.30 } 7.31 @@ -6426,13 +6426,13 @@ 7.32 get_thread(java_thread); 7.33 } 7.34 // we must set sp to zero to clear frame 7.35 - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), (int32_t)NULL_WORD); 7.36 + movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); 7.37 if (clear_fp) { 7.38 - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), (int32_t)NULL_WORD); 7.39 + movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); 7.40 } 7.41 7.42 if (clear_pc) 7.43 - movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), (int32_t)NULL_WORD); 7.44 + movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); 7.45 7.46 } 7.47 7.48 @@ -6943,29 +6943,32 @@ 7.49 7.50 Label slow_case, done; 7.51 7.52 - // x ?<= pi/4 7.53 - fld_d(ExternalAddress((address)&pi_4)); 7.54 - fld_s(1); // Stack: X PI/4 X 7.55 - fabs(); // Stack: |X| PI/4 X 7.56 - fcmp(tmp); 7.57 - jcc(Assembler::above, slow_case); 7.58 - 7.59 - // fastest case: -pi/4 <= x <= pi/4 7.60 - switch(trig) { 7.61 - case 's': 7.62 - fsin(); 7.63 - break; 7.64 - case 'c': 7.65 - fcos(); 7.66 - break; 7.67 - case 't': 7.68 - ftan(); 7.69 - break; 7.70 - default: 7.71 - assert(false, "bad intrinsic"); 7.72 - break; 7.73 - } 7.74 - jmp(done); 7.75 + ExternalAddress pi4_adr = (address)&pi_4; 7.76 + if (reachable(pi4_adr)) { 7.77 + // x ?<= pi/4 7.78 + fld_d(pi4_adr); 7.79 + fld_s(1); // Stack: X PI/4 X 7.80 + fabs(); // Stack: |X| PI/4 X 7.81 + fcmp(tmp); 7.82 + jcc(Assembler::above, slow_case); 7.83 + 7.84 + // fastest case: -pi/4 <= x <= pi/4 7.85 + switch(trig) { 7.86 + case 's': 7.87 + fsin(); 7.88 + break; 7.89 + case 'c': 7.90 + fcos(); 7.91 + break; 7.92 + case 't': 7.93 + ftan(); 7.94 + break; 7.95 + default: 7.96 + assert(false, "bad intrinsic"); 7.97 + break; 7.98 + } 7.99 + jmp(done); 7.100 + } 7.101 7.102 // slow case: runtime call 7.103 bind(slow_case);
8.1 --- a/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp Sat Jan 31 17:19:42 2009 -0800 8.2 +++ b/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp Fri Feb 27 15:13:00 2009 -0800 8.3 @@ -213,7 +213,7 @@ 8.4 8.5 inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) { 8.6 /* it's possible we could catch this special case implicitly */ 8.7 - if (op1 == 0x80000000 && op2 == -1) return op1; 8.8 + if ((juint)op1 == 0x80000000 && op2 == -1) return op1; 8.9 else return op1 / op2; 8.10 } 8.11 8.12 @@ -231,7 +231,7 @@ 8.13 8.14 inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) { 8.15 /* it's possible we could catch this special case implicitly */ 8.16 - if (op1 == 0x80000000 && op2 == -1) return 0; 8.17 + if ((juint)op1 == 0x80000000 && op2 == -1) return 0; 8.18 else return op1 % op2; 8.19 } 8.20
9.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Sat Jan 31 17:19:42 2009 -0800 9.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Feb 27 15:13:00 2009 -0800 9.3 @@ -779,7 +779,7 @@ 9.4 case T_OBJECT: // fall through 9.5 case T_ARRAY: 9.6 if (c->as_jobject() == NULL) { 9.7 - __ movptr(as_Address(addr), (int32_t)NULL_WORD); 9.8 + __ movptr(as_Address(addr), NULL_WORD); 9.9 } else { 9.10 if (is_literal_address(addr)) { 9.11 ShouldNotReachHere();
10.1 --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Sat Jan 31 17:19:42 2009 -0800 10.2 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Feb 27 15:13:00 2009 -0800 10.3 @@ -78,10 +78,10 @@ 10.4 movptr(rax, Address(thread, Thread::pending_exception_offset())); 10.5 // make sure that the vm_results are cleared 10.6 if (oop_result1->is_valid()) { 10.7 - movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 10.8 + movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 10.9 } 10.10 if (oop_result2->is_valid()) { 10.11 - movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); 10.12 + movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 10.13 } 10.14 if (frame_size() == no_frame_size) { 10.15 leave(); 10.16 @@ -96,12 +96,12 @@ 10.17 // get oop results if there are any and reset the values in the thread 10.18 if (oop_result1->is_valid()) { 10.19 movptr(oop_result1, Address(thread, JavaThread::vm_result_offset())); 10.20 - movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 10.21 + movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 10.22 verify_oop(oop_result1); 10.23 } 10.24 if (oop_result2->is_valid()) { 10.25 movptr(oop_result2, Address(thread, JavaThread::vm_result_2_offset())); 10.26 - movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); 10.27 + movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 10.28 verify_oop(oop_result2); 10.29 } 10.30 return call_offset; 10.31 @@ -728,8 +728,8 @@ 10.32 10.33 // clear exception fields in JavaThread because they are no longer needed 10.34 // (fields must be cleared because they are processed by GC otherwise) 10.35 - __ movptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); 10.36 - __ movptr(Address(thread, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); 10.37 + __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); 10.38 + __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); 10.39 10.40 // pop the stub frame off 10.41 __ leave(); 10.42 @@ -878,7 +878,7 @@ 10.43 10.44 // load and clear pending exception 10.45 __ movptr(rax, Address(thread, Thread::pending_exception_offset())); 10.46 - __ movptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); 10.47 + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 10.48 10.49 // check that there is really a valid exception 10.50 __ verify_not_null_oop(rax); 10.51 @@ -971,14 +971,14 @@ 10.52 // load pending exception oop into rax, 10.53 __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); 10.54 // clear pending exception 10.55 - __ movptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); 10.56 + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 10.57 10.58 // load issuing PC (the return address for this stub) into rdx 10.59 __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); 10.60 10.61 // make sure that the vm_results are cleared (may be unnecessary) 10.62 - __ movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 10.63 - __ movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); 10.64 + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 10.65 + __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 10.66 10.67 // verify that that there is really a valid exception in rax, 10.68 __ verify_not_null_oop(exception_oop); 10.69 @@ -1393,7 +1393,7 @@ 10.70 __ ret(0); 10.71 10.72 __ bind(miss); 10.73 - __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), 0); // result 10.74 + __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result 10.75 __ pop(rax); 10.76 __ pop(rcx); 10.77 __ pop(rsi);
11.1 --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Sat Jan 31 17:19:42 2009 -0800 11.2 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Fri Feb 27 15:13:00 2009 -0800 11.3 @@ -594,7 +594,7 @@ 11.4 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax); 11.5 11.6 // for c++ interpreter can rsi really be munged? 11.7 - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); // restore state 11.8 + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); // restore state 11.9 __ movptr(rbx, Address(state, byte_offset_of(BytecodeInterpreter, _method))); // restore method 11.10 __ movptr(rdi, Address(state, byte_offset_of(BytecodeInterpreter, _locals))); // get locals pointer 11.11 11.12 @@ -658,7 +658,7 @@ 11.13 const Address size_of_stack (rbx, methodOopDesc::max_stack_offset()); 11.14 // Always give one monitor to allow us to start interp if sync method. 11.15 // Any additional monitors need a check when moving the expression stack 11.16 - const one_monitor = frame::interpreter_frame_monitor_size() * wordSize; 11.17 + const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; 11.18 __ load_unsigned_word(rax, size_of_stack); // get size of expression stack in words 11.19 __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor)); 11.20 __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size)); 11.21 @@ -1829,7 +1829,7 @@ 11.22 Label unwind_and_forward; 11.23 11.24 // restore state pointer. 11.25 - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); 11.26 + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); 11.27 11.28 __ movptr(rbx, STATE(_method)); // get method 11.29 #ifdef _LP64 11.30 @@ -1877,14 +1877,14 @@ 11.31 11.32 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases 11.33 if (UseSSE < 2) { 11.34 - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); 11.35 + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); 11.36 __ movptr(rbx, STATE(_result._to_call._callee)); // get method just executed 11.37 __ movl(rcx, Address(rbx, methodOopDesc::result_index_offset())); 11.38 __ cmpl(rcx, AbstractInterpreter::BasicType_as_index(T_FLOAT)); // Result stub address array index 11.39 __ jcc(Assembler::equal, do_float); 11.40 __ cmpl(rcx, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); // Result stub address array index 11.41 __ jcc(Assembler::equal, do_double); 11.42 -#ifdef COMPILER2 11.43 +#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) 11.44 __ empty_FPU_stack(); 11.45 #endif // COMPILER2 11.46 __ jmp(done_conv); 11.47 @@ -1928,7 +1928,7 @@ 11.48 11.49 // Restore rsi/r13 as compiled code may not preserve it 11.50 11.51 - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); 11.52 + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); 11.53 11.54 // restore stack to what we had when we left (in case i2c extended it) 11.55 11.56 @@ -1942,7 +1942,7 @@ 11.57 #else 11.58 __ movptr(rcx, STATE(_thread)); // get thread 11.59 __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); 11.60 -#endif / __LP64 11.61 +#endif // _LP64 11.62 __ jcc(Assembler::notZero, return_with_exception); 11.63 11.64 // get method just executed
12.1 --- a/src/cpu/x86/vm/frame_x86.inline.hpp Sat Jan 31 17:19:42 2009 -0800 12.2 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Fri Feb 27 15:13:00 2009 -0800 12.3 @@ -139,7 +139,7 @@ 12.4 #ifdef CC_INTERP 12.5 12.6 inline interpreterState frame::get_interpreterState() const { 12.7 - return ((interpreterState)addr_at( -sizeof(BytecodeInterpreter)/wordSize )); 12.8 + return ((interpreterState)addr_at( -((int)sizeof(BytecodeInterpreter))/wordSize )); 12.9 } 12.10 12.11 inline intptr_t* frame::sender_sp() const {
13.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 13.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 13.3 @@ -133,7 +133,7 @@ 13.4 + in_ByteSize(wordSize)); 13.5 switch (state) { 13.6 case atos: movptr(rax, oop_addr); 13.7 - movptr(oop_addr, (int32_t)NULL_WORD); 13.8 + movptr(oop_addr, NULL_WORD); 13.9 verify_oop(rax, state); break; 13.10 case ltos: 13.11 movl(rdx, val_addr1); // fall through 13.12 @@ -148,8 +148,8 @@ 13.13 } 13.14 // Clean up tos value in the thread object 13.15 movl(tos_addr, (int32_t) ilgl); 13.16 - movptr(val_addr, (int32_t)NULL_WORD); 13.17 - NOT_LP64(movl(val_addr1, (int32_t)NULL_WORD)); 13.18 + movptr(val_addr, NULL_WORD); 13.19 + NOT_LP64(movptr(val_addr1, NULL_WORD)); 13.20 } 13.21 13.22 13.23 @@ -944,7 +944,7 @@ 13.24 movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); 13.25 13.26 // Free entry 13.27 - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); 13.28 + movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); 13.29 13.30 if (UseBiasedLocking) { 13.31 biased_locking_exit(obj_reg, header_reg, done);
14.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.hpp Sat Jan 31 17:19:42 2009 -0800 14.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp Fri Feb 27 15:13:00 2009 -0800 14.3 @@ -120,7 +120,7 @@ 14.4 void empty_expression_stack() { 14.5 movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); 14.6 // NULL last_sp until next java call 14.7 - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 14.8 + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 14.9 } 14.10 14.11 // Tagged stack helpers for swap and dup
15.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Sat Jan 31 17:19:42 2009 -0800 15.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Feb 27 15:13:00 2009 -0800 15.3 @@ -30,7 +30,7 @@ 15.4 15.5 #ifdef CC_INTERP 15.6 void InterpreterMacroAssembler::get_method(Register reg) { 15.7 - movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); 15.8 + movptr(reg, Address(rbp, -((int)sizeof(BytecodeInterpreter) + 2 * wordSize))); 15.9 movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); 15.10 } 15.11 #endif // CC_INTERP
16.1 --- a/src/cpu/x86/vm/interpreterRT_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 16.2 +++ b/src/cpu/x86/vm/interpreterRT_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 16.3 @@ -54,7 +54,7 @@ 16.4 __ cmpptr(Address(from(), Interpreter::local_offset_in_bytes(from_offset)), (int32_t)NULL_WORD); // do not use temp() to avoid AGI 16.5 Label L; 16.6 __ jcc(Assembler::notZero, L); 16.7 - __ movptr(temp(), ((int32_t)NULL_WORD)); 16.8 + __ movptr(temp(), NULL_WORD); 16.9 __ bind(L); 16.10 __ movptr(Address(to(), to_offset * wordSize), temp()); 16.11 } 16.12 @@ -110,7 +110,7 @@ 16.13 virtual void pass_object() { 16.14 // pass address of from 16.15 intptr_t from_addr = (intptr_t)(_from + Interpreter::local_offset_in_bytes(0)); 16.16 - *_to++ = (*(intptr_t*)from_addr == 0) ? NULL : from_addr; 16.17 + *_to++ = (*(intptr_t*)from_addr == 0) ? NULL_WORD : from_addr; 16.18 debug_only(verify_tag(frame::TagReference)); 16.19 _from -= Interpreter::stackElementSize(); 16.20 }
17.1 --- a/src/cpu/x86/vm/jni_x86.h Sat Jan 31 17:19:42 2009 -0800 17.2 +++ b/src/cpu/x86/vm/jni_x86.h Fri Feb 27 15:13:00 2009 -0800 17.3 @@ -32,7 +32,13 @@ 17.4 #define JNICALL 17.5 17.6 typedef int jint; 17.7 + 17.8 +#ifdef _LP64 17.9 + typedef long jlong; 17.10 +#else 17.11 typedef long long jlong; 17.12 +#endif 17.13 + 17.14 #else 17.15 #define JNIEXPORT __declspec(dllexport) 17.16 #define JNIIMPORT __declspec(dllimport)
18.1 --- a/src/cpu/x86/vm/runtime_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 18.2 +++ b/src/cpu/x86/vm/runtime_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 18.3 @@ -129,11 +129,11 @@ 18.4 // Get the exception pc in case we are deoptimized 18.5 __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); 18.6 #ifdef ASSERT 18.7 - __ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), (int32_t)NULL_WORD); 18.8 - __ movptr(Address(rcx, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); 18.9 + __ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), NULL_WORD); 18.10 + __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); 18.11 #endif 18.12 // Clear the exception oop so GC no longer processes it as a root. 18.13 - __ movptr(Address(rcx, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); 18.14 + __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); 18.15 18.16 __ pop(rcx); 18.17
19.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 19.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 19.3 @@ -39,6 +39,8 @@ 19.4 RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; 19.5 RuntimeStub* SharedRuntime::_resolve_static_call_blob; 19.6 19.7 +const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; 19.8 + 19.9 class RegisterSaver { 19.10 enum { FPU_regs_live = 8 /*for the FPU stack*/+8/*eight more for XMM registers*/ }; 19.11 // Capture info about frame layout 19.12 @@ -1299,7 +1301,7 @@ 19.13 19.14 // Now compute actual number of stack words we need rounding to make 19.15 // stack properly aligned. 19.16 - stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); 19.17 + stack_slots = round_to(stack_slots, StackAlignmentInSlots); 19.18 19.19 int stack_size = stack_slots * VMRegImpl::stack_slot_size; 19.20 19.21 @@ -1793,7 +1795,7 @@ 19.22 // reset handle block 19.23 __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); 19.24 19.25 - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); 19.26 + __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); 19.27 19.28 // Any exception pending? 19.29 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); 19.30 @@ -1865,7 +1867,7 @@ 19.31 // Save pending exception around call to VM (which contains an EXCEPTION_MARK) 19.32 19.33 __ pushptr(Address(thread, in_bytes(Thread::pending_exception_offset()))); 19.34 - __ movptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); 19.35 + __ movptr(Address(thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); 19.36 19.37 19.38 // should be a peal 19.39 @@ -2431,7 +2433,7 @@ 19.40 __ get_thread(rdi); 19.41 __ movptr(rdx, Address(rdi, JavaThread::exception_pc_offset())); 19.42 __ movptr(Address(rbp, wordSize), rdx); 19.43 - __ movptr(Address(rdi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); 19.44 + __ movptr(Address(rdi, JavaThread::exception_pc_offset()), NULL_WORD); 19.45 19.46 #ifdef ASSERT 19.47 // verify that there is really an exception oop in JavaThread 19.48 @@ -2489,8 +2491,8 @@ 19.49 __ jcc(Assembler::notEqual, noException); 19.50 __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); 19.51 __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); 19.52 - __ movptr(Address(rcx, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); 19.53 - __ movptr(Address(rcx, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); 19.54 + __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); 19.55 + __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); 19.56 19.57 __ verify_oop(rax); 19.58 19.59 @@ -2582,7 +2584,7 @@ 19.60 rbx); // Make it walkable 19.61 #else /* CC_INTERP */ 19.62 // This value is corrected by layout_activation_impl 19.63 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); 19.64 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 19.65 __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable 19.66 #endif /* CC_INTERP */ 19.67 __ movptr(sp_temp, rsp); // pass to next frame 19.68 @@ -2802,7 +2804,7 @@ 19.69 rbx); // Make it walkable 19.70 #else /* CC_INTERP */ 19.71 // This value is corrected by layout_activation_impl 19.72 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); 19.73 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); 19.74 __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable 19.75 #endif /* CC_INTERP */ 19.76 __ movptr(sp_temp, rsp); // pass to next frame 19.77 @@ -3020,7 +3022,7 @@ 19.78 // exception pending => remove activation and forward to exception handler 19.79 19.80 __ get_thread(thread); 19.81 - __ movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 19.82 + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 19.83 __ movptr(rax, Address(thread, Thread::pending_exception_offset())); 19.84 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); 19.85
20.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sat Jan 31 17:19:42 2009 -0800 20.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Feb 27 15:13:00 2009 -0800 20.3 @@ -39,6 +39,8 @@ 20.4 RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; 20.5 RuntimeStub* SharedRuntime::_resolve_static_call_blob; 20.6 20.7 +const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; 20.8 + 20.9 #define __ masm-> 20.10 20.11 class SimpleRuntimeFrame { 20.12 @@ -1286,7 +1288,7 @@ 20.13 20.14 // Now compute actual number of stack words we need rounding to make 20.15 // stack properly aligned. 20.16 - stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word); 20.17 + stack_slots = round_to(stack_slots, StackAlignmentInSlots); 20.18 20.19 int stack_size = stack_slots * VMRegImpl::stack_slot_size; 20.20 20.21 @@ -2954,10 +2956,16 @@ 20.22 __ pushptr(Address(rcx, 0)); // Save return address 20.23 __ enter(); // Save old & set new rbp 20.24 __ subptr(rsp, rbx); // Prolog 20.25 +#ifdef CC_INTERP 20.26 + __ movptr(Address(rbp, 20.27 + -(sizeof(BytecodeInterpreter)) + in_bytes(byte_offset_of(BytecodeInterpreter, _sender_sp))), 20.28 + sender_sp); // Make it walkable 20.29 +#else // CC_INTERP 20.30 __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), 20.31 sender_sp); // Make it walkable 20.32 // This value is corrected by layout_activation_impl 20.33 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); 20.34 +#endif // CC_INTERP 20.35 __ mov(sender_sp, rsp); // Pass sender_sp to next frame 20.36 __ addptr(rsi, wordSize); // Bump array pointer (sizes) 20.37 __ addptr(rcx, wordSize); // Bump array pointer (pcs)
21.1 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 21.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 21.3 @@ -407,7 +407,7 @@ 21.4 __ get_thread(rcx); 21.5 __ pop(rdx); 21.6 __ movptr(rax, Address(rcx, Thread::pending_exception_offset())); 21.7 - __ movptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); 21.8 + __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD); 21.9 21.10 #ifdef ASSERT 21.11 // make sure exception is set
22.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Sat Jan 31 17:19:42 2009 -0800 22.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Feb 27 15:13:00 2009 -0800 22.3 @@ -472,7 +472,7 @@ 22.4 // setup rax & rdx, remove return address & clear pending exception 22.5 __ pop(rdx); 22.6 __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); 22.7 - __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); 22.8 + __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); 22.9 22.10 #ifdef ASSERT 22.11 // make sure exception is set 22.12 @@ -954,9 +954,9 @@ 22.13 __ jcc(Assembler::zero, exit); // if obj is NULL it is OK 22.14 // Check if the oop is in the right area of memory 22.15 __ movptr(c_rarg2, rax); 22.16 - __ movptr(c_rarg3, (int64_t) Universe::verify_oop_mask()); 22.17 + __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_mask()); 22.18 __ andptr(c_rarg2, c_rarg3); 22.19 - __ movptr(c_rarg3, (int64_t) Universe::verify_oop_bits()); 22.20 + __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_bits()); 22.21 __ cmpptr(c_rarg2, c_rarg3); 22.22 __ jcc(Assembler::notZero, error); 22.23 22.24 @@ -969,9 +969,9 @@ 22.25 __ jcc(Assembler::zero, error); // if klass is NULL it is broken 22.26 // Check if the klass is in the right area of memory 22.27 __ mov(c_rarg2, rax); 22.28 - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); 22.29 + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); 22.30 __ andptr(c_rarg2, c_rarg3); 22.31 - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); 22.32 + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); 22.33 __ cmpptr(c_rarg2, c_rarg3); 22.34 __ jcc(Assembler::notZero, error); 22.35 22.36 @@ -980,9 +980,9 @@ 22.37 __ testptr(rax, rax); 22.38 __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken 22.39 // Check if the klass' klass is in the right area of memory 22.40 - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); 22.41 + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); 22.42 __ andptr(rax, c_rarg3); 22.43 - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); 22.44 + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); 22.45 __ cmpptr(rax, c_rarg3); 22.46 __ jcc(Assembler::notZero, error); 22.47
23.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 23.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 23.3 @@ -110,7 +110,7 @@ 23.4 if (message != NULL) { 23.5 __ lea(rbx, ExternalAddress((address)message)); 23.6 } else { 23.7 - __ movptr(rbx, (int32_t)NULL_WORD); 23.8 + __ movptr(rbx, NULL_WORD); 23.9 } 23.10 __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), rax, rbx); 23.11 } 23.12 @@ -123,7 +123,7 @@ 23.13 address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { 23.14 address entry = __ pc(); 23.15 // NULL last_sp until next java call 23.16 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 23.17 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 23.18 __ dispatch_next(state); 23.19 return entry; 23.20 } 23.21 @@ -176,7 +176,7 @@ 23.22 // Restore stack bottom in case i2c adjusted stack 23.23 __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); 23.24 // and NULL it as marker that rsp is now tos until next java call 23.25 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 23.26 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 23.27 23.28 __ restore_bcp(); 23.29 __ restore_locals(); 23.30 @@ -211,7 +211,7 @@ 23.31 23.32 // The stack is not extended by deopt but we must NULL last_sp as this 23.33 // entry is like a "return". 23.34 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 23.35 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 23.36 __ restore_bcp(); 23.37 __ restore_locals(); 23.38 // handle exceptions 23.39 @@ -382,7 +382,7 @@ 23.40 // indicating if the counter overflow occurs at a backwards branch (non-NULL bcp). 23.41 // The call returns the address of the verified entry point for the method or NULL 23.42 // if the compilation did not complete (either went background or bailed out). 23.43 - __ movptr(rax, (int32_t)false); 23.44 + __ movptr(rax, (intptr_t)false); 23.45 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax); 23.46 23.47 __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop 23.48 @@ -1028,7 +1028,7 @@ 23.49 23.50 // reset handle block 23.51 __ movptr(t, Address(thread, JavaThread::active_handles_offset())); 23.52 - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); 23.53 + __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); 23.54 23.55 // If result was an oop then unbox and save it in the frame 23.56 { Label L; 23.57 @@ -1488,7 +1488,7 @@ 23.58 23.59 // Restore sp to interpreter_frame_last_sp even though we are going 23.60 // to empty the expression stack for the exception processing. 23.61 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 23.62 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 23.63 // rax,: exception 23.64 // rdx: return address/pc that threw exception 23.65 __ restore_bcp(); // rsi points to call/send 23.66 @@ -1608,7 +1608,7 @@ 23.67 __ reset_last_Java_frame(rcx, true, true); 23.68 // Restore the last_sp and null it out 23.69 __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); 23.70 - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); 23.71 + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); 23.72 23.73 __ restore_bcp(); 23.74 __ restore_locals(); 23.75 @@ -1636,7 +1636,7 @@ 23.76 // restore exception 23.77 __ get_thread(rcx); 23.78 __ movptr(rax, Address(rcx, JavaThread::vm_result_offset())); 23.79 - __ movptr(Address(rcx, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); 23.80 + __ movptr(Address(rcx, JavaThread::vm_result_offset()), NULL_WORD); 23.81 __ verify_oop(rax); 23.82 23.83 // Inbetween activations - previous activation type unknown yet
24.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Sat Jan 31 17:19:42 2009 -0800 24.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Feb 27 15:13:00 2009 -0800 24.3 @@ -137,7 +137,7 @@ 24.4 // Do the actual store 24.5 // noreg means NULL 24.6 if (val == noreg) { 24.7 - __ movl(Address(rdx, 0), NULL_WORD); 24.8 + __ movptr(Address(rdx, 0), NULL_WORD); 24.9 // No post barrier for NULL 24.10 } else { 24.11 __ movl(Address(rdx, 0), val); 24.12 @@ -152,7 +152,7 @@ 24.13 case BarrierSet::CardTableExtension: 24.14 { 24.15 if (val == noreg) { 24.16 - __ movl(obj, NULL_WORD); 24.17 + __ movptr(obj, NULL_WORD); 24.18 } else { 24.19 __ movl(obj, val); 24.20 // flatten object address if needed 24.21 @@ -168,7 +168,7 @@ 24.22 case BarrierSet::ModRef: 24.23 case BarrierSet::Other: 24.24 if (val == noreg) { 24.25 - __ movl(obj, NULL_WORD); 24.26 + __ movptr(obj, NULL_WORD); 24.27 } else { 24.28 __ movl(obj, val); 24.29 }
25.1 --- a/src/cpu/x86/vm/x86_32.ad Sat Jan 31 17:19:42 2009 -0800 25.2 +++ b/src/cpu/x86/vm/x86_32.ad Fri Feb 27 15:13:00 2009 -0800 25.3 @@ -3371,7 +3371,7 @@ 25.4 masm.movptr(Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty 25.5 masm.get_thread (scrReg) ; 25.6 masm.movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] 25.7 - masm.movptr(tmpReg, 0); // consider: xor vs mov 25.8 + masm.movptr(tmpReg, NULL_WORD); // consider: xor vs mov 25.9 if (os::is_MP()) { masm.lock(); } 25.10 masm.cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; 25.11 } else 25.12 @@ -3387,7 +3387,7 @@ 25.13 25.14 if ((EmitSync & 64) == 0) { 25.15 // Optimistic form: consider XORL tmpReg,tmpReg 25.16 - masm.movptr(tmpReg, 0 ) ; 25.17 + masm.movptr(tmpReg, NULL_WORD) ; 25.18 } else { 25.19 // Can suffer RTS->RTO upgrades on shared or cold $ lines 25.20 // Test-And-CAS instead of CAS 25.21 @@ -3587,7 +3587,7 @@ 25.22 masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; 25.23 masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; 25.24 masm.jccb (Assembler::notZero, DONE_LABEL) ; 25.25 - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; 25.26 + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; 25.27 masm.jmpb (DONE_LABEL) ; 25.28 } else { 25.29 masm.xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; 25.30 @@ -3596,7 +3596,7 @@ 25.31 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; 25.32 masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; 25.33 masm.jccb (Assembler::notZero, CheckSucc) ; 25.34 - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; 25.35 + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; 25.36 masm.jmpb (DONE_LABEL) ; 25.37 } 25.38 25.39 @@ -3644,7 +3644,7 @@ 25.40 // We currently use (3), although it's likely that switching to (2) 25.41 // is correct for the future. 25.42 25.43 - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; 25.44 + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; 25.45 if (os::is_MP()) { 25.46 if (VM_Version::supports_sse2() && 1 == FenceInstruction) { 25.47 masm.mfence(); 25.48 @@ -6413,9 +6413,9 @@ 25.49 ins_pipe( ialu_reg_mem ); 25.50 %} 25.51 25.52 -// Load Char (16bit unsigned) 25.53 -instruct loadC(eRegI dst, memory mem) %{ 25.54 - match(Set dst (LoadC mem)); 25.55 +// Load Unsigned Short/Char (16bit unsigned) 25.56 +instruct loadUS(eRegI dst, memory mem) %{ 25.57 + match(Set dst (LoadUS mem)); 25.58 25.59 ins_cost(125); 25.60 format %{ "MOVZX $dst,$mem" %}
26.1 --- a/src/cpu/x86/vm/x86_64.ad Sat Jan 31 17:19:42 2009 -0800 26.2 +++ b/src/cpu/x86/vm/x86_64.ad Fri Feb 27 15:13:00 2009 -0800 26.3 @@ -6096,25 +6096,25 @@ 26.4 // ins_pipe(ialu_reg_mem); 26.5 // %} 26.6 26.7 -// Load Char (16 bit UNsigned) 26.8 -instruct loadC(rRegI dst, memory mem) 26.9 -%{ 26.10 - match(Set dst (LoadC mem)); 26.11 +// Load Unsigned Short/Char (16 bit UNsigned) 26.12 +instruct loadUS(rRegI dst, memory mem) 26.13 +%{ 26.14 + match(Set dst (LoadUS mem)); 26.15 26.16 ins_cost(125); 26.17 - format %{ "movzwl $dst, $mem\t# char" %} 26.18 + format %{ "movzwl $dst, $mem\t# ushort/char" %} 26.19 opcode(0x0F, 0xB7); 26.20 ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 26.21 ins_pipe(ialu_reg_mem); 26.22 %} 26.23 26.24 -// Load Char (16 bit UNsigned) into long 26.25 -// instruct loadC2L(rRegL dst, memory mem) 26.26 +// Load Unsigned Short/Char (16 bit UNsigned) into long 26.27 +// instruct loadUS2L(rRegL dst, memory mem) 26.28 // %{ 26.29 -// match(Set dst (ConvI2L (LoadC mem))); 26.30 +// match(Set dst (ConvI2L (LoadUS mem))); 26.31 26.32 // ins_cost(125); 26.33 -// format %{ "movzwl $dst, $mem\t# char -> long" %} 26.34 +// format %{ "movzwl $dst, $mem\t# ushort/char -> long" %} 26.35 // opcode(0x0F, 0xB7); 26.36 // ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 26.37 // ins_pipe(ialu_reg_mem); 26.38 @@ -9490,14 +9490,14 @@ 26.39 %{ 26.40 match(Set dst (AndL dst src)); 26.41 26.42 - format %{ "movzbq $dst, $src\t# long & 0xFF" %} 26.43 + format %{ "movzbq $dst, $dst\t# long & 0xFF" %} 26.44 opcode(0x0F, 0xB6); 26.45 ins_encode(REX_reg_reg_wide(dst, dst), OpcP, OpcS, reg_reg(dst, dst)); 26.46 ins_pipe(ialu_reg); 26.47 %} 26.48 26.49 // And Register with Immediate 65535 26.50 -instruct andL_rReg_imm65535(rRegI dst, immL_65535 src) 26.51 +instruct andL_rReg_imm65535(rRegL dst, immL_65535 src) 26.52 %{ 26.53 match(Set dst (AndL dst src)); 26.54
27.1 --- a/src/os/linux/vm/os_linux.cpp Sat Jan 31 17:19:42 2009 -0800 27.2 +++ b/src/os/linux/vm/os_linux.cpp Fri Feb 27 15:13:00 2009 -0800 27.3 @@ -279,7 +279,11 @@ 27.4 * ... 27.5 * 7: The default directories, normally /lib and /usr/lib. 27.6 */ 27.7 +#if defined(AMD64) || defined(_LP64) && (defined(SPARC) || defined(PPC) || defined(S390)) 27.8 +#define DEFAULT_LIBPATH "/usr/lib64:/lib64:/lib:/usr/lib" 27.9 +#else 27.10 #define DEFAULT_LIBPATH "/lib:/usr/lib" 27.11 +#endif 27.12 27.13 #define EXTENSIONS_DIR "/lib/ext" 27.14 #define ENDORSED_DIR "/lib/endorsed" 27.15 @@ -1160,7 +1164,10 @@ 27.16 27.17 /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */ 27.18 /* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */ 27.19 - i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu", 27.20 + i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld " 27.21 + UINTX_FORMAT UINTX_FORMAT UINTX_FORMAT 27.22 + " %lu " 27.23 + UINTX_FORMAT UINTX_FORMAT UINTX_FORMAT, 27.24 &state, /* 3 %c */ 27.25 &ppid, /* 4 %d */ 27.26 &pgrp, /* 5 %d */ 27.27 @@ -1180,13 +1187,13 @@ 27.28 &nice, /* 19 %ld */ 27.29 &junk, /* 20 %ld */ 27.30 &it_real, /* 21 %ld */ 27.31 - &start, /* 22 %lu */ 27.32 - &vsize, /* 23 %lu */ 27.33 - &rss, /* 24 %ld */ 27.34 + &start, /* 22 UINTX_FORMAT */ 27.35 + &vsize, /* 23 UINTX_FORMAT */ 27.36 + &rss, /* 24 UINTX_FORMAT */ 27.37 &rsslim, /* 25 %lu */ 27.38 - &scodes, /* 26 %lu */ 27.39 - &ecode, /* 27 %lu */ 27.40 - &stack_start); /* 28 %lu */ 27.41 + &scodes, /* 26 UINTX_FORMAT */ 27.42 + &ecode, /* 27 UINTX_FORMAT */ 27.43 + &stack_start); /* 28 UINTX_FORMAT */ 27.44 } 27.45 27.46 if (i != 28 - 2) { 27.47 @@ -1425,6 +1432,10 @@ 27.48 return buf; 27.49 } 27.50 27.51 +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { 27.52 + return localtime_r(clock, res); 27.53 +} 27.54 + 27.55 //////////////////////////////////////////////////////////////////////////////// 27.56 // runtime exit support 27.57 27.58 @@ -2024,7 +2035,8 @@ 27.59 CAST_FROM_FN_PTR(address, os::jvm_path), 27.60 dli_fname, sizeof(dli_fname), NULL); 27.61 assert(ret != 0, "cannot locate libjvm"); 27.62 - realpath(dli_fname, buf); 27.63 + if (realpath(dli_fname, buf) == NULL) 27.64 + return; 27.65 27.66 if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { 27.67 // Support for the gamma launcher. Typical value for buf is 27.68 @@ -2048,7 +2060,8 @@ 27.69 assert(strstr(p, "/libjvm") == p, "invalid library name"); 27.70 p = strstr(p, "_g") ? "_g" : ""; 27.71 27.72 - realpath(java_home_var, buf); 27.73 + if (realpath(java_home_var, buf) == NULL) 27.74 + return; 27.75 sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch); 27.76 if (0 == access(buf, F_OK)) { 27.77 // Use current module name "libjvm[_g].so" instead of 27.78 @@ -2059,7 +2072,8 @@ 27.79 sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p); 27.80 } else { 27.81 // Go back to path of .so 27.82 - realpath(dli_fname, buf); 27.83 + if (realpath(dli_fname, buf) == NULL) 27.84 + return; 27.85 } 27.86 } 27.87 } 27.88 @@ -4184,11 +4198,11 @@ 27.89 // Skip blank chars 27.90 do s++; while (isspace(*s)); 27.91 27.92 - count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu", 27.93 - &idummy, &idummy, &idummy, &idummy, &idummy, &idummy, 27.94 + count = sscanf(s,"%*c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu", 27.95 + &idummy, &idummy, &idummy, &idummy, &idummy, 27.96 &ldummy, &ldummy, &ldummy, &ldummy, &ldummy, 27.97 &user_time, &sys_time); 27.98 - if ( count != 13 ) return -1; 27.99 + if ( count != 12 ) return -1; 27.100 if (user_sys_cpu_time) { 27.101 return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec); 27.102 } else {
28.1 --- a/src/os/solaris/vm/os_solaris.cpp Sat Jan 31 17:19:42 2009 -0800 28.2 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Feb 27 15:13:00 2009 -0800 28.3 @@ -323,6 +323,10 @@ 28.4 return (size_t)(base - bottom); 28.5 } 28.6 28.7 +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { 28.8 + return localtime_r(clock, res); 28.9 +} 28.10 + 28.11 // interruptible infrastructure 28.12 28.13 // setup_interruptible saves the thread state before going into an
29.1 --- a/src/os/windows/vm/os_windows.cpp Sat Jan 31 17:19:42 2009 -0800 29.2 +++ b/src/os/windows/vm/os_windows.cpp Fri Feb 27 15:13:00 2009 -0800 29.3 @@ -327,6 +327,14 @@ 29.4 return sz; 29.5 } 29.6 29.7 +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { 29.8 + const struct tm* time_struct_ptr = localtime(clock); 29.9 + if (time_struct_ptr != NULL) { 29.10 + *res = *time_struct_ptr; 29.11 + return res; 29.12 + } 29.13 + return NULL; 29.14 +} 29.15 29.16 LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo); 29.17
30.1 --- a/src/share/vm/adlc/dict2.cpp Sat Jan 31 17:19:42 2009 -0800 30.2 +++ b/src/share/vm/adlc/dict2.cpp Fri Feb 27 15:13:00 2009 -0800 30.3 @@ -316,9 +316,12 @@ 30.4 return strcmp((const char *)k1,(const char *)k2); 30.5 } 30.6 30.7 -// Slimey cheap key comparator. 30.8 +// Cheap key comparator. 30.9 int cmpkey(const void *key1, const void *key2) { 30.10 - return (int)((intptr_t)key1 - (intptr_t)key2); 30.11 + if (key1 == key2) return 0; 30.12 + intptr_t delta = (intptr_t)key1 - (intptr_t)key2; 30.13 + if (delta > 0) return 1; 30.14 + return -1; 30.15 } 30.16 30.17 //=============================================================================
31.1 --- a/src/share/vm/adlc/forms.cpp Sat Jan 31 17:19:42 2009 -0800 31.2 +++ b/src/share/vm/adlc/forms.cpp Fri Feb 27 15:13:00 2009 -0800 31.3 @@ -248,7 +248,7 @@ 31.4 // True if 'opType', an ideal name, loads or stores. 31.5 Form::DataType Form::is_load_from_memory(const char *opType) const { 31.6 if( strcmp(opType,"LoadB")==0 ) return Form::idealB; 31.7 - if( strcmp(opType,"LoadC")==0 ) return Form::idealC; 31.8 + if( strcmp(opType,"LoadUS")==0 ) return Form::idealC; 31.9 if( strcmp(opType,"LoadD")==0 ) return Form::idealD; 31.10 if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD; 31.11 if( strcmp(opType,"LoadF")==0 ) return Form::idealF;
32.1 --- a/src/share/vm/adlc/formssel.cpp Sat Jan 31 17:19:42 2009 -0800 32.2 +++ b/src/share/vm/adlc/formssel.cpp Fri Feb 27 15:13:00 2009 -0800 32.3 @@ -3314,7 +3314,7 @@ 32.4 "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , 32.5 "StoreB","StoreC","Store" ,"StoreFP", 32.6 "LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , 32.7 - "LoadB" ,"LoadC" ,"LoadS" ,"Load" , 32.8 + "LoadB" ,"LoadUS" ,"LoadS" ,"Load" , 32.9 "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B", 32.10 "Store8B","Store4B","Store8C","Store4C","Store2C", 32.11 "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" ,
33.1 --- a/src/share/vm/asm/codeBuffer.cpp Sat Jan 31 17:19:42 2009 -0800 33.2 +++ b/src/share/vm/asm/codeBuffer.cpp Fri Feb 27 15:13:00 2009 -0800 33.3 @@ -123,6 +123,10 @@ 33.4 // addresses constructed before expansions will not be confused. 33.5 cb->free_blob(); 33.6 } 33.7 + 33.8 + // free any overflow storage 33.9 + delete _overflow_arena; 33.10 + 33.11 #ifdef ASSERT 33.12 Copy::fill_to_bytes(this, sizeof(*this), badResourceValue); 33.13 #endif
34.1 --- a/src/share/vm/classfile/classFileParser.cpp Sat Jan 31 17:19:42 2009 -0800 34.2 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Feb 27 15:13:00 2009 -0800 34.3 @@ -232,7 +232,9 @@ 34.4 length >= 1, "Illegal constant pool size %u in class file %s", 34.5 length, CHECK_(nullHandle)); 34.6 constantPoolOop constant_pool = 34.7 - oopFactory::new_constantPool(length, CHECK_(nullHandle)); 34.8 + oopFactory::new_constantPool(length, 34.9 + methodOopDesc::IsSafeConc, 34.10 + CHECK_(nullHandle)); 34.11 constantPoolHandle cp (THREAD, constant_pool); 34.12 34.13 cp->set_partially_loaded(); // Enables heap verify to work on partial constantPoolOops 34.14 @@ -1675,7 +1677,8 @@ 34.15 // All sizing information for a methodOop is finally available, now create it 34.16 methodOop m_oop = oopFactory::new_method( 34.17 code_length, access_flags, linenumber_table_length, 34.18 - total_lvt_length, checked_exceptions_length, CHECK_(nullHandle)); 34.19 + total_lvt_length, checked_exceptions_length, 34.20 + methodOopDesc::IsSafeConc, CHECK_(nullHandle)); 34.21 methodHandle m (THREAD, m_oop); 34.22 34.23 ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize);
35.1 --- a/src/share/vm/classfile/javaClasses.cpp Sat Jan 31 17:19:42 2009 -0800 35.2 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Feb 27 15:13:00 2009 -0800 35.3 @@ -441,6 +441,7 @@ 35.4 35.5 bool java_lang_Class::offsets_computed = false; 35.6 int java_lang_Class::classRedefinedCount_offset = -1; 35.7 +int java_lang_Class::parallelCapable_offset = -1; 35.8 35.9 void java_lang_Class::compute_offsets() { 35.10 assert(!offsets_computed, "offsets should be initialized only once"); 35.11 @@ -451,6 +452,23 @@ 35.12 // so don't go fatal. 35.13 compute_optional_offset(classRedefinedCount_offset, 35.14 k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); 35.15 + 35.16 + // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, 35.17 + klassOop k1 = SystemDictionary::classloader_klass(); 35.18 + compute_optional_offset(parallelCapable_offset, 35.19 + k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); 35.20 +} 35.21 + 35.22 +// For class loader classes, parallelCapable defined 35.23 +// based on non-null field 35.24 +// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it 35.25 +bool java_lang_Class::parallelCapable(oop class_loader) { 35.26 + if (!JDK_Version::is_gte_jdk17x_version() 35.27 + || parallelCapable_offset == -1) { 35.28 + // Default for backward compatibility is false 35.29 + return false; 35.30 + } 35.31 + return (class_loader->obj_field(parallelCapable_offset) != NULL); 35.32 } 35.33 35.34 int java_lang_Class::classRedefinedCount(oop the_class_mirror) { 35.35 @@ -866,7 +884,7 @@ 35.36 } 35.37 nmethod* nm = method->code(); 35.38 if (WizardMode && nm != NULL) { 35.39 - sprintf(buf + (int)strlen(buf), "(nmethod %#x)", nm); 35.40 + sprintf(buf + (int)strlen(buf), "(nmethod " PTR_FORMAT ")", (intptr_t)nm); 35.41 } 35.42 } 35.43
36.1 --- a/src/share/vm/classfile/javaClasses.hpp Sat Jan 31 17:19:42 2009 -0800 36.2 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Feb 27 15:13:00 2009 -0800 36.3 @@ -141,6 +141,7 @@ 36.4 static void compute_offsets(); 36.5 static bool offsets_computed; 36.6 static int classRedefinedCount_offset; 36.7 + static int parallelCapable_offset; 36.8 36.9 public: 36.10 // Instance creation 36.11 @@ -168,6 +169,8 @@ 36.12 // Support for classRedefinedCount field 36.13 static int classRedefinedCount(oop the_class_mirror); 36.14 static void set_classRedefinedCount(oop the_class_mirror, int value); 36.15 + // Support for parallelCapable field 36.16 + static bool parallelCapable(oop the_class_mirror); 36.17 // Debugging 36.18 friend class JavaClasses; 36.19 friend class instanceKlass; // verification code accesses offsets
37.1 --- a/src/share/vm/classfile/systemDictionary.cpp Sat Jan 31 17:19:42 2009 -0800 37.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Fri Feb 27 15:13:00 2009 -0800 37.3 @@ -90,6 +90,14 @@ 37.4 #endif 37.5 37.6 // ---------------------------------------------------------------------------- 37.7 +// Parallel class loading check 37.8 + 37.9 +bool SystemDictionary::is_parallelCapable(Handle class_loader) { 37.10 + if (UnsyncloadClass || class_loader.is_null()) return true; 37.11 + if (AlwaysLockClassLoader) return false; 37.12 + return java_lang_Class::parallelCapable(class_loader()); 37.13 +} 37.14 +// ---------------------------------------------------------------------------- 37.15 // Resolving of classes 37.16 37.17 // Forwards to resolve_or_null 37.18 @@ -196,7 +204,8 @@ 37.19 // super-class callers: 37.20 // ClassFileParser - for defineClass & jvmtiRedefineClasses 37.21 // load_shared_class - while loading a class from shared archive 37.22 -// resolve_instance_class_or_fail: 37.23 +// resolve_instance_class_or_null: 37.24 +// via: handle_parallel_super_load 37.25 // when resolving a class that has an existing placeholder with 37.26 // a saved superclass [i.e. a defineClass is currently in progress] 37.27 // if another thread is trying to resolve the class, it must do 37.28 @@ -283,12 +292,9 @@ 37.29 if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) { 37.30 throw_circularity_error = true; 37.31 } 37.32 - 37.33 - // add placeholder entry even if error - callers will remove on error 37.34 + } 37.35 + if (!throw_circularity_error) { 37.36 PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, child_name, class_loader, PlaceholderTable::LOAD_SUPER, class_name, THREAD); 37.37 - if (throw_circularity_error) { 37.38 - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER); 37.39 - } 37.40 } 37.41 } 37.42 if (throw_circularity_error) { 37.43 @@ -325,7 +331,6 @@ 37.44 return superk_h(); 37.45 } 37.46 37.47 - 37.48 void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, 37.49 Handle class_loader, 37.50 Handle protection_domain, 37.51 @@ -421,7 +426,7 @@ 37.52 bool calledholdinglock 37.53 = ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject); 37.54 assert(calledholdinglock,"must hold lock for notify"); 37.55 - assert(!UnsyncloadClass, "unexpected double_lock_wait"); 37.56 + assert((!(lockObject() == _system_loader_lock_obj) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait"); 37.57 ObjectSynchronizer::notifyall(lockObject, THREAD); 37.58 intptr_t recursions = ObjectSynchronizer::complete_exit(lockObject, THREAD); 37.59 SystemDictionary_lock->wait(); 37.60 @@ -439,7 +444,7 @@ 37.61 // even in non-circularity situations. 37.62 // Note: only one thread can define the class, but multiple can resolve 37.63 // Note: must call resolve_super_or_fail even if null super - 37.64 -// to force placeholder entry creation for this class 37.65 +// to force placeholder entry creation for this class for circularity detection 37.66 // Caller must check for pending exception 37.67 // Returns non-null klassOop if other thread has completed load 37.68 // and we are done, 37.69 @@ -477,9 +482,9 @@ 37.70 SystemDictionary_lock->notify_all(); 37.71 } 37.72 37.73 - // UnsyncloadClass does NOT wait for parallel superclass loads to complete 37.74 - // Bootstrap classloader does wait for parallel superclass loads 37.75 - if (UnsyncloadClass) { 37.76 + // parallelCapable class loaders do NOT wait for parallel superclass loads to complete 37.77 + // Serial class loaders and bootstrap classloader do wait for superclass loads 37.78 + if (!class_loader.is_null() && is_parallelCapable(class_loader)) { 37.79 MutexLocker mu(SystemDictionary_lock, THREAD); 37.80 // Check if classloading completed while we were loading superclass or waiting 37.81 klassOop check = find_class(d_index, d_hash, name, class_loader); 37.82 @@ -566,10 +571,10 @@ 37.83 // This lock must be acquired here so the waiter will find 37.84 // any successful result in the SystemDictionary and not attempt 37.85 // the define 37.86 - // Classloaders that support parallelism, e.g. bootstrap classloader, 37.87 + // ParallelCapable Classloaders and the bootstrap classloader, 37.88 // or all classloaders with UnsyncloadClass do not acquire lock here 37.89 bool DoObjectLock = true; 37.90 - if (UnsyncloadClass || (class_loader.is_null())) { 37.91 + if (is_parallelCapable(class_loader)) { 37.92 DoObjectLock = false; 37.93 } 37.94 37.95 @@ -627,6 +632,9 @@ 37.96 // Five cases: 37.97 // All cases need to prevent modifying bootclasssearchpath 37.98 // in parallel with a classload of same classname 37.99 + // Redefineclasses uses existence of the placeholder for the duration 37.100 + // of the class load to prevent concurrent redefinition of not completely 37.101 + // defined classes. 37.102 // case 1. traditional classloaders that rely on the classloader object lock 37.103 // - no other need for LOAD_INSTANCE 37.104 // case 2. traditional classloaders that break the classloader object lock 37.105 @@ -642,12 +650,13 @@ 37.106 // This classloader supports parallelism at the classloader level, 37.107 // but only allows a single load of a class/classloader pair. 37.108 // No performance benefit and no deadlock issues. 37.109 - // case 5. Future: parallel user level classloaders - without objectLocker 37.110 + // case 5. parallelCapable user level classloaders - without objectLocker 37.111 + // Allow parallel classloading of a class/classloader pair 37.112 symbolHandle nullsymbolHandle; 37.113 bool throw_circularity_error = false; 37.114 { 37.115 MutexLocker mu(SystemDictionary_lock, THREAD); 37.116 - if (!UnsyncloadClass) { 37.117 + if (class_loader.is_null() || !is_parallelCapable(class_loader)) { 37.118 PlaceholderEntry* oldprobe = placeholders()->get_entry(p_index, p_hash, name, class_loader); 37.119 if (oldprobe) { 37.120 // only need check_seen_thread once, not on each loop 37.121 @@ -681,25 +690,25 @@ 37.122 } 37.123 } 37.124 // All cases: add LOAD_INSTANCE 37.125 - // case 3: UnsyncloadClass: allow competing threads to try 37.126 + // case 3: UnsyncloadClass || case 5: parallelCapable: allow competing threads to try 37.127 // LOAD_INSTANCE in parallel 37.128 // add placeholder entry even if error - callers will remove on error 37.129 - if (!class_has_been_loaded) { 37.130 + if (!throw_circularity_error && !class_has_been_loaded) { 37.131 PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, class_loader, PlaceholderTable::LOAD_INSTANCE, nullsymbolHandle, THREAD); 37.132 - if (throw_circularity_error) { 37.133 - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); 37.134 - } 37.135 // For class loaders that do not acquire the classloader object lock, 37.136 // if they did not catch another thread holding LOAD_INSTANCE, 37.137 // need a check analogous to the acquire ObjectLocker/find_class 37.138 // i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL 37.139 // one final check if the load has already completed 37.140 + // class loaders holding the ObjectLock shouldn't find the class here 37.141 klassOop check = find_class(d_index, d_hash, name, class_loader); 37.142 if (check != NULL) { 37.143 // Klass is already loaded, so just return it 37.144 k = instanceKlassHandle(THREAD, check); 37.145 class_has_been_loaded = true; 37.146 newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); 37.147 + placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD); 37.148 + SystemDictionary_lock->notify_all(); 37.149 } 37.150 } 37.151 } 37.152 @@ -714,18 +723,14 @@ 37.153 // Do actual loading 37.154 k = load_instance_class(name, class_loader, THREAD); 37.155 37.156 - // In custom class loaders, the usual findClass calls 37.157 - // findLoadedClass, which directly searches the SystemDictionary, then 37.158 - // defineClass. If these are not atomic with respect to other threads, 37.159 - // the findLoadedClass can fail, but the defineClass can get a 37.160 - // LinkageError:: duplicate class definition. 37.161 + // For UnsyncloadClass and AllowParallelDefineClass only: 37.162 // If they got a linkageError, check if a parallel class load succeeded. 37.163 // If it did, then for bytecode resolution the specification requires 37.164 // that we return the same result we did for the other thread, i.e. the 37.165 // successfully loaded instanceKlass 37.166 - // Note: Class can not be unloaded as long as any classloader refs exist 37.167 // Should not get here for classloaders that support parallelism 37.168 - // with the new cleaner mechanism, e.g. bootstrap classloader 37.169 + // with the new cleaner mechanism 37.170 + // Bootstrap goes through here to allow for an extra guarantee check 37.171 if (UnsyncloadClass || (class_loader.is_null())) { 37.172 if (k.is_null() && HAS_PENDING_EXCEPTION 37.173 && PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { 37.174 @@ -841,6 +846,12 @@ 37.175 Handle protection_domain, 37.176 TRAPS) { 37.177 37.178 + // UseNewReflection 37.179 + // The result of this call should be consistent with the result 37.180 + // of the call to resolve_instance_class_or_null(). 37.181 + // See evaluation 6790209 and 4474172 for more details. 37.182 + class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); 37.183 + 37.184 unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader); 37.185 int d_index = dictionary()->hash_to_index(d_hash); 37.186 37.187 @@ -955,10 +966,10 @@ 37.188 instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, 37.189 class_loader, 37.190 protection_domain, 37.191 - cp_patches, 37.192 parsed_name, 37.193 THREAD); 37.194 37.195 + 37.196 // We don't redefine the class, so we just need to clean up whether there 37.197 // was an error or not (don't want to modify any system dictionary 37.198 // data structures). 37.199 @@ -1013,11 +1024,17 @@ 37.200 ClassFileStream* st, 37.201 TRAPS) { 37.202 37.203 - // Make sure we are synchronized on the class loader before we initiate 37.204 - // loading. 37.205 + // Classloaders that support parallelism, e.g. bootstrap classloader, 37.206 + // or all classloaders with UnsyncloadClass do not acquire lock here 37.207 + bool DoObjectLock = true; 37.208 + if (is_parallelCapable(class_loader)) { 37.209 + DoObjectLock = false; 37.210 + } 37.211 + 37.212 + // Make sure we are synchronized on the class loader before we proceed 37.213 Handle lockObject = compute_loader_lock_object(class_loader, THREAD); 37.214 check_loader_lock_contention(lockObject, THREAD); 37.215 - ObjectLocker ol(lockObject, THREAD); 37.216 + ObjectLocker ol(lockObject, THREAD, DoObjectLock); 37.217 37.218 symbolHandle parsed_name; 37.219 37.220 @@ -1069,7 +1086,13 @@ 37.221 "external class name format used internally"); 37.222 37.223 // Add class just loaded 37.224 - define_instance_class(k, THREAD); 37.225 + // If a class loader supports parallel classloading handle parallel define requests 37.226 + // find_or_define_instance_class may return a different instanceKlass 37.227 + if (is_parallelCapable(class_loader)) { 37.228 + k = find_or_define_instance_class(class_name, class_loader, k, THREAD); 37.229 + } else { 37.230 + define_instance_class(k, THREAD); 37.231 + } 37.232 } 37.233 37.234 // If parsing the class file or define_instance_class failed, we 37.235 @@ -1299,7 +1322,7 @@ 37.236 } 37.237 #endif // KERNEL 37.238 37.239 - // find_or_define_instance_class may return a different k 37.240 + // find_or_define_instance_class may return a different instanceKlass 37.241 if (!k.is_null()) { 37.242 k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); 37.243 } 37.244 @@ -1316,14 +1339,24 @@ 37.245 37.246 KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass()); 37.247 37.248 - // UnsyncloadClass option means don't synchronize loadClass() calls. 37.249 - // loadClassInternal() is synchronized and public loadClass(String) is not. 37.250 - // This flag is for diagnostic purposes only. It is risky to call 37.251 + // Call public unsynchronized loadClass(String) directly for all class loaders 37.252 + // for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will 37.253 + // acquire a class-name based lock rather than the class loader object lock. 37.254 + // JDK < 7 already acquire the class loader lock in loadClass(String, boolean), 37.255 + // so the call to loadClassInternal() was not required. 37.256 + // 37.257 + // UnsyncloadClass flag means both call loadClass(String) and do 37.258 + // not acquire the class loader lock even for class loaders that are 37.259 + // not parallelCapable. This was a risky transitional 37.260 + // flag for diagnostic purposes only. It is risky to call 37.261 // custom class loaders without synchronization. 37.262 // WARNING If a custom class loader does NOT synchronizer findClass, or callers of 37.263 - // findClass, this flag risks unexpected timing bugs in the field. 37.264 + // findClass, the UnsyncloadClass flag risks unexpected timing bugs in the field. 37.265 // Do NOT assume this will be supported in future releases. 37.266 - if (!UnsyncloadClass && has_loadClassInternal()) { 37.267 + // 37.268 + // Added MustCallLoadClassInternal in case we discover in the field 37.269 + // a customer that counts on this call 37.270 + if (MustCallLoadClassInternal && has_loadClassInternal()) { 37.271 JavaCalls::call_special(&result, 37.272 class_loader, 37.273 spec_klass, 37.274 @@ -1365,14 +1398,17 @@ 37.275 37.276 Handle class_loader_h(THREAD, k->class_loader()); 37.277 37.278 - // for bootstrap classloader don't acquire lock 37.279 - if (!class_loader_h.is_null()) { 37.280 + // for bootstrap and other parallel classloaders don't acquire lock, 37.281 + // use placeholder token 37.282 + // If a parallelCapable class loader calls define_instance_class instead of 37.283 + // find_or_define_instance_class to get here, we have a timing 37.284 + // hole with systemDictionary updates and check_constraints 37.285 + if (!class_loader_h.is_null() && !is_parallelCapable(class_loader_h)) { 37.286 assert(ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, 37.287 compute_loader_lock_object(class_loader_h, THREAD)), 37.288 "define called without lock"); 37.289 } 37.290 37.291 - 37.292 // Check class-loading constraints. Throw exception if violation is detected. 37.293 // Grabs and releases SystemDictionary_lock 37.294 // The check_constraints/find_class call and update_dictionary sequence 37.295 @@ -1427,59 +1463,63 @@ 37.296 37.297 // Support parallel classloading 37.298 // Initial implementation for bootstrap classloader 37.299 -// For future: 37.300 // For custom class loaders that support parallel classloading, 37.301 -// in case they do not synchronize around 37.302 -// FindLoadedClass/DefineClass calls, we check for parallel 37.303 +// With AllowParallelDefine flag==true, in case they do not synchronize around 37.304 +// FindLoadedClass/DefineClass, calls, we check for parallel 37.305 // loading for them, wait if a defineClass is in progress 37.306 // and return the initial requestor's results 37.307 +// With AllowParallelDefine flag==false, call through to define_instance_class 37.308 +// which will throw LinkageError: duplicate class definition. 37.309 // For better performance, the class loaders should synchronize 37.310 -// findClass(), i.e. FindLoadedClass/DefineClass or they 37.311 +// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they 37.312 // potentially waste time reading and parsing the bytestream. 37.313 // Note: VM callers should ensure consistency of k/class_name,class_loader 37.314 instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle class_name, Handle class_loader, instanceKlassHandle k, TRAPS) { 37.315 37.316 instanceKlassHandle nh = instanceKlassHandle(); // null Handle 37.317 + symbolHandle name_h(THREAD, k->name()); // passed in class_name may be null 37.318 37.319 - unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader); 37.320 + unsigned int d_hash = dictionary()->compute_hash(name_h, class_loader); 37.321 int d_index = dictionary()->hash_to_index(d_hash); 37.322 37.323 // Hold SD lock around find_class and placeholder creation for DEFINE_CLASS 37.324 - unsigned int p_hash = placeholders()->compute_hash(class_name, class_loader); 37.325 + unsigned int p_hash = placeholders()->compute_hash(name_h, class_loader); 37.326 int p_index = placeholders()->hash_to_index(p_hash); 37.327 PlaceholderEntry* probe; 37.328 37.329 { 37.330 MutexLocker mu(SystemDictionary_lock, THREAD); 37.331 // First check if class already defined 37.332 - klassOop check = find_class(d_index, d_hash, class_name, class_loader); 37.333 + klassOop check = find_class(d_index, d_hash, name_h, class_loader); 37.334 if (check != NULL) { 37.335 return(instanceKlassHandle(THREAD, check)); 37.336 } 37.337 37.338 // Acquire define token for this class/classloader 37.339 symbolHandle nullsymbolHandle; 37.340 - probe = placeholders()->find_and_add(p_index, p_hash, class_name, class_loader, PlaceholderTable::DEFINE_CLASS, nullsymbolHandle, THREAD); 37.341 - // Check if another thread defining in parallel 37.342 - if (probe->definer() == NULL) { 37.343 - // Thread will define the class 37.344 + probe = placeholders()->find_and_add(p_index, p_hash, name_h, class_loader, PlaceholderTable::DEFINE_CLASS, nullsymbolHandle, THREAD); 37.345 + // Wait if another thread defining in parallel 37.346 + // All threads wait - even those that will throw duplicate class: otherwise 37.347 + // caller is surprised by LinkageError: duplicate, but findLoadedClass fails 37.348 + // if other thread has not finished updating dictionary 37.349 + while (probe->definer() != NULL) { 37.350 + SystemDictionary_lock->wait(); 37.351 + } 37.352 + // Only special cases allow parallel defines and can use other thread's results 37.353 + // Other cases fall through, and may run into duplicate defines 37.354 + // caught by finding an entry in the SystemDictionary 37.355 + if ((UnsyncloadClass || AllowParallelDefineClass) && (probe->instanceKlass() != NULL)) { 37.356 + probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); 37.357 + placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD); 37.358 + SystemDictionary_lock->notify_all(); 37.359 +#ifdef ASSERT 37.360 + klassOop check = find_class(d_index, d_hash, name_h, class_loader); 37.361 + assert(check != NULL, "definer missed recording success"); 37.362 +#endif 37.363 + return(instanceKlassHandle(THREAD, probe->instanceKlass())); 37.364 + } else { 37.365 + // This thread will define the class (even if earlier thread tried and had an error) 37.366 probe->set_definer(THREAD); 37.367 - } else { 37.368 - // Wait for defining thread to finish and return results 37.369 - while (probe->definer() != NULL) { 37.370 - SystemDictionary_lock->wait(); 37.371 - } 37.372 - if (probe->instanceKlass() != NULL) { 37.373 - probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); 37.374 - return(instanceKlassHandle(THREAD, probe->instanceKlass())); 37.375 - } else { 37.376 - // If definer had an error, try again as any new thread would 37.377 - probe->set_definer(THREAD); 37.378 -#ifdef ASSERT 37.379 - klassOop check = find_class(d_index, d_hash, class_name, class_loader); 37.380 - assert(check == NULL, "definer missed recording success"); 37.381 -#endif 37.382 - } 37.383 } 37.384 } 37.385 37.386 @@ -1490,7 +1530,7 @@ 37.387 // definer must notify any waiting threads 37.388 { 37.389 MutexLocker mu(SystemDictionary_lock, THREAD); 37.390 - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, class_name, class_loader); 37.391 + PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, name_h, class_loader); 37.392 assert(probe != NULL, "DEFINE_CLASS placeholder lost?"); 37.393 if (probe != NULL) { 37.394 if (HAS_PENDING_EXCEPTION) { 37.395 @@ -1501,6 +1541,7 @@ 37.396 } 37.397 probe->set_definer(NULL); 37.398 probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); 37.399 + placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD); 37.400 SystemDictionary_lock->notify_all(); 37.401 } 37.402 } 37.403 @@ -1512,7 +1553,6 @@ 37.404 37.405 return k; 37.406 } 37.407 - 37.408 Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) { 37.409 // If class_loader is NULL we synchronize on _system_loader_lock_obj 37.410 if (class_loader.is_null()) { 37.411 @@ -1902,11 +1942,11 @@ 37.412 warning("Cannot find sun/jkernel/DownloadManager"); 37.413 } 37.414 #endif // KERNEL 37.415 + 37.416 { // Compute whether we should use loadClass or loadClassInternal when loading classes. 37.417 methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); 37.418 _has_loadClassInternal = (method != NULL); 37.419 } 37.420 - 37.421 { // Compute whether we should use checkPackageAccess or NOT 37.422 methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); 37.423 _has_checkPackageAccess = (method != NULL);
38.1 --- a/src/share/vm/classfile/systemDictionary.hpp Sat Jan 31 17:19:42 2009 -0800 38.2 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Feb 27 15:13:00 2009 -0800 38.3 @@ -526,6 +526,7 @@ 38.4 static instanceKlassHandle load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS); 38.5 static Handle compute_loader_lock_object(Handle class_loader, TRAPS); 38.6 static void check_loader_lock_contention(Handle loader_lock, TRAPS); 38.7 + static bool is_parallelCapable(Handle class_loader); 38.8 38.9 static klassOop find_shared_class(symbolHandle class_name); 38.10
39.1 --- a/src/share/vm/classfile/vmSymbols.hpp Sat Jan 31 17:19:42 2009 -0800 39.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Feb 27 15:13:00 2009 -0800 39.3 @@ -362,6 +362,7 @@ 39.4 template(class_signature, "Ljava/lang/Class;") \ 39.5 template(string_signature, "Ljava/lang/String;") \ 39.6 template(reference_signature, "Ljava/lang/ref/Reference;") \ 39.7 + template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \ 39.8 /* signature symbols needed by intrinsics */ \ 39.9 VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ 39.10 \ 39.11 @@ -374,6 +375,9 @@ 39.12 /* used by ClassFormatError when class name is not known yet */ \ 39.13 template(unknown_class_name, "<Unknown>") \ 39.14 \ 39.15 + /* used to identify class loaders handling parallel class loading */ \ 39.16 + template(parallelCapable_name, "parallelLockMap;") \ 39.17 + \ 39.18 /* JVM monitoring and management support */ \ 39.19 template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \ 39.20 template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
40.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Sat Jan 31 17:19:42 2009 -0800 40.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Feb 27 15:13:00 2009 -0800 40.3 @@ -706,6 +706,30 @@ 40.4 } 40.5 } 40.6 40.7 +// Apply the given closure to each live object in the space 40.8 +// The usage of CompactibleFreeListSpace 40.9 +// by the ConcurrentMarkSweepGeneration for concurrent GC's allows 40.10 +// objects in the space with references to objects that are no longer 40.11 +// valid. For example, an object may reference another object 40.12 +// that has already been sweep up (collected). This method uses 40.13 +// obj_is_alive() to determine whether it is safe to apply the closure to 40.14 +// an object. See obj_is_alive() for details on how liveness of an 40.15 +// object is decided. 40.16 + 40.17 +void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { 40.18 + assert_lock_strong(freelistLock()); 40.19 + NOT_PRODUCT(verify_objects_initialized()); 40.20 + HeapWord *cur, *limit; 40.21 + size_t curSize; 40.22 + for (cur = bottom(), limit = end(); cur < limit; 40.23 + cur += curSize) { 40.24 + curSize = block_size(cur); 40.25 + if (block_is_obj(cur) && obj_is_alive(cur)) { 40.26 + blk->do_object(oop(cur)); 40.27 + } 40.28 + } 40.29 +} 40.30 + 40.31 void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, 40.32 UpwardsObjectClosure* cl) { 40.33 assert_locked(); 40.34 @@ -861,7 +885,9 @@ 40.35 } else { 40.36 // must read from what 'p' points to in each loop. 40.37 klassOop k = ((volatile oopDesc*)p)->klass_or_null(); 40.38 - if (k != NULL && ((oopDesc*)p)->is_parsable()) { 40.39 + if (k != NULL && 40.40 + ((oopDesc*)p)->is_parsable() && 40.41 + ((oopDesc*)p)->is_conc_safe()) { 40.42 assert(k->is_oop(), "Should really be klass oop."); 40.43 oop o = (oop)p; 40.44 assert(o->is_oop(), "Should be an oop");
41.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Sat Jan 31 17:19:42 2009 -0800 41.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Fri Feb 27 15:13:00 2009 -0800 41.3 @@ -481,6 +481,15 @@ 41.4 void oop_iterate(OopClosure* cl); 41.5 41.6 void object_iterate(ObjectClosure* blk); 41.7 + // Apply the closure to each object in the space whose references 41.8 + // point to objects in the heap. The usage of CompactibleFreeListSpace 41.9 + // by the ConcurrentMarkSweepGeneration for concurrent GC's allows 41.10 + // objects in the space with references to objects that are no longer 41.11 + // valid. For example, an object may reference another object 41.12 + // that has already been sweep up (collected). This method uses 41.13 + // obj_is_alive() to determine whether it is safe to iterate of 41.14 + // an object. 41.15 + void safe_object_iterate(ObjectClosure* blk); 41.16 void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); 41.17 41.18 // Requires that "mr" be entirely within the space.
42.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sat Jan 31 17:19:42 2009 -0800 42.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Feb 27 15:13:00 2009 -0800 42.3 @@ -3018,6 +3018,16 @@ 42.4 } 42.5 42.6 void 42.7 +ConcurrentMarkSweepGeneration::safe_object_iterate(ObjectClosure* cl) { 42.8 + if (freelistLock()->owned_by_self()) { 42.9 + Generation::safe_object_iterate(cl); 42.10 + } else { 42.11 + MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); 42.12 + Generation::safe_object_iterate(cl); 42.13 + } 42.14 +} 42.15 + 42.16 +void 42.17 ConcurrentMarkSweepGeneration::pre_adjust_pointers() { 42.18 } 42.19 42.20 @@ -6623,7 +6633,11 @@ 42.21 if (_bitMap->isMarked(addr)) { 42.22 // it's marked; is it potentially uninitialized? 42.23 if (p->klass_or_null() != NULL) { 42.24 - if (CMSPermGenPrecleaningEnabled && !p->is_parsable()) { 42.25 + // If is_conc_safe is false, the object may be undergoing 42.26 + // change by the VM outside a safepoint. Don't try to 42.27 + // scan it, but rather leave it for the remark phase. 42.28 + if (CMSPermGenPrecleaningEnabled && 42.29 + (!p->is_conc_safe() || !p->is_parsable())) { 42.30 // Signal precleaning to redirty the card since 42.31 // the klass pointer is already installed. 42.32 assert(size == 0, "Initial value"); 42.33 @@ -7001,7 +7015,6 @@ 42.34 _mut->clear_range(mr); 42.35 } 42.36 DEBUG_ONLY(}) 42.37 - 42.38 // Note: the finger doesn't advance while we drain 42.39 // the stack below. 42.40 PushOrMarkClosure pushOrMarkClosure(_collector, 42.41 @@ -8062,9 +8075,13 @@ 42.42 #ifdef DEBUG 42.43 if (oop(addr)->klass_or_null() != NULL && 42.44 ( !_collector->should_unload_classes() 42.45 - || oop(addr)->is_parsable())) { 42.46 + || (oop(addr)->is_parsable()) && 42.47 + oop(addr)->is_conc_safe())) { 42.48 // Ignore mark word because we are running concurrent with mutators 42.49 assert(oop(addr)->is_oop(true), "live block should be an oop"); 42.50 + // is_conc_safe is checked before performing this assertion 42.51 + // because an object that is not is_conc_safe may yet have 42.52 + // the return from size() correct. 42.53 assert(size == 42.54 CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()), 42.55 "P-mark and computed size do not agree"); 42.56 @@ -8077,6 +8094,13 @@ 42.57 (!_collector->should_unload_classes() 42.58 || oop(addr)->is_parsable()), 42.59 "Should be an initialized object"); 42.60 + // Note that there are objects used during class redefinition 42.61 + // (e.g., merge_cp in VM_RedefineClasses::merge_cp_and_rewrite() 42.62 + // which are discarded with their is_conc_safe state still 42.63 + // false. These object may be floating garbage so may be 42.64 + // seen here. If they are floating garbage their size 42.65 + // should be attainable from their klass. Do not that 42.66 + // is_conc_safe() is true for oop(addr). 42.67 // Ignore mark word because we are running concurrent with mutators 42.68 assert(oop(addr)->is_oop(true), "live block should be an oop"); 42.69 // Verify that the bit map has no bits marked between 42.70 @@ -8484,7 +8508,7 @@ 42.71 size_t i = num; 42.72 oop cur = _overflow_list; 42.73 const markOop proto = markOopDesc::prototype(); 42.74 - NOT_PRODUCT(size_t n = 0;) 42.75 + NOT_PRODUCT(ssize_t n = 0;) 42.76 for (oop next; i > 0 && cur != NULL; cur = next, i--) { 42.77 next = oop(cur->mark()); 42.78 cur->set_mark(proto); // until proven otherwise 42.79 @@ -8501,45 +8525,131 @@ 42.80 return !stack->isEmpty(); 42.81 } 42.82 42.83 -// Multi-threaded; use CAS to break off a prefix 42.84 +#define BUSY (oop(0x1aff1aff)) 42.85 +// (MT-safe) Get a prefix of at most "num" from the list. 42.86 +// The overflow list is chained through the mark word of 42.87 +// each object in the list. We fetch the entire list, 42.88 +// break off a prefix of the right size and return the 42.89 +// remainder. If other threads try to take objects from 42.90 +// the overflow list at that time, they will wait for 42.91 +// some time to see if data becomes available. If (and 42.92 +// only if) another thread places one or more object(s) 42.93 +// on the global list before we have returned the suffix 42.94 +// to the global list, we will walk down our local list 42.95 +// to find its end and append the global list to 42.96 +// our suffix before returning it. This suffix walk can 42.97 +// prove to be expensive (quadratic in the amount of traffic) 42.98 +// when there are many objects in the overflow list and 42.99 +// there is much producer-consumer contention on the list. 42.100 +// *NOTE*: The overflow list manipulation code here and 42.101 +// in ParNewGeneration:: are very similar in shape, 42.102 +// except that in the ParNew case we use the old (from/eden) 42.103 +// copy of the object to thread the list via its klass word. 42.104 +// Because of the common code, if you make any changes in 42.105 +// the code below, please check the ParNew version to see if 42.106 +// similar changes might be needed. 42.107 +// CR 6797058 has been filed to consolidate the common code. 42.108 bool CMSCollector::par_take_from_overflow_list(size_t num, 42.109 OopTaskQueue* work_q) { 42.110 - assert(work_q->size() == 0, "That's the current policy"); 42.111 + assert(work_q->size() == 0, "First empty local work queue"); 42.112 assert(num < work_q->max_elems(), "Can't bite more than we can chew"); 42.113 if (_overflow_list == NULL) { 42.114 return false; 42.115 } 42.116 // Grab the entire list; we'll put back a suffix 42.117 - oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list); 42.118 - if (prefix == NULL) { // someone grabbed it before we did ... 42.119 - // ... we could spin for a short while, but for now we don't 42.120 - return false; 42.121 - } 42.122 + oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); 42.123 + Thread* tid = Thread::current(); 42.124 + size_t CMSOverflowSpinCount = (size_t)ParallelGCThreads; 42.125 + size_t sleep_time_millis = MAX2((size_t)1, num/100); 42.126 + // If the list is busy, we spin for a short while, 42.127 + // sleeping between attempts to get the list. 42.128 + for (size_t spin = 0; prefix == BUSY && spin < CMSOverflowSpinCount; spin++) { 42.129 + os::sleep(tid, sleep_time_millis, false); 42.130 + if (_overflow_list == NULL) { 42.131 + // Nothing left to take 42.132 + return false; 42.133 + } else if (_overflow_list != BUSY) { 42.134 + // Try and grab the prefix 42.135 + prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); 42.136 + } 42.137 + } 42.138 + // If the list was found to be empty, or we spun long 42.139 + // enough, we give up and return empty-handed. If we leave 42.140 + // the list in the BUSY state below, it must be the case that 42.141 + // some other thread holds the overflow list and will set it 42.142 + // to a non-BUSY state in the future. 42.143 + if (prefix == NULL || prefix == BUSY) { 42.144 + // Nothing to take or waited long enough 42.145 + if (prefix == NULL) { 42.146 + // Write back the NULL in case we overwrote it with BUSY above 42.147 + // and it is still the same value. 42.148 + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); 42.149 + } 42.150 + return false; 42.151 + } 42.152 + assert(prefix != NULL && prefix != BUSY, "Error"); 42.153 size_t i = num; 42.154 oop cur = prefix; 42.155 + // Walk down the first "num" objects, unless we reach the end. 42.156 for (; i > 1 && cur->mark() != NULL; cur = oop(cur->mark()), i--); 42.157 - if (cur->mark() != NULL) { 42.158 + if (cur->mark() == NULL) { 42.159 + // We have "num" or fewer elements in the list, so there 42.160 + // is nothing to return to the global list. 42.161 + // Write back the NULL in lieu of the BUSY we wrote 42.162 + // above, if it is still the same value. 42.163 + if (_overflow_list == BUSY) { 42.164 + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); 42.165 + } 42.166 + } else { 42.167 + // Chop off the suffix and rerturn it to the global list. 42.168 + assert(cur->mark() != BUSY, "Error"); 42.169 oop suffix_head = cur->mark(); // suffix will be put back on global list 42.170 cur->set_mark(NULL); // break off suffix 42.171 - // Find tail of suffix so we can prepend suffix to global list 42.172 - for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark())); 42.173 - oop suffix_tail = cur; 42.174 - assert(suffix_tail != NULL && suffix_tail->mark() == NULL, 42.175 - "Tautology"); 42.176 + // It's possible that the list is still in the empty(busy) state 42.177 + // we left it in a short while ago; in that case we may be 42.178 + // able to place back the suffix without incurring the cost 42.179 + // of a walk down the list. 42.180 oop observed_overflow_list = _overflow_list; 42.181 - do { 42.182 - cur = observed_overflow_list; 42.183 - suffix_tail->set_mark(markOop(cur)); 42.184 + oop cur_overflow_list = observed_overflow_list; 42.185 + bool attached = false; 42.186 + while (observed_overflow_list == BUSY || observed_overflow_list == NULL) { 42.187 observed_overflow_list = 42.188 - (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur); 42.189 - } while (cur != observed_overflow_list); 42.190 + (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list); 42.191 + if (cur_overflow_list == observed_overflow_list) { 42.192 + attached = true; 42.193 + break; 42.194 + } else cur_overflow_list = observed_overflow_list; 42.195 + } 42.196 + if (!attached) { 42.197 + // Too bad, someone else sneaked in (at least) an element; we'll need 42.198 + // to do a splice. Find tail of suffix so we can prepend suffix to global 42.199 + // list. 42.200 + for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark())); 42.201 + oop suffix_tail = cur; 42.202 + assert(suffix_tail != NULL && suffix_tail->mark() == NULL, 42.203 + "Tautology"); 42.204 + observed_overflow_list = _overflow_list; 42.205 + do { 42.206 + cur_overflow_list = observed_overflow_list; 42.207 + if (cur_overflow_list != BUSY) { 42.208 + // Do the splice ... 42.209 + suffix_tail->set_mark(markOop(cur_overflow_list)); 42.210 + } else { // cur_overflow_list == BUSY 42.211 + suffix_tail->set_mark(NULL); 42.212 + } 42.213 + // ... and try to place spliced list back on overflow_list ... 42.214 + observed_overflow_list = 42.215 + (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list); 42.216 + } while (cur_overflow_list != observed_overflow_list); 42.217 + // ... until we have succeeded in doing so. 42.218 + } 42.219 } 42.220 42.221 // Push the prefix elements on work_q 42.222 assert(prefix != NULL, "control point invariant"); 42.223 const markOop proto = markOopDesc::prototype(); 42.224 oop next; 42.225 - NOT_PRODUCT(size_t n = 0;) 42.226 + NOT_PRODUCT(ssize_t n = 0;) 42.227 for (cur = prefix; cur != NULL; cur = next) { 42.228 next = oop(cur->mark()); 42.229 cur->set_mark(proto); // until proven otherwise 42.230 @@ -8573,11 +8683,16 @@ 42.231 oop cur_overflow_list; 42.232 do { 42.233 cur_overflow_list = observed_overflow_list; 42.234 - p->set_mark(markOop(cur_overflow_list)); 42.235 + if (cur_overflow_list != BUSY) { 42.236 + p->set_mark(markOop(cur_overflow_list)); 42.237 + } else { 42.238 + p->set_mark(NULL); 42.239 + } 42.240 observed_overflow_list = 42.241 (oop) Atomic::cmpxchg_ptr(p, &_overflow_list, cur_overflow_list); 42.242 } while (cur_overflow_list != observed_overflow_list); 42.243 } 42.244 +#undef BUSY 42.245 42.246 // Single threaded 42.247 // General Note on GrowableArray: pushes may silently fail 42.248 @@ -8586,7 +8701,7 @@ 42.249 // a lot of code in the JVM. The prudent thing for GrowableArray 42.250 // to do (for now) is to exit with an error. However, that may 42.251 // be too draconian in some cases because the caller may be 42.252 -// able to recover without much harm. For suych cases, we 42.253 +// able to recover without much harm. For such cases, we 42.254 // should probably introduce a "soft_push" method which returns 42.255 // an indication of success or failure with the assumption that 42.256 // the caller may be able to recover from a failure; code in 42.257 @@ -8594,8 +8709,6 @@ 42.258 // failures where possible, thus, incrementally hardening the VM 42.259 // in such low resource situations. 42.260 void CMSCollector::preserve_mark_work(oop p, markOop m) { 42.261 - int PreserveMarkStackSize = 128; 42.262 - 42.263 if (_preserved_oop_stack == NULL) { 42.264 assert(_preserved_mark_stack == NULL, 42.265 "bijection with preserved_oop_stack");
43.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Sat Jan 31 17:19:42 2009 -0800 43.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Feb 27 15:13:00 2009 -0800 43.3 @@ -595,7 +595,7 @@ 43.4 size_t _ser_kac_preclean_ovflw; 43.5 size_t _ser_kac_ovflw; 43.6 size_t _par_kac_ovflw; 43.7 - NOT_PRODUCT(size_t _num_par_pushes;) 43.8 + NOT_PRODUCT(ssize_t _num_par_pushes;) 43.9 43.10 // ("Weak") Reference processing support 43.11 ReferenceProcessor* _ref_processor; 43.12 @@ -1212,6 +1212,7 @@ 43.13 // More iteration support 43.14 virtual void oop_iterate(MemRegion mr, OopClosure* cl); 43.15 virtual void oop_iterate(OopClosure* cl); 43.16 + virtual void safe_object_iterate(ObjectClosure* cl); 43.17 virtual void object_iterate(ObjectClosure* cl); 43.18 43.19 // Need to declare the full complement of closures, whether we'll
44.1 --- a/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Sat Jan 31 17:19:42 2009 -0800 44.2 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Fri Feb 27 15:13:00 2009 -0800 44.3 @@ -24,7 +24,7 @@ 44.4 44.5 // We need to sort heap regions by collection desirability. 44.6 44.7 -class CSetChooserCache { 44.8 +class CSetChooserCache VALUE_OBJ_CLASS_SPEC { 44.9 private: 44.10 enum { 44.11 CacheLength = 16
45.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Sat Jan 31 17:19:42 2009 -0800 45.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Fri Feb 27 15:13:00 2009 -0800 45.3 @@ -33,7 +33,7 @@ 45.4 PYA_cancel // It's been completed by somebody else: cancel. 45.5 }; 45.6 45.7 -class ConcurrentG1Refine { 45.8 +class ConcurrentG1Refine: public CHeapObj { 45.9 ConcurrentG1RefineThread* _cg1rThread; 45.10 45.11 volatile jint _pya;
46.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Sat Jan 31 17:19:42 2009 -0800 46.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Feb 27 15:13:00 2009 -0800 46.3 @@ -30,7 +30,7 @@ 46.4 // A generic CM bit map. This is essentially a wrapper around the BitMap 46.5 // class, with one bit per (1<<_shifter) HeapWords. 46.6 46.7 -class CMBitMapRO { 46.8 +class CMBitMapRO VALUE_OBJ_CLASS_SPEC { 46.9 protected: 46.10 HeapWord* _bmStartWord; // base address of range covered by map 46.11 size_t _bmWordSize; // map size (in #HeapWords covered) 46.12 @@ -139,7 +139,7 @@ 46.13 46.14 // Represents a marking stack used by the CM collector. 46.15 // Ideally this should be GrowableArray<> just like MSC's marking stack(s). 46.16 -class CMMarkStack { 46.17 +class CMMarkStack VALUE_OBJ_CLASS_SPEC { 46.18 ConcurrentMark* _cm; 46.19 oop* _base; // bottom of stack 46.20 jint _index; // one more than last occupied index 46.21 @@ -237,7 +237,7 @@ 46.22 void oops_do(OopClosure* f); 46.23 }; 46.24 46.25 -class CMRegionStack { 46.26 +class CMRegionStack VALUE_OBJ_CLASS_SPEC { 46.27 MemRegion* _base; 46.28 jint _capacity; 46.29 jint _index; 46.30 @@ -312,7 +312,7 @@ 46.31 46.32 class ConcurrentMarkThread; 46.33 46.34 -class ConcurrentMark { 46.35 +class ConcurrentMark: public CHeapObj { 46.36 friend class ConcurrentMarkThread; 46.37 friend class CMTask; 46.38 friend class CMBitMapClosure;
47.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sat Jan 31 17:19:42 2009 -0800 47.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Feb 27 15:13:00 2009 -0800 47.3 @@ -141,7 +141,7 @@ 47.4 _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL), 47.5 _length(0), _scan_only_length(0), 47.6 _last_sampled_rs_lengths(0), 47.7 - _survivor_head(NULL), _survivors_tail(NULL), _survivor_length(0) 47.8 + _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) 47.9 { 47.10 guarantee( check_list_empty(false), "just making sure..." ); 47.11 } 47.12 @@ -159,16 +159,15 @@ 47.13 } 47.14 47.15 void YoungList::add_survivor_region(HeapRegion* hr) { 47.16 - assert(!hr->is_survivor(), "should not already be for survived"); 47.17 + assert(hr->is_survivor(), "should be flagged as survivor region"); 47.18 assert(hr->get_next_young_region() == NULL, "cause it should!"); 47.19 47.20 hr->set_next_young_region(_survivor_head); 47.21 if (_survivor_head == NULL) { 47.22 - _survivors_tail = hr; 47.23 + _survivor_tail = hr; 47.24 } 47.25 _survivor_head = hr; 47.26 47.27 - hr->set_survivor(); 47.28 ++_survivor_length; 47.29 } 47.30 47.31 @@ -239,7 +238,7 @@ 47.32 47.33 empty_list(_survivor_head); 47.34 _survivor_head = NULL; 47.35 - _survivors_tail = NULL; 47.36 + _survivor_tail = NULL; 47.37 _survivor_length = 0; 47.38 47.39 _last_sampled_rs_lengths = 0; 47.40 @@ -391,6 +390,7 @@ 47.41 47.42 // Add survivor regions to SurvRateGroup. 47.43 _g1h->g1_policy()->note_start_adding_survivor_regions(); 47.44 + _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); 47.45 for (HeapRegion* curr = _survivor_head; 47.46 curr != NULL; 47.47 curr = curr->get_next_young_region()) { 47.48 @@ -401,7 +401,7 @@ 47.49 if (_survivor_head != NULL) { 47.50 _head = _survivor_head; 47.51 _length = _survivor_length + _scan_only_length; 47.52 - _survivors_tail->set_next_young_region(_scan_only_head); 47.53 + _survivor_tail->set_next_young_region(_scan_only_head); 47.54 } else { 47.55 _head = _scan_only_head; 47.56 _length = _scan_only_length; 47.57 @@ -418,9 +418,9 @@ 47.58 _curr_scan_only = NULL; 47.59 47.60 _survivor_head = NULL; 47.61 - _survivors_tail = NULL; 47.62 + _survivor_tail = NULL; 47.63 _survivor_length = 0; 47.64 - _g1h->g1_policy()->finished_recalculating_age_indexes(); 47.65 + _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); 47.66 47.67 assert(check_list_well_formed(), "young list should be well formed"); 47.68 } 47.69 @@ -553,7 +553,7 @@ 47.70 if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) { 47.71 alloc_region = newAllocRegion_work(word_size, true, zero_filled); 47.72 if (purpose == GCAllocForSurvived && alloc_region != NULL) { 47.73 - _young_list->add_survivor_region(alloc_region); 47.74 + alloc_region->set_survivor(); 47.75 } 47.76 ++_gc_alloc_region_counts[purpose]; 47.77 } else { 47.78 @@ -949,6 +949,10 @@ 47.79 GCOverheadReporter::recordSTWEnd(end); 47.80 g1_policy()->record_full_collection_end(); 47.81 47.82 +#ifdef TRACESPINNING 47.83 + ParallelTaskTerminator::print_termination_counts(); 47.84 +#endif 47.85 + 47.86 gc_epilogue(true); 47.87 47.88 // Abandon concurrent refinement. This must happen last: in the 47.89 @@ -1285,7 +1289,9 @@ 47.90 _unclean_regions_coming(false), 47.91 _young_list(new YoungList(this)), 47.92 _gc_time_stamp(0), 47.93 - _surviving_young_words(NULL) 47.94 + _surviving_young_words(NULL), 47.95 + _in_cset_fast_test(NULL), 47.96 + _in_cset_fast_test_base(NULL) 47.97 { 47.98 _g1h = this; // To catch bugs. 47.99 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { 47.100 @@ -2485,6 +2491,19 @@ 47.101 g1_policy()->record_collection_pause_start(start_time_sec, 47.102 start_used_bytes); 47.103 47.104 + guarantee(_in_cset_fast_test == NULL, "invariant"); 47.105 + guarantee(_in_cset_fast_test_base == NULL, "invariant"); 47.106 + _in_cset_fast_test_length = n_regions(); 47.107 + _in_cset_fast_test_base = 47.108 + NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); 47.109 + memset(_in_cset_fast_test_base, false, 47.110 + _in_cset_fast_test_length * sizeof(bool)); 47.111 + // We're biasing _in_cset_fast_test to avoid subtracting the 47.112 + // beginning of the heap every time we want to index; basically 47.113 + // it's the same with what we do with the card table. 47.114 + _in_cset_fast_test = _in_cset_fast_test_base - 47.115 + ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); 47.116 + 47.117 #if SCAN_ONLY_VERBOSE 47.118 _young_list->print(); 47.119 #endif // SCAN_ONLY_VERBOSE 47.120 @@ -2553,6 +2572,12 @@ 47.121 free_collection_set(g1_policy()->collection_set()); 47.122 g1_policy()->clear_collection_set(); 47.123 47.124 + FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); 47.125 + // this is more for peace of mind; we're nulling them here and 47.126 + // we're expecting them to be null at the beginning of the next GC 47.127 + _in_cset_fast_test = NULL; 47.128 + _in_cset_fast_test_base = NULL; 47.129 + 47.130 if (popular_region != NULL) { 47.131 // We have to wait until now, because we don't want the region to 47.132 // be rescheduled for pop-evac during RS update. 47.133 @@ -2572,6 +2597,9 @@ 47.134 _young_list->print(); 47.135 #endif // SCAN_ONLY_VERBOSE 47.136 47.137 + g1_policy()->record_survivor_regions(_young_list->survivor_length(), 47.138 + _young_list->first_survivor_region(), 47.139 + _young_list->last_survivor_region()); 47.140 _young_list->reset_auxilary_lists(); 47.141 } 47.142 } else { 47.143 @@ -2598,7 +2626,9 @@ 47.144 #endif // SCAN_ONLY_VERBOSE 47.145 47.146 double end_time_sec = os::elapsedTime(); 47.147 - g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); 47.148 + if (!evacuation_failed()) { 47.149 + g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); 47.150 + } 47.151 GCOverheadReporter::recordSTWEnd(end_time_sec); 47.152 g1_policy()->record_collection_pause_end(popular_region != NULL, 47.153 abandoned); 47.154 @@ -2621,8 +2651,13 @@ 47.155 } 47.156 } 47.157 47.158 - if (mark_in_progress()) 47.159 + if (mark_in_progress()) { 47.160 concurrent_mark()->update_g1_committed(); 47.161 + } 47.162 + 47.163 +#ifdef TRACESPINNING 47.164 + ParallelTaskTerminator::print_termination_counts(); 47.165 +#endif 47.166 47.167 gc_epilogue(false); 47.168 } 47.169 @@ -2733,6 +2768,13 @@ 47.170 _gc_alloc_region_list = r->next_gc_alloc_region(); 47.171 r->set_next_gc_alloc_region(NULL); 47.172 r->set_is_gc_alloc_region(false); 47.173 + if (r->is_survivor()) { 47.174 + if (r->is_empty()) { 47.175 + r->set_not_young(); 47.176 + } else { 47.177 + _young_list->add_survivor_region(r); 47.178 + } 47.179 + } 47.180 if (r->is_empty()) { 47.181 ++_free_regions; 47.182 } 47.183 @@ -3129,6 +3171,20 @@ 47.184 return block; 47.185 } 47.186 47.187 +void G1CollectedHeap::retire_alloc_region(HeapRegion* alloc_region, 47.188 + bool par) { 47.189 + // Another thread might have obtained alloc_region for the given 47.190 + // purpose, and might be attempting to allocate in it, and might 47.191 + // succeed. Therefore, we can't do the "finalization" stuff on the 47.192 + // region below until we're sure the last allocation has happened. 47.193 + // We ensure this by allocating the remaining space with a garbage 47.194 + // object. 47.195 + if (par) par_allocate_remaining_space(alloc_region); 47.196 + // Now we can do the post-GC stuff on the region. 47.197 + alloc_region->note_end_of_copying(); 47.198 + g1_policy()->record_after_bytes(alloc_region->used()); 47.199 +} 47.200 + 47.201 HeapWord* 47.202 G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, 47.203 HeapRegion* alloc_region, 47.204 @@ -3146,16 +3202,7 @@ 47.205 // Otherwise, continue; this new region is empty, too. 47.206 } 47.207 assert(alloc_region != NULL, "We better have an allocation region"); 47.208 - // Another thread might have obtained alloc_region for the given 47.209 - // purpose, and might be attempting to allocate in it, and might 47.210 - // succeed. Therefore, we can't do the "finalization" stuff on the 47.211 - // region below until we're sure the last allocation has happened. 47.212 - // We ensure this by allocating the remaining space with a garbage 47.213 - // object. 47.214 - if (par) par_allocate_remaining_space(alloc_region); 47.215 - // Now we can do the post-GC stuff on the region. 47.216 - alloc_region->note_end_of_copying(); 47.217 - g1_policy()->record_after_bytes(alloc_region->used()); 47.218 + retire_alloc_region(alloc_region, par); 47.219 47.220 if (_gc_alloc_region_counts[purpose] >= g1_policy()->max_regions(purpose)) { 47.221 // Cannot allocate more regions for the given purpose. 47.222 @@ -3164,7 +3211,7 @@ 47.223 if (purpose != alt_purpose) { 47.224 HeapRegion* alt_region = _gc_alloc_regions[alt_purpose]; 47.225 // Has not the alternative region been aliased? 47.226 - if (alloc_region != alt_region) { 47.227 + if (alloc_region != alt_region && alt_region != NULL) { 47.228 // Try to allocate in the alternative region. 47.229 if (par) { 47.230 block = alt_region->par_allocate(word_size); 47.231 @@ -3173,9 +3220,10 @@ 47.232 } 47.233 // Make an alias. 47.234 _gc_alloc_regions[purpose] = _gc_alloc_regions[alt_purpose]; 47.235 - } 47.236 - if (block != NULL) { 47.237 - return block; 47.238 + if (block != NULL) { 47.239 + return block; 47.240 + } 47.241 + retire_alloc_region(alt_region, par); 47.242 } 47.243 // Both the allocation region and the alternative one are full 47.244 // and aliased, replace them with a new allocation region. 47.245 @@ -3476,6 +3524,7 @@ 47.246 OverflowQueue* _overflowed_refs; 47.247 47.248 G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount]; 47.249 + ageTable _age_table; 47.250 47.251 size_t _alloc_buffer_waste; 47.252 size_t _undo_waste; 47.253 @@ -3517,6 +3566,7 @@ 47.254 _refs(g1h->task_queue(queue_num)), 47.255 _hash_seed(17), _queue_num(queue_num), 47.256 _term_attempts(0), 47.257 + _age_table(false), 47.258 #if G1_DETAILED_STATS 47.259 _pushes(0), _pops(0), _steals(0), 47.260 _steal_attempts(0), _overflow_pushes(0), 47.261 @@ -3551,8 +3601,9 @@ 47.262 47.263 RefToScanQueue* refs() { return _refs; } 47.264 OverflowQueue* overflowed_refs() { return _overflowed_refs; } 47.265 - 47.266 - inline G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 47.267 + ageTable* age_table() { return &_age_table; } 47.268 + 47.269 + G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 47.270 return &_alloc_buffers[purpose]; 47.271 } 47.272 47.273 @@ -3560,6 +3611,9 @@ 47.274 size_t undo_waste() { return _undo_waste; } 47.275 47.276 void push_on_queue(oop* ref) { 47.277 + assert(ref != NULL, "invariant"); 47.278 + assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), "invariant"); 47.279 + 47.280 if (!refs()->push(ref)) { 47.281 overflowed_refs()->push(ref); 47.282 IF_G1_DETAILED_STATS(note_overflow_push()); 47.283 @@ -3572,6 +3626,10 @@ 47.284 if (!refs()->pop_local(ref)) { 47.285 ref = NULL; 47.286 } else { 47.287 + assert(ref != NULL, "invariant"); 47.288 + assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), 47.289 + "invariant"); 47.290 + 47.291 IF_G1_DETAILED_STATS(note_pop()); 47.292 } 47.293 } 47.294 @@ -3601,8 +3659,7 @@ 47.295 47.296 obj = alloc_buf->allocate(word_sz); 47.297 assert(obj != NULL, "buffer was definitely big enough..."); 47.298 - } 47.299 - else { 47.300 + } else { 47.301 obj = _g1h->par_allocate_during_gc(purpose, word_sz); 47.302 } 47.303 return obj; 47.304 @@ -3695,24 +3752,57 @@ 47.305 } 47.306 } 47.307 47.308 +private: 47.309 + void deal_with_reference(oop* ref_to_scan) { 47.310 + if (has_partial_array_mask(ref_to_scan)) { 47.311 + _partial_scan_cl->do_oop_nv(ref_to_scan); 47.312 + } else { 47.313 + // Note: we can use "raw" versions of "region_containing" because 47.314 + // "obj_to_scan" is definitely in the heap, and is not in a 47.315 + // humongous region. 47.316 + HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); 47.317 + _evac_cl->set_region(r); 47.318 + _evac_cl->do_oop_nv(ref_to_scan); 47.319 + } 47.320 + } 47.321 + 47.322 +public: 47.323 void trim_queue() { 47.324 + // I've replicated the loop twice, first to drain the overflow 47.325 + // queue, second to drain the task queue. This is better than 47.326 + // having a single loop, which checks both conditions and, inside 47.327 + // it, either pops the overflow queue or the task queue, as each 47.328 + // loop is tighter. Also, the decision to drain the overflow queue 47.329 + // first is not arbitrary, as the overflow queue is not visible 47.330 + // to the other workers, whereas the task queue is. So, we want to 47.331 + // drain the "invisible" entries first, while allowing the other 47.332 + // workers to potentially steal the "visible" entries. 47.333 + 47.334 while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) { 47.335 - oop *ref_to_scan = NULL; 47.336 - if (overflowed_refs_to_scan() == 0) { 47.337 + while (overflowed_refs_to_scan() > 0) { 47.338 + oop *ref_to_scan = NULL; 47.339 + pop_from_overflow_queue(ref_to_scan); 47.340 + assert(ref_to_scan != NULL, "invariant"); 47.341 + // We shouldn't have pushed it on the queue if it was not 47.342 + // pointing into the CSet. 47.343 + assert(ref_to_scan != NULL, "sanity"); 47.344 + assert(has_partial_array_mask(ref_to_scan) || 47.345 + _g1h->obj_in_cs(*ref_to_scan), "sanity"); 47.346 + 47.347 + deal_with_reference(ref_to_scan); 47.348 + } 47.349 + 47.350 + while (refs_to_scan() > 0) { 47.351 + oop *ref_to_scan = NULL; 47.352 pop_from_queue(ref_to_scan); 47.353 - } else { 47.354 - pop_from_overflow_queue(ref_to_scan); 47.355 - } 47.356 - if (ref_to_scan != NULL) { 47.357 - if ((intptr_t)ref_to_scan & G1_PARTIAL_ARRAY_MASK) { 47.358 - _partial_scan_cl->do_oop_nv(ref_to_scan); 47.359 - } else { 47.360 - // Note: we can use "raw" versions of "region_containing" because 47.361 - // "obj_to_scan" is definitely in the heap, and is not in a 47.362 - // humongous region. 47.363 - HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); 47.364 - _evac_cl->set_region(r); 47.365 - _evac_cl->do_oop_nv(ref_to_scan); 47.366 + 47.367 + if (ref_to_scan != NULL) { 47.368 + // We shouldn't have pushed it on the queue if it was not 47.369 + // pointing into the CSet. 47.370 + assert(has_partial_array_mask(ref_to_scan) || 47.371 + _g1h->obj_in_cs(*ref_to_scan), "sanity"); 47.372 + 47.373 + deal_with_reference(ref_to_scan); 47.374 } 47.375 } 47.376 } 47.377 @@ -3728,16 +3818,25 @@ 47.378 // Should probably be made inline and moved in g1OopClosures.inline.hpp. 47.379 void G1ParScanClosure::do_oop_nv(oop* p) { 47.380 oop obj = *p; 47.381 + 47.382 if (obj != NULL) { 47.383 - if (_g1->obj_in_cs(obj)) { 47.384 - if (obj->is_forwarded()) { 47.385 - *p = obj->forwardee(); 47.386 - } else { 47.387 - _par_scan_state->push_on_queue(p); 47.388 - return; 47.389 - } 47.390 + if (_g1->in_cset_fast_test(obj)) { 47.391 + // We're not going to even bother checking whether the object is 47.392 + // already forwarded or not, as this usually causes an immediate 47.393 + // stall. We'll try to prefetch the object (for write, given that 47.394 + // we might need to install the forwarding reference) and we'll 47.395 + // get back to it when pop it from the queue 47.396 + Prefetch::write(obj->mark_addr(), 0); 47.397 + Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); 47.398 + 47.399 + // slightly paranoid test; I'm trying to catch potential 47.400 + // problems before we go into push_on_queue to know where the 47.401 + // problem is coming from 47.402 + assert(obj == *p, "the value of *p should not have changed"); 47.403 + _par_scan_state->push_on_queue(p); 47.404 + } else { 47.405 + _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); 47.406 } 47.407 - _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); 47.408 } 47.409 } 47.410 47.411 @@ -3765,7 +3864,9 @@ 47.412 (!from_region->is_young() && young_index == 0), "invariant" ); 47.413 G1CollectorPolicy* g1p = _g1->g1_policy(); 47.414 markOop m = old->mark(); 47.415 - GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, m->age(), 47.416 + int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() 47.417 + : m->age(); 47.418 + GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, 47.419 word_sz); 47.420 HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); 47.421 oop obj = oop(obj_ptr); 47.422 @@ -3777,13 +3878,39 @@ 47.423 return _g1->handle_evacuation_failure_par(cl, old); 47.424 } 47.425 47.426 + // We're going to allocate linearly, so might as well prefetch ahead. 47.427 + Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); 47.428 + 47.429 oop forward_ptr = old->forward_to_atomic(obj); 47.430 if (forward_ptr == NULL) { 47.431 Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz); 47.432 - obj->set_mark(m); 47.433 if (g1p->track_object_age(alloc_purpose)) { 47.434 - obj->incr_age(); 47.435 + // We could simply do obj->incr_age(). However, this causes a 47.436 + // performance issue. obj->incr_age() will first check whether 47.437 + // the object has a displaced mark by checking its mark word; 47.438 + // getting the mark word from the new location of the object 47.439 + // stalls. So, given that we already have the mark word and we 47.440 + // are about to install it anyway, it's better to increase the 47.441 + // age on the mark word, when the object does not have a 47.442 + // displaced mark word. We're not expecting many objects to have 47.443 + // a displaced marked word, so that case is not optimized 47.444 + // further (it could be...) and we simply call obj->incr_age(). 47.445 + 47.446 + if (m->has_displaced_mark_helper()) { 47.447 + // in this case, we have to install the mark word first, 47.448 + // otherwise obj looks to be forwarded (the old mark word, 47.449 + // which contains the forward pointer, was copied) 47.450 + obj->set_mark(m); 47.451 + obj->incr_age(); 47.452 + } else { 47.453 + m = m->incr_age(); 47.454 + obj->set_mark(m); 47.455 + } 47.456 + _par_scan_state->age_table()->add(obj, word_sz); 47.457 + } else { 47.458 + obj->set_mark(m); 47.459 } 47.460 + 47.461 // preserve "next" mark bit 47.462 if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { 47.463 if (!use_local_bitmaps || 47.464 @@ -3805,9 +3932,11 @@ 47.465 47.466 if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { 47.467 arrayOop(old)->set_length(0); 47.468 - _par_scan_state->push_on_queue((oop*) ((intptr_t)old | G1_PARTIAL_ARRAY_MASK)); 47.469 + _par_scan_state->push_on_queue(set_partial_array_mask(old)); 47.470 } else { 47.471 - _scanner->set_region(_g1->heap_region_containing(obj)); 47.472 + // No point in using the slower heap_region_containing() method, 47.473 + // given that we know obj is in the heap. 47.474 + _scanner->set_region(_g1->heap_region_containing_raw(obj)); 47.475 obj->oop_iterate_backwards(_scanner); 47.476 } 47.477 } else { 47.478 @@ -3817,47 +3946,55 @@ 47.479 return obj; 47.480 } 47.481 47.482 -template<bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> 47.483 -void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_forwardee>::do_oop_work(oop* p) { 47.484 +template<bool do_gen_barrier, G1Barrier barrier, 47.485 + bool do_mark_forwardee, bool skip_cset_test> 47.486 +void G1ParCopyClosure<do_gen_barrier, barrier, 47.487 + do_mark_forwardee, skip_cset_test>::do_oop_work(oop* p) { 47.488 oop obj = *p; 47.489 assert(barrier != G1BarrierRS || obj != NULL, 47.490 "Precondition: G1BarrierRS implies obj is nonNull"); 47.491 47.492 - if (obj != NULL) { 47.493 - if (_g1->obj_in_cs(obj)) { 47.494 + // The only time we skip the cset test is when we're scanning 47.495 + // references popped from the queue. And we only push on the queue 47.496 + // references that we know point into the cset, so no point in 47.497 + // checking again. But we'll leave an assert here for peace of mind. 47.498 + assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant"); 47.499 + 47.500 + // here the null check is implicit in the cset_fast_test() test 47.501 + if (skip_cset_test || _g1->in_cset_fast_test(obj)) { 47.502 #if G1_REM_SET_LOGGING 47.503 - gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" into CS.", 47.504 - p, (void*) obj); 47.505 + gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" " 47.506 + "into CS.", p, (void*) obj); 47.507 #endif 47.508 - if (obj->is_forwarded()) { 47.509 - *p = obj->forwardee(); 47.510 - } else { 47.511 - *p = copy_to_survivor_space(obj); 47.512 - } 47.513 - // When scanning the RS, we only care about objs in CS. 47.514 - if (barrier == G1BarrierRS) { 47.515 - _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); 47.516 - } 47.517 + if (obj->is_forwarded()) { 47.518 + *p = obj->forwardee(); 47.519 + } else { 47.520 + *p = copy_to_survivor_space(obj); 47.521 } 47.522 - // When scanning moved objs, must look at all oops. 47.523 - if (barrier == G1BarrierEvac) { 47.524 + // When scanning the RS, we only care about objs in CS. 47.525 + if (barrier == G1BarrierRS) { 47.526 _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); 47.527 } 47.528 - 47.529 - if (do_gen_barrier) { 47.530 - par_do_barrier(p); 47.531 - } 47.532 - } 47.533 -} 47.534 - 47.535 -template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p); 47.536 - 47.537 -template <class T> void G1ParScanPartialArrayClosure::process_array_chunk( 47.538 + } 47.539 + 47.540 + // When scanning moved objs, must look at all oops. 47.541 + if (barrier == G1BarrierEvac && obj != NULL) { 47.542 + _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); 47.543 + } 47.544 + 47.545 + if (do_gen_barrier && obj != NULL) { 47.546 + par_do_barrier(p); 47.547 + } 47.548 +} 47.549 + 47.550 +template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p); 47.551 + 47.552 +template<class T> void G1ParScanPartialArrayClosure::process_array_chunk( 47.553 oop obj, int start, int end) { 47.554 // process our set of indices (include header in first chunk) 47.555 assert(start < end, "invariant"); 47.556 T* const base = (T*)objArrayOop(obj)->base(); 47.557 - T* const start_addr = base + start; 47.558 + T* const start_addr = (start == 0) ? (T*) obj : base + start; 47.559 T* const end_addr = base + end; 47.560 MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); 47.561 _scanner.set_region(_g1->heap_region_containing(obj)); 47.562 @@ -3866,7 +4003,8 @@ 47.563 47.564 void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) { 47.565 assert(!UseCompressedOops, "Needs to be fixed to work with compressed oops"); 47.566 - oop old = oop((intptr_t)p & ~G1_PARTIAL_ARRAY_MASK); 47.567 + assert(has_partial_array_mask(p), "invariant"); 47.568 + oop old = clear_partial_array_mask(p); 47.569 assert(old->is_objArray(), "must be obj array"); 47.570 assert(old->is_forwarded(), "must be forwarded"); 47.571 assert(Universe::heap()->is_in_reserved(old), "must be in heap."); 47.572 @@ -3884,7 +4022,7 @@ 47.573 end = start + ParGCArrayScanChunk; 47.574 arrayOop(old)->set_length(end); 47.575 // Push remainder. 47.576 - _par_scan_state->push_on_queue((oop*) ((intptr_t) old | G1_PARTIAL_ARRAY_MASK)); 47.577 + _par_scan_state->push_on_queue(set_partial_array_mask(old)); 47.578 } else { 47.579 // Restore length so that the heap remains parsable in 47.580 // case of evacuation failure. 47.581 @@ -3893,11 +4031,6 @@ 47.582 47.583 // process our set of indices (include header in first chunk) 47.584 process_array_chunk<oop>(obj, start, end); 47.585 - oop* start_addr = start == 0 ? (oop*)obj : obj->obj_at_addr<oop>(start); 47.586 - oop* end_addr = (oop*)(obj->base()) + end; // obj_at_addr(end) asserts end < length 47.587 - MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); 47.588 - _scanner.set_region(_g1->heap_region_containing(obj)); 47.589 - obj->oop_iterate(&_scanner, mr); 47.590 } 47.591 47.592 int G1ScanAndBalanceClosure::_nq = 0; 47.593 @@ -3931,6 +4064,13 @@ 47.594 pss->hash_seed(), 47.595 ref_to_scan)) { 47.596 IF_G1_DETAILED_STATS(pss->note_steal()); 47.597 + 47.598 + // slightly paranoid tests; I'm trying to catch potential 47.599 + // problems before we go into push_on_queue to know where the 47.600 + // problem is coming from 47.601 + assert(ref_to_scan != NULL, "invariant"); 47.602 + assert(has_partial_array_mask(ref_to_scan) || 47.603 + _g1h->obj_in_cs(*ref_to_scan), "invariant"); 47.604 pss->push_on_queue(ref_to_scan); 47.605 continue; 47.606 } 47.607 @@ -3976,10 +4116,10 @@ 47.608 ResourceMark rm; 47.609 HandleMark hm; 47.610 47.611 - G1ParScanThreadState pss(_g1h, i); 47.612 - G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); 47.613 - G1ParScanHeapEvacClosure evac_failure_cl(_g1h, &pss); 47.614 - G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); 47.615 + G1ParScanThreadState pss(_g1h, i); 47.616 + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); 47.617 + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss); 47.618 + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); 47.619 47.620 pss.set_evac_closure(&scan_evac_cl); 47.621 pss.set_evac_failure_closure(&evac_failure_cl); 47.622 @@ -4024,6 +4164,9 @@ 47.623 _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms); 47.624 _g1h->g1_policy()->record_termination_time(i, term_ms); 47.625 } 47.626 + if (G1UseSurvivorSpace) { 47.627 + _g1h->g1_policy()->record_thread_age_table(pss.age_table()); 47.628 + } 47.629 _g1h->update_surviving_young_words(pss.surviving_young_words()+1); 47.630 47.631 // Clean up any par-expanded rem sets. 47.632 @@ -4263,7 +4406,7 @@ 47.633 // Is this the right thing to do here? We don't save marks 47.634 // on individual heap regions when we allocate from 47.635 // them in parallel, so this seems like the correct place for this. 47.636 - all_alloc_regions_note_end_of_copying(); 47.637 + retire_all_alloc_regions(); 47.638 { 47.639 G1IsAliveClosure is_alive(this); 47.640 G1KeepAliveClosure keep_alive(this); 47.641 @@ -4903,7 +5046,7 @@ 47.642 return no_allocs; 47.643 } 47.644 47.645 -void G1CollectedHeap::all_alloc_regions_note_end_of_copying() { 47.646 +void G1CollectedHeap::retire_all_alloc_regions() { 47.647 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { 47.648 HeapRegion* r = _gc_alloc_regions[ap]; 47.649 if (r != NULL) { 47.650 @@ -4916,8 +5059,7 @@ 47.651 } 47.652 } 47.653 if (!has_processed_alias) { 47.654 - r->note_end_of_copying(); 47.655 - g1_policy()->record_after_bytes(r->used()); 47.656 + retire_alloc_region(r, false /* par */); 47.657 } 47.658 } 47.659 }
48.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Sat Jan 31 17:19:42 2009 -0800 48.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Feb 27 15:13:00 2009 -0800 48.3 @@ -90,7 +90,7 @@ 48.4 HeapRegion* _curr_scan_only; 48.5 48.6 HeapRegion* _survivor_head; 48.7 - HeapRegion* _survivors_tail; 48.8 + HeapRegion* _survivor_tail; 48.9 size_t _survivor_length; 48.10 48.11 void empty_list(HeapRegion* list); 48.12 @@ -105,6 +105,7 @@ 48.13 bool is_empty() { return _length == 0; } 48.14 size_t length() { return _length; } 48.15 size_t scan_only_length() { return _scan_only_length; } 48.16 + size_t survivor_length() { return _survivor_length; } 48.17 48.18 void rs_length_sampling_init(); 48.19 bool rs_length_sampling_more(); 48.20 @@ -120,6 +121,7 @@ 48.21 HeapRegion* first_region() { return _head; } 48.22 HeapRegion* first_scan_only_region() { return _scan_only_head; } 48.23 HeapRegion* first_survivor_region() { return _survivor_head; } 48.24 + HeapRegion* last_survivor_region() { return _survivor_tail; } 48.25 HeapRegion* par_get_next_scan_only_region() { 48.26 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 48.27 HeapRegion* ret = _curr_scan_only; 48.28 @@ -219,7 +221,7 @@ 48.29 // The to-space memory regions into which objects are being copied during 48.30 // a GC. 48.31 HeapRegion* _gc_alloc_regions[GCAllocPurposeCount]; 48.32 - uint _gc_alloc_region_counts[GCAllocPurposeCount]; 48.33 + size_t _gc_alloc_region_counts[GCAllocPurposeCount]; 48.34 48.35 // A list of the regions that have been set to be alloc regions in the 48.36 // current collection. 48.37 @@ -247,6 +249,27 @@ 48.38 NumberSeq _pop_obj_rc_at_copy; 48.39 void print_popularity_summary_info() const; 48.40 48.41 + // This is used for a quick test on whether a reference points into 48.42 + // the collection set or not. Basically, we have an array, with one 48.43 + // byte per region, and that byte denotes whether the corresponding 48.44 + // region is in the collection set or not. The entry corresponding 48.45 + // the bottom of the heap, i.e., region 0, is pointed to by 48.46 + // _in_cset_fast_test_base. The _in_cset_fast_test field has been 48.47 + // biased so that it actually points to address 0 of the address 48.48 + // space, to make the test as fast as possible (we can simply shift 48.49 + // the address to address into it, instead of having to subtract the 48.50 + // bottom of the heap from the address before shifting it; basically 48.51 + // it works in the same way the card table works). 48.52 + bool* _in_cset_fast_test; 48.53 + 48.54 + // The allocated array used for the fast test on whether a reference 48.55 + // points into the collection set or not. This field is also used to 48.56 + // free the array. 48.57 + bool* _in_cset_fast_test_base; 48.58 + 48.59 + // The length of the _in_cset_fast_test_base array. 48.60 + size_t _in_cset_fast_test_length; 48.61 + 48.62 volatile unsigned _gc_time_stamp; 48.63 48.64 size_t* _surviving_young_words; 48.65 @@ -260,8 +283,8 @@ 48.66 // Returns "true" iff none of the gc alloc regions have any allocations 48.67 // since the last call to "save_marks". 48.68 bool all_alloc_regions_no_allocs_since_save_marks(); 48.69 - // Calls "note_end_of_copying on all gc alloc_regions. 48.70 - void all_alloc_regions_note_end_of_copying(); 48.71 + // Perform finalization stuff on all allocation regions. 48.72 + void retire_all_alloc_regions(); 48.73 48.74 // The number of regions allocated to hold humongous objects. 48.75 int _num_humongous_regions; 48.76 @@ -330,6 +353,10 @@ 48.77 // that parallel threads might be attempting allocations. 48.78 void par_allocate_remaining_space(HeapRegion* r); 48.79 48.80 + // Retires an allocation region when it is full or at the end of a 48.81 + // GC pause. 48.82 + void retire_alloc_region(HeapRegion* alloc_region, bool par); 48.83 + 48.84 // Helper function for two callbacks below. 48.85 // "full", if true, indicates that the GC is for a System.gc() request, 48.86 // and should collect the entire heap. If "clear_all_soft_refs" is true, 48.87 @@ -368,6 +395,38 @@ 48.88 virtual void gc_prologue(bool full); 48.89 virtual void gc_epilogue(bool full); 48.90 48.91 + // We register a region with the fast "in collection set" test. We 48.92 + // simply set to true the array slot corresponding to this region. 48.93 + void register_region_with_in_cset_fast_test(HeapRegion* r) { 48.94 + assert(_in_cset_fast_test_base != NULL, "sanity"); 48.95 + assert(r->in_collection_set(), "invariant"); 48.96 + int index = r->hrs_index(); 48.97 + assert(0 <= (size_t) index && (size_t) index < _in_cset_fast_test_length, 48.98 + "invariant"); 48.99 + assert(!_in_cset_fast_test_base[index], "invariant"); 48.100 + _in_cset_fast_test_base[index] = true; 48.101 + } 48.102 + 48.103 + // This is a fast test on whether a reference points into the 48.104 + // collection set or not. It does not assume that the reference 48.105 + // points into the heap; if it doesn't, it will return false. 48.106 + bool in_cset_fast_test(oop obj) { 48.107 + assert(_in_cset_fast_test != NULL, "sanity"); 48.108 + if (_g1_committed.contains((HeapWord*) obj)) { 48.109 + // no need to subtract the bottom of the heap from obj, 48.110 + // _in_cset_fast_test is biased 48.111 + size_t index = ((size_t) obj) >> HeapRegion::LogOfHRGrainBytes; 48.112 + bool ret = _in_cset_fast_test[index]; 48.113 + // let's make sure the result is consistent with what the slower 48.114 + // test returns 48.115 + assert( ret || !obj_in_cs(obj), "sanity"); 48.116 + assert(!ret || obj_in_cs(obj), "sanity"); 48.117 + return ret; 48.118 + } else { 48.119 + return false; 48.120 + } 48.121 + } 48.122 + 48.123 protected: 48.124 48.125 // Shrink the garbage-first heap by at most the given size (in bytes!). 48.126 @@ -850,6 +909,7 @@ 48.127 48.128 // Iterate over all objects, calling "cl.do_object" on each. 48.129 virtual void object_iterate(ObjectClosure* cl); 48.130 + virtual void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } 48.131 48.132 // Iterate over all objects allocated since the last collection, calling 48.133 // "cl.do_object" on each. The heap must have been initialized properly
49.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Sat Jan 31 17:19:42 2009 -0800 49.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Feb 27 15:13:00 2009 -0800 49.3 @@ -36,8 +36,11 @@ 49.4 49.5 inline HeapRegion* 49.6 G1CollectedHeap::heap_region_containing_raw(const void* addr) const { 49.7 - HeapRegion* res = _hrs->addr_to_region(addr); 49.8 - assert(res != NULL, "addr outside of heap?"); 49.9 + assert(_g1_reserved.contains(addr), "invariant"); 49.10 + size_t index = ((intptr_t) addr - (intptr_t) _g1_reserved.start()) 49.11 + >> HeapRegion::LogOfHRGrainBytes; 49.12 + HeapRegion* res = _hrs->at(index); 49.13 + assert(res == _hrs->addr_to_region(addr), "sanity"); 49.14 return res; 49.15 } 49.16
50.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sat Jan 31 17:19:42 2009 -0800 50.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Feb 27 15:13:00 2009 -0800 50.3 @@ -196,8 +196,13 @@ 50.4 _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived", 50.5 G1YoungSurvRateNumRegionsSummary)), 50.6 _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor", 50.7 - G1YoungSurvRateNumRegionsSummary)) 50.8 + G1YoungSurvRateNumRegionsSummary)), 50.9 // add here any more surv rate groups 50.10 + _recorded_survivor_regions(0), 50.11 + _recorded_survivor_head(NULL), 50.12 + _recorded_survivor_tail(NULL), 50.13 + _survivors_age_table(true) 50.14 + 50.15 { 50.16 _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); 50.17 _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; 50.18 @@ -272,6 +277,15 @@ 50.19 _concurrent_mark_cleanup_times_ms->add(0.20); 50.20 _tenuring_threshold = MaxTenuringThreshold; 50.21 50.22 + if (G1UseSurvivorSpace) { 50.23 + // if G1FixedSurvivorSpaceSize is 0 which means the size is not 50.24 + // fixed, then _max_survivor_regions will be calculated at 50.25 + // calculate_young_list_target_config during initialization 50.26 + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; 50.27 + } else { 50.28 + _max_survivor_regions = 0; 50.29 + } 50.30 + 50.31 initialize_all(); 50.32 } 50.33 50.34 @@ -283,6 +297,9 @@ 50.35 void G1CollectorPolicy::initialize_flags() { 50.36 set_min_alignment(HeapRegion::GrainBytes); 50.37 set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name())); 50.38 + if (SurvivorRatio < 1) { 50.39 + vm_exit_during_initialization("Invalid survivor ratio specified"); 50.40 + } 50.41 CollectorPolicy::initialize_flags(); 50.42 } 50.43 50.44 @@ -301,6 +318,8 @@ 50.45 "-XX:+UseConcMarkSweepGC."); 50.46 } 50.47 50.48 + initialize_gc_policy_counters(); 50.49 + 50.50 if (G1Gen) { 50.51 _in_young_gc_mode = true; 50.52 50.53 @@ -322,6 +341,12 @@ 50.54 } 50.55 } 50.56 50.57 +// Create the jstat counters for the policy. 50.58 +void G1CollectorPolicy::initialize_gc_policy_counters() 50.59 +{ 50.60 + _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 2 + G1Gen); 50.61 +} 50.62 + 50.63 void G1CollectorPolicy::calculate_young_list_min_length() { 50.64 _young_list_min_length = 0; 50.65 50.66 @@ -352,6 +377,7 @@ 50.67 guarantee( so_length < _young_list_target_length, "invariant" ); 50.68 _young_list_so_prefix_length = so_length; 50.69 } 50.70 + calculate_survivors_policy(); 50.71 } 50.72 50.73 // This method calculate the optimal scan-only set for a fixed young 50.74 @@ -448,6 +474,9 @@ 50.75 if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { 50.76 // we are in fully-young mode and there are free regions in the heap 50.77 50.78 + double survivor_regions_evac_time = 50.79 + predict_survivor_regions_evac_time(); 50.80 + 50.81 size_t min_so_length = 0; 50.82 size_t max_so_length = 0; 50.83 50.84 @@ -497,9 +526,8 @@ 50.85 scanned_cards = predict_non_young_card_num(adj_rs_lengths); 50.86 // calculate this once, so that we don't have to recalculate it in 50.87 // the innermost loop 50.88 - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, 50.89 - scanned_cards); 50.90 - 50.91 + double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) 50.92 + + survivor_regions_evac_time; 50.93 // the result 50.94 size_t final_young_length = 0; 50.95 size_t final_so_length = 0; 50.96 @@ -548,14 +576,14 @@ 50.97 bool done = false; 50.98 // this is the outermost loop 50.99 while (!done) { 50.100 -#if 0 50.101 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.102 // leave this in for debugging, just in case 50.103 gclog_or_tty->print_cr("searching between " SIZE_FORMAT " and " SIZE_FORMAT 50.104 ", incr " SIZE_FORMAT ", pass %s", 50.105 from_so_length, to_so_length, so_length_incr, 50.106 (pass == pass_type_coarse) ? "coarse" : 50.107 (pass == pass_type_fine) ? "fine" : "final"); 50.108 -#endif // 0 50.109 +#endif // TRACE_CALC_YOUNG_CONFIG 50.110 50.111 size_t so_length = from_so_length; 50.112 size_t init_free_regions = 50.113 @@ -651,11 +679,11 @@ 50.114 guarantee( so_length_incr == so_coarse_increments, "invariant" ); 50.115 guarantee( final_so_length >= min_so_length, "invariant" ); 50.116 50.117 -#if 0 50.118 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.119 // leave this in for debugging, just in case 50.120 gclog_or_tty->print_cr(" coarse pass: SO length " SIZE_FORMAT, 50.121 final_so_length); 50.122 -#endif // 0 50.123 +#endif // TRACE_CALC_YOUNG_CONFIG 50.124 50.125 from_so_length = 50.126 (final_so_length - min_so_length > so_coarse_increments) ? 50.127 @@ -687,12 +715,12 @@ 50.128 // of the optimal 50.129 size_t new_so_length = 950 * final_so_length / 1000; 50.130 50.131 -#if 0 50.132 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.133 // leave this in for debugging, just in case 50.134 gclog_or_tty->print_cr(" fine pass: SO length " SIZE_FORMAT 50.135 ", setting it to " SIZE_FORMAT, 50.136 final_so_length, new_so_length); 50.137 -#endif // 0 50.138 +#endif // TRACE_CALC_YOUNG_CONFIG 50.139 50.140 from_so_length = new_so_length; 50.141 to_so_length = new_so_length; 50.142 @@ -719,7 +747,8 @@ 50.143 } 50.144 50.145 // we should have at least one region in the target young length 50.146 - _young_list_target_length = MAX2((size_t) 1, final_young_length); 50.147 + _young_list_target_length = 50.148 + MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); 50.149 if (final_so_length >= final_young_length) 50.150 // and we need to ensure that the S-O length is not greater than 50.151 // the target young length (this is being a bit careful) 50.152 @@ -734,7 +763,7 @@ 50.153 double end_time_sec = os::elapsedTime(); 50.154 double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; 50.155 50.156 -#if 0 50.157 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.158 // leave this in for debugging, just in case 50.159 gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT 50.160 ", SO = " SIZE_FORMAT ", " 50.161 @@ -747,9 +776,9 @@ 50.162 calculations, 50.163 full_young_gcs() ? "full" : "partial", 50.164 should_initiate_conc_mark() ? " i-m" : "", 50.165 - in_marking_window(), 50.166 - in_marking_window_im()); 50.167 -#endif // 0 50.168 + _in_marking_window, 50.169 + _in_marking_window_im); 50.170 +#endif // TRACE_CALC_YOUNG_CONFIG 50.171 50.172 if (_young_list_target_length < _young_list_min_length) { 50.173 // bummer; this means that, if we do a pause when the optimal 50.174 @@ -768,14 +797,14 @@ 50.175 // S-O length 50.176 so_length = calculate_optimal_so_length(_young_list_min_length); 50.177 50.178 -#if 0 50.179 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.180 // leave this in for debugging, just in case 50.181 gclog_or_tty->print_cr("adjusted target length from " 50.182 SIZE_FORMAT " to " SIZE_FORMAT 50.183 ", SO " SIZE_FORMAT, 50.184 _young_list_target_length, _young_list_min_length, 50.185 so_length); 50.186 -#endif // 0 50.187 +#endif // TRACE_CALC_YOUNG_CONFIG 50.188 50.189 _young_list_target_length = 50.190 MAX2(_young_list_min_length, (size_t)1); 50.191 @@ -785,12 +814,12 @@ 50.192 // we are in a partially-young mode or we've run out of regions (due 50.193 // to evacuation failure) 50.194 50.195 -#if 0 50.196 +#ifdef TRACE_CALC_YOUNG_CONFIG 50.197 // leave this in for debugging, just in case 50.198 gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT 50.199 ", SO " SIZE_FORMAT, 50.200 _young_list_min_length, 0); 50.201 -#endif // 0 50.202 +#endif // TRACE_CALC_YOUNG_CONFIG 50.203 50.204 // we'll do the pause as soon as possible and with no S-O prefix 50.205 // (see above for the reasons behind the latter) 50.206 @@ -884,6 +913,16 @@ 50.207 return true; 50.208 } 50.209 50.210 +double G1CollectorPolicy::predict_survivor_regions_evac_time() { 50.211 + double survivor_regions_evac_time = 0.0; 50.212 + for (HeapRegion * r = _recorded_survivor_head; 50.213 + r != NULL && r != _recorded_survivor_tail->get_next_young_region(); 50.214 + r = r->get_next_young_region()) { 50.215 + survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true); 50.216 + } 50.217 + return survivor_regions_evac_time; 50.218 +} 50.219 + 50.220 void G1CollectorPolicy::check_prediction_validity() { 50.221 guarantee( adaptive_young_list_length(), "should not call this otherwise" ); 50.222 50.223 @@ -995,11 +1034,15 @@ 50.224 _short_lived_surv_rate_group->start_adding_regions(); 50.225 // also call this on any additional surv rate groups 50.226 50.227 + record_survivor_regions(0, NULL, NULL); 50.228 + 50.229 _prev_region_num_young = _region_num_young; 50.230 _prev_region_num_tenured = _region_num_tenured; 50.231 50.232 _free_regions_at_end_of_collection = _g1->free_regions(); 50.233 _scan_only_regions_at_end_of_collection = 0; 50.234 + // Reset survivors SurvRateGroup. 50.235 + _survivor_surv_rate_group->reset(); 50.236 calculate_young_list_min_length(); 50.237 calculate_young_list_target_config(); 50.238 } 50.239 @@ -1104,6 +1147,10 @@ 50.240 _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length); 50.241 tag_scan_only(short_lived_so_length); 50.242 50.243 + if (G1UseSurvivorSpace) { 50.244 + _survivors_age_table.clear(); 50.245 + } 50.246 + 50.247 assert( verify_young_ages(), "region age verification" ); 50.248 } 50.249 50.250 @@ -1965,9 +2012,6 @@ 50.251 // </NEW PREDICTION> 50.252 50.253 _target_pause_time_ms = -1.0; 50.254 - 50.255 - // TODO: calculate tenuring threshold 50.256 - _tenuring_threshold = MaxTenuringThreshold; 50.257 } 50.258 50.259 // <NEW PREDICTION> 50.260 @@ -2058,7 +2102,7 @@ 50.261 guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1, 50.262 "invariant" ); 50.263 int age = hr->age_in_surv_rate_group(); 50.264 - double yg_surv_rate = predict_yg_surv_rate(age); 50.265 + double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); 50.266 bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate); 50.267 } 50.268 50.269 @@ -2091,7 +2135,7 @@ 50.270 } 50.271 #if PREDICTIONS_VERBOSE 50.272 if (young) { 50.273 - _recorded_young_bytes += hr->asSpace()->used(); 50.274 + _recorded_young_bytes += hr->used(); 50.275 } else { 50.276 _recorded_marked_bytes += hr->max_live_bytes(); 50.277 } 50.278 @@ -2119,11 +2163,6 @@ 50.279 predict_non_young_card_num(_predicted_rs_lengths); 50.280 _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions; 50.281 50.282 - _predicted_young_survival_ratio = 0.0; 50.283 - for (int i = 0; i < _recorded_young_regions; ++i) 50.284 - _predicted_young_survival_ratio += predict_yg_surv_rate(i); 50.285 - _predicted_young_survival_ratio /= (double) _recorded_young_regions; 50.286 - 50.287 _predicted_scan_only_scan_time_ms = 50.288 predict_scan_only_time_ms(_recorded_scan_only_regions); 50.289 _predicted_rs_update_time_ms = 50.290 @@ -2673,8 +2712,11 @@ 50.291 assert(in_young_gc_mode(), "should be in young GC mode"); 50.292 bool ret; 50.293 size_t young_list_length = _g1->young_list_length(); 50.294 - 50.295 - if (young_list_length < _young_list_target_length) { 50.296 + size_t young_list_max_length = _young_list_target_length; 50.297 + if (G1FixedEdenSize) { 50.298 + young_list_max_length -= _max_survivor_regions; 50.299 + } 50.300 + if (young_list_length < young_list_max_length) { 50.301 ret = true; 50.302 ++_region_num_young; 50.303 } else { 50.304 @@ -2710,17 +2752,39 @@ 50.305 } 50.306 50.307 50.308 -uint G1CollectorPolicy::max_regions(int purpose) { 50.309 +size_t G1CollectorPolicy::max_regions(int purpose) { 50.310 switch (purpose) { 50.311 case GCAllocForSurvived: 50.312 - return G1MaxSurvivorRegions; 50.313 + return _max_survivor_regions; 50.314 case GCAllocForTenured: 50.315 - return UINT_MAX; 50.316 + return REGIONS_UNLIMITED; 50.317 default: 50.318 - return UINT_MAX; 50.319 + ShouldNotReachHere(); 50.320 + return REGIONS_UNLIMITED; 50.321 }; 50.322 } 50.323 50.324 +// Calculates survivor space parameters. 50.325 +void G1CollectorPolicy::calculate_survivors_policy() 50.326 +{ 50.327 + if (!G1UseSurvivorSpace) { 50.328 + return; 50.329 + } 50.330 + if (G1FixedSurvivorSpaceSize == 0) { 50.331 + _max_survivor_regions = _young_list_target_length / SurvivorRatio; 50.332 + } else { 50.333 + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; 50.334 + } 50.335 + 50.336 + if (G1FixedTenuringThreshold) { 50.337 + _tenuring_threshold = MaxTenuringThreshold; 50.338 + } else { 50.339 + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( 50.340 + HeapRegion::GrainWords * _max_survivor_regions); 50.341 + } 50.342 +} 50.343 + 50.344 + 50.345 void 50.346 G1CollectorPolicy_BestRegionsFirst:: 50.347 set_single_region_collection_set(HeapRegion* hr) { 50.348 @@ -2743,7 +2807,11 @@ 50.349 double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; 50.350 50.351 size_t young_list_length = _g1->young_list_length(); 50.352 - bool reached_target_length = young_list_length >= _young_list_target_length; 50.353 + size_t young_list_max_length = _young_list_target_length; 50.354 + if (G1FixedEdenSize) { 50.355 + young_list_max_length -= _max_survivor_regions; 50.356 + } 50.357 + bool reached_target_length = young_list_length >= young_list_max_length; 50.358 50.359 if (in_young_gc_mode()) { 50.360 if (reached_target_length) { 50.361 @@ -2985,6 +3053,7 @@ 50.362 _collection_set = hr; 50.363 _collection_set_size++; 50.364 _collection_set_bytes_used_before += hr->used(); 50.365 + _g1->register_region_with_in_cset_fast_test(hr); 50.366 } 50.367 50.368 void
51.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Sat Jan 31 17:19:42 2009 -0800 51.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Feb 27 15:13:00 2009 -0800 51.3 @@ -49,7 +49,7 @@ 51.4 class MainBodySummary; 51.5 class PopPreambleSummary; 51.6 51.7 -class PauseSummary { 51.8 +class PauseSummary: public CHeapObj { 51.9 define_num_seq(total) 51.10 define_num_seq(other) 51.11 51.12 @@ -58,7 +58,7 @@ 51.13 virtual PopPreambleSummary* pop_preamble_summary() { return NULL; } 51.14 }; 51.15 51.16 -class MainBodySummary { 51.17 +class MainBodySummary: public CHeapObj { 51.18 define_num_seq(satb_drain) // optional 51.19 define_num_seq(parallel) // parallel only 51.20 define_num_seq(ext_root_scan) 51.21 @@ -75,7 +75,7 @@ 51.22 define_num_seq(clear_ct) // parallel only 51.23 }; 51.24 51.25 -class PopPreambleSummary { 51.26 +class PopPreambleSummary: public CHeapObj { 51.27 define_num_seq(pop_preamble) 51.28 define_num_seq(pop_update_rs) 51.29 define_num_seq(pop_scan_rs) 51.30 @@ -557,6 +557,8 @@ 51.31 return get_new_neg_prediction(_young_gc_eff_seq); 51.32 } 51.33 51.34 + double predict_survivor_regions_evac_time(); 51.35 + 51.36 // </NEW PREDICTION> 51.37 51.38 public: 51.39 @@ -599,8 +601,8 @@ 51.40 51.41 // Returns an estimate of the survival rate of the region at yg-age 51.42 // "yg_age". 51.43 - double predict_yg_surv_rate(int age) { 51.44 - TruncatedSeq* seq = _short_lived_surv_rate_group->get_seq(age); 51.45 + double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) { 51.46 + TruncatedSeq* seq = surv_rate_group->get_seq(age); 51.47 if (seq->num() == 0) 51.48 gclog_or_tty->print("BARF! age is %d", age); 51.49 guarantee( seq->num() > 0, "invariant" ); 51.50 @@ -610,6 +612,10 @@ 51.51 return pred; 51.52 } 51.53 51.54 + double predict_yg_surv_rate(int age) { 51.55 + return predict_yg_surv_rate(age, _short_lived_surv_rate_group); 51.56 + } 51.57 + 51.58 double accum_yg_surv_rate_pred(int age) { 51.59 return _short_lived_surv_rate_group->accum_surv_rate_pred(age); 51.60 } 51.61 @@ -822,6 +828,9 @@ 51.62 51.63 virtual void init(); 51.64 51.65 + // Create jstat counters for the policy. 51.66 + virtual void initialize_gc_policy_counters(); 51.67 + 51.68 virtual HeapWord* mem_allocate_work(size_t size, 51.69 bool is_tlab, 51.70 bool* gc_overhead_limit_was_exceeded); 51.71 @@ -1047,8 +1056,12 @@ 51.72 // Print stats on young survival ratio 51.73 void print_yg_surv_rate_info() const; 51.74 51.75 - void finished_recalculating_age_indexes() { 51.76 - _short_lived_surv_rate_group->finished_recalculating_age_indexes(); 51.77 + void finished_recalculating_age_indexes(bool is_survivors) { 51.78 + if (is_survivors) { 51.79 + _survivor_surv_rate_group->finished_recalculating_age_indexes(); 51.80 + } else { 51.81 + _short_lived_surv_rate_group->finished_recalculating_age_indexes(); 51.82 + } 51.83 // do that for any other surv rate groups 51.84 } 51.85 51.86 @@ -1097,6 +1110,17 @@ 51.87 // maximum amount of suvivors regions. 51.88 int _tenuring_threshold; 51.89 51.90 + // The limit on the number of regions allocated for survivors. 51.91 + size_t _max_survivor_regions; 51.92 + 51.93 + // The amount of survor regions after a collection. 51.94 + size_t _recorded_survivor_regions; 51.95 + // List of survivor regions. 51.96 + HeapRegion* _recorded_survivor_head; 51.97 + HeapRegion* _recorded_survivor_tail; 51.98 + 51.99 + ageTable _survivors_age_table; 51.100 + 51.101 public: 51.102 51.103 inline GCAllocPurpose 51.104 @@ -1116,7 +1140,9 @@ 51.105 return GCAllocForTenured; 51.106 } 51.107 51.108 - uint max_regions(int purpose); 51.109 + static const size_t REGIONS_UNLIMITED = ~(size_t)0; 51.110 + 51.111 + size_t max_regions(int purpose); 51.112 51.113 // The limit on regions for a particular purpose is reached. 51.114 void note_alloc_region_limit_reached(int purpose) { 51.115 @@ -1132,6 +1158,23 @@ 51.116 void note_stop_adding_survivor_regions() { 51.117 _survivor_surv_rate_group->stop_adding_regions(); 51.118 } 51.119 + 51.120 + void record_survivor_regions(size_t regions, 51.121 + HeapRegion* head, 51.122 + HeapRegion* tail) { 51.123 + _recorded_survivor_regions = regions; 51.124 + _recorded_survivor_head = head; 51.125 + _recorded_survivor_tail = tail; 51.126 + } 51.127 + 51.128 + void record_thread_age_table(ageTable* age_table) 51.129 + { 51.130 + _survivors_age_table.merge_par(age_table); 51.131 + } 51.132 + 51.133 + // Calculates survivor space parameters. 51.134 + void calculate_survivors_policy(); 51.135 + 51.136 }; 51.137 51.138 // This encapsulates a particular strategy for a g1 Collector.
52.1 --- a/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Sat Jan 31 17:19:42 2009 -0800 52.2 +++ b/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Fri Feb 27 15:13:00 2009 -0800 52.3 @@ -28,7 +28,7 @@ 52.4 /***** ALL TIMES ARE IN SECS!!!!!!! *****/ 52.5 52.6 // this is the "interface" 52.7 -class G1MMUTracker { 52.8 +class G1MMUTracker: public CHeapObj { 52.9 protected: 52.10 double _time_slice; 52.11 double _max_gc_time; // this is per time slice 52.12 @@ -67,7 +67,7 @@ 52.13 } 52.14 }; 52.15 52.16 -class G1MMUTrackerQueueElem { 52.17 +class G1MMUTrackerQueueElem VALUE_OBJ_CLASS_SPEC { 52.18 private: 52.19 double _start_time; 52.20 double _end_time;
53.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Sat Jan 31 17:19:42 2009 -0800 53.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Fri Feb 27 15:13:00 2009 -0800 53.3 @@ -77,6 +77,18 @@ 53.4 53.5 #define G1_PARTIAL_ARRAY_MASK 1 53.6 53.7 +inline bool has_partial_array_mask(oop* ref) { 53.8 + return (intptr_t) ref & G1_PARTIAL_ARRAY_MASK; 53.9 +} 53.10 + 53.11 +inline oop* set_partial_array_mask(oop obj) { 53.12 + return (oop*) ((intptr_t) obj | G1_PARTIAL_ARRAY_MASK); 53.13 +} 53.14 + 53.15 +inline oop clear_partial_array_mask(oop* ref) { 53.16 + return oop((intptr_t) ref & ~G1_PARTIAL_ARRAY_MASK); 53.17 +} 53.18 + 53.19 class G1ParScanPartialArrayClosure : public G1ParClosureSuper { 53.20 G1ParScanClosure _scanner; 53.21 template <class T> void process_array_chunk(oop obj, int start, int end); 53.22 @@ -101,7 +113,8 @@ 53.23 G1ParClosureSuper(g1, par_scan_state), _scanner(scanner) { } 53.24 }; 53.25 53.26 -template<bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> 53.27 +template<bool do_gen_barrier, G1Barrier barrier, 53.28 + bool do_mark_forwardee, bool skip_cset_test> 53.29 class G1ParCopyClosure : public G1ParCopyHelper { 53.30 G1ParScanClosure _scanner; 53.31 void do_oop_work(oop* p); 53.32 @@ -119,14 +132,22 @@ 53.33 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 53.34 }; 53.35 53.36 -typedef G1ParCopyClosure<false, G1BarrierNone, false> G1ParScanExtRootClosure; 53.37 -typedef G1ParCopyClosure<true, G1BarrierNone, false> G1ParScanPermClosure; 53.38 -typedef G1ParCopyClosure<false, G1BarrierNone, true> G1ParScanAndMarkExtRootClosure; 53.39 -typedef G1ParCopyClosure<true, G1BarrierNone, true> G1ParScanAndMarkPermClosure; 53.40 -typedef G1ParCopyClosure<false, G1BarrierRS, false> G1ParScanHeapRSClosure; 53.41 -typedef G1ParCopyClosure<false, G1BarrierRS, true> G1ParScanAndMarkHeapRSClosure; 53.42 -typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure; 53.43 - 53.44 +typedef G1ParCopyClosure<false, G1BarrierNone, false, false> G1ParScanExtRootClosure; 53.45 +typedef G1ParCopyClosure<true, G1BarrierNone, false, false> G1ParScanPermClosure; 53.46 +typedef G1ParCopyClosure<false, G1BarrierNone, true, false> G1ParScanAndMarkExtRootClosure; 53.47 +typedef G1ParCopyClosure<true, G1BarrierNone, true, false> G1ParScanAndMarkPermClosure; 53.48 +typedef G1ParCopyClosure<false, G1BarrierRS, false, false> G1ParScanHeapRSClosure; 53.49 +typedef G1ParCopyClosure<false, G1BarrierRS, true, false> G1ParScanAndMarkHeapRSClosure; 53.50 +// This is the only case when we set skip_cset_test. Basically, this 53.51 +// closure is (should?) only be called directly while we're draining 53.52 +// the overflow and task queues. In that case we know that the 53.53 +// reference in question points into the collection set, otherwise we 53.54 +// would not have pushed it on the queue. 53.55 +typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure; 53.56 +// We need a separate closure to handle references during evacuation 53.57 +// failure processing, as it cannot asume that the reference already 53.58 + // points to the collection set (like G1ParScanHeapEvacClosure does). 53.59 +typedef G1ParCopyClosure<false, G1BarrierEvac, false, false> G1ParScanHeapEvacFailureClosure; 53.60 53.61 class FilterIntoCSClosure: public OopClosure { 53.62 G1CollectedHeap* _g1;
54.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Sat Jan 31 17:19:42 2009 -0800 54.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Feb 27 15:13:00 2009 -0800 54.3 @@ -572,6 +572,9 @@ 54.4 } 54.5 guarantee( _cards_scanned == NULL, "invariant" ); 54.6 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers()); 54.7 + for (uint i = 0; i < n_workers(); ++i) { 54.8 + _cards_scanned[i] = 0; 54.9 + } 54.10 _total_cards_scanned = 0; 54.11 } 54.12
55.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp Sat Jan 31 17:19:42 2009 -0800 55.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Feb 27 15:13:00 2009 -0800 55.3 @@ -30,7 +30,7 @@ 55.4 class HRInto_G1RemSet; 55.5 class ConcurrentG1Refine; 55.6 55.7 -class G1RemSet { 55.8 +class G1RemSet: public CHeapObj { 55.9 protected: 55.10 G1CollectedHeap* _g1; 55.11
56.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Sat Jan 31 17:19:42 2009 -0800 56.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Feb 27 15:13:00 2009 -0800 56.3 @@ -28,7 +28,7 @@ 56.4 56.5 #define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \ 56.6 \ 56.7 - product(intx, ParallelGCG1AllocBufferSize, 4*K, \ 56.8 + product(intx, ParallelGCG1AllocBufferSize, 8*K, \ 56.9 "Size of parallel G1 allocation buffers in to-space.") \ 56.10 \ 56.11 product(intx, G1TimeSliceMS, 500, \ 56.12 @@ -281,7 +281,17 @@ 56.13 develop(bool, G1HRRSFlushLogBuffersOnVerify, false, \ 56.14 "Forces flushing of log buffers before verification.") \ 56.15 \ 56.16 - product(intx, G1MaxSurvivorRegions, 0, \ 56.17 - "The maximum number of survivor regions") 56.18 + product(bool, G1UseSurvivorSpace, true, \ 56.19 + "When true, use survivor space.") \ 56.20 + \ 56.21 + product(bool, G1FixedTenuringThreshold, false, \ 56.22 + "When set, G1 will not adjust the tenuring threshold") \ 56.23 + \ 56.24 + product(bool, G1FixedEdenSize, false, \ 56.25 + "When set, G1 will not allocate unused survivor space regions") \ 56.26 + \ 56.27 + product(uintx, G1FixedSurvivorSpaceSize, 0, \ 56.28 + "If non-0 is the size of the G1 survivor space, " \ 56.29 + "otherwise SurvivorRatio is used to determine the size") 56.30 56.31 G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
57.1 --- a/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Sat Jan 31 17:19:42 2009 -0800 57.2 +++ b/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Fri Feb 27 15:13:00 2009 -0800 57.3 @@ -32,11 +32,13 @@ 57.4 G1BarrierNone, G1BarrierRS, G1BarrierEvac 57.5 }; 57.6 57.7 -template<bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> 57.8 +template<bool do_gen_barrier, G1Barrier barrier, 57.9 + bool do_mark_forwardee, bool skip_cset_test> 57.10 class G1ParCopyClosure; 57.11 class G1ParScanClosure; 57.12 57.13 -typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure; 57.14 +typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> 57.15 + G1ParScanHeapEvacClosure; 57.16 57.17 class FilterIntoCSClosure; 57.18 class FilterOutOfRegionClosure;
58.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Sat Jan 31 17:19:42 2009 -0800 58.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Feb 27 15:13:00 2009 -0800 58.3 @@ -566,7 +566,11 @@ 58.4 void note_end_of_copying() { 58.5 assert(top() >= _next_top_at_mark_start, 58.6 "Increase only"); 58.7 - _next_top_at_mark_start = top(); 58.8 + // Survivor regions will be scanned on the start of concurrent 58.9 + // marking. 58.10 + if (!is_survivor()) { 58.11 + _next_top_at_mark_start = top(); 58.12 + } 58.13 } 58.14 58.15 // Returns "false" iff no object in the region was allocated when the 58.16 @@ -829,7 +833,7 @@ 58.17 58.18 // A linked lists of heap regions. It leaves the "next" field 58.19 // unspecified; that's up to subtypes. 58.20 -class RegionList { 58.21 +class RegionList VALUE_OBJ_CLASS_SPEC { 58.22 protected: 58.23 virtual HeapRegion* get_next(HeapRegion* chr) = 0; 58.24 virtual void set_next(HeapRegion* chr,
59.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Sat Jan 31 17:19:42 2009 -0800 59.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Feb 27 15:13:00 2009 -0800 59.3 @@ -65,9 +65,11 @@ 59.4 // We need access in order to union things into the base table. 59.5 BitMap* bm() { return &_bm; } 59.6 59.7 +#if PRT_COUNT_OCCUPIED 59.8 void recount_occupied() { 59.9 _occupied = (jint) bm()->count_one_bits(); 59.10 } 59.11 +#endif 59.12 59.13 PerRegionTable(HeapRegion* hr) : 59.14 _hr(hr), 59.15 @@ -1144,7 +1146,9 @@ 59.16 size_t i = _outgoing_region_map.get_next_one_offset(0); 59.17 while (i < _outgoing_region_map.size()) { 59.18 HeapRegion* to_region = g1h->region_at(i); 59.19 - to_region->rem_set()->clear_incoming_entry(hr()); 59.20 + if (!to_region->in_collection_set()) { 59.21 + to_region->rem_set()->clear_incoming_entry(hr()); 59.22 + } 59.23 i = _outgoing_region_map.get_next_one_offset(i+1); 59.24 } 59.25 }
60.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Sat Jan 31 17:19:42 2009 -0800 60.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Fri Feb 27 15:13:00 2009 -0800 60.3 @@ -58,7 +58,7 @@ 60.4 // is represented. If a deleted PRT is re-used, a thread adding a bit, 60.5 // thinking the PRT is for a different region, does no harm. 60.6 60.7 -class OtherRegionsTable: public CHeapObj { 60.8 +class OtherRegionsTable VALUE_OBJ_CLASS_SPEC { 60.9 friend class HeapRegionRemSetIterator; 60.10 60.11 G1CollectedHeap* _g1h;
61.1 --- a/src/share/vm/gc_implementation/g1/ptrQueue.hpp Sat Jan 31 17:19:42 2009 -0800 61.2 +++ b/src/share/vm/gc_implementation/g1/ptrQueue.hpp Fri Feb 27 15:13:00 2009 -0800 61.3 @@ -29,7 +29,7 @@ 61.4 61.5 class PtrQueueSet; 61.6 61.7 -class PtrQueue: public CHeapObj { 61.8 +class PtrQueue VALUE_OBJ_CLASS_SPEC { 61.9 61.10 protected: 61.11 // The ptr queue set to which this queue belongs. 61.12 @@ -130,7 +130,7 @@ 61.13 // In particular, the individual queues allocate buffers from this shared 61.14 // set, and return completed buffers to the set. 61.15 // All these variables are are protected by the TLOQ_CBL_mon. XXX ??? 61.16 -class PtrQueueSet: public CHeapObj { 61.17 +class PtrQueueSet VALUE_OBJ_CLASS_SPEC { 61.18 61.19 protected: 61.20
62.1 --- a/src/share/vm/gc_implementation/g1/sparsePRT.hpp Sat Jan 31 17:19:42 2009 -0800 62.2 +++ b/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri Feb 27 15:13:00 2009 -0800 62.3 @@ -33,7 +33,7 @@ 62.4 // old versions synchronously. 62.5 62.6 62.7 -class SparsePRTEntry { 62.8 +class SparsePRTEntry: public CHeapObj { 62.9 public: 62.10 enum SomePublicConstants { 62.11 CardsPerEntry = (short)4, 62.12 @@ -167,7 +167,7 @@ 62.13 }; 62.14 62.15 // ValueObj because will be embedded in HRRS iterator. 62.16 -class RSHashTableIter: public CHeapObj { 62.17 +class RSHashTableIter VALUE_OBJ_CLASS_SPEC { 62.18 short _tbl_ind; 62.19 short _bl_ind; 62.20 short _card_ind; 62.21 @@ -213,7 +213,7 @@ 62.22 62.23 class SparsePRTIter; 62.24 62.25 -class SparsePRT : public CHeapObj { 62.26 +class SparsePRT VALUE_OBJ_CLASS_SPEC { 62.27 // Iterations are done on the _cur hash table, since they only need to 62.28 // see entries visible at the start of a collection pause. 62.29 // All other operations are done using the _next hash table.
63.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.cpp Sat Jan 31 17:19:42 2009 -0800 63.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.cpp Fri Feb 27 15:13:00 2009 -0800 63.3 @@ -29,23 +29,14 @@ 63.4 const char* name, 63.5 size_t summary_surv_rates_len) : 63.6 _g1p(g1p), _name(name), 63.7 - _all_regions_allocated(0), 63.8 - _curr_length(0), _scan_only_prefix(0), _setup_seq_num(0), 63.9 - _array_length(0), _surv_rate(NULL), _accum_surv_rate_pred(NULL), 63.10 - _accum_surv_rate(0.0), _surv_rate_pred(NULL), _last_pred(0.0), 63.11 _summary_surv_rates_len(summary_surv_rates_len), 63.12 _summary_surv_rates_max_len(0), 63.13 - _summary_surv_rates(NULL) { 63.14 - 63.15 - // the following will set up the arrays with length 1 63.16 - _curr_length = 1; 63.17 - stop_adding_regions(); 63.18 - guarantee( _array_length == 1, "invariant" ); 63.19 - guarantee( _surv_rate_pred[0] != NULL, "invariant" ); 63.20 - _surv_rate_pred[0]->add(0.4); 63.21 - all_surviving_words_recorded(false); 63.22 - _curr_length = 0; 63.23 - 63.24 + _summary_surv_rates(NULL), 63.25 + _surv_rate(NULL), 63.26 + _accum_surv_rate_pred(NULL), 63.27 + _surv_rate_pred(NULL) 63.28 +{ 63.29 + reset(); 63.30 if (summary_surv_rates_len > 0) { 63.31 size_t length = summary_surv_rates_len; 63.32 _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length); 63.33 @@ -60,61 +51,80 @@ 63.34 start_adding_regions(); 63.35 } 63.36 63.37 + 63.38 +void SurvRateGroup::reset() 63.39 +{ 63.40 + _all_regions_allocated = 0; 63.41 + _scan_only_prefix = 0; 63.42 + _setup_seq_num = 0; 63.43 + _stats_arrays_length = 0; 63.44 + _accum_surv_rate = 0.0; 63.45 + _last_pred = 0.0; 63.46 + // the following will set up the arrays with length 1 63.47 + _region_num = 1; 63.48 + stop_adding_regions(); 63.49 + guarantee( _stats_arrays_length == 1, "invariant" ); 63.50 + guarantee( _surv_rate_pred[0] != NULL, "invariant" ); 63.51 + _surv_rate_pred[0]->add(0.4); 63.52 + all_surviving_words_recorded(false); 63.53 + _region_num = 0; 63.54 +} 63.55 + 63.56 + 63.57 void 63.58 SurvRateGroup::start_adding_regions() { 63.59 - _setup_seq_num = _array_length; 63.60 - _curr_length = _scan_only_prefix; 63.61 + _setup_seq_num = _stats_arrays_length; 63.62 + _region_num = _scan_only_prefix; 63.63 _accum_surv_rate = 0.0; 63.64 63.65 #if 0 63.66 - gclog_or_tty->print_cr("start adding regions, seq num %d, length %d", 63.67 - _setup_seq_num, _curr_length); 63.68 + gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d", 63.69 + _name, _setup_seq_num, _region_num); 63.70 #endif // 0 63.71 } 63.72 63.73 void 63.74 SurvRateGroup::stop_adding_regions() { 63.75 - size_t length = _curr_length; 63.76 63.77 #if 0 63.78 - gclog_or_tty->print_cr("stop adding regions, length %d", length); 63.79 + gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num); 63.80 #endif // 0 63.81 63.82 - if (length > _array_length) { 63.83 + if (_region_num > _stats_arrays_length) { 63.84 double* old_surv_rate = _surv_rate; 63.85 double* old_accum_surv_rate_pred = _accum_surv_rate_pred; 63.86 TruncatedSeq** old_surv_rate_pred = _surv_rate_pred; 63.87 63.88 - _surv_rate = NEW_C_HEAP_ARRAY(double, length); 63.89 + _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num); 63.90 if (_surv_rate == NULL) { 63.91 - vm_exit_out_of_memory(sizeof(double) * length, 63.92 + vm_exit_out_of_memory(sizeof(double) * _region_num, 63.93 "Not enough space for surv rate array."); 63.94 } 63.95 - _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, length); 63.96 + _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num); 63.97 if (_accum_surv_rate_pred == NULL) { 63.98 - vm_exit_out_of_memory(sizeof(double) * length, 63.99 + vm_exit_out_of_memory(sizeof(double) * _region_num, 63.100 "Not enough space for accum surv rate pred array."); 63.101 } 63.102 - _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, length); 63.103 + _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num); 63.104 if (_surv_rate == NULL) { 63.105 - vm_exit_out_of_memory(sizeof(TruncatedSeq*) * length, 63.106 + vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num, 63.107 "Not enough space for surv rate pred array."); 63.108 } 63.109 63.110 - for (size_t i = 0; i < _array_length; ++i) 63.111 + for (size_t i = 0; i < _stats_arrays_length; ++i) 63.112 _surv_rate_pred[i] = old_surv_rate_pred[i]; 63.113 63.114 #if 0 63.115 - gclog_or_tty->print_cr("stop adding regions, new seqs %d to %d", 63.116 - _array_length, length - 1); 63.117 + gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d", 63.118 + _name, _array_length, _region_num - 1); 63.119 #endif // 0 63.120 63.121 - for (size_t i = _array_length; i < length; ++i) { 63.122 + for (size_t i = _stats_arrays_length; i < _region_num; ++i) { 63.123 _surv_rate_pred[i] = new TruncatedSeq(10); 63.124 // _surv_rate_pred[i]->add(last_pred); 63.125 } 63.126 63.127 - _array_length = length; 63.128 + _stats_arrays_length = _region_num; 63.129 63.130 if (old_surv_rate != NULL) 63.131 FREE_C_HEAP_ARRAY(double, old_surv_rate); 63.132 @@ -124,7 +134,7 @@ 63.133 FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred); 63.134 } 63.135 63.136 - for (size_t i = 0; i < _array_length; ++i) 63.137 + for (size_t i = 0; i < _stats_arrays_length; ++i) 63.138 _surv_rate[i] = 0.0; 63.139 } 63.140 63.141 @@ -135,7 +145,7 @@ 63.142 63.143 double ret = _accum_surv_rate; 63.144 if (adjustment > 0) { 63.145 - TruncatedSeq* seq = get_seq(_curr_length+1); 63.146 + TruncatedSeq* seq = get_seq(_region_num+1); 63.147 double surv_rate = _g1p->get_new_prediction(seq); 63.148 ret += surv_rate; 63.149 } 63.150 @@ -145,23 +155,23 @@ 63.151 63.152 int 63.153 SurvRateGroup::next_age_index() { 63.154 - TruncatedSeq* seq = get_seq(_curr_length); 63.155 + TruncatedSeq* seq = get_seq(_region_num); 63.156 double surv_rate = _g1p->get_new_prediction(seq); 63.157 _accum_surv_rate += surv_rate; 63.158 63.159 - ++_curr_length; 63.160 + ++_region_num; 63.161 return (int) ++_all_regions_allocated; 63.162 } 63.163 63.164 void 63.165 SurvRateGroup::record_scan_only_prefix(size_t scan_only_prefix) { 63.166 - guarantee( scan_only_prefix <= _curr_length, "pre-condition" ); 63.167 + guarantee( scan_only_prefix <= _region_num, "pre-condition" ); 63.168 _scan_only_prefix = scan_only_prefix; 63.169 } 63.170 63.171 void 63.172 SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { 63.173 - guarantee( 0 <= age_in_group && (size_t) age_in_group < _curr_length, 63.174 + guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num, 63.175 "pre-condition" ); 63.176 guarantee( _surv_rate[age_in_group] <= 0.00001, 63.177 "should only update each slot once" ); 63.178 @@ -178,15 +188,15 @@ 63.179 63.180 void 63.181 SurvRateGroup::all_surviving_words_recorded(bool propagate) { 63.182 - if (propagate && _curr_length > 0) { // conservative 63.183 - double surv_rate = _surv_rate_pred[_curr_length-1]->last(); 63.184 + if (propagate && _region_num > 0) { // conservative 63.185 + double surv_rate = _surv_rate_pred[_region_num-1]->last(); 63.186 63.187 #if 0 63.188 gclog_or_tty->print_cr("propagating %1.2lf from %d to %d", 63.189 surv_rate, _curr_length, _array_length - 1); 63.190 #endif // 0 63.191 63.192 - for (size_t i = _curr_length; i < _array_length; ++i) { 63.193 + for (size_t i = _region_num; i < _stats_arrays_length; ++i) { 63.194 guarantee( _surv_rate[i] <= 0.00001, 63.195 "the slot should not have been updated" ); 63.196 _surv_rate_pred[i]->add(surv_rate); 63.197 @@ -195,7 +205,7 @@ 63.198 63.199 double accum = 0.0; 63.200 double pred = 0.0; 63.201 - for (size_t i = 0; i < _array_length; ++i) { 63.202 + for (size_t i = 0; i < _stats_arrays_length; ++i) { 63.203 pred = _g1p->get_new_prediction(_surv_rate_pred[i]); 63.204 if (pred > 1.0) pred = 1.0; 63.205 accum += pred; 63.206 @@ -209,8 +219,8 @@ 63.207 void 63.208 SurvRateGroup::print() { 63.209 gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries, %d scan-only)", 63.210 - _name, _curr_length, _scan_only_prefix); 63.211 - for (size_t i = 0; i < _curr_length; ++i) { 63.212 + _name, _region_num, _scan_only_prefix); 63.213 + for (size_t i = 0; i < _region_num; ++i) { 63.214 gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%%s", 63.215 i, _surv_rate[i] * 100.0, 63.216 _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0,
64.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.hpp Sat Jan 31 17:19:42 2009 -0800 64.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.hpp Fri Feb 27 15:13:00 2009 -0800 64.3 @@ -29,7 +29,7 @@ 64.4 G1CollectorPolicy* _g1p; 64.5 const char* _name; 64.6 64.7 - size_t _array_length; 64.8 + size_t _stats_arrays_length; 64.9 double* _surv_rate; 64.10 double* _accum_surv_rate_pred; 64.11 double _last_pred; 64.12 @@ -40,7 +40,7 @@ 64.13 size_t _summary_surv_rates_max_len; 64.14 64.15 int _all_regions_allocated; 64.16 - size_t _curr_length; 64.17 + size_t _region_num; 64.18 size_t _scan_only_prefix; 64.19 size_t _setup_seq_num; 64.20 64.21 @@ -48,6 +48,7 @@ 64.22 SurvRateGroup(G1CollectorPolicy* g1p, 64.23 const char* name, 64.24 size_t summary_surv_rates_len); 64.25 + void reset(); 64.26 void start_adding_regions(); 64.27 void stop_adding_regions(); 64.28 void record_scan_only_prefix(size_t scan_only_prefix); 64.29 @@ -55,22 +56,21 @@ 64.30 void all_surviving_words_recorded(bool propagate); 64.31 const char* name() { return _name; } 64.32 64.33 - size_t region_num() { return _curr_length; } 64.34 + size_t region_num() { return _region_num; } 64.35 size_t scan_only_length() { return _scan_only_prefix; } 64.36 double accum_surv_rate_pred(int age) { 64.37 assert(age >= 0, "must be"); 64.38 - if ((size_t)age < _array_length) 64.39 + if ((size_t)age < _stats_arrays_length) 64.40 return _accum_surv_rate_pred[age]; 64.41 else { 64.42 - double diff = (double) (age - _array_length + 1); 64.43 - return _accum_surv_rate_pred[_array_length-1] + diff * _last_pred; 64.44 + double diff = (double) (age - _stats_arrays_length + 1); 64.45 + return _accum_surv_rate_pred[_stats_arrays_length-1] + diff * _last_pred; 64.46 } 64.47 } 64.48 64.49 double accum_surv_rate(size_t adjustment); 64.50 64.51 TruncatedSeq* get_seq(size_t age) { 64.52 - guarantee( 0 <= age, "pre-condition" ); 64.53 if (age >= _setup_seq_num) { 64.54 guarantee( _setup_seq_num > 0, "invariant" ); 64.55 age = _setup_seq_num-1;
65.1 --- a/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep Sat Jan 31 17:19:42 2009 -0800 65.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep Fri Feb 27 15:13:00 2009 -0800 65.3 @@ -28,6 +28,7 @@ 65.4 binaryTreeDictionary.cpp binaryTreeDictionary.hpp 65.5 binaryTreeDictionary.cpp globals.hpp 65.6 binaryTreeDictionary.cpp ostream.hpp 65.7 +binaryTreeDictionary.cpp space.inline.hpp 65.8 binaryTreeDictionary.cpp spaceDecorator.hpp 65.9 65.10 binaryTreeDictionary.hpp freeBlockDictionary.hpp
66.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1 Sat Jan 31 17:19:42 2009 -0800 66.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1 Fri Feb 27 15:13:00 2009 -0800 66.3 @@ -31,9 +31,10 @@ 66.4 cardTableRS.cpp concurrentMark.hpp 66.5 cardTableRS.cpp g1SATBCardTableModRefBS.hpp 66.6 66.7 -collectionSetChooser.cpp g1CollectedHeap.hpp 66.8 +collectionSetChooser.cpp g1CollectedHeap.inline.hpp 66.9 collectionSetChooser.cpp g1CollectorPolicy.hpp 66.10 collectionSetChooser.cpp collectionSetChooser.hpp 66.11 +collectionSetChooser.cpp space.inline.hpp 66.12 66.13 collectionSetChooser.hpp heapRegion.hpp 66.14 collectionSetChooser.hpp growableArray.hpp 66.15 @@ -42,14 +43,16 @@ 66.16 concurrentG1Refine.cpp concurrentG1Refine.hpp 66.17 concurrentG1Refine.cpp concurrentG1RefineThread.hpp 66.18 concurrentG1Refine.cpp copy.hpp 66.19 -concurrentG1Refine.cpp g1CollectedHeap.hpp 66.20 +concurrentG1Refine.cpp g1CollectedHeap.inline.hpp 66.21 concurrentG1Refine.cpp g1RemSet.hpp 66.22 +concurrentG1Refine.cpp space.inline.hpp 66.23 66.24 concurrentG1Refine.hpp globalDefinitions.hpp 66.25 +concurrentG1Refine.hpp allocation.hpp 66.26 66.27 concurrentG1RefineThread.cpp concurrentG1Refine.hpp 66.28 concurrentG1RefineThread.cpp concurrentG1RefineThread.hpp 66.29 -concurrentG1RefineThread.cpp g1CollectedHeap.hpp 66.30 +concurrentG1RefineThread.cpp g1CollectedHeap.inline.hpp 66.31 concurrentG1RefineThread.cpp g1CollectorPolicy.hpp 66.32 concurrentG1RefineThread.cpp handles.inline.hpp 66.33 concurrentG1RefineThread.cpp mutexLocker.hpp 66.34 @@ -166,10 +169,11 @@ 66.35 g1CollectorPolicy.cpp concurrentMarkThread.inline.hpp 66.36 g1CollectorPolicy.cpp debug.hpp 66.37 g1CollectorPolicy.cpp java.hpp 66.38 -g1CollectorPolicy.cpp g1CollectedHeap.hpp 66.39 +g1CollectorPolicy.cpp g1CollectedHeap.inline.hpp 66.40 g1CollectorPolicy.cpp g1CollectorPolicy.hpp 66.41 g1CollectorPolicy.cpp heapRegionRemSet.hpp 66.42 g1CollectorPolicy.cpp mutexLocker.hpp 66.43 +g1CollectorPolicy.cpp gcPolicyCounters.hpp 66.44 66.45 g1CollectorPolicy.hpp collectorPolicy.hpp 66.46 g1CollectorPolicy.hpp collectionSetChooser.hpp 66.47 @@ -187,7 +191,7 @@ 66.48 g1MarkSweep.cpp codeCache.hpp 66.49 g1MarkSweep.cpp events.hpp 66.50 g1MarkSweep.cpp fprofiler.hpp 66.51 -g1MarkSweep.hpp g1CollectedHeap.hpp 66.52 +g1MarkSweep.hpp g1CollectedHeap.inline.hpp 66.53 g1MarkSweep.cpp g1MarkSweep.hpp 66.54 g1MarkSweep.cpp gcLocker.hpp 66.55 g1MarkSweep.cpp genCollectedHeap.hpp 66.56 @@ -226,7 +230,7 @@ 66.57 g1MMUTracker.cpp mutexLocker.hpp 66.58 66.59 g1MMUTracker.hpp debug.hpp 66.60 - 66.61 +g1MMUTracker.hpp allocation.hpp 66.62 g1RemSet.cpp bufferingOopClosure.hpp 66.63 g1RemSet.cpp concurrentG1Refine.hpp 66.64 g1RemSet.cpp concurrentG1RefineThread.hpp 66.65 @@ -264,12 +268,13 @@ 66.66 heapRegion.cpp iterator.hpp 66.67 heapRegion.cpp oop.inline.hpp 66.68 66.69 -heapRegion.hpp space.hpp 66.70 +heapRegion.hpp space.inline.hpp 66.71 heapRegion.hpp spaceDecorator.hpp 66.72 heapRegion.hpp g1BlockOffsetTable.inline.hpp 66.73 heapRegion.hpp watermark.hpp 66.74 heapRegion.hpp g1_specialized_oop_closures.hpp 66.75 heapRegion.hpp survRateGroup.hpp 66.76 +heapRegion.hpp ageTable.hpp 66.77 66.78 heapRegionRemSet.hpp sparsePRT.hpp 66.79 66.80 @@ -283,7 +288,7 @@ 66.81 heapRegionRemSet.cpp space.inline.hpp 66.82 66.83 heapRegionSeq.cpp allocation.hpp 66.84 -heapRegionSeq.cpp g1CollectedHeap.hpp 66.85 +heapRegionSeq.cpp g1CollectedHeap.inline.hpp 66.86 heapRegionSeq.cpp heapRegionSeq.hpp 66.87 66.88 heapRegionSeq.hpp growableArray.hpp 66.89 @@ -334,18 +339,18 @@ 66.90 survRateGroup.hpp numberSeq.hpp 66.91 66.92 survRateGroup.cpp allocation.hpp 66.93 -survRateGroup.cpp g1CollectedHeap.hpp 66.94 +survRateGroup.cpp g1CollectedHeap.inline.hpp 66.95 survRateGroup.cpp g1CollectorPolicy.hpp 66.96 survRateGroup.cpp heapRegion.hpp 66.97 survRateGroup.cpp survRateGroup.hpp 66.98 66.99 thread.cpp concurrentMarkThread.inline.hpp 66.100 66.101 -universe.cpp g1CollectedHeap.hpp 66.102 +universe.cpp g1CollectedHeap.inline.hpp 66.103 universe.cpp g1CollectorPolicy.hpp 66.104 66.105 vm_operations_g1.hpp vmGCOperations.hpp 66.106 66.107 vm_operations_g1.cpp vm_operations_g1.hpp 66.108 -vm_operations_g1.cpp g1CollectedHeap.hpp 66.109 +vm_operations_g1.cpp g1CollectedHeap.inline.hpp 66.110 vm_operations_g1.cpp isGCActiveMark.hpp
67.1 --- a/src/share/vm/gc_implementation/includeDB_gc_parNew Sat Jan 31 17:19:42 2009 -0800 67.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_parNew Fri Feb 27 15:13:00 2009 -0800 67.3 @@ -29,6 +29,8 @@ 67.4 asParNewGeneration.cpp cmsAdaptiveSizePolicy.hpp 67.5 asParNewGeneration.cpp cmsGCAdaptivePolicyCounters.hpp 67.6 asParNewGeneration.cpp defNewGeneration.inline.hpp 67.7 +asParNewGeneration.cpp markOop.inline.hpp 67.8 +asParNewGeneration.cpp markSweep.inline.hpp 67.9 asParNewGeneration.cpp oop.pcgc.inline.hpp 67.10 asParNewGeneration.cpp parNewGeneration.hpp 67.11 asParNewGeneration.cpp referencePolicy.hpp 67.12 @@ -40,7 +42,7 @@ 67.13 parCardTableModRefBS.cpp java.hpp 67.14 parCardTableModRefBS.cpp mutexLocker.hpp 67.15 parCardTableModRefBS.cpp sharedHeap.hpp 67.16 -parCardTableModRefBS.cpp space.hpp 67.17 +parCardTableModRefBS.cpp space.inline.hpp 67.18 parCardTableModRefBS.cpp universe.hpp 67.19 parCardTableModRefBS.cpp virtualspace.hpp 67.20 67.21 @@ -77,6 +79,7 @@ 67.22 parNewGeneration.cpp sharedHeap.hpp 67.23 parNewGeneration.cpp space.hpp 67.24 parNewGeneration.cpp spaceDecorator.hpp 67.25 +parNewGeneration.cpp thread.hpp 67.26 parNewGeneration.cpp workgroup.hpp 67.27 67.28 parNewGeneration.hpp defNewGeneration.hpp
68.1 --- a/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Sat Jan 31 17:19:42 2009 -0800 68.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Fri Feb 27 15:13:00 2009 -0800 68.3 @@ -302,6 +302,8 @@ 68.4 psOldGen.hpp spaceCounters.hpp 68.5 68.6 psPermGen.cpp gcUtil.hpp 68.7 +psPermGen.cpp markOop.inline.hpp 68.8 +psPermGen.cpp markSweep.inline.hpp 68.9 psPermGen.cpp parallelScavengeHeap.hpp 68.10 psPermGen.cpp psMarkSweepDecorator.hpp 68.11 psPermGen.cpp psParallelCompact.hpp
69.1 --- a/src/share/vm/gc_implementation/includeDB_gc_shared Sat Jan 31 17:19:42 2009 -0800 69.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_shared Fri Feb 27 15:13:00 2009 -0800 69.3 @@ -100,4 +100,4 @@ 69.4 spaceCounters.hpp perfData.hpp 69.5 spaceCounters.hpp generationCounters.hpp 69.6 69.7 -vmGCOperations.cpp g1CollectedHeap.hpp 69.8 +vmGCOperations.cpp g1CollectedHeap.inline.hpp
70.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Sat Jan 31 17:19:42 2009 -0800 70.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Feb 27 15:13:00 2009 -0800 70.3 @@ -404,6 +404,8 @@ 70.4 if (terminator()->offer_termination()) break; 70.5 par_scan_state()->end_term_time(); 70.6 } 70.7 + assert(par_gen()->_overflow_list == NULL && par_gen()->_num_par_pushes == 0, 70.8 + "Broken overflow list?"); 70.9 // Finish the last termination pause. 70.10 par_scan_state()->end_term_time(); 70.11 } 70.12 @@ -456,6 +458,8 @@ 70.13 _is_alive_closure(this), 70.14 _plab_stats(YoungPLABSize, PLABWeight) 70.15 { 70.16 + NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) 70.17 + NOT_PRODUCT(_num_par_pushes = 0;) 70.18 _task_queues = new ObjToScanQueueSet(ParallelGCThreads); 70.19 guarantee(_task_queues != NULL, "task_queues allocation failure."); 70.20 70.21 @@ -993,12 +997,19 @@ 70.22 "push forwarded object"); 70.23 } 70.24 // Push it on one of the queues of to-be-scanned objects. 70.25 - if (!par_scan_state->work_queue()->push(obj_to_push)) { 70.26 + bool simulate_overflow = false; 70.27 + NOT_PRODUCT( 70.28 + if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) { 70.29 + // simulate a stack overflow 70.30 + simulate_overflow = true; 70.31 + } 70.32 + ) 70.33 + if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) { 70.34 // Add stats for overflow pushes. 70.35 if (Verbose && PrintGCDetails) { 70.36 gclog_or_tty->print("queue overflow!\n"); 70.37 } 70.38 - push_on_overflow_list(old); 70.39 + push_on_overflow_list(old, par_scan_state); 70.40 par_scan_state->note_overflow_push(); 70.41 } 70.42 par_scan_state->note_push(); 70.43 @@ -1110,9 +1121,16 @@ 70.44 "push forwarded object"); 70.45 } 70.46 // Push it on one of the queues of to-be-scanned objects. 70.47 - if (!par_scan_state->work_queue()->push(obj_to_push)) { 70.48 + bool simulate_overflow = false; 70.49 + NOT_PRODUCT( 70.50 + if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) { 70.51 + // simulate a stack overflow 70.52 + simulate_overflow = true; 70.53 + } 70.54 + ) 70.55 + if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) { 70.56 // Add stats for overflow pushes. 70.57 - push_on_overflow_list(old); 70.58 + push_on_overflow_list(old, par_scan_state); 70.59 par_scan_state->note_overflow_push(); 70.60 } 70.61 par_scan_state->note_push(); 70.62 @@ -1135,89 +1153,190 @@ 70.63 return forward_ptr; 70.64 } 70.65 70.66 -void ParNewGeneration::push_on_overflow_list(oop from_space_obj) { 70.67 - oop cur_overflow_list = _overflow_list; 70.68 +#ifndef PRODUCT 70.69 +// It's OK to call this multi-threaded; the worst thing 70.70 +// that can happen is that we'll get a bunch of closely 70.71 +// spaced simulated oveflows, but that's OK, in fact 70.72 +// probably good as it would exercise the overflow code 70.73 +// under contention. 70.74 +bool ParNewGeneration::should_simulate_overflow() { 70.75 + if (_overflow_counter-- <= 0) { // just being defensive 70.76 + _overflow_counter = ParGCWorkQueueOverflowInterval; 70.77 + return true; 70.78 + } else { 70.79 + return false; 70.80 + } 70.81 +} 70.82 +#endif 70.83 + 70.84 +#define BUSY (oop(0x1aff1aff)) 70.85 +void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) { 70.86 // if the object has been forwarded to itself, then we cannot 70.87 // use the klass pointer for the linked list. Instead we have 70.88 // to allocate an oopDesc in the C-Heap and use that for the linked list. 70.89 + // XXX This is horribly inefficient when a promotion failure occurs 70.90 + // and should be fixed. XXX FIX ME !!! 70.91 +#ifndef PRODUCT 70.92 + Atomic::inc_ptr(&_num_par_pushes); 70.93 + assert(_num_par_pushes > 0, "Tautology"); 70.94 +#endif 70.95 if (from_space_obj->forwardee() == from_space_obj) { 70.96 oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1); 70.97 listhead->forward_to(from_space_obj); 70.98 from_space_obj = listhead; 70.99 } 70.100 - while (true) { 70.101 - from_space_obj->set_klass_to_list_ptr(cur_overflow_list); 70.102 - oop observed_overflow_list = 70.103 + oop observed_overflow_list = _overflow_list; 70.104 + oop cur_overflow_list; 70.105 + do { 70.106 + cur_overflow_list = observed_overflow_list; 70.107 + if (cur_overflow_list != BUSY) { 70.108 + from_space_obj->set_klass_to_list_ptr(cur_overflow_list); 70.109 + } else { 70.110 + from_space_obj->set_klass_to_list_ptr(NULL); 70.111 + } 70.112 + observed_overflow_list = 70.113 (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list); 70.114 - if (observed_overflow_list == cur_overflow_list) break; 70.115 - // Otherwise... 70.116 - cur_overflow_list = observed_overflow_list; 70.117 - } 70.118 + } while (cur_overflow_list != observed_overflow_list); 70.119 } 70.120 70.121 +// *NOTE*: The overflow list manipulation code here and 70.122 +// in CMSCollector:: are very similar in shape, 70.123 +// except that in the CMS case we thread the objects 70.124 +// directly into the list via their mark word, and do 70.125 +// not need to deal with special cases below related 70.126 +// to chunking of object arrays and promotion failure 70.127 +// handling. 70.128 +// CR 6797058 has been filed to attempt consolidation of 70.129 +// the common code. 70.130 +// Because of the common code, if you make any changes in 70.131 +// the code below, please check the CMS version to see if 70.132 +// similar changes might be needed. 70.133 +// See CMSCollector::par_take_from_overflow_list() for 70.134 +// more extensive documentation comments. 70.135 bool 70.136 ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) { 70.137 ObjToScanQueue* work_q = par_scan_state->work_queue(); 70.138 + assert(work_q->size() == 0, "Should first empty local work queue"); 70.139 // How many to take? 70.140 - int objsFromOverflow = MIN2(work_q->max_elems()/4, 70.141 - (juint)ParGCDesiredObjsFromOverflowList); 70.142 + size_t objsFromOverflow = MIN2((size_t)work_q->max_elems()/4, 70.143 + (size_t)ParGCDesiredObjsFromOverflowList); 70.144 70.145 if (_overflow_list == NULL) return false; 70.146 70.147 // Otherwise, there was something there; try claiming the list. 70.148 - oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list); 70.149 - 70.150 - if (prefix == NULL) { 70.151 - return false; 70.152 + oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); 70.153 + // Trim off a prefix of at most objsFromOverflow items 70.154 + Thread* tid = Thread::current(); 70.155 + size_t spin_count = (size_t)ParallelGCThreads; 70.156 + size_t sleep_time_millis = MAX2((size_t)1, objsFromOverflow/100); 70.157 + for (size_t spin = 0; prefix == BUSY && spin < spin_count; spin++) { 70.158 + // someone grabbed it before we did ... 70.159 + // ... we spin for a short while... 70.160 + os::sleep(tid, sleep_time_millis, false); 70.161 + if (_overflow_list == NULL) { 70.162 + // nothing left to take 70.163 + return false; 70.164 + } else if (_overflow_list != BUSY) { 70.165 + // try and grab the prefix 70.166 + prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); 70.167 + } 70.168 } 70.169 - // Trim off a prefix of at most objsFromOverflow items 70.170 - int i = 1; 70.171 + if (prefix == NULL || prefix == BUSY) { 70.172 + // Nothing to take or waited long enough 70.173 + if (prefix == NULL) { 70.174 + // Write back the NULL in case we overwrote it with BUSY above 70.175 + // and it is still the same value. 70.176 + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); 70.177 + } 70.178 + return false; 70.179 + } 70.180 + assert(prefix != NULL && prefix != BUSY, "Error"); 70.181 + size_t i = 1; 70.182 oop cur = prefix; 70.183 while (i < objsFromOverflow && cur->klass_or_null() != NULL) { 70.184 i++; cur = oop(cur->klass()); 70.185 } 70.186 70.187 // Reattach remaining (suffix) to overflow list 70.188 - if (cur->klass_or_null() != NULL) { 70.189 - oop suffix = oop(cur->klass()); 70.190 - cur->set_klass_to_list_ptr(NULL); 70.191 - 70.192 - // Find last item of suffix list 70.193 - oop last = suffix; 70.194 - while (last->klass_or_null() != NULL) { 70.195 - last = oop(last->klass()); 70.196 + if (cur->klass_or_null() == NULL) { 70.197 + // Write back the NULL in lieu of the BUSY we wrote 70.198 + // above and it is still the same value. 70.199 + if (_overflow_list == BUSY) { 70.200 + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); 70.201 } 70.202 - // Atomically prepend suffix to current overflow list 70.203 - oop cur_overflow_list = _overflow_list; 70.204 - while (true) { 70.205 - last->set_klass_to_list_ptr(cur_overflow_list); 70.206 - oop observed_overflow_list = 70.207 - (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); 70.208 - if (observed_overflow_list == cur_overflow_list) break; 70.209 - // Otherwise... 70.210 - cur_overflow_list = observed_overflow_list; 70.211 + } else { 70.212 + assert(cur->klass_or_null() != BUSY, "Error"); 70.213 + oop suffix = oop(cur->klass()); // suffix will be put back on global list 70.214 + cur->set_klass_to_list_ptr(NULL); // break off suffix 70.215 + // It's possible that the list is still in the empty(busy) state 70.216 + // we left it in a short while ago; in that case we may be 70.217 + // able to place back the suffix. 70.218 + oop observed_overflow_list = _overflow_list; 70.219 + oop cur_overflow_list = observed_overflow_list; 70.220 + bool attached = false; 70.221 + while (observed_overflow_list == BUSY || observed_overflow_list == NULL) { 70.222 + observed_overflow_list = 70.223 + (oop) Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); 70.224 + if (cur_overflow_list == observed_overflow_list) { 70.225 + attached = true; 70.226 + break; 70.227 + } else cur_overflow_list = observed_overflow_list; 70.228 + } 70.229 + if (!attached) { 70.230 + // Too bad, someone else got in in between; we'll need to do a splice. 70.231 + // Find the last item of suffix list 70.232 + oop last = suffix; 70.233 + while (last->klass_or_null() != NULL) { 70.234 + last = oop(last->klass()); 70.235 + } 70.236 + // Atomically prepend suffix to current overflow list 70.237 + observed_overflow_list = _overflow_list; 70.238 + do { 70.239 + cur_overflow_list = observed_overflow_list; 70.240 + if (cur_overflow_list != BUSY) { 70.241 + // Do the splice ... 70.242 + last->set_klass_to_list_ptr(cur_overflow_list); 70.243 + } else { // cur_overflow_list == BUSY 70.244 + last->set_klass_to_list_ptr(NULL); 70.245 + } 70.246 + observed_overflow_list = 70.247 + (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); 70.248 + } while (cur_overflow_list != observed_overflow_list); 70.249 } 70.250 } 70.251 70.252 // Push objects on prefix list onto this thread's work queue 70.253 - assert(cur != NULL, "program logic"); 70.254 + assert(prefix != NULL && prefix != BUSY, "program logic"); 70.255 cur = prefix; 70.256 - int n = 0; 70.257 + ssize_t n = 0; 70.258 while (cur != NULL) { 70.259 oop obj_to_push = cur->forwardee(); 70.260 oop next = oop(cur->klass_or_null()); 70.261 cur->set_klass(obj_to_push->klass()); 70.262 - if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) { 70.263 + // This may be an array object that is self-forwarded. In that case, the list pointer 70.264 + // space, cur, is not in the Java heap, but rather in the C-heap and should be freed. 70.265 + if (!is_in_reserved(cur)) { 70.266 + // This can become a scaling bottleneck when there is work queue overflow coincident 70.267 + // with promotion failure. 70.268 + oopDesc* f = cur; 70.269 + FREE_C_HEAP_ARRAY(oopDesc, f); 70.270 + } else if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) { 70.271 + assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned"); 70.272 obj_to_push = cur; 70.273 - assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned"); 70.274 } 70.275 - work_q->push(obj_to_push); 70.276 + bool ok = work_q->push(obj_to_push); 70.277 + assert(ok, "Should have succeeded"); 70.278 cur = next; 70.279 n++; 70.280 } 70.281 par_scan_state->note_overflow_refill(n); 70.282 +#ifndef PRODUCT 70.283 + assert(_num_par_pushes >= n, "Too many pops?"); 70.284 + Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes); 70.285 +#endif 70.286 return true; 70.287 } 70.288 +#undef BUSY 70.289 70.290 void ParNewGeneration::ref_processor_init() 70.291 {
71.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Sat Jan 31 17:19:42 2009 -0800 71.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Feb 27 15:13:00 2009 -0800 71.3 @@ -278,6 +278,7 @@ 71.4 friend class ParNewRefProcTask; 71.5 friend class ParNewRefProcTaskExecutor; 71.6 friend class ParScanThreadStateSet; 71.7 + friend class ParEvacuateFollowersClosure; 71.8 71.9 private: 71.10 // XXX use a global constant instead of 64! 71.11 @@ -296,6 +297,7 @@ 71.12 // klass-pointers (klass information already copied to the forwarded 71.13 // image.) Manipulated with CAS. 71.14 oop _overflow_list; 71.15 + NOT_PRODUCT(ssize_t _num_par_pushes;) 71.16 71.17 // If true, older generation does not support promotion undo, so avoid. 71.18 static bool _avoid_promotion_undo; 71.19 @@ -372,8 +374,12 @@ 71.20 oop copy_to_survivor_space_with_undo(ParScanThreadState* par_scan_state, 71.21 oop obj, size_t obj_sz, markOop m); 71.22 71.23 + // in support of testing overflow code 71.24 + NOT_PRODUCT(int _overflow_counter;) 71.25 + NOT_PRODUCT(bool should_simulate_overflow();) 71.26 + 71.27 // Push the given (from-space) object on the global overflow list. 71.28 - void push_on_overflow_list(oop from_space_obj); 71.29 + void push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state); 71.30 71.31 // If the global overflow list is non-empty, move some tasks from it 71.32 // onto "work_q" (which must be empty). No more than 1/4 of the
72.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Sat Jan 31 17:19:42 2009 -0800 72.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Feb 27 15:13:00 2009 -0800 72.3 @@ -200,6 +200,7 @@ 72.4 72.5 void oop_iterate(OopClosure* cl); 72.6 void object_iterate(ObjectClosure* cl); 72.7 + void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } 72.8 void permanent_oop_iterate(OopClosure* cl); 72.9 void permanent_object_iterate(ObjectClosure* cl); 72.10
73.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Sat Jan 31 17:19:42 2009 -0800 73.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Feb 27 15:13:00 2009 -0800 73.3 @@ -362,6 +362,10 @@ 73.4 if (PrintHeapAtGC) { 73.5 Universe::print_heap_after_gc(); 73.6 } 73.7 + 73.8 +#ifdef TRACESPINNING 73.9 + ParallelTaskTerminator::print_termination_counts(); 73.10 +#endif 73.11 } 73.12 73.13 bool PSMarkSweep::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
74.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Sat Jan 31 17:19:42 2009 -0800 74.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Fri Feb 27 15:13:00 2009 -0800 74.3 @@ -116,7 +116,7 @@ 74.4 // ObjectSpace stuff 74.5 // 74.6 74.7 - _object_space = new MutableSpace(); 74.8 + _object_space = new MutableSpace(virtual_space()->alignment()); 74.9 74.10 if (_object_space == NULL) 74.11 vm_exit_during_initialization("Could not allocate an old gen space"); 74.12 @@ -385,10 +385,10 @@ 74.13 start_array()->set_covered_region(new_memregion); 74.14 Universe::heap()->barrier_set()->resize_covered_region(new_memregion); 74.15 74.16 - HeapWord* const virtual_space_high = (HeapWord*) virtual_space()->high(); 74.17 - 74.18 // ALWAYS do this last!! 74.19 - object_space()->set_end(virtual_space_high); 74.20 + object_space()->initialize(new_memregion, 74.21 + SpaceDecorator::DontClear, 74.22 + SpaceDecorator::DontMangle); 74.23 74.24 assert(new_word_size == heap_word_size(object_space()->capacity_in_bytes()), 74.25 "Sanity");
75.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Sat Jan 31 17:19:42 2009 -0800 75.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Feb 27 15:13:00 2009 -0800 75.3 @@ -2203,6 +2203,10 @@ 75.4 collection_exit.ticks()); 75.5 gc_task_manager()->print_task_time_stamps(); 75.6 } 75.7 + 75.8 +#ifdef TRACESPINNING 75.9 + ParallelTaskTerminator::print_termination_counts(); 75.10 +#endif 75.11 } 75.12 75.13 bool PSParallelCompact::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
76.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Sat Jan 31 17:19:42 2009 -0800 76.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Feb 27 15:13:00 2009 -0800 76.3 @@ -615,6 +615,10 @@ 76.4 gc_task_manager()->print_task_time_stamps(); 76.5 } 76.6 76.7 +#ifdef TRACESPINNING 76.8 + ParallelTaskTerminator::print_termination_counts(); 76.9 +#endif 76.10 + 76.11 return !promotion_failure_occurred; 76.12 } 76.13
77.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp Sat Jan 31 17:19:42 2009 -0800 77.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp Fri Feb 27 15:13:00 2009 -0800 77.3 @@ -78,7 +78,7 @@ 77.4 _special = false; 77.5 } 77.6 77.7 -bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) { 77.8 +bool PSVirtualSpace::expand_by(size_t bytes) { 77.9 assert(is_aligned(bytes), "arg not aligned"); 77.10 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 77.11 77.12 @@ -92,15 +92,6 @@ 77.13 _committed_high_addr += bytes; 77.14 } 77.15 77.16 - if (pre_touch || AlwaysPreTouch) { 77.17 - for (char* curr = base_addr; 77.18 - curr < _committed_high_addr; 77.19 - curr += os::vm_page_size()) { 77.20 - char tmp = *curr; 77.21 - *curr = 0; 77.22 - } 77.23 - } 77.24 - 77.25 return result; 77.26 } 77.27 77.28 @@ -255,7 +246,7 @@ 77.29 DEBUG_ONLY(verify()); 77.30 } 77.31 77.32 -bool PSVirtualSpaceHighToLow::expand_by(size_t bytes, bool pre_touch) { 77.33 +bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) { 77.34 assert(is_aligned(bytes), "arg not aligned"); 77.35 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 77.36 77.37 @@ -269,15 +260,6 @@ 77.38 _committed_low_addr -= bytes; 77.39 } 77.40 77.41 - if (pre_touch || AlwaysPreTouch) { 77.42 - for (char* curr = base_addr; 77.43 - curr < _committed_high_addr; 77.44 - curr += os::vm_page_size()) { 77.45 - char tmp = *curr; 77.46 - *curr = 0; 77.47 - } 77.48 - } 77.49 - 77.50 return result; 77.51 } 77.52
78.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp Sat Jan 31 17:19:42 2009 -0800 78.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp Fri Feb 27 15:13:00 2009 -0800 78.3 @@ -80,7 +80,7 @@ 78.4 inline void set_reserved(char* low_addr, char* high_addr, bool special); 78.5 inline void set_reserved(ReservedSpace rs); 78.6 inline void set_committed(char* low_addr, char* high_addr); 78.7 - virtual bool expand_by(size_t bytes, bool pre_touch = false); 78.8 + virtual bool expand_by(size_t bytes); 78.9 virtual bool shrink_by(size_t bytes); 78.10 virtual size_t expand_into(PSVirtualSpace* space, size_t bytes); 78.11 void release(); 78.12 @@ -127,7 +127,7 @@ 78.13 PSVirtualSpaceHighToLow(ReservedSpace rs, size_t alignment); 78.14 PSVirtualSpaceHighToLow(ReservedSpace rs); 78.15 78.16 - virtual bool expand_by(size_t bytes, bool pre_touch = false); 78.17 + virtual bool expand_by(size_t bytes); 78.18 virtual bool shrink_by(size_t bytes); 78.19 virtual size_t expand_into(PSVirtualSpace* space, size_t bytes); 78.20
79.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp Sat Jan 31 17:19:42 2009 -0800 79.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp Fri Feb 27 15:13:00 2009 -0800 79.3 @@ -64,12 +64,12 @@ 79.4 } 79.5 79.6 if (UseNUMA) { 79.7 - _eden_space = new MutableNUMASpace(); 79.8 + _eden_space = new MutableNUMASpace(virtual_space()->alignment()); 79.9 } else { 79.10 - _eden_space = new MutableSpace(); 79.11 + _eden_space = new MutableSpace(virtual_space()->alignment()); 79.12 } 79.13 - _from_space = new MutableSpace(); 79.14 - _to_space = new MutableSpace(); 79.15 + _from_space = new MutableSpace(virtual_space()->alignment()); 79.16 + _to_space = new MutableSpace(virtual_space()->alignment()); 79.17 79.18 if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) { 79.19 vm_exit_during_initialization("Could not allocate a young gen space");
80.1 --- a/src/share/vm/gc_implementation/shared/ageTable.cpp Sat Jan 31 17:19:42 2009 -0800 80.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.cpp Fri Feb 27 15:13:00 2009 -0800 80.3 @@ -67,6 +67,12 @@ 80.4 } 80.5 } 80.6 80.7 +void ageTable::merge_par(ageTable* subTable) { 80.8 + for (int i = 0; i < table_size; i++) { 80.9 + Atomic::add_ptr(subTable->sizes[i], &sizes[i]); 80.10 + } 80.11 +} 80.12 + 80.13 int ageTable::compute_tenuring_threshold(size_t survivor_capacity) { 80.14 size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); 80.15 size_t total = 0;
81.1 --- a/src/share/vm/gc_implementation/shared/ageTable.hpp Sat Jan 31 17:19:42 2009 -0800 81.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Feb 27 15:13:00 2009 -0800 81.3 @@ -56,6 +56,7 @@ 81.4 // Merge another age table with the current one. Used 81.5 // for parallel young generation gc. 81.6 void merge(ageTable* subTable); 81.7 + void merge_par(ageTable* subTable); 81.8 81.9 // calculate new tenuring threshold based on age information 81.10 int compute_tenuring_threshold(size_t survivor_capacity);
82.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Sat Jan 31 17:19:42 2009 -0800 82.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Fri Feb 27 15:13:00 2009 -0800 82.3 @@ -27,7 +27,7 @@ 82.4 # include "incls/_mutableNUMASpace.cpp.incl" 82.5 82.6 82.7 -MutableNUMASpace::MutableNUMASpace() { 82.8 +MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) { 82.9 _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray<LGRPSpace*>(0, true); 82.10 _page_size = os::vm_page_size(); 82.11 _adaptation_cycles = 0; 82.12 @@ -221,7 +221,7 @@ 82.13 } 82.14 } 82.15 if (!found) { 82.16 - lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i])); 82.17 + lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment())); 82.18 } 82.19 } 82.20 82.21 @@ -443,10 +443,10 @@ 82.22 // Is there bottom? 82.23 if (new_region.start() < intersection.start()) { // Yes 82.24 // Try to coalesce small pages into a large one. 82.25 - if (UseLargePages && page_size() >= os::large_page_size()) { 82.26 - HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), os::large_page_size()); 82.27 + if (UseLargePages && page_size() >= alignment()) { 82.28 + HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), alignment()); 82.29 if (new_region.contains(p) 82.30 - && pointer_delta(p, new_region.start(), sizeof(char)) >= os::large_page_size()) { 82.31 + && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) { 82.32 if (intersection.contains(p)) { 82.33 intersection = MemRegion(p, intersection.end()); 82.34 } else { 82.35 @@ -462,10 +462,10 @@ 82.36 // Is there top? 82.37 if (intersection.end() < new_region.end()) { // Yes 82.38 // Try to coalesce small pages into a large one. 82.39 - if (UseLargePages && page_size() >= os::large_page_size()) { 82.40 - HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), os::large_page_size()); 82.41 + if (UseLargePages && page_size() >= alignment()) { 82.42 + HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), alignment()); 82.43 if (new_region.contains(p) 82.44 - && pointer_delta(new_region.end(), p, sizeof(char)) >= os::large_page_size()) { 82.45 + && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) { 82.46 if (intersection.contains(p)) { 82.47 intersection = MemRegion(intersection.start(), p); 82.48 } else { 82.49 @@ -504,12 +504,12 @@ 82.50 // That's the only case we have to make an additional bias_region() call. 82.51 HeapWord* start = invalid_region->start(); 82.52 HeapWord* end = invalid_region->end(); 82.53 - if (UseLargePages && page_size() >= os::large_page_size()) { 82.54 - HeapWord *p = (HeapWord*)round_down((intptr_t) start, os::large_page_size()); 82.55 + if (UseLargePages && page_size() >= alignment()) { 82.56 + HeapWord *p = (HeapWord*)round_down((intptr_t) start, alignment()); 82.57 if (new_region.contains(p)) { 82.58 start = p; 82.59 } 82.60 - p = (HeapWord*)round_to((intptr_t) end, os::large_page_size()); 82.61 + p = (HeapWord*)round_to((intptr_t) end, alignment()); 82.62 if (new_region.contains(end)) { 82.63 end = p; 82.64 } 82.65 @@ -526,7 +526,8 @@ 82.66 82.67 void MutableNUMASpace::initialize(MemRegion mr, 82.68 bool clear_space, 82.69 - bool mangle_space) { 82.70 + bool mangle_space, 82.71 + bool setup_pages) { 82.72 assert(clear_space, "Reallocation will destory data!"); 82.73 assert(lgrp_spaces()->length() > 0, "There should be at least one space"); 82.74 82.75 @@ -538,7 +539,7 @@ 82.76 82.77 // Compute chunk sizes 82.78 size_t prev_page_size = page_size(); 82.79 - set_page_size(UseLargePages ? os::large_page_size() : os::vm_page_size()); 82.80 + set_page_size(UseLargePages ? alignment() : os::vm_page_size()); 82.81 HeapWord* rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size()); 82.82 HeapWord* rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size()); 82.83 size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size(); 82.84 @@ -666,7 +667,7 @@ 82.85 } 82.86 82.87 // Clear space (set top = bottom) but never mangle. 82.88 - s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle); 82.89 + s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages); 82.90 82.91 set_adaptation_cycles(samples_count()); 82.92 }
83.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Sat Jan 31 17:19:42 2009 -0800 83.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Fri Feb 27 15:13:00 2009 -0800 83.3 @@ -82,8 +82,8 @@ 83.4 char* last_page_scanned() { return _last_page_scanned; } 83.5 void set_last_page_scanned(char* p) { _last_page_scanned = p; } 83.6 public: 83.7 - LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { 83.8 - _space = new MutableSpace(); 83.9 + LGRPSpace(int l, size_t alignment) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { 83.10 + _space = new MutableSpace(alignment); 83.11 _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight); 83.12 } 83.13 ~LGRPSpace() { 83.14 @@ -183,10 +183,10 @@ 83.15 83.16 public: 83.17 GrowableArray<LGRPSpace*>* lgrp_spaces() const { return _lgrp_spaces; } 83.18 - MutableNUMASpace(); 83.19 + MutableNUMASpace(size_t alignment); 83.20 virtual ~MutableNUMASpace(); 83.21 // Space initialization. 83.22 - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); 83.23 + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space, bool setup_pages = SetupPages); 83.24 // Update space layout if necessary. Do all adaptive resizing job. 83.25 virtual void update(); 83.26 // Update allocation rate averages.
84.1 --- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp Sat Jan 31 17:19:42 2009 -0800 84.2 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp Fri Feb 27 15:13:00 2009 -0800 84.3 @@ -25,7 +25,10 @@ 84.4 # include "incls/_precompiled.incl" 84.5 # include "incls/_mutableSpace.cpp.incl" 84.6 84.7 -MutableSpace::MutableSpace(): ImmutableSpace(), _top(NULL) { 84.8 +MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { 84.9 + assert(MutableSpace::alignment() >= 0 && 84.10 + MutableSpace::alignment() % os::vm_page_size() == 0, 84.11 + "Space should be aligned"); 84.12 _mangler = new MutableSpaceMangler(this); 84.13 } 84.14 84.15 @@ -33,16 +36,88 @@ 84.16 delete _mangler; 84.17 } 84.18 84.19 +void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) { 84.20 + if (!mr.is_empty()) { 84.21 + size_t page_size = UseLargePages ? alignment() : os::vm_page_size(); 84.22 + HeapWord *start = (HeapWord*)round_to((intptr_t) mr.start(), page_size); 84.23 + HeapWord *end = (HeapWord*)round_down((intptr_t) mr.end(), page_size); 84.24 + if (end > start) { 84.25 + size_t size = pointer_delta(end, start, sizeof(char)); 84.26 + if (clear_space) { 84.27 + // Prefer page reallocation to migration. 84.28 + os::free_memory((char*)start, size); 84.29 + } 84.30 + os::numa_make_global((char*)start, size); 84.31 + } 84.32 + } 84.33 +} 84.34 + 84.35 +void MutableSpace::pretouch_pages(MemRegion mr) { 84.36 + for (volatile char *p = (char*)mr.start(); p < (char*)mr.end(); p += os::vm_page_size()) { 84.37 + char t = *p; *p = t; 84.38 + } 84.39 +} 84.40 + 84.41 void MutableSpace::initialize(MemRegion mr, 84.42 bool clear_space, 84.43 - bool mangle_space) { 84.44 - HeapWord* bottom = mr.start(); 84.45 - HeapWord* end = mr.end(); 84.46 + bool mangle_space, 84.47 + bool setup_pages) { 84.48 84.49 - assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), 84.50 + assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()), 84.51 "invalid space boundaries"); 84.52 - set_bottom(bottom); 84.53 - set_end(end); 84.54 + 84.55 + if (setup_pages && (UseNUMA || AlwaysPreTouch)) { 84.56 + // The space may move left and right or expand/shrink. 84.57 + // We'd like to enforce the desired page placement. 84.58 + MemRegion head, tail; 84.59 + if (last_setup_region().is_empty()) { 84.60 + // If it's the first initialization don't limit the amount of work. 84.61 + head = mr; 84.62 + tail = MemRegion(mr.end(), mr.end()); 84.63 + } else { 84.64 + // Is there an intersection with the address space? 84.65 + MemRegion intersection = last_setup_region().intersection(mr); 84.66 + if (intersection.is_empty()) { 84.67 + intersection = MemRegion(mr.end(), mr.end()); 84.68 + } 84.69 + // All the sizes below are in words. 84.70 + size_t head_size = 0, tail_size = 0; 84.71 + if (mr.start() <= intersection.start()) { 84.72 + head_size = pointer_delta(intersection.start(), mr.start()); 84.73 + } 84.74 + if(intersection.end() <= mr.end()) { 84.75 + tail_size = pointer_delta(mr.end(), intersection.end()); 84.76 + } 84.77 + // Limit the amount of page manipulation if necessary. 84.78 + if (NUMASpaceResizeRate > 0 && !AlwaysPreTouch) { 84.79 + const size_t change_size = head_size + tail_size; 84.80 + const float setup_rate_words = NUMASpaceResizeRate >> LogBytesPerWord; 84.81 + head_size = MIN2((size_t)(setup_rate_words * head_size / change_size), 84.82 + head_size); 84.83 + tail_size = MIN2((size_t)(setup_rate_words * tail_size / change_size), 84.84 + tail_size); 84.85 + } 84.86 + head = MemRegion(intersection.start() - head_size, intersection.start()); 84.87 + tail = MemRegion(intersection.end(), intersection.end() + tail_size); 84.88 + } 84.89 + assert(mr.contains(head) && mr.contains(tail), "Sanity"); 84.90 + 84.91 + if (UseNUMA) { 84.92 + numa_setup_pages(head, clear_space); 84.93 + numa_setup_pages(tail, clear_space); 84.94 + } 84.95 + 84.96 + if (AlwaysPreTouch) { 84.97 + pretouch_pages(head); 84.98 + pretouch_pages(tail); 84.99 + } 84.100 + 84.101 + // Remember where we stopped so that we can continue later. 84.102 + set_last_setup_region(MemRegion(head.start(), tail.end())); 84.103 + } 84.104 + 84.105 + set_bottom(mr.start()); 84.106 + set_end(mr.end()); 84.107 84.108 if (clear_space) { 84.109 clear(mangle_space);
85.1 --- a/src/share/vm/gc_implementation/shared/mutableSpace.hpp Sat Jan 31 17:19:42 2009 -0800 85.2 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.hpp Fri Feb 27 15:13:00 2009 -0800 85.3 @@ -25,7 +25,10 @@ 85.4 // A MutableSpace is a subtype of ImmutableSpace that supports the 85.5 // concept of allocation. This includes the concepts that a space may 85.6 // be only partially full, and the querry methods that go with such 85.7 -// an assumption. 85.8 +// an assumption. MutableSpace is also responsible for minimizing the 85.9 +// page allocation time by having the memory pretouched (with 85.10 +// AlwaysPretouch) and for optimizing page placement on NUMA systems 85.11 +// by make the underlying region interleaved (with UseNUMA). 85.12 // 85.13 // Invariant: (ImmutableSpace +) bottom() <= top() <= end() 85.14 // top() is inclusive and end() is exclusive. 85.15 @@ -37,15 +40,23 @@ 85.16 85.17 // Helper for mangling unused space in debug builds 85.18 MutableSpaceMangler* _mangler; 85.19 - 85.20 + // The last region which page had been setup to be interleaved. 85.21 + MemRegion _last_setup_region; 85.22 + size_t _alignment; 85.23 protected: 85.24 HeapWord* _top; 85.25 85.26 MutableSpaceMangler* mangler() { return _mangler; } 85.27 85.28 + void numa_setup_pages(MemRegion mr, bool clear_space); 85.29 + void pretouch_pages(MemRegion mr); 85.30 + 85.31 + void set_last_setup_region(MemRegion mr) { _last_setup_region = mr; } 85.32 + MemRegion last_setup_region() const { return _last_setup_region; } 85.33 + 85.34 public: 85.35 virtual ~MutableSpace(); 85.36 - MutableSpace(); 85.37 + MutableSpace(size_t page_size); 85.38 85.39 // Accessors 85.40 HeapWord* top() const { return _top; } 85.41 @@ -57,13 +68,20 @@ 85.42 virtual void set_bottom(HeapWord* value) { _bottom = value; } 85.43 virtual void set_end(HeapWord* value) { _end = value; } 85.44 85.45 + size_t alignment() { return _alignment; } 85.46 + 85.47 // Returns a subregion containing all objects in this space. 85.48 MemRegion used_region() { return MemRegion(bottom(), top()); } 85.49 85.50 + static const bool SetupPages = true; 85.51 + static const bool DontSetupPages = false; 85.52 + 85.53 // Initialization 85.54 virtual void initialize(MemRegion mr, 85.55 bool clear_space, 85.56 - bool mangle_space); 85.57 + bool mangle_space, 85.58 + bool setup_pages = SetupPages); 85.59 + 85.60 virtual void clear(bool mangle_space); 85.61 // Does the usual initialization but optionally resets top to bottom. 85.62 #if 0 // MANGLE_SPACE
86.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp Sat Jan 31 17:19:42 2009 -0800 86.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Fri Feb 27 15:13:00 2009 -0800 86.3 @@ -42,6 +42,7 @@ 86.4 class CollectedHeap : public CHeapObj { 86.5 friend class VMStructs; 86.6 friend class IsGCActiveMark; // Block structured external access to _is_gc_active 86.7 + friend class constantPoolCacheKlass; // allocate() method inserts is_conc_safe 86.8 86.9 #ifdef ASSERT 86.10 static int _fire_out_of_memory_count; 86.11 @@ -82,8 +83,6 @@ 86.12 // Reinitialize tlabs before resuming mutators. 86.13 virtual void resize_all_tlabs(); 86.14 86.15 - debug_only(static void check_for_valid_allocation_state();) 86.16 - 86.17 protected: 86.18 // Allocate from the current thread's TLAB, with broken-out slow path. 86.19 inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size); 86.20 @@ -142,6 +141,7 @@ 86.21 PRODUCT_RETURN; 86.22 virtual void check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) 86.23 PRODUCT_RETURN; 86.24 + debug_only(static void check_for_valid_allocation_state();) 86.25 86.26 public: 86.27 enum Name { 86.28 @@ -466,6 +466,10 @@ 86.29 // This includes objects in permanent memory. 86.30 virtual void object_iterate(ObjectClosure* cl) = 0; 86.31 86.32 + // Similar to object_iterate() except iterates only 86.33 + // over live objects. 86.34 + virtual void safe_object_iterate(ObjectClosure* cl) = 0; 86.35 + 86.36 // Behaves the same as oop_iterate, except only traverses 86.37 // interior pointers contained in permanent memory. If there 86.38 // is no permanent memory, does nothing.
87.1 --- a/src/share/vm/includeDB_compiler2 Sat Jan 31 17:19:42 2009 -0800 87.2 +++ b/src/share/vm/includeDB_compiler2 Fri Feb 27 15:13:00 2009 -0800 87.3 @@ -140,6 +140,7 @@ 87.4 c2_globals_<os_family>.hpp macros.hpp 87.5 87.6 c2_init_<arch>.cpp compile.hpp 87.7 +c2_init_<arch>.cpp node.hpp 87.8 87.9 c2compiler.cpp ad_<arch_model>.hpp 87.10 c2compiler.cpp c2compiler.hpp 87.11 @@ -839,6 +840,7 @@ 87.12 phase.cpp compile.hpp 87.13 phase.cpp compileBroker.hpp 87.14 phase.cpp nmethod.hpp 87.15 +phase.cpp node.hpp 87.16 phase.cpp phase.hpp 87.17 87.18 phase.hpp port.hpp
88.1 --- a/src/share/vm/includeDB_core Sat Jan 31 17:19:42 2009 -0800 88.2 +++ b/src/share/vm/includeDB_core Fri Feb 27 15:13:00 2009 -0800 88.3 @@ -1311,6 +1311,7 @@ 88.4 cppInterpreter_<arch>.cpp debug.hpp 88.5 cppInterpreter_<arch>.cpp deoptimization.hpp 88.6 cppInterpreter_<arch>.cpp frame.inline.hpp 88.7 +cppInterpreter_<arch>.cpp interfaceSupport.hpp 88.8 cppInterpreter_<arch>.cpp interpreterRuntime.hpp 88.9 cppInterpreter_<arch>.cpp interpreter.hpp 88.10 cppInterpreter_<arch>.cpp interpreterGenerator.hpp 88.11 @@ -2014,7 +2015,7 @@ 88.12 instanceKlass.cpp vmSymbols.hpp 88.13 88.14 instanceKlass.hpp accessFlags.hpp 88.15 -instanceKlass.hpp bitMap.hpp 88.16 +instanceKlass.hpp bitMap.inline.hpp 88.17 instanceKlass.hpp constMethodOop.hpp 88.18 instanceKlass.hpp constantPoolOop.hpp 88.19 instanceKlass.hpp handles.hpp 88.20 @@ -3771,6 +3772,7 @@ 88.21 88.22 spaceDecorator.cpp copy.hpp 88.23 spaceDecorator.cpp spaceDecorator.hpp 88.24 +spaceDecorator.cpp space.inline.hpp 88.25 88.26 specialized_oop_closures.cpp ostream.hpp 88.27 specialized_oop_closures.cpp specialized_oop_closures.hpp
89.1 --- a/src/share/vm/includeDB_features Sat Jan 31 17:19:42 2009 -0800 89.2 +++ b/src/share/vm/includeDB_features Fri Feb 27 15:13:00 2009 -0800 89.3 @@ -59,6 +59,8 @@ 89.4 89.5 dump_<arch_model>.cpp assembler_<arch>.inline.hpp 89.6 dump_<arch_model>.cpp compactingPermGenGen.hpp 89.7 +dump_<arch_model>.cpp generation.inline.hpp 89.8 +dump_<arch_model>.cpp space.inline.hpp 89.9 89.10 forte.cpp collectedHeap.inline.hpp 89.11 forte.cpp debugInfoRec.hpp
90.1 --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Sat Jan 31 17:19:42 2009 -0800 90.2 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Feb 27 15:13:00 2009 -0800 90.3 @@ -163,7 +163,7 @@ 90.4 #ifdef USELABELS 90.5 // Have to do this dispatch this way in C++ because otherwise gcc complains about crossing an 90.6 // initialization (which is is the initialization of the table pointer...) 90.7 -#define DISPATCH(opcode) goto *dispatch_table[opcode] 90.8 +#define DISPATCH(opcode) goto *(void*)dispatch_table[opcode] 90.9 #define CONTINUE { \ 90.10 opcode = *pc; \ 90.11 DO_UPDATE_INSTRUCTION_COUNT(opcode); \ 90.12 @@ -341,7 +341,7 @@ 90.13 */ 90.14 #undef CHECK_NULL 90.15 #define CHECK_NULL(obj_) \ 90.16 - if ((obj_) == 0) { \ 90.17 + if ((obj_) == NULL) { \ 90.18 VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), ""); \ 90.19 } 90.20 90.21 @@ -1362,7 +1362,7 @@ 90.22 90.23 #define NULL_COMPARISON_NOT_OP(name) \ 90.24 CASE(_if##name): { \ 90.25 - int skip = (!(STACK_OBJECT(-1) == 0)) \ 90.26 + int skip = (!(STACK_OBJECT(-1) == NULL)) \ 90.27 ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ 90.28 address branch_pc = pc; \ 90.29 UPDATE_PC_AND_TOS(skip, -1); \ 90.30 @@ -1372,7 +1372,7 @@ 90.31 90.32 #define NULL_COMPARISON_OP(name) \ 90.33 CASE(_if##name): { \ 90.34 - int skip = ((STACK_OBJECT(-1) == 0)) \ 90.35 + int skip = ((STACK_OBJECT(-1) == NULL)) \ 90.36 ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ 90.37 address branch_pc = pc; \ 90.38 UPDATE_PC_AND_TOS(skip, -1); \
91.1 --- a/src/share/vm/interpreter/bytecodeInterpreter.hpp Sat Jan 31 17:19:42 2009 -0800 91.2 +++ b/src/share/vm/interpreter/bytecodeInterpreter.hpp Fri Feb 27 15:13:00 2009 -0800 91.3 @@ -66,7 +66,6 @@ 91.4 friend class InterpreterGenerator; 91.5 friend class InterpreterMacroAssembler; 91.6 friend class frame; 91.7 -friend class SharedRuntime; 91.8 friend class VMStructs; 91.9 91.10 public:
92.1 --- a/src/share/vm/interpreter/rewriter.cpp Sat Jan 31 17:19:42 2009 -0800 92.2 +++ b/src/share/vm/interpreter/rewriter.cpp Fri Feb 27 15:13:00 2009 -0800 92.3 @@ -48,9 +48,14 @@ 92.4 92.5 92.6 // Creates a constant pool cache given an inverse_index_map 92.7 +// This creates the constant pool cache initially in a state 92.8 +// that is unsafe for concurrent GC processing but sets it to 92.9 +// a safe mode before the constant pool cache is returned. 92.10 constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) { 92.11 const int length = inverse_index_map.length(); 92.12 - constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK_(constantPoolCacheHandle())); 92.13 + constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, 92.14 + methodOopDesc::IsUnsafeConc, 92.15 + CHECK_(constantPoolCacheHandle())); 92.16 cache->initialize(inverse_index_map); 92.17 return constantPoolCacheHandle(THREAD, cache); 92.18 }
93.1 --- a/src/share/vm/libadt/dict.cpp Sat Jan 31 17:19:42 2009 -0800 93.2 +++ b/src/share/vm/libadt/dict.cpp Fri Feb 27 15:13:00 2009 -0800 93.3 @@ -346,9 +346,12 @@ 93.4 return strcmp((const char *)k1,(const char *)k2); 93.5 } 93.6 93.7 -// Slimey cheap key comparator. 93.8 +// Cheap key comparator. 93.9 int32 cmpkey(const void *key1, const void *key2) { 93.10 - return (int32)((intptr_t)key1 - (intptr_t)key2); 93.11 + if (key1 == key2) return 0; 93.12 + intptr_t delta = (intptr_t)key1 - (intptr_t)key2; 93.13 + if (delta > 0) return 1; 93.14 + return -1; 93.15 } 93.16 93.17 //=============================================================================
94.1 --- a/src/share/vm/libadt/port.hpp Sat Jan 31 17:19:42 2009 -0800 94.2 +++ b/src/share/vm/libadt/port.hpp Fri Feb 27 15:13:00 2009 -0800 94.3 @@ -34,17 +34,6 @@ 94.4 #include <stddef.h> 94.5 #include <stdlib.h> 94.6 #include <string.h> 94.7 -#undef bzero 94.8 -inline void bzero(void *b, int len) { memset(b,0,len); } 94.9 -#undef bcopy 94.10 -inline void bcopy(const void *s, void *d, size_t len) { memmove(d,s,len); } 94.11 -#undef bcmp 94.12 -inline int bcmp(const void *s,const void *t,int len) { return memcmp(s,t,len);} 94.13 -extern "C" unsigned long strtoul(const char *s, char **end, int base); 94.14 - 94.15 -// Definition for sys_errlist varies from Sun 4.1 & Solaris. 94.16 -// We use the new Solaris definition. 94.17 -#include <string.h> 94.18 94.19 // Access to the C++ class virtual function pointer 94.20 // Put the class in the macro
95.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Sat Jan 31 17:19:42 2009 -0800 95.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Fri Feb 27 15:13:00 2009 -0800 95.3 @@ -610,6 +610,10 @@ 95.4 Universe::print_heap_after_gc(); 95.5 } 95.6 95.7 +#ifdef TRACESPINNING 95.8 + ParallelTaskTerminator::print_termination_counts(); 95.9 +#endif 95.10 + 95.11 if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { 95.12 tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); 95.13 vm_exit(-1); 95.14 @@ -910,6 +914,13 @@ 95.15 perm_gen()->object_iterate(cl); 95.16 } 95.17 95.18 +void GenCollectedHeap::safe_object_iterate(ObjectClosure* cl) { 95.19 + for (int i = 0; i < _n_gens; i++) { 95.20 + _gens[i]->safe_object_iterate(cl); 95.21 + } 95.22 + perm_gen()->safe_object_iterate(cl); 95.23 +} 95.24 + 95.25 void GenCollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { 95.26 for (int i = 0; i < _n_gens; i++) { 95.27 _gens[i]->object_iterate_since_last_GC(cl);
96.1 --- a/src/share/vm/memory/genCollectedHeap.hpp Sat Jan 31 17:19:42 2009 -0800 96.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp Fri Feb 27 15:13:00 2009 -0800 96.3 @@ -215,6 +215,7 @@ 96.4 void oop_iterate(OopClosure* cl); 96.5 void oop_iterate(MemRegion mr, OopClosure* cl); 96.6 void object_iterate(ObjectClosure* cl); 96.7 + void safe_object_iterate(ObjectClosure* cl); 96.8 void object_iterate_since_last_GC(ObjectClosure* cl); 96.9 Space* space_containing(const void* addr) const; 96.10
97.1 --- a/src/share/vm/memory/generation.cpp Sat Jan 31 17:19:42 2009 -0800 97.2 +++ b/src/share/vm/memory/generation.cpp Fri Feb 27 15:13:00 2009 -0800 97.3 @@ -319,6 +319,21 @@ 97.4 space_iterate(&blk); 97.5 } 97.6 97.7 +class GenerationSafeObjIterateClosure : public SpaceClosure { 97.8 + private: 97.9 + ObjectClosure* _cl; 97.10 + public: 97.11 + virtual void do_space(Space* s) { 97.12 + s->safe_object_iterate(_cl); 97.13 + } 97.14 + GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {} 97.15 +}; 97.16 + 97.17 +void Generation::safe_object_iterate(ObjectClosure* cl) { 97.18 + GenerationSafeObjIterateClosure blk(cl); 97.19 + space_iterate(&blk); 97.20 +} 97.21 + 97.22 void Generation::prepare_for_compaction(CompactPoint* cp) { 97.23 // Generic implementation, can be specialized 97.24 CompactibleSpace* space = first_compaction_space();
98.1 --- a/src/share/vm/memory/generation.hpp Sat Jan 31 17:19:42 2009 -0800 98.2 +++ b/src/share/vm/memory/generation.hpp Fri Feb 27 15:13:00 2009 -0800 98.3 @@ -518,6 +518,11 @@ 98.4 // each. 98.5 virtual void object_iterate(ObjectClosure* cl); 98.6 98.7 + // Iterate over all safe objects in the generation, calling "cl.do_object" on 98.8 + // each. An object is safe if its references point to other objects in 98.9 + // the heap. This defaults to object_iterate() unless overridden. 98.10 + virtual void safe_object_iterate(ObjectClosure* cl); 98.11 + 98.12 // Iterate over all objects allocated in the generation since the last 98.13 // collection, calling "cl.do_object" on each. The generation must have 98.14 // been initialized properly to support this function, or else this call
99.1 --- a/src/share/vm/memory/heapInspection.cpp Sat Jan 31 17:19:42 2009 -0800 99.2 +++ b/src/share/vm/memory/heapInspection.cpp Fri Feb 27 15:13:00 2009 -0800 99.3 @@ -263,6 +263,9 @@ 99.4 if (!cit.allocation_failed()) { 99.5 // Iterate over objects in the heap 99.6 RecordInstanceClosure ric(&cit); 99.7 + // If this operation encounters a bad object when using CMS, 99.8 + // consider using safe_object_iterate() which avoids perm gen 99.9 + // objects that may contain bad references. 99.10 Universe::heap()->object_iterate(&ric); 99.11 99.12 // Report if certain classes are not counted because of 99.13 @@ -317,5 +320,8 @@ 99.14 99.15 // Iterate over objects in the heap 99.16 FindInstanceClosure fic(k, result); 99.17 + // If this operation encounters a bad object when using CMS, 99.18 + // consider using safe_object_iterate() which avoids perm gen 99.19 + // objects that may contain bad references. 99.20 Universe::heap()->object_iterate(&fic); 99.21 }
100.1 --- a/src/share/vm/memory/oopFactory.cpp Sat Jan 31 17:19:42 2009 -0800 100.2 +++ b/src/share/vm/memory/oopFactory.cpp Fri Feb 27 15:13:00 2009 -0800 100.3 @@ -82,15 +82,19 @@ 100.4 } 100.5 100.6 100.7 -constantPoolOop oopFactory::new_constantPool(int length, TRAPS) { 100.8 +constantPoolOop oopFactory::new_constantPool(int length, 100.9 + bool is_conc_safe, 100.10 + TRAPS) { 100.11 constantPoolKlass* ck = constantPoolKlass::cast(Universe::constantPoolKlassObj()); 100.12 - return ck->allocate(length, CHECK_NULL); 100.13 + return ck->allocate(length, is_conc_safe, CHECK_NULL); 100.14 } 100.15 100.16 100.17 -constantPoolCacheOop oopFactory::new_constantPoolCache(int length, TRAPS) { 100.18 +constantPoolCacheOop oopFactory::new_constantPoolCache(int length, 100.19 + bool is_conc_safe, 100.20 + TRAPS) { 100.21 constantPoolCacheKlass* ck = constantPoolCacheKlass::cast(Universe::constantPoolCacheKlassObj()); 100.22 - return ck->allocate(length, CHECK_NULL); 100.23 + return ck->allocate(length, is_conc_safe, CHECK_NULL); 100.24 } 100.25 100.26 100.27 @@ -105,11 +109,13 @@ 100.28 int compressed_line_number_size, 100.29 int localvariable_table_length, 100.30 int checked_exceptions_length, 100.31 + bool is_conc_safe, 100.32 TRAPS) { 100.33 klassOop cmkObj = Universe::constMethodKlassObj(); 100.34 constMethodKlass* cmk = constMethodKlass::cast(cmkObj); 100.35 return cmk->allocate(byte_code_size, compressed_line_number_size, 100.36 localvariable_table_length, checked_exceptions_length, 100.37 + is_conc_safe, 100.38 CHECK_NULL); 100.39 } 100.40 100.41 @@ -117,14 +123,17 @@ 100.42 methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags, 100.43 int compressed_line_number_size, 100.44 int localvariable_table_length, 100.45 - int checked_exceptions_length, TRAPS) { 100.46 + int checked_exceptions_length, 100.47 + bool is_conc_safe, 100.48 + TRAPS) { 100.49 methodKlass* mk = methodKlass::cast(Universe::methodKlassObj()); 100.50 assert(!access_flags.is_native() || byte_code_size == 0, 100.51 "native methods should not contain byte codes"); 100.52 constMethodOop cm = new_constMethod(byte_code_size, 100.53 compressed_line_number_size, 100.54 localvariable_table_length, 100.55 - checked_exceptions_length, CHECK_NULL); 100.56 + checked_exceptions_length, 100.57 + is_conc_safe, CHECK_NULL); 100.58 constMethodHandle rw(THREAD, cm); 100.59 return mk->allocate(rw, access_flags, CHECK_NULL); 100.60 }
101.1 --- a/src/share/vm/memory/oopFactory.hpp Sat Jan 31 17:19:42 2009 -0800 101.2 +++ b/src/share/vm/memory/oopFactory.hpp Fri Feb 27 15:13:00 2009 -0800 101.3 @@ -81,8 +81,12 @@ 101.4 static symbolHandle new_symbol_handle(const char* name, TRAPS) { return new_symbol_handle(name, (int)strlen(name), CHECK_(symbolHandle())); } 101.5 101.6 // Constant pools 101.7 - static constantPoolOop new_constantPool (int length, TRAPS); 101.8 - static constantPoolCacheOop new_constantPoolCache(int length, TRAPS); 101.9 + static constantPoolOop new_constantPool (int length, 101.10 + bool is_conc_safe, 101.11 + TRAPS); 101.12 + static constantPoolCacheOop new_constantPoolCache(int length, 101.13 + bool is_conc_safe, 101.14 + TRAPS); 101.15 101.16 // Instance classes 101.17 static klassOop new_instanceKlass(int vtable_len, int itable_len, int static_field_size, 101.18 @@ -93,9 +97,20 @@ 101.19 static constMethodOop new_constMethod(int byte_code_size, 101.20 int compressed_line_number_size, 101.21 int localvariable_table_length, 101.22 - int checked_exceptions_length, TRAPS); 101.23 + int checked_exceptions_length, 101.24 + bool is_conc_safe, 101.25 + TRAPS); 101.26 public: 101.27 - static methodOop new_method(int byte_code_size, AccessFlags access_flags, int compressed_line_number_size, int localvariable_table_length, int checked_exceptions_length, TRAPS); 101.28 + // Set is_conc_safe for methods which cannot safely be 101.29 + // processed by concurrent GC even after the return of 101.30 + // the method. 101.31 + static methodOop new_method(int byte_code_size, 101.32 + AccessFlags access_flags, 101.33 + int compressed_line_number_size, 101.34 + int localvariable_table_length, 101.35 + int checked_exceptions_length, 101.36 + bool is_conc_safe, 101.37 + TRAPS); 101.38 101.39 // Method Data containers 101.40 static methodDataOop new_methodData(methodHandle method, TRAPS);
102.1 --- a/src/share/vm/memory/referenceProcessor.cpp Sat Jan 31 17:19:42 2009 -0800 102.2 +++ b/src/share/vm/memory/referenceProcessor.cpp Fri Feb 27 15:13:00 2009 -0800 102.3 @@ -721,12 +721,6 @@ 102.4 iter.obj(), iter.obj()->blueprint()->internal_name()); 102.5 } 102.6 assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); 102.7 - // If discovery is concurrent, we may have objects with null referents, 102.8 - // being those that were concurrently cleared after they were discovered 102.9 - // (and not subsequently precleaned). 102.10 - assert( (discovery_is_atomic() && iter.referent()->is_oop()) 102.11 - || (!discovery_is_atomic() && iter.referent()->is_oop_or_null(UseConcMarkSweepGC)), 102.12 - "Adding a bad referent"); 102.13 iter.next(); 102.14 } 102.15 // Remember to keep sentinel pointer around
103.1 --- a/src/share/vm/memory/space.cpp Sat Jan 31 17:19:42 2009 -0800 103.2 +++ b/src/share/vm/memory/space.cpp Fri Feb 27 15:13:00 2009 -0800 103.3 @@ -569,7 +569,15 @@ 103.4 if (prev > mr.start()) { 103.5 region_start_addr = prev; 103.6 blk_start_addr = prev; 103.7 - assert(blk_start_addr == block_start(region_start_addr), "invariant"); 103.8 + // The previous invocation may have pushed "prev" beyond the 103.9 + // last allocated block yet there may be still be blocks 103.10 + // in this region due to a particular coalescing policy. 103.11 + // Relax the assertion so that the case where the unallocated 103.12 + // block is maintained and "prev" is beyond the unallocated 103.13 + // block does not cause the assertion to fire. 103.14 + assert((BlockOffsetArrayUseUnallocatedBlock && 103.15 + (!is_in(prev))) || 103.16 + (blk_start_addr == block_start(region_start_addr)), "invariant"); 103.17 } else { 103.18 region_start_addr = mr.start(); 103.19 blk_start_addr = block_start(region_start_addr); 103.20 @@ -705,6 +713,12 @@ 103.21 object_iterate_from(bm, blk); 103.22 } 103.23 103.24 +// For a continguous space object_iterate() and safe_object_iterate() 103.25 +// are the same. 103.26 +void ContiguousSpace::safe_object_iterate(ObjectClosure* blk) { 103.27 + object_iterate(blk); 103.28 +} 103.29 + 103.30 void ContiguousSpace::object_iterate_from(WaterMark mark, ObjectClosure* blk) { 103.31 assert(mark.space() == this, "Mark does not match space"); 103.32 HeapWord* p = mark.point();
104.1 --- a/src/share/vm/memory/space.hpp Sat Jan 31 17:19:42 2009 -0800 104.2 +++ b/src/share/vm/memory/space.hpp Fri Feb 27 15:13:00 2009 -0800 104.3 @@ -193,6 +193,9 @@ 104.4 // each. Objects allocated by applications of the closure are not 104.5 // included in the iteration. 104.6 virtual void object_iterate(ObjectClosure* blk) = 0; 104.7 + // Similar to object_iterate() except only iterates over 104.8 + // objects whose internal references point to objects in the space. 104.9 + virtual void safe_object_iterate(ObjectClosure* blk) = 0; 104.10 104.11 // Iterate over all objects that intersect with mr, calling "cl->do_object" 104.12 // on each. There is an exception to this: if this closure has already 104.13 @@ -843,6 +846,9 @@ 104.14 void oop_iterate(OopClosure* cl); 104.15 void oop_iterate(MemRegion mr, OopClosure* cl); 104.16 void object_iterate(ObjectClosure* blk); 104.17 + // For contiguous spaces this method will iterate safely over objects 104.18 + // in the space (i.e., between bottom and top) when at a safepoint. 104.19 + void safe_object_iterate(ObjectClosure* blk); 104.20 void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); 104.21 // iterates on objects up to the safe limit 104.22 HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
105.1 --- a/src/share/vm/oops/constMethodKlass.cpp Sat Jan 31 17:19:42 2009 -0800 105.2 +++ b/src/share/vm/oops/constMethodKlass.cpp Fri Feb 27 15:13:00 2009 -0800 105.3 @@ -49,10 +49,16 @@ 105.4 return constMethodOop(obj)->object_is_parsable(); 105.5 } 105.6 105.7 +bool constMethodKlass::oop_is_conc_safe(oop obj) const { 105.8 + assert(obj->is_constMethod(), "must be constMethod oop"); 105.9 + return constMethodOop(obj)->is_conc_safe(); 105.10 +} 105.11 + 105.12 constMethodOop constMethodKlass::allocate(int byte_code_size, 105.13 int compressed_line_number_size, 105.14 int localvariable_table_length, 105.15 int checked_exceptions_length, 105.16 + bool is_conc_safe, 105.17 TRAPS) { 105.18 105.19 int size = constMethodOopDesc::object_size(byte_code_size, 105.20 @@ -75,6 +81,7 @@ 105.21 compressed_line_number_size, 105.22 localvariable_table_length); 105.23 assert(cm->size() == size, "wrong size for object"); 105.24 + cm->set_is_conc_safe(is_conc_safe); 105.25 cm->set_partially_loaded(); 105.26 assert(cm->is_parsable(), "Is safely parsable by gc"); 105.27 return cm;
106.1 --- a/src/share/vm/oops/constMethodKlass.hpp Sat Jan 31 17:19:42 2009 -0800 106.2 +++ b/src/share/vm/oops/constMethodKlass.hpp Fri Feb 27 15:13:00 2009 -0800 106.3 @@ -32,12 +32,16 @@ 106.4 // Testing 106.5 bool oop_is_constMethod() const { return true; } 106.6 virtual bool oop_is_parsable(oop obj) const; 106.7 + virtual bool oop_is_conc_safe(oop obj) const; 106.8 + 106.9 106.10 // Allocation 106.11 DEFINE_ALLOCATE_PERMANENT(constMethodKlass); 106.12 constMethodOop allocate(int byte_code_size, int compressed_line_number_size, 106.13 int localvariable_table_length, 106.14 - int checked_exceptions_length, TRAPS); 106.15 + int checked_exceptions_length, 106.16 + bool is_conc_safe, 106.17 + TRAPS); 106.18 static klassOop create_klass(TRAPS); 106.19 106.20 // Sizing
107.1 --- a/src/share/vm/oops/constMethodOop.hpp Sat Jan 31 17:19:42 2009 -0800 107.2 +++ b/src/share/vm/oops/constMethodOop.hpp Fri Feb 27 15:13:00 2009 -0800 107.3 @@ -104,6 +104,7 @@ 107.4 // loads and stores. This value may updated and read without a lock by 107.5 // multiple threads, so is volatile. 107.6 volatile uint64_t _fingerprint; 107.7 + volatile bool _is_conc_safe; // if true, safe for concurrent GC processing 107.8 107.9 public: 107.10 oop* oop_block_beg() const { return adr_method(); } 107.11 @@ -273,6 +274,8 @@ 107.12 oop* adr_method() const { return (oop*)&_method; } 107.13 oop* adr_stackmap_data() const { return (oop*)&_stackmap_data; } 107.14 oop* adr_exception_table() const { return (oop*)&_exception_table; } 107.15 + bool is_conc_safe() { return _is_conc_safe; } 107.16 + void set_is_conc_safe(bool v) { _is_conc_safe = v; } 107.17 107.18 // Unique id for the method 107.19 static const u2 MAX_IDNUM;
108.1 --- a/src/share/vm/oops/constantPoolKlass.cpp Sat Jan 31 17:19:42 2009 -0800 108.2 +++ b/src/share/vm/oops/constantPoolKlass.cpp Fri Feb 27 15:13:00 2009 -0800 108.3 @@ -25,7 +25,7 @@ 108.4 # include "incls/_precompiled.incl" 108.5 # include "incls/_constantPoolKlass.cpp.incl" 108.6 108.7 -constantPoolOop constantPoolKlass::allocate(int length, TRAPS) { 108.8 +constantPoolOop constantPoolKlass::allocate(int length, bool is_conc_safe, TRAPS) { 108.9 int size = constantPoolOopDesc::object_size(length); 108.10 KlassHandle klass (THREAD, as_klassOop()); 108.11 constantPoolOop c = 108.12 @@ -38,6 +38,9 @@ 108.13 c->set_flags(0); 108.14 // only set to non-zero if constant pool is merged by RedefineClasses 108.15 c->set_orig_length(0); 108.16 + // if constant pool may change during RedefineClasses, it is created 108.17 + // unsafe for GC concurrent processing. 108.18 + c->set_is_conc_safe(is_conc_safe); 108.19 // all fields are initialized; needed for GC 108.20 108.21 // initialize tag array 108.22 @@ -207,6 +210,11 @@ 108.23 return size; 108.24 } 108.25 108.26 +bool constantPoolKlass::oop_is_conc_safe(oop obj) const { 108.27 + assert(obj->is_constantPool(), "must be constantPool"); 108.28 + return constantPoolOop(obj)->is_conc_safe(); 108.29 +} 108.30 + 108.31 #ifndef SERIALGC 108.32 int constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 108.33 assert (obj->is_constantPool(), "obj must be constant pool");
109.1 --- a/src/share/vm/oops/constantPoolKlass.hpp Sat Jan 31 17:19:42 2009 -0800 109.2 +++ b/src/share/vm/oops/constantPoolKlass.hpp Fri Feb 27 15:13:00 2009 -0800 109.3 @@ -34,7 +34,7 @@ 109.4 109.5 // Allocation 109.6 DEFINE_ALLOCATE_PERMANENT(constantPoolKlass); 109.7 - constantPoolOop allocate(int length, TRAPS); 109.8 + constantPoolOop allocate(int length, bool is_conc_safe, TRAPS); 109.9 static klassOop create_klass(TRAPS); 109.10 109.11 // Casting from klassOop 109.12 @@ -48,6 +48,8 @@ 109.13 int object_size() const { return align_object_size(header_size()); } 109.14 109.15 // Garbage collection 109.16 + // Returns true is the object is safe for GC concurrent processing. 109.17 + virtual bool oop_is_conc_safe(oop obj) const; 109.18 void oop_follow_contents(oop obj); 109.19 int oop_adjust_pointers(oop obj); 109.20
110.1 --- a/src/share/vm/oops/constantPoolOop.cpp Sat Jan 31 17:19:42 2009 -0800 110.2 +++ b/src/share/vm/oops/constantPoolOop.cpp Fri Feb 27 15:13:00 2009 -0800 110.3 @@ -962,7 +962,7 @@ 110.4 } 110.5 case JVM_CONSTANT_Long: { 110.6 u8 val = Bytes::get_Java_u8(bytes); 110.7 - printf("long %lldl", *(jlong *) &val); 110.8 + printf("long "INT64_FORMAT, *(jlong *) &val); 110.9 ent_size = 8; 110.10 idx++; // Long takes two cpool slots 110.11 break;
111.1 --- a/src/share/vm/oops/constantPoolOop.hpp Sat Jan 31 17:19:42 2009 -0800 111.2 +++ b/src/share/vm/oops/constantPoolOop.hpp Fri Feb 27 15:13:00 2009 -0800 111.3 @@ -43,6 +43,8 @@ 111.4 klassOop _pool_holder; // the corresponding class 111.5 int _flags; // a few header bits to describe contents for GC 111.6 int _length; // number of elements in the array 111.7 + volatile bool _is_conc_safe; // if true, safe for concurrent 111.8 + // GC processing 111.9 // only set to non-zero if constant pool is merged by RedefineClasses 111.10 int _orig_length; 111.11 111.12 @@ -379,6 +381,9 @@ 111.13 static int object_size(int length) { return align_object_size(header_size() + length); } 111.14 int object_size() { return object_size(length()); } 111.15 111.16 + bool is_conc_safe() { return _is_conc_safe; } 111.17 + void set_is_conc_safe(bool v) { _is_conc_safe = v; } 111.18 + 111.19 friend class constantPoolKlass; 111.20 friend class ClassFileParser; 111.21 friend class SystemDictionary;
112.1 --- a/src/share/vm/oops/cpCacheKlass.cpp Sat Jan 31 17:19:42 2009 -0800 112.2 +++ b/src/share/vm/oops/cpCacheKlass.cpp Fri Feb 27 15:13:00 2009 -0800 112.3 @@ -32,13 +32,43 @@ 112.4 } 112.5 112.6 112.7 -constantPoolCacheOop constantPoolCacheKlass::allocate(int length, TRAPS) { 112.8 +constantPoolCacheOop constantPoolCacheKlass::allocate(int length, 112.9 + bool is_conc_safe, 112.10 + TRAPS) { 112.11 // allocate memory 112.12 int size = constantPoolCacheOopDesc::object_size(length); 112.13 + 112.14 KlassHandle klass (THREAD, as_klassOop()); 112.15 - constantPoolCacheOop cache = (constantPoolCacheOop) 112.16 - CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); 112.17 + 112.18 + // This is the original code. The code from permanent_obj_allocate() 112.19 + // was in-lined to allow the setting of is_conc_safe before the klass 112.20 + // is installed. 112.21 + // constantPoolCacheOop cache = (constantPoolCacheOop) 112.22 + // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); 112.23 + 112.24 + oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); 112.25 + constantPoolCacheOop cache = (constantPoolCacheOop) obj; 112.26 + cache->set_is_conc_safe(is_conc_safe); 112.27 + // The store to is_conc_safe must be visible before the klass 112.28 + // is set. This should be done safely because _is_conc_safe has 112.29 + // been declared volatile. If there are any problems, consider adding 112.30 + // OrderAccess::storestore(); 112.31 + CollectedHeap::post_allocation_install_obj_klass(klass, obj, size); 112.32 + NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, 112.33 + size)); 112.34 + 112.35 + // The length field affects the size of the object. The allocation 112.36 + // above allocates the correct size (see calculation of "size") but 112.37 + // the size() method of the constant pool cache oop will not reflect 112.38 + // that size until the correct length is set. 112.39 cache->set_length(length); 112.40 + 112.41 + // The store of the length must be visible before is_conc_safe is 112.42 + // set to a safe state. 112.43 + // This should be done safely because _is_conc_safe has 112.44 + // been declared volatile. If there are any problems, consider adding 112.45 + // OrderAccess::storestore(); 112.46 + cache->set_is_conc_safe(methodOopDesc::IsSafeConc); 112.47 cache->set_constant_pool(NULL); 112.48 return cache; 112.49 } 112.50 @@ -114,7 +144,6 @@ 112.51 return size; 112.52 } 112.53 112.54 - 112.55 int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { 112.56 assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); 112.57 constantPoolCacheOop cache = (constantPoolCacheOop)obj; 112.58 @@ -131,6 +160,11 @@ 112.59 return size; 112.60 } 112.61 112.62 +bool constantPoolCacheKlass::oop_is_conc_safe(oop obj) const { 112.63 + assert(obj->is_constantPoolCache(), "should be constant pool"); 112.64 + return constantPoolCacheOop(obj)->is_conc_safe(); 112.65 +} 112.66 + 112.67 #ifndef SERIALGC 112.68 void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm, 112.69 oop obj) {
113.1 --- a/src/share/vm/oops/cpCacheKlass.hpp Sat Jan 31 17:19:42 2009 -0800 113.2 +++ b/src/share/vm/oops/cpCacheKlass.hpp Fri Feb 27 15:13:00 2009 -0800 113.3 @@ -32,7 +32,7 @@ 113.4 113.5 // Allocation 113.6 DEFINE_ALLOCATE_PERMANENT(constantPoolCacheKlass); 113.7 - constantPoolCacheOop allocate(int length, TRAPS); 113.8 + constantPoolCacheOop allocate(int length, bool is_conc_safe, TRAPS); 113.9 static klassOop create_klass(TRAPS); 113.10 113.11 // Casting from klassOop 113.12 @@ -48,6 +48,7 @@ 113.13 // Garbage collection 113.14 void oop_follow_contents(oop obj); 113.15 int oop_adjust_pointers(oop obj); 113.16 + virtual bool oop_is_conc_safe(oop obj) const; 113.17 113.18 // Parallel Scavenge and Parallel Old 113.19 PARALLEL_GC_DECLS
114.1 --- a/src/share/vm/oops/cpCacheOop.hpp Sat Jan 31 17:19:42 2009 -0800 114.2 +++ b/src/share/vm/oops/cpCacheOop.hpp Fri Feb 27 15:13:00 2009 -0800 114.3 @@ -291,6 +291,9 @@ 114.4 private: 114.5 int _length; 114.6 constantPoolOop _constant_pool; // the corresponding constant pool 114.7 + // If true, safe for concurrent GC processing, 114.8 + // Set unconditionally in constantPoolCacheKlass::allocate() 114.9 + volatile bool _is_conc_safe; 114.10 114.11 // Sizing 114.12 debug_only(friend class ClassVerifier;) 114.13 @@ -316,6 +319,12 @@ 114.14 constantPoolOop constant_pool() const { return _constant_pool; } 114.15 ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; } 114.16 114.17 + // GC support 114.18 + // If the _length field has not been set, the size of the 114.19 + // constantPoolCache cannot be correctly calculated. 114.20 + bool is_conc_safe() { return _is_conc_safe; } 114.21 + void set_is_conc_safe(bool v) { _is_conc_safe = v; } 114.22 + 114.23 // Code generation 114.24 static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } 114.25
115.1 --- a/src/share/vm/oops/klass.hpp Sat Jan 31 17:19:42 2009 -0800 115.2 +++ b/src/share/vm/oops/klass.hpp Fri Feb 27 15:13:00 2009 -0800 115.3 @@ -606,8 +606,19 @@ 115.4 #undef assert_same_query 115.5 115.6 // Unless overridden, oop is parsable if it has a klass pointer. 115.7 + // Parsability of an object is object specific. 115.8 virtual bool oop_is_parsable(oop obj) const { return true; } 115.9 115.10 + // Unless overridden, oop is safe for concurrent GC processing 115.11 + // after its allocation is complete. The exception to 115.12 + // this is the case where objects are changed after allocation. 115.13 + // Class redefinition is one of the known exceptions. During 115.14 + // class redefinition, an allocated class can changed in order 115.15 + // order to create a merged class (the combiniation of the 115.16 + // old class definition that has to be perserved and the new class 115.17 + // definition which is being created. 115.18 + virtual bool oop_is_conc_safe(oop obj) const { return true; } 115.19 + 115.20 // Access flags 115.21 AccessFlags access_flags() const { return _access_flags; } 115.22 void set_access_flags(AccessFlags flags) { _access_flags = flags; }
116.1 --- a/src/share/vm/oops/methodOop.cpp Sat Jan 31 17:19:42 2009 -0800 116.2 +++ b/src/share/vm/oops/methodOop.cpp Fri Feb 27 15:13:00 2009 -0800 116.3 @@ -792,15 +792,34 @@ 116.4 AccessFlags flags = m->access_flags(); 116.5 int checked_exceptions_len = m->checked_exceptions_length(); 116.6 int localvariable_len = m->localvariable_table_length(); 116.7 - methodOop newm_oop = oopFactory::new_method(new_code_length, flags, new_compressed_linenumber_size, localvariable_len, checked_exceptions_len, CHECK_(methodHandle())); 116.8 + // Allocate newm_oop with the is_conc_safe parameter set 116.9 + // to IsUnsafeConc to indicate that newm_oop is not yet 116.10 + // safe for concurrent processing by a GC. 116.11 + methodOop newm_oop = oopFactory::new_method(new_code_length, 116.12 + flags, 116.13 + new_compressed_linenumber_size, 116.14 + localvariable_len, 116.15 + checked_exceptions_len, 116.16 + IsUnsafeConc, 116.17 + CHECK_(methodHandle())); 116.18 methodHandle newm (THREAD, newm_oop); 116.19 int new_method_size = newm->method_size(); 116.20 // Create a shallow copy of methodOopDesc part, but be careful to preserve the new constMethodOop 116.21 constMethodOop newcm = newm->constMethod(); 116.22 int new_const_method_size = newm->constMethod()->object_size(); 116.23 + 116.24 memcpy(newm(), m(), sizeof(methodOopDesc)); 116.25 // Create shallow copy of constMethodOopDesc, but be careful to preserve the methodOop 116.26 + // is_conc_safe is set to false because that is the value of 116.27 + // is_conc_safe initialzied into newcm and the copy should 116.28 + // not overwrite that value. During the window during which it is 116.29 + // tagged as unsafe, some extra work could be needed during precleaning 116.30 + // or concurrent marking but those phases will be correct. Setting and 116.31 + // resetting is done in preference to a careful copying into newcm to 116.32 + // avoid having to know the precise layout of a constMethodOop. 116.33 + m->constMethod()->set_is_conc_safe(false); 116.34 memcpy(newcm, m->constMethod(), sizeof(constMethodOopDesc)); 116.35 + m->constMethod()->set_is_conc_safe(true); 116.36 // Reset correct method/const method, method size, and parameter info 116.37 newcm->set_method(newm()); 116.38 newm->set_constMethod(newcm); 116.39 @@ -831,6 +850,10 @@ 116.40 m->localvariable_table_start(), 116.41 localvariable_len * sizeof(LocalVariableTableElement)); 116.42 } 116.43 + 116.44 + // Only set is_conc_safe to true when changes to newcm are 116.45 + // complete. 116.46 + newcm->set_is_conc_safe(true); 116.47 return newm; 116.48 } 116.49
117.1 --- a/src/share/vm/oops/methodOop.hpp Sat Jan 31 17:19:42 2009 -0800 117.2 +++ b/src/share/vm/oops/methodOop.hpp Fri Feb 27 15:13:00 2009 -0800 117.3 @@ -129,6 +129,10 @@ 117.4 volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry 117.5 117.6 public: 117.7 + 117.8 + static const bool IsUnsafeConc = false; 117.9 + static const bool IsSafeConc = true; 117.10 + 117.11 // accessors for instance variables 117.12 constMethodOop constMethod() const { return _constMethod; } 117.13 void set_constMethod(constMethodOop xconst) { oop_store_without_check((oop*)&_constMethod, (oop)xconst); }
118.1 --- a/src/share/vm/oops/oop.hpp Sat Jan 31 17:19:42 2009 -0800 118.2 +++ b/src/share/vm/oops/oop.hpp Fri Feb 27 15:13:00 2009 -0800 118.3 @@ -108,6 +108,13 @@ 118.4 // installation of their klass pointer. 118.5 bool is_parsable(); 118.6 118.7 + // Some perm gen objects that have been allocated and initialized 118.8 + // can be changed by the VM when not at a safe point (class rededfinition 118.9 + // is an example). Such objects should not be examined by the 118.10 + // concurrent processing of a garbage collector if is_conc_safe() 118.11 + // returns false. 118.12 + bool is_conc_safe(); 118.13 + 118.14 // type test operations (inlined in oop.inline.h) 118.15 bool is_instance() const; 118.16 bool is_instanceRef() const;
119.1 --- a/src/share/vm/oops/oop.inline.hpp Sat Jan 31 17:19:42 2009 -0800 119.2 +++ b/src/share/vm/oops/oop.inline.hpp Fri Feb 27 15:13:00 2009 -0800 119.3 @@ -435,6 +435,10 @@ 119.4 return blueprint()->oop_is_parsable(this); 119.5 } 119.6 119.7 +inline bool oopDesc::is_conc_safe() { 119.8 + return blueprint()->oop_is_conc_safe(this); 119.9 +} 119.10 + 119.11 inline void update_barrier_set(void* p, oop v) { 119.12 assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); 119.13 oopDesc::bs()->write_ref_field(p, v);
120.1 --- a/src/share/vm/oops/oopsHierarchy.hpp Sat Jan 31 17:19:42 2009 -0800 120.2 +++ b/src/share/vm/oops/oopsHierarchy.hpp Fri Feb 27 15:13:00 2009 -0800 120.3 @@ -126,8 +126,11 @@ 120.4 operator jobject () const { return (jobject)obj(); } 120.5 // from javaClasses.cpp 120.6 operator JavaThread* () const { return (JavaThread*)obj(); } 120.7 + 120.8 +#ifndef _LP64 120.9 // from jvm.cpp 120.10 operator jlong* () const { return (jlong*)obj(); } 120.11 +#endif 120.12 120.13 // from parNewGeneration and other things that want to get to the end of 120.14 // an oop for stuff (like constMethodKlass.cpp, objArrayKlass.cpp)
121.1 --- a/src/share/vm/opto/block.cpp Sat Jan 31 17:19:42 2009 -0800 121.2 +++ b/src/share/vm/opto/block.cpp Fri Feb 27 15:13:00 2009 -0800 121.3 @@ -880,6 +880,7 @@ 121.4 } 121.5 121.6 void PhaseCFG::verify( ) const { 121.7 +#ifdef ASSERT 121.8 // Verify sane CFG 121.9 for( uint i = 0; i < _num_blocks; i++ ) { 121.10 Block *b = _blocks[i]; 121.11 @@ -894,10 +895,20 @@ 121.12 "CreateEx must be first instruction in block" ); 121.13 } 121.14 for( uint k = 0; k < n->req(); k++ ) { 121.15 - Node *use = n->in(k); 121.16 - if( use && use != n ) { 121.17 - assert( _bbs[use->_idx] || use->is_Con(), 121.18 + Node *def = n->in(k); 121.19 + if( def && def != n ) { 121.20 + assert( _bbs[def->_idx] || def->is_Con(), 121.21 "must have block; constants for debug info ok" ); 121.22 + // Verify that instructions in the block is in correct order. 121.23 + // Uses must follow their definition if they are at the same block. 121.24 + // Mostly done to check that MachSpillCopy nodes are placed correctly 121.25 + // when CreateEx node is moved in build_ifg_physical(). 121.26 + if( _bbs[def->_idx] == b && 121.27 + !(b->head()->is_Loop() && n->is_Phi()) && 121.28 + // See (+++) comment in reg_split.cpp 121.29 + !(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) { 121.30 + assert( b->find_node(def) < j, "uses must follow definitions" ); 121.31 + } 121.32 } 121.33 } 121.34 } 121.35 @@ -914,6 +925,7 @@ 121.36 assert( b->_num_succs == 2, "Conditional branch must have two targets"); 121.37 } 121.38 } 121.39 +#endif 121.40 } 121.41 #endif 121.42
122.1 --- a/src/share/vm/opto/c2_globals.hpp Sat Jan 31 17:19:42 2009 -0800 122.2 +++ b/src/share/vm/opto/c2_globals.hpp Fri Feb 27 15:13:00 2009 -0800 122.3 @@ -191,6 +191,9 @@ 122.4 notproduct(bool, VerifyHashTableKeys, true, \ 122.5 "Verify the immutability of keys in the VN hash tables") \ 122.6 \ 122.7 + notproduct(bool, VerifyRegisterAllocator , false, \ 122.8 + "Verify Register Allocator") \ 122.9 + \ 122.10 develop_pd(intx, FLOATPRESSURE, \ 122.11 "Number of float LRG's that constitute high register pressure") \ 122.12 \
123.1 --- a/src/share/vm/opto/cfgnode.cpp Sat Jan 31 17:19:42 2009 -0800 123.2 +++ b/src/share/vm/opto/cfgnode.cpp Fri Feb 27 15:13:00 2009 -0800 123.3 @@ -858,12 +858,18 @@ 123.4 // convert the one to the other. 123.5 const TypePtr* ttp = _type->make_ptr(); 123.6 const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL; 123.7 + const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_klassptr() : NULL; 123.8 bool is_intf = false; 123.9 if (ttip != NULL) { 123.10 ciKlass* k = ttip->klass(); 123.11 if (k->is_loaded() && k->is_interface()) 123.12 is_intf = true; 123.13 } 123.14 + if (ttkp != NULL) { 123.15 + ciKlass* k = ttkp->klass(); 123.16 + if (k->is_loaded() && k->is_interface()) 123.17 + is_intf = true; 123.18 + } 123.19 123.20 // Default case: merge all inputs 123.21 const Type *t = Type::TOP; // Merged type starting value 123.22 @@ -921,6 +927,8 @@ 123.23 // uplift the type. 123.24 if( !t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface() ) 123.25 { assert(ft == _type, ""); } // Uplift to interface 123.26 + else if( !t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface() ) 123.27 + { assert(ft == _type, ""); } // Uplift to interface 123.28 // Otherwise it's something stupid like non-overlapping int ranges 123.29 // found on dying counted loops. 123.30 else 123.31 @@ -936,6 +944,7 @@ 123.32 // because the type system doesn't interact well with interfaces. 123.33 const TypePtr *jtp = jt->make_ptr(); 123.34 const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL; 123.35 + const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_klassptr() : NULL; 123.36 if( jtip && ttip ) { 123.37 if( jtip->is_loaded() && jtip->klass()->is_interface() && 123.38 ttip->is_loaded() && !ttip->klass()->is_interface() ) { 123.39 @@ -945,6 +954,14 @@ 123.40 jt = ft; 123.41 } 123.42 } 123.43 + if( jtkp && ttkp ) { 123.44 + if( jtkp->is_loaded() && jtkp->klass()->is_interface() && 123.45 + ttkp->is_loaded() && !ttkp->klass()->is_interface() ) { 123.46 + assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) || 123.47 + ft->isa_narrowoop() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), ""); 123.48 + jt = ft; 123.49 + } 123.50 + } 123.51 if (jt != ft && jt->base() == ft->base()) { 123.52 if (jt->isa_int() && 123.53 jt->is_int()->_lo == ft->is_int()->_lo &&
124.1 --- a/src/share/vm/opto/chaitin.cpp Sat Jan 31 17:19:42 2009 -0800 124.2 +++ b/src/share/vm/opto/chaitin.cpp Fri Feb 27 15:13:00 2009 -0800 124.3 @@ -228,6 +228,11 @@ 124.4 // them for real. 124.5 de_ssa(); 124.6 124.7 +#ifdef ASSERT 124.8 + // Veify the graph before RA. 124.9 + verify(&live_arena); 124.10 +#endif 124.11 + 124.12 { 124.13 NOT_PRODUCT( Compile::TracePhase t3("computeLive", &_t_computeLive, TimeCompiler); ) 124.14 _live = NULL; // Mark live as being not available 124.15 @@ -306,12 +311,6 @@ 124.16 C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after physical split"); 124.17 if (C->failing()) return; 124.18 124.19 -#ifdef ASSERT 124.20 - if( VerifyOpto ) { 124.21 - _cfg.verify(); 124.22 - verify_base_ptrs(&live_arena); 124.23 - } 124.24 -#endif 124.25 NOT_PRODUCT( C->verify_graph_edges(); ) 124.26 124.27 compact(); // Compact LRGs; return new lower max lrg 124.28 @@ -340,7 +339,7 @@ 124.29 compress_uf_map_for_nodes(); 124.30 124.31 #ifdef ASSERT 124.32 - if( VerifyOpto ) _ifg->verify(this); 124.33 + verify(&live_arena, true); 124.34 #endif 124.35 } else { 124.36 ifg.SquareUp(); 124.37 @@ -376,12 +375,6 @@ 124.38 // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) 124.39 C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after split"); 124.40 if (C->failing()) return; 124.41 -#ifdef ASSERT 124.42 - if( VerifyOpto ) { 124.43 - _cfg.verify(); 124.44 - verify_base_ptrs(&live_arena); 124.45 - } 124.46 -#endif 124.47 124.48 compact(); // Compact LRGs; return new lower max lrg 124.49 124.50 @@ -412,7 +405,7 @@ 124.51 } 124.52 compress_uf_map_for_nodes(); 124.53 #ifdef ASSERT 124.54 - if( VerifyOpto ) _ifg->verify(this); 124.55 + verify(&live_arena, true); 124.56 #endif 124.57 cache_lrg_info(); // Count degree of LRGs 124.58 124.59 @@ -432,6 +425,11 @@ 124.60 // Peephole remove copies 124.61 post_allocate_copy_removal(); 124.62 124.63 +#ifdef ASSERT 124.64 + // Veify the graph after RA. 124.65 + verify(&live_arena); 124.66 +#endif 124.67 + 124.68 // max_reg is past the largest *register* used. 124.69 // Convert that to a frame_slot number. 124.70 if( _max_reg <= _matcher._new_SP ) 124.71 @@ -956,7 +954,7 @@ 124.72 while ((neighbor = elements.next()) != 0) { 124.73 LRG *n = &lrgs(neighbor); 124.74 #ifdef ASSERT 124.75 - if( VerifyOpto ) { 124.76 + if( VerifyOpto || VerifyRegisterAllocator ) { 124.77 assert( _ifg->effective_degree(neighbor) == n->degree(), "" ); 124.78 } 124.79 #endif
125.1 --- a/src/share/vm/opto/chaitin.hpp Sat Jan 31 17:19:42 2009 -0800 125.2 +++ b/src/share/vm/opto/chaitin.hpp Fri Feb 27 15:13:00 2009 -0800 125.3 @@ -491,6 +491,8 @@ 125.4 // Verify that base pointers and derived pointers are still sane 125.5 void verify_base_ptrs( ResourceArea *a ) const; 125.6 125.7 + void verify( ResourceArea *a, bool verify_ifg = false ) const; 125.8 + 125.9 void dump_for_spill_split_recycle() const; 125.10 125.11 public:
126.1 --- a/src/share/vm/opto/classes.hpp Sat Jan 31 17:19:42 2009 -0800 126.2 +++ b/src/share/vm/opto/classes.hpp Fri Feb 27 15:13:00 2009 -0800 126.3 @@ -129,7 +129,7 @@ 126.4 macro(LShiftI) 126.5 macro(LShiftL) 126.6 macro(LoadB) 126.7 -macro(LoadC) 126.8 +macro(LoadUS) 126.9 macro(LoadD) 126.10 macro(LoadD_unaligned) 126.11 macro(LoadF)
127.1 --- a/src/share/vm/opto/compile.cpp Sat Jan 31 17:19:42 2009 -0800 127.2 +++ b/src/share/vm/opto/compile.cpp Fri Feb 27 15:13:00 2009 -0800 127.3 @@ -2005,7 +2005,7 @@ 127.4 case Op_StoreP: 127.5 case Op_StoreN: 127.6 case Op_LoadB: 127.7 - case Op_LoadC: 127.8 + case Op_LoadUS: 127.9 case Op_LoadI: 127.10 case Op_LoadKlass: 127.11 case Op_LoadNKlass:
128.1 --- a/src/share/vm/opto/divnode.cpp Sat Jan 31 17:19:42 2009 -0800 128.2 +++ b/src/share/vm/opto/divnode.cpp Fri Feb 27 15:13:00 2009 -0800 128.3 @@ -1,5 +1,5 @@ 128.4 /* 128.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 128.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 128.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 128.8 * 128.9 * This code is free software; you can redistribute it and/or modify it 128.10 @@ -244,42 +244,73 @@ 128.11 128.12 //---------------------long_by_long_mulhi-------------------------------------- 128.13 // Generate ideal node graph for upper half of a 64 bit x 64 bit multiplication 128.14 -static Node *long_by_long_mulhi( PhaseGVN *phase, Node *dividend, jlong magic_const) { 128.15 +static Node* long_by_long_mulhi(PhaseGVN* phase, Node* dividend, jlong magic_const) { 128.16 // If the architecture supports a 64x64 mulhi, there is 128.17 // no need to synthesize it in ideal nodes. 128.18 if (Matcher::has_match_rule(Op_MulHiL)) { 128.19 - Node *v = phase->longcon(magic_const); 128.20 + Node* v = phase->longcon(magic_const); 128.21 return new (phase->C, 3) MulHiLNode(dividend, v); 128.22 } 128.23 128.24 + // Taken from Hacker's Delight, Fig. 8-2. Multiply high signed. 128.25 + // (http://www.hackersdelight.org/HDcode/mulhs.c) 128.26 + // 128.27 + // int mulhs(int u, int v) { 128.28 + // unsigned u0, v0, w0; 128.29 + // int u1, v1, w1, w2, t; 128.30 + // 128.31 + // u0 = u & 0xFFFF; u1 = u >> 16; 128.32 + // v0 = v & 0xFFFF; v1 = v >> 16; 128.33 + // w0 = u0*v0; 128.34 + // t = u1*v0 + (w0 >> 16); 128.35 + // w1 = t & 0xFFFF; 128.36 + // w2 = t >> 16; 128.37 + // w1 = u0*v1 + w1; 128.38 + // return u1*v1 + w2 + (w1 >> 16); 128.39 + // } 128.40 + // 128.41 + // Note: The version above is for 32x32 multiplications, while the 128.42 + // following inline comments are adapted to 64x64. 128.43 + 128.44 const int N = 64; 128.45 128.46 - Node *u_hi = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); 128.47 - Node *u_lo = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); 128.48 + // u0 = u & 0xFFFFFFFF; u1 = u >> 32; 128.49 + Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); 128.50 + Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); 128.51 128.52 - Node *v_hi = phase->longcon(magic_const >> N/2); 128.53 - Node *v_lo = phase->longcon(magic_const & 0XFFFFFFFF); 128.54 + // v0 = v & 0xFFFFFFFF; v1 = v >> 32; 128.55 + Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF); 128.56 + Node* v1 = phase->longcon(magic_const >> (N / 2)); 128.57 128.58 - Node *hihi_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_hi)); 128.59 - Node *hilo_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_lo)); 128.60 - Node *lohi_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_hi)); 128.61 - Node *lolo_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_lo)); 128.62 + // w0 = u0*v0; 128.63 + Node* w0 = phase->transform(new (phase->C, 3) MulLNode(u0, v0)); 128.64 128.65 - Node *t1 = phase->transform(new (phase->C, 3) URShiftLNode(lolo_product, phase->intcon(N / 2))); 128.66 - Node *t2 = phase->transform(new (phase->C, 3) AddLNode(hilo_product, t1)); 128.67 + // t = u1*v0 + (w0 >> 32); 128.68 + Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0)); 128.69 + Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2))); 128.70 + Node* t = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp)); 128.71 128.72 - // Construct both t3 and t4 before transforming so t2 doesn't go dead 128.73 - // prematurely. 128.74 - Node *t3 = new (phase->C, 3) RShiftLNode(t2, phase->intcon(N / 2)); 128.75 - Node *t4 = new (phase->C, 3) AndLNode(t2, phase->longcon(0xFFFFFFFF)); 128.76 - t3 = phase->transform(t3); 128.77 - t4 = phase->transform(t4); 128.78 + // w1 = t & 0xFFFFFFFF; 128.79 + Node* w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF)); 128.80 128.81 - Node *t5 = phase->transform(new (phase->C, 3) AddLNode(t4, lohi_product)); 128.82 - Node *t6 = phase->transform(new (phase->C, 3) RShiftLNode(t5, phase->intcon(N / 2))); 128.83 - Node *t7 = phase->transform(new (phase->C, 3) AddLNode(t3, hihi_product)); 128.84 + // w2 = t >> 32; 128.85 + Node* w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2)); 128.86 128.87 - return new (phase->C, 3) AddLNode(t7, t6); 128.88 + // 6732154: Construct both w1 and w2 before transforming, so t 128.89 + // doesn't go dead prematurely. 128.90 + w1 = phase->transform(w1); 128.91 + w2 = phase->transform(w2); 128.92 + 128.93 + // w1 = u0*v1 + w1; 128.94 + Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1)); 128.95 + w1 = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1)); 128.96 + 128.97 + // return u1*v1 + w2 + (w1 >> 32); 128.98 + Node* u1v1 = phase->transform(new (phase->C, 3) MulLNode(u1, v1)); 128.99 + Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2)); 128.100 + Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2))); 128.101 + 128.102 + return new (phase->C, 3) AddLNode(temp1, temp2); 128.103 } 128.104 128.105 128.106 @@ -976,7 +1007,7 @@ 128.107 128.108 // Expand mod 128.109 if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) { 128.110 - uint k = log2_long(con); // Extract k 128.111 + uint k = exact_log2_long(con+1); // Extract k 128.112 128.113 // Basic algorithm by David Detlefs. See fastmod_long.java for gory details. 128.114 // Used to help a popular random number generator which does a long-mod
129.1 --- a/src/share/vm/opto/gcm.cpp Sat Jan 31 17:19:42 2009 -0800 129.2 +++ b/src/share/vm/opto/gcm.cpp Fri Feb 27 15:13:00 2009 -0800 129.3 @@ -29,6 +29,9 @@ 129.4 #include "incls/_precompiled.incl" 129.5 #include "incls/_gcm.cpp.incl" 129.6 129.7 +// To avoid float value underflow 129.8 +#define MIN_BLOCK_FREQUENCY 1.e-35f 129.9 + 129.10 //----------------------------schedule_node_into_block------------------------- 129.11 // Insert node n into block b. Look for projections of n and make sure they 129.12 // are in b also. 129.13 @@ -1380,6 +1383,13 @@ 129.14 } 129.15 } 129.16 129.17 +#ifdef ASSERT 129.18 + for (uint i = 0; i < _num_blocks; i++ ) { 129.19 + Block *b = _blocks[i]; 129.20 + assert(b->_freq >= MIN_BLOCK_FREQUENCY, "Register Allocator requiers meaningful block frequency"); 129.21 + } 129.22 +#endif 129.23 + 129.24 #ifndef PRODUCT 129.25 if (PrintCFGBlockFreq) { 129.26 tty->print_cr("CFG Block Frequencies"); 129.27 @@ -1877,7 +1887,9 @@ 129.28 float loop_freq = _freq * trip_count(); 129.29 for (int i = 0; i < _members.length(); i++) { 129.30 CFGElement* s = _members.at(i); 129.31 - s->_freq *= loop_freq; 129.32 + float block_freq = s->_freq * loop_freq; 129.33 + if (block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY; 129.34 + s->_freq = block_freq; 129.35 } 129.36 CFGLoop* ch = _child; 129.37 while (ch != NULL) {
130.1 --- a/src/share/vm/opto/graphKit.cpp Sat Jan 31 17:19:42 2009 -0800 130.2 +++ b/src/share/vm/opto/graphKit.cpp Fri Feb 27 15:13:00 2009 -0800 130.3 @@ -1836,10 +1836,7 @@ 130.4 (CardTableModRefBS*)(Universe::heap()->barrier_set()); 130.5 Node *b = _gvn.transform(new (C, 3) URShiftXNode( cast, _gvn.intcon(CardTableModRefBS::card_shift) )); 130.6 // We store into a byte array, so do not bother to left-shift by zero 130.7 - // Get base of card map 130.8 - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), 130.9 - "adjust this code"); 130.10 - Node *c = makecon(TypeRawPtr::make((address)ct->byte_map_base)); 130.11 + Node *c = byte_map_base_node(); 130.12 // Combine 130.13 Node *sb_ctl = control(); 130.14 Node *sb_adr = _gvn.transform(new (C, 4) AddPNode( top()/*no base ptr*/, c, b )); 130.15 @@ -2945,16 +2942,10 @@ 130.16 130.17 // Now generate allocation code 130.18 130.19 - // With escape analysis, the entire memory state is needed to be able to 130.20 - // eliminate the allocation. If the allocations cannot be eliminated, this 130.21 - // will be optimized to the raw slice when the allocation is expanded. 130.22 - Node *mem; 130.23 - if (C->do_escape_analysis()) { 130.24 - mem = reset_memory(); 130.25 - set_all_memory(mem); 130.26 - } else { 130.27 - mem = memory(Compile::AliasIdxRaw); 130.28 - } 130.29 + // The entire memory state is needed for slow path of the allocation 130.30 + // since GC and deoptimization can happened. 130.31 + Node *mem = reset_memory(); 130.32 + set_all_memory(mem); // Create new memory state 130.33 130.34 AllocateNode* alloc 130.35 = new (C, AllocateNode::ParmLimit) 130.36 @@ -3091,16 +3082,10 @@ 130.37 130.38 // Now generate allocation code 130.39 130.40 - // With escape analysis, the entire memory state is needed to be able to 130.41 - // eliminate the allocation. If the allocations cannot be eliminated, this 130.42 - // will be optimized to the raw slice when the allocation is expanded. 130.43 - Node *mem; 130.44 - if (C->do_escape_analysis()) { 130.45 - mem = reset_memory(); 130.46 - set_all_memory(mem); 130.47 - } else { 130.48 - mem = memory(Compile::AliasIdxRaw); 130.49 - } 130.50 + // The entire memory state is needed for slow path of the allocation 130.51 + // since GC and deoptimization can happened. 130.52 + Node *mem = reset_memory(); 130.53 + set_all_memory(mem); // Create new memory state 130.54 130.55 // Create the AllocateArrayNode and its result projections 130.56 AllocateArrayNode* alloc 130.57 @@ -3233,12 +3218,11 @@ 130.58 130.59 // Now some of the values 130.60 130.61 - Node* marking = __ load(no_ctrl, marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw); 130.62 - Node* index = __ load(no_ctrl, index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw); 130.63 - Node* buffer = __ load(no_ctrl, buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); 130.64 + Node* marking = __ load(__ ctrl(), marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw); 130.65 130.66 // if (!marking) 130.67 __ if_then(marking, BoolTest::ne, zero); { 130.68 + Node* index = __ load(__ ctrl(), index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw); 130.69 130.70 const Type* t1 = adr->bottom_type(); 130.71 const Type* t2 = val->bottom_type(); 130.72 @@ -3246,6 +3230,7 @@ 130.73 Node* orig = __ load(no_ctrl, adr, val_type, bt, alias_idx); 130.74 // if (orig != NULL) 130.75 __ if_then(orig, BoolTest::ne, null()); { 130.76 + Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); 130.77 130.78 // load original value 130.79 // alias_idx correct?? 130.80 @@ -3365,14 +3350,6 @@ 130.81 130.82 const TypeFunc *tf = OptoRuntime::g1_wb_post_Type(); 130.83 130.84 - // Get the address of the card table 130.85 - CardTableModRefBS* ct = 130.86 - (CardTableModRefBS*)(Universe::heap()->barrier_set()); 130.87 - Node *card_table = __ makecon(TypeRawPtr::make((address)ct->byte_map_base)); 130.88 - // Get base of card map 130.89 - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); 130.90 - 130.91 - 130.92 // Offsets into the thread 130.93 const int index_offset = in_bytes(JavaThread::dirty_card_queue_offset() + 130.94 PtrQueue::byte_offset_of_index()); 130.95 @@ -3402,7 +3379,7 @@ 130.96 Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) ); 130.97 130.98 // Combine card table base and card offset 130.99 - Node *card_adr = __ AddP(no_base, card_table, card_offset ); 130.100 + Node *card_adr = __ AddP(no_base, byte_map_base_node(), card_offset ); 130.101 130.102 // If we know the value being stored does it cross regions? 130.103
131.1 --- a/src/share/vm/opto/graphKit.hpp Sat Jan 31 17:19:42 2009 -0800 131.2 +++ b/src/share/vm/opto/graphKit.hpp Fri Feb 27 15:13:00 2009 -0800 131.3 @@ -83,6 +83,18 @@ 131.4 Node* zerocon(BasicType bt) const { return _gvn.zerocon(bt); } 131.5 // (See also macro MakeConX in type.hpp, which uses intcon or longcon.) 131.6 131.7 + // Helper for byte_map_base 131.8 + Node* byte_map_base_node() { 131.9 + // Get base of card map 131.10 + CardTableModRefBS* ct = (CardTableModRefBS*)(Universe::heap()->barrier_set()); 131.11 + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust users of this code"); 131.12 + if (ct->byte_map_base != NULL) { 131.13 + return makecon(TypeRawPtr::make((address)ct->byte_map_base)); 131.14 + } else { 131.15 + return null(); 131.16 + } 131.17 + } 131.18 + 131.19 jint find_int_con(Node* n, jint value_if_unknown) { 131.20 return _gvn.find_int_con(n, value_if_unknown); 131.21 }
132.1 --- a/src/share/vm/opto/idealGraphPrinter.cpp Sat Jan 31 17:19:42 2009 -0800 132.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Fri Feb 27 15:13:00 2009 -0800 132.3 @@ -557,7 +557,7 @@ 132.4 132.5 // max. 2 chars allowed 132.6 if (value >= -9 && value <= 99) { 132.7 - sprintf(buffer, "%d", value); 132.8 + sprintf(buffer, INT64_FORMAT, value); 132.9 print_prop(short_name, buffer); 132.10 } else { 132.11 print_prop(short_name, "L");
133.1 --- a/src/share/vm/opto/ifg.cpp Sat Jan 31 17:19:42 2009 -0800 133.2 +++ b/src/share/vm/opto/ifg.cpp Fri Feb 27 15:13:00 2009 -0800 133.3 @@ -471,12 +471,28 @@ 133.4 // for the "collect_gc_info" phase later. 133.5 IndexSet liveout(_live->live(b)); 133.6 uint last_inst = b->end_idx(); 133.7 - // Compute last phi index 133.8 - uint last_phi; 133.9 - for( last_phi = 1; last_phi < last_inst; last_phi++ ) 133.10 - if( !b->_nodes[last_phi]->is_Phi() ) 133.11 + // Compute first nonphi node index 133.12 + uint first_inst; 133.13 + for( first_inst = 1; first_inst < last_inst; first_inst++ ) 133.14 + if( !b->_nodes[first_inst]->is_Phi() ) 133.15 break; 133.16 133.17 + // Spills could be inserted before CreateEx node which should be 133.18 + // first instruction in block after Phis. Move CreateEx up. 133.19 + for( uint insidx = first_inst; insidx < last_inst; insidx++ ) { 133.20 + Node *ex = b->_nodes[insidx]; 133.21 + if( ex->is_SpillCopy() ) continue; 133.22 + if( insidx > first_inst && ex->is_Mach() && 133.23 + ex->as_Mach()->ideal_Opcode() == Op_CreateEx ) { 133.24 + // If the CreateEx isn't above all the MachSpillCopies 133.25 + // then move it to the top. 133.26 + b->_nodes.remove(insidx); 133.27 + b->_nodes.insert(first_inst, ex); 133.28 + } 133.29 + // Stop once a CreateEx or any other node is found 133.30 + break; 133.31 + } 133.32 + 133.33 // Reset block's register pressure values for each ifg construction 133.34 uint pressure[2], hrp_index[2]; 133.35 pressure[0] = pressure[1] = 0; 133.36 @@ -485,7 +501,7 @@ 133.37 // Liveout things are presumed live for the whole block. We accumulate 133.38 // 'area' accordingly. If they get killed in the block, we'll subtract 133.39 // the unused part of the block from the area. 133.40 - int inst_count = last_inst - last_phi; 133.41 + int inst_count = last_inst - first_inst; 133.42 double cost = (inst_count <= 0) ? 0.0 : b->_freq * double(inst_count); 133.43 assert(!(cost < 0.0), "negative spill cost" ); 133.44 IndexSetIterator elements(&liveout);
134.1 --- a/src/share/vm/opto/lcm.cpp Sat Jan 31 17:19:42 2009 -0800 134.2 +++ b/src/share/vm/opto/lcm.cpp Fri Feb 27 15:13:00 2009 -0800 134.3 @@ -107,7 +107,7 @@ 134.4 was_store = false; 134.5 switch( mach->ideal_Opcode() ) { 134.6 case Op_LoadB: 134.7 - case Op_LoadC: 134.8 + case Op_LoadUS: 134.9 case Op_LoadD: 134.10 case Op_LoadF: 134.11 case Op_LoadI:
135.1 --- a/src/share/vm/opto/live.cpp Sat Jan 31 17:19:42 2009 -0800 135.2 +++ b/src/share/vm/opto/live.cpp Fri Feb 27 15:13:00 2009 -0800 135.3 @@ -271,9 +271,9 @@ 135.4 135.5 //------------------------------verify_base_ptrs------------------------------- 135.6 // Verify that base pointers and derived pointers are still sane. 135.7 -// Basically, if a derived pointer is live at a safepoint, then its 135.8 -// base pointer must be live also. 135.9 void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const { 135.10 +#ifdef ASSERT 135.11 + Unique_Node_List worklist(a); 135.12 for( uint i = 0; i < _cfg._num_blocks; i++ ) { 135.13 Block *b = _cfg._blocks[i]; 135.14 for( uint j = b->end_idx() + 1; j > 1; j-- ) { 135.15 @@ -287,28 +287,81 @@ 135.16 // Now scan for a live derived pointer 135.17 if (jvms->oopoff() < sfpt->req()) { 135.18 // Check each derived/base pair 135.19 - for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx += 2) { 135.20 + for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx++) { 135.21 Node *check = sfpt->in(idx); 135.22 - uint j = 0; 135.23 + bool is_derived = ((idx - jvms->oopoff()) & 1) == 0; 135.24 // search upwards through spills and spill phis for AddP 135.25 - while(true) { 135.26 - if( !check ) break; 135.27 - int idx = check->is_Copy(); 135.28 - if( idx ) { 135.29 - check = check->in(idx); 135.30 - } else if( check->is_Phi() && check->_idx >= _oldphi ) { 135.31 - check = check->in(1); 135.32 - } else 135.33 - break; 135.34 - j++; 135.35 - assert(j < 100000,"Derived pointer checking in infinite loop"); 135.36 + worklist.clear(); 135.37 + worklist.push(check); 135.38 + uint k = 0; 135.39 + while( k < worklist.size() ) { 135.40 + check = worklist.at(k); 135.41 + assert(check,"Bad base or derived pointer"); 135.42 + // See PhaseChaitin::find_base_for_derived() for all cases. 135.43 + int isc = check->is_Copy(); 135.44 + if( isc ) { 135.45 + worklist.push(check->in(isc)); 135.46 + } else if( check->is_Phi() ) { 135.47 + for (uint m = 1; m < check->req(); m++) 135.48 + worklist.push(check->in(m)); 135.49 + } else if( check->is_Con() ) { 135.50 + if (is_derived) { 135.51 + // Derived is NULL+offset 135.52 + assert(!is_derived || check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad derived pointer"); 135.53 + } else { 135.54 + assert(check->bottom_type()->is_ptr()->_offset == 0,"Bad base pointer"); 135.55 + // Base either ConP(NULL) or loadConP 135.56 + if (check->is_Mach()) { 135.57 + assert(check->as_Mach()->ideal_Opcode() == Op_ConP,"Bad base pointer"); 135.58 + } else { 135.59 + assert(check->Opcode() == Op_ConP && 135.60 + check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad base pointer"); 135.61 + } 135.62 + } 135.63 + } else if( check->bottom_type()->is_ptr()->_offset == 0 ) { 135.64 + if(check->is_Proj() || check->is_Mach() && 135.65 + (check->as_Mach()->ideal_Opcode() == Op_CreateEx || 135.66 + check->as_Mach()->ideal_Opcode() == Op_ThreadLocal || 135.67 + check->as_Mach()->ideal_Opcode() == Op_CMoveP || 135.68 + check->as_Mach()->ideal_Opcode() == Op_CheckCastPP || 135.69 +#ifdef _LP64 135.70 + UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP || 135.71 + UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN || 135.72 +#endif 135.73 + check->as_Mach()->ideal_Opcode() == Op_LoadP || 135.74 + check->as_Mach()->ideal_Opcode() == Op_LoadKlass)) { 135.75 + // Valid nodes 135.76 + } else { 135.77 + check->dump(); 135.78 + assert(false,"Bad base or derived pointer"); 135.79 + } 135.80 + } else { 135.81 + assert(is_derived,"Bad base pointer"); 135.82 + assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer"); 135.83 + } 135.84 + k++; 135.85 + assert(k < 100000,"Derived pointer checking in infinite loop"); 135.86 } // End while 135.87 - assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer") 135.88 } 135.89 } // End of check for derived pointers 135.90 } // End of Kcheck for debug info 135.91 } // End of if found a safepoint 135.92 } // End of forall instructions in block 135.93 } // End of forall blocks 135.94 +#endif 135.95 } 135.96 + 135.97 +//------------------------------verify------------------------------------- 135.98 +// Verify that graphs and base pointers are still sane. 135.99 +void PhaseChaitin::verify( ResourceArea *a, bool verify_ifg ) const { 135.100 +#ifdef ASSERT 135.101 + if( VerifyOpto || VerifyRegisterAllocator ) { 135.102 + _cfg.verify(); 135.103 + verify_base_ptrs(a); 135.104 + if(verify_ifg) 135.105 + _ifg->verify(this); 135.106 + } 135.107 #endif 135.108 +} 135.109 + 135.110 +#endif
136.1 --- a/src/share/vm/opto/loopnode.cpp Sat Jan 31 17:19:42 2009 -0800 136.2 +++ b/src/share/vm/opto/loopnode.cpp Fri Feb 27 15:13:00 2009 -0800 136.3 @@ -2654,7 +2654,7 @@ 136.4 case Op_ModF: 136.5 case Op_ModD: 136.6 case Op_LoadB: // Same with Loads; they can sink 136.7 - case Op_LoadC: // during loop optimizations. 136.8 + case Op_LoadUS: // during loop optimizations. 136.9 case Op_LoadD: 136.10 case Op_LoadF: 136.11 case Op_LoadI:
137.1 --- a/src/share/vm/opto/macro.cpp Sat Jan 31 17:19:42 2009 -0800 137.2 +++ b/src/share/vm/opto/macro.cpp Fri Feb 27 15:13:00 2009 -0800 137.3 @@ -952,13 +952,6 @@ 137.4 Node* klass_node = alloc->in(AllocateNode::KlassNode); 137.5 Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); 137.6 137.7 - // With escape analysis, the entire memory state was needed to be able to 137.8 - // eliminate the allocation. Since the allocations cannot be eliminated, 137.9 - // optimize it to the raw slice. 137.10 - if (mem->is_MergeMem()) { 137.11 - mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw); 137.12 - } 137.13 - 137.14 assert(ctrl != NULL, "must have control"); 137.15 // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. 137.16 // they will not be used if "always_slow" is set 137.17 @@ -1016,6 +1009,11 @@ 137.18 Node *slow_mem = mem; // save the current memory state for slow path 137.19 // generate the fast allocation code unless we know that the initial test will always go slow 137.20 if (!always_slow) { 137.21 + // Fast path modifies only raw memory. 137.22 + if (mem->is_MergeMem()) { 137.23 + mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw); 137.24 + } 137.25 + 137.26 Node* eden_top_adr; 137.27 Node* eden_end_adr; 137.28 137.29 @@ -1239,8 +1237,6 @@ 137.30 } 137.31 } 137.32 137.33 - mem = result_phi_rawmem; 137.34 - 137.35 // An allocate node has separate i_o projections for the uses on the control and i_o paths 137.36 // Replace uses of the control i_o projection with result_phi_i_o (unless we are only generating a slow call) 137.37 if (_ioproj_fallthrough == NULL) {
138.1 --- a/src/share/vm/opto/matcher.cpp Sat Jan 31 17:19:42 2009 -0800 138.2 +++ b/src/share/vm/opto/matcher.cpp Fri Feb 27 15:13:00 2009 -0800 138.3 @@ -1824,7 +1824,7 @@ 138.4 mem_op = true; 138.5 break; 138.6 case Op_LoadB: 138.7 - case Op_LoadC: 138.8 + case Op_LoadUS: 138.9 case Op_LoadD: 138.10 case Op_LoadF: 138.11 case Op_LoadI:
139.1 --- a/src/share/vm/opto/memnode.cpp Sat Jan 31 17:19:42 2009 -0800 139.2 +++ b/src/share/vm/opto/memnode.cpp Fri Feb 27 15:13:00 2009 -0800 139.3 @@ -779,14 +779,14 @@ 139.4 "use LoadRangeNode instead"); 139.5 switch (bt) { 139.6 case T_BOOLEAN: 139.7 - case T_BYTE: return new (C, 3) LoadBNode(ctl, mem, adr, adr_type, rt->is_int() ); 139.8 - case T_INT: return new (C, 3) LoadINode(ctl, mem, adr, adr_type, rt->is_int() ); 139.9 - case T_CHAR: return new (C, 3) LoadCNode(ctl, mem, adr, adr_type, rt->is_int() ); 139.10 - case T_SHORT: return new (C, 3) LoadSNode(ctl, mem, adr, adr_type, rt->is_int() ); 139.11 - case T_LONG: return new (C, 3) LoadLNode(ctl, mem, adr, adr_type, rt->is_long() ); 139.12 - case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt ); 139.13 - case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt ); 139.14 - case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() ); 139.15 + case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); 139.16 + case T_INT: return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); 139.17 + case T_CHAR: return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); 139.18 + case T_SHORT: return new (C, 3) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() ); 139.19 + case T_LONG: return new (C, 3) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() ); 139.20 + case T_FLOAT: return new (C, 3) LoadFNode (ctl, mem, adr, adr_type, rt ); 139.21 + case T_DOUBLE: return new (C, 3) LoadDNode (ctl, mem, adr, adr_type, rt ); 139.22 + case T_ADDRESS: return new (C, 3) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() ); 139.23 case T_OBJECT: 139.24 #ifdef _LP64 139.25 if (adr->bottom_type()->is_ptr_to_narrowoop()) { 139.26 @@ -1076,13 +1076,14 @@ 139.27 // of the original value. 139.28 Node* mem_phi = in(Memory); 139.29 Node* offset = in(Address)->in(AddPNode::Offset); 139.30 + Node* region = base->in(0); 139.31 139.32 Node* in1 = clone(); 139.33 Node* in1_addr = in1->in(Address)->clone(); 139.34 in1_addr->set_req(AddPNode::Base, base->in(allocation_index)); 139.35 in1_addr->set_req(AddPNode::Address, base->in(allocation_index)); 139.36 in1_addr->set_req(AddPNode::Offset, offset); 139.37 - in1->set_req(0, base->in(allocation_index)); 139.38 + in1->set_req(0, region->in(allocation_index)); 139.39 in1->set_req(Address, in1_addr); 139.40 in1->set_req(Memory, mem_phi->in(allocation_index)); 139.41 139.42 @@ -1091,7 +1092,7 @@ 139.43 in2_addr->set_req(AddPNode::Base, base->in(load_index)); 139.44 in2_addr->set_req(AddPNode::Address, base->in(load_index)); 139.45 in2_addr->set_req(AddPNode::Offset, offset); 139.46 - in2->set_req(0, base->in(load_index)); 139.47 + in2->set_req(0, region->in(load_index)); 139.48 in2->set_req(Address, in2_addr); 139.49 in2->set_req(Memory, mem_phi->in(load_index)); 139.50 139.51 @@ -1100,7 +1101,7 @@ 139.52 in2_addr = phase->transform(in2_addr); 139.53 in2 = phase->transform(in2); 139.54 139.55 - PhiNode* result = PhiNode::make_blank(base->in(0), this); 139.56 + PhiNode* result = PhiNode::make_blank(region, this); 139.57 result->set_req(allocation_index, in1); 139.58 result->set_req(load_index, in2); 139.59 return result; 139.60 @@ -1303,6 +1304,7 @@ 139.61 Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); 139.62 if (base != NULL 139.63 && phase->type(base)->higher_equal(TypePtr::NOTNULL) 139.64 + && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw 139.65 && all_controls_dominate(base, phase->C->start())) { 139.66 // A method-invariant, non-null address (constant or 'this' argument). 139.67 set_req(MemNode::Control, NULL); 139.68 @@ -1356,7 +1358,7 @@ 139.69 // Steps (a), (b): Walk past independent stores to find an exact match. 139.70 if (prev_mem != NULL && prev_mem != in(MemNode::Memory)) { 139.71 // (c) See if we can fold up on the spot, but don't fold up here. 139.72 - // Fold-up might require truncation (for LoadB/LoadS/LoadC) or 139.73 + // Fold-up might require truncation (for LoadB/LoadS/LoadUS) or 139.74 // just return a prior value, which is done by Identity calls. 139.75 if (can_see_stored_value(prev_mem, phase)) { 139.76 // Make ready for step (d): 139.77 @@ -1605,14 +1607,14 @@ 139.78 return LoadNode::Ideal(phase, can_reshape); 139.79 } 139.80 139.81 -//--------------------------LoadCNode::Ideal-------------------------------------- 139.82 +//--------------------------LoadUSNode::Ideal------------------------------------- 139.83 // 139.84 // If the previous store is to the same address as this load, 139.85 // and the value stored was larger than a char, replace this load 139.86 // with the value stored truncated to a char. If no truncation is 139.87 // needed, the replacement is done in LoadNode::Identity(). 139.88 // 139.89 -Node *LoadCNode::Ideal(PhaseGVN *phase, bool can_reshape) { 139.90 +Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) { 139.91 Node* mem = in(MemNode::Memory); 139.92 Node* value = can_see_stored_value(mem,phase); 139.93 if( value && !phase->type(value)->higher_equal( _type ) )
140.1 --- a/src/share/vm/opto/memnode.hpp Sat Jan 31 17:19:42 2009 -0800 140.2 +++ b/src/share/vm/opto/memnode.hpp Fri Feb 27 15:13:00 2009 -0800 140.3 @@ -207,11 +207,11 @@ 140.4 virtual BasicType memory_type() const { return T_BYTE; } 140.5 }; 140.6 140.7 -//------------------------------LoadCNode-------------------------------------- 140.8 -// Load a char (16bits unsigned) from memory 140.9 -class LoadCNode : public LoadNode { 140.10 +//------------------------------LoadUSNode------------------------------------- 140.11 +// Load an unsigned short/char (16bits unsigned) from memory 140.12 +class LoadUSNode : public LoadNode { 140.13 public: 140.14 - LoadCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) 140.15 + LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) 140.16 : LoadNode(c,mem,adr,at,ti) {} 140.17 virtual int Opcode() const; 140.18 virtual uint ideal_reg() const { return Op_RegI; }
141.1 --- a/src/share/vm/opto/mulnode.cpp Sat Jan 31 17:19:42 2009 -0800 141.2 +++ b/src/share/vm/opto/mulnode.cpp Fri Feb 27 15:13:00 2009 -0800 141.3 @@ -1,5 +1,5 @@ 141.4 /* 141.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 141.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 141.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 141.8 * 141.9 * This code is free software; you can redistribute it and/or modify it 141.10 @@ -442,16 +442,17 @@ 141.11 return load; 141.12 } 141.13 uint lop = load->Opcode(); 141.14 - if( lop == Op_LoadC && 141.15 + if( lop == Op_LoadUS && 141.16 con == 0x0000FFFF ) // Already zero-extended 141.17 return load; 141.18 // Masking off the high bits of a unsigned-shift-right is not 141.19 // needed either. 141.20 if( lop == Op_URShiftI ) { 141.21 const TypeInt *t12 = phase->type( load->in(2) )->isa_int(); 141.22 - if( t12 && t12->is_con() ) { 141.23 - int shift_con = t12->get_con(); 141.24 - int mask = max_juint >> shift_con; 141.25 + if( t12 && t12->is_con() ) { // Shift is by a constant 141.26 + int shift = t12->get_con(); 141.27 + shift &= BitsPerJavaInteger - 1; // semantics of Java shifts 141.28 + int mask = max_juint >> shift; 141.29 if( (mask&con) == mask ) // If AND is useless, skip it 141.30 return load; 141.31 } 141.32 @@ -470,19 +471,19 @@ 141.33 uint lop = load->Opcode(); 141.34 141.35 // Masking bits off of a Character? Hi bits are already zero. 141.36 - if( lop == Op_LoadC && 141.37 + if( lop == Op_LoadUS && 141.38 (mask & 0xFFFF0000) ) // Can we make a smaller mask? 141.39 return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF)); 141.40 141.41 // Masking bits off of a Short? Loading a Character does some masking 141.42 if( lop == Op_LoadS && 141.43 (mask & 0xFFFF0000) == 0 ) { 141.44 - Node *ldc = new (phase->C, 3) LoadCNode(load->in(MemNode::Control), 141.45 + Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control), 141.46 load->in(MemNode::Memory), 141.47 load->in(MemNode::Address), 141.48 load->adr_type()); 141.49 - ldc = phase->transform(ldc); 141.50 - return new (phase->C, 3) AndINode(ldc,phase->intcon(mask&0xFFFF)); 141.51 + ldus = phase->transform(ldus); 141.52 + return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF)); 141.53 } 141.54 141.55 // Masking sign bits off of a Byte? Let the matcher use an unsigned load 141.56 @@ -579,9 +580,10 @@ 141.57 // needed either. 141.58 if( lop == Op_URShiftL ) { 141.59 const TypeInt *t12 = phase->type( usr->in(2) )->isa_int(); 141.60 - if( t12 && t12->is_con() ) { 141.61 - int shift_con = t12->get_con(); 141.62 - jlong mask = max_julong >> shift_con; 141.63 + if( t12 && t12->is_con() ) { // Shift is by a constant 141.64 + int shift = t12->get_con(); 141.65 + shift &= BitsPerJavaLong - 1; // semantics of Java shifts 141.66 + jlong mask = max_julong >> shift; 141.67 if( (mask&con) == mask ) // If AND is useless, skip it 141.68 return usr; 141.69 } 141.70 @@ -605,8 +607,8 @@ 141.71 const TypeInt *t12 = phase->type(rsh->in(2))->isa_int(); 141.72 if( t12 && t12->is_con() ) { // Shift is by a constant 141.73 int shift = t12->get_con(); 141.74 - shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts 141.75 - const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - shift)) -1); 141.76 + shift &= BitsPerJavaLong - 1; // semantics of Java shifts 141.77 + const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - shift)) -1); 141.78 // If the AND'ing of the 2 masks has no bits, then only original shifted 141.79 // bits survive. NO sign-extension bits survive the maskings. 141.80 if( (sign_bits_mask & mask) == 0 ) { 141.81 @@ -786,7 +788,7 @@ 141.82 141.83 // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits 141.84 // before shifting them away. 141.85 - const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) - CONST64(1); 141.86 + const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) - CONST64(1); 141.87 if( add1_op == Op_AndL && 141.88 phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) 141.89 return new (phase->C, 3) LShiftLNode( add1->in(1), in(2) ); 141.90 @@ -820,7 +822,7 @@ 141.91 return TypeLong::LONG; 141.92 141.93 uint shift = r2->get_con(); 141.94 - shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts 141.95 + shift &= BitsPerJavaLong - 1; // semantics of Java shifts 141.96 // Shift by a multiple of 64 does nothing: 141.97 if (shift == 0) return t1; 141.98 141.99 @@ -913,7 +915,7 @@ 141.100 set_req(2, phase->intcon(0)); 141.101 return this; 141.102 } 141.103 - else if( ld->Opcode() == Op_LoadC ) 141.104 + else if( ld->Opcode() == Op_LoadUS ) 141.105 // Replace zero-extension-load with sign-extension-load 141.106 return new (phase->C, 3) LoadSNode( ld->in(MemNode::Control), 141.107 ld->in(MemNode::Memory), 141.108 @@ -1235,7 +1237,7 @@ 141.109 if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count 141.110 // note: mask computation below does not work for 0 shift count 141.111 // We'll be wanting the right-shift amount as a mask of that many bits 141.112 - const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) -1); 141.113 + const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) -1); 141.114 141.115 // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z 141.116 // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". 141.117 @@ -1302,7 +1304,7 @@ 141.118 141.119 if (r2->is_con()) { 141.120 uint shift = r2->get_con(); 141.121 - shift &= (2*BitsPerJavaInteger)-1; // semantics of Java shifts 141.122 + shift &= BitsPerJavaLong - 1; // semantics of Java shifts 141.123 // Shift by a multiple of 64 does nothing: 141.124 if (shift == 0) return t1; 141.125 // Calculate reasonably aggressive bounds for the result. 141.126 @@ -1325,7 +1327,7 @@ 141.127 const TypeLong* tl = TypeLong::make(lo, hi, MAX2(r1->_widen,r2->_widen)); 141.128 #ifdef ASSERT 141.129 // Make sure we get the sign-capture idiom correct. 141.130 - if (shift == (2*BitsPerJavaInteger)-1) { 141.131 + if (shift == BitsPerJavaLong - 1) { 141.132 if (r1->_lo >= 0) assert(tl == TypeLong::ZERO, ">>>63 of + is 0"); 141.133 if (r1->_hi < 0) assert(tl == TypeLong::ONE, ">>>63 of - is +1"); 141.134 }
142.1 --- a/src/share/vm/opto/superword.cpp Sat Jan 31 17:19:42 2009 -0800 142.2 +++ b/src/share/vm/opto/superword.cpp Fri Feb 27 15:13:00 2009 -0800 142.3 @@ -1444,7 +1444,7 @@ 142.4 // (Start, end] half-open range defining which operands are vector 142.5 void SuperWord::vector_opd_range(Node* n, uint* start, uint* end) { 142.6 switch (n->Opcode()) { 142.7 - case Op_LoadB: case Op_LoadC: 142.8 + case Op_LoadB: case Op_LoadUS: 142.9 case Op_LoadI: case Op_LoadL: 142.10 case Op_LoadF: case Op_LoadD: 142.11 case Op_LoadP:
143.1 --- a/src/share/vm/opto/type.cpp Sat Jan 31 17:19:42 2009 -0800 143.2 +++ b/src/share/vm/opto/type.cpp Fri Feb 27 15:13:00 2009 -0800 143.3 @@ -2471,6 +2471,8 @@ 143.4 const Type* ft = join(kills); 143.5 const TypeInstPtr* ftip = ft->isa_instptr(); 143.6 const TypeInstPtr* ktip = kills->isa_instptr(); 143.7 + const TypeKlassPtr* ftkp = ft->isa_klassptr(); 143.8 + const TypeKlassPtr* ktkp = kills->isa_klassptr(); 143.9 143.10 if (ft->empty()) { 143.11 // Check for evil case of 'this' being a class and 'kills' expecting an 143.12 @@ -2484,6 +2486,8 @@ 143.13 // uplift the type. 143.14 if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) 143.15 return kills; // Uplift to interface 143.16 + if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface()) 143.17 + return kills; // Uplift to interface 143.18 143.19 return Type::TOP; // Canonical empty value 143.20 } 143.21 @@ -2499,6 +2503,12 @@ 143.22 // Happens in a CTW of rt.jar, 320-341, no extra flags 143.23 return ktip->cast_to_ptr_type(ftip->ptr()); 143.24 } 143.25 + if (ftkp != NULL && ktkp != NULL && 143.26 + ftkp->is_loaded() && ftkp->klass()->is_interface() && 143.27 + ktkp->is_loaded() && !ktkp->klass()->is_interface()) { 143.28 + // Happens in a CTW of rt.jar, 320-341, no extra flags 143.29 + return ktkp->cast_to_ptr_type(ftkp->ptr()); 143.30 + } 143.31 143.32 return ft; 143.33 } 143.34 @@ -3657,7 +3667,7 @@ 143.35 143.36 //------------------------------cast_to_ptr_type------------------------------- 143.37 const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const { 143.38 - assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); 143.39 + assert(_base == KlassPtr, "subclass must override cast_to_ptr_type"); 143.40 if( ptr == _ptr ) return this; 143.41 return make(ptr, _klass, _offset); 143.42 }
144.1 --- a/src/share/vm/opto/type.hpp Sat Jan 31 17:19:42 2009 -0800 144.2 +++ b/src/share/vm/opto/type.hpp Fri Feb 27 15:13:00 2009 -0800 144.3 @@ -882,6 +882,8 @@ 144.4 public: 144.5 ciSymbol* name() const { return _klass->name(); } 144.6 144.7 + bool is_loaded() const { return _klass->is_loaded(); } 144.8 + 144.9 // ptr to klass 'k' 144.10 static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); } 144.11 // ptr to klass 'k' with offset
145.1 --- a/src/share/vm/opto/vectornode.cpp Sat Jan 31 17:19:42 2009 -0800 145.2 +++ b/src/share/vm/opto/vectornode.cpp Fri Feb 27 15:13:00 2009 -0800 145.3 @@ -239,7 +239,7 @@ 145.4 return Op_XorV; 145.5 145.6 case Op_LoadB: 145.7 - case Op_LoadC: 145.8 + case Op_LoadUS: 145.9 case Op_LoadS: 145.10 case Op_LoadI: 145.11 case Op_LoadL: 145.12 @@ -269,7 +269,7 @@ 145.13 case 16: return Op_Load16B; 145.14 } 145.15 break; 145.16 - case Op_LoadC: 145.17 + case Op_LoadUS: 145.18 switch (vlen) { 145.19 case 2: return Op_Load2C; 145.20 case 4: return Op_Load4C;
146.1 --- a/src/share/vm/prims/jni.cpp Sat Jan 31 17:19:42 2009 -0800 146.2 +++ b/src/share/vm/prims/jni.cpp Fri Feb 27 15:13:00 2009 -0800 146.3 @@ -2691,8 +2691,13 @@ 146.4 146.5 directBufferSupportInitializeEnded = 1; 146.6 } else { 146.7 - ThreadInVMfromNative tivn(thread); // set state as yield_all can call os:sleep 146.8 while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) { 146.9 + // Set state as yield_all can call os:sleep. On Solaris, yield_all calls 146.10 + // os::sleep which requires the VM state transition. On other platforms, it 146.11 + // is not necessary. The following call to change the VM state is purposely 146.12 + // put inside the loop to avoid potential deadlock when multiple threads 146.13 + // try to call this method. See 6791815 for more details. 146.14 + ThreadInVMfromNative tivn(thread); 146.15 os::yield_all(); 146.16 } 146.17 }
147.1 --- a/src/share/vm/prims/jvm.cpp Sat Jan 31 17:19:42 2009 -0800 147.2 +++ b/src/share/vm/prims/jvm.cpp Fri Feb 27 15:13:00 2009 -0800 147.3 @@ -2475,7 +2475,8 @@ 147.4 if (Arguments::vfprintf_hook() != NULL) { 147.5 jio_fprintf(defaultStream::output_stream(), "%s", s); 147.6 } else { 147.7 - ::write(defaultStream::output_fd(), s, (int)strlen(s)); 147.8 + // Make an unused local variable to avoid warning from gcc 4.x compiler. 147.9 + size_t count = ::write(defaultStream::output_fd(), s, (int)strlen(s)); 147.10 } 147.11 } 147.12
148.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Sat Jan 31 17:19:42 2009 -0800 148.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Feb 27 15:13:00 2009 -0800 148.3 @@ -1230,8 +1230,14 @@ 148.4 148.5 // Constant pools are not easily reused so we allocate a new one 148.6 // each time. 148.7 + // merge_cp is created unsafe for concurrent GC processing. It 148.8 + // should be marked safe before discarding it because, even if 148.9 + // garbage. If it crosses a card boundary, it may be scanned 148.10 + // in order to find the start of the first complete object on the card. 148.11 constantPoolHandle merge_cp(THREAD, 148.12 - oopFactory::new_constantPool(merge_cp_length, THREAD)); 148.13 + oopFactory::new_constantPool(merge_cp_length, 148.14 + methodOopDesc::IsUnsafeConc, 148.15 + THREAD)); 148.16 int orig_length = old_cp->orig_length(); 148.17 if (orig_length == 0) { 148.18 // This old_cp is an actual original constant pool. We save 148.19 @@ -1274,6 +1280,7 @@ 148.20 // rewriting so we can't use the old constant pool with the new 148.21 // class. 148.22 148.23 + merge_cp()->set_is_conc_safe(true); 148.24 merge_cp = constantPoolHandle(); // toss the merged constant pool 148.25 } else if (old_cp->length() < scratch_cp->length()) { 148.26 // The old constant pool has fewer entries than the new constant 148.27 @@ -1283,6 +1290,7 @@ 148.28 // rewriting so we can't use the new constant pool with the old 148.29 // class. 148.30 148.31 + merge_cp()->set_is_conc_safe(true); 148.32 merge_cp = constantPoolHandle(); // toss the merged constant pool 148.33 } else { 148.34 // The old constant pool has more entries than the new constant 148.35 @@ -1296,6 +1304,7 @@ 148.36 set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true, 148.37 THREAD); 148.38 // drop local ref to the merged constant pool 148.39 + merge_cp()->set_is_conc_safe(true); 148.40 merge_cp = constantPoolHandle(); 148.41 } 148.42 } else { 148.43 @@ -1325,7 +1334,10 @@ 148.44 // GCed. 148.45 set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true, 148.46 THREAD); 148.47 + merge_cp()->set_is_conc_safe(true); 148.48 } 148.49 + assert(old_cp()->is_conc_safe(), "Just checking"); 148.50 + assert(scratch_cp()->is_conc_safe(), "Just checking"); 148.51 148.52 return JVMTI_ERROR_NONE; 148.53 } // end merge_cp_and_rewrite() 148.54 @@ -2314,13 +2326,16 @@ 148.55 // worst case merge situation. We want to associate the minimum 148.56 // sized constant pool with the klass to save space. 148.57 constantPoolHandle smaller_cp(THREAD, 148.58 - oopFactory::new_constantPool(scratch_cp_length, THREAD)); 148.59 + oopFactory::new_constantPool(scratch_cp_length, 148.60 + methodOopDesc::IsUnsafeConc, 148.61 + THREAD)); 148.62 // preserve orig_length() value in the smaller copy 148.63 int orig_length = scratch_cp->orig_length(); 148.64 assert(orig_length != 0, "sanity check"); 148.65 smaller_cp->set_orig_length(orig_length); 148.66 scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); 148.67 scratch_cp = smaller_cp; 148.68 + smaller_cp()->set_is_conc_safe(true); 148.69 } 148.70 148.71 // attach new constant pool to klass 148.72 @@ -2516,6 +2531,7 @@ 148.73 148.74 rewrite_cp_refs_in_stack_map_table(method, THREAD); 148.75 } // end for each method 148.76 + assert(scratch_cp()->is_conc_safe(), "Just checking"); 148.77 } // end set_new_constant_pool() 148.78 148.79
149.1 --- a/src/share/vm/prims/jvmtiTagMap.cpp Sat Jan 31 17:19:42 2009 -0800 149.2 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 27 15:13:00 2009 -0800 149.3 @@ -1320,6 +1320,9 @@ 149.4 } 149.5 149.6 // do the iteration 149.7 + // If this operation encounters a bad object when using CMS, 149.8 + // consider using safe_object_iterate() which avoids perm gen 149.9 + // objects that may contain bad references. 149.10 Universe::heap()->object_iterate(_blk); 149.11 149.12 // when sharing is enabled we must iterate over the shared spaces
150.1 --- a/src/share/vm/runtime/arguments.cpp Sat Jan 31 17:19:42 2009 -0800 150.2 +++ b/src/share/vm/runtime/arguments.cpp Fri Feb 27 15:13:00 2009 -0800 150.3 @@ -229,6 +229,7 @@ 150.4 150.5 inline void set_base(const char* base); 150.6 inline void add_prefix(const char* prefix); 150.7 + inline void add_suffix_to_prefix(const char* suffix); 150.8 inline void add_suffix(const char* suffix); 150.9 inline void reset_path(const char* base); 150.10 150.11 @@ -290,6 +291,10 @@ 150.12 _items[_scp_prefix] = add_to_path(_items[_scp_prefix], prefix, true); 150.13 } 150.14 150.15 +inline void SysClassPath::add_suffix_to_prefix(const char* suffix) { 150.16 + _items[_scp_prefix] = add_to_path(_items[_scp_prefix], suffix, false); 150.17 +} 150.18 + 150.19 inline void SysClassPath::add_suffix(const char* suffix) { 150.20 _items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false); 150.21 } 150.22 @@ -512,7 +517,6 @@ 150.23 return CommandLineFlags::boolAtPut(name, &value, origin); 150.24 } 150.25 150.26 - 150.27 static bool set_fp_numeric_flag(char* name, char* value, FlagValueOrigin origin) { 150.28 double v; 150.29 if (sscanf(value, "%lf", &v) != 1) { 150.30 @@ -525,7 +529,6 @@ 150.31 return false; 150.32 } 150.33 150.34 - 150.35 static bool set_numeric_flag(char* name, char* value, FlagValueOrigin origin) { 150.36 julong v; 150.37 intx intx_v; 150.38 @@ -555,7 +558,6 @@ 150.39 return false; 150.40 } 150.41 150.42 - 150.43 static bool set_string_flag(char* name, const char* value, FlagValueOrigin origin) { 150.44 if (!CommandLineFlags::ccstrAtPut(name, &value, origin)) return false; 150.45 // Contract: CommandLineFlags always returns a pointer that needs freeing. 150.46 @@ -591,7 +593,6 @@ 150.47 return true; 150.48 } 150.49 150.50 - 150.51 bool Arguments::parse_argument(const char* arg, FlagValueOrigin origin) { 150.52 150.53 // range of acceptable characters spelled out for portability reasons 150.54 @@ -652,7 +653,6 @@ 150.55 return false; 150.56 } 150.57 150.58 - 150.59 void Arguments::add_string(char*** bldarray, int* count, const char* arg) { 150.60 assert(bldarray != NULL, "illegal argument"); 150.61 150.62 @@ -756,7 +756,6 @@ 150.63 return true; 150.64 } 150.65 150.66 - 150.67 bool Arguments::process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized) { 150.68 FILE* stream = fopen(file_name, "rb"); 150.69 if (stream == NULL) { 150.70 @@ -932,7 +931,6 @@ 150.71 } 150.72 } 150.73 150.74 - 150.75 // Conflict: required to use shared spaces (-Xshare:on), but 150.76 // incompatible command line options were chosen. 150.77 150.78 @@ -946,7 +944,6 @@ 150.79 } 150.80 } 150.81 150.82 - 150.83 // If the user has chosen ParallelGCThreads > 0, we set UseParNewGC 150.84 // if it's not explictly set or unset. If the user has chosen 150.85 // UseParNewGC and not explicitly set ParallelGCThreads we 150.86 @@ -1361,7 +1358,7 @@ 150.87 150.88 // Feed the cache size setting into the JDK 150.89 char buffer[1024]; 150.90 - sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax); 150.91 + sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax); 150.92 add_property(buffer); 150.93 } 150.94 if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) { 150.95 @@ -1714,6 +1711,21 @@ 150.96 return result; 150.97 } 150.98 150.99 + if (AggressiveOpts) { 150.100 + // Insert alt-rt.jar between user-specified bootclasspath 150.101 + // prefix and the default bootclasspath. os::set_boot_path() 150.102 + // uses meta_index_dir as the default bootclasspath directory. 150.103 + const char* altclasses_jar = "alt-rt.jar"; 150.104 + size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 + 150.105 + strlen(altclasses_jar); 150.106 + char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len); 150.107 + strcpy(altclasses_path, get_meta_index_dir()); 150.108 + strcat(altclasses_path, altclasses_jar); 150.109 + scp.add_suffix_to_prefix(altclasses_path); 150.110 + scp_assembly_required = true; 150.111 + FREE_C_HEAP_ARRAY(char, altclasses_path); 150.112 + } 150.113 + 150.114 // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) 150.115 result = parse_java_options_environment_variable(&scp, &scp_assembly_required); 150.116 if (result != JNI_OK) { 150.117 @@ -1729,7 +1741,6 @@ 150.118 return JNI_OK; 150.119 } 150.120 150.121 - 150.122 jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, 150.123 SysClassPath* scp_p, 150.124 bool* scp_assembly_required_p, 150.125 @@ -1795,7 +1806,7 @@ 150.126 *scp_assembly_required_p = true; 150.127 // -Xrun 150.128 } else if (match_option(option, "-Xrun", &tail)) { 150.129 - if(tail != NULL) { 150.130 + if (tail != NULL) { 150.131 const char* pos = strchr(tail, ':'); 150.132 size_t len = (pos == NULL) ? strlen(tail) : pos - tail; 150.133 char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1), tail, len); 150.134 @@ -2478,7 +2489,7 @@ 150.135 vm_args.version = JNI_VERSION_1_2; 150.136 vm_args.options = options; 150.137 vm_args.nOptions = i; 150.138 - vm_args.ignoreUnrecognized = false; 150.139 + vm_args.ignoreUnrecognized = IgnoreUnrecognizedVMOptions; 150.140 150.141 if (PrintVMOptions) { 150.142 const char* tail; 150.143 @@ -2525,13 +2536,12 @@ 150.144 150.145 // If flag "-XX:Flags=flags-file" is used it will be the first option to be processed. 150.146 bool settings_file_specified = false; 150.147 + const char* flags_file; 150.148 int index; 150.149 for (index = 0; index < args->nOptions; index++) { 150.150 const JavaVMOption *option = args->options + index; 150.151 if (match_option(option, "-XX:Flags=", &tail)) { 150.152 - if (!process_settings_file(tail, true, args->ignoreUnrecognized)) { 150.153 - return JNI_EINVAL; 150.154 - } 150.155 + flags_file = tail; 150.156 settings_file_specified = true; 150.157 } 150.158 if (match_option(option, "-XX:+PrintVMOptions", &tail)) { 150.159 @@ -2540,6 +2550,24 @@ 150.160 if (match_option(option, "-XX:-PrintVMOptions", &tail)) { 150.161 PrintVMOptions = false; 150.162 } 150.163 + if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) { 150.164 + IgnoreUnrecognizedVMOptions = true; 150.165 + } 150.166 + if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { 150.167 + IgnoreUnrecognizedVMOptions = false; 150.168 + } 150.169 + } 150.170 + 150.171 + if (IgnoreUnrecognizedVMOptions) { 150.172 + // uncast const to modify the flag args->ignoreUnrecognized 150.173 + *(jboolean*)(&args->ignoreUnrecognized) = true; 150.174 + } 150.175 + 150.176 + // Parse specified settings file 150.177 + if (settings_file_specified) { 150.178 + if (!process_settings_file(flags_file, true, args->ignoreUnrecognized)) { 150.179 + return JNI_EINVAL; 150.180 + } 150.181 } 150.182 150.183 // Parse default .hotspotrc settings file 150.184 @@ -2558,7 +2586,6 @@ 150.185 } 150.186 } 150.187 150.188 - 150.189 // Parse JavaVMInitArgs structure passed in, as well as JAVA_TOOL_OPTIONS and _JAVA_OPTIONS 150.190 jint result = parse_vm_init_args(args); 150.191 if (result != JNI_OK) {
151.1 --- a/src/share/vm/runtime/globals.hpp Sat Jan 31 17:19:42 2009 -0800 151.2 +++ b/src/share/vm/runtime/globals.hpp Fri Feb 27 15:13:00 2009 -0800 151.3 @@ -835,8 +835,21 @@ 151.4 "Prints the system dictionary at exit") \ 151.5 \ 151.6 diagnostic(bool, UnsyncloadClass, false, \ 151.7 - "Unstable: VM calls loadClass unsynchronized. Custom classloader "\ 151.8 - "must call VM synchronized for findClass & defineClass") \ 151.9 + "Unstable: VM calls loadClass unsynchronized. Custom " \ 151.10 + "class loader must call VM synchronized for findClass " \ 151.11 + "and defineClass.") \ 151.12 + \ 151.13 + product(bool, AlwaysLockClassLoader, false, \ 151.14 + "Require the VM to acquire the class loader lock before calling " \ 151.15 + "loadClass() even for class loaders registering " \ 151.16 + "as parallel capable. Default false. ") \ 151.17 + \ 151.18 + product(bool, AllowParallelDefineClass, false, \ 151.19 + "Allow parallel defineClass requests for class loaders " \ 151.20 + "registering as parallel capable. Default false") \ 151.21 + \ 151.22 + product(bool, MustCallLoadClassInternal, false, \ 151.23 + "Call loadClassInternal() rather than loadClass().Default false") \ 151.24 \ 151.25 product_pd(bool, DontYieldALot, \ 151.26 "Throw away obvious excess yield calls (for SOLARIS only)") \ 151.27 @@ -1294,7 +1307,14 @@ 151.28 product(intx, ParGCArrayScanChunk, 50, \ 151.29 "Scan a subset and push remainder, if array is bigger than this") \ 151.30 \ 151.31 - product(intx, ParGCDesiredObjsFromOverflowList, 20, \ 151.32 + notproduct(bool, ParGCWorkQueueOverflowALot, false, \ 151.33 + "Whether we should simulate work queue overflow in ParNew") \ 151.34 + \ 151.35 + notproduct(uintx, ParGCWorkQueueOverflowInterval, 1000, \ 151.36 + "An `interval' counter that determines how frequently" \ 151.37 + " we simulate overflow; a smaller number increases frequency") \ 151.38 + \ 151.39 + product(uintx, ParGCDesiredObjsFromOverflowList, 20, \ 151.40 "The desired number of objects to claim from the overflow list") \ 151.41 \ 151.42 product(uintx, CMSParPromoteBlocksToClaim, 50, \ 151.43 @@ -1406,18 +1426,18 @@ 151.44 develop(bool, CMSOverflowEarlyRestoration, false, \ 151.45 "Whether preserved marks should be restored early") \ 151.46 \ 151.47 - product(uintx, CMSMarkStackSize, 32*K, \ 151.48 + product(uintx, CMSMarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \ 151.49 "Size of CMS marking stack") \ 151.50 \ 151.51 - product(uintx, CMSMarkStackSizeMax, 4*M, \ 151.52 + product(uintx, CMSMarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \ 151.53 "Max size of CMS marking stack") \ 151.54 \ 151.55 notproduct(bool, CMSMarkStackOverflowALot, false, \ 151.56 "Whether we should simulate frequent marking stack / work queue" \ 151.57 " overflow") \ 151.58 \ 151.59 - notproduct(intx, CMSMarkStackOverflowInterval, 1000, \ 151.60 - "A per-thread `interval' counter that determines how frequently" \ 151.61 + notproduct(uintx, CMSMarkStackOverflowInterval, 1000, \ 151.62 + "An `interval' counter that determines how frequently" \ 151.63 " we simulate overflow; a smaller number increases frequency") \ 151.64 \ 151.65 product(uintx, CMSMaxAbortablePrecleanLoops, 0, \ 151.66 @@ -1635,7 +1655,14 @@ 151.67 develop(uintx, WorkStealingYieldsBeforeSleep, 1000, \ 151.68 "Number of yields before a sleep is done during workstealing") \ 151.69 \ 151.70 - product(uintx, PreserveMarkStackSize, 40, \ 151.71 + develop(uintx, WorkStealingHardSpins, 4096, \ 151.72 + "Number of iterations in a spin loop between checks on " \ 151.73 + "time out of hard spin") \ 151.74 + \ 151.75 + develop(uintx, WorkStealingSpinToYieldRatio, 10, \ 151.76 + "Ratio of hard spins to calls to yield") \ 151.77 + \ 151.78 + product(uintx, PreserveMarkStackSize, 1024, \ 151.79 "Size for stack used in promotion failure handling") \ 151.80 \ 151.81 product_pd(bool, UseTLAB, "Use thread-local object allocation") \ 151.82 @@ -2167,6 +2194,9 @@ 151.83 product(bool, PrintVMOptions, trueInDebug, \ 151.84 "print VM flag settings") \ 151.85 \ 151.86 + product(bool, IgnoreUnrecognizedVMOptions, false, \ 151.87 + "Ignore unrecognized VM options") \ 151.88 + \ 151.89 diagnostic(bool, SerializeVMOutput, true, \ 151.90 "Use a mutex to serialize output to tty and hotspot.log") \ 151.91 \
152.1 --- a/src/share/vm/runtime/memprofiler.cpp Sat Jan 31 17:19:42 2009 -0800 152.2 +++ b/src/share/vm/runtime/memprofiler.cpp Fri Feb 27 15:13:00 2009 -0800 152.3 @@ -104,21 +104,22 @@ 152.4 } 152.5 152.6 // Print trace line in log 152.7 - fprintf(_log_fp, "%6.1f,%5d,%5d,%6ld,%6ld,%6ld,%6ld,", 152.8 - os::elapsedTime(), 152.9 - Threads::number_of_threads(), 152.10 - SystemDictionary::number_of_classes(), 152.11 - Universe::heap()->used() / K, 152.12 - Universe::heap()->capacity() / K, 152.13 - Universe::heap()->permanent_used() / HWperKB, 152.14 - Universe::heap()->permanent_capacity() / HWperKB); 152.15 + fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) "," 152.16 + UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",", 152.17 + os::elapsedTime(), 152.18 + Threads::number_of_threads(), 152.19 + SystemDictionary::number_of_classes(), 152.20 + Universe::heap()->used() / K, 152.21 + Universe::heap()->capacity() / K, 152.22 + Universe::heap()->permanent_used() / HWperKB, 152.23 + Universe::heap()->permanent_capacity() / HWperKB); 152.24 152.25 - fprintf(_log_fp, "%6ld,", CodeCache::capacity() / K); 152.26 + fprintf(_log_fp, UINTX_FORMAT_W(6) ",", CodeCache::capacity() / K); 152.27 152.28 - fprintf(_log_fp, "%6ld,%6ld,%6ld\n", 152.29 - handles_memory_usage / K, 152.30 - resource_memory_usage / K, 152.31 - OopMapCache::memory_usage() / K); 152.32 + fprintf(_log_fp, UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",%6ld\n", 152.33 + handles_memory_usage / K, 152.34 + resource_memory_usage / K, 152.35 + OopMapCache::memory_usage() / K); 152.36 fflush(_log_fp); 152.37 } 152.38
153.1 --- a/src/share/vm/runtime/os.cpp Sat Jan 31 17:19:42 2009 -0800 153.2 +++ b/src/share/vm/runtime/os.cpp Fri Feb 27 15:13:00 2009 -0800 153.3 @@ -74,13 +74,11 @@ 153.4 const int milliseconds_after_second = 153.5 milliseconds_since_19700101 % milliseconds_per_microsecond; 153.6 // Convert the time value to a tm and timezone variable 153.7 - const struct tm *time_struct_temp = localtime(&seconds_since_19700101); 153.8 - if (time_struct_temp == NULL) { 153.9 - assert(false, "Failed localtime"); 153.10 + struct tm time_struct; 153.11 + if (localtime_pd(&seconds_since_19700101, &time_struct) == NULL) { 153.12 + assert(false, "Failed localtime_pd"); 153.13 return NULL; 153.14 } 153.15 - // Save the results of localtime 153.16 - const struct tm time_struct = *time_struct_temp; 153.17 const time_t zone = timezone; 153.18 153.19 // If daylight savings time is in effect, 153.20 @@ -93,10 +91,10 @@ 153.21 UTC_to_local = UTC_to_local - seconds_per_hour; 153.22 } 153.23 // Compute the time zone offset. 153.24 - // localtime(3C) sets timezone to the difference (in seconds) 153.25 + // localtime_pd() sets timezone to the difference (in seconds) 153.26 // between UTC and and local time. 153.27 // ISO 8601 says we need the difference between local time and UTC, 153.28 - // we change the sign of the localtime(3C) result. 153.29 + // we change the sign of the localtime_pd() result. 153.30 const time_t local_to_UTC = -(UTC_to_local); 153.31 // Then we have to figure out if if we are ahead (+) or behind (-) UTC. 153.32 char sign_local_to_UTC = '+';
154.1 --- a/src/share/vm/runtime/os.hpp Sat Jan 31 17:19:42 2009 -0800 154.2 +++ b/src/share/vm/runtime/os.hpp Fri Feb 27 15:13:00 2009 -0800 154.3 @@ -120,7 +120,8 @@ 154.4 // Return current local time in a string (YYYY-MM-DD HH:MM:SS). 154.5 // It is MT safe, but not async-safe, as reading time zone 154.6 // information may require a lock on some platforms. 154.7 - static char* local_time_string(char *buf, size_t buflen); 154.8 + static char* local_time_string(char *buf, size_t buflen); 154.9 + static struct tm* localtime_pd (const time_t* clock, struct tm* res); 154.10 // Fill in buffer with current local time as an ISO-8601 string. 154.11 // E.g., YYYY-MM-DDThh:mm:ss.mmm+zzzz. 154.12 // Returns buffer, or NULL if it failed.
155.1 --- a/src/share/vm/runtime/safepoint.cpp Sat Jan 31 17:19:42 2009 -0800 155.2 +++ b/src/share/vm/runtime/safepoint.cpp Fri Feb 27 15:13:00 2009 -0800 155.3 @@ -730,7 +730,7 @@ 155.4 if (DieOnSafepointTimeout) { 155.5 char msg[1024]; 155.6 VM_Operation *op = VMThread::vm_operation(); 155.7 - sprintf(msg, "Safepoint sync time longer than %d ms detected when executing %s.", 155.8 + sprintf(msg, "Safepoint sync time longer than " INTX_FORMAT "ms detected when executing %s.", 155.9 SafepointTimeoutDelay, 155.10 op != NULL ? op->name() : "no vm operation"); 155.11 fatal(msg);
156.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Sat Jan 31 17:19:42 2009 -0800 156.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 27 15:13:00 2009 -0800 156.3 @@ -192,64 +192,46 @@ 156.4 156.5 156.6 JRT_LEAF(jint, SharedRuntime::f2i(jfloat x)) 156.7 - if (g_isnan(x)) {return 0;} 156.8 - jlong lltmp = (jlong)x; 156.9 - jint ltmp = (jint)lltmp; 156.10 - if (ltmp == lltmp) { 156.11 - return ltmp; 156.12 - } else { 156.13 - if (x < 0) { 156.14 - return min_jint; 156.15 - } else { 156.16 - return max_jint; 156.17 - } 156.18 - } 156.19 + if (g_isnan(x)) 156.20 + return 0; 156.21 + if (x >= (jfloat) max_jint) 156.22 + return max_jint; 156.23 + if (x <= (jfloat) min_jint) 156.24 + return min_jint; 156.25 + return (jint) x; 156.26 JRT_END 156.27 156.28 156.29 JRT_LEAF(jlong, SharedRuntime::f2l(jfloat x)) 156.30 - if (g_isnan(x)) {return 0;} 156.31 - jlong lltmp = (jlong)x; 156.32 - if (lltmp != min_jlong) { 156.33 - return lltmp; 156.34 - } else { 156.35 - if (x < 0) { 156.36 - return min_jlong; 156.37 - } else { 156.38 - return max_jlong; 156.39 - } 156.40 - } 156.41 + if (g_isnan(x)) 156.42 + return 0; 156.43 + if (x >= (jfloat) max_jlong) 156.44 + return max_jlong; 156.45 + if (x <= (jfloat) min_jlong) 156.46 + return min_jlong; 156.47 + return (jlong) x; 156.48 JRT_END 156.49 156.50 156.51 JRT_LEAF(jint, SharedRuntime::d2i(jdouble x)) 156.52 - if (g_isnan(x)) {return 0;} 156.53 - jlong lltmp = (jlong)x; 156.54 - jint ltmp = (jint)lltmp; 156.55 - if (ltmp == lltmp) { 156.56 - return ltmp; 156.57 - } else { 156.58 - if (x < 0) { 156.59 - return min_jint; 156.60 - } else { 156.61 - return max_jint; 156.62 - } 156.63 - } 156.64 + if (g_isnan(x)) 156.65 + return 0; 156.66 + if (x >= (jdouble) max_jint) 156.67 + return max_jint; 156.68 + if (x <= (jdouble) min_jint) 156.69 + return min_jint; 156.70 + return (jint) x; 156.71 JRT_END 156.72 156.73 156.74 JRT_LEAF(jlong, SharedRuntime::d2l(jdouble x)) 156.75 - if (g_isnan(x)) {return 0;} 156.76 - jlong lltmp = (jlong)x; 156.77 - if (lltmp != min_jlong) { 156.78 - return lltmp; 156.79 - } else { 156.80 - if (x < 0) { 156.81 - return min_jlong; 156.82 - } else { 156.83 - return max_jlong; 156.84 - } 156.85 - } 156.86 + if (g_isnan(x)) 156.87 + return 0; 156.88 + if (x >= (jdouble) max_jlong) 156.89 + return max_jlong; 156.90 + if (x <= (jdouble) min_jlong) 156.91 + return min_jlong; 156.92 + return (jlong) x; 156.93 JRT_END 156.94 156.95
157.1 --- a/src/share/vm/runtime/synchronizer.cpp Sat Jan 31 17:19:42 2009 -0800 157.2 +++ b/src/share/vm/runtime/synchronizer.cpp Fri Feb 27 15:13:00 2009 -0800 157.3 @@ -424,7 +424,7 @@ 157.4 // asserts is that error message -- often something about negative array 157.5 // indices -- is opaque. 157.6 157.7 -#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @%X\n", tag); } 157.8 +#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @" INTPTR_FORMAT "\n", (intptr_t)tag); } 157.9 157.10 void ObjectMonitor::ctAsserts() { 157.11 CTASSERT(offset_of (ObjectMonitor, _header) == 0);
158.1 --- a/src/share/vm/services/heapDumper.cpp Sat Jan 31 17:19:42 2009 -0800 158.2 +++ b/src/share/vm/services/heapDumper.cpp Fri Feb 27 15:13:00 2009 -0800 158.3 @@ -1700,7 +1700,7 @@ 158.4 // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk 158.5 // of the heap dump. 158.6 HeapObjectDumper obj_dumper(this, writer()); 158.7 - Universe::heap()->object_iterate(&obj_dumper); 158.8 + Universe::heap()->safe_object_iterate(&obj_dumper); 158.9 158.10 // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals 158.11 do_threads();
159.1 --- a/src/share/vm/utilities/globalDefinitions.hpp Sat Jan 31 17:19:42 2009 -0800 159.2 +++ b/src/share/vm/utilities/globalDefinitions.hpp Fri Feb 27 15:13:00 2009 -0800 159.3 @@ -1,5 +1,5 @@ 159.4 /* 159.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 159.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 159.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 159.8 * 159.9 * This code is free software; you can redistribute it and/or modify it 159.10 @@ -74,6 +74,7 @@ 159.11 extern int BitsPerHeapOop; 159.12 159.13 const int BitsPerJavaInteger = 32; 159.14 +const int BitsPerJavaLong = 64; 159.15 const int BitsPerSize_t = size_tSize * BitsPerByte; 159.16 159.17 // Size of a char[] needed to represent a jint as a string in decimal. 159.18 @@ -906,6 +907,14 @@ 159.19 return log2_intptr(x); 159.20 } 159.21 159.22 +//* the argument must be exactly a power of 2 159.23 +inline int exact_log2_long(jlong x) { 159.24 + #ifdef ASSERT 159.25 + if (!is_power_of_2_long(x)) basic_fatal("x must be a power of 2"); 159.26 + #endif 159.27 + return log2_long(x); 159.28 +} 159.29 + 159.30 159.31 // returns integer round-up to the nearest multiple of s (s must be a power of two) 159.32 inline intptr_t round_to(intptr_t x, uintx s) { 159.33 @@ -1087,15 +1096,24 @@ 159.34 // Format macros that allow the field width to be specified. The width must be 159.35 // a string literal (e.g., "8") or a macro that evaluates to one. 159.36 #ifdef _LP64 159.37 +#define UINTX_FORMAT_W(width) UINT64_FORMAT_W(width) 159.38 #define SSIZE_FORMAT_W(width) INT64_FORMAT_W(width) 159.39 #define SIZE_FORMAT_W(width) UINT64_FORMAT_W(width) 159.40 #else 159.41 +#define UINTX_FORMAT_W(width) UINT32_FORMAT_W(width) 159.42 #define SSIZE_FORMAT_W(width) INT32_FORMAT_W(width) 159.43 #define SIZE_FORMAT_W(width) UINT32_FORMAT_W(width) 159.44 #endif // _LP64 159.45 159.46 // Format pointers and size_t (or size_t-like integer types) which change size 159.47 -// between 32- and 64-bit. 159.48 +// between 32- and 64-bit. The pointer format theoretically should be "%p", 159.49 +// however, it has different output on different platforms. On Windows, the data 159.50 +// will be padded with zeros automatically. On Solaris, we can use "%016p" & 159.51 +// "%08p" on 64 bit & 32 bit platforms to make the data padded with extra zeros. 159.52 +// On Linux, "%016p" or "%08p" is not be allowed, at least on the latest GCC 159.53 +// 4.3.2. So we have to use "%016x" or "%08x" to simulate the printing format. 159.54 +// GCC 4.3.2, however requires the data to be converted to "intptr_t" when 159.55 +// using "%x". 159.56 #ifdef _LP64 159.57 #define PTR_FORMAT PTR64_FORMAT 159.58 #define UINTX_FORMAT UINT64_FORMAT
160.1 --- a/src/share/vm/utilities/globalDefinitions_gcc.hpp Sat Jan 31 17:19:42 2009 -0800 160.2 +++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Feb 27 15:13:00 2009 -0800 160.3 @@ -116,7 +116,9 @@ 160.4 #ifdef _LP64 160.5 #define NULL_WORD 0L 160.6 #else 160.7 - #define NULL_WORD 0 160.8 + // Cast 0 to intptr_t rather than int32_t since they are not the same type 160.9 + // on platforms such as Mac OS X. 160.10 + #define NULL_WORD ((intptr_t)0) 160.11 #endif 160.12 #else 160.13 #define NULL_WORD NULL
161.1 --- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Sat Jan 31 17:19:42 2009 -0800 161.2 +++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Feb 27 15:13:00 2009 -0800 161.3 @@ -115,7 +115,9 @@ 161.4 #ifdef _LP64 161.5 #define NULL_WORD 0L 161.6 #else 161.7 - #define NULL_WORD 0 161.8 + // Cast 0 to intptr_t rather than int32_t since they are not the same type 161.9 + // on some platforms. 161.10 + #define NULL_WORD ((intptr_t)0) 161.11 #endif 161.12 #else 161.13 #define NULL_WORD NULL
162.1 --- a/src/share/vm/utilities/ostream.cpp Sat Jan 31 17:19:42 2009 -0800 162.2 +++ b/src/share/vm/utilities/ostream.cpp Fri Feb 27 15:13:00 2009 -0800 162.3 @@ -300,7 +300,10 @@ 162.4 } 162.5 162.6 void fileStream::write(const char* s, size_t len) { 162.7 - if (_file != NULL) fwrite(s, 1, len, _file); 162.8 + if (_file != NULL) { 162.9 + // Make an unused local variable to avoid warning from gcc 4.x compiler. 162.10 + size_t count = fwrite(s, 1, len, _file); 162.11 + } 162.12 update_position(s, len); 162.13 } 162.14 162.15 @@ -328,7 +331,10 @@ 162.16 } 162.17 162.18 void fdStream::write(const char* s, size_t len) { 162.19 - if (_fd != -1) ::write(_fd, s, (int)len); 162.20 + if (_fd != -1) { 162.21 + // Make an unused local variable to avoid warning from gcc 4.x compiler. 162.22 + size_t count = ::write(_fd, s, (int)len); 162.23 + } 162.24 update_position(s, len); 162.25 } 162.26
163.1 --- a/src/share/vm/utilities/taskqueue.cpp Sat Jan 31 17:19:42 2009 -0800 163.2 +++ b/src/share/vm/utilities/taskqueue.cpp Fri Feb 27 15:13:00 2009 -0800 163.3 @@ -25,6 +25,12 @@ 163.4 # include "incls/_precompiled.incl" 163.5 # include "incls/_taskqueue.cpp.incl" 163.6 163.7 +#ifdef TRACESPINNING 163.8 +uint ParallelTaskTerminator::_total_yields = 0; 163.9 +uint ParallelTaskTerminator::_total_spins = 0; 163.10 +uint ParallelTaskTerminator::_total_peeks = 0; 163.11 +#endif 163.12 + 163.13 bool TaskQueueSuper::peek() { 163.14 return _bottom != _age.top(); 163.15 } 163.16 @@ -69,15 +75,62 @@ 163.17 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { 163.18 Atomic::inc(&_offered_termination); 163.19 163.20 - juint yield_count = 0; 163.21 + uint yield_count = 0; 163.22 + // Number of hard spin loops done since last yield 163.23 + uint hard_spin_count = 0; 163.24 + // Number of iterations in the hard spin loop. 163.25 + uint hard_spin_limit = WorkStealingHardSpins; 163.26 + 163.27 + // If WorkStealingSpinToYieldRatio is 0, no hard spinning is done. 163.28 + // If it is greater than 0, then start with a small number 163.29 + // of spins and increase number with each turn at spinning until 163.30 + // the count of hard spins exceeds WorkStealingSpinToYieldRatio. 163.31 + // Then do a yield() call and start spinning afresh. 163.32 + if (WorkStealingSpinToYieldRatio > 0) { 163.33 + hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio; 163.34 + hard_spin_limit = MAX2(hard_spin_limit, 1U); 163.35 + } 163.36 + // Remember the initial spin limit. 163.37 + uint hard_spin_start = hard_spin_limit; 163.38 + 163.39 + // Loop waiting for all threads to offer termination or 163.40 + // more work. 163.41 while (true) { 163.42 + // Are all threads offering termination? 163.43 if (_offered_termination == _n_threads) { 163.44 - //inner_termination_loop(); 163.45 return true; 163.46 } else { 163.47 + // Look for more work. 163.48 + // Periodically sleep() instead of yield() to give threads 163.49 + // waiting on the cores the chance to grab this code 163.50 if (yield_count <= WorkStealingYieldsBeforeSleep) { 163.51 + // Do a yield or hardspin. For purposes of deciding whether 163.52 + // to sleep, count this as a yield. 163.53 yield_count++; 163.54 - yield(); 163.55 + 163.56 + // Periodically call yield() instead spinning 163.57 + // After WorkStealingSpinToYieldRatio spins, do a yield() call 163.58 + // and reset the counts and starting limit. 163.59 + if (hard_spin_count > WorkStealingSpinToYieldRatio) { 163.60 + yield(); 163.61 + hard_spin_count = 0; 163.62 + hard_spin_limit = hard_spin_start; 163.63 +#ifdef TRACESPINNING 163.64 + _total_yields++; 163.65 +#endif 163.66 + } else { 163.67 + // Hard spin this time 163.68 + // Increase the hard spinning period but only up to a limit. 163.69 + hard_spin_limit = MIN2(2*hard_spin_limit, 163.70 + (uint) WorkStealingHardSpins); 163.71 + for (uint j = 0; j < hard_spin_limit; j++) { 163.72 + SpinPause(); 163.73 + } 163.74 + hard_spin_count++; 163.75 +#ifdef TRACESPINNING 163.76 + _total_spins++; 163.77 +#endif 163.78 + } 163.79 } else { 163.80 if (PrintGCDetails && Verbose) { 163.81 gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() " 163.82 @@ -92,6 +145,9 @@ 163.83 sleep(WorkStealingSleepMillis); 163.84 } 163.85 163.86 +#ifdef TRACESPINNING 163.87 + _total_peeks++; 163.88 +#endif 163.89 if (peek_in_queue_set() || 163.90 (terminator != NULL && terminator->should_exit_termination())) { 163.91 Atomic::dec(&_offered_termination); 163.92 @@ -101,6 +157,16 @@ 163.93 } 163.94 } 163.95 163.96 +#ifdef TRACESPINNING 163.97 +void ParallelTaskTerminator::print_termination_counts() { 163.98 + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " 163.99 + "Total spins: %lld Total peeks: %lld", 163.100 + total_yields(), 163.101 + total_spins(), 163.102 + total_peeks()); 163.103 +} 163.104 +#endif 163.105 + 163.106 void ParallelTaskTerminator::reset_for_reuse() { 163.107 if (_offered_termination != 0) { 163.108 assert(_offered_termination == _n_threads,
164.1 --- a/src/share/vm/utilities/taskqueue.hpp Sat Jan 31 17:19:42 2009 -0800 164.2 +++ b/src/share/vm/utilities/taskqueue.hpp Fri Feb 27 15:13:00 2009 -0800 164.3 @@ -22,67 +22,76 @@ 164.4 * 164.5 */ 164.6 164.7 +#ifdef LP64 164.8 +typedef juint TAG_TYPE; 164.9 +// for a taskqueue size of 4M 164.10 +#define LOG_TASKQ_SIZE 22 164.11 +#else 164.12 +typedef jushort TAG_TYPE; 164.13 +// for a taskqueue size of 16K 164.14 +#define LOG_TASKQ_SIZE 14 164.15 +#endif 164.16 + 164.17 class TaskQueueSuper: public CHeapObj { 164.18 protected: 164.19 // The first free element after the last one pushed (mod _n). 164.20 - // (For now we'll assume only 32-bit CAS). 164.21 - volatile juint _bottom; 164.22 + volatile uint _bottom; 164.23 164.24 // log2 of the size of the queue. 164.25 enum SomeProtectedConstants { 164.26 - Log_n = 14 164.27 + Log_n = LOG_TASKQ_SIZE 164.28 }; 164.29 +#undef LOG_TASKQ_SIZE 164.30 164.31 // Size of the queue. 164.32 - juint n() { return (1 << Log_n); } 164.33 + uint n() { return (1 << Log_n); } 164.34 // For computing "x mod n" efficiently. 164.35 - juint n_mod_mask() { return n() - 1; } 164.36 + uint n_mod_mask() { return n() - 1; } 164.37 164.38 struct Age { 164.39 - jushort _top; 164.40 - jushort _tag; 164.41 + TAG_TYPE _top; 164.42 + TAG_TYPE _tag; 164.43 164.44 - jushort tag() const { return _tag; } 164.45 - jushort top() const { return _top; } 164.46 + TAG_TYPE tag() const { return _tag; } 164.47 + TAG_TYPE top() const { return _top; } 164.48 164.49 Age() { _tag = 0; _top = 0; } 164.50 164.51 friend bool operator ==(const Age& a1, const Age& a2) { 164.52 return a1.tag() == a2.tag() && a1.top() == a2.top(); 164.53 } 164.54 - 164.55 }; 164.56 Age _age; 164.57 // These make sure we do single atomic reads and writes. 164.58 Age get_age() { 164.59 - jint res = *(volatile jint*)(&_age); 164.60 + uint res = *(volatile uint*)(&_age); 164.61 return *(Age*)(&res); 164.62 } 164.63 void set_age(Age a) { 164.64 - *(volatile jint*)(&_age) = *(int*)(&a); 164.65 + *(volatile uint*)(&_age) = *(uint*)(&a); 164.66 } 164.67 164.68 - jushort get_top() { 164.69 + TAG_TYPE get_top() { 164.70 return get_age().top(); 164.71 } 164.72 164.73 // These both operate mod _n. 164.74 - juint increment_index(juint ind) { 164.75 + uint increment_index(uint ind) { 164.76 return (ind + 1) & n_mod_mask(); 164.77 } 164.78 - juint decrement_index(juint ind) { 164.79 + uint decrement_index(uint ind) { 164.80 return (ind - 1) & n_mod_mask(); 164.81 } 164.82 164.83 // Returns a number in the range [0.._n). If the result is "n-1", it 164.84 // should be interpreted as 0. 164.85 - juint dirty_size(juint bot, juint top) { 164.86 - return ((jint)bot - (jint)top) & n_mod_mask(); 164.87 + uint dirty_size(uint bot, uint top) { 164.88 + return ((int)bot - (int)top) & n_mod_mask(); 164.89 } 164.90 164.91 // Returns the size corresponding to the given "bot" and "top". 164.92 - juint size(juint bot, juint top) { 164.93 - juint sz = dirty_size(bot, top); 164.94 + uint size(uint bot, uint top) { 164.95 + uint sz = dirty_size(bot, top); 164.96 // Has the queue "wrapped", so that bottom is less than top? 164.97 // There's a complicated special case here. A pair of threads could 164.98 // perform pop_local and pop_global operations concurrently, starting 164.99 @@ -94,7 +103,7 @@ 164.100 // owner performs pop_local's, and several concurrent threads 164.101 // attempting to perform the pop_global will all perform the same CAS, 164.102 // and only one can succeed. Any stealing thread that reads after 164.103 - // either the increment or decrement will seen an empty queue, and will 164.104 + // either the increment or decrement will see an empty queue, and will 164.105 // not join the competitors. The "sz == -1 || sz == _n-1" state will 164.106 // not be modified by concurrent queues, so the owner thread can reset 164.107 // the state to _bottom == top so subsequent pushes will be performed 164.108 @@ -112,11 +121,11 @@ 164.109 // Return an estimate of the number of elements in the queue. 164.110 // The "careful" version admits the possibility of pop_local/pop_global 164.111 // races. 164.112 - juint size() { 164.113 + uint size() { 164.114 return size(_bottom, get_top()); 164.115 } 164.116 164.117 - juint dirty_size() { 164.118 + uint dirty_size() { 164.119 return dirty_size(_bottom, get_top()); 164.120 } 164.121 164.122 @@ -127,15 +136,15 @@ 164.123 164.124 // Maximum number of elements allowed in the queue. This is two less 164.125 // than the actual queue size, for somewhat complicated reasons. 164.126 - juint max_elems() { return n() - 2; } 164.127 + uint max_elems() { return n() - 2; } 164.128 164.129 }; 164.130 164.131 template<class E> class GenericTaskQueue: public TaskQueueSuper { 164.132 private: 164.133 // Slow paths for push, pop_local. (pop_global has no fast path.) 164.134 - bool push_slow(E t, juint dirty_n_elems); 164.135 - bool pop_local_slow(juint localBot, Age oldAge); 164.136 + bool push_slow(E t, uint dirty_n_elems); 164.137 + bool pop_local_slow(uint localBot, Age oldAge); 164.138 164.139 public: 164.140 // Initializes the queue to empty. 164.141 @@ -170,7 +179,7 @@ 164.142 164.143 template<class E> 164.144 GenericTaskQueue<E>::GenericTaskQueue():TaskQueueSuper() { 164.145 - assert(sizeof(Age) == sizeof(jint), "Depends on this."); 164.146 + assert(sizeof(Age) == sizeof(int), "Depends on this."); 164.147 } 164.148 164.149 template<class E> 164.150 @@ -182,9 +191,9 @@ 164.151 template<class E> 164.152 void GenericTaskQueue<E>::oops_do(OopClosure* f) { 164.153 // tty->print_cr("START OopTaskQueue::oops_do"); 164.154 - int iters = size(); 164.155 - juint index = _bottom; 164.156 - for (int i = 0; i < iters; ++i) { 164.157 + uint iters = size(); 164.158 + uint index = _bottom; 164.159 + for (uint i = 0; i < iters; ++i) { 164.160 index = decrement_index(index); 164.161 // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T, 164.162 // index, &_elems[index], _elems[index]); 164.163 @@ -198,10 +207,10 @@ 164.164 164.165 164.166 template<class E> 164.167 -bool GenericTaskQueue<E>::push_slow(E t, juint dirty_n_elems) { 164.168 +bool GenericTaskQueue<E>::push_slow(E t, uint dirty_n_elems) { 164.169 if (dirty_n_elems == n() - 1) { 164.170 // Actually means 0, so do the push. 164.171 - juint localBot = _bottom; 164.172 + uint localBot = _bottom; 164.173 _elems[localBot] = t; 164.174 _bottom = increment_index(localBot); 164.175 return true; 164.176 @@ -211,7 +220,7 @@ 164.177 164.178 template<class E> 164.179 bool GenericTaskQueue<E>:: 164.180 -pop_local_slow(juint localBot, Age oldAge) { 164.181 +pop_local_slow(uint localBot, Age oldAge) { 164.182 // This queue was observed to contain exactly one element; either this 164.183 // thread will claim it, or a competing "pop_global". In either case, 164.184 // the queue will be logically empty afterwards. Create a new Age value 164.185 @@ -230,9 +239,8 @@ 164.186 Age tempAge; 164.187 // No competing pop_global has yet incremented "top"; we'll try to 164.188 // install new_age, thus claiming the element. 164.189 - assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), 164.190 - "Assumption about CAS unit."); 164.191 - *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); 164.192 + assert(sizeof(Age) == sizeof(int), "Assumption about CAS unit."); 164.193 + *(uint*)&tempAge = Atomic::cmpxchg(*(uint*)&newAge, (volatile uint*)&_age, *(uint*)&oldAge); 164.194 if (tempAge == oldAge) { 164.195 // We win. 164.196 assert(dirty_size(localBot, get_top()) != n() - 1, 164.197 @@ -253,8 +261,8 @@ 164.198 bool GenericTaskQueue<E>::pop_global(E& t) { 164.199 Age newAge; 164.200 Age oldAge = get_age(); 164.201 - juint localBot = _bottom; 164.202 - juint n_elems = size(localBot, oldAge.top()); 164.203 + uint localBot = _bottom; 164.204 + uint n_elems = size(localBot, oldAge.top()); 164.205 if (n_elems == 0) { 164.206 return false; 164.207 } 164.208 @@ -263,7 +271,7 @@ 164.209 newAge._top = increment_index(newAge.top()); 164.210 if ( newAge._top == 0 ) newAge._tag++; 164.211 Age resAge; 164.212 - *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); 164.213 + *(uint*)&resAge = Atomic::cmpxchg(*(uint*)&newAge, (volatile uint*)&_age, *(uint*)&oldAge); 164.214 // Note that using "_bottom" here might fail, since a pop_local might 164.215 // have decremented it. 164.216 assert(dirty_size(localBot, newAge._top) != n() - 1, 164.217 @@ -287,7 +295,7 @@ 164.218 164.219 template<class E> class GenericTaskQueueSet: public TaskQueueSetSuper { 164.220 private: 164.221 - int _n; 164.222 + uint _n; 164.223 GenericTaskQueue<E>** _queues; 164.224 164.225 public: 164.226 @@ -300,51 +308,51 @@ 164.227 } 164.228 } 164.229 164.230 - bool steal_1_random(int queue_num, int* seed, E& t); 164.231 - bool steal_best_of_2(int queue_num, int* seed, E& t); 164.232 - bool steal_best_of_all(int queue_num, int* seed, E& t); 164.233 + bool steal_1_random(uint queue_num, int* seed, E& t); 164.234 + bool steal_best_of_2(uint queue_num, int* seed, E& t); 164.235 + bool steal_best_of_all(uint queue_num, int* seed, E& t); 164.236 164.237 - void register_queue(int i, GenericTaskQueue<E>* q); 164.238 + void register_queue(uint i, GenericTaskQueue<E>* q); 164.239 164.240 - GenericTaskQueue<E>* queue(int n); 164.241 + GenericTaskQueue<E>* queue(uint n); 164.242 164.243 // The thread with queue number "queue_num" (and whose random number seed 164.244 // is at "seed") is trying to steal a task from some other queue. (It 164.245 // may try several queues, according to some configuration parameter.) 164.246 // If some steal succeeds, returns "true" and sets "t" the stolen task, 164.247 // otherwise returns false. 164.248 - bool steal(int queue_num, int* seed, E& t); 164.249 + bool steal(uint queue_num, int* seed, E& t); 164.250 164.251 bool peek(); 164.252 }; 164.253 164.254 template<class E> 164.255 -void GenericTaskQueueSet<E>::register_queue(int i, GenericTaskQueue<E>* q) { 164.256 - assert(0 <= i && i < _n, "index out of range."); 164.257 +void GenericTaskQueueSet<E>::register_queue(uint i, GenericTaskQueue<E>* q) { 164.258 + assert(i < _n, "index out of range."); 164.259 _queues[i] = q; 164.260 } 164.261 164.262 template<class E> 164.263 -GenericTaskQueue<E>* GenericTaskQueueSet<E>::queue(int i) { 164.264 +GenericTaskQueue<E>* GenericTaskQueueSet<E>::queue(uint i) { 164.265 return _queues[i]; 164.266 } 164.267 164.268 template<class E> 164.269 -bool GenericTaskQueueSet<E>::steal(int queue_num, int* seed, E& t) { 164.270 - for (int i = 0; i < 2 * _n; i++) 164.271 +bool GenericTaskQueueSet<E>::steal(uint queue_num, int* seed, E& t) { 164.272 + for (uint i = 0; i < 2 * _n; i++) 164.273 if (steal_best_of_2(queue_num, seed, t)) 164.274 return true; 164.275 return false; 164.276 } 164.277 164.278 template<class E> 164.279 -bool GenericTaskQueueSet<E>::steal_best_of_all(int queue_num, int* seed, E& t) { 164.280 +bool GenericTaskQueueSet<E>::steal_best_of_all(uint queue_num, int* seed, E& t) { 164.281 if (_n > 2) { 164.282 int best_k; 164.283 - jint best_sz = 0; 164.284 - for (int k = 0; k < _n; k++) { 164.285 + uint best_sz = 0; 164.286 + for (uint k = 0; k < _n; k++) { 164.287 if (k == queue_num) continue; 164.288 - jint sz = _queues[k]->size(); 164.289 + uint sz = _queues[k]->size(); 164.290 if (sz > best_sz) { 164.291 best_sz = sz; 164.292 best_k = k; 164.293 @@ -362,9 +370,9 @@ 164.294 } 164.295 164.296 template<class E> 164.297 -bool GenericTaskQueueSet<E>::steal_1_random(int queue_num, int* seed, E& t) { 164.298 +bool GenericTaskQueueSet<E>::steal_1_random(uint queue_num, int* seed, E& t) { 164.299 if (_n > 2) { 164.300 - int k = queue_num; 164.301 + uint k = queue_num; 164.302 while (k == queue_num) k = randomParkAndMiller(seed) % _n; 164.303 return _queues[2]->pop_global(t); 164.304 } else if (_n == 2) { 164.305 @@ -378,20 +386,20 @@ 164.306 } 164.307 164.308 template<class E> 164.309 -bool GenericTaskQueueSet<E>::steal_best_of_2(int queue_num, int* seed, E& t) { 164.310 +bool GenericTaskQueueSet<E>::steal_best_of_2(uint queue_num, int* seed, E& t) { 164.311 if (_n > 2) { 164.312 - int k1 = queue_num; 164.313 + uint k1 = queue_num; 164.314 while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; 164.315 - int k2 = queue_num; 164.316 + uint k2 = queue_num; 164.317 while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; 164.318 // Sample both and try the larger. 164.319 - juint sz1 = _queues[k1]->size(); 164.320 - juint sz2 = _queues[k2]->size(); 164.321 + uint sz1 = _queues[k1]->size(); 164.322 + uint sz2 = _queues[k2]->size(); 164.323 if (sz2 > sz1) return _queues[k2]->pop_global(t); 164.324 else return _queues[k1]->pop_global(t); 164.325 } else if (_n == 2) { 164.326 // Just try the other one. 164.327 - int k = (queue_num + 1) % 2; 164.328 + uint k = (queue_num + 1) % 2; 164.329 return _queues[k]->pop_global(t); 164.330 } else { 164.331 assert(_n == 1, "can't be zero."); 164.332 @@ -402,7 +410,7 @@ 164.333 template<class E> 164.334 bool GenericTaskQueueSet<E>::peek() { 164.335 // Try all the queues. 164.336 - for (int j = 0; j < _n; j++) { 164.337 + for (uint j = 0; j < _n; j++) { 164.338 if (_queues[j]->peek()) 164.339 return true; 164.340 } 164.341 @@ -418,11 +426,19 @@ 164.342 // A class to aid in the termination of a set of parallel tasks using 164.343 // TaskQueueSet's for work stealing. 164.344 164.345 +#undef TRACESPINNING 164.346 + 164.347 class ParallelTaskTerminator: public StackObj { 164.348 private: 164.349 int _n_threads; 164.350 TaskQueueSetSuper* _queue_set; 164.351 - jint _offered_termination; 164.352 + int _offered_termination; 164.353 + 164.354 +#ifdef TRACESPINNING 164.355 + static uint _total_yields; 164.356 + static uint _total_spins; 164.357 + static uint _total_peeks; 164.358 +#endif 164.359 164.360 bool peek_in_queue_set(); 164.361 protected: 164.362 @@ -454,13 +470,19 @@ 164.363 // the terminator is finished. 164.364 void reset_for_reuse(); 164.365 164.366 +#ifdef TRACESPINNING 164.367 + static uint total_yields() { return _total_yields; } 164.368 + static uint total_spins() { return _total_spins; } 164.369 + static uint total_peeks() { return _total_peeks; } 164.370 + static void print_termination_counts(); 164.371 +#endif 164.372 }; 164.373 164.374 #define SIMPLE_STACK 0 164.375 164.376 template<class E> inline bool GenericTaskQueue<E>::push(E t) { 164.377 #if SIMPLE_STACK 164.378 - juint localBot = _bottom; 164.379 + uint localBot = _bottom; 164.380 if (_bottom < max_elems()) { 164.381 _elems[localBot] = t; 164.382 _bottom = localBot + 1; 164.383 @@ -469,10 +491,10 @@ 164.384 return false; 164.385 } 164.386 #else 164.387 - juint localBot = _bottom; 164.388 + uint localBot = _bottom; 164.389 assert((localBot >= 0) && (localBot < n()), "_bottom out of range."); 164.390 - jushort top = get_top(); 164.391 - juint dirty_n_elems = dirty_size(localBot, top); 164.392 + TAG_TYPE top = get_top(); 164.393 + uint dirty_n_elems = dirty_size(localBot, top); 164.394 assert((dirty_n_elems >= 0) && (dirty_n_elems < n()), 164.395 "n_elems out of range."); 164.396 if (dirty_n_elems < max_elems()) { 164.397 @@ -487,19 +509,19 @@ 164.398 164.399 template<class E> inline bool GenericTaskQueue<E>::pop_local(E& t) { 164.400 #if SIMPLE_STACK 164.401 - juint localBot = _bottom; 164.402 + uint localBot = _bottom; 164.403 assert(localBot > 0, "precondition."); 164.404 localBot--; 164.405 t = _elems[localBot]; 164.406 _bottom = localBot; 164.407 return true; 164.408 #else 164.409 - juint localBot = _bottom; 164.410 + uint localBot = _bottom; 164.411 // This value cannot be n-1. That can only occur as a result of 164.412 // the assignment to bottom in this method. If it does, this method 164.413 // resets the size( to 0 before the next call (which is sequential, 164.414 // since this is pop_local.) 164.415 - juint dirty_n_elems = dirty_size(localBot, get_top()); 164.416 + uint dirty_n_elems = dirty_size(localBot, get_top()); 164.417 assert(dirty_n_elems != n() - 1, "Shouldn't be possible..."); 164.418 if (dirty_n_elems == 0) return false; 164.419 localBot = decrement_index(localBot); 164.420 @@ -512,7 +534,7 @@ 164.421 // If there's still at least one element in the queue, based on the 164.422 // "_bottom" and "age" we've read, then there can be no interference with 164.423 // a "pop_global" operation, and we're done. 164.424 - juint tp = get_top(); 164.425 + TAG_TYPE tp = get_top(); // XXX 164.426 if (size(localBot, tp) > 0) { 164.427 assert(dirty_size(localBot, tp) != n() - 1, 164.428 "Shouldn't be possible..."); 164.429 @@ -581,7 +603,7 @@ 164.430 bool is_empty(); 164.431 bool stealable_is_empty(); 164.432 bool overflow_is_empty(); 164.433 - juint stealable_size() { return _region_queue.size(); } 164.434 + uint stealable_size() { return _region_queue.size(); } 164.435 RegionTaskQueue* task_queue() { return &_region_queue; } 164.436 }; 164.437
165.1 --- a/src/share/vm/utilities/vmError.cpp Sat Jan 31 17:19:42 2009 -0800 165.2 +++ b/src/share/vm/utilities/vmError.cpp Fri Feb 27 15:13:00 2009 -0800 165.3 @@ -674,6 +674,11 @@ 165.4 reset_signal_handlers(); 165.5 165.6 } else { 165.7 + // If UseOsErrorReporting we call this for each level of the call stack 165.8 + // while searching for the exception handler. Only the first level needs 165.9 + // to be reported. 165.10 + if (UseOSErrorReporting && log_done) return; 165.11 + 165.12 // This is not the first error, see if it happened in a different thread 165.13 // or in the same thread during error reporting. 165.14 if (first_error_tid != mytid) {
166.1 --- a/src/share/vm/utilities/vmError.hpp Sat Jan 31 17:19:42 2009 -0800 166.2 +++ b/src/share/vm/utilities/vmError.hpp Fri Feb 27 15:13:00 2009 -0800 166.3 @@ -50,7 +50,7 @@ 166.4 166.5 // additional info for VM internal errors 166.6 const char * _filename; 166.7 - int _lineno; 166.8 + size_t _lineno; 166.9 166.10 // used by fatal error handler 166.11 int _current_step;
167.1 --- a/src/share/vm/utilities/workgroup.hpp Sat Jan 31 17:19:42 2009 -0800 167.2 +++ b/src/share/vm/utilities/workgroup.hpp Fri Feb 27 15:13:00 2009 -0800 167.3 @@ -32,7 +32,7 @@ 167.4 167.5 // An abstract task to be worked on by a gang. 167.6 // You subclass this to supply your own work() method 167.7 -class AbstractGangTask: public CHeapObj { 167.8 +class AbstractGangTask VALUE_OBJ_CLASS_SPEC { 167.9 public: 167.10 // The abstract work method. 167.11 // The argument tells you which member of the gang you are.
168.1 --- a/test/Makefile Sat Jan 31 17:19:42 2009 -0800 168.2 +++ b/test/Makefile Fri Feb 27 15:13:00 2009 -0800 168.3 @@ -28,9 +28,9 @@ 168.4 168.5 # Get OS/ARCH specifics 168.6 OSNAME = $(shell uname -s) 168.7 -SLASH_JAVA = /java 168.8 ifeq ($(OSNAME), SunOS) 168.9 PLATFORM = solaris 168.10 + SLASH_JAVA = /java 168.11 ARCH = $(shell uname -p) 168.12 ifeq ($(ARCH), i386) 168.13 ARCH=i586 168.14 @@ -38,6 +38,7 @@ 168.15 endif 168.16 ifeq ($(OSNAME), Linux) 168.17 PLATFORM = linux 168.18 + SLASH_JAVA = /java 168.19 ARCH = $(shell uname -m) 168.20 ifeq ($(ARCH), i386) 168.21 ARCH = i586 168.22 @@ -62,6 +63,10 @@ 168.23 EXESUFFIX = .exe 168.24 endif 168.25 168.26 +ifdef ALT_SLASH_JAVA 168.27 + SLASH_JAVA = $(ALT_SLASH_JAVA) 168.28 +endif 168.29 + 168.30 # Utilities used 168.31 CD = cd 168.32 CP = cp
169.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 169.2 +++ b/test/compiler/6603011/Test.java Fri Feb 27 15:13:00 2009 -0800 169.3 @@ -0,0 +1,220 @@ 169.4 +/* 169.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 169.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 169.7 + * 169.8 + * This code is free software; you can redistribute it and/or modify it 169.9 + * under the terms of the GNU General Public License version 2 only, as 169.10 + * published by the Free Software Foundation. 169.11 + * 169.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 169.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 169.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 169.15 + * version 2 for more details (a copy is included in the LICENSE file that 169.16 + * accompanied this code). 169.17 + * 169.18 + * You should have received a copy of the GNU General Public License version 169.19 + * 2 along with this work; if not, write to the Free Software Foundation, 169.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 169.21 + * 169.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 169.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 169.24 + * have any questions. 169.25 + */ 169.26 + 169.27 +/** 169.28 + * @test 169.29 + * @bug 6603011 169.30 + * @summary long/int division by constant 169.31 + * 169.32 + * @run main/othervm -Xcomp -Xbatch -XX:-Inline Test 169.33 + */ 169.34 + 169.35 +// 169.36 +// -XX:-Inline is essential to this test so that verification functions 169.37 +// divi, modi, divl and modl generate "plain" divides. 169.38 +// -Xcomp -Xbatch are also useful to ensure the full range of 169.39 +// dividend and divisor combinations are tested 169.40 +// 169.41 + 169.42 +import java.net.*; 169.43 + 169.44 +class s { 169.45 + static int divi(int dividend, int divisor) { return dividend / divisor; } 169.46 + static int modi(int dividend, int divisor) { return dividend % divisor; } 169.47 + static long divl(long dividend, long divisor) { return dividend / divisor; } 169.48 + static long modl(long dividend, long divisor) { return dividend % divisor; } 169.49 +} 169.50 + 169.51 +public class Test implements Runnable { 169.52 + // Report verbose messages on failure; turn off to suppress 169.53 + // too much output with gross numbers of failures. 169.54 + static final boolean VERBOSE = true; 169.55 + 169.56 + // Initailize DIVISOR so that it is final in this class. 169.57 + static final int DIVISOR; 169.58 + static { 169.59 + int value = 0; 169.60 + try { 169.61 + value = Integer.decode(System.getProperty("divisor")); 169.62 + } catch (Throwable e) { 169.63 + } 169.64 + DIVISOR = value; 169.65 + } 169.66 + 169.67 + // The methods of interest. We want the JIT to compile these 169.68 + // and convert the divide into a multiply. 169.69 + public int divbyI (int dividend) { return dividend / DIVISOR; } 169.70 + public int modbyI (int dividend) { return dividend % DIVISOR; } 169.71 + public long divbyL (long dividend) { return dividend / DIVISOR; } 169.72 + public long modbyL (long dividend) { return dividend % DIVISOR; } 169.73 + 169.74 + public int divisor() { return DIVISOR; } 169.75 + 169.76 + public boolean checkI (int dividend) { 169.77 + int quo = divbyI(dividend); 169.78 + int rem = modbyI(dividend); 169.79 + int quo0 = s.divi(dividend, divisor()); 169.80 + int rem0 = s.modi(dividend, divisor()); 169.81 + 169.82 + if (quo != quo0 || rem != rem0) { 169.83 + if (VERBOSE) { 169.84 + System.out.println("Computed: " + dividend + " / " + divisor() + " = " + 169.85 + quo + ", " + dividend + " % " + divisor() + " = " + rem ); 169.86 + System.out.println("expected: " + dividend + " / " + divisor() + " = " + 169.87 + quo0 + ", " + dividend + " % " + divisor() + " = " + rem0); 169.88 + // Report sign of rem failure 169.89 + if (rem != 0 && (rem ^ dividend) < 0) { 169.90 + System.out.println(" rem & dividend have different signs"); 169.91 + } 169.92 + // Report range of rem failure 169.93 + if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) { 169.94 + System.out.println(" remainder out of range"); 169.95 + } 169.96 + // Report quo/rem identity relationship failure 169.97 + if ((quo * divisor()) + rem != dividend) { 169.98 + System.out.println(" quotien/remainder invariant broken"); 169.99 + } 169.100 + } 169.101 + return false; 169.102 + } 169.103 + return true; 169.104 + } 169.105 + 169.106 + public boolean checkL (long dividend) { 169.107 + long quo = divbyL(dividend); 169.108 + long rem = modbyL(dividend); 169.109 + long quo0 = s.divl(dividend, divisor()); 169.110 + long rem0 = s.modl(dividend, divisor()); 169.111 + 169.112 + if (quo != quo0 || rem != rem0) { 169.113 + if (VERBOSE) { 169.114 + System.out.println(" " + dividend + " / " + divisor() + " = " + 169.115 + quo + ", " + dividend + " % " + divisor() + " = " + rem); 169.116 + // Report sign of rem failure 169.117 + if (rem != 0 && (rem ^ dividend) < 0) { 169.118 + System.out.println(" rem & dividend have different signs"); 169.119 + } 169.120 + // Report range of rem failure 169.121 + if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) { 169.122 + System.out.println(" remainder out of range"); 169.123 + } 169.124 + // Report quo/rem identity relationship failure 169.125 + if ((quo * divisor()) + rem != dividend) { 169.126 + System.out.println(" (" + quo + " * " + divisor() + ") + " + rem + " != " 169.127 + + dividend); 169.128 + } 169.129 + } 169.130 + return false; 169.131 + } 169.132 + return true; 169.133 + } 169.134 + 169.135 + public void run() { 169.136 + // Don't try to divide by zero 169.137 + if (divisor() == 0) return; 169.138 + 169.139 + // Range of dividends to check. Try dividends from start to end 169.140 + // inclusive, as well as variations on those values as shifted 169.141 + // left. 169.142 + int start = -1024; 169.143 + int end = 1024; 169.144 + 169.145 + // Test int division using a variety of dividends. 169.146 + int wrong = 0; 169.147 + int total = 0; 169.148 + 169.149 + outerloop: 169.150 + for (int i = start; i <= end; i++) { 169.151 + for (int s = 0; s < 32; s += 4) { 169.152 + total++; 169.153 + int dividend = i << s; 169.154 + if (!checkI(dividend)) { 169.155 + wrong++; 169.156 + // Stop on the first failure 169.157 + // break outerloop; 169.158 + } 169.159 + } 169.160 + } 169.161 + if (wrong > 0) { 169.162 + System.out.println("divisor " + divisor() + ": " + 169.163 + wrong + "/" + total + " wrong int divisions"); 169.164 + } 169.165 + 169.166 + // Test long division using a variety of dividends. 169.167 + wrong = 0; 169.168 + total = 0; 169.169 + 169.170 + outerloop: 169.171 + for (int i = start; i <= end; i++) { 169.172 + for (int s = 0; s < 64; s += 4) { 169.173 + total++; 169.174 + long dividend = i << s; 169.175 + if (!checkL(dividend)) { 169.176 + wrong++; 169.177 + // Stop on the first failure 169.178 + // break outerloop; 169.179 + } 169.180 + } 169.181 + } 169.182 + if (wrong > 0) { 169.183 + System.out.println("divisor " + divisor() + ": " + 169.184 + wrong + "/" + total + " wrong long divisions"); 169.185 + } 169.186 + 169.187 + } 169.188 + 169.189 + // Reload this class with the "divisor" property set to the input parameter. 169.190 + // This allows the JIT to see q.DIVISOR as a final constant, and change 169.191 + // any divisions or mod operations into multiplies. 169.192 + public static void test_divisor(int divisor, 169.193 + URLClassLoader apploader) throws Exception { 169.194 + System.setProperty("divisor", "" + divisor); 169.195 + ClassLoader loader = new URLClassLoader(apploader.getURLs(), 169.196 + apploader.getParent()); 169.197 + Class c = loader.loadClass("Test"); 169.198 + Runnable r = (Runnable)c.newInstance(); 169.199 + r.run(); 169.200 + } 169.201 + 169.202 + public static void main(String[] args) throws Exception { 169.203 + Class cl = Class.forName("Test"); 169.204 + URLClassLoader apploader = (URLClassLoader)cl.getClassLoader(); 169.205 + 169.206 + 169.207 + // Test every divisor between -100 and 100. 169.208 + for (int i = -100; i <= 100; i++) { 169.209 + test_divisor(i, apploader); 169.210 + } 169.211 + 169.212 + // Try a few divisors outside the typical range. 169.213 + // The values below have been observed in rt.jar. 169.214 + test_divisor(101, apploader); 169.215 + test_divisor(400, apploader); 169.216 + test_divisor(1000, apploader); 169.217 + test_divisor(3600, apploader); 169.218 + test_divisor(9973, apploader); 169.219 + test_divisor(86400, apploader); 169.220 + test_divisor(1000000, apploader); 169.221 + } 169.222 + 169.223 +}
170.1 --- a/test/compiler/6775880/Test.java Sat Jan 31 17:19:42 2009 -0800 170.2 +++ b/test/compiler/6775880/Test.java Fri Feb 27 15:13:00 2009 -0800 170.3 @@ -27,7 +27,7 @@ 170.4 * @bug 6775880 170.5 * @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now") 170.6 * @compile -source 1.4 -target 1.4 Test.java 170.7 - * @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test 170.8 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test 170.9 */ 170.10 170.11 public class Test {
171.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 171.2 +++ b/test/compiler/6778657/Test.java Fri Feb 27 15:13:00 2009 -0800 171.3 @@ -0,0 +1,75 @@ 171.4 +/* 171.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 171.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 171.7 + * 171.8 + * This code is free software; you can redistribute it and/or modify it 171.9 + * under the terms of the GNU General Public License version 2 only, as 171.10 + * published by the Free Software Foundation. 171.11 + * 171.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 171.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 171.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 171.15 + * version 2 for more details (a copy is included in the LICENSE file that 171.16 + * accompanied this code). 171.17 + * 171.18 + * You should have received a copy of the GNU General Public License version 171.19 + * 2 along with this work; if not, write to the Free Software Foundation, 171.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 171.21 + * 171.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 171.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 171.24 + * have any questions. 171.25 + * 171.26 + */ 171.27 + 171.28 +/* 171.29 + * @test 171.30 + * @bug 6778657 171.31 + * @summary Casts in SharedRuntime::f2i, f2l, d2i and d2l rely on undefined C++ behaviour 171.32 + */ 171.33 + 171.34 +public class Test { 171.35 + public static void check_f2i(int expect) { 171.36 + float check = expect; 171.37 + check *= 2; 171.38 + int actual = (int) check; 171.39 + if (actual != expect) 171.40 + throw new RuntimeException("expecting " + expect + ", got " + actual); 171.41 + } 171.42 + 171.43 + public static void check_f2l(long expect) { 171.44 + float check = expect; 171.45 + check *= 2; 171.46 + long actual = (long) check; 171.47 + if (actual != expect) 171.48 + throw new RuntimeException("expecting " + expect + ", got " + actual); 171.49 + } 171.50 + 171.51 + public static void check_d2i(int expect) { 171.52 + double check = expect; 171.53 + check *= 2; 171.54 + int actual = (int) check; 171.55 + if (actual != expect) 171.56 + throw new RuntimeException("expecting " + expect + ", got " + actual); 171.57 + } 171.58 + 171.59 + public static void check_d2l(long expect) { 171.60 + double check = expect; 171.61 + check *= 2; 171.62 + long actual = (long) check; 171.63 + if (actual != expect) 171.64 + throw new RuntimeException("expecting " + expect + ", got " + actual); 171.65 + } 171.66 + 171.67 + public static void main(String[] args) { 171.68 + check_f2i(Integer.MAX_VALUE); 171.69 + check_f2i(Integer.MIN_VALUE); 171.70 + check_f2l(Long.MAX_VALUE); 171.71 + check_f2l(Long.MIN_VALUE); 171.72 + check_d2i(Integer.MAX_VALUE); 171.73 + check_d2i(Integer.MIN_VALUE); 171.74 + check_d2l(Long.MAX_VALUE); 171.75 + check_d2l(Long.MIN_VALUE); 171.76 + } 171.77 +} 171.78 +
172.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 172.2 +++ b/test/compiler/6795161/Test.java Fri Feb 27 15:13:00 2009 -0800 172.3 @@ -0,0 +1,60 @@ 172.4 +/* 172.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 172.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 172.7 + * 172.8 + * This code is free software; you can redistribute it and/or modify it 172.9 + * under the terms of the GNU General Public License version 2 only, as 172.10 + * published by the Free Software Foundation. 172.11 + * 172.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 172.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 172.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 172.15 + * version 2 for more details (a copy is included in the LICENSE file that 172.16 + * accompanied this code). 172.17 + * 172.18 + * You should have received a copy of the GNU General Public License version 172.19 + * 2 along with this work; if not, write to the Free Software Foundation, 172.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 172.21 + * 172.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 172.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 172.24 + * have any questions. 172.25 + * 172.26 + */ 172.27 + 172.28 +/* 172.29 + * @test 172.30 + * @bug 6795161 172.31 + * @summary Escape analysis leads to data corruption 172.32 + * @run main/othervm -server -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test 172.33 + */ 172.34 + 172.35 +class Test_Class_1 { 172.36 + static String var_1; 172.37 + 172.38 + static void badFunc(int size) 172.39 + { 172.40 + try { 172.41 + for (int i = 0; i < 1; (new byte[size-i])[0] = 0, i++) {} 172.42 + } catch (Exception e) { 172.43 + // don't comment it out, it will lead to correct results ;) 172.44 + //System.out.println("Got exception: " + e); 172.45 + } 172.46 + } 172.47 +} 172.48 + 172.49 +public class Test { 172.50 + static String var_1_copy = Test_Class_1.var_1; 172.51 + 172.52 + static byte var_check; 172.53 + 172.54 + public static void main(String[] args) 172.55 + { 172.56 + var_check = 1; 172.57 + 172.58 + Test_Class_1.badFunc(-1); 172.59 + 172.60 + System.out.println("EATester.var_check = " + Test.var_check + " (expected 1)\n"); 172.61 + } 172.62 +} 172.63 +
173.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 173.2 +++ b/test/compiler/6795362/Test6795362.java Fri Feb 27 15:13:00 2009 -0800 173.3 @@ -0,0 +1,48 @@ 173.4 +/* 173.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 173.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 173.7 + * 173.8 + * This code is free software; you can redistribute it and/or modify it 173.9 + * under the terms of the GNU General Public License version 2 only, as 173.10 + * published by the Free Software Foundation. 173.11 + * 173.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 173.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 173.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 173.15 + * version 2 for more details (a copy is included in the LICENSE file that 173.16 + * accompanied this code). 173.17 + * 173.18 + * You should have received a copy of the GNU General Public License version 173.19 + * 2 along with this work; if not, write to the Free Software Foundation, 173.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 173.21 + * 173.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 173.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 173.24 + * have any questions. 173.25 + */ 173.26 + 173.27 +/** 173.28 + * @test 173.29 + * @bug 6795362 173.30 + * @summary 32bit server compiler leads to wrong results on solaris-x86 173.31 + * 173.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test6795362.sub Test6795362 173.33 + */ 173.34 + 173.35 +public class Test6795362 { 173.36 + public static void main(String[] args) 173.37 + { 173.38 + sub(); 173.39 + 173.40 + if (var_bad != 0) 173.41 + throw new InternalError(var_bad + " != 0"); 173.42 + } 173.43 + 173.44 + static long var_bad = -1L; 173.45 + 173.46 + static void sub() 173.47 + { 173.48 + var_bad >>= 65; 173.49 + var_bad /= 65; 173.50 + } 173.51 +}
174.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 174.2 +++ b/test/compiler/6799693/Test.java Fri Feb 27 15:13:00 2009 -0800 174.3 @@ -0,0 +1,47 @@ 174.4 +/* 174.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 174.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 174.7 + * 174.8 + * This code is free software; you can redistribute it and/or modify it 174.9 + * under the terms of the GNU General Public License version 2 only, as 174.10 + * published by the Free Software Foundation. 174.11 + * 174.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 174.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 174.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 174.15 + * version 2 for more details (a copy is included in the LICENSE file that 174.16 + * accompanied this code). 174.17 + * 174.18 + * You should have received a copy of the GNU General Public License version 174.19 + * 2 along with this work; if not, write to the Free Software Foundation, 174.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 174.21 + * 174.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 174.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 174.24 + * have any questions. 174.25 + * 174.26 + */ 174.27 + 174.28 +/* 174.29 + * @test 174.30 + * @bug 6799693 174.31 + * @summary Server compiler leads to data corruption when expression throws an Exception 174.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test Test 174.33 + */ 174.34 + 174.35 +public class Test { 174.36 + static int var_bad = 1; 174.37 + 174.38 + public static void main(String[] args) 174.39 + { 174.40 + var_bad++; 174.41 + 174.42 + try { 174.43 + for (int i = 0; i < 10; i++) (new byte[((byte)-1 << i)])[0] = 0; 174.44 + } 174.45 + catch (Exception e) { System.out.println("Got " + e); } 174.46 + 174.47 + System.out.println("Test.var_bad = " + var_bad + " (expected 2)\n"); 174.48 + } 174.49 +} 174.50 +
175.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 175.2 +++ b/test/compiler/6800154/Test6800154.java Fri Feb 27 15:13:00 2009 -0800 175.3 @@ -0,0 +1,109 @@ 175.4 +/* 175.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 175.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 175.7 + * 175.8 + * This code is free software; you can redistribute it and/or modify it 175.9 + * under the terms of the GNU General Public License version 2 only, as 175.10 + * published by the Free Software Foundation. 175.11 + * 175.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 175.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 175.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 175.15 + * version 2 for more details (a copy is included in the LICENSE file that 175.16 + * accompanied this code). 175.17 + * 175.18 + * You should have received a copy of the GNU General Public License version 175.19 + * 2 along with this work; if not, write to the Free Software Foundation, 175.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 175.21 + * 175.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 175.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 175.24 + * have any questions. 175.25 + */ 175.26 + 175.27 +/** 175.28 + * @test 175.29 + * @bug 6800154 175.30 + * @summary Add comments to long_by_long_mulhi() for better understandability 175.31 + * 175.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test6800154.divcomp Test6800154 175.33 + */ 175.34 + 175.35 +import java.net.URLClassLoader; 175.36 + 175.37 +public class Test6800154 implements Runnable { 175.38 + static final long[] DIVIDENDS = { 175.39 + 0, 175.40 + 1, 175.41 + 2, 175.42 + 1423487, 175.43 + 4444441, 175.44 + 4918923241323L, 175.45 + -1, 175.46 + -24351, 175.47 + 0x3333, 175.48 + 0x0000000080000000L, 175.49 + 0x7fffffffffffffffL, 175.50 + 0x8000000000000000L 175.51 + }; 175.52 + 175.53 + static final long[] DIVISORS = { 175.54 + 1, 175.55 + 2, 175.56 + 17, 175.57 + 12342, 175.58 + 24123, 175.59 + 143444, 175.60 + 123444442344L, 175.61 + -1, 175.62 + -2, 175.63 + -4423423234231423L, 175.64 + 0x0000000080000000L, 175.65 + 0x7fffffffffffffffL, 175.66 + 0x8000000000000000L 175.67 + }; 175.68 + 175.69 + // Initialize DIVISOR so that it is final in this class. 175.70 + static final long DIVISOR; 175.71 + 175.72 + static { 175.73 + long value = 0; 175.74 + try { 175.75 + value = Long.decode(System.getProperty("divisor")); 175.76 + } catch (Throwable e) { 175.77 + } 175.78 + DIVISOR = value; 175.79 + } 175.80 + 175.81 + public static void main(String[] args) throws Exception 175.82 + { 175.83 + Class cl = Class.forName("Test6800154"); 175.84 + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); 175.85 + 175.86 + // Iterate over all divisors. 175.87 + for (int i = 0; i < DIVISORS.length; i++) { 175.88 + System.setProperty("divisor", "" + DIVISORS[i]); 175.89 + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); 175.90 + Class c = loader.loadClass("Test6800154"); 175.91 + Runnable r = (Runnable) c.newInstance(); 175.92 + r.run(); 175.93 + } 175.94 + } 175.95 + 175.96 + public void run() 175.97 + { 175.98 + // Iterate over all dividends. 175.99 + for (int i = 0; i < DIVIDENDS.length; i++) { 175.100 + long dividend = DIVIDENDS[i]; 175.101 + 175.102 + long expected = divint(dividend); 175.103 + long result = divcomp(dividend); 175.104 + 175.105 + if (result != expected) 175.106 + throw new InternalError(dividend + " / " + DIVISOR + " failed: " + result + " != " + expected); 175.107 + } 175.108 + } 175.109 + 175.110 + static long divint(long a) { return a / DIVISOR; } 175.111 + static long divcomp(long a) { return a / DIVISOR; } 175.112 +}
176.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 176.2 +++ b/test/compiler/6805724/Test6805724.java Fri Feb 27 15:13:00 2009 -0800 176.3 @@ -0,0 +1,80 @@ 176.4 +/* 176.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 176.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 176.7 + * 176.8 + * This code is free software; you can redistribute it and/or modify it 176.9 + * under the terms of the GNU General Public License version 2 only, as 176.10 + * published by the Free Software Foundation. 176.11 + * 176.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 176.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 176.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 176.15 + * version 2 for more details (a copy is included in the LICENSE file that 176.16 + * accompanied this code). 176.17 + * 176.18 + * You should have received a copy of the GNU General Public License version 176.19 + * 2 along with this work; if not, write to the Free Software Foundation, 176.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 176.21 + * 176.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 176.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 176.24 + * have any questions. 176.25 + */ 176.26 + 176.27 +/** 176.28 + * @test 176.29 + * @bug 6805724 176.30 + * @summary ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant. 176.31 + * 176.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test6805724.fcomp Test6805724 176.33 + */ 176.34 + 176.35 +import java.net.URLClassLoader; 176.36 + 176.37 +public class Test6805724 implements Runnable { 176.38 + // Initialize DIVISOR so that it is final in this class. 176.39 + static final long DIVISOR; // 2^k-1 constant 176.40 + 176.41 + static { 176.42 + long value = 0; 176.43 + try { 176.44 + value = Long.decode(System.getProperty("divisor")); 176.45 + } catch (Throwable t) { 176.46 + // This one is required for the Class.forName() in main. 176.47 + } 176.48 + DIVISOR = value; 176.49 + } 176.50 + 176.51 + static long fint(long x) { 176.52 + return x % DIVISOR; 176.53 + } 176.54 + 176.55 + static long fcomp(long x) { 176.56 + return x % DIVISOR; 176.57 + } 176.58 + 176.59 + public void run() { 176.60 + long a = 0x617981E1L; 176.61 + 176.62 + long expected = fint(a); 176.63 + long result = fcomp(a); 176.64 + 176.65 + if (result != expected) 176.66 + throw new InternalError(result + " != " + expected); 176.67 + } 176.68 + 176.69 + public static void main(String args[]) throws Exception { 176.70 + Class cl = Class.forName("Test6805724"); 176.71 + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); 176.72 + 176.73 + // Iterate over all 2^k-1 divisors. 176.74 + for (int k = 1; k < Long.SIZE; k++) { 176.75 + long divisor = (1L << k) - 1; 176.76 + System.setProperty("divisor", "" + divisor); 176.77 + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); 176.78 + Class c = loader.loadClass("Test6805724"); 176.79 + Runnable r = (Runnable) c.newInstance(); 176.80 + r.run(); 176.81 + } 176.82 + } 176.83 +}