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

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

mercurial