1/*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "jvm.h"
27#include "classfile/systemDictionary.hpp"
28#include "code/codeCache.hpp"
29#include "code/icBuffer.hpp"
30#include "code/nmethod.hpp"
31#include "code/vtableStubs.hpp"
32#include "compiler/compileBroker.hpp"
33#include "compiler/disassembler.hpp"
34#include "gc/shared/collectedHeap.hpp"
35#include "interpreter/bytecodeHistogram.hpp"
36#include "interpreter/interpreter.hpp"
37#include "memory/allocation.hpp"
38#include "memory/resourceArea.hpp"
39#include "memory/universe.hpp"
40#include "oops/oop.inline.hpp"
41#include "runtime/arguments.hpp"
42#include "runtime/atomic.hpp"
43#include "runtime/flags/flagSetting.hpp"
44#include "runtime/frame.inline.hpp"
45#include "runtime/handles.inline.hpp"
46#include "runtime/java.hpp"
47#include "runtime/os.hpp"
48#include "runtime/sharedRuntime.hpp"
49#include "runtime/stubCodeGenerator.hpp"
50#include "runtime/stubRoutines.hpp"
51#include "runtime/thread.inline.hpp"
52#include "runtime/vframe.hpp"
53#include "runtime/vm_version.hpp"
54#include "services/heapDumper.hpp"
55#include "services/memTracker.hpp"
56#include "utilities/defaultStream.hpp"
57#include "utilities/events.hpp"
58#include "utilities/formatBuffer.hpp"
59#include "utilities/globalDefinitions.hpp"
60#include "utilities/macros.hpp"
61#include "utilities/vmError.hpp"
62
63#include <stdio.h>
64#include <stdarg.h>
65
66// Support for showing register content on asserts/guarantees.
67#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
68static char g_dummy;
69char* g_assert_poison = &g_dummy;
70static intx g_asserting_thread = 0;
71static void* g_assertion_context = NULL;
72#endif // CAN_SHOW_REGISTERS_ON_ASSERT
73
74#ifndef ASSERT
75# ifdef _DEBUG
76 // NOTE: don't turn the lines below into a comment -- if you're getting
77 // a compile error here, change the settings to define ASSERT
78 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging
79 functions that do not slow down the system too much and thus can be left in optimized code.
80 On the other hand, the code should not be included in a production version.
81# endif // _DEBUG
82#endif // ASSERT
83
84
85#ifdef _DEBUG
86# ifndef ASSERT
87 configuration error: ASSERT must be defined in debug version
88# endif // ASSERT
89#endif // _DEBUG
90
91
92#ifdef PRODUCT
93# if -defined _DEBUG || -defined ASSERT
94 configuration error: ASSERT et al. must not be defined in PRODUCT version
95# endif
96#endif // PRODUCT
97
98#ifdef ASSERT
99// This is to test that error reporting works if we assert during dynamic
100// initialization of the hotspot. See JDK-8214975.
101struct Crasher {
102 Crasher() {
103 // Using getenv - no other mechanism would work yet.
104 const char* s = ::getenv("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION");
105 if (s != NULL && ::strcmp(s, "1") == 0) {
106 fatal("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION");
107 }
108 }
109};
110static Crasher g_crasher;
111#endif // ASSERT
112
113ATTRIBUTE_PRINTF(1, 2)
114void warning(const char* format, ...) {
115 if (PrintWarnings) {
116 FILE* const err = defaultStream::error_stream();
117 jio_fprintf(err, "%s warning: ", VM_Version::vm_name());
118 va_list ap;
119 va_start(ap, format);
120 vfprintf(err, format, ap);
121 va_end(ap);
122 fputc('\n', err);
123 }
124 if (BreakAtWarning) BREAKPOINT;
125}
126
127#ifndef PRODUCT
128
129#define is_token_break(ch) (isspace(ch) || (ch) == ',')
130
131static const char* last_file_name = NULL;
132static int last_line_no = -1;
133
134// assert/guarantee/... may happen very early during VM initialization.
135// Don't rely on anything that is initialized by Threads::create_vm(). For
136// example, don't use tty.
137bool error_is_suppressed(const char* file_name, int line_no) {
138 // The following 1-element cache requires that passed-in
139 // file names are always only constant literals.
140 if (file_name == last_file_name && line_no == last_line_no) return true;
141
142 int file_name_len = (int)strlen(file_name);
143 char separator = os::file_separator()[0];
144 const char* base_name = strrchr(file_name, separator);
145 if (base_name == NULL)
146 base_name = file_name;
147
148 // scan the SuppressErrorAt option
149 const char* cp = SuppressErrorAt;
150 for (;;) {
151 const char* sfile;
152 int sfile_len;
153 int sline;
154 bool noisy;
155 while ((*cp) != '\0' && is_token_break(*cp)) cp++;
156 if ((*cp) == '\0') break;
157 sfile = cp;
158 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++;
159 sfile_len = cp - sfile;
160 if ((*cp) == ':') cp++;
161 sline = 0;
162 while ((*cp) != '\0' && isdigit(*cp)) {
163 sline *= 10;
164 sline += (*cp) - '0';
165 cp++;
166 }
167 // "file:line!" means the assert suppression is not silent
168 noisy = ((*cp) == '!');
169 while ((*cp) != '\0' && !is_token_break(*cp)) cp++;
170 // match the line
171 if (sline != 0) {
172 if (sline != line_no) continue;
173 }
174 // match the file
175 if (sfile_len > 0) {
176 const char* look = file_name;
177 const char* look_max = file_name + file_name_len - sfile_len;
178 const char* foundp;
179 bool match = false;
180 while (!match
181 && (foundp = strchr(look, sfile[0])) != NULL
182 && foundp <= look_max) {
183 match = true;
184 for (int i = 1; i < sfile_len; i++) {
185 if (sfile[i] != foundp[i]) {
186 match = false;
187 break;
188 }
189 }
190 look = foundp + 1;
191 }
192 if (!match) continue;
193 }
194 // got a match!
195 if (noisy) {
196 fdStream out(defaultStream::output_fd());
197 out.print_raw("[error suppressed at ");
198 out.print_raw(base_name);
199 char buf[16];
200 jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
201 out.print_raw_cr(buf);
202 } else {
203 // update 1-element cache for fast silent matches
204 last_file_name = file_name;
205 last_line_no = line_no;
206 }
207 return true;
208 }
209
210 if (!VMError::is_error_reported() && !SuppressFatalErrorMessage) {
211 // print a friendly hint:
212 fdStream out(defaultStream::output_fd());
213 out.print_raw_cr("# To suppress the following error report, specify this argument");
214 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt=");
215 out.print_raw (base_name);
216 char buf[16];
217 jio_snprintf(buf, sizeof(buf), ":%d", line_no);
218 out.print_raw_cr(buf);
219 }
220 return false;
221}
222
223#undef is_token_break
224
225#else
226
227// Place-holder for non-existent suppression check:
228#define error_is_suppressed(file_name, line_no) (false)
229
230#endif // !PRODUCT
231
232void report_vm_error(const char* file, int line, const char* error_msg)
233{
234 report_vm_error(file, line, error_msg, "%s", "");
235}
236
237void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...)
238{
239 if (Debugging || error_is_suppressed(file, line)) return;
240 va_list detail_args;
241 va_start(detail_args, detail_fmt);
242 void* context = NULL;
243#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
244 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) {
245 context = g_assertion_context;
246 }
247#endif // CAN_SHOW_REGISTERS_ON_ASSERT
248
249#ifdef ASSERT
250 if (detail_fmt != NULL && ExecutingUnitTests) {
251 // Special handling for the sake of gtest death tests which expect the assert
252 // message to be printed in one short line to stderr (see TEST_VM_ASSERT_MSG) and
253 // cannot be tweaked to accept our normal assert message.
254 va_list detail_args_copy;
255 va_copy(detail_args_copy, detail_args);
256 ::fputs("assert failed: ", stderr);
257 ::vfprintf(stderr, detail_fmt, detail_args_copy);
258 ::fputs("\n", stderr);
259 ::fflush(stderr);
260 va_end(detail_args_copy);
261 }
262#endif
263
264 VMError::report_and_die(Thread::current_or_null(), context, file, line, error_msg, detail_fmt, detail_args);
265 va_end(detail_args);
266}
267
268void report_vm_status_error(const char* file, int line, const char* error_msg,
269 int status, const char* detail) {
270 report_vm_error(file, line, error_msg, "error %s(%d), %s", os::errno_name(status), status, detail);
271}
272
273void report_fatal(const char* file, int line, const char* detail_fmt, ...)
274{
275 if (Debugging || error_is_suppressed(file, line)) return;
276 va_list detail_args;
277 va_start(detail_args, detail_fmt);
278 void* context = NULL;
279#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
280 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) {
281 context = g_assertion_context;
282 }
283#endif // CAN_SHOW_REGISTERS_ON_ASSERT
284 VMError::report_and_die(Thread::current_or_null(), context, file, line, "fatal error", detail_fmt, detail_args);
285 va_end(detail_args);
286}
287
288void report_vm_out_of_memory(const char* file, int line, size_t size,
289 VMErrorType vm_err_type, const char* detail_fmt, ...) {
290 if (Debugging) return;
291 va_list detail_args;
292 va_start(detail_args, detail_fmt);
293 VMError::report_and_die(Thread::current_or_null(), file, line, size, vm_err_type, detail_fmt, detail_args);
294 va_end(detail_args);
295
296 // The UseOSErrorReporting option in report_and_die() may allow a return
297 // to here. If so then we'll have to figure out how to handle it.
298 guarantee(false, "report_and_die() should not return here");
299}
300
301void report_should_not_call(const char* file, int line) {
302 report_vm_error(file, line, "ShouldNotCall()");
303}
304
305void report_should_not_reach_here(const char* file, int line) {
306 report_vm_error(file, line, "ShouldNotReachHere()");
307}
308
309void report_unimplemented(const char* file, int line) {
310 report_vm_error(file, line, "Unimplemented()");
311}
312
313void report_untested(const char* file, int line, const char* message) {
314#ifndef PRODUCT
315 warning("Untested: %s in %s: %d\n", message, file, line);
316#endif // !PRODUCT
317}
318
319void report_java_out_of_memory(const char* message) {
320 static int out_of_memory_reported = 0;
321
322 // A number of threads may attempt to report OutOfMemoryError at around the
323 // same time. To avoid dumping the heap or executing the data collection
324 // commands multiple times we just do it once when the first threads reports
325 // the error.
326 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
327 // create heap dump before OnOutOfMemoryError commands are executed
328 if (HeapDumpOnOutOfMemoryError) {
329 tty->print_cr("java.lang.OutOfMemoryError: %s", message);
330 HeapDumper::dump_heap_from_oome();
331 }
332
333 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
334 VMError::report_java_out_of_memory(message);
335 }
336
337 if (CrashOnOutOfMemoryError) {
338 tty->print_cr("Aborting due to java.lang.OutOfMemoryError: %s", message);
339 fatal("OutOfMemory encountered: %s", message);
340 }
341
342 if (ExitOnOutOfMemoryError) {
343 tty->print_cr("Terminating due to java.lang.OutOfMemoryError: %s", message);
344 os::exit(3);
345 }
346 }
347}
348
349// ------ helper functions for debugging go here ------------
350
351// All debug entries should be wrapped with a stack allocated
352// Command object. It makes sure a resource mark is set and
353// flushes the logfile to prevent file sharing problems.
354
355class Command : public StackObj {
356 private:
357 ResourceMark rm;
358 ResetNoHandleMark rnhm;
359 HandleMark hm;
360 bool debug_save;
361 public:
362 static int level;
363 Command(const char* str) {
364 debug_save = Debugging;
365 Debugging = true;
366 if (level++ > 0) return;
367 tty->cr();
368 tty->print_cr("\"Executing %s\"", str);
369 }
370
371 ~Command() {
372 tty->flush();
373 Debugging = debug_save;
374 level--;
375 }
376};
377
378int Command::level = 0;
379
380#ifndef PRODUCT
381
382extern "C" void blob(CodeBlob* cb) {
383 Command c("blob");
384 cb->print();
385}
386
387
388extern "C" void dump_vtable(address p) {
389 Command c("dump_vtable");
390 Klass* k = (Klass*)p;
391 k->vtable().print();
392}
393
394
395extern "C" void nm(intptr_t p) {
396 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
397 Command c("nm");
398 CodeBlob* cb = CodeCache::find_blob((address)p);
399 if (cb == NULL) {
400 tty->print_cr("NULL");
401 } else {
402 cb->print();
403 }
404}
405
406
407extern "C" void disnm(intptr_t p) {
408 Command c("disnm");
409 CodeBlob* cb = CodeCache::find_blob((address) p);
410 if (cb != NULL) {
411 nmethod* nm = cb->as_nmethod_or_null();
412 if (nm != NULL) {
413 nm->print();
414 } else {
415 cb->print();
416 }
417 Disassembler::decode(cb);
418 }
419}
420
421
422extern "C" void printnm(intptr_t p) {
423 char buffer[256];
424 sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
425 Command c(buffer);
426 CodeBlob* cb = CodeCache::find_blob((address) p);
427 if (cb->is_nmethod()) {
428 nmethod* nm = (nmethod*)cb;
429 nm->print_nmethod(true);
430 }
431}
432
433
434extern "C" void universe() {
435 Command c("universe");
436 Universe::print_on(tty);
437}
438
439
440extern "C" void verify() {
441 // try to run a verify on the entire system
442 // note: this may not be safe if we're not at a safepoint; for debugging,
443 // this manipulates the safepoint settings to avoid assertion failures
444 Command c("universe verify");
445 bool safe = SafepointSynchronize::is_at_safepoint();
446 if (!safe) {
447 tty->print_cr("warning: not at safepoint -- verify may fail");
448 SafepointSynchronize::set_is_at_safepoint();
449 }
450 // Ensure Eden top is correct before verification
451 Universe::heap()->prepare_for_verify();
452 Universe::verify();
453 if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
454}
455
456
457extern "C" void pp(void* p) {
458 Command c("pp");
459 FlagSetting fl(PrintVMMessages, true);
460 FlagSetting f2(DisplayVMOutput, true);
461 if (Universe::heap()->is_in(p)) {
462 oop obj = oop(p);
463 obj->print();
464 } else {
465 tty->print(PTR_FORMAT, p2i(p));
466 }
467}
468
469
470// pv: print vm-printable object
471extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); }
472extern "C" void findpc(intptr_t x);
473
474#endif // !PRODUCT
475
476extern "C" void ps() { // print stack
477 if (Thread::current_or_null() == NULL) return;
478 Command c("ps");
479
480
481 // Prints the stack of the current Java thread
482 JavaThread* p = JavaThread::active();
483 tty->print(" for thread: ");
484 p->print();
485 tty->cr();
486
487 if (p->has_last_Java_frame()) {
488 // If the last_Java_fp is set we are in C land and
489 // can call the standard stack_trace function.
490#ifdef PRODUCT
491 p->print_stack();
492 } else {
493 tty->print_cr("Cannot find the last Java frame, printing stack disabled.");
494#else // !PRODUCT
495 p->trace_stack();
496 } else {
497 frame f = os::current_frame();
498 RegisterMap reg_map(p);
499 f = f.sender(&reg_map);
500 tty->print("(guessing starting frame id=" PTR_FORMAT " based on current fp)\n", p2i(f.id()));
501 p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
502 f.pd_ps();
503#endif // PRODUCT
504 }
505
506}
507
508extern "C" void pfl() {
509 // print frame layout
510 Command c("pfl");
511 JavaThread* p = JavaThread::active();
512 tty->print(" for thread: ");
513 p->print();
514 tty->cr();
515 if (p->has_last_Java_frame()) {
516 p->print_frame_layout();
517 }
518}
519
520#ifndef PRODUCT
521
522extern "C" void psf() { // print stack frames
523 {
524 Command c("psf");
525 JavaThread* p = JavaThread::active();
526 tty->print(" for thread: ");
527 p->print();
528 tty->cr();
529 if (p->has_last_Java_frame()) {
530 p->trace_frames();
531 }
532 }
533}
534
535
536extern "C" void threads() {
537 Command c("threads");
538 Threads::print(false, true);
539}
540
541
542extern "C" void psd() {
543 Command c("psd");
544 SystemDictionary::print();
545}
546
547#endif // !PRODUCT
548
549extern "C" void pss() { // print all stacks
550 if (Thread::current_or_null() == NULL) return;
551 Command c("pss");
552 Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true));
553}
554
555#ifndef PRODUCT
556
557extern "C" void debug() { // to set things up for compiler debugging
558 Command c("debug");
559 WizardMode = true;
560 PrintVMMessages = PrintCompilation = true;
561 PrintInlining = PrintAssembly = true;
562 tty->flush();
563}
564
565
566extern "C" void ndebug() { // undo debug()
567 Command c("ndebug");
568 PrintCompilation = false;
569 PrintInlining = PrintAssembly = false;
570 tty->flush();
571}
572
573
574extern "C" void flush() {
575 Command c("flush");
576 tty->flush();
577}
578
579extern "C" void events() {
580 Command c("events");
581 Events::print();
582}
583
584extern "C" Method* findm(intptr_t pc) {
585 Command c("findm");
586 nmethod* nm = CodeCache::find_nmethod((address)pc);
587 return (nm == NULL) ? (Method*)NULL : nm->method();
588}
589
590
591extern "C" nmethod* findnm(intptr_t addr) {
592 Command c("findnm");
593 return CodeCache::find_nmethod((address)addr);
594}
595
596// Another interface that isn't ambiguous in dbx.
597// Can we someday rename the other find to hsfind?
598extern "C" void hsfind(intptr_t x) {
599 Command c("hsfind");
600 os::print_location(tty, x, false);
601}
602
603
604extern "C" void find(intptr_t x) {
605 Command c("find");
606 os::print_location(tty, x, false);
607}
608
609
610extern "C" void findpc(intptr_t x) {
611 Command c("findpc");
612 os::print_location(tty, x, true);
613}
614
615
616// Need method pointer to find bcp, when not in permgen.
617extern "C" void findbcp(intptr_t method, intptr_t bcp) {
618 Command c("findbcp");
619 Method* mh = (Method*)method;
620 if (!mh->is_native()) {
621 tty->print_cr("bci_from(%p) = %d; print_codes():",
622 mh, mh->bci_from(address(bcp)));
623 mh->print_codes_on(tty);
624 }
625}
626
627// int versions of all methods to avoid having to type type casts in the debugger
628
629void pp(intptr_t p) { pp((void*)p); }
630void pp(oop p) { pp((void*)p); }
631
632void help() {
633 Command c("help");
634 tty->print_cr("basic");
635 tty->print_cr(" pp(void* p) - try to make sense of p");
636 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
637 tty->print_cr(" ps() - print current thread stack");
638 tty->print_cr(" pss() - print all thread stacks");
639 tty->print_cr(" pm(int pc) - print Method* given compiled PC");
640 tty->print_cr(" findm(intptr_t pc) - finds Method*");
641 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
642 tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g.");
643 tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
644 tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or");
645 tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or");
646 tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or");
647 tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
648 tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()");
649 tty->print_cr(" - in dbx do 'frame 1' before calling pns()");
650
651 tty->print_cr("misc.");
652 tty->print_cr(" flush() - flushes the log file");
653 tty->print_cr(" events() - dump events from ring buffers");
654
655
656 tty->print_cr("compiler debugging");
657 tty->print_cr(" debug() - to set things up for compiler debugging");
658 tty->print_cr(" ndebug() - undo debug");
659}
660
661extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack
662 Command c("pns");
663 static char buf[O_BUFLEN];
664 Thread* t = Thread::current_or_null();
665 // Call generic frame constructor (certain arguments may be ignored)
666 frame fr(sp, fp, pc);
667 VMError::print_native_stack(tty, fr, t, buf, sizeof(buf));
668}
669
670//
671// This version of pns() will not work when called from the debugger, but is
672// useful when called from within hotspot code. The advantages over pns()
673// are not having to pass in any arguments, and it will work on Windows/x64.
674//
675// WARNING: Only intended for use when debugging. Do not leave calls to
676// pns2() in committed source (product or debug).
677//
678extern "C" void pns2() { // print native stack
679 Command c("pns2");
680 static char buf[O_BUFLEN];
681 if (os::platform_print_native_stack(tty, NULL, buf, sizeof(buf))) {
682 // We have printed the native stack in platform-specific code,
683 // so nothing else to do in this case.
684 } else {
685 Thread* t = Thread::current_or_null();
686 frame fr = os::current_frame();
687 VMError::print_native_stack(tty, fr, t, buf, sizeof(buf));
688 }
689}
690
691#endif // !PRODUCT
692
693//////////////////////////////////////////////////////////////////////////////
694// Test multiple STATIC_ASSERT forms in various scopes.
695
696#ifndef PRODUCT
697
698// namespace scope
699STATIC_ASSERT(true);
700STATIC_ASSERT(true);
701STATIC_ASSERT(1 == 1);
702STATIC_ASSERT(0 == 0);
703
704void test_multiple_static_assert_forms_in_function_scope() {
705 STATIC_ASSERT(true);
706 STATIC_ASSERT(true);
707 STATIC_ASSERT(0 == 0);
708 STATIC_ASSERT(1 == 1);
709}
710
711// class scope
712struct TestMultipleStaticAssertFormsInClassScope {
713 STATIC_ASSERT(true);
714 STATIC_ASSERT(true);
715 STATIC_ASSERT(0 == 0);
716 STATIC_ASSERT(1 == 1);
717};
718
719#endif // !PRODUCT
720
721// Support for showing register content on asserts/guarantees.
722#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
723
724static ucontext_t g_stored_assertion_context;
725
726void initialize_assert_poison() {
727 char* page = os::reserve_memory(os::vm_page_size());
728 if (page) {
729 MemTracker::record_virtual_memory_type(page, mtInternal);
730 if (os::commit_memory(page, os::vm_page_size(), false) &&
731 os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) {
732 g_assert_poison = page;
733 }
734 }
735}
736
737static void store_context(const void* context) {
738 memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
739#if defined(__linux) && defined(PPC64)
740 // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
741 // after copying the context (see comment in sys/ucontext.h):
742 *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs);
743#endif
744}
745
746bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
747 if (faulting_address == g_assert_poison) {
748 // Disarm poison page.
749 os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX);
750 // Store Context away.
751 if (ucVoid) {
752 const intx my_tid = os::current_thread_id();
753 if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) {
754 store_context(ucVoid);
755 g_assertion_context = &g_stored_assertion_context;
756 }
757 }
758 return true;
759 }
760 return false;
761}
762#endif // CAN_SHOW_REGISTERS_ON_ASSERT
763
764