< prev index next >

src/hotspot/share/runtime/globals.cpp

Print this page
rev 49218 : 8198608: Improvements to command-line flags printing


 445   if (is_notproduct() && is_product_build()) {
 446     jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
 447                  _name);
 448     return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;
 449   }
 450   get_locked_message_ext(buf, buflen);
 451   return Flag::NONE;
 452 }
 453 
 454 bool Flag::is_writeable() const {
 455   return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
 456 }
 457 
 458 // All flags except "manageable" are assumed to be internal flags.
 459 // Long term, we need to define a mechanism to specify which flags
 460 // are external/stable and change this function accordingly.
 461 bool Flag::is_external() const {
 462   return is_manageable() || is_external_ext();
 463 }
 464 












 465 void Flag::print_on(outputStream* st, bool withComments, bool printRanges) {
 466   // Don't print notproduct and develop flags in a product build.
 467   if (is_constant_in_binary()) {
 468     return;
 469   }
 470 
 471   if (!printRanges) {
 472     // Use some named constants to make code more readable.
 473     const unsigned int nSpaces    = 10;
 474     const unsigned int maxFlagLen = 40 + nSpaces;
 475 
 476     // The print below assumes that the flag name is 40 characters or less.
 477     // This works for most flags, but there are exceptions. Our longest flag
 478     // name right now is UseAdaptiveGenerationSizePolicyAtMajorCollection and
 479     // its minor collection buddy. These are 48 characters. We use a buffer of
 480     // nSpaces spaces below to adjust the space between the flag value and the
 481     // column of flag type and origin that is printed in the end of the line.
 482     char spaces[nSpaces + 1] = "          ";
 483     st->print("%9s %-*s = ", _type, maxFlagLen-nSpaces, _name);












































 484 

 485     if (is_bool()) {
 486       st->print("%-20s", get_bool() ? "true" : "false");
 487     } else if (is_int()) {
 488       st->print("%-20d", get_int());
 489     } else if (is_uint()) {
 490       st->print("%-20u", get_uint());
 491     } else if (is_intx()) {
 492       st->print(INTX_FORMAT_W(-20), get_intx());
 493     } else if (is_uintx()) {
 494       st->print(UINTX_FORMAT_W(-20), get_uintx());
 495     } else if (is_uint64_t()) {
 496       st->print(UINT64_FORMAT_W(-20), get_uint64_t());
 497     } else if (is_size_t()) {
 498       st->print(SIZE_FORMAT_W(-20), get_size_t());
 499     } else if (is_double()) {
 500       st->print("%-20f", get_double());
 501     } else if (is_ccstr()) {

 502       const char* cp = get_ccstr();
 503       if (cp != NULL) {
 504         const char* eol;
 505         while ((eol = strchr(cp, '\n')) != NULL) {
 506           size_t llen = pointer_delta(eol, cp, sizeof(char));
 507           st->print("%.*s", (int)llen, cp);
 508           st->cr();
 509           cp = eol+1;
 510           st->print("%5s %-35s += ", "", _name);




 511         }
 512         st->print("%-20s", cp);
 513       }
 514       else st->print("%-20s", "");
 515     }
 516     // Make sure we do not punch a '\0' at a negative char array index.
 517     unsigned int nameLen = (unsigned int)strlen(_name);
 518     if (nameLen <= maxFlagLen) {
 519       spaces[maxFlagLen - MAX2(maxFlagLen-nSpaces, nameLen)] = '\0';
 520       st->print("%s", spaces);
 521     }
 522     print_kind_and_origin(st);





 523 
 524 #ifndef PRODUCT
 525     if (withComments) {

 526       st->print("%s", _doc);
 527     }
 528 #endif
 529 
 530     st->cr();
 531 
 532   } else if (!is_bool() && !is_ccstr()) {
 533     st->print("%9s %-50s ", _type, _name);
















































 534 

 535     RangeStrFunc func = NULL;
 536     if (is_int()) {
 537       func = Flag::get_int_default_range_str;
 538     } else if (is_uint()) {
 539       func = Flag::get_uint_default_range_str;
 540     } else if (is_intx()) {
 541       func = Flag::get_intx_default_range_str;
 542     } else if (is_uintx()) {
 543       func = Flag::get_uintx_default_range_str;
 544     } else if (is_uint64_t()) {
 545       func = Flag::get_uint64_t_default_range_str;
 546     } else if (is_size_t()) {
 547       func = Flag::get_size_t_default_range_str;
 548     } else if (is_double()) {
 549       func = Flag::get_double_default_range_str;
 550     } else {
 551       ShouldNotReachHere();


 552     }
 553     CommandLineFlagRangeList::print(st, _name, func);
 554 
 555     st->print(" %-16s", " ");
 556     print_kind_and_origin(st);



 557 
 558 #ifndef PRODUCT
 559     if (withComments) {

 560       st->print("%s", _doc);
 561     }
 562 #endif
 563 
 564     st->cr();
 565   }
 566 }
 567 
 568 void Flag::print_kind_and_origin(outputStream* st) {
 569   struct Data {
 570     int flag;
 571     const char* name;
 572   };
 573 
 574   Data data[] = {
 575       { KIND_JVMCI, "JVMCI" },
 576       { KIND_C1, "C1" },
 577       { KIND_C2, "C2" },
 578       { KIND_ARCH, "ARCH" },
 579       { KIND_PLATFORM_DEPENDENT, "pd" },
 580       { KIND_PRODUCT, "product" },
 581       { KIND_MANAGEABLE, "manageable" },
 582       { KIND_DIAGNOSTIC, "diagnostic" },
 583       { KIND_EXPERIMENTAL, "experimental" },
 584       { KIND_COMMERCIAL, "commercial" },
 585       { KIND_NOT_PRODUCT, "notproduct" },
 586       { KIND_DEVELOP, "develop" },
 587       { KIND_LP64_PRODUCT, "lp64_product" },
 588       { KIND_READ_WRITE, "rw" },


 598     jio_snprintf(kind, buffer_size, "{");
 599     buffer_used++;
 600     for (int i = 0; data[i].flag != -1; i++) {
 601       Data d = data[i];
 602       if ((_flags & d.flag) != 0) {
 603         if (is_first) {
 604           is_first = false;
 605         } else {
 606           assert(buffer_used + 1 < buffer_size, "Too small buffer");
 607           jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " ");
 608           buffer_used++;
 609         }
 610         size_t length = strlen(d.name);
 611         assert(buffer_used + length < buffer_size, "Too small buffer");
 612         jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name);
 613         buffer_used += length;
 614       }
 615     }
 616     assert(buffer_used + 2 <= buffer_size, "Too small buffer");
 617     jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}");
 618     st->print("%20s", kind);
 619   }

 620 

 621   int origin = _flags & VALUE_ORIGIN_MASK;
 622   st->print(" {");
 623   switch(origin) {
 624     case DEFAULT:
 625       st->print("default"); break;
 626     case COMMAND_LINE:
 627       st->print("command line"); break;
 628     case ENVIRON_VAR:
 629       st->print("environment"); break;
 630     case CONFIG_FILE:
 631       st->print("config file"); break;
 632     case MANAGEMENT:
 633       st->print("management"); break;
 634     case ERGONOMIC:
 635       if (_flags & ORIG_COMMAND_LINE) {
 636         st->print("command line, ");
 637       }
 638       st->print("ergonomic"); break;
 639     case ATTACH_ON_DEMAND:
 640       st->print("attach"); break;
 641     case INTERNAL:
 642       st->print("internal"); break;




 445   if (is_notproduct() && is_product_build()) {
 446     jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
 447                  _name);
 448     return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;
 449   }
 450   get_locked_message_ext(buf, buflen);
 451   return Flag::NONE;
 452 }
 453 
 454 bool Flag::is_writeable() const {
 455   return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
 456 }
 457 
 458 // All flags except "manageable" are assumed to be internal flags.
 459 // Long term, we need to define a mechanism to specify which flags
 460 // are external/stable and change this function accordingly.
 461 bool Flag::is_external() const {
 462   return is_manageable() || is_external_ext();
 463 }
 464 
 465 // Helper function for Flag::print_on().
 466 // Fills current line up to requested position.
 467 // Should the current position already be past the requested position,
 468 // one separator blank is enforced.
 469 void fill_to_pos(outputStream* st, unsigned int req_pos) {
 470   if ((unsigned int)st->position() < req_pos) {
 471     st->fill_to(req_pos);  // need to fill with blanks to reach req_pos
 472   } else {
 473     st->print(" ");        // enforce blank separation. Previous field too long.
 474   }
 475 }
 476 
 477 void Flag::print_on(outputStream* st, bool withComments, bool printRanges) {
 478   // Don't print notproduct and develop flags in a product build.
 479   if (is_constant_in_binary()) {
 480     return;
 481   }
 482 
 483   if (!printRanges) {
 484     // The command line options -XX:+PrintFlags* cause this function to be called
 485     // for each existing flag to print information pertinent to this flag. The data
 486     // is displayed in columnar form, with the following layout:
 487     //  col1 - data type, right-justified
 488     //  col2 - name,      left-justified
 489     //  col3 - ' ='       double-char, leading space to align with possible '+='
 490     //  col4 - value      left-justified
 491     //  col5 - kind       right-justified
 492     //  col6 - origin     left-justified
 493     //  col7 - comments   left-justified
 494     //
 495     //  The column widths are fixed. They are defined such that, for most cases,
 496     //  an eye-pleasing tabular output is created.
 497     //
 498     //  Sample output:
 499     //       bool CMSScavengeBeforeRemark                  = false                                     {product} {default}
 500     //      uintx CMSScheduleRemarkEdenPenetration         = 50                                        {product} {default}
 501     //     size_t CMSScheduleRemarkEdenSizeThreshold       = 2097152                                   {product} {default}
 502     //      uintx CMSScheduleRemarkSamplingRatio           = 5                                         {product} {default}
 503     //     double CMSSmallCoalSurplusPercent               = 1.050000                                  {product} {default}
 504     //      ccstr CompileCommandFile                       = MyFile.cmd                                {product} {command line}
 505     //  ccstrlist CompileOnly                              = Method1
 506     //            CompileOnly                             += Method2                                   {product} {command line}
 507     //  |         |                                       |  |                              |                    |               |
 508     //  |         |                                       |  |                              |                    |               +-- col7
 509     //  |         |                                       |  |                              |                    +-- col6
 510     //  |         |                                       |  |                              +-- col5
 511     //  |         |                                       |  +-- col4
 512     //  |         |                                       +-- col3
 513     //  |         +-- col2
 514     //  +-- col1
 515 
 516     const unsigned int col_spacing = 1;
 517     const unsigned int col1_pos    = 0;
 518     const unsigned int col1_width  = 9;
 519     const unsigned int col2_pos    = col1_pos + col1_width + col_spacing;
 520     const unsigned int col2_width  = 39;
 521     const unsigned int col3_pos    = col2_pos + col2_width + col_spacing;
 522     const unsigned int col3_width  = 2;
 523     const unsigned int col4_pos    = col3_pos + col3_width + col_spacing;
 524     const unsigned int col4_width  = 30;
 525     const unsigned int col5_pos    = col4_pos + col4_width + col_spacing;
 526     const unsigned int col5_width  = 20;
 527     const unsigned int col6_pos    = col5_pos + col5_width + col_spacing;
 528     const unsigned int col6_width  = 15;
 529     const unsigned int col7_pos    = col6_pos + col6_width + col_spacing;
 530     const unsigned int col7_width  = 1;
 531 
 532     st->fill_to(col1_pos);
 533     st->print("%*s", col1_width, _type);  // right-justified, therefore width is required.
 534 
 535     fill_to_pos(st, col2_pos);
 536     st->print("%s", _name);
 537 
 538     fill_to_pos(st, col3_pos);
 539     st->print(" =");  // use " =" for proper alignment with multiline ccstr output.
 540 
 541     fill_to_pos(st, col4_pos);
 542     if (is_bool()) {
 543       st->print("%s", get_bool() ? "true" : "false");
 544     } else if (is_int()) {
 545       st->print("%d", get_int());
 546     } else if (is_uint()) {
 547       st->print("%u", get_uint());
 548     } else if (is_intx()) {
 549       st->print(INTX_FORMAT, get_intx());
 550     } else if (is_uintx()) {
 551       st->print(UINTX_FORMAT, get_uintx());
 552     } else if (is_uint64_t()) {
 553       st->print(UINT64_FORMAT, get_uint64_t());
 554     } else if (is_size_t()) {
 555       st->print(SIZE_FORMAT, get_size_t());
 556     } else if (is_double()) {
 557       st->print("%f", get_double());
 558     } else if (is_ccstr()) {
 559       // Honor <newline> characters in ccstr: print multiple lines.
 560       const char* cp = get_ccstr();
 561       if (cp != NULL) {
 562         const char* eol;
 563         while ((eol = strchr(cp, '\n')) != NULL) {
 564           size_t llen = pointer_delta(eol, cp, sizeof(char));
 565           st->print("%.*s", (int)llen, cp);
 566           st->cr();
 567           cp = eol+1;
 568           fill_to_pos(st, col2_pos);
 569           st->print("%s", _name);
 570           fill_to_pos(st, col3_pos);
 571           st->print("+=");
 572           fill_to_pos(st, col4_pos);
 573         }
 574         st->print("%s", cp);
 575       }
 576     } else {
 577       st->print("unhandled  type %s", _type);
 578       st->cr();
 579       return;



 580     }
 581 
 582     fill_to_pos(st, col5_pos);
 583     print_kind(st, col5_width);
 584 
 585     fill_to_pos(st, col6_pos);
 586     print_origin(st, col6_width);
 587 
 588 #ifndef PRODUCT
 589     if (withComments) {
 590       fill_to_pos(st, col7_pos);
 591       st->print("%s", _doc);
 592     }
 593 #endif

 594     st->cr();

 595   } else if (!is_bool() && !is_ccstr()) {
 596     // The command line options -XX:+PrintFlags* cause this function to be called
 597     // for each existing flag to print information pertinent to this flag. The data
 598     // is displayed in columnar form, with the following layout:
 599     //  col1 - data type, right-justified
 600     //  col2 - name,      left-justified
 601     //  col4 - range      [ min ... max]
 602     //  col5 - kind       right-justified
 603     //  col6 - origin     left-justified
 604     //  col7 - comments   left-justified
 605     //
 606     //  The column widths are fixed. They are defined such that, for most cases,
 607     //  an eye-pleasing tabular output is created.
 608     //
 609     //  Sample output:
 610     //       intx MinPassesBeforeFlush                               [ 0                         ...       9223372036854775807 ]                         {diagnostic} {default}
 611     //      uintx MinRAMFraction                                     [ 1                         ...      18446744073709551615 ]                            {product} {default}
 612     //     double MinRAMPercentage                                   [ 0.000                     ...                   100.000 ]                            {product} {default}
 613     //      uintx MinSurvivorRatio                                   [ 3                         ...      18446744073709551615 ]                            {product} {default}
 614     //     size_t MinTLABSize                                        [ 1                         ...       9223372036854775807 ]                            {product} {default}
 615     //       intx MonitorBound                                       [ 0                         ...                2147483647 ]                            {product} {default}
 616     //  |         |                                                  |                                                           |                                    |               |
 617     //  |         |                                                  |                                                           |                                    |               +-- col7
 618     //  |         |                                                  |                                                           |                                    +-- col6
 619     //  |         |                                                  |                                                           +-- col5
 620     //  |         |                                                  +-- col4
 621     //  |         +-- col2
 622     //  +-- col1
 623 
 624     const unsigned int col_spacing = 1;
 625     const unsigned int col1_pos    = 0;
 626     const unsigned int col1_width  = 9;
 627     const unsigned int col2_pos    = col1_pos + col1_width + col_spacing;
 628     const unsigned int col2_width  = 49;
 629     const unsigned int col3_pos    = col2_pos + col2_width + col_spacing;
 630     const unsigned int col3_width  = 0;
 631     const unsigned int col4_pos    = col3_pos + col3_width + col_spacing;
 632     const unsigned int col4_width  = 60;
 633     const unsigned int col5_pos    = col4_pos + col4_width + col_spacing;
 634     const unsigned int col5_width  = 35;
 635     const unsigned int col6_pos    = col5_pos + col5_width + col_spacing;
 636     const unsigned int col6_width  = 15;
 637     const unsigned int col7_pos    = col6_pos + col6_width + col_spacing;
 638     const unsigned int col7_width  = 1;
 639 
 640     st->fill_to(col1_pos);
 641     st->print("%*s", col1_width, _type);  // right-justified, therefore width is required.
 642 
 643     fill_to_pos(st, col2_pos);
 644     st->print("%s", _name);
 645 
 646     fill_to_pos(st, col4_pos);
 647     RangeStrFunc func = NULL;
 648     if (is_int()) {
 649       func = Flag::get_int_default_range_str;
 650     } else if (is_uint()) {
 651       func = Flag::get_uint_default_range_str;
 652     } else if (is_intx()) {
 653       func = Flag::get_intx_default_range_str;
 654     } else if (is_uintx()) {
 655       func = Flag::get_uintx_default_range_str;
 656     } else if (is_uint64_t()) {
 657       func = Flag::get_uint64_t_default_range_str;
 658     } else if (is_size_t()) {
 659       func = Flag::get_size_t_default_range_str;
 660     } else if (is_double()) {
 661       func = Flag::get_double_default_range_str;
 662     } else {
 663       st->print("unhandled  type %s", _type);
 664       st->cr();
 665       return;
 666     }
 667     CommandLineFlagRangeList::print(st, _name, func);
 668 
 669     fill_to_pos(st, col5_pos);
 670     print_kind(st, col5_width);
 671 
 672     fill_to_pos(st, col6_pos);
 673     print_origin(st, col6_width);
 674 
 675 #ifndef PRODUCT
 676     if (withComments) {
 677       fill_to_pos(st, col7_pos);
 678       st->print("%s", _doc);
 679     }
 680 #endif

 681     st->cr();
 682   }
 683 }
 684 
 685 void Flag::print_kind(outputStream* st, unsigned int width) {
 686   struct Data {
 687     int flag;
 688     const char* name;
 689   };
 690 
 691   Data data[] = {
 692       { KIND_JVMCI, "JVMCI" },
 693       { KIND_C1, "C1" },
 694       { KIND_C2, "C2" },
 695       { KIND_ARCH, "ARCH" },
 696       { KIND_PLATFORM_DEPENDENT, "pd" },
 697       { KIND_PRODUCT, "product" },
 698       { KIND_MANAGEABLE, "manageable" },
 699       { KIND_DIAGNOSTIC, "diagnostic" },
 700       { KIND_EXPERIMENTAL, "experimental" },
 701       { KIND_COMMERCIAL, "commercial" },
 702       { KIND_NOT_PRODUCT, "notproduct" },
 703       { KIND_DEVELOP, "develop" },
 704       { KIND_LP64_PRODUCT, "lp64_product" },
 705       { KIND_READ_WRITE, "rw" },


 715     jio_snprintf(kind, buffer_size, "{");
 716     buffer_used++;
 717     for (int i = 0; data[i].flag != -1; i++) {
 718       Data d = data[i];
 719       if ((_flags & d.flag) != 0) {
 720         if (is_first) {
 721           is_first = false;
 722         } else {
 723           assert(buffer_used + 1 < buffer_size, "Too small buffer");
 724           jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " ");
 725           buffer_used++;
 726         }
 727         size_t length = strlen(d.name);
 728         assert(buffer_used + length < buffer_size, "Too small buffer");
 729         jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name);
 730         buffer_used += length;
 731       }
 732     }
 733     assert(buffer_used + 2 <= buffer_size, "Too small buffer");
 734     jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}");
 735     st->print("%*s", width, kind);
 736   }
 737 }
 738 
 739 void Flag::print_origin(outputStream* st, unsigned int width) {
 740   int origin = _flags & VALUE_ORIGIN_MASK;
 741   st->print("{");
 742   switch(origin) {
 743     case DEFAULT:
 744       st->print("default"); break;
 745     case COMMAND_LINE:
 746       st->print("command line"); break;
 747     case ENVIRON_VAR:
 748       st->print("environment"); break;
 749     case CONFIG_FILE:
 750       st->print("config file"); break;
 751     case MANAGEMENT:
 752       st->print("management"); break;
 753     case ERGONOMIC:
 754       if (_flags & ORIG_COMMAND_LINE) {
 755         st->print("command line, ");
 756       }
 757       st->print("ergonomic"); break;
 758     case ATTACH_ON_DEMAND:
 759       st->print("attach"); break;
 760     case INTERNAL:
 761       st->print("internal"); break;


< prev index next >