1 /* 2 * Copyright (c) 1997, 2015, 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 "memory/allocation.inline.hpp" 27 #include "oops/oop.inline.hpp" 28 #include "runtime/arguments.hpp" 29 #include "runtime/globals.hpp" 30 #include "runtime/globals_extension.hpp" 31 #include "runtime/os.hpp" 32 #include "trace/tracing.hpp" 33 #include "utilities/macros.hpp" 34 #include "utilities/ostream.hpp" 35 #include "utilities/top.hpp" 36 #if INCLUDE_ALL_GCS 37 #include "gc/g1/g1_globals.hpp" 38 #endif // INCLUDE_ALL_GCS 39 #ifdef COMPILER1 40 #include "c1/c1_globals.hpp" 41 #endif 42 #ifdef COMPILER2 43 #include "opto/c2_globals.hpp" 44 #endif 45 #ifdef SHARK 46 #include "shark/shark_globals.hpp" 47 #endif 48 49 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 50 51 RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ 52 MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ 53 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \ 54 MATERIALIZE_NOTPRODUCT_FLAG, \ 55 MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \ 56 MATERIALIZE_LP64_PRODUCT_FLAG) 57 58 RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ 59 MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ 60 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) 61 62 ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, \ 63 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \ 64 MATERIALIZE_NOTPRODUCT_FLAG) 65 66 MATERIALIZE_FLAGS_EXT 67 68 69 static bool is_product_build() { 70 #ifdef PRODUCT 71 return true; 72 #else 73 return false; 74 #endif 75 } 76 77 void Flag::check_writable() { 78 if (is_constant_in_binary()) { 79 fatal(err_msg("flag is constant: %s", _name)); 80 } 81 } 82 83 bool Flag::is_bool() const { 84 return strcmp(_type, "bool") == 0; 85 } 86 87 bool Flag::get_bool() const { 88 return *((bool*) _addr); 89 } 90 91 void Flag::set_bool(bool value) { 92 check_writable(); 93 *((bool*) _addr) = value; 94 } 95 96 bool Flag::is_int() const { 97 return strcmp(_type, "int") == 0; 98 } 99 100 int Flag::get_int() const { 101 return *((int*) _addr); 102 } 103 104 void Flag::set_int(int value) { 105 check_writable(); 106 *((int*) _addr) = value; 107 } 108 109 bool Flag::is_uint() const { 110 return strcmp(_type, "uint") == 0; 111 } 112 113 uint Flag::get_uint() const { 114 return *((uint*) _addr); 115 } 116 117 void Flag::set_uint(uint value) { 118 check_writable(); 119 *((uint*) _addr) = value; 120 } 121 122 bool Flag::is_intx() const { 123 return strcmp(_type, "intx") == 0; 124 } 125 126 intx Flag::get_intx() const { 127 return *((intx*) _addr); 128 } 129 130 void Flag::set_intx(intx value) { 131 check_writable(); 132 *((intx*) _addr) = value; 133 } 134 135 bool Flag::is_uintx() const { 136 return strcmp(_type, "uintx") == 0; 137 } 138 139 uintx Flag::get_uintx() const { 140 return *((uintx*) _addr); 141 } 142 143 void Flag::set_uintx(uintx value) { 144 check_writable(); 145 *((uintx*) _addr) = value; 146 } 147 148 bool Flag::is_uint64_t() const { 149 return strcmp(_type, "uint64_t") == 0; 150 } 151 152 uint64_t Flag::get_uint64_t() const { 153 return *((uint64_t*) _addr); 154 } 155 156 void Flag::set_uint64_t(uint64_t value) { 157 check_writable(); 158 *((uint64_t*) _addr) = value; 159 } 160 161 bool Flag::is_size_t() const { 162 return strcmp(_type, "size_t") == 0; 163 } 164 165 size_t Flag::get_size_t() const { 166 return *((size_t*) _addr); 167 } 168 169 void Flag::set_size_t(size_t value) { 170 check_writable(); 171 *((size_t*) _addr) = value; 172 } 173 174 bool Flag::is_double() const { 175 return strcmp(_type, "double") == 0; 176 } 177 178 double Flag::get_double() const { 179 return *((double*) _addr); 180 } 181 182 void Flag::set_double(double value) { 183 check_writable(); 184 *((double*) _addr) = value; 185 } 186 187 bool Flag::is_ccstr() const { 188 return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0; 189 } 190 191 bool Flag::ccstr_accumulates() const { 192 return strcmp(_type, "ccstrlist") == 0; 193 } 194 195 ccstr Flag::get_ccstr() const { 196 return *((ccstr*) _addr); 197 } 198 199 void Flag::set_ccstr(ccstr value) { 200 check_writable(); 201 *((ccstr*) _addr) = value; 202 } 203 204 205 Flag::Flags Flag::get_origin() { 206 return Flags(_flags & VALUE_ORIGIN_MASK); 207 } 208 209 void Flag::set_origin(Flags origin) { 210 assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity"); 211 _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | origin); 212 } 213 214 bool Flag::is_default() { 215 return (get_origin() == DEFAULT); 216 } 217 218 bool Flag::is_ergonomic() { 219 return (get_origin() == ERGONOMIC); 220 } 221 222 bool Flag::is_command_line() { 223 return (get_origin() == COMMAND_LINE); 224 } 225 226 bool Flag::is_product() const { 227 return (_flags & KIND_PRODUCT) != 0; 228 } 229 230 bool Flag::is_manageable() const { 231 return (_flags & KIND_MANAGEABLE) != 0; 232 } 233 234 bool Flag::is_diagnostic() const { 235 return (_flags & KIND_DIAGNOSTIC) != 0; 236 } 237 238 bool Flag::is_experimental() const { 239 return (_flags & KIND_EXPERIMENTAL) != 0; 240 } 241 242 bool Flag::is_notproduct() const { 243 return (_flags & KIND_NOT_PRODUCT) != 0; 244 } 245 246 bool Flag::is_develop() const { 247 return (_flags & KIND_DEVELOP) != 0; 248 } 249 250 bool Flag::is_read_write() const { 251 return (_flags & KIND_READ_WRITE) != 0; 252 } 253 254 bool Flag::is_commercial() const { 255 return (_flags & KIND_COMMERCIAL) != 0; 256 } 257 258 /** 259 * Returns if this flag is a constant in the binary. Right now this is 260 * true for notproduct and develop flags in product builds. 261 */ 262 bool Flag::is_constant_in_binary() const { 263 #ifdef PRODUCT 264 return is_notproduct() || is_develop(); 265 #else 266 return false; 267 #endif 268 } 269 270 bool Flag::is_unlocker() const { 271 return strcmp(_name, "UnlockDiagnosticVMOptions") == 0 || 272 strcmp(_name, "UnlockExperimentalVMOptions") == 0 || 273 is_unlocker_ext(); 274 } 275 276 bool Flag::is_unlocked() const { 277 if (is_diagnostic()) { 278 return UnlockDiagnosticVMOptions; 279 } 280 if (is_experimental()) { 281 return UnlockExperimentalVMOptions; 282 } 283 return is_unlocked_ext(); 284 } 285 286 void Flag::unlock_diagnostic() { 287 assert(is_diagnostic(), "sanity"); 288 _flags = Flags(_flags & ~KIND_DIAGNOSTIC); 289 } 290 291 // Get custom message for this locked flag, or return NULL if 292 // none is available. 293 void Flag::get_locked_message(char* buf, int buflen) const { 294 buf[0] = '\0'; 295 if (is_diagnostic() && !is_unlocked()) { 296 jio_snprintf(buf, buflen, "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n", 297 _name); 298 return; 299 } 300 if (is_experimental() && !is_unlocked()) { 301 jio_snprintf(buf, buflen, "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n", 302 _name); 303 return; 304 } 305 if (is_develop() && is_product_build()) { 306 jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n", 307 _name); 308 return; 309 } 310 if (is_notproduct() && is_product_build()) { 311 jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n", 312 _name); 313 return; 314 } 315 get_locked_message_ext(buf, buflen); 316 } 317 318 bool Flag::is_writeable() const { 319 return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext(); 320 } 321 322 // All flags except "manageable" are assumed to be internal flags. 323 // Long term, we need to define a mechanism to specify which flags 324 // are external/stable and change this function accordingly. 325 bool Flag::is_external() const { 326 return is_manageable() || is_external_ext(); 327 } 328 329 330 // Length of format string (e.g. "%.1234s") for printing ccstr below 331 #define FORMAT_BUFFER_LEN 16 332 333 PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL 334 void Flag::print_on(outputStream* st, bool withComments) { 335 // Don't print notproduct and develop flags in a product build. 336 if (is_constant_in_binary()) { 337 return; 338 } 339 340 st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' ')); 341 342 if (is_bool()) { 343 st->print("%-16s", get_bool() ? "true" : "false"); 344 } 345 if (is_int()) { 346 st->print("%-16d", get_int()); 347 } 348 if (is_uint()) { 349 st->print("%-16u", get_uint()); 350 } 351 if (is_intx()) { 352 st->print("%-16ld", get_intx()); 353 } 354 if (is_uintx()) { 355 st->print("%-16lu", get_uintx()); 356 } 357 if (is_uint64_t()) { 358 st->print("%-16lu", get_uint64_t()); 359 } 360 if (is_size_t()) { 361 st->print(SIZE_FORMAT_W(-16), get_size_t()); 362 } 363 if (is_double()) { 364 st->print("%-16f", get_double()); 365 } 366 if (is_ccstr()) { 367 const char* cp = get_ccstr(); 368 if (cp != NULL) { 369 const char* eol; 370 while ((eol = strchr(cp, '\n')) != NULL) { 371 char format_buffer[FORMAT_BUFFER_LEN]; 372 size_t llen = pointer_delta(eol, cp, sizeof(char)); 373 jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, 374 "%%." SIZE_FORMAT "s", llen); 375 PRAGMA_DIAG_PUSH 376 PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL 377 st->print(format_buffer, cp); 378 PRAGMA_DIAG_POP 379 st->cr(); 380 cp = eol+1; 381 st->print("%5s %-35s += ", "", _name); 382 } 383 st->print("%-16s", cp); 384 } 385 else st->print("%-16s", ""); 386 } 387 388 st->print("%-20s", " "); 389 print_kind(st); 390 391 if (withComments) { 392 #ifndef PRODUCT 393 st->print("%s", _doc); 394 #endif 395 } 396 st->cr(); 397 } 398 399 void Flag::print_kind(outputStream* st) { 400 struct Data { 401 int flag; 402 const char* name; 403 }; 404 405 Data data[] = { 406 { KIND_C1, "C1" }, 407 { KIND_C2, "C2" }, 408 { KIND_ARCH, "ARCH" }, 409 { KIND_SHARK, "SHARK" }, 410 { KIND_PLATFORM_DEPENDENT, "pd" }, 411 { KIND_PRODUCT, "product" }, 412 { KIND_MANAGEABLE, "manageable" }, 413 { KIND_DIAGNOSTIC, "diagnostic" }, 414 { KIND_EXPERIMENTAL, "experimental" }, 415 { KIND_COMMERCIAL, "commercial" }, 416 { KIND_NOT_PRODUCT, "notproduct" }, 417 { KIND_DEVELOP, "develop" }, 418 { KIND_LP64_PRODUCT, "lp64_product" }, 419 { KIND_READ_WRITE, "rw" }, 420 { -1, "" } 421 }; 422 423 if ((_flags & KIND_MASK) != 0) { 424 st->print("{"); 425 bool is_first = true; 426 427 for (int i = 0; data[i].flag != -1; i++) { 428 Data d = data[i]; 429 if ((_flags & d.flag) != 0) { 430 if (is_first) { 431 is_first = false; 432 } else { 433 st->print(" "); 434 } 435 st->print("%s", d.name); 436 } 437 } 438 439 st->print("}"); 440 } 441 } 442 443 void Flag::print_as_flag(outputStream* st) { 444 if (is_bool()) { 445 st->print("-XX:%s%s", get_bool() ? "+" : "-", _name); 446 } else if (is_int()) { 447 st->print("-XX:%s=%d", _name, get_int()); 448 } else if (is_uint()) { 449 st->print("-XX:%s=%u", _name, get_uint()); 450 } else if (is_intx()) { 451 st->print("-XX:%s=" INTX_FORMAT, _name, get_intx()); 452 } else if (is_uintx()) { 453 st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx()); 454 } else if (is_uint64_t()) { 455 st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t()); 456 } else if (is_size_t()) { 457 st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t()); 458 } else if (is_double()) { 459 st->print("-XX:%s=%f", _name, get_double()); 460 } else if (is_ccstr()) { 461 st->print("-XX:%s=", _name); 462 const char* cp = get_ccstr(); 463 if (cp != NULL) { 464 // Need to turn embedded '\n's back into separate arguments 465 // Not so efficient to print one character at a time, 466 // but the choice is to do the transformation to a buffer 467 // and print that. And this need not be efficient. 468 for (; *cp != '\0'; cp += 1) { 469 switch (*cp) { 470 default: 471 st->print("%c", *cp); 472 break; 473 case '\n': 474 st->print(" -XX:%s=", _name); 475 break; 476 } 477 } 478 } 479 } else { 480 ShouldNotReachHere(); 481 } 482 } 483 484 // 4991491 do not "optimize out" the was_set false values: omitting them 485 // tickles a Microsoft compiler bug causing flagTable to be malformed 486 487 #define NAME(name) NOT_PRODUCT(&name) PRODUCT_ONLY(&CONST_##name) 488 489 #define RUNTIME_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT) }, 490 #define RUNTIME_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 491 #define RUNTIME_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DIAGNOSTIC) }, 492 #define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_EXPERIMENTAL) }, 493 #define RUNTIME_MANAGEABLE_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_MANAGEABLE) }, 494 #define RUNTIME_PRODUCT_RW_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT | Flag::KIND_READ_WRITE) }, 495 #define RUNTIME_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP) }, 496 #define RUNTIME_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 497 #define RUNTIME_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_NOT_PRODUCT) }, 498 499 #ifdef _LP64 500 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_LP64_PRODUCT) }, 501 #else 502 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 503 #endif // _LP64 504 505 #define C1_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_PRODUCT) }, 506 #define C1_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 507 #define C1_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DIAGNOSTIC) }, 508 #define C1_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP) }, 509 #define C1_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 510 #define C1_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_NOT_PRODUCT) }, 511 512 #define C2_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT) }, 513 #define C2_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 514 #define C2_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DIAGNOSTIC) }, 515 #define C2_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_EXPERIMENTAL) }, 516 #define C2_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP) }, 517 #define C2_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 518 #define C2_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_NOT_PRODUCT) }, 519 520 #define ARCH_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_PRODUCT) }, 521 #define ARCH_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DIAGNOSTIC) }, 522 #define ARCH_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_EXPERIMENTAL) }, 523 #define ARCH_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DEVELOP) }, 524 #define ARCH_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_NOT_PRODUCT) }, 525 526 #define SHARK_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT) }, 527 #define SHARK_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 528 #define SHARK_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DIAGNOSTIC) }, 529 #define SHARK_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP) }, 530 #define SHARK_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 531 #define SHARK_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_NOT_PRODUCT) }, 532 533 static Flag flagTable[] = { 534 RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) 535 RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) 536 #if INCLUDE_ALL_GCS 537 G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) 538 #endif // INCLUDE_ALL_GCS 539 #ifdef COMPILER1 540 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) 541 #endif 542 #ifdef COMPILER2 543 C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT) 544 #endif 545 #ifdef SHARK 546 SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, SHARK_PD_DEVELOP_FLAG_STRUCT, SHARK_PRODUCT_FLAG_STRUCT, SHARK_PD_PRODUCT_FLAG_STRUCT, SHARK_DIAGNOSTIC_FLAG_STRUCT, SHARK_NOTPRODUCT_FLAG_STRUCT) 547 #endif 548 ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, ARCH_PRODUCT_FLAG_STRUCT, ARCH_DIAGNOSTIC_FLAG_STRUCT, ARCH_EXPERIMENTAL_FLAG_STRUCT, ARCH_NOTPRODUCT_FLAG_STRUCT) 549 FLAGTABLE_EXT 550 {0, NULL, NULL} 551 }; 552 553 Flag* Flag::flags = flagTable; 554 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag)); 555 556 inline bool str_equal(const char* s, const char* q, size_t len) { 557 // s is null terminated, q is not! 558 if (strlen(s) != (unsigned int) len) return false; 559 return strncmp(s, q, len) == 0; 560 } 561 562 // Search the flag table for a named flag 563 Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) { 564 for (Flag* current = &flagTable[0]; current->_name != NULL; current++) { 565 if (str_equal(current->_name, name, length)) { 566 // Found a matching entry. 567 // Don't report notproduct and develop flags in product builds. 568 if (current->is_constant_in_binary()) { 569 return (return_flag == true ? current : NULL); 570 } 571 // Report locked flags only if allowed. 572 if (!(current->is_unlocked() || current->is_unlocker())) { 573 if (!allow_locked) { 574 // disable use of locked flags, e.g. diagnostic, experimental, 575 // commercial... until they are explicitly unlocked 576 return NULL; 577 } 578 } 579 return current; 580 } 581 } 582 // Flag name is not in the flag table 583 return NULL; 584 } 585 586 // Compute string similarity based on Dice's coefficient 587 static float str_similar(const char* str1, const char* str2, size_t len2) { 588 int len1 = (int) strlen(str1); 589 int total = len1 + (int) len2; 590 591 int hit = 0; 592 593 for (int i = 0; i < len1 -1; ++i) { 594 for (int j = 0; j < (int) len2 -1; ++j) { 595 if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) { 596 ++hit; 597 break; 598 } 599 } 600 } 601 602 return 2.0f * (float) hit / (float) total; 603 } 604 605 Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) { 606 float VMOptionsFuzzyMatchSimilarity = 0.7f; 607 Flag* match = NULL; 608 float score; 609 float max_score = -1; 610 611 for (Flag* current = &flagTable[0]; current->_name != NULL; current++) { 612 score = str_similar(current->_name, name, length); 613 if (score > max_score) { 614 max_score = score; 615 match = current; 616 } 617 } 618 619 if (!(match->is_unlocked() || match->is_unlocker())) { 620 if (!allow_locked) { 621 return NULL; 622 } 623 } 624 625 if (max_score < VMOptionsFuzzyMatchSimilarity) { 626 return NULL; 627 } 628 629 return match; 630 } 631 632 // Returns the address of the index'th element 633 static Flag* address_of_flag(CommandLineFlagWithType flag) { 634 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 635 return &Flag::flags[flag]; 636 } 637 638 bool CommandLineFlagsEx::is_default(CommandLineFlag flag) { 639 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 640 Flag* f = &Flag::flags[flag]; 641 return f->is_default(); 642 } 643 644 bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) { 645 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 646 Flag* f = &Flag::flags[flag]; 647 return f->is_ergonomic(); 648 } 649 650 bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) { 651 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 652 Flag* f = &Flag::flags[flag]; 653 return f->is_command_line(); 654 } 655 656 bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) { 657 Flag* result = Flag::find_flag((char*)name, strlen(name)); 658 if (result == NULL) return false; 659 *value = result->is_command_line(); 660 return true; 661 } 662 663 template<class E, class T> 664 static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin) 665 { 666 E e; 667 e.set_name(name); 668 e.set_old_value(old_value); 669 e.set_new_value(new_value); 670 e.set_origin(origin); 671 e.commit(); 672 } 673 674 bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) { 675 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 676 if (result == NULL) return false; 677 if (!result->is_bool()) return false; 678 *value = result->get_bool(); 679 return true; 680 } 681 682 bool CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) { 683 Flag* result = Flag::find_flag(name, len); 684 if (result == NULL) return false; 685 if (!result->is_bool()) return false; 686 bool old_value = result->get_bool(); 687 trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin); 688 result->set_bool(*value); 689 *value = old_value; 690 result->set_origin(origin); 691 return true; 692 } 693 694 void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) { 695 Flag* faddr = address_of_flag(flag); 696 guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type"); 697 trace_flag_changed<EventBooleanFlagChanged, bool>(faddr->_name, faddr->get_bool(), value, origin); 698 faddr->set_bool(value); 699 faddr->set_origin(origin); 700 } 701 702 bool CommandLineFlags::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) { 703 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 704 if (result == NULL) return false; 705 if (!result->is_int()) return false; 706 *value = result->get_int(); 707 return true; 708 } 709 710 bool CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) { 711 Flag* result = Flag::find_flag(name, len); 712 if (result == NULL) return false; 713 if (!result->is_int()) return false; 714 int old_value = result->get_int(); 715 trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin); 716 result->set_int(*value); 717 *value = old_value; 718 result->set_origin(origin); 719 return true; 720 } 721 722 void CommandLineFlagsEx::intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin) { 723 Flag* faddr = address_of_flag(flag); 724 guarantee(faddr != NULL && faddr->is_int(), "wrong flag type"); 725 trace_flag_changed<EventIntFlagChanged, s4>(faddr->_name, faddr->get_int(), value, origin); 726 faddr->set_int(value); 727 faddr->set_origin(origin); 728 } 729 730 bool CommandLineFlags::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) { 731 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 732 if (result == NULL) return false; 733 if (!result->is_uint()) return false; 734 *value = result->get_uint(); 735 return true; 736 } 737 738 bool CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) { 739 Flag* result = Flag::find_flag(name, len); 740 if (result == NULL) return false; 741 if (!result->is_uint()) return false; 742 uint old_value = result->get_uint(); 743 trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin); 744 result->set_uint(*value); 745 *value = old_value; 746 result->set_origin(origin); 747 return true; 748 } 749 750 void CommandLineFlagsEx::uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin) { 751 Flag* faddr = address_of_flag(flag); 752 guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type"); 753 trace_flag_changed<EventUnsignedIntFlagChanged, u4>(faddr->_name, faddr->get_uint(), value, origin); 754 faddr->set_uint(value); 755 faddr->set_origin(origin); 756 } 757 758 bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) { 759 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 760 if (result == NULL) return false; 761 if (!result->is_intx()) return false; 762 *value = result->get_intx(); 763 return true; 764 } 765 766 bool CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) { 767 Flag* result = Flag::find_flag(name, len); 768 if (result == NULL) return false; 769 if (!result->is_intx()) return false; 770 intx old_value = result->get_intx(); 771 trace_flag_changed<EventLongFlagChanged, s8>(name, old_value, *value, origin); 772 result->set_intx(*value); 773 *value = old_value; 774 result->set_origin(origin); 775 return true; 776 } 777 778 void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) { 779 Flag* faddr = address_of_flag(flag); 780 guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type"); 781 trace_flag_changed<EventLongFlagChanged, s8>(faddr->_name, faddr->get_intx(), value, origin); 782 faddr->set_intx(value); 783 faddr->set_origin(origin); 784 } 785 786 bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) { 787 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 788 if (result == NULL) return false; 789 if (!result->is_uintx()) return false; 790 *value = result->get_uintx(); 791 return true; 792 } 793 794 bool CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) { 795 Flag* result = Flag::find_flag(name, len); 796 if (result == NULL) return false; 797 if (!result->is_uintx()) return false; 798 uintx old_value = result->get_uintx(); 799 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin); 800 result->set_uintx(*value); 801 *value = old_value; 802 result->set_origin(origin); 803 return true; 804 } 805 806 void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) { 807 Flag* faddr = address_of_flag(flag); 808 guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type"); 809 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uintx(), value, origin); 810 faddr->set_uintx(value); 811 faddr->set_origin(origin); 812 } 813 814 bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) { 815 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 816 if (result == NULL) return false; 817 if (!result->is_uint64_t()) return false; 818 *value = result->get_uint64_t(); 819 return true; 820 } 821 822 bool CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) { 823 Flag* result = Flag::find_flag(name, len); 824 if (result == NULL) return false; 825 if (!result->is_uint64_t()) return false; 826 uint64_t old_value = result->get_uint64_t(); 827 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin); 828 result->set_uint64_t(*value); 829 *value = old_value; 830 result->set_origin(origin); 831 return true; 832 } 833 834 void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) { 835 Flag* faddr = address_of_flag(flag); 836 guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type"); 837 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uint64_t(), value, origin); 838 faddr->set_uint64_t(value); 839 faddr->set_origin(origin); 840 } 841 842 bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) { 843 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 844 if (result == NULL) return false; 845 if (!result->is_size_t()) return false; 846 *value = result->get_size_t(); 847 return true; 848 } 849 850 bool CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) { 851 Flag* result = Flag::find_flag(name, len); 852 if (result == NULL) return false; 853 if (!result->is_size_t()) return false; 854 size_t old_value = result->get_size_t(); 855 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin); 856 result->set_size_t(*value); 857 *value = old_value; 858 result->set_origin(origin); 859 return true; 860 } 861 862 void CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) { 863 Flag* faddr = address_of_flag(flag); 864 guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type"); 865 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_size_t(), value, origin); 866 faddr->set_size_t(value); 867 faddr->set_origin(origin); 868 } 869 870 bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) { 871 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 872 if (result == NULL) return false; 873 if (!result->is_double()) return false; 874 *value = result->get_double(); 875 return true; 876 } 877 878 bool CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) { 879 Flag* result = Flag::find_flag(name, len); 880 if (result == NULL) return false; 881 if (!result->is_double()) return false; 882 double old_value = result->get_double(); 883 trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin); 884 result->set_double(*value); 885 *value = old_value; 886 result->set_origin(origin); 887 return true; 888 } 889 890 void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) { 891 Flag* faddr = address_of_flag(flag); 892 guarantee(faddr != NULL && faddr->is_double(), "wrong flag type"); 893 trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin); 894 faddr->set_double(value); 895 faddr->set_origin(origin); 896 } 897 898 bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) { 899 Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); 900 if (result == NULL) return false; 901 if (!result->is_ccstr()) return false; 902 *value = result->get_ccstr(); 903 return true; 904 } 905 906 bool CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) { 907 Flag* result = Flag::find_flag(name, len); 908 if (result == NULL) return false; 909 if (!result->is_ccstr()) return false; 910 ccstr old_value = result->get_ccstr(); 911 trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin); 912 char* new_value = NULL; 913 if (*value != NULL) { 914 new_value = os::strdup_check_oom(*value); 915 } 916 result->set_ccstr(new_value); 917 if (result->is_default() && old_value != NULL) { 918 // Prior value is NOT heap allocated, but was a literal constant. 919 old_value = os::strdup_check_oom(old_value); 920 } 921 *value = old_value; 922 result->set_origin(origin); 923 return true; 924 } 925 926 void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) { 927 Flag* faddr = address_of_flag(flag); 928 guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type"); 929 ccstr old_value = faddr->get_ccstr(); 930 trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin); 931 char* new_value = os::strdup_check_oom(value); 932 faddr->set_ccstr(new_value); 933 if (!faddr->is_default() && old_value != NULL) { 934 // Prior value is heap allocated so free it. 935 FREE_C_HEAP_ARRAY(char, old_value); 936 } 937 faddr->set_origin(origin); 938 } 939 940 extern "C" { 941 static int compare_flags(const void* void_a, const void* void_b) { 942 return strcmp((*((Flag**) void_a))->_name, (*((Flag**) void_b))->_name); 943 } 944 } 945 946 void CommandLineFlags::printSetFlags(outputStream* out) { 947 // Print which flags were set on the command line 948 // note: this method is called before the thread structure is in place 949 // which means resource allocation cannot be used. 950 951 // The last entry is the null entry. 952 const size_t length = Flag::numFlags - 1; 953 954 // Sort 955 Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); 956 for (size_t i = 0; i < length; i++) { 957 array[i] = &flagTable[i]; 958 } 959 qsort(array, length, sizeof(Flag*), compare_flags); 960 961 // Print 962 for (size_t i = 0; i < length; i++) { 963 if (array[i]->get_origin() /* naked field! */) { 964 array[i]->print_as_flag(out); 965 out->print(" "); 966 } 967 } 968 out->cr(); 969 FREE_C_HEAP_ARRAY(Flag*, array); 970 } 971 972 #ifndef PRODUCT 973 974 975 void CommandLineFlags::verify() { 976 assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict"); 977 } 978 979 #endif // PRODUCT 980 981 void CommandLineFlags::printFlags(outputStream* out, bool withComments) { 982 // Print the flags sorted by name 983 // note: this method is called before the thread structure is in place 984 // which means resource allocation cannot be used. 985 986 // The last entry is the null entry. 987 const size_t length = Flag::numFlags - 1; 988 989 // Sort 990 Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); 991 for (size_t i = 0; i < length; i++) { 992 array[i] = &flagTable[i]; 993 } 994 qsort(array, length, sizeof(Flag*), compare_flags); 995 996 // Print 997 out->print_cr("[Global flags]"); 998 for (size_t i = 0; i < length; i++) { 999 if (array[i]->is_unlocked()) { 1000 array[i]->print_on(out, withComments); 1001 } 1002 } 1003 FREE_C_HEAP_ARRAY(Flag*, array); 1004 }