JDK-5051064 : Error: assert(pc_desc != 0,"Must be able to find matching PcDesc")
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_9
  • CPU: sparc
  • Submitted: 2004-05-21
  • Updated: 2004-06-15
  • Resolved: 2004-06-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b56Fixed
Related Reports
Relates :  
Description
While running my testcase for 5050705 after applying a fix for that bug
the vm failed with this assert. Looking at the traceback where this
happens this seems likley to cause a segv in product mode.

To reproduce run the testcase for 5050705.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-rc FIXED IN: tiger-rc INTEGRATED IN: tiger-b56 tiger-rc
08-07-2004

SUGGESTED FIX *** 1,12 **** --- 1,12 ---- #ifdef USE_PRAGMA_IDENT_HDR - #pragma ident "@(#)thread.hpp 1.415 04/04/19 15:16:35 JVM" + #pragma ident "@(#)thread.hpp 1.416 04/06/08 13:02:43 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ class ThreadSafepointState; class ThreadProfiler; class JvmtiThreadState; *** 766,785 **** --- 766,786 ---- void set_pc_not_at_call_for_frame(intptr_t* id) { _anchor.set_pc_not_at_call_for_frame(id); } bool not_at_call_frame_exists() const { return _anchor.not_at_call_frame_exists(); } intptr_t* not_at_call_id() const { return _anchor.not_at_call_id(); } // Safepoint support JavaThreadState thread_state() const { return _thread_state; } void set_thread_state(JavaThreadState s) { _thread_state=s; } ThreadSafepointState *safepoint_state() const { return _safepoint_state; } void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; } bool is_in_compiled_safepoint() { return _safepoint_state->type() == ThreadSafepointState::_compiled_safepoint; } + bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); } // thread has called JavaThread::exit() or is terminated bool is_exiting() { return _terminated == _thread_exiting || is_terminated(); } // thread is terminated (no longer on the threads list); we compare // against the two non-terminated values so that a freed JavaThread // will also be considered terminated. bool is_terminated() { return _terminated != _not_terminated && _terminated != _thread_exiting; } void set_terminated(TerminatedTypes t) { _terminated = t; } // special for Threads::remove() which is static: void set_terminated_value() { _terminated = _thread_terminated; } void block_if_vm_exited(); #ifdef USE_PRAGMA_IDENT_SRC - #pragma ident "@(#)thread.cpp 1.731 04/04/19 15:16:34 JVM" + #pragma ident "@(#)thread.cpp 1.732 04/06/08 13:02:41 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ # include "incls/_precompiled.incl" # include "incls/_thread.cpp.incl" // Class hierarchy *** 1596,1634 **** --- 1596,1639 ---- guarantee(monitor_chunks() != NULL, "must be non empty"); if (monitor_chunks() == chunk) { set_monitor_chunks(chunk->next()); } else { MonitorChunk* prev = monitor_chunks(); while (prev->next() != chunk) prev = prev->next(); prev->set_next(chunk->next()); } } // JVM support. // Note: this function shouldn't block if it's called in // _thread_in_native_trans state (such as from // check_safepoint_and_suspend_for_native_trans()). void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) { #ifndef CORE if (has_last_Java_frame() && has_async_condition()) { - frame f = last_frame(); - // We'd like to use is_in_compiled_safepoint() but SafepointPolling - // doesn't set the state properly so we can't use it at the moment. - if (f.is_safepoint_blob_frame()) { + // If we are at a polling page safepoint (not a poll return) + // then we must defer async exception because live registers + // will be clobbered by the exception path. Poll return is + // ok because the call we a returning from already collides + // with exception handling registers and so there is no issue. + // (The exception handling path kills call result registers but + // this is ok since the exception kills the result anyway). + + if (is_at_poll_safepoint() || + (!SafepointPolling && last_frame().is_safepoint_blob_frame())) { // if the code we are returning to has deoptimized we must defer // the exception otherwise live registers get clobbered on the // exception path before deoptimization is able to retrieve them. RegisterMap map(this, false); - frame caller_fr = f.sender(&map); + frame caller_fr = last_frame().sender(&map); CodeBlob *cb = CodeCache::find_blob(caller_fr.pc()); if (cb != NULL && cb->is_nmethod() && ((nmethod*)cb)->is_patched_for_deopt()) { if (TraceExceptions) { ResourceMark rm; tty->print_cr("deferred async exception at compiled safepoint"); } return; } } } *** 1649,1670 **** --- 1654,1680 ---- // Check for pending async. exception if (_pending_async_exception != NULL) { // Only overwrite an already pending exception, if it is not a threadDeath. if (!has_pending_exception() || !pending_exception()->is_a(SystemDictionary::threaddeath_klass())) { // We cannot call Exceptions::_throw(...) here because we cannot block set_pending_exception(_pending_async_exception, __FILE__, __LINE__); if (TraceExceptions) { ResourceMark rm; - tty->print_cr("Async. exception installed at runtime exit of type: %s", instanceKlass::cast(_pending_async_exception->klass())->external_name()); + tty->print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", this); + if (has_last_Java_frame() ) { + frame f = last_frame(); + tty->print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", f.pc(), f.sp()); } + tty->print_cr(" of type: %s", instanceKlass::cast(_pending_async_exception->klass())->external_name()); + } _pending_async_exception = NULL; clear_has_async_exception_with_lock(); } } if (check_unsafe_error && condition == _async_unsafe_access_error && !has_pending_exception()) { condition = _no_async_condition; // done switch (thread_state()) { case _thread_in_vm: - #pragma ident "@(#)safepoint.hpp 1.87 04/04/19 18:42:30 JVM" + #pragma ident "@(#)safepoint.hpp 1.88 04/06/08 13:02:41 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ // // Safepoint synchronization //// // The VMThread or CMS_thread uses the SafepointSynchronize::begin/end *** 153,172 **** --- 153,173 ---- // State class for a thread suspended at a safepoint class ThreadSafepointState: public CHeapObj { public: enum suspend_type { _running = 0, // Thread state not yet determined (i.e., not at a safepoint yet) _at_safepoint = 1, // Thread at a safepoint (f.ex., when blocked on a lock) _call_back = 2, // Keep executing and wait for callback (if thread is in interpreter or vm) _compiled_safepoint = 3 // Compiled safepoint }; private: + volatile bool _at_poll_safepoint; // At polling page safepoint (NOT a poll return safepoint) volatile suspend_type _type; JavaThread * _thread; // use an ExtendedPC to be sure we have real containment -- on SPARC the pc // might be at the delay slot of a branch so we don't contain the PC, but we do // contain the nPC ExtendedPC _addr; SafepointHandler* _handle; // Used when _type == _safepoint_handler // Thead local code buffer NOT_CORE(ThreadCodeBuffer* _code_buffer;) *** 191,210 **** --- 192,214 ---- bool caller_must_gc_arguments() const; #ifndef CORE // Local code-cache management ThreadCodeBuffer* allocate_code_buffer(int size_in_bytes, nmethod *code, address real_pc); void enable_code_buffer() { _code_buffer_is_enabled = true; } void disable_code_buffer(){ _code_buffer_is_enabled = false; } void destroy_code_buffer(); ThreadCodeBuffer* code_buffer() { return _code_buffer_is_enabled ? _code_buffer : NULL; } void notify_set_thread_pc_result(bool success); + bool is_at_poll_safepoint() { return _at_poll_safepoint; } + void set_at_poll_safepoint(bool val) { _at_poll_safepoint = val; } + // adjustment of pc if it points into a thread local codebuffer (might block) inline address compute_adjusted_pc(address pc); // the inverse adjustment of pc, if it can be redirected into the codebuffer: inline address maybe_capture_pc(address pc); #endif // debugging void print(); JavaThreadState _stop_state; // Usefull for debugging a deadlock (to be taken out) --- 1,12 ---- #ifdef USE_PRAGMA_IDENT_SRC - #pragma ident "@(#)safepoint.cpp 1.271 04/04/20 19:40:12 JVM" + #pragma ident "@(#)safepoint.cpp 1.272 04/06/08 13:02:40 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ # include "incls/_precompiled.incl" # include "incls/_safepoint.cpp.incl" // -------------------------------------------------------------------------------------------------- *** 471,493 **** --- 471,501 ---- break; default: fatal1("Illegal threadstate encountered: %d", state); } // Check for pending. async. exceptions or suspends - except if the // thread was blocked inside the VM. has_special_runtime_exit_condition() // is called last since it grabs a lock and we only want to do that when // we must. - if (state != _thread_blocked_trans && state != _thread_in_vm_trans && + // + // Note: we never deliver an async exception at a polling point as the + // compiler may not have an exception handler for it. The polling + // code will notice the async and deoptimize and the exception will + // be delivered. (Polling at a return point is ok though). Sure is + // a lot of bother for a deprecated feature... + + if (state != _thread_blocked_trans && + state != _thread_in_vm_trans && thread->has_special_runtime_exit_condition()) { ! thread->handle_special_runtime_exit_condition(!thread->is_at_poll_safepoint()); } } // ------------------------------------------------------------------------------------------------------ // Exception handlers #ifndef PRODUCT #ifdef _LP64 #define PTR_PAD "" #else *** 602,621 **** --- 610,630 ---- return result; } // ------------------------------------------------------------------------------------------------------- // Implementation of ThreadSafepointState ThreadSafepointState::ThreadSafepointState(JavaThread *thread) { _thread = thread; _type = _running; + _at_poll_safepoint = false; NOT_CORE(_handle = new CompiledCodeSafepointHandler(thread);) NOT_CORE(_code_buffer = NULL;) } ThreadSafepointState::~ThreadSafepointState() { #ifndef CORE assert(_handle != NULL, "must be created"); delete _handle; _handle = NULL; assert(_code_buffer == NULL, "should already been removed"); *** 1410,1449 **** --- 1419,1468 ---- caller_fr.set_saved_oop_result(&map, return_value()); } } // This is a safepoint poll. Mark it as not at a call, and patch the // return address. else { // Mark this as not at a call thread()->set_pc_not_at_call_for_frame(caller_fr.id()); + thread()->safepoint_state()->set_at_poll_safepoint(true); // patch the return address caller_fr.patch_pc(thread(), real_return_addr); // Block the thread SafepointSynchronize::block(thread()); + thread()->safepoint_state()->set_at_poll_safepoint(false); + + // If we have a pending async exception deoptimize the frame + // as otherwise we may never deliver it. + if (thread()->has_async_condition()) { + ThreadInVMfromJavaNoAsyncException __tiv(thread()); + VM_DeoptimizeFrame deopt(thread(), caller_fr.id()); + VMThread::execute(&deopt); } // If an exception has been installed we must check for a pending deoptimization // Deoptimize frame if exception has been thrown. if (thread()->has_pending_exception() && nm->is_patched_for_deopt()) { // The exception patch will destroy registers that are still // live and will be needed during deoptimization. Defer the // Async exception should have defered the exception until the // next safepoint which will be detected when we get into // the interpreter so if we have an exception now things // are messed up. fatal("Exception installed and deoptimization is pending"); } + } return NULL; } void CompiledCodeSafepointHandler::print() { ResourceMark rm; tty->print_cr("%s: %s", name(), _nm->method()->name_and_sig_as_C_string()); }
08-07-2004

EVALUATION This is our old friend at_call/not_at_call. In this case an async exception was installed at a safepoint poll. These are stored not_at_call and the lookup of the scopedesc was at_call so we failed. The last SafepointPolling bug? :-) ###@###.### 2004-05-21
21-05-2004