V8 Project
flags.cc
Go to the documentation of this file.
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <ctype.h>
6 #include <stdlib.h>
7 
8 #include "src/v8.h"
9 
10 #include "src/assembler.h"
12 #include "src/ostreams.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // Define all of our flags.
18 #define FLAG_MODE_DEFINE
19 #include "src/flag-definitions.h" // NOLINT
20 
21 // Define all of our flags default values.
22 #define FLAG_MODE_DEFINE_DEFAULTS
23 #include "src/flag-definitions.h" // NOLINT
24 
25 namespace {
26 
27 // This structure represents a single entry in the flag system, with a pointer
28 // to the actual flag, default value, comment, etc. This is designed to be POD
29 // initialized as to avoid requiring static constructors.
30 struct Flag {
31  enum FlagType { TYPE_BOOL, TYPE_MAYBE_BOOL, TYPE_INT, TYPE_FLOAT,
32  TYPE_STRING, TYPE_ARGS };
33 
34  FlagType type_; // What type of flag, bool, int, or string.
35  const char* name_; // Name of the flag, ex "my_flag".
36  void* valptr_; // Pointer to the global flag variable.
37  const void* defptr_; // Pointer to the default value.
38  const char* cmt_; // A comment about the flags purpose.
39  bool owns_ptr_; // Does the flag own its string value?
40 
41  FlagType type() const { return type_; }
42 
43  const char* name() const { return name_; }
44 
45  const char* comment() const { return cmt_; }
46 
47  bool* bool_variable() const {
48  DCHECK(type_ == TYPE_BOOL);
49  return reinterpret_cast<bool*>(valptr_);
50  }
51 
52  MaybeBoolFlag* maybe_bool_variable() const {
53  DCHECK(type_ == TYPE_MAYBE_BOOL);
54  return reinterpret_cast<MaybeBoolFlag*>(valptr_);
55  }
56 
57  int* int_variable() const {
58  DCHECK(type_ == TYPE_INT);
59  return reinterpret_cast<int*>(valptr_);
60  }
61 
62  double* float_variable() const {
63  DCHECK(type_ == TYPE_FLOAT);
64  return reinterpret_cast<double*>(valptr_);
65  }
66 
67  const char* string_value() const {
68  DCHECK(type_ == TYPE_STRING);
69  return *reinterpret_cast<const char**>(valptr_);
70  }
71 
72  void set_string_value(const char* value, bool owns_ptr) {
73  DCHECK(type_ == TYPE_STRING);
74  const char** ptr = reinterpret_cast<const char**>(valptr_);
75  if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
76  *ptr = value;
77  owns_ptr_ = owns_ptr;
78  }
79 
80  JSArguments* args_variable() const {
81  DCHECK(type_ == TYPE_ARGS);
82  return reinterpret_cast<JSArguments*>(valptr_);
83  }
84 
85  bool bool_default() const {
86  DCHECK(type_ == TYPE_BOOL);
87  return *reinterpret_cast<const bool*>(defptr_);
88  }
89 
90  int int_default() const {
91  DCHECK(type_ == TYPE_INT);
92  return *reinterpret_cast<const int*>(defptr_);
93  }
94 
95  double float_default() const {
96  DCHECK(type_ == TYPE_FLOAT);
97  return *reinterpret_cast<const double*>(defptr_);
98  }
99 
100  const char* string_default() const {
101  DCHECK(type_ == TYPE_STRING);
102  return *reinterpret_cast<const char* const *>(defptr_);
103  }
104 
105  JSArguments args_default() const {
106  DCHECK(type_ == TYPE_ARGS);
107  return *reinterpret_cast<const JSArguments*>(defptr_);
108  }
109 
110  // Compare this flag's current value against the default.
111  bool IsDefault() const {
112  switch (type_) {
113  case TYPE_BOOL:
114  return *bool_variable() == bool_default();
115  case TYPE_MAYBE_BOOL:
116  return maybe_bool_variable()->has_value == false;
117  case TYPE_INT:
118  return *int_variable() == int_default();
119  case TYPE_FLOAT:
120  return *float_variable() == float_default();
121  case TYPE_STRING: {
122  const char* str1 = string_value();
123  const char* str2 = string_default();
124  if (str2 == NULL) return str1 == NULL;
125  if (str1 == NULL) return str2 == NULL;
126  return strcmp(str1, str2) == 0;
127  }
128  case TYPE_ARGS:
129  return args_variable()->argc == 0;
130  }
131  UNREACHABLE();
132  return true;
133  }
134 
135  // Set a flag back to it's default value.
136  void Reset() {
137  switch (type_) {
138  case TYPE_BOOL:
139  *bool_variable() = bool_default();
140  break;
141  case TYPE_MAYBE_BOOL:
142  *maybe_bool_variable() = MaybeBoolFlag::Create(false, false);
143  break;
144  case TYPE_INT:
145  *int_variable() = int_default();
146  break;
147  case TYPE_FLOAT:
148  *float_variable() = float_default();
149  break;
150  case TYPE_STRING:
151  set_string_value(string_default(), false);
152  break;
153  case TYPE_ARGS:
154  *args_variable() = args_default();
155  break;
156  }
157  }
158 };
159 
160 Flag flags[] = {
161 #define FLAG_MODE_META
162 #include "src/flag-definitions.h"
163 };
164 
165 const size_t num_flags = sizeof(flags) / sizeof(*flags);
166 
167 } // namespace
168 
169 
170 static const char* Type2String(Flag::FlagType type) {
171  switch (type) {
172  case Flag::TYPE_BOOL: return "bool";
173  case Flag::TYPE_MAYBE_BOOL: return "maybe_bool";
174  case Flag::TYPE_INT: return "int";
175  case Flag::TYPE_FLOAT: return "float";
176  case Flag::TYPE_STRING: return "string";
177  case Flag::TYPE_ARGS: return "arguments";
178  }
179  UNREACHABLE();
180  return NULL;
181 }
182 
183 
184 OStream& operator<<(OStream& os, const Flag& flag) { // NOLINT
185  switch (flag.type()) {
186  case Flag::TYPE_BOOL:
187  os << (*flag.bool_variable() ? "true" : "false");
188  break;
189  case Flag::TYPE_MAYBE_BOOL:
190  os << (flag.maybe_bool_variable()->has_value
191  ? (flag.maybe_bool_variable()->value ? "true" : "false")
192  : "unset");
193  break;
194  case Flag::TYPE_INT:
195  os << *flag.int_variable();
196  break;
197  case Flag::TYPE_FLOAT:
198  os << *flag.float_variable();
199  break;
200  case Flag::TYPE_STRING: {
201  const char* str = flag.string_value();
202  os << (str ? str : "NULL");
203  break;
204  }
205  case Flag::TYPE_ARGS: {
206  JSArguments args = *flag.args_variable();
207  if (args.argc > 0) {
208  os << args[0];
209  for (int i = 1; i < args.argc; i++) {
210  os << args[i];
211  }
212  }
213  break;
214  }
215  }
216  return os;
217 }
218 
219 
220 // static
222  List<const char*>* args = new List<const char*>(8);
223  Flag* args_flag = NULL;
224  for (size_t i = 0; i < num_flags; ++i) {
225  Flag* f = &flags[i];
226  if (!f->IsDefault()) {
227  if (f->type() == Flag::TYPE_ARGS) {
228  DCHECK(args_flag == NULL);
229  args_flag = f; // Must be last in arguments.
230  continue;
231  }
232  {
233  bool disabled = f->type() == Flag::TYPE_BOOL && !*f->bool_variable();
234  OStringStream os;
235  os << (disabled ? "--no" : "--") << f->name();
236  args->Add(StrDup(os.c_str()));
237  }
238  if (f->type() != Flag::TYPE_BOOL) {
239  OStringStream os;
240  os << *f;
241  args->Add(StrDup(os.c_str()));
242  }
243  }
244  }
245  if (args_flag != NULL) {
246  OStringStream os;
247  os << "--" << args_flag->name();
248  args->Add(StrDup(os.c_str()));
249  JSArguments jsargs = *args_flag->args_variable();
250  for (int j = 0; j < jsargs.argc; j++) {
251  args->Add(StrDup(jsargs[j]));
252  }
253  }
254  return args;
255 }
256 
257 
258 inline char NormalizeChar(char ch) {
259  return ch == '_' ? '-' : ch;
260 }
261 
262 
263 // Helper function to parse flags: Takes an argument arg and splits it into
264 // a flag name and flag value (or NULL if they are missing). is_bool is set
265 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
266 // terminate the name, it must be large enough to hold any possible name.
267 static void SplitArgument(const char* arg,
268  char* buffer,
269  int buffer_size,
270  const char** name,
271  const char** value,
272  bool* is_bool) {
273  *name = NULL;
274  *value = NULL;
275  *is_bool = false;
276 
277  if (arg != NULL && *arg == '-') {
278  // find the begin of the flag name
279  arg++; // remove 1st '-'
280  if (*arg == '-') {
281  arg++; // remove 2nd '-'
282  if (arg[0] == '\0') {
283  const char* kJSArgumentsFlagName = "js_arguments";
284  *name = kJSArgumentsFlagName;
285  return;
286  }
287  }
288  if (arg[0] == 'n' && arg[1] == 'o') {
289  arg += 2; // remove "no"
290  if (NormalizeChar(arg[0]) == '-') arg++; // remove dash after "no".
291  *is_bool = true;
292  }
293  *name = arg;
294 
295  // find the end of the flag name
296  while (*arg != '\0' && *arg != '=')
297  arg++;
298 
299  // get the value if any
300  if (*arg == '=') {
301  // make a copy so we can NUL-terminate flag name
302  size_t n = arg - *name;
303  CHECK(n < static_cast<size_t>(buffer_size)); // buffer is too small
304  MemCopy(buffer, *name, n);
305  buffer[n] = '\0';
306  *name = buffer;
307  // get the value
308  *value = arg + 1;
309  }
310  }
311 }
312 
313 
314 static bool EqualNames(const char* a, const char* b) {
315  for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
316  if (a[i] == '\0') {
317  return true;
318  }
319  }
320  return false;
321 }
322 
323 
324 static Flag* FindFlag(const char* name) {
325  for (size_t i = 0; i < num_flags; ++i) {
326  if (EqualNames(name, flags[i].name()))
327  return &flags[i];
328  }
329  return NULL;
330 }
331 
332 
333 // static
335  char** argv,
336  bool remove_flags) {
337  int return_code = 0;
338  // parse arguments
339  for (int i = 1; i < *argc;) {
340  int j = i; // j > 0
341  const char* arg = argv[i++];
342 
343  // split arg into flag components
344  char buffer[1*KB];
345  const char* name;
346  const char* value;
347  bool is_bool;
348  SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
349 
350  if (name != NULL) {
351  // lookup the flag
352  Flag* flag = FindFlag(name);
353  if (flag == NULL) {
354  if (remove_flags) {
355  // We don't recognize this flag but since we're removing
356  // the flags we recognize we assume that the remaining flags
357  // will be processed somewhere else so this flag might make
358  // sense there.
359  continue;
360  } else {
361  PrintF(stderr, "Error: unrecognized flag %s\n"
362  "Try --help for options\n", arg);
363  return_code = j;
364  break;
365  }
366  }
367 
368  // if we still need a flag value, use the next argument if available
369  if (flag->type() != Flag::TYPE_BOOL &&
370  flag->type() != Flag::TYPE_MAYBE_BOOL &&
371  flag->type() != Flag::TYPE_ARGS &&
372  value == NULL) {
373  if (i < *argc) {
374  value = argv[i++];
375  }
376  if (!value) {
377  PrintF(stderr, "Error: missing value for flag %s of type %s\n"
378  "Try --help for options\n",
379  arg, Type2String(flag->type()));
380  return_code = j;
381  break;
382  }
383  }
384 
385  // set the flag
386  char* endp = const_cast<char*>(""); // *endp is only read
387  switch (flag->type()) {
388  case Flag::TYPE_BOOL:
389  *flag->bool_variable() = !is_bool;
390  break;
391  case Flag::TYPE_MAYBE_BOOL:
392  *flag->maybe_bool_variable() = MaybeBoolFlag::Create(true, !is_bool);
393  break;
394  case Flag::TYPE_INT:
395  *flag->int_variable() = strtol(value, &endp, 10); // NOLINT
396  break;
397  case Flag::TYPE_FLOAT:
398  *flag->float_variable() = strtod(value, &endp);
399  break;
400  case Flag::TYPE_STRING:
401  flag->set_string_value(value ? StrDup(value) : NULL, true);
402  break;
403  case Flag::TYPE_ARGS: {
404  int start_pos = (value == NULL) ? i : i - 1;
405  int js_argc = *argc - start_pos;
406  const char** js_argv = NewArray<const char*>(js_argc);
407  if (value != NULL) {
408  js_argv[0] = StrDup(value);
409  }
410  for (int k = i; k < *argc; k++) {
411  js_argv[k - start_pos] = StrDup(argv[k]);
412  }
413  *flag->args_variable() = JSArguments::Create(js_argc, js_argv);
414  i = *argc; // Consume all arguments
415  break;
416  }
417  }
418 
419  // handle errors
420  bool is_bool_type = flag->type() == Flag::TYPE_BOOL ||
421  flag->type() == Flag::TYPE_MAYBE_BOOL;
422  if ((is_bool_type && value != NULL) || (!is_bool_type && is_bool) ||
423  *endp != '\0') {
424  PrintF(stderr, "Error: illegal value for flag %s of type %s\n"
425  "Try --help for options\n",
426  arg, Type2String(flag->type()));
427  return_code = j;
428  break;
429  }
430 
431  // remove the flag & value from the command
432  if (remove_flags) {
433  while (j < i) {
434  argv[j++] = NULL;
435  }
436  }
437  }
438  }
439 
440  // shrink the argument list
441  if (remove_flags) {
442  int j = 1;
443  for (int i = 1; i < *argc; i++) {
444  if (argv[i] != NULL)
445  argv[j++] = argv[i];
446  }
447  *argc = j;
448  }
449 
450  if (FLAG_help) {
451  PrintHelp();
452  exit(0);
453  }
454  // parsed all flags successfully
455  return return_code;
456 }
457 
458 
459 static char* SkipWhiteSpace(char* p) {
460  while (*p != '\0' && isspace(*p) != 0) p++;
461  return p;
462 }
463 
464 
465 static char* SkipBlackSpace(char* p) {
466  while (*p != '\0' && isspace(*p) == 0) p++;
467  return p;
468 }
469 
470 
471 // static
472 int FlagList::SetFlagsFromString(const char* str, int len) {
473  // make a 0-terminated copy of str
474  ScopedVector<char> copy0(len + 1);
475  MemCopy(copy0.start(), str, len);
476  copy0[len] = '\0';
477 
478  // strip leading white space
479  char* copy = SkipWhiteSpace(copy0.start());
480 
481  // count the number of 'arguments'
482  int argc = 1; // be compatible with SetFlagsFromCommandLine()
483  for (char* p = copy; *p != '\0'; argc++) {
484  p = SkipBlackSpace(p);
485  p = SkipWhiteSpace(p);
486  }
487 
488  // allocate argument array
490 
491  // split the flags string into arguments
492  argc = 1; // be compatible with SetFlagsFromCommandLine()
493  for (char* p = copy; *p != '\0'; argc++) {
494  argv[argc] = p;
495  p = SkipBlackSpace(p);
496  if (*p != '\0') *p++ = '\0'; // 0-terminate argument
497  p = SkipWhiteSpace(p);
498  }
499 
500  // set the flags
501  int result = SetFlagsFromCommandLine(&argc, argv.start(), false);
502 
503  return result;
504 }
505 
506 
507 // static
509  for (size_t i = 0; i < num_flags; ++i) {
510  flags[i].Reset();
511  }
512 }
513 
514 
515 // static
517  CpuFeatures::Probe(false);
520 
521  OFStream os(stdout);
522  os << "Usage:\n"
523  << " shell [options] -e string\n"
524  << " execute string in V8\n"
525  << " shell [options] file1 file2 ... filek\n"
526  << " run JavaScript scripts in file1, file2, ..., filek\n"
527  << " shell [options]\n"
528  << " shell [options] --shell [file1 file2 ... filek]\n"
529  << " run an interactive JavaScript shell\n"
530  << " d8 [options] file1 file2 ... filek\n"
531  << " d8 [options]\n"
532  << " d8 [options] --shell [file1 file2 ... filek]\n"
533  << " run the new debugging shell\n\n"
534  << "Options:\n";
535  for (size_t i = 0; i < num_flags; ++i) {
536  Flag* f = &flags[i];
537  os << " --" << f->name() << " (" << f->comment() << ")\n"
538  << " type: " << Type2String(f->type()) << " default: " << *f
539  << "\n";
540  }
541 }
542 
543 
544 // static
546 #define FLAG_MODE_DEFINE_IMPLICATIONS
547 #include "src/flag-definitions.h"
548 #undef FLAG_MODE_DEFINE_IMPLICATIONS
549 }
550 
551 } } // namespace v8::internal
static void Probe(bool cross_compile)
Definition: assembler.h:172
static void PrintFeatures()
static int SetFlagsFromCommandLine(int *argc, char **argv, bool remove_flags)
Definition: flags.cc:334
static void EnforceFlagImplications()
Definition: flags.cc:545
static void ResetAllFlags()
Definition: flags.cc:508
static void PrintHelp()
Definition: flags.cc:516
static int SetFlagsFromString(const char *str, int len)
Definition: flags.cc:472
static List< const char * > * argv()
Definition: flags.cc:221
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
const char * c_str() const
Definition: ostreams.h:84
T * start() const
Definition: vector.h:47
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define DCHECK(condition)
Definition: logging.h:205
void DeleteArray(T *array)
Definition: allocation.h:68
static char * SkipWhiteSpace(char *p)
Definition: flags.cc:459
const int KB
Definition: globals.h:106
static Flag * FindFlag(const char *name)
Definition: flags.cc:324
static char * SkipBlackSpace(char *p)
Definition: flags.cc:465
OStream & operator<<(OStream &os, const BasicBlockProfiler &p)
char NormalizeChar(char ch)
Definition: flags.cc:258
void PrintF(const char *format,...)
Definition: utils.cc:80
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
static void SplitArgument(const char *arg, char *buffer, int buffer_size, const char **name, const char **value, bool *is_bool)
Definition: flags.cc:267
static const char * Type2String(Flag::FlagType type)
Definition: flags.cc:170
void MemCopy(void *dest, const void *src, size_t size)
Definition: utils.h:350
static bool EqualNames(const char *a, const char *b)
Definition: flags.cc:314
char * StrDup(const char *str)
Definition: allocation.cc:67
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
MaybeBoolFlag * maybe_bool_variable() const
Definition: flags.cc:52
void set_string_value(const char *value, bool owns_ptr)
Definition: flags.cc:72