v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
flags.cc
Go to the documentation of this file.
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <ctype.h>
29 #include <stdlib.h>
30 
31 #include "v8.h"
32 
33 #include "platform.h"
34 #include "smart-pointers.h"
35 #include "string-stream.h"
36 
37 
38 namespace v8 {
39 namespace internal {
40 
41 // Define all of our flags.
42 #define FLAG_MODE_DEFINE
43 #include "flag-definitions.h"
44 
45 // Define all of our flags default values.
46 #define FLAG_MODE_DEFINE_DEFAULTS
47 #include "flag-definitions.h"
48 
49 namespace {
50 
51 // This structure represents a single entry in the flag system, with a pointer
52 // to the actual flag, default value, comment, etc. This is designed to be POD
53 // initialized as to avoid requiring static constructors.
54 struct Flag {
55  enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS };
56 
57  FlagType type_; // What type of flag, bool, int, or string.
58  const char* name_; // Name of the flag, ex "my_flag".
59  void* valptr_; // Pointer to the global flag variable.
60  const void* defptr_; // Pointer to the default value.
61  const char* cmt_; // A comment about the flags purpose.
62  bool owns_ptr_; // Does the flag own its string value?
63 
64  FlagType type() const { return type_; }
65 
66  const char* name() const { return name_; }
67 
68  const char* comment() const { return cmt_; }
69 
70  bool* bool_variable() const {
71  ASSERT(type_ == TYPE_BOOL);
72  return reinterpret_cast<bool*>(valptr_);
73  }
74 
75  int* int_variable() const {
76  ASSERT(type_ == TYPE_INT);
77  return reinterpret_cast<int*>(valptr_);
78  }
79 
80  double* float_variable() const {
81  ASSERT(type_ == TYPE_FLOAT);
82  return reinterpret_cast<double*>(valptr_);
83  }
84 
85  const char* string_value() const {
86  ASSERT(type_ == TYPE_STRING);
87  return *reinterpret_cast<const char**>(valptr_);
88  }
89 
90  void set_string_value(const char* value, bool owns_ptr) {
91  ASSERT(type_ == TYPE_STRING);
92  const char** ptr = reinterpret_cast<const char**>(valptr_);
93  if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
94  *ptr = value;
95  owns_ptr_ = owns_ptr;
96  }
97 
99  ASSERT(type_ == TYPE_ARGS);
100  return reinterpret_cast<JSArguments*>(valptr_);
101  }
102 
103  bool bool_default() const {
104  ASSERT(type_ == TYPE_BOOL);
105  return *reinterpret_cast<const bool*>(defptr_);
106  }
107 
108  int int_default() const {
109  ASSERT(type_ == TYPE_INT);
110  return *reinterpret_cast<const int*>(defptr_);
111  }
112 
113  double float_default() const {
114  ASSERT(type_ == TYPE_FLOAT);
115  return *reinterpret_cast<const double*>(defptr_);
116  }
117 
118  const char* string_default() const {
119  ASSERT(type_ == TYPE_STRING);
120  return *reinterpret_cast<const char* const *>(defptr_);
121  }
122 
124  ASSERT(type_ == TYPE_ARGS);
125  return *reinterpret_cast<const JSArguments*>(defptr_);
126  }
127 
128  // Compare this flag's current value against the default.
129  bool IsDefault() const {
130  switch (type_) {
131  case TYPE_BOOL:
132  return *bool_variable() == bool_default();
133  case TYPE_INT:
134  return *int_variable() == int_default();
135  case TYPE_FLOAT:
136  return *float_variable() == float_default();
137  case TYPE_STRING: {
138  const char* str1 = string_value();
139  const char* str2 = string_default();
140  if (str2 == NULL) return str1 == NULL;
141  if (str1 == NULL) return str2 == NULL;
142  return strcmp(str1, str2) == 0;
143  }
144  case TYPE_ARGS:
145  return args_variable()->argc() == 0;
146  }
147  UNREACHABLE();
148  return true;
149  }
150 
151  // Set a flag back to it's default value.
152  void Reset() {
153  switch (type_) {
154  case TYPE_BOOL:
155  *bool_variable() = bool_default();
156  break;
157  case TYPE_INT:
158  *int_variable() = int_default();
159  break;
160  case TYPE_FLOAT:
161  *float_variable() = float_default();
162  break;
163  case TYPE_STRING:
164  set_string_value(string_default(), false);
165  break;
166  case TYPE_ARGS:
167  *args_variable() = args_default();
168  break;
169  }
170  }
171 };
172 
173 Flag flags[] = {
174 #define FLAG_MODE_META
175 #include "flag-definitions.h"
176 };
177 
178 const size_t num_flags = sizeof(flags) / sizeof(*flags);
179 
180 } // namespace
181 
182 
183 static const char* Type2String(Flag::FlagType type) {
184  switch (type) {
185  case Flag::TYPE_BOOL: return "bool";
186  case Flag::TYPE_INT: return "int";
187  case Flag::TYPE_FLOAT: return "float";
188  case Flag::TYPE_STRING: return "string";
189  case Flag::TYPE_ARGS: return "arguments";
190  }
191  UNREACHABLE();
192  return NULL;
193 }
194 
195 
196 static SmartArrayPointer<const char> ToString(Flag* flag) {
197  HeapStringAllocator string_allocator;
198  StringStream buffer(&string_allocator);
199  switch (flag->type()) {
200  case Flag::TYPE_BOOL:
201  buffer.Add("%s", (*flag->bool_variable() ? "true" : "false"));
202  break;
203  case Flag::TYPE_INT:
204  buffer.Add("%d", *flag->int_variable());
205  break;
206  case Flag::TYPE_FLOAT:
207  buffer.Add("%f", FmtElm(*flag->float_variable()));
208  break;
209  case Flag::TYPE_STRING: {
210  const char* str = flag->string_value();
211  buffer.Add("%s", str ? str : "NULL");
212  break;
213  }
214  case Flag::TYPE_ARGS: {
215  JSArguments args = *flag->args_variable();
216  if (args.argc() > 0) {
217  buffer.Add("%s", args[0]);
218  for (int i = 1; i < args.argc(); i++) {
219  buffer.Add(" %s", args[i]);
220  }
221  }
222  break;
223  }
224  }
225  return buffer.ToCString();
226 }
227 
228 
229 // static
231  List<const char*>* args = new List<const char*>(8);
232  Flag* args_flag = NULL;
233  for (size_t i = 0; i < num_flags; ++i) {
234  Flag* f = &flags[i];
235  if (!f->IsDefault()) {
236  if (f->type() == Flag::TYPE_ARGS) {
237  ASSERT(args_flag == NULL);
238  args_flag = f; // Must be last in arguments.
239  continue;
240  }
241  HeapStringAllocator string_allocator;
242  StringStream buffer(&string_allocator);
243  if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
244  buffer.Add("--%s", f->name());
245  } else {
246  buffer.Add("--no%s", f->name());
247  }
248  args->Add(buffer.ToCString().Detach());
249  if (f->type() != Flag::TYPE_BOOL) {
250  args->Add(ToString(f).Detach());
251  }
252  }
253  }
254  if (args_flag != NULL) {
255  HeapStringAllocator string_allocator;
256  StringStream buffer(&string_allocator);
257  buffer.Add("--%s", args_flag->name());
258  args->Add(buffer.ToCString().Detach());
259  JSArguments jsargs = *args_flag->args_variable();
260  for (int j = 0; j < jsargs.argc(); j++) {
261  args->Add(StrDup(jsargs[j]));
262  }
263  }
264  return args;
265 }
266 
267 
268 // Helper function to parse flags: Takes an argument arg and splits it into
269 // a flag name and flag value (or NULL if they are missing). is_bool is set
270 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
271 // terminate the name, it must be large enough to hold any possible name.
272 static void SplitArgument(const char* arg,
273  char* buffer,
274  int buffer_size,
275  const char** name,
276  const char** value,
277  bool* is_bool) {
278  *name = NULL;
279  *value = NULL;
280  *is_bool = false;
281 
282  if (arg != NULL && *arg == '-') {
283  // find the begin of the flag name
284  arg++; // remove 1st '-'
285  if (*arg == '-') {
286  arg++; // remove 2nd '-'
287  if (arg[0] == '\0') {
288  const char* kJSArgumentsFlagName = "js_arguments";
289  *name = kJSArgumentsFlagName;
290  return;
291  }
292  }
293  if (arg[0] == 'n' && arg[1] == 'o') {
294  arg += 2; // remove "no"
295  *is_bool = true;
296  }
297  *name = arg;
298 
299  // find the end of the flag name
300  while (*arg != '\0' && *arg != '=')
301  arg++;
302 
303  // get the value if any
304  if (*arg == '=') {
305  // make a copy so we can NUL-terminate flag name
306  size_t n = arg - *name;
307  CHECK(n < static_cast<size_t>(buffer_size)); // buffer is too small
308  memcpy(buffer, *name, n);
309  buffer[n] = '\0';
310  *name = buffer;
311  // get the value
312  *value = arg + 1;
313  }
314  }
315 }
316 
317 
318 inline char NormalizeChar(char ch) {
319  return ch == '_' ? '-' : ch;
320 }
321 
322 
323 static bool EqualNames(const char* a, const char* b) {
324  for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
325  if (a[i] == '\0') {
326  return true;
327  }
328  }
329  return false;
330 }
331 
332 
333 static Flag* FindFlag(const char* name) {
334  for (size_t i = 0; i < num_flags; ++i) {
335  if (EqualNames(name, flags[i].name()))
336  return &flags[i];
337  }
338  return NULL;
339 }
340 
341 
342 // static
344  char** argv,
345  bool remove_flags) {
346  int return_code = 0;
347  // parse arguments
348  for (int i = 1; i < *argc;) {
349  int j = i; // j > 0
350  const char* arg = argv[i++];
351 
352  // split arg into flag components
353  char buffer[1*KB];
354  const char* name;
355  const char* value;
356  bool is_bool;
357  SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
358 
359  if (name != NULL) {
360  // lookup the flag
361  Flag* flag = FindFlag(name);
362  if (flag == NULL) {
363  if (remove_flags) {
364  // We don't recognize this flag but since we're removing
365  // the flags we recognize we assume that the remaining flags
366  // will be processed somewhere else so this flag might make
367  // sense there.
368  continue;
369  } else {
370  fprintf(stderr, "Error: unrecognized flag %s\n"
371  "Try --help for options\n", arg);
372  return_code = j;
373  break;
374  }
375  }
376 
377  // if we still need a flag value, use the next argument if available
378  if (flag->type() != Flag::TYPE_BOOL &&
379  flag->type() != Flag::TYPE_ARGS &&
380  value == NULL) {
381  if (i < *argc) {
382  value = argv[i++];
383  } else {
384  fprintf(stderr, "Error: missing value for flag %s of type %s\n"
385  "Try --help for options\n",
386  arg, Type2String(flag->type()));
387  return_code = j;
388  break;
389  }
390  }
391 
392  // set the flag
393  char* endp = const_cast<char*>(""); // *endp is only read
394  switch (flag->type()) {
395  case Flag::TYPE_BOOL:
396  *flag->bool_variable() = !is_bool;
397  break;
398  case Flag::TYPE_INT:
399  *flag->int_variable() = strtol(value, &endp, 10); // NOLINT
400  break;
401  case Flag::TYPE_FLOAT:
402  *flag->float_variable() = strtod(value, &endp);
403  break;
404  case Flag::TYPE_STRING:
405  flag->set_string_value(value ? StrDup(value) : NULL, true);
406  break;
407  case Flag::TYPE_ARGS: {
408  int start_pos = (value == NULL) ? i : i - 1;
409  int js_argc = *argc - start_pos;
410  const char** js_argv = NewArray<const char*>(js_argc);
411  if (value != NULL) {
412  js_argv[0] = StrDup(value);
413  }
414  for (int k = i; k < *argc; k++) {
415  js_argv[k - start_pos] = StrDup(argv[k]);
416  }
417  *flag->args_variable() = JSArguments::Create(js_argc, js_argv);
418  i = *argc; // Consume all arguments
419  break;
420  }
421  }
422 
423  // handle errors
424  if ((flag->type() == Flag::TYPE_BOOL && value != NULL) ||
425  (flag->type() != Flag::TYPE_BOOL && is_bool) ||
426  *endp != '\0') {
427  fprintf(stderr, "Error: illegal value for flag %s of type %s\n"
428  "Try --help for options\n",
429  arg, Type2String(flag->type()));
430  return_code = j;
431  break;
432  }
433 
434  // remove the flag & value from the command
435  if (remove_flags) {
436  while (j < i) {
437  argv[j++] = NULL;
438  }
439  }
440  }
441  }
442 
443  // shrink the argument list
444  if (remove_flags) {
445  int j = 1;
446  for (int i = 1; i < *argc; i++) {
447  if (argv[i] != NULL)
448  argv[j++] = argv[i];
449  }
450  *argc = j;
451  }
452 
453  if (FLAG_help) {
454  PrintHelp();
455  exit(0);
456  }
457  // parsed all flags successfully
458  return return_code;
459 }
460 
461 
462 static char* SkipWhiteSpace(char* p) {
463  while (*p != '\0' && isspace(*p) != 0) p++;
464  return p;
465 }
466 
467 
468 static char* SkipBlackSpace(char* p) {
469  while (*p != '\0' && isspace(*p) == 0) p++;
470  return p;
471 }
472 
473 
474 // static
475 int FlagList::SetFlagsFromString(const char* str, int len) {
476  // make a 0-terminated copy of str
477  ScopedVector<char> copy0(len + 1);
478  memcpy(copy0.start(), str, len);
479  copy0[len] = '\0';
480 
481  // strip leading white space
482  char* copy = SkipWhiteSpace(copy0.start());
483 
484  // count the number of 'arguments'
485  int argc = 1; // be compatible with SetFlagsFromCommandLine()
486  for (char* p = copy; *p != '\0'; argc++) {
487  p = SkipBlackSpace(p);
488  p = SkipWhiteSpace(p);
489  }
490 
491  // allocate argument array
493 
494  // split the flags string into arguments
495  argc = 1; // be compatible with SetFlagsFromCommandLine()
496  for (char* p = copy; *p != '\0'; argc++) {
497  argv[argc] = p;
498  p = SkipBlackSpace(p);
499  if (*p != '\0') *p++ = '\0'; // 0-terminate argument
500  p = SkipWhiteSpace(p);
501  }
502 
503  // set the flags
504  int result = SetFlagsFromCommandLine(&argc, argv.start(), false);
505 
506  return result;
507 }
508 
509 
510 // static
512  for (size_t i = 0; i < num_flags; ++i) {
513  flags[i].Reset();
514  }
515 }
516 
517 
518 // static
520  printf("Usage:\n");
521  printf(" shell [options] -e string\n");
522  printf(" execute string in V8\n");
523  printf(" shell [options] file1 file2 ... filek\n");
524  printf(" run JavaScript scripts in file1, file2, ..., filek\n");
525  printf(" shell [options]\n");
526  printf(" shell [options] --shell [file1 file2 ... filek]\n");
527  printf(" run an interactive JavaScript shell\n");
528  printf(" d8 [options] file1 file2 ... filek\n");
529  printf(" d8 [options]\n");
530  printf(" d8 [options] --shell [file1 file2 ... filek]\n");
531  printf(" run the new debugging shell\n\n");
532  printf("Options:\n");
533  for (size_t i = 0; i < num_flags; ++i) {
534  Flag* f = &flags[i];
535  SmartArrayPointer<const char> value = ToString(f);
536  printf(" --%s (%s)\n type: %s default: %s\n",
537  f->name(), f->comment(), Type2String(f->type()), *value);
538  }
539 }
540 
541 
543 #define FLAG_MODE_DEFINE_IMPLICATIONS
544 #include "flag-definitions.h"
545 }
546 
547 } } // namespace v8::internal
JSArguments * args_variable() const
Definition: flags.cc:98
const int KB
Definition: globals.h:207
static void PrintHelp()
Definition: flags.cc:519
static void ResetAllFlags()
Definition: flags.cc:511
#define ASSERT(condition)
Definition: checks.h:270
char NormalizeChar(char ch)
Definition: flags.cc:318
int * int_variable() const
Definition: flags.cc:75
static void EnforceFlagImplications()
Definition: flags.cc:542
FlagType type() const
Definition: flags.cc:64
double float_default() const
Definition: flags.cc:113
#define CHECK(condition)
Definition: checks.h:56
const size_t num_flags
Definition: flags.cc:178
void Add(Vector< const char > format, Vector< FmtElm > elms)
#define UNREACHABLE()
Definition: checks.h:50
double * float_variable() const
Definition: flags.cc:80
T * start() const
Definition: utils.h:390
const char * string_value() const
Definition: flags.cc:85
static JSArguments Create(int argc, const char **argv)
Definition: flags.h:102
JSArguments args_default() const
Definition: flags.cc:123
const char * name() const
Definition: flags.cc:66
bool bool_default() const
Definition: flags.cc:103
int int_default() const
Definition: flags.cc:108
int argc() const
Definition: flags.h:88
const void * defptr_
Definition: flags.cc:60
static int SetFlagsFromString(const char *str, int len)
Definition: flags.cc:475
bool IsDefault() const
Definition: flags.cc:129
const char * comment() const
Definition: flags.cc:68
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
const char * string_default() const
Definition: flags.cc:118
void set_string_value(const char *value, bool owns_ptr)
Definition: flags.cc:90
char * StrDup(const char *str)
Definition: allocation.cc:85
SmartArrayPointer< const char > ToCString() const
void DeleteArray(T *array)
Definition: allocation.h:91
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Definition: flags.cc:495
static List< const char * > * argv()
Definition: flags.cc:230
static int SetFlagsFromCommandLine(int *argc, char **argv, bool remove_flags)
Definition: flags.cc:343
bool * bool_variable() const
Definition: flags.cc:70
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset flag
Definition: objects-inl.h:3923