src/share/vm/utilities/exceptions.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 435
a61af66fc99e
child 1446
fcb148c6b605
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

     1 /*
     2  * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 #include "incls/_precompiled.incl"
    26 #include "incls/_exceptions.cpp.incl"
    29 // Implementation of ThreadShadow
    30 void check_ThreadShadow() {
    31   const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception);
    32   const ByteSize offset2 = Thread::pending_exception_offset();
    33   if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly");
    34 }
    37 void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) {
    38   assert(exception != NULL && exception->is_oop(), "invalid exception oop");
    39   _pending_exception = exception;
    40   _exception_file    = file;
    41   _exception_line    = line;
    42 }
    44 void ThreadShadow::clear_pending_exception() {
    45   if (TraceClearedExceptions) {
    46     if (_pending_exception != NULL) {
    47       tty->print_cr("Thread::clear_pending_exception: cleared exception:");
    48       _pending_exception->print();
    49     }
    50   }
    51   _pending_exception = NULL;
    52   _exception_file    = NULL;
    53   _exception_line    = 0;
    54 }
    55 // Implementation of Exceptions
    57 bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) {
    58   // bootstrapping check
    59   if (!Universe::is_fully_initialized()) {
    60    vm_exit_during_initialization(h_exception);
    61    ShouldNotReachHere();
    62   }
    64   if (thread->is_VM_thread()
    65       || thread->is_Compiler_thread() ) {
    66     // We do not care what kind of exception we get for the vm-thread or a thread which
    67     // is compiling.  We just install a dummy exception object
    68     thread->set_pending_exception(Universe::vm_exception(), file, line);
    69     return true;
    70   }
    72   return false;
    73 }
    75 bool Exceptions::special_exception(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message) {
    76   // bootstrapping check
    77   if (!Universe::is_fully_initialized()) {
    78     if (h_name.is_null()) {
    79       // atleast an informative message.
    80       vm_exit_during_initialization("Exception", message);
    81     } else {
    82       vm_exit_during_initialization(h_name, message);
    83     }
    84     ShouldNotReachHere();
    85   }
    87   if (thread->is_VM_thread()
    88       || thread->is_Compiler_thread() ) {
    89     // We do not care what kind of exception we get for the vm-thread or a thread which
    90     // is compiling.  We just install a dummy exception object
    91     thread->set_pending_exception(Universe::vm_exception(), file, line);
    92     return true;
    93   }
    95   return false;
    96 }
    98 // This method should only be called from generated code,
    99 // therefore the exception oop should be in the oopmap.
   100 void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) {
   101   assert(exception != NULL, "exception should not be NULL");
   102   Handle h_exception = Handle(thread, exception);
   103   _throw(thread, file, line, h_exception);
   104 }
   106 void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception) {
   107   assert(h_exception() != NULL, "exception should not be NULL");
   109   // tracing (do this up front - so it works during boot strapping)
   110   if (TraceExceptions) {
   111     ttyLocker ttyl;
   112     ResourceMark rm;
   113     tty->print_cr("Exception <%s> (" INTPTR_FORMAT " ) \nthrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
   114                       h_exception->print_value_string(), (address)h_exception(), file, line, thread);
   115   }
   116   // for AbortVMOnException flag
   117   NOT_PRODUCT(Exceptions::debug_check_abort(h_exception));
   119   // Check for special boot-strapping/vm-thread handling
   120   if (special_exception(thread, file, line, h_exception)) return;
   122   assert(h_exception->is_a(SystemDictionary::throwable_klass()), "exception is not a subclass of java/lang/Throwable");
   124   // set the pending exception
   125   thread->set_pending_exception(h_exception(), file, line);
   127   // vm log
   128   Events::log("throw_exception " INTPTR_FORMAT, (address)h_exception());
   129 }
   132 void Exceptions::_throw_msg(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_loader, Handle h_protection_domain) {
   133   // Check for special boot-strapping/vm-thread handling
   134   if (special_exception(thread, file, line, h_name, message)) return;
   135   // Create and throw exception
   136   Handle h_cause(thread, NULL);
   137   Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
   138   _throw(thread, file, line, h_exception);
   139 }
   141 // Throw an exception with a message and a cause
   142 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_cause, Handle h_loader, Handle h_protection_domain) {
   143   // Check for special boot-strapping/vm-thread handling
   144   if (special_exception(thread, file, line, h_name, message)) return;
   145   // Create and throw exception and init cause
   146   Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
   147   _throw(thread, file, line, h_exception);
   148 }
   150 // This version creates handles and calls the other version
   151 void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
   152                             symbolOop name, const char* message) {
   153   symbolHandle h_name(thread, name);
   154   Handle       h_loader(thread, NULL);
   155   Handle       h_protection_domain(thread, NULL);
   156   Exceptions::_throw_msg(thread, file, line, h_name, message, h_loader, h_protection_domain);
   157 }
   159 // This version already has a handle for name
   160 void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
   161                             symbolHandle name, const char* message) {
   162   Handle       h_loader(thread, NULL);
   163   Handle       h_protection_domain(thread, NULL);
   164   Exceptions::_throw_msg(thread, file, line, name, message, h_loader, h_protection_domain);
   165 }
   167 // This version already has a handle for name
   168 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line,
   169                             symbolHandle name, const char* message, Handle cause) {
   170   Handle       h_loader(thread, NULL);
   171   Handle       h_protection_domain(thread, NULL);
   172   Exceptions::_throw_msg_cause(thread, file, line, name, message, cause, h_loader, h_protection_domain);
   173 }
   175 void Exceptions::_throw_args(Thread* thread, const char* file, int line, symbolHandle h_name, symbolHandle h_signature, JavaCallArguments *args) {
   176   // Check for special boot-strapping/vm-thread handling
   177   if (special_exception(thread, file, line, h_name, NULL)) return;
   178   // Create and throw exception
   179   Handle h_loader(thread, NULL);
   180   Handle h_prot(thread, NULL);
   181   Handle h_cause(thread, NULL);
   182   Handle exception = new_exception(thread, h_name, h_signature, args, h_cause, h_loader, h_prot);
   183   _throw(thread, file, line, exception);
   184 }
   187 void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line) {
   188   Handle exception;
   189   if (!THREAD->has_pending_exception()) {
   190     klassOop k = SystemDictionary::StackOverflowError_klass();
   191     oop e = instanceKlass::cast(k)->allocate_instance(CHECK);
   192     exception = Handle(THREAD, e);  // fill_in_stack trace does gc
   193     if (StackTraceInThrowable) {
   194       java_lang_Throwable::fill_in_stack_trace(exception);
   195     }
   196   } else {
   197     // if prior exception, throw that one instead
   198     exception = Handle(THREAD, THREAD->pending_exception());
   199   }
   200   _throw_oop(THREAD, file, line, exception());
   201 }
   203 void Exceptions::fthrow(Thread* thread, const char* file, int line, symbolHandle h_name, const char* format, ...) {
   204   const int max_msg_size = 1024;
   205   va_list ap;
   206   va_start(ap, format);
   207   char msg[max_msg_size];
   208   vsnprintf(msg, max_msg_size, format, ap);
   209   msg[max_msg_size-1] = '\0';
   210   va_end(ap);
   211   _throw_msg(thread, file, line, h_name, msg);
   212 }
   214 // Creates an exception oop, calls the <init> method with the given signature.
   215 // and returns a Handle
   216 // Initializes the cause if cause non-null
   217 Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name,
   218                                  symbolHandle signature,
   219                                  JavaCallArguments *args,
   220                                  Handle h_cause, Handle h_loader,
   221                                  Handle h_protection_domain) {
   222   assert(Universe::is_fully_initialized(),
   223     "cannot be called during initialization");
   224   assert(thread->is_Java_thread(), "can only be called by a Java thread");
   225   assert(!thread->has_pending_exception(), "already has exception");
   227   Handle h_exception;
   229   // Resolve exception klass
   230   klassOop ik = SystemDictionary::resolve_or_fail(h_name, h_loader, h_protection_domain, true, thread);
   231   instanceKlassHandle klass (thread, ik);
   233   if (!thread->has_pending_exception()) {
   234     assert(klass.not_null(), "klass must exist");
   235     // We are about to create an instance - so make sure that klass is initialized
   236     klass->initialize(thread);
   237     if (!thread->has_pending_exception()) {
   238       // Allocate new exception
   239       h_exception = klass->allocate_instance_handle(thread);
   240       if (!thread->has_pending_exception()) {
   241         JavaValue result(T_VOID);
   242         args->set_receiver(h_exception);
   243         // Call constructor
   244         JavaCalls::call_special(&result, klass,
   245                                          vmSymbolHandles::object_initializer_name(),
   246                                          signature,
   247                                          args,
   248                                          thread);
   250       }
   251     }
   253     // Future: object initializer should take a cause argument
   254     if (h_cause() != NULL) {
   255       assert(h_cause->is_a(SystemDictionary::throwable_klass()),
   256           "exception cause is not a subclass of java/lang/Throwable");
   257       JavaValue result1(T_OBJECT);
   258       JavaCallArguments args1;
   259       args1.set_receiver(h_exception);
   260       args1.push_oop(h_cause);
   261       JavaCalls::call_virtual(&result1, klass,
   262                                      vmSymbolHandles::initCause_name(),
   263                                      vmSymbolHandles::throwable_throwable_signature(),
   264                                      &args1,
   265                                      thread);
   266     }
   267   }
   269   // Check if another exception was thrown in the process, if so rethrow that one
   270   if (thread->has_pending_exception()) {
   271     h_exception = Handle(thread, thread->pending_exception());
   272     thread->clear_pending_exception();
   273   }
   274   return h_exception;
   275 }
   277 // Convenience method. Calls either the <init>() or <init>(String) method when
   278 // creating a new exception
   279 Handle Exceptions::new_exception(Thread* thread, symbolHandle h_name,
   280                                  const char* message, Handle h_cause,
   281                                  Handle h_loader,
   282                                  Handle h_protection_domain,
   283                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
   284   JavaCallArguments args;
   285   symbolHandle signature;
   286   if (message == NULL) {
   287     signature = vmSymbolHandles::void_method_signature();
   288   } else {
   289     // We want to allocate storage, but we can't do that if there's
   290     // a pending exception, so we preserve any pending exception
   291     // around the allocation.
   292     // If we get an exception from the allocation, prefer that to
   293     // the exception we are trying to build, or the pending exception.
   294     // This is sort of like what PRESERVE_EXCEPTION_MARK does, except
   295     // for the preferencing and the early returns.
   296     Handle incoming_exception (thread, NULL);
   297     if (thread->has_pending_exception()) {
   298       incoming_exception = Handle(thread, thread->pending_exception());
   299       thread->clear_pending_exception();
   300     }
   301     Handle msg;
   302     if (to_utf8_safe == safe_to_utf8) {
   303       // Make a java UTF8 string.
   304       msg = java_lang_String::create_from_str(message, thread);
   305     } else {
   306       // Make a java string keeping the encoding scheme of the original string.
   307       msg = java_lang_String::create_from_platform_dependent_str(message, thread);
   308     }
   309     if (thread->has_pending_exception()) {
   310       Handle exception(thread, thread->pending_exception());
   311       thread->clear_pending_exception();
   312       return exception;
   313     }
   314     if (incoming_exception.not_null()) {
   315       return incoming_exception;
   316     }
   317     args.push_oop(msg);
   318     signature = vmSymbolHandles::string_void_signature();
   319   }
   320   return new_exception(thread, h_name, signature, &args, h_cause, h_loader, h_protection_domain);
   321 }
   323 // Another convenience method that creates handles for null class loaders and
   324 // protection domains and null causes.
   325 // If the last parameter 'to_utf8_mode' is safe_to_utf8,
   326 // it means we can safely ignore the encoding scheme of the message string and
   327 // convert it directly to a java UTF8 string. Otherwise, we need to take the
   328 // encoding scheme of the string into account. One thing we should do at some
   329 // point is to push this flag down to class java_lang_String since other
   330 // classes may need similar functionalities.
   331 Handle Exceptions::new_exception(Thread* thread,
   332                                  symbolOop name,
   333                                  const char* message,
   334                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
   336   symbolHandle h_name(thread, name);
   337   Handle       h_loader(thread, NULL);
   338   Handle       h_prot(thread, NULL);
   339   Handle       h_cause(thread, NULL);
   340   return Exceptions::new_exception(thread, h_name, message, h_cause, h_loader,
   341                                    h_prot, to_utf8_safe);
   342 }
   344 // Implementation of ExceptionMark
   346 ExceptionMark::ExceptionMark(Thread*& thread) {
   347   thread     = Thread::current();
   348   _thread    = thread;
   349   if (_thread->has_pending_exception()) {
   350     oop exception = _thread->pending_exception();
   351     _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   352     exception->print();
   353     fatal("ExceptionMark constructor expects no pending exceptions");
   354   }
   355 }
   358 ExceptionMark::~ExceptionMark() {
   359   if (_thread->has_pending_exception()) {
   360     Handle exception(_thread, _thread->pending_exception());
   361     _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   362     if (is_init_completed()) {
   363       exception->print();
   364       fatal("ExceptionMark destructor expects no pending exceptions");
   365     } else {
   366       vm_exit_during_initialization(exception);
   367     }
   368   }
   369 }
   371 // ----------------------------------------------------------------------------------------
   373 #ifndef PRODUCT
   374 // caller frees value_string if necessary
   375 void Exceptions::debug_check_abort(const char *value_string) {
   376   if (AbortVMOnException != NULL && value_string != NULL &&
   377       strstr(value_string, AbortVMOnException)) {
   378     fatal1("Saw %s, aborting", value_string);
   379   }
   380 }
   382 void Exceptions::debug_check_abort(Handle exception) {
   383   if (AbortVMOnException != NULL) {
   384     ResourceMark rm;
   385     debug_check_abort(instanceKlass::cast(exception()->klass())->external_name());
   386   }
   387 }
   388 #endif

mercurial