444 if (is_notproduct() && is_product_build()) { 445 jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n", 446 _name); 447 return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD; 448 } 449 get_locked_message_ext(buf, buflen); 450 return Flag::NONE; 451 } 452 453 bool Flag::is_writeable() const { 454 return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext(); 455 } 456 457 // All flags except "manageable" are assumed to be internal flags. 458 // Long term, we need to define a mechanism to specify which flags 459 // are external/stable and change this function accordingly. 460 bool Flag::is_external() const { 461 return is_manageable() || is_external_ext(); 462 } 463 464 void Flag::print_on(outputStream* st, bool withComments, bool printRanges) { 465 // Don't print notproduct and develop flags in a product build. 466 if (is_constant_in_binary()) { 467 return; 468 } 469 470 if (!printRanges) { 471 // Use some named constants to make code more readable. 472 const unsigned int nSpaces = 10; 473 const unsigned int maxFlagLen = 40 + nSpaces; 474 475 // The print below assumes that the flag name is 40 characters or less. 476 // This works for most flags, but there are exceptions. Our longest flag 477 // name right now is UseAdaptiveGenerationSizePolicyAtMajorCollection and 478 // its minor collection buddy. These are 48 characters. We use a buffer of 479 // nSpaces spaces below to adjust the space between the flag value and the 480 // column of flag type and origin that is printed in the end of the line. 481 char spaces[nSpaces + 1] = " "; 482 st->print("%9s %-*s = ", _type, maxFlagLen-nSpaces, _name); 483 484 if (is_bool()) { 485 st->print("%-20s", get_bool() ? "true" : "false"); 486 } else if (is_int()) { 487 st->print("%-20d", get_int()); 488 } else if (is_uint()) { 489 st->print("%-20u", get_uint()); 490 } else if (is_intx()) { 491 st->print(INTX_FORMAT_W(-20), get_intx()); 492 } else if (is_uintx()) { 493 st->print(UINTX_FORMAT_W(-20), get_uintx()); 494 } else if (is_uint64_t()) { 495 st->print(UINT64_FORMAT_W(-20), get_uint64_t()); 496 } else if (is_size_t()) { 497 st->print(SIZE_FORMAT_W(-20), get_size_t()); 498 } else if (is_double()) { 499 st->print("%-20f", get_double()); 500 } else if (is_ccstr()) { 501 const char* cp = get_ccstr(); 502 if (cp != NULL) { 503 const char* eol; 504 while ((eol = strchr(cp, '\n')) != NULL) { 505 size_t llen = pointer_delta(eol, cp, sizeof(char)); 506 st->print("%.*s", (int)llen, cp); 507 st->cr(); 508 cp = eol+1; 509 st->print("%5s %-35s += ", "", _name); 510 } 511 st->print("%-20s", cp); 512 } 513 else st->print("%-20s", ""); 514 } 515 // Make sure we do not punch a '\0' at a negative char array index. 516 unsigned int nameLen = (unsigned int)strlen(_name); 517 if (nameLen <= maxFlagLen) { 518 spaces[maxFlagLen - MAX2(maxFlagLen-nSpaces, nameLen)] = '\0'; 519 st->print("%s", spaces); 520 } 521 print_kind_and_origin(st); 522 523 #ifndef PRODUCT 524 if (withComments) { 525 st->print("%s", _doc); 526 } 527 #endif 528 529 st->cr(); 530 531 } else if (!is_bool() && !is_ccstr()) { 532 st->print("%9s %-50s ", _type, _name); 533 534 RangeStrFunc func = NULL; 535 if (is_int()) { 536 func = Flag::get_int_default_range_str; 537 } else if (is_uint()) { 538 func = Flag::get_uint_default_range_str; 539 } else if (is_intx()) { 540 func = Flag::get_intx_default_range_str; 541 } else if (is_uintx()) { 542 func = Flag::get_uintx_default_range_str; 543 } else if (is_uint64_t()) { 544 func = Flag::get_uint64_t_default_range_str; 545 } else if (is_size_t()) { 546 func = Flag::get_size_t_default_range_str; 547 } else if (is_double()) { 548 func = Flag::get_double_default_range_str; 549 } else { 550 ShouldNotReachHere(); 551 } 552 CommandLineFlagRangeList::print(st, _name, func); 553 554 st->print(" %-16s", " "); 555 print_kind_and_origin(st); 556 557 #ifndef PRODUCT 558 if (withComments) { 559 st->print("%s", _doc); 560 } 561 #endif 562 563 st->cr(); 564 } 565 } 566 567 void Flag::print_kind_and_origin(outputStream* st) { 568 struct Data { 569 int flag; 570 const char* name; 571 }; 572 573 Data data[] = { 574 { KIND_JVMCI, "JVMCI" }, 575 { KIND_C1, "C1" }, 576 { KIND_C2, "C2" }, 577 { KIND_ARCH, "ARCH" }, 578 { KIND_PLATFORM_DEPENDENT, "pd" }, 579 { KIND_PRODUCT, "product" }, 580 { KIND_MANAGEABLE, "manageable" }, 581 { KIND_DIAGNOSTIC, "diagnostic" }, 582 { KIND_EXPERIMENTAL, "experimental" }, 583 { KIND_COMMERCIAL, "commercial" }, 584 { KIND_NOT_PRODUCT, "notproduct" }, 585 { KIND_DEVELOP, "develop" }, 586 { KIND_LP64_PRODUCT, "lp64_product" }, 587 { KIND_READ_WRITE, "rw" }, 597 jio_snprintf(kind, buffer_size, "{"); 598 buffer_used++; 599 for (int i = 0; data[i].flag != -1; i++) { 600 Data d = data[i]; 601 if ((_flags & d.flag) != 0) { 602 if (is_first) { 603 is_first = false; 604 } else { 605 assert(buffer_used + 1 < buffer_size, "Too small buffer"); 606 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " "); 607 buffer_used++; 608 } 609 size_t length = strlen(d.name); 610 assert(buffer_used + length < buffer_size, "Too small buffer"); 611 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name); 612 buffer_used += length; 613 } 614 } 615 assert(buffer_used + 2 <= buffer_size, "Too small buffer"); 616 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}"); 617 st->print("%20s", kind); 618 } 619 620 int origin = _flags & VALUE_ORIGIN_MASK; 621 st->print(" {"); 622 switch(origin) { 623 case DEFAULT: 624 st->print("default"); break; 625 case COMMAND_LINE: 626 st->print("command line"); break; 627 case ENVIRON_VAR: 628 st->print("environment"); break; 629 case CONFIG_FILE: 630 st->print("config file"); break; 631 case MANAGEMENT: 632 st->print("management"); break; 633 case ERGONOMIC: 634 if (_flags & ORIG_COMMAND_LINE) { 635 st->print("command line, "); 636 } 637 st->print("ergonomic"); break; 638 case ATTACH_ON_DEMAND: 639 st->print("attach"); break; 640 case INTERNAL: 641 st->print("internal"); break; | 444 if (is_notproduct() && is_product_build()) { 445 jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n", 446 _name); 447 return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD; 448 } 449 get_locked_message_ext(buf, buflen); 450 return Flag::NONE; 451 } 452 453 bool Flag::is_writeable() const { 454 return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext(); 455 } 456 457 // All flags except "manageable" are assumed to be internal flags. 458 // Long term, we need to define a mechanism to specify which flags 459 // are external/stable and change this function accordingly. 460 bool Flag::is_external() const { 461 return is_manageable() || is_external_ext(); 462 } 463 464 // The purpose of using stringStream: 465 // The Flag::print_on() method constructs the output for each existing command-line flag out of 466 // multiple st->print() calls, where st is an outputStream usually mapped to tty directly. 467 // That may cause significant overhead in elapsed time and cpu cycles. 468 // With a stringStream buffer, the output string for a command-line flag is constructed in a 469 // local stringStream object. Only after construction is complete, the stringStream object is 470 // written to the outputStream (usually tty), all at once. 471 void Flag::print_on(outputStream* ost, bool withComments, bool printRanges) { 472 // Don't print notproduct and develop flags in a product build. 473 if (is_constant_in_binary()) { 474 return; 475 } 476 477 ResourceMark rm; 478 stringStream stobj = stringStream(1024); 479 stringStream* st = &stobj; 480 481 if (!printRanges) { 482 // The command line options -XX:+PrintFlags* cause this function to be called 483 // for each existing flag to print information pertinent to this flag. The data 484 // is displayed in columnar form, with the following layout: 485 // col1 - data type, right-justified 486 // col2 - name, left-justified 487 // col3 - '=' single-char 488 // col4 - value left-justified 489 // col5 - kind right-justified 490 // col6 - origin left-justified 491 // col7 - comments left-justified 492 // 493 // The column widths are fixed. They are defined such that, for most cases, 494 // an eye-pleasing tabular output is created. 495 496 const unsigned int col_spacing = 1; 497 const unsigned int col1_pos = 0; 498 const unsigned int col1_width = 9; 499 const unsigned int col2_pos = col1_pos + col1_width + col_spacing; 500 const unsigned int col2_width = 39; 501 const unsigned int col3_pos = col2_pos + col2_width + col_spacing; 502 const unsigned int col3_width = 2; 503 const unsigned int col4_pos = col3_pos + col3_width + col_spacing; 504 const unsigned int col4_width = 30; 505 const unsigned int col5_pos = col4_pos + col4_width + col_spacing; 506 const unsigned int col5_width = 19; 507 const unsigned int col6_pos = col5_pos + col5_width + col_spacing; 508 const unsigned int col6_width = 15; 509 const unsigned int col7_pos = col6_pos + col6_width + col_spacing; 510 const unsigned int col7_width = 1; 511 512 st->fill_to(col1_pos); 513 st->print("%*s", col1_width, _type); // right-justified, therefore width is required. 514 515 st->fill_to(col2_pos); 516 st->print("%s", _name); 517 518 st->fill_to(col3_pos); 519 st->print(" ="); // use " =" for proper alignment with multiline ccstr output. 520 521 st->fill_to(col4_pos); 522 if (is_bool()) { 523 st->print("%s", get_bool() ? "true" : "false"); 524 } else if (is_int()) { 525 st->print("%d", get_int()); 526 } else if (is_uint()) { 527 st->print("%u", get_uint()); 528 } else if (is_intx()) { 529 st->print(INTX_FORMAT, get_intx()); 530 } else if (is_uintx()) { 531 st->print(UINTX_FORMAT, get_uintx()); 532 } else if (is_uint64_t()) { 533 st->print(UINT64_FORMAT, get_uint64_t()); 534 } else if (is_size_t()) { 535 st->print(SIZE_FORMAT, get_size_t()); 536 } else if (is_double()) { 537 st->print("%f", get_double()); 538 } else if (is_ccstr()) { 539 // Honor <newline> characters in ccstr: print multiple lines. 540 const char* cp = get_ccstr(); 541 if (cp != NULL) { 542 const char* eol; 543 while ((eol = strchr(cp, '\n')) != NULL) { 544 size_t llen = pointer_delta(eol, cp, sizeof(char)); 545 st->print("%.*s", (int)llen, cp); 546 st->cr(); 547 cp = eol+1; 548 st->fill_to(col2_pos); 549 st->print("%s", _name); 550 st->fill_to(col3_pos); 551 st->print("+="); 552 st->fill_to(col4_pos); 553 } 554 st->print("%s", cp); 555 } 556 } 557 558 st->fill_to(col5_pos); 559 print_kind(st, col5_width); 560 561 st->fill_to(col6_pos); 562 print_origin(st, col6_width); 563 564 #ifndef PRODUCT 565 if (withComments) { 566 st->fill_to(col7_pos); 567 st->print("%s", _doc); 568 } 569 #endif 570 st->cr(); 571 } else if (!is_bool() && !is_ccstr()) { 572 // The command line options -XX:+PrintFlags* cause this function to be called 573 // for each existing flag to print information pertinent to this flag. The data 574 // is displayed in columnar form, with the following layout: 575 // col1 - data type, right-justified 576 // col2 - name, left-justified 577 // col4 - range [ min ... max] 578 // col5 - kind right-justified 579 // col6 - origin left-justified 580 // col7 - comments left-justified 581 // 582 // The column widths are fixed. They are defined such that, for most cases, 583 // an eye-pleasing tabular output is created. 584 585 const unsigned int col_spacing = 1; 586 const unsigned int col1_pos = 0; 587 const unsigned int col1_width = 9; 588 const unsigned int col2_pos = col1_pos + col1_width + col_spacing; 589 const unsigned int col2_width = 49; 590 const unsigned int col3_pos = col2_pos + col2_width + col_spacing; 591 const unsigned int col3_width = 0; 592 const unsigned int col4_pos = col3_pos + col3_width + col_spacing; 593 const unsigned int col4_width = 60; 594 const unsigned int col5_pos = col4_pos + col4_width + col_spacing; 595 const unsigned int col5_width = 35; 596 const unsigned int col6_pos = col5_pos + col5_width + col_spacing; 597 const unsigned int col6_width = 15; 598 const unsigned int col7_pos = col6_pos + col6_width + col_spacing; 599 const unsigned int col7_width = 1; 600 601 st->fill_to(col1_pos); 602 st->print("%*s", col1_width, _type); // right-justified, therefore width is required. 603 604 st->fill_to(col2_pos); 605 st->print("%s", _name); 606 607 RangeStrFunc func = NULL; 608 if (is_int()) { 609 func = Flag::get_int_default_range_str; 610 } else if (is_uint()) { 611 func = Flag::get_uint_default_range_str; 612 } else if (is_intx()) { 613 func = Flag::get_intx_default_range_str; 614 } else if (is_uintx()) { 615 func = Flag::get_uintx_default_range_str; 616 } else if (is_uint64_t()) { 617 func = Flag::get_uint64_t_default_range_str; 618 } else if (is_size_t()) { 619 func = Flag::get_size_t_default_range_str; 620 } else if (is_double()) { 621 func = Flag::get_double_default_range_str; 622 } else { 623 ShouldNotReachHere(); 624 } 625 st->fill_to(col4_pos); 626 CommandLineFlagRangeList::print(st, _name, func); 627 628 st->fill_to(col5_pos); 629 print_kind(st, col5_width); 630 631 st->fill_to(col6_pos); 632 print_origin(st, col6_width); 633 634 #ifndef PRODUCT 635 if (withComments) { 636 st->fill_to(col7_pos); 637 st->print("%s", _doc); 638 } 639 #endif 640 st->cr(); 641 } 642 ost->print("%s", st->as_string()); 643 } 644 645 void Flag::print_kind(outputStream* st, unsigned int width) { 646 struct Data { 647 int flag; 648 const char* name; 649 }; 650 651 Data data[] = { 652 { KIND_JVMCI, "JVMCI" }, 653 { KIND_C1, "C1" }, 654 { KIND_C2, "C2" }, 655 { KIND_ARCH, "ARCH" }, 656 { KIND_PLATFORM_DEPENDENT, "pd" }, 657 { KIND_PRODUCT, "product" }, 658 { KIND_MANAGEABLE, "manageable" }, 659 { KIND_DIAGNOSTIC, "diagnostic" }, 660 { KIND_EXPERIMENTAL, "experimental" }, 661 { KIND_COMMERCIAL, "commercial" }, 662 { KIND_NOT_PRODUCT, "notproduct" }, 663 { KIND_DEVELOP, "develop" }, 664 { KIND_LP64_PRODUCT, "lp64_product" }, 665 { KIND_READ_WRITE, "rw" }, 675 jio_snprintf(kind, buffer_size, "{"); 676 buffer_used++; 677 for (int i = 0; data[i].flag != -1; i++) { 678 Data d = data[i]; 679 if ((_flags & d.flag) != 0) { 680 if (is_first) { 681 is_first = false; 682 } else { 683 assert(buffer_used + 1 < buffer_size, "Too small buffer"); 684 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " "); 685 buffer_used++; 686 } 687 size_t length = strlen(d.name); 688 assert(buffer_used + length < buffer_size, "Too small buffer"); 689 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name); 690 buffer_used += length; 691 } 692 } 693 assert(buffer_used + 2 <= buffer_size, "Too small buffer"); 694 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}"); 695 st->print("%*s", width, kind); 696 } 697 } 698 699 void Flag::print_origin(outputStream* st, unsigned int width) { 700 701 int origin = _flags & VALUE_ORIGIN_MASK; 702 st->print("{"); 703 switch(origin) { 704 case DEFAULT: 705 st->print("default"); break; 706 case COMMAND_LINE: 707 st->print("command line"); break; 708 case ENVIRON_VAR: 709 st->print("environment"); break; 710 case CONFIG_FILE: 711 st->print("config file"); break; 712 case MANAGEMENT: 713 st->print("management"); break; 714 case ERGONOMIC: 715 if (_flags & ORIG_COMMAND_LINE) { 716 st->print("command line, "); 717 } 718 st->print("ergonomic"); break; 719 case ATTACH_ON_DEMAND: 720 st->print("attach"); break; 721 case INTERNAL: 722 st->print("internal"); break; |