OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 ::printf("| %-38s | %11i |\n", (*i).first, counter->value()); | 378 ::printf("| %-38s | %11i |\n", (*i).first, counter->value()); |
379 } | 379 } |
380 ::printf("+----------------------------------------+-------------+\n"); | 380 ::printf("+----------------------------------------+-------------+\n"); |
381 } | 381 } |
382 if (counters_file_ != NULL) | 382 if (counters_file_ != NULL) |
383 delete counters_file_; | 383 delete counters_file_; |
384 } | 384 } |
385 | 385 |
386 | 386 |
387 static char* ReadChars(const char *name, int* size_out) { | 387 static char* ReadChars(const char *name, int* size_out) { |
| 388 v8::Unlocker unlocker; // Release the V8 lock while reading files. |
388 FILE* file = i::OS::FOpen(name, "rb"); | 389 FILE* file = i::OS::FOpen(name, "rb"); |
389 if (file == NULL) return NULL; | 390 if (file == NULL) return NULL; |
390 | 391 |
391 fseek(file, 0, SEEK_END); | 392 fseek(file, 0, SEEK_END); |
392 int size = ftell(file); | 393 int size = ftell(file); |
393 rewind(file); | 394 rewind(file); |
394 | 395 |
395 char* chars = new char[size + 1]; | 396 char* chars = new char[size + 1]; |
396 chars[size] = '\0'; | 397 chars[size] = '\0'; |
397 for (int i = 0; i < size;) { | 398 for (int i = 0; i < size;) { |
(...skipping 17 matching lines...) Expand all Loading... |
415 } | 416 } |
416 | 417 |
417 | 418 |
418 void Shell::RunShell() { | 419 void Shell::RunShell() { |
419 LineEditor* editor = LineEditor::Get(); | 420 LineEditor* editor = LineEditor::Get(); |
420 printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name()); | 421 printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name()); |
421 editor->Open(); | 422 editor->Open(); |
422 while (true) { | 423 while (true) { |
423 Locker locker; | 424 Locker locker; |
424 HandleScope handle_scope; | 425 HandleScope handle_scope; |
| 426 Context::Scope context_scope(evaluation_context_); |
425 i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt); | 427 i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt); |
426 if (input.is_empty()) | 428 if (input.is_empty()) |
427 break; | 429 break; |
428 editor->AddHistory(*input); | 430 editor->AddHistory(*input); |
429 Handle<String> name = String::New("(d8)"); | 431 Handle<String> name = String::New("(d8)"); |
430 ExecuteString(String::New(*input), name, true, true); | 432 ExecuteString(String::New(*input), name, true, true); |
431 } | 433 } |
432 editor->Close(); | 434 editor->Close(); |
433 printf("\n"); | 435 printf("\n"); |
434 } | 436 } |
435 | 437 |
436 | 438 |
437 class ShellThread : public i::Thread { | 439 class ShellThread : public i::Thread { |
438 public: | 440 public: |
439 ShellThread(int no, i::Vector<const char> files) | 441 ShellThread(int no, i::Vector<const char> files) |
440 : no_(no), files_(files) { } | 442 : no_(no), files_(files) { } |
441 virtual void Run(); | 443 virtual void Run(); |
442 private: | 444 private: |
443 int no_; | 445 int no_; |
444 i::Vector<const char> files_; | 446 i::Vector<const char> files_; |
445 }; | 447 }; |
446 | 448 |
447 | 449 |
448 void ShellThread::Run() { | 450 void ShellThread::Run() { |
| 451 // Prepare the context for this thread. |
| 452 Locker locker; |
| 453 HandleScope scope; |
| 454 Handle<ObjectTemplate> global_template = ObjectTemplate::New(); |
| 455 global_template->Set(String::New("print"), |
| 456 FunctionTemplate::New(Shell::Print)); |
| 457 global_template->Set(String::New("load"), |
| 458 FunctionTemplate::New(Shell::Load)); |
| 459 global_template->Set(String::New("version"), |
| 460 FunctionTemplate::New(Shell::Version)); |
| 461 |
| 462 Persistent<Context> thread_context = Context::New(NULL, global_template); |
| 463 thread_context->SetSecurityToken(Undefined()); |
| 464 |
| 465 Context::Scope context_scope(thread_context); |
| 466 |
449 char* ptr = const_cast<char*>(files_.start()); | 467 char* ptr = const_cast<char*>(files_.start()); |
450 while (ptr != NULL) { | 468 while ((ptr != NULL) && (*ptr != '\0')) { |
451 // For each newline-separated line. | 469 // For each newline-separated line. |
452 char *filename = ptr; | 470 char *filename = ptr; |
453 char* next = ::strchr(ptr, '\n'); | 471 char* next = ::strchr(ptr, '\n'); |
454 if (next != NULL) { | 472 if (next != NULL) { |
455 *next = '\0'; | 473 *next = '\0'; |
456 ptr = (next + 1); | 474 ptr = (next + 1); |
457 } else { | 475 } else { |
458 ptr = NULL; | 476 ptr = NULL; |
459 } | 477 } |
460 Locker locker; | |
461 HandleScope scope; | |
462 Handle<String> str = Shell::ReadFile(filename); | 478 Handle<String> str = Shell::ReadFile(filename); |
463 Shell::ExecuteString(str, String::New(filename), false, false); | 479 Shell::ExecuteString(str, String::New(filename), false, false); |
464 } | 480 } |
| 481 |
| 482 thread_context.Dispose(); |
465 } | 483 } |
466 | 484 |
467 | 485 |
468 int Shell::Main(int argc, char* argv[]) { | 486 int Shell::Main(int argc, char* argv[]) { |
469 i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); | 487 i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); |
470 if (i::FLAG_help) { | 488 if (i::FLAG_help) { |
471 return 1; | 489 return 1; |
472 } | 490 } |
473 Initialize(); | 491 Initialize(); |
474 bool run_shell = (argc == 1); | 492 bool run_shell = (argc == 1); |
475 i::List<i::Thread*> threads(1); | 493 i::List<i::Thread*> threads(1); |
476 Context::Scope context_scope(evaluation_context_); | 494 |
477 for (int i = 1; i < argc; i++) { | 495 { |
478 char* str = argv[i]; | 496 // Acquire the V8 lock once initialization has finished. Since the thread |
479 if (strcmp(str, "--shell") == 0) { | 497 // below may spawn new threads accessing V8 holding the V8 lock here is |
480 run_shell = true; | 498 // mandatory. |
481 } else if (strcmp(str, "-f") == 0) { | 499 Locker locker; |
482 // Ignore any -f flags for compatibility with other stand-alone | 500 Context::Scope context_scope(evaluation_context_); |
483 // JavaScript engines. | 501 for (int i = 1; i < argc; i++) { |
484 continue; | 502 char* str = argv[i]; |
485 } else if (strncmp(str, "--", 2) == 0) { | 503 if (strcmp(str, "--shell") == 0) { |
486 printf("Warning: unknown flag %s.\nTry --help for options\n", str); | 504 run_shell = true; |
487 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { | 505 } else if (strcmp(str, "-f") == 0) { |
488 // Execute argument given to -e option directly. | 506 // Ignore any -f flags for compatibility with other stand-alone |
489 Locker locker; | 507 // JavaScript engines. |
490 v8::HandleScope handle_scope; | 508 continue; |
491 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); | 509 } else if (strncmp(str, "--", 2) == 0) { |
492 v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); | 510 printf("Warning: unknown flag %s.\nTry --help for options\n", str); |
493 if (!ExecuteString(source, file_name, false, true)) | 511 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { |
494 return 1; | 512 // Execute argument given to -e option directly. |
495 i++; | 513 v8::HandleScope handle_scope; |
496 } else if (strcmp(str, "-p") == 0 && i + 1 < argc) { | 514 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); |
497 Locker locker; | 515 v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); |
498 Locker::StartPreemption(10); | 516 if (!ExecuteString(source, file_name, false, true)) |
499 int size = 0; | 517 return 1; |
500 const char *files = ReadChars(argv[++i], &size); | 518 i++; |
501 if (files == NULL) return 1; | 519 } else if (strcmp(str, "-p") == 0 && i + 1 < argc) { |
502 ShellThread *thread = | 520 // Use the lowest possible thread preemption interval to test as many |
503 new ShellThread(threads.length(), i::Vector<const char>(files, size)); | 521 // edgecases as possible. |
504 thread->Start(); | 522 Locker::StartPreemption(1); |
505 threads.Add(thread); | 523 int size = 0; |
506 } else { | 524 const char *files = ReadChars(argv[++i], &size); |
507 // Use all other arguments as names of files to load and run. | 525 if (files == NULL) return 1; |
508 Locker locker; | 526 ShellThread *thread = |
509 HandleScope handle_scope; | 527 new ShellThread(threads.length(), |
510 Handle<String> file_name = v8::String::New(str); | 528 i::Vector<const char>(files, size)); |
511 Handle<String> source = ReadFile(str); | 529 thread->Start(); |
512 if (source.IsEmpty()) { | 530 threads.Add(thread); |
513 printf("Error reading '%s'\n", str); | 531 } else { |
514 return 1; | 532 // Use all other arguments as names of files to load and run. |
| 533 HandleScope handle_scope; |
| 534 Handle<String> file_name = v8::String::New(str); |
| 535 Handle<String> source = ReadFile(str); |
| 536 if (source.IsEmpty()) { |
| 537 printf("Error reading '%s'\n", str); |
| 538 return 1; |
| 539 } |
| 540 if (!ExecuteString(source, file_name, false, true)) |
| 541 return 1; |
515 } | 542 } |
516 if (!ExecuteString(source, file_name, false, true)) | |
517 return 1; | |
518 } | 543 } |
| 544 if (i::FLAG_debugger) |
| 545 v8::Debug::AddDebugEventListener(HandleDebugEvent); |
519 } | 546 } |
520 if (i::FLAG_debugger) | |
521 v8::Debug::AddDebugEventListener(HandleDebugEvent); | |
522 if (run_shell) | 547 if (run_shell) |
523 RunShell(); | 548 RunShell(); |
524 for (int i = 0; i < threads.length(); i++) { | 549 for (int i = 0; i < threads.length(); i++) { |
525 i::Thread *thread = threads[i]; | 550 i::Thread *thread = threads[i]; |
526 thread->Join(); | 551 thread->Join(); |
527 delete thread; | 552 delete thread; |
528 } | 553 } |
529 OnExit(); | 554 OnExit(); |
530 return 0; | 555 return 0; |
531 } | 556 } |
532 | 557 |
533 | 558 |
534 } // namespace v8 | 559 } // namespace v8 |
535 | 560 |
536 | 561 |
537 int main(int argc, char* argv[]) { | 562 int main(int argc, char* argv[]) { |
538 return v8::Shell::Main(argc, argv); | 563 return v8::Shell::Main(argc, argv); |
539 } | 564 } |
OLD | NEW |