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