| 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 |