exceptions.hpp 13.5 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1998, 2011, 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);
D
duke 已提交
115
  static void _throw_msg(Thread* thread, const char* file, int line,
116
                         Symbol* name, const char* message, Handle loader,
D
duke 已提交
117 118
                         Handle protection_domain);
  static void _throw_msg(Thread* thread, const char* file, int line,
119
                         Symbol* name, const char* message);
D
duke 已提交
120
  static void _throw_args(Thread* thread, const char* file, int line,
121
                          Symbol* name, Symbol* signature,
D
duke 已提交
122 123
                          JavaCallArguments* args);
  static void _throw_msg_cause(Thread* thread, const char* file,
124
                         int line, Symbol* h_name, const char* message,
D
duke 已提交
125 126
                         Handle h_cause, Handle h_loader, Handle h_protection_domain);
  static void _throw_msg_cause(Thread* thread, const char* file, int line,
127
                            Symbol* name, const char* message, Handle cause);
D
duke 已提交
128 129 130

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

  // Create and initialize a new exception
135 136
  static Handle new_exception(Thread* thread, Symbol* name,
                              Symbol* signature, JavaCallArguments* args,
D
duke 已提交
137 138 139
                              Handle cause, Handle loader,
                              Handle protection_domain);

140
  static Handle new_exception(Thread* thread, Symbol* name,
D
duke 已提交
141 142 143 144
                              const char* message, Handle cause, Handle loader,
                              Handle protection_domain,
                              ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);

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

149
  static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, methodHandle method);
D
duke 已提交
150 151

  // for AbortVMOnException flag
152 153
  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 已提交
154 155 156 157 158 159 160 161 162 163 164 165 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
};


// 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())

#define CHECK                                    THREAD); if (HAS_PENDING_EXCEPTION) return       ; (0
#define CHECK_(result)                           THREAD); if (HAS_PENDING_EXCEPTION) return result; (0
#define CHECK_0                                  CHECK_(0)
#define CHECK_NH                                 CHECK_(Handle())
#define CHECK_NULL                               CHECK_(NULL)
#define CHECK_false                              CHECK_(false)

192 193 194 195 196 197 198
#define CHECK_AND_CLEAR                         THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return;        } (0
#define CHECK_AND_CLEAR_(result)                THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return result; } (0
#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 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
// 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;  }

#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; }

#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)

253 254 255
#define THROW_NULL(name)                    THROW_(name, NULL)
#define THROW_MSG_NULL(name, message)       THROW_MSG_(name, message, NULL)

D
duke 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
// 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();                  \
  } (0

// 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);
291 292

#endif // SHARE_VM_UTILITIES_EXCEPTIONS_HPP