Sat, 23 Mar 2013 06:22:07 -0700
8009026: [parfait] Null pointer deference in hotspot/src/share/vm/code/nmethod.cpp
Summary: add guarantee() to nmethod constructor and checks to ensure CodeCache has space before allocation
Reviewed-by: kvn
src/share/vm/code/codeCache.hpp | file | annotate | diff | comparison | revisions | |
src/share/vm/code/nmethod.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/code/codeCache.hpp Fri Mar 22 13:35:31 2013 -0400 1.2 +++ b/src/share/vm/code/codeCache.hpp Sat Mar 23 06:22:07 2013 -0700 1.3 @@ -156,6 +156,11 @@ 1.4 static address low_bound() { return (address) _heap->low_boundary(); } 1.5 static address high_bound() { return (address) _heap->high_boundary(); } 1.6 1.7 + static bool has_space(int size) { 1.8 + // Always leave some room in the CodeCache for I2C/C2I adapters 1.9 + return largest_free_block() > (CodeCacheMinimumFreeSpace + size); 1.10 + } 1.11 + 1.12 // Profiling 1.13 static address first_address(); // first address used for CodeBlobs 1.14 static address last_address(); // last address used for CodeBlobs
2.1 --- a/src/share/vm/code/nmethod.cpp Fri Mar 22 13:35:31 2013 -0400 2.2 +++ b/src/share/vm/code/nmethod.cpp Sat Mar 23 06:22:07 2013 -0700 2.3 @@ -486,7 +486,6 @@ 2.4 #endif // def HAVE_DTRACE_H 2.5 } 2.6 2.7 - 2.8 nmethod* nmethod::new_native_nmethod(methodHandle method, 2.9 int compile_id, 2.10 CodeBuffer *code_buffer, 2.11 @@ -502,17 +501,19 @@ 2.12 { 2.13 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 2.14 int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); 2.15 - CodeOffsets offsets; 2.16 - offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); 2.17 - offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); 2.18 - nm = new (native_nmethod_size) 2.19 - nmethod(method(), native_nmethod_size, compile_id, &offsets, 2.20 - code_buffer, frame_size, 2.21 - basic_lock_owner_sp_offset, basic_lock_sp_offset, 2.22 - oop_maps); 2.23 - NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); 2.24 - if (PrintAssembly && nm != NULL) 2.25 - Disassembler::decode(nm); 2.26 + if (CodeCache::has_space(native_nmethod_size)) { 2.27 + CodeOffsets offsets; 2.28 + offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); 2.29 + offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); 2.30 + nm = new (native_nmethod_size) nmethod(method(), native_nmethod_size, 2.31 + compile_id, &offsets, 2.32 + code_buffer, frame_size, 2.33 + basic_lock_owner_sp_offset, 2.34 + basic_lock_sp_offset, oop_maps); 2.35 + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); 2.36 + if (PrintAssembly && nm != NULL) 2.37 + Disassembler::decode(nm); 2.38 + } 2.39 } 2.40 // verify nmethod 2.41 debug_only(if (nm) nm->verify();) // might block 2.42 @@ -537,16 +538,19 @@ 2.43 { 2.44 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 2.45 int nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); 2.46 - CodeOffsets offsets; 2.47 - offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); 2.48 - offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset); 2.49 - offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); 2.50 + if (CodeCache::has_space(nmethod_size)) { 2.51 + CodeOffsets offsets; 2.52 + offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); 2.53 + offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset); 2.54 + offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); 2.55 2.56 - nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size); 2.57 + nm = new (nmethod_size) nmethod(method(), nmethod_size, 2.58 + &offsets, code_buffer, frame_size); 2.59 2.60 - NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); 2.61 - if (PrintAssembly && nm != NULL) 2.62 - Disassembler::decode(nm); 2.63 + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); 2.64 + if (PrintAssembly && nm != NULL) 2.65 + Disassembler::decode(nm); 2.66 + } 2.67 } 2.68 // verify nmethod 2.69 debug_only(if (nm) nm->verify();) // might block 2.70 @@ -587,7 +591,8 @@ 2.71 + round_to(handler_table->size_in_bytes(), oopSize) 2.72 + round_to(nul_chk_table->size_in_bytes(), oopSize) 2.73 + round_to(debug_info->data_size() , oopSize); 2.74 - nm = new (nmethod_size) 2.75 + if (CodeCache::has_space(nmethod_size)) { 2.76 + nm = new (nmethod_size) 2.77 nmethod(method(), nmethod_size, compile_id, entry_bci, offsets, 2.78 orig_pc_offset, debug_info, dependencies, code_buffer, frame_size, 2.79 oop_maps, 2.80 @@ -595,6 +600,7 @@ 2.81 nul_chk_table, 2.82 compiler, 2.83 comp_level); 2.84 + } 2.85 if (nm != NULL) { 2.86 // To make dependency checking during class loading fast, record 2.87 // the nmethod dependencies in the classes it is dependent on. 2.88 @@ -793,9 +799,9 @@ 2.89 #endif // def HAVE_DTRACE_H 2.90 2.91 void* nmethod::operator new(size_t size, int nmethod_size) { 2.92 - // Always leave some room in the CodeCache for I2C/C2I adapters 2.93 - if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) return NULL; 2.94 - return CodeCache::allocate(nmethod_size); 2.95 + void* alloc = CodeCache::allocate(nmethod_size); 2.96 + guarantee(alloc != NULL, "CodeCache should have enough space"); 2.97 + return alloc; 2.98 } 2.99 2.100