exceptions.hpp 14.5 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31
#ifndef SHARE_VM_UTILITIES_EXCEPTIONS_HPP
#define SHARE_VM_UTILITIES_EXCEPTIONS_HPP

#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/sizes.hpp"

D
duke 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// This file provides the basic support for exception handling in the VM.
// Note: We do not use C++ exceptions to avoid compiler dependencies and
// unpredictable performance.
//
// Scheme: Exceptions are stored with the thread. There is never more
// than one pending exception per thread. All functions that can throw
// an exception carry a THREAD argument (usually the last argument and
// declared with the TRAPS macro). Throwing an exception means setting
// a pending exception in the thread. Upon return from a function that
// can throw an exception, we must check if an exception is pending.
// The CHECK macros do this in a convenient way. Carrying around the
// thread provides also convenient access to it (e.g. for Handle
// creation, w/o the need for recomputation).



// Forward declarations to be independent of the include structure.
// This allows us to have exceptions.hpp included in top.hpp.

class Thread;
class Handle;
53
class Symbol;
D
duke 已提交
54 55 56 57 58 59
class JavaCallArguments;

// The ThreadShadow class is a helper class to access the _pending_exception
// field of the Thread class w/o having access to the Thread's interface (for
// include hierachy reasons).

Z
zgu 已提交
60
class ThreadShadow: public CHeapObj<mtThread> {
N
never 已提交
61 62
  friend class VMStructs;

D
duke 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
 protected:
  oop  _pending_exception;                       // Thread has gc actions.
  const char* _exception_file;                   // file information for exception (debugging only)
  int         _exception_line;                   // line information for exception (debugging only)
  friend void check_ThreadShadow();              // checks _pending_exception offset

  // The following virtual exists only to force creation of a vtable.
  // We need ThreadShadow to have a vtable, even in product builds,
  // so that its layout will start at an offset of zero relative to Thread.
  // Some C++ compilers are so "clever" that they put the ThreadShadow
  // base class at offset 4 in Thread (after Thread's vtable), if they
  // notice that Thread has a vtable but ThreadShadow does not.
  virtual void unused_initial_virtual() { }

 public:
  oop  pending_exception() const                 { return _pending_exception; }
  bool has_pending_exception() const             { return _pending_exception != NULL; }
  const char* exception_file() const             { return _exception_file; }
  int  exception_line() const                    { return _exception_line; }

  // Code generation support
  static ByteSize pending_exception_offset()     { return byte_offset_of(ThreadShadow, _pending_exception); }

  // use THROW whenever possible!
  void set_pending_exception(oop exception, const char* file, int line);

  // use CLEAR_PENDING_EXCEPTION whenever possible!
  void clear_pending_exception();

  ThreadShadow() : _pending_exception(NULL),
                   _exception_file(NULL), _exception_line(0) {}
};


// Exceptions is a helper class that encapsulates all operations
// that require access to the thread interface and which are
// relatively rare. The Exceptions operations should only be
// used directly if the macros below are insufficient.

class Exceptions {
  static bool special_exception(Thread *thread, const char* file, int line, Handle exception);
104
  static bool special_exception(Thread* thread, const char* file, int line, Symbol* name, const char* message);
D
duke 已提交
105 106 107 108 109 110 111 112 113
 public:
  // this enum is defined to indicate whether it is safe to
  // ignore the encoding scheme of the original message string.
  typedef enum {
    safe_to_utf8 = 0,
    unsafe_to_utf8 = 1
  } ExceptionMsgToUtf8Mode;
  // Throw exceptions: w/o message, w/ message & with formatted message.
  static void _throw_oop(Thread* thread, const char* file, int line, oop exception);
114
  static void _throw(Thread* thread, const char* file, int line, Handle exception, const char* msg = NULL);
115 116 117 118 119 120 121 122 123 124 125 126 127

  static void _throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message);
  static void _throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message,
                         Handle loader, Handle protection_domain);

  static void _throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause);
  static void _throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause,
                               Handle h_loader, Handle h_protection_domain);

  static void _throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause);
  static void _throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause,
                           Handle h_loader, Handle h_protection_domain);

