globals.cpp revision 196:d1605aabd0a1
1/*
2 * Copyright 1997-2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_globals.cpp.incl"
27
28
29RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
30              MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
31              MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG, \
32              MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \
33              MATERIALIZE_LP64_PRODUCT_FLAG)
34
35RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
36                 MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
37                 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
38
39bool Flag::is_unlocker() const {
40  return strcmp(name, "UnlockDiagnosticVMOptions") == 0;
41}
42
43bool Flag::is_unlocked() const {
44  if (strcmp(kind, "{diagnostic}") == 0) {
45    return UnlockDiagnosticVMOptions;
46  } else {
47    return true;
48  }
49}
50
51bool Flag::is_writeable() const {
52  return (strcmp(kind, "{manageable}") == 0 || strcmp(kind, "{product rw}") == 0);
53}
54
55// All flags except "manageable" are assumed internal flags.
56// Long term, we need to define a mechanism to specify which flags
57// are external/stable and change this function accordingly.
58bool Flag::is_external() const {
59  return (strcmp(kind, "{manageable}") == 0);
60}
61
62// Length of format string (e.g. "%.1234s") for printing ccstr below
63#define FORMAT_BUFFER_LEN 16
64
65void Flag::print_on(outputStream* st) {
66  st->print("%5s %-35s %c= ", type, name, (origin != DEFAULT ? ':' : ' '));
67  if (is_bool())  st->print("%-16s", get_bool() ? "true" : "false");
68  if (is_intx())  st->print("%-16ld", get_intx());
69  if (is_uintx()) st->print("%-16lu", get_uintx());
70  if (is_ccstr()) {
71    const char* cp = get_ccstr();
72    if (cp != NULL) {
73      const char* eol;
74      while ((eol = strchr(cp, '\n')) != NULL) {
75        char format_buffer[FORMAT_BUFFER_LEN];
76        size_t llen = pointer_delta(eol, cp, sizeof(char));
77        jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
78                     "%%." SIZE_FORMAT "s", llen);
79        st->print(format_buffer, cp);
80        st->cr();
81        cp = eol+1;
82        st->print("%5s %-35s += ", "", name);
83      }
84      st->print("%-16s", cp);
85    }
86  }
87  st->print(" %s", kind);
88  st->cr();
89}
90
91void Flag::print_as_flag(outputStream* st) {
92  if (is_bool()) {
93    st->print("-XX:%s%s", get_bool() ? "+" : "-", name);
94  } else if (is_intx()) {
95    st->print("-XX:%s=" INTX_FORMAT, name, get_intx());
96  } else if (is_uintx()) {
97    st->print("-XX:%s=" UINTX_FORMAT, name, get_uintx());
98  } else if (is_ccstr()) {
99    st->print("-XX:%s=", name);
100    const char* cp = get_ccstr();
101    if (cp != NULL) {
102      // Need to turn embedded '\n's back into separate arguments
103      // Not so efficient to print one character at a time,
104      // but the choice is to do the transformation to a buffer
105      // and print that.  And this need not be efficient.
106      for (; *cp != '\0'; cp += 1) {
107        switch (*cp) {
108          default:
109            st->print("%c", *cp);
110            break;
111          case '\n':
112            st->print(" -XX:%s=", name);
113            break;
114        }
115      }
116    }
117  } else {
118    ShouldNotReachHere();
119  }
120}
121
122// 4991491 do not "optimize out" the was_set false values: omitting them
123// tickles a Microsoft compiler bug causing flagTable to be malformed
124
125#define RUNTIME_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{product}", DEFAULT },
126#define RUNTIME_PD_PRODUCT_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{pd product}", DEFAULT },
127#define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{diagnostic}", DEFAULT },
128#define RUNTIME_MANAGEABLE_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{manageable}", DEFAULT },
129#define RUNTIME_PRODUCT_RW_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{product rw}", DEFAULT },
130
131#ifdef PRODUCT
132  #define RUNTIME_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
133  #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     /* flag is constant */
134  #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc)
135#else
136  #define RUNTIME_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "", DEFAULT },
137  #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{pd}", DEFAULT },
138  #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{notproduct}", DEFAULT },
139#endif
140
141#ifdef _LP64
142  #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{lp64_product}", DEFAULT },
143#else
144  #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
145#endif // _LP64
146
147#define C1_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C1 product}", DEFAULT },
148#define C1_PD_PRODUCT_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{C1 pd product}", DEFAULT },
149#ifdef PRODUCT
150  #define C1_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
151  #define C1_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     /* flag is constant */
152  #define C1_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc)
153#else
154  #define C1_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C1}", DEFAULT },
155  #define C1_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{C1 pd}", DEFAULT },
156  #define C1_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C1 notproduct}", DEFAULT },
157#endif
158
159
160#define C2_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 product}", DEFAULT },
161#define C2_PD_PRODUCT_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{C2 pd product}", DEFAULT },
162#define C2_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 diagnostic}", DEFAULT },
163#ifdef PRODUCT
164  #define C2_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
165  #define C2_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     /* flag is constant */
166  #define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc)
167#else
168  #define C2_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2}", DEFAULT },
169  #define C2_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{C2 pd}", DEFAULT },
170  #define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 notproduct}", DEFAULT },
171#endif
172
173
174static Flag flagTable[] = {
175 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_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT)
176 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)
177#ifdef COMPILER1
178 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
179#endif
180#ifdef COMPILER2
181 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_NOTPRODUCT_FLAG_STRUCT)
182#endif
183 {0, NULL, NULL}
184};
185
186Flag* Flag::flags = flagTable;
187size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
188
189inline bool str_equal(const char* s, char* q, size_t len) {
190  // s is null terminated, q is not!
191  if (strlen(s) != (unsigned int) len) return false;
192  return strncmp(s, q, len) == 0;
193}
194
195Flag* Flag::find_flag(char* name, size_t length) {
196  for (Flag* current = &flagTable[0]; current->name; current++) {
197    if (str_equal(current->name, name, length)) {
198      if (!(current->is_unlocked() || current->is_unlocker())) {
199        // disable use of diagnostic flags until they are unlocked
200        return NULL;
201      }
202      return current;
203    }
204  }
205  return NULL;
206}
207
208// Returns the address of the index'th element
209static Flag* address_of_flag(CommandLineFlagWithType flag) {
210  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
211  return &Flag::flags[flag];
212}
213
214bool CommandLineFlagsEx::is_default(CommandLineFlag flag) {
215  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
216  Flag* f = &Flag::flags[flag];
217  return (f->origin == DEFAULT);
218}
219
220bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) {
221  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
222  Flag* f = &Flag::flags[flag];
223  return (f->origin == ERGONOMIC);
224}
225
226bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) {
227  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
228  Flag* f = &Flag::flags[flag];
229  return (f->origin == COMMAND_LINE);
230}
231
232bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
233  Flag* result = Flag::find_flag((char*)name, strlen(name));
234  if (result == NULL) return false;
235  *value = (result->origin == COMMAND_LINE);
236  return true;
237}
238
239bool CommandLineFlags::boolAt(char* name, size_t len, bool* value) {
240  Flag* result = Flag::find_flag(name, len);
241  if (result == NULL) return false;
242  if (!result->is_bool()) return false;
243  *value = result->get_bool();
244  return true;
245}
246
247bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, FlagValueOrigin origin) {
248  Flag* result = Flag::find_flag(name, len);
249  if (result == NULL) return false;
250  if (!result->is_bool()) return false;
251  bool old_value = result->get_bool();
252  result->set_bool(*value);
253  *value = old_value;
254  result->origin = origin;
255  return true;
256}
257
258void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, FlagValueOrigin origin) {
259  Flag* faddr = address_of_flag(flag);
260  guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
261  faddr->set_bool(value);
262  faddr->origin = origin;
263}
264
265bool CommandLineFlags::intxAt(char* name, size_t len, intx* value) {
266  Flag* result = Flag::find_flag(name, len);
267  if (result == NULL) return false;
268  if (!result->is_intx()) return false;
269  *value = result->get_intx();
270  return true;
271}
272
273bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, FlagValueOrigin origin) {
274  Flag* result = Flag::find_flag(name, len);
275  if (result == NULL) return false;
276  if (!result->is_intx()) return false;
277  intx old_value = result->get_intx();
278  result->set_intx(*value);
279  *value = old_value;
280  result->origin = origin;
281  return true;
282}
283
284void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, FlagValueOrigin origin) {
285  Flag* faddr = address_of_flag(flag);
286  guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
287  faddr->set_intx(value);
288  faddr->origin = origin;
289}
290
291bool CommandLineFlags::uintxAt(char* name, size_t len, uintx* value) {
292  Flag* result = Flag::find_flag(name, len);
293  if (result == NULL) return false;
294  if (!result->is_uintx()) return false;
295  *value = result->get_uintx();
296  return true;
297}
298
299bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, FlagValueOrigin origin) {
300  Flag* result = Flag::find_flag(name, len);
301  if (result == NULL) return false;
302  if (!result->is_uintx()) return false;
303  uintx old_value = result->get_uintx();
304  result->set_uintx(*value);
305  *value = old_value;
306  result->origin = origin;
307  return true;
308}
309
310void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, FlagValueOrigin origin) {
311  Flag* faddr = address_of_flag(flag);
312  guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
313  faddr->set_uintx(value);
314  faddr->origin = origin;
315}
316
317bool CommandLineFlags::doubleAt(char* name, size_t len, double* value) {
318  Flag* result = Flag::find_flag(name, len);
319  if (result == NULL) return false;
320  if (!result->is_double()) return false;
321  *value = result->get_double();
322  return true;
323}
324
325bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, FlagValueOrigin origin) {
326  Flag* result = Flag::find_flag(name, len);
327  if (result == NULL) return false;
328  if (!result->is_double()) return false;
329  double old_value = result->get_double();
330  result->set_double(*value);
331  *value = old_value;
332  result->origin = origin;
333  return true;
334}
335
336void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, FlagValueOrigin origin) {
337  Flag* faddr = address_of_flag(flag);
338  guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
339  faddr->set_double(value);
340  faddr->origin = origin;
341}
342
343bool CommandLineFlags::ccstrAt(char* name, size_t len, ccstr* value) {
344  Flag* result = Flag::find_flag(name, len);
345  if (result == NULL) return false;
346  if (!result->is_ccstr()) return false;
347  *value = result->get_ccstr();
348  return true;
349}
350
351// Contract:  Flag will make private copy of the incoming value.
352// Outgoing value is always malloc-ed, and caller MUST call free.
353bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, FlagValueOrigin origin) {
354  Flag* result = Flag::find_flag(name, len);
355  if (result == NULL) return false;
356  if (!result->is_ccstr()) return false;
357  ccstr old_value = result->get_ccstr();
358  char* new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1);
359  strcpy(new_value, *value);
360  result->set_ccstr(new_value);
361  if (result->origin == DEFAULT && old_value != NULL) {
362    // Prior value is NOT heap allocated, but was a literal constant.
363    char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1);
364    strcpy(old_value_to_free, old_value);
365    old_value = old_value_to_free;
366  }
367  *value = old_value;
368  result->origin = origin;
369  return true;
370}
371
372// Contract:  Flag will make private copy of the incoming value.
373void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, FlagValueOrigin origin) {
374  Flag* faddr = address_of_flag(flag);
375  guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
376  ccstr old_value = faddr->get_ccstr();
377  char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1);
378  strcpy(new_value, value);
379  faddr->set_ccstr(new_value);
380  if (faddr->origin != DEFAULT && old_value != NULL) {
381    // Prior value is heap allocated so free it.
382    FREE_C_HEAP_ARRAY(char, old_value);
383  }
384  faddr->origin = origin;
385}
386
387extern "C" {
388  static int compare_flags(const void* void_a, const void* void_b) {
389    return strcmp((*((Flag**) void_a))->name, (*((Flag**) void_b))->name);
390  }
391}
392
393void CommandLineFlags::printSetFlags() {
394  // Print which flags were set on the command line
395  // note: this method is called before the thread structure is in place
396  //       which means resource allocation cannot be used.
397
398  // Compute size
399  int length= 0;
400  while (flagTable[length].name != NULL) length++;
401
402  // Sort
403  Flag** array = NEW_C_HEAP_ARRAY(Flag*, length);
404  for (int index = 0; index < length; index++) {
405    array[index] = &flagTable[index];
406  }
407  qsort(array, length, sizeof(Flag*), compare_flags);
408
409  // Print
410  for (int i = 0; i < length; i++) {
411    if (array[i]->origin /* naked field! */) {
412      array[i]->print_as_flag(tty);
413      tty->print(" ");
414    }
415  }
416  tty->cr();
417  FREE_C_HEAP_ARRAY(Flag*, array);
418}
419
420#ifndef PRODUCT
421
422
423void CommandLineFlags::verify() {
424  assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
425}
426
427void CommandLineFlags::printFlags() {
428  // Print the flags sorted by name
429  // note: this method is called before the thread structure is in place
430  //       which means resource allocation cannot be used.
431
432  // Compute size
433  int length= 0;
434  while (flagTable[length].name != NULL) length++;
435
436  // Sort
437  Flag** array = NEW_C_HEAP_ARRAY(Flag*, length);
438  for (int index = 0; index < length; index++) {
439    array[index] = &flagTable[index];
440  }
441  qsort(array, length, sizeof(Flag*), compare_flags);
442
443  // Print
444  tty->print_cr("[Global flags]");
445  for (int i = 0; i < length; i++) {
446    if (array[i]->is_unlocked()) {
447      array[i]->print_on(tty);
448    }
449  }
450  FREE_C_HEAP_ARRAY(Flag*, array);
451}
452
453#endif
454