# HG changeset patch # User kvn # Date 1229044810 28800 # Node ID 7b75310e57e2f9188cfe9a4f46bb702b8e3e90bb # Parent 3ad2b8576c4a8c189eee1994e35a72ac792883b7# Parent 284d0af00d53cbb37480e8400eff71bdca3c7d0c Merge diff -r 284d0af00d53 -r 7b75310e57e2 .hgtags --- a/.hgtags Tue Dec 09 12:41:26 2008 -0800 +++ b/.hgtags Thu Dec 11 17:20:10 2008 -0800 @@ -15,3 +15,4 @@ d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38 49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39 81a0cbe3b28460ce836109934ece03db7afaf9cc jdk7-b40 +f9d938ede1960d18cb7cf23c645b026519c1a678 jdk7-b41 diff -r 284d0af00d53 -r 7b75310e57e2 make/hotspot_version --- a/make/hotspot_version Tue Dec 09 12:41:26 2008 -0800 +++ b/make/hotspot_version Thu Dec 11 17:20:10 2008 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=14 HS_MINOR_VER=0 -HS_BUILD_NUMBER=08 +HS_BUILD_NUMBER=09 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff -r 284d0af00d53 -r 7b75310e57e2 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os/linux/vm/os_linux.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -2272,7 +2272,9 @@ uncommit_memory(addr, bytes); } -void os::numa_make_global(char *addr, size_t bytes) { } +void os::numa_make_global(char *addr, size_t bytes) { + Linux::numa_interleave_memory(addr, bytes); +} void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { Linux::numa_tonode_memory(addr, bytes, lgrp_hint); @@ -2314,7 +2316,7 @@ extern "C" void numa_warn(int number, char *where, ...) { } extern "C" void numa_error(char *where) { } -void os::Linux::libnuma_init() { +bool os::Linux::libnuma_init() { // sched_getcpu() should be in libc. set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, dlsym(RTLD_DEFAULT, "sched_getcpu"))); @@ -2330,31 +2332,51 @@ dlsym(handle, "numa_available"))); set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t, dlsym(handle, "numa_tonode_memory"))); + set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t, + dlsym(handle, "numa_interleave_memory"))); + + if (numa_available() != -1) { + set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes")); // Create a cpu -> node mapping _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray(0, true); rebuild_cpu_to_node_map(); + return true; } } } + return false; } // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id. // The table is later used in get_node_by_cpu(). void os::Linux::rebuild_cpu_to_node_map() { - int cpu_num = os::active_processor_count(); + const size_t NCPUS = 32768; // Since the buffer size computation is very obscure + // in libnuma (possible values are starting from 16, + // and continuing up with every other power of 2, but less + // than the maximum number of CPUs supported by kernel), and + // is a subject to change (in libnuma version 2 the requirements + // are more reasonable) we'll just hardcode the number they use + // in the library. + const size_t BitsPerCLong = sizeof(long) * CHAR_BIT; + + size_t cpu_num = os::active_processor_count(); + size_t cpu_map_size = NCPUS / BitsPerCLong; + size_t cpu_map_valid_size = + MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size); + cpu_to_node()->clear(); cpu_to_node()->at_grow(cpu_num - 1); - int node_num = numa_get_groups_num(); - int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong; + size_t node_num = numa_get_groups_num(); + unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size); - for (int i = 0; i < node_num; i++) { + for (size_t i = 0; i < node_num; i++) { if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) { - for (int j = 0; j < cpu_map_size; j++) { + for (size_t j = 0; j < cpu_map_valid_size; j++) { if (cpu_map[j] != 0) { - for (int k = 0; k < BitsPerLong; k++) { + for (size_t k = 0; k < BitsPerCLong; k++) { if (cpu_map[j] & (1UL << k)) { - cpu_to_node()->at_put(j * BitsPerLong + k, i); + cpu_to_node()->at_put(j * BitsPerCLong + k, i); } } } @@ -2377,7 +2399,8 @@ os::Linux::numa_max_node_func_t os::Linux::_numa_max_node; os::Linux::numa_available_func_t os::Linux::_numa_available; os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory; - +os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory; +unsigned long* os::Linux::_numa_all_nodes; bool os::uncommit_memory(char* addr, size_t size) { return ::mmap(addr, size, @@ -3695,7 +3718,17 @@ } if (UseNUMA) { - Linux::libnuma_init(); + if (!Linux::libnuma_init()) { + UseNUMA = false; + } else { + if ((Linux::numa_max_node() < 1)) { + // There's only one node(they start from 0), disable NUMA. + UseNUMA = false; + } + } + if (!UseNUMA && ForceNUMA) { + UseNUMA = true; + } } if (MaxFDLimit) { diff -r 284d0af00d53 -r 7b75310e57e2 src/os/linux/vm/os_linux.hpp --- a/src/os/linux/vm/os_linux.hpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os/linux/vm/os_linux.hpp Thu Dec 11 17:20:10 2008 -0800 @@ -146,7 +146,7 @@ static bool is_floating_stack() { return _is_floating_stack; } static void libpthread_init(); - static void libnuma_init(); + static bool libnuma_init(); // Minimum stack size a thread can be created with (allowing // the VM to completely create the thread and enter user code) @@ -240,20 +240,23 @@ typedef int (*numa_max_node_func_t)(void); typedef int (*numa_available_func_t)(void); typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); - + typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); static sched_getcpu_func_t _sched_getcpu; static numa_node_to_cpus_func_t _numa_node_to_cpus; static numa_max_node_func_t _numa_max_node; static numa_available_func_t _numa_available; static numa_tonode_memory_func_t _numa_tonode_memory; + static numa_interleave_memory_func_t _numa_interleave_memory; + static unsigned long* _numa_all_nodes; static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } static void set_numa_available(numa_available_func_t func) { _numa_available = func; } static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } - + static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } + static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } public: static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { @@ -264,6 +267,11 @@ static int numa_tonode_memory(void *start, size_t size, int node) { return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; } + static void numa_interleave_memory(void *start, size_t size) { + if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) { + _numa_interleave_memory(start, size, _numa_all_nodes); + } + } static int get_node_by_cpu(int cpu_id); }; diff -r 284d0af00d53 -r 7b75310e57e2 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -4638,7 +4638,7 @@ } } -void os::Solaris::liblgrp_init() { +bool os::Solaris::liblgrp_init() { void *handle = dlopen("liblgrp.so.1", RTLD_LAZY); if (handle != NULL) { os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home"))); @@ -4653,9 +4653,9 @@ lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER); set_lgrp_cookie(c); - } else { - warning("your OS does not support NUMA"); - } + return true; + } + return false; } void os::Solaris::misc_sym_init() { @@ -4824,9 +4824,25 @@ vm_page_size())); Solaris::libthread_init(); + if (UseNUMA) { - Solaris::liblgrp_init(); - } + if (!Solaris::liblgrp_init()) { + UseNUMA = false; + } else { + size_t lgrp_limit = os::numa_get_groups_num(); + int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit); + size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit); + FREE_C_HEAP_ARRAY(int, lgrp_ids); + if (lgrp_num < 2) { + // There's only one locality group, disable NUMA. + UseNUMA = false; + } + } + if (!UseNUMA && ForceNUMA) { + UseNUMA = true; + } + } + Solaris::misc_sym_init(); Solaris::signal_sets_init(); Solaris::init_signal_mem(); diff -r 284d0af00d53 -r 7b75310e57e2 src/os/solaris/vm/os_solaris.hpp --- a/src/os/solaris/vm/os_solaris.hpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os/solaris/vm/os_solaris.hpp Thu Dec 11 17:20:10 2008 -0800 @@ -176,7 +176,7 @@ public: static void libthread_init(); static void synchronization_init(); - static void liblgrp_init(); + static bool liblgrp_init(); // Load miscellaneous symbols. static void misc_sym_init(); // This boolean allows users to forward their own non-matching signals diff -r 284d0af00d53 -r 7b75310e57e2 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os/windows/vm/os_windows.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -2217,15 +2217,10 @@ // We only expect null pointers in the stubs (vtable) // the rest are checked explicitly now. // - CodeBlob* cb = CodeCache::find_blob(pc); - if (cb != NULL) { - if (VtableStubs::stub_containing(pc) != NULL) { - if (((uintptr_t)addr) < os::vm_page_size() ) { - // an access to the first page of VM--assume it is a null pointer - return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL)); - } - } + if (((uintptr_t)addr) < os::vm_page_size() ) { + // an access to the first page of VM--assume it is a null pointer + address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + if (stub != NULL) return Handle_Exception(exceptionInfo, stub); } } } // in_java @@ -2241,9 +2236,8 @@ // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || !os::win32::is_nt()) { - - return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL)); + address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + if (stub != NULL) return Handle_Exception(exceptionInfo, stub); } report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); @@ -3353,6 +3347,10 @@ // initialize thread priority policy prio_init(); + if (UseNUMA && !ForceNUMA) { + UseNUMA = false; // Currently unsupported. + } + return JNI_OK; } diff -r 284d0af00d53 -r 7b75310e57e2 src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -203,10 +203,10 @@ return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); } -extern "C" intptr_t *_get_previous_fp(); // in .il file. +extern "C" intptr_t *_get_current_fp(); // in .il file frame os::current_frame() { - intptr_t* fp = _get_previous_fp(); + intptr_t* fp = _get_current_fp(); // it's inlined so want current fp frame myframe((intptr_t*)os::current_stack_pointer(), (intptr_t*)fp, CAST_FROM_FN_PTR(address, os::current_frame)); diff -r 284d0af00d53 -r 7b75310e57e2 src/os_cpu/solaris_x86/vm/solaris_x86_32.il --- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Thu Dec 11 17:20:10 2008 -0800 @@ -37,10 +37,10 @@ movl %gs:0, %eax .end - // Get callers fp - .inline _get_previous_fp,0 + // Get current fp + .inline _get_current_fp,0 + .volatile movl %ebp, %eax - movl %eax, %eax .end // Support for jint Atomic::add(jint inc, volatile jint* dest) diff -r 284d0af00d53 -r 7b75310e57e2 src/os_cpu/solaris_x86/vm/solaris_x86_64.il --- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Tue Dec 09 12:41:26 2008 -0800 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.il Thu Dec 11 17:20:10 2008 -0800 @@ -30,10 +30,10 @@ movq %fs:0, %rax .end - // Get the frame pointer from previous frame. - .inline _get_previous_fp,0 + // Get the frame pointer from current frame. + .inline _get_current_fp,0 + .volatile movq %rbp, %rax - movq %rax, %rax .end // Support for jint Atomic::add(jint add_value, volatile jint* dest) diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -414,9 +414,20 @@ if (limit > 0) { limit = round_down(limit, page_size()); if (chunk_size > current_chunk_size(i)) { - chunk_size = MIN2((off_t)chunk_size, (off_t)current_chunk_size(i) + (off_t)limit); + size_t upper_bound = pages_available * page_size(); + if (upper_bound > limit && + current_chunk_size(i) < upper_bound - limit) { + // The resulting upper bound should not exceed the available + // amount of memory (pages_available * page_size()). + upper_bound = current_chunk_size(i) + limit; + } + chunk_size = MIN2(chunk_size, upper_bound); } else { - chunk_size = MAX2((off_t)chunk_size, (off_t)current_chunk_size(i) - (off_t)limit); + size_t lower_bound = page_size(); + if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow. + lower_bound = current_chunk_size(i) - limit; + } + chunk_size = MAX2(chunk_size, lower_bound); } } assert(chunk_size <= pages_available * page_size(), "Chunk size out of range"); diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/includeDB_core Thu Dec 11 17:20:10 2008 -0800 @@ -2303,6 +2303,7 @@ javaCalls.cpp interfaceSupport.hpp javaCalls.cpp interpreter.hpp javaCalls.cpp javaCalls.hpp +javaCalls.cpp jniCheck.hpp javaCalls.cpp linkResolver.hpp javaCalls.cpp mutexLocker.hpp javaCalls.cpp nmethod.hpp diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/includeDB_features --- a/src/share/vm/includeDB_features Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/includeDB_features Thu Dec 11 17:20:10 2008 -0800 @@ -115,6 +115,8 @@ heapInspection.cpp os.hpp heapInspection.cpp resourceArea.hpp +javaCalls.cpp jniCheck.hpp + jniCheck.cpp fieldDescriptor.hpp jniCheck.cpp handles.hpp jniCheck.cpp instanceKlass.hpp diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/prims/jniCheck.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -112,18 +112,6 @@ static const char * fatal_non_string = "JNI string operation received a non-string"; - -// Report a JNI failure caught by -Xcheck:jni. Perform a core dump. -// Note: two variations -- one to be called when in VM state (e.g. when -// within IN_VM macro), one to be called when in NATIVE state. - -// When in VM state: -static void ReportJNIFatalError(JavaThread* thr, const char *msg) { - tty->print_cr("FATAL ERROR in native method: %s", msg); - thr->print_stack(); - os::abort(true); -} - // When in VM state: static void ReportJNIWarning(JavaThread* thr, const char *msg) { tty->print_cr("WARNING in native method: %s", msg); diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/prims/jniCheck.hpp --- a/src/share/vm/prims/jniCheck.hpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/prims/jniCheck.hpp Thu Dec 11 17:20:10 2008 -0800 @@ -22,6 +22,19 @@ * */ +extern "C" { + // Report a JNI failure caught by -Xcheck:jni. Perform a core dump. + // Note: two variations -- one to be called when in VM state (e.g. when + // within IN_VM macro), one to be called when in NATIVE state. + + // When in VM state: + static void ReportJNIFatalError(JavaThread* thr, const char *msg) { + tty->print_cr("FATAL ERROR in native method: %s", msg); + thr->print_stack(); + os::abort(true); + } +} + // // Checked JNI routines that are useful for outside of checked JNI // diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/runtime/globals.hpp Thu Dec 11 17:20:10 2008 -0800 @@ -342,6 +342,9 @@ product(bool, UseNUMA, false, \ "Use NUMA if available") \ \ + product(bool, ForceNUMA, false, \ + "Force NUMA optimizations on single-node/UMA systems") \ + \ product(intx, NUMAChunkResizeWeight, 20, \ "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying average for " \ diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/runtime/javaCalls.cpp --- a/src/share/vm/runtime/javaCalls.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/runtime/javaCalls.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -309,8 +309,12 @@ CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();) - // Make sure that the arguments have the right type - debug_only(args->verify(method, result->get_type(), thread)); + // Verify the arguments + + if (CheckJNICalls) { + args->verify(method, result->get_type(), thread); + } + else debug_only(args->verify(method, result->get_type(), thread)); // Ignore call if method is empty if (method->is_empty_method()) { @@ -431,24 +435,26 @@ return TaggedStackInterpreter ? _parameters : _value; } -//-------------------------------------------------------------------------------------- -// Non-Product code -#ifndef PRODUCT class SignatureChekker : public SignatureIterator { private: bool *_is_oop; int _pos; BasicType _return_type; + intptr_t* _value; + Thread* _thread; public: bool _is_return; - SignatureChekker(symbolHandle signature, BasicType return_type, bool is_static, bool* is_oop) : SignatureIterator(signature) { + SignatureChekker(symbolHandle signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) { _is_oop = is_oop; _is_return = false; _return_type = return_type; _pos = 0; + _value = value; + _thread = thread; + if (!is_static) { check_value(true); // Receiver must be an oop } @@ -489,6 +495,24 @@ check_return_type(t); return; } + + // verify handle and the oop pointed to by handle + int p = _pos; + bool bad = false; + // If argument is oop + if (_is_oop[p]) { + intptr_t v = _value[p]; + if (v != 0 ) { + size_t t = (size_t)v; + bad = (t < (size_t)os::vm_page_size() ) || !(*(oop*)v)->is_oop_or_null(true); + if (CheckJNICalls && bad) { + ReportJNIFatalError((JavaThread*)_thread, "Bad JNI oop argument"); + } + } + // for the regular debug case. + assert(!bad, "Bad JNI oop argument"); + } + check_value(true); } @@ -505,6 +529,7 @@ void do_array(int begin, int end) { check_obj(T_OBJECT); } }; + void JavaCallArguments::verify(methodHandle method, BasicType return_type, Thread *thread) { guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed"); @@ -515,10 +540,9 @@ // Check that oop information is correct symbolHandle signature (thread, method->signature()); - SignatureChekker sc(signature, return_type, method->is_static(),_is_oop); + SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread); sc.iterate_parameters(); sc.check_doing_return(true); sc.iterate_returntype(); } -#endif // PRODUCT diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/runtime/javaCalls.hpp --- a/src/share/vm/runtime/javaCalls.hpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/runtime/javaCalls.hpp Thu Dec 11 17:20:10 2008 -0800 @@ -150,7 +150,7 @@ int size_of_parameters() const { return _size; } // Verify that pushed arguments fits a given method - void verify(methodHandle method, BasicType return_type, Thread *thread) PRODUCT_RETURN; + void verify(methodHandle method, BasicType return_type, Thread *thread); }; // All calls to Java have to go via JavaCalls. Sets up the stack frame diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -556,7 +556,10 @@ // the caller was at a call site, it's safe to destroy all // caller-saved registers, as these entry points do. VtableStub* vt_stub = VtableStubs::stub_containing(pc); - guarantee(vt_stub != NULL, "unable to find SEGVing vtable stub"); + + // If vt_stub is NULL, then return NULL to signal handler to report the SEGV error. + if (vt_stub == NULL) return NULL; + if (vt_stub->is_abstract_method_error(pc)) { assert(!vt_stub->is_vtable_stub(), "should never see AbstractMethodErrors from vtable-type VtableStubs"); return StubRoutines::throw_AbstractMethodError_entry(); @@ -565,7 +568,9 @@ } } else { CodeBlob* cb = CodeCache::find_blob(pc); - guarantee(cb != NULL, "exception happened outside interpreter, nmethods and vtable stubs (1)"); + + // If code blob is NULL, then return NULL to signal handler to report the SEGV error. + if (cb == NULL) return NULL; // Exception happened in CodeCache. Must be either: // 1. Inline-cache check in C2I handler blob, @@ -574,7 +579,7 @@ if (!cb->is_nmethod()) { guarantee(cb->is_adapter_blob(), - "exception happened outside interpreter, nmethods and vtable stubs (2)"); + "exception happened outside interpreter, nmethods and vtable stubs (1)"); // There is no handler here, so we will simply unwind. return StubRoutines::throw_NullPointerException_at_call_entry(); } diff -r 284d0af00d53 -r 7b75310e57e2 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Tue Dec 09 12:41:26 2008 -0800 +++ b/src/share/vm/utilities/vmError.cpp Thu Dec 11 17:20:10 2008 -0800 @@ -332,6 +332,8 @@ // VM version st->print_cr("#"); + JDK_Version::current().to_string(buf, sizeof(buf)); + st->print_cr("# JRE version: %s", buf); st->print_cr("# Java VM: %s (%s %s %s %s)", Abstract_VM_Version::vm_name(), Abstract_VM_Version::vm_release(),