D
duke 已提交
128
  static void _throw_args(Thread* thread, const char* file, int line,
129
                          Symbol* name, Symbol* signature,
D
duke 已提交
130 131 132 133
                          JavaCallArguments* args);

  // There is no THROW... macro for this method. Caller should remember
  // to do a return after calling it.
134
  static void fthrow(Thread* thread, const char* file, int line, Symbol* name,
D
duke 已提交
135 136 137
                     const char* format, ...);

  // Create and initialize a new exception
138 139
  static Handle new_exception(Thread* thread, Symbol* name,
                              Symbol* signature, JavaCallArguments* args,
140 141 142 143 144 145
                              Handle loader, Handle protection_domain);

  static Handle new_exception(Thread* thread, Symbol* name,
                              Symbol* signature, JavaCallArguments* args,
                              Handle cause,
                              Handle loader, Handle protection_domain);
D
duke 已提交
146

147
  static Handle new_exception(Thread* thread, Symbol* name,
148 149
                              Handle cause,
                              Handle loader, Handle protection_domain,
D
duke 已提交
150 151
                              ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);

152 153 154 155 156 157 158 159
  static Handle new_exception(Thread* thread, Symbol* name,
                              const char* message, Handle cause,
                              Handle loader, Handle protection_domain,
                              ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);

  static Handle new_exception(Thread* thread, Symbol* name,
                              const char* message,
                              ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
D
duke 已提交
160

161
  static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, methodHandle method);
D
duke 已提交
162 163

  // for AbortVMOnException flag
164 165
  NOT_PRODUCT(static void debug_check_abort(Handle exception, const char* message = NULL);)
  NOT_PRODUCT(static void debug_check_abort(const char *value_string, const char* message = NULL);)
D
duke 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
};


// The THREAD & TRAPS macros facilitate the declaration of functions that throw exceptions.
// Convention: Use the TRAPS macro as the last argument of such a function; e.g.:
//
// int this_function_may_trap(int x, float y, TRAPS)

#define THREAD __the_thread__
#define TRAPS  Thread* THREAD


// The CHECK... macros should be used to pass along a THREAD reference and to check for pending
// exceptions. In special situations it is necessary to handle pending exceptions explicitly,
// in these cases the PENDING_EXCEPTION helper macros should be used.
//
// Macro naming conventions: Macros that end with _ require a result value to be returned. They
// are for functions with non-void result type. The result value is usually ignored because of
// the exception and is only needed for syntactic correctness. The _0 ending is a shortcut for
// _(0) since this is a frequent case. Example:
//
// int result = this_function_may_trap(x_arg, y_arg, CHECK_0);
//
// CAUTION: make sure that the function call using a CHECK macro is not the only statement of a
// conditional branch w/o enclosing {} braces, since the CHECK macros expand into several state-
// ments!

#define PENDING_EXCEPTION                        (((ThreadShadow*)THREAD)->pending_exception())
#define HAS_PENDING_EXCEPTION                    (((ThreadShadow*)THREAD)->has_pending_exception())
#define CLEAR_PENDING_EXCEPTION                  (((ThreadShadow*)THREAD)->clear_pending_exception())

197 198
#define CHECK                                    THREAD); if (HAS_PENDING_EXCEPTION) return       ; (void)(0
#define CHECK_(result)                           THREAD); if (HAS_PENDING_EXCEPTION) return result; (void)(0
D
duke 已提交
199 200 201 202 203
#define CHECK_0                                  CHECK_(0)
#define CHECK_NH                                 CHECK_(Handle())
#define CHECK_NULL                               CHECK_(NULL)
#define CHECK_false                              CHECK_(false)

204 205
#define CHECK_AND_CLEAR                         THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return;        } (void)(0
#define CHECK_AND_CLEAR_(result)                THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return result; } (void)(0
206 207 208 209 210
#define CHECK_AND_CLEAR_0                       CHECK_AND_CLEAR_(0)
#define CHECK_AND_CLEAR_NH                      CHECK_AND_CLEAR_(Handle())
#define CHECK_AND_CLEAR_NULL                    CHECK_AND_CLEAR_(NULL)
#define CHECK_AND_CLEAR_false                   CHECK_AND_CLEAR_(false)

