70 static int last_line_no = -1; |
70 static int last_line_no = -1; |
71 |
71 |
72 // assert/guarantee/... may happen very early during VM initialization. |
72 // assert/guarantee/... may happen very early during VM initialization. |
73 // Don't rely on anything that is initialized by Threads::create_vm(). For |
73 // Don't rely on anything that is initialized by Threads::create_vm(). For |
74 // example, don't use tty. |
74 // example, don't use tty. |
75 bool assert_is_suppressed(const char* file_name, int line_no) { |
75 bool error_is_suppressed(const char* file_name, int line_no) { |
76 // The following 1-element cache requires that passed-in |
76 // The following 1-element cache requires that passed-in |
77 // file names are always only constant literals. |
77 // file names are always only constant literals. |
78 if (file_name == last_file_name && line_no == last_line_no) return true; |
78 if (file_name == last_file_name && line_no == last_line_no) return true; |
79 |
79 |
80 int file_name_len = (int)strlen(file_name); |
80 int file_name_len = (int)strlen(file_name); |
161 #undef is_token_break |
161 #undef is_token_break |
162 |
162 |
163 #else |
163 #else |
164 |
164 |
165 // Place-holder for non-existent suppression check: |
165 // Place-holder for non-existent suppression check: |
166 #define assert_is_suppressed(file_name, line_no) (false) |
166 #define error_is_suppressed(file_name, line_no) (false) |
167 |
167 |
168 #endif //PRODUCT |
168 #endif //PRODUCT |
169 |
169 |
170 void report_assertion_failure(const char* file_name, int line_no, const char* message) { |
170 void report_vm_error(const char* file, int line, const char* error_msg, |
171 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
171 const char* detail_msg) |
172 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); |
172 { |
|
173 if (Debugging || error_is_suppressed(file, line)) return; |
|
174 Thread* const thread = ThreadLocalStorage::get_thread_slow(); |
|
175 VMError err(thread, file, line, error_msg, detail_msg); |
173 err.report_and_die(); |
176 err.report_and_die(); |
174 } |
177 } |
175 |
178 |
176 void report_fatal(const char* file_name, int line_no, const char* message) { |
179 void report_fatal(const char* file, int line, const char* message) |
177 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
180 { |
178 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); |
181 report_vm_error(file, line, "fatal error", message); |
179 err.report_and_die(); |
182 } |
180 } |
|
181 |
|
182 void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...) { |
|
183 char buffer[256]; |
|
184 va_list ap; |
|
185 va_start(ap, format); |
|
186 jio_vsnprintf(buffer, sizeof(buffer), format, ap); |
|
187 va_end(ap); |
|
188 report_fatal(file_name, line_no, buffer); |
|
189 } |
|
190 |
|
191 |
183 |
192 // Used by report_vm_out_of_memory to detect recursion. |
184 // Used by report_vm_out_of_memory to detect recursion. |
193 static jint _exiting_out_of_mem = 0; |
185 static jint _exiting_out_of_mem = 0; |
194 |
186 |
195 // Just passing the flow to VMError to handle error |
187 void report_vm_out_of_memory(const char* file, int line, size_t size, |
196 void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) { |
188 const char* message) { |
197 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
189 if (Debugging || error_is_suppressed(file, line)) return; |
198 |
190 |
199 // We try to gather additional information for the first out of memory |
191 // We try to gather additional information for the first out of memory |
200 // error only; gathering additional data might cause an allocation and a |
192 // error only; gathering additional data might cause an allocation and a |
201 // recursive out_of_memory condition. |
193 // recursive out_of_memory condition. |
202 |
194 |
204 // If we succeed in changing the value, we're the first one in. |
196 // If we succeed in changing the value, we're the first one in. |
205 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; |
197 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; |
206 |
198 |
207 if (first_time_here) { |
199 if (first_time_here) { |
208 Thread* thread = ThreadLocalStorage::get_thread_slow(); |
200 Thread* thread = ThreadLocalStorage::get_thread_slow(); |
209 VMError(thread, size, message, file_name, line_no).report_and_die(); |
201 VMError(thread, file, line, size, message).report_and_die(); |
210 } |
202 } |
211 |
203 |
212 // Dump core and abort |
204 // Dump core and abort |
213 vm_abort(true); |
205 vm_abort(true); |
214 } |
206 } |
215 |
207 |
216 void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) { |
208 void report_should_not_call(const char* file, int line) { |
217 char buffer[256]; |
209 report_vm_error(file, line, "ShouldNotCall()"); |
218 va_list ap; |
210 } |
219 va_start(ap, format); |
211 |
220 jio_vsnprintf(buffer, sizeof(buffer), format, ap); |
212 void report_should_not_reach_here(const char* file, int line) { |
221 va_end(ap); |
213 report_vm_error(file, line, "ShouldNotReachHere()"); |
222 report_vm_out_of_memory(file_name, line_no, size, buffer); |
214 } |
223 } |
215 |
224 |
216 void report_unimplemented(const char* file, int line) { |
225 void report_should_not_call(const char* file_name, int line_no) { |
217 report_vm_error(file, line, "Unimplemented()"); |
226 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
218 } |
227 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no); |
219 |
228 err.report_and_die(); |
220 void report_untested(const char* file, int line, const char* message) { |
229 } |
|
230 |
|
231 |
|
232 void report_should_not_reach_here(const char* file_name, int line_no) { |
|
233 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
|
234 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no); |
|
235 err.report_and_die(); |
|
236 } |
|
237 |
|
238 |
|
239 void report_unimplemented(const char* file_name, int line_no) { |
|
240 if (Debugging || assert_is_suppressed(file_name, line_no)) return; |
|
241 VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no); |
|
242 err.report_and_die(); |
|
243 } |
|
244 |
|
245 |
|
246 void report_untested(const char* file_name, int line_no, const char* msg) { |
|
247 #ifndef PRODUCT |
221 #ifndef PRODUCT |
248 warning("Untested: %s in %s: %d\n", msg, file_name, line_no); |
222 warning("Untested: %s in %s: %d\n", message, file, line); |
249 #endif // PRODUCT |
223 #endif // PRODUCT |
250 } |
224 } |
251 |
225 |
252 void report_java_out_of_memory(const char* message) { |
226 void report_java_out_of_memory(const char* message) { |
253 static jint out_of_memory_reported = 0; |
227 static jint out_of_memory_reported = 0; |
281 } |
255 } |
282 |
256 |
283 bool is_error_reported() { |
257 bool is_error_reported() { |
284 return error_reported; |
258 return error_reported; |
285 } |
259 } |
|
260 |
|
261 #ifndef PRODUCT |
|
262 #include <signal.h> |
|
263 |
|
264 void test_error_handler(size_t test_num) |
|
265 { |
|
266 if (test_num == 0) return; |
|
267 |
|
268 // If asserts are disabled, use the corresponding guarantee instead. |
|
269 size_t n = test_num; |
|
270 NOT_DEBUG(if (n <= 2) n += 2); |
|
271 |
|
272 const char* const str = "hello"; |
|
273 const size_t num = (size_t)os::vm_page_size(); |
|
274 |
|
275 const char* const eol = os::line_separator(); |
|
276 const char* const msg = "this message should be truncated during formatting"; |
|
277 |
|
278 // Keep this in sync with test/runtime/6888954/vmerrors.sh. |
|
279 switch (n) { |
|
280 case 1: assert(str == NULL, "expected null"); |
|
281 case 2: assert(num == 1023 && *str == 'X', |
|
282 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
|
283 case 3: guarantee(str == NULL, "expected null"); |
|
284 case 4: guarantee(num == 1023 && *str == 'X', |
|
285 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
|
286 case 5: fatal("expected null"); |
|
287 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
|
288 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " |
|
289 "%s%s# %s%s# %s%s# %s%s# %s%s# " |
|
290 "%s%s# %s%s# %s%s# %s%s# %s", |
|
291 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, |
|
292 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, |
|
293 msg, eol, msg, eol, msg, eol, msg, eol, msg)); |
|
294 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate"); |
|
295 case 9: ShouldNotCallThis(); |
|
296 case 10: ShouldNotReachHere(); |
|
297 case 11: Unimplemented(); |
|
298 // This is last because it does not generate an hs_err* file on Windows. |
|
299 case 12: os::signal_raise(SIGSEGV); |
|
300 |
|
301 default: ShouldNotReachHere(); |
|
302 } |
|
303 } |
|
304 #endif // #ifndef PRODUCT |
286 |
305 |
287 // ------ helper functions for debugging go here ------------ |
306 // ------ helper functions for debugging go here ------------ |
288 |
307 |
289 #ifndef PRODUCT |
308 #ifndef PRODUCT |
290 // All debug entries should be wrapped with a stack allocated |
309 // All debug entries should be wrapped with a stack allocated |