| 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 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 | 28 |
| 29 #include <stdlib.h> | 29 #include <stdlib.h> |
| 30 | 30 |
| 31 #include "d8.h" | 31 #include "d8.h" |
| 32 #include "d8-debug.h" | 32 #include "d8-debug.h" |
| 33 #include "debug.h" | 33 #include "debug.h" |
| 34 #include "api.h" | 34 #include "api.h" |
| 35 #include "natives.h" | 35 #include "natives.h" |
| 36 #include "platform.h" |
| 36 | 37 |
| 37 | 38 |
| 38 namespace v8 { | 39 namespace v8 { |
| 39 | 40 |
| 40 | 41 |
| 41 const char* Shell::kHistoryFileName = ".d8_history"; | 42 const char* Shell::kHistoryFileName = ".d8_history"; |
| 42 const char* Shell::kPrompt = "d8> "; | 43 const char* Shell::kPrompt = "d8> "; |
| 43 | 44 |
| 44 | 45 |
| 45 LineEditor *LineEditor::first_ = NULL; | 46 LineEditor *LineEditor::first_ = NULL; |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 Counter* counter = (*i).second; | 377 Counter* counter = (*i).second; |
| 377 ::printf("| %-38s | %11i |\n", (*i).first, counter->value()); | 378 ::printf("| %-38s | %11i |\n", (*i).first, counter->value()); |
| 378 } | 379 } |
| 379 ::printf("+----------------------------------------+-------------+\n"); | 380 ::printf("+----------------------------------------+-------------+\n"); |
| 380 } | 381 } |
| 381 if (counters_file_ != NULL) | 382 if (counters_file_ != NULL) |
| 382 delete counters_file_; | 383 delete counters_file_; |
| 383 } | 384 } |
| 384 | 385 |
| 385 | 386 |
| 386 // Reads a file into a v8 string. | 387 static char* ReadChars(const char *name, int* size_out) { |
| 387 Handle<String> Shell::ReadFile(const char* name) { | 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 Handle<String>(); | 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;) { |
| 398 int read = fread(&chars[i], 1, size - i, file); | 399 int read = fread(&chars[i], 1, size - i, file); |
| 399 i += read; | 400 i += read; |
| 400 } | 401 } |
| 401 fclose(file); | 402 fclose(file); |
| 402 Handle<String> result = String::New(chars, size); | 403 *size_out = size; |
| 404 return chars; |
| 405 } |
| 406 |
| 407 |
| 408 // Reads a file into a v8 string. |
| 409 Handle<String> Shell::ReadFile(const char* name) { |
| 410 int size = 0; |
| 411 char* chars = ReadChars(name, &size); |
| 412 if (chars == NULL) return Handle<String>(); |
| 413 Handle<String> result = String::New(chars); |
| 403 delete[] chars; | 414 delete[] chars; |
| 404 return result; | 415 return result; |
| 405 } | 416 } |
| 406 | 417 |
| 407 | 418 |
| 408 void Shell::RunShell() { | 419 void Shell::RunShell() { |
| 409 LineEditor* editor = LineEditor::Get(); | 420 LineEditor* editor = LineEditor::Get(); |
| 410 printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name()); | 421 printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name()); |
| 411 editor->Open(); | 422 editor->Open(); |
| 412 while (true) { | 423 while (true) { |
| 424 Locker locker; |
| 413 HandleScope handle_scope; | 425 HandleScope handle_scope; |
| 426 Context::Scope context_scope(evaluation_context_); |
| 414 i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt); | 427 i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt); |
| 415 if (input.is_empty()) | 428 if (input.is_empty()) |
| 416 break; | 429 break; |
| 417 editor->AddHistory(*input); | 430 editor->AddHistory(*input); |
| 418 Handle<String> name = String::New("(d8)"); | 431 Handle<String> name = String::New("(d8)"); |
| 419 ExecuteString(String::New(*input), name, true, true); | 432 ExecuteString(String::New(*input), name, true, true); |
| 420 } | 433 } |
| 421 editor->Close(); | 434 editor->Close(); |
| 422 printf("\n"); | 435 printf("\n"); |
| 423 } | 436 } |
| 424 | 437 |
| 425 | 438 |
| 439 class ShellThread : public i::Thread { |
| 440 public: |
| 441 ShellThread(int no, i::Vector<const char> files) |
| 442 : no_(no), files_(files) { } |
| 443 virtual void Run(); |
| 444 private: |
| 445 int no_; |
| 446 i::Vector<const char> files_; |
| 447 }; |
| 448 |
| 449 |
| 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 |
| 467 char* ptr = const_cast<char*>(files_.start()); |
| 468 while ((ptr != NULL) && (*ptr != '\0')) { |
| 469 // For each newline-separated line. |
| 470 char *filename = ptr; |
| 471 char* next = ::strchr(ptr, '\n'); |
| 472 if (next != NULL) { |
| 473 *next = '\0'; |
| 474 ptr = (next + 1); |
| 475 } else { |
| 476 ptr = NULL; |
| 477 } |
| 478 Handle<String> str = Shell::ReadFile(filename); |
| 479 Shell::ExecuteString(str, String::New(filename), false, false); |
| 480 } |
| 481 |
| 482 thread_context.Dispose(); |
| 483 } |
| 484 |
| 485 |
| 426 int Shell::Main(int argc, char* argv[]) { | 486 int Shell::Main(int argc, char* argv[]) { |
| 427 i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); | 487 i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); |
| 428 if (i::FLAG_help) { | 488 if (i::FLAG_help) { |
| 429 return 1; | 489 return 1; |
| 430 } | 490 } |
| 431 Initialize(); | 491 Initialize(); |
| 432 bool run_shell = (argc == 1); | 492 bool run_shell = (argc == 1); |
| 433 Context::Scope context_scope(evaluation_context_); | 493 i::List<i::Thread*> threads(1); |
| 434 for (int i = 1; i < argc; i++) { | 494 |
| 435 char* str = argv[i]; | 495 { |
| 436 if (strcmp(str, "--shell") == 0) { | 496 // Acquire the V8 lock once initialization has finished. Since the thread |
| 437 run_shell = true; | 497 // below may spawn new threads accessing V8 holding the V8 lock here is |
| 438 } else if (strcmp(str, "-f") == 0) { | 498 // mandatory. |
| 439 // Ignore any -f flags for compatibility with other stand-alone | 499 Locker locker; |
| 440 // JavaScript engines. | 500 Context::Scope context_scope(evaluation_context_); |
| 441 continue; | 501 for (int i = 1; i < argc; i++) { |
| 442 } else if (strncmp(str, "--", 2) == 0) { | 502 char* str = argv[i]; |
| 443 printf("Warning: unknown flag %s.\nTry --help for options\n", str); | 503 if (strcmp(str, "--shell") == 0) { |
| 444 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { | 504 run_shell = true; |
| 445 // Execute argument given to -e option directly. | 505 } else if (strcmp(str, "-f") == 0) { |
| 446 v8::HandleScope handle_scope; | 506 // Ignore any -f flags for compatibility with other stand-alone |
| 447 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); | 507 // JavaScript engines. |
| 448 v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); | 508 continue; |
| 449 if (!ExecuteString(source, file_name, false, true)) | 509 } else if (strncmp(str, "--", 2) == 0) { |
| 450 return 1; | 510 printf("Warning: unknown flag %s.\nTry --help for options\n", str); |
| 451 i++; | 511 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { |
| 452 } else { | 512 // Execute argument given to -e option directly. |
| 453 // Use all other arguments as names of files to load and run. | 513 v8::HandleScope handle_scope; |
| 454 HandleScope handle_scope; | 514 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); |
| 455 Handle<String> file_name = v8::String::New(str); | 515 v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); |
| 456 Handle<String> source = ReadFile(str); | 516 if (!ExecuteString(source, file_name, false, true)) |
| 457 if (source.IsEmpty()) { | 517 return 1; |
| 458 printf("Error reading '%s'\n", str); | 518 i++; |
| 459 return 1; | 519 } else if (strcmp(str, "-p") == 0 && i + 1 < argc) { |
| 520 // Use the lowest possible thread preemption interval to test as many |
| 521 // edgecases as possible. |
| 522 Locker::StartPreemption(1); |
| 523 int size = 0; |
| 524 const char *files = ReadChars(argv[++i], &size); |
| 525 if (files == NULL) return 1; |
| 526 ShellThread *thread = |
| 527 new ShellThread(threads.length(), |
| 528 i::Vector<const char>(files, size)); |
| 529 thread->Start(); |
| 530 threads.Add(thread); |
| 531 } else { |
| 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; |
| 460 } | 542 } |
| 461 if (!ExecuteString(source, file_name, false, true)) | |
| 462 return 1; | |
| 463 } | 543 } |
| 544 if (i::FLAG_debugger) |
| 545 v8::Debug::AddDebugEventListener(HandleDebugEvent); |
| 464 } | 546 } |
| 465 if (i::FLAG_debugger) | |
| 466 v8::Debug::AddDebugEventListener(HandleDebugEvent); | |
| 467 if (run_shell) | 547 if (run_shell) |
| 468 RunShell(); | 548 RunShell(); |
| 549 for (int i = 0; i < threads.length(); i++) { |
| 550 i::Thread *thread = threads[i]; |
| 551 thread->Join(); |
| 552 delete thread; |
| 553 } |
| 469 OnExit(); | 554 OnExit(); |
| 470 return 0; | 555 return 0; |
| 471 } | 556 } |
| 472 | 557 |
| 473 | 558 |
| 474 } // namespace v8 | 559 } // namespace v8 |
| 475 | 560 |
| 476 | 561 |
| 477 int main(int argc, char* argv[]) { | 562 int main(int argc, char* argv[]) { |
| 478 return v8::Shell::Main(argc, argv); | 563 return v8::Shell::Main(argc, argv); |
| 479 } | 564 } |
| OLD | NEW |