D
duke 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
// The THROW... macros should be used to throw an exception. They require a THREAD variable to be
// visible within the scope containing the THROW. Usually this is achieved by declaring the function
// with a TRAPS argument.

#define THREAD_AND_LOCATION                      THREAD, __FILE__, __LINE__

#define THROW_OOP(e)                                \
  { Exceptions::_throw_oop(THREAD_AND_LOCATION, e);                             return;  }

#define THROW_HANDLE(e)                                \
  { Exceptions::_throw(THREAD_AND_LOCATION, e);                             return;  }

#define THROW(name)                                 \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, NULL); return;  }

#define THROW_MSG(name, message)                    \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message); return;  }

229 230 231
#define THROW_CAUSE(name, cause)   \
  { Exceptions::_throw_cause(THREAD_AND_LOCATION, name, cause); return; }

D
duke 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
#define THROW_MSG_LOADER(name, message, loader, protection_domain) \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return;  }

#define THROW_ARG(name, signature, args) \
  { Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args);   return; }

#define THROW_OOP_(e, result)                       \
  { Exceptions::_throw_oop(THREAD_AND_LOCATION, e);                           return result; }

#define THROW_HANDLE_(e, result)                       \
  { Exceptions::_throw(THREAD_AND_LOCATION, e);                           return result; }

#define THROW_(name, result)                        \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, NULL); return result; }

#define THROW_MSG_(name, message, result)           \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message); return result; }

#define THROW_MSG_LOADER_(name, message, loader, protection_domain, result) \
  { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return result; }

#define THROW_ARG_(name, signature, args, result) \
  { Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args); return result; }
255 256 257

#define THROW_MSG_CAUSE(name, message, cause)   \
  { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION, name, message, cause); return; }
D
duke 已提交
258 259 260 261 262 263 264 265 266 267 268 269

#define THROW_MSG_CAUSE_(name, message, cause, result)   \
  { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION, name, message, cause); return result; }


#define THROW_OOP_0(e)                      THROW_OOP_(e, 0)
#define THROW_HANDLE_0(e)                   THROW_HANDLE_(e, 0)
#define THROW_0(name)                       THROW_(name, 0)
#define THROW_MSG_0(name, message)          THROW_MSG_(name, message, 0)
#define THROW_WRAPPED_0(name, oop_to_wrap)  THROW_WRAPPED_(name, oop_to_wrap, 0)
#define THROW_ARG_0(name, signature, arg)   THROW_ARG_(name, signature, arg, 0)
#define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0)
270
#define THROW_MSG_CAUSE_NULL(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, NULL)
D
duke 已提交
271

272 273 274
#define THROW_NULL(name)                    THROW_(name, NULL)
#define THROW_MSG_NULL(name, message)       THROW_MSG_(name, message, NULL)

D
duke 已提交
275 276 277 278 279 280 281 282 283 284
// The CATCH macro checks that no exception has been thrown by a function; it is used at
// call sites about which is statically known that the callee cannot throw an exception
// even though it is declared with TRAPS.

#define CATCH                              \
  THREAD); if (HAS_PENDING_EXCEPTION) {    \
    oop ex = PENDING_EXCEPTION;            \
    CLEAR_PENDING_EXCEPTION;               \
    ex->print();                           \
    ShouldNotReachHere();                  \
285
  } (void)(0
D
duke 已提交
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

// ExceptionMark is a stack-allocated helper class for local exception handling.
// It is used with the EXCEPTION_MARK macro.

class ExceptionMark {
 private:
  Thread* _thread;

 public:
  ExceptionMark(Thread*& thread);
  ~ExceptionMark();
};



// Use an EXCEPTION_MARK for 'local' exceptions. EXCEPTION_MARK makes sure that no
// pending exception exists upon entering its scope and tests that no pending exception
// exists when leaving the scope.

// See also preserveException.hpp for PRESERVE_EXCEPTION_MARK macro,
// which preserves pre-existing exceptions and does not allow new
// exceptions.

#define EXCEPTION_MARK                           Thread* THREAD; ExceptionMark __em(THREAD);
310 311

#endif // SHARE_VM_UTILITIES_EXCEPTIONS_HPP