d8.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h>
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <errno.h>
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8-debug.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "natives.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* Shell::kHistoryFileName = ".d8_history";
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* Shell::kPrompt = "d8> ";
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockLineEditor *LineEditor::first_ = NULL;
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockLineEditor::LineEditor(Type type, const char* name)
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : type_(type),
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name_(name),
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next_(first_) {
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  first_ = this;
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockLineEditor* LineEditor::Get() {
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LineEditor* current = first_;
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LineEditor* best = current;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (current != NULL) {
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current->type_ > best->type_)
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      best = current;
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = current->next_;
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return best;
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DumbLineEditor: public LineEditor {
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual i::SmartPointer<char> Prompt(const char* prompt);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic DumbLineEditor dumb_line_editor;
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocki::SmartPointer<char> DumbLineEditor::Prompt(const char* prompt) {
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 256;
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buffer[kBufferSize];
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printf("%s", prompt);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* str = fgets(buffer, kBufferSize, stdin);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return i::SmartPointer<char>(str ? i::StrDup(str) : str);
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounterMap* Shell::counter_map_;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocki::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounterCollection Shell::local_counters_;
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounterCollection* Shell::counters_ = &local_counters_;
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPersistent<Context> Shell::utility_context_;
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPersistent<Context> Shell::evaluation_context_;
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool CounterMap::Match(void* key1, void* key2) {
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* name1 = reinterpret_cast<const char*>(key1);
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* name2 = reinterpret_cast<const char*>(key2);
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return strcmp(name1, name2) == 0;
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Converts a V8 value to a C string.
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst char* Shell::ToCString(const v8::String::Utf8Value& value) {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return *value ? *value : "<string conversion failed>";
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Executes a string within the current v8 context.
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Shell::ExecuteString(Handle<String> source,
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Handle<Value> name,
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          bool print_result,
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          bool report_exceptions) {
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope handle_scope;
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TryCatch try_catch;
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_debugger) {
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When debugging make exceptions appear to be uncaught.
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    try_catch.SetVerbose(true);
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Script> script = Script::Compile(source, name);
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (script.IsEmpty()) {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print errors that happened during compilation.
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (report_exceptions && !i::FLAG_debugger)
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ReportException(&try_catch);
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Value> result = script->Run();
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (result.IsEmpty()) {
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Print errors that happened during execution.
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (report_exceptions && !i::FLAG_debugger)
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ReportException(&try_catch);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (print_result && !result->IsUndefined()) {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // If all went well and the result wasn't undefined then print
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // the returned value.
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::String::Utf8Value str(result);
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* cstr = ToCString(str);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        printf("%s\n", cstr);
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Print(const Arguments& args) {
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> val = Write(args);
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printf("\n");
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return val;
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Write(const Arguments& args) {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.Length(); i++) {
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HandleScope handle_scope;
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i != 0) {
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      printf(" ");
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::String::Utf8Value str(args[i]);
162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int n = fwrite(*str, sizeof(**str), str.length(), stdout);
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (n != str.length()) {
164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      printf("Error in fwrite\n");
165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      exit(1);
166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Undefined();
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Read(const Arguments& args) {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String::Utf8Value file(args[0]);
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*file == NULL) {
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ThrowException(String::New("Error loading file"));
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source = ReadFile(*file);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source.IsEmpty()) {
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ThrowException(String::New("Error loading file"));
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return source;
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::ReadLine(const Arguments& args) {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::SmartPointer<char> line(i::ReadLine(""));
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*line == NULL) {
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Null();
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_t len = strlen(*line);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (len > 0 && line[len - 1] == '\n') {
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    --len;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return String::New(*line, len);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Load(const Arguments& args) {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.Length(); i++) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HandleScope handle_scope;
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    String::Utf8Value file(args[i]);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (*file == NULL) {
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return ThrowException(String::New("Error loading file"));
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> source = ReadFile(*file);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (source.IsEmpty()) {
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return ThrowException(String::New("Error loading file"));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!ExecuteString(source, String::New(*file), false, false)) {
210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return ThrowException(String::New("Error executing file"));
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Undefined();
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Yield(const Arguments& args) {
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Unlocker unlocker;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Undefined();
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Quit(const Arguments& args) {
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int exit_code = args[0]->Int32Value();
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OnExit();
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  exit(exit_code);
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Undefined();
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::Version(const Arguments& args) {
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return String::New(V8::GetVersion());
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::ReportException(v8::TryCatch* try_catch) {
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope handle_scope;
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::String::Utf8Value exception(try_catch->Exception());
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* exception_string = ToCString(exception);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Message> message = try_catch->Message();
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEmpty()) {
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // V8 didn't provide any extra information about this error; just
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // print the exception.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("%s\n", exception_string);
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print (filename):(line number): (message).
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::String::Utf8Value filename(message->GetScriptResourceName());
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* filename_string = ToCString(filename);
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int linenum = message->GetLineNumber();
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print line of source code.
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::String::Utf8Value sourceline(message->GetSourceLine());
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* sourceline_string = ToCString(sourceline);
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("%s\n", sourceline_string);
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print wavy underline (GetUnderline is deprecated).
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int start = message->GetStartColumn();
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < start; i++) {
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      printf(" ");
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int end = message->GetEndColumn();
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = start; i < end; i++) {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      printf("^");
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("\n");
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope handle_scope;
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope context_scope(utility_context_);
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> global = utility_context_->Global();
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> fun = global->Get(String::New("GetCompletions"));
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kArgc = 3;
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return handle_scope.Close(Handle<Array>::Cast(val));
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> Shell::DebugMessageDetails(Handle<String> message) {
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope context_scope(utility_context_);
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> global = utility_context_->Global();
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kArgc = 1;
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> argv[kArgc] = { message };
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Handle<Object>::Cast(val);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope context_scope(utility_context_);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> global = utility_context_->Global();
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kArgc = 1;
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> argv[kArgc] = { command };
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return val;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint32_t* Counter::Bind(const char* name, bool is_histogram) {
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int i;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    name_[i] = static_cast<char>(name[i]);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  name_[i] = '\0';
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  is_histogram_ = is_histogram;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ptr();
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Counter::AddSample(int32_t sample) {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  count_++;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sample_total_ += sample;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounterCollection::CounterCollection() {
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  magic_number_ = 0xDEADFACE;
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  max_counters_ = kMaxCounters;
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  max_name_size_ = Counter::kMaxNameSize;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  counters_in_use_ = 0;
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounter* CounterCollection::GetNextCounter() {
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (counters_in_use_ == kMaxCounters) return NULL;
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return &counters_[counters_in_use_++];
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::MapCounters(const char* name) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  counters_file_ = i::OS::MemoryMappedFile::create(name,
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    sizeof(CounterCollection), &local_counters_);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void* memory = (counters_file_ == NULL) ?
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      NULL : counters_file_->memory();
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (memory == NULL) {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("Could not map counters file %s\n", name);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exit(1);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  counters_ = static_cast<CounterCollection*>(memory);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::SetCounterFunction(LookupCounter);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::SetCreateHistogramFunction(CreateHistogram);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::SetAddHistogramSampleFunction(AddHistogramSample);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint CounterMap::Hash(const char* name) {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int h = 0;
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int c;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((c = *name++) != 0) {
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    h += h << 5;
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    h += c;
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return h;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCounter* Shell::GetCounter(const char* name, bool is_histogram) {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Counter* counter = counter_map_->Lookup(name);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (counter == NULL) {
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    counter = counters_->GetNextCounter();
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (counter != NULL) {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      counter_map_->Set(name, counter);
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      counter->Bind(name, is_histogram);
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(counter->is_histogram() == is_histogram);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return counter;
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint* Shell::LookupCounter(const char* name) {
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Counter* counter = GetCounter(name, false);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (counter != NULL) {
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return counter->ptr();
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Shell::CreateHistogram(const char* name,
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             int min,
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             int max,
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             size_t buckets) {
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCounter(name, true);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::AddHistogramSample(void* histogram, int sample) {
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Counter* counter = reinterpret_cast<Counter*>(histogram);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  counter->AddSample(sample);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::Initialize() {
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Shell::counter_map_ = new CounterMap();
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up counters
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_map_counters != NULL)
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MapCounters(i::FLAG_map_counters);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_dump_counters) {
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    V8::SetCounterFunction(LookupCounter);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    V8::SetCreateHistogramFunction(CreateHistogram);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    V8::SetAddHistogramSampleFunction(AddHistogramSample);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the global objects
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<ObjectTemplate> global_template = ObjectTemplate::New();
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("print"), FunctionTemplate::New(Print));
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("write"), FunctionTemplate::New(Write));
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("read"), FunctionTemplate::New(Read));
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("readline"),
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(ReadLine));
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("load"), FunctionTemplate::New(Load));
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("version"), FunctionTemplate::New(Version));
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddOSMethods(os_templ);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("os"), os_templ);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  utility_context_ = Context::New(NULL, global_template);
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  utility_context_->SetSecurityToken(Undefined());
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context::Scope utility_scope(utility_context_);
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::JSArguments js_args = i::FLAG_js_arguments;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Handle<i::FixedArray> arguments_array =
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      i::Factory::NewFixedArray(js_args.argc());
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int j = 0; j < js_args.argc(); j++) {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::Handle<i::String> arg =
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        i::Factory::NewStringFromUtf8(i::CStrVector(js_args[j]));
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arguments_array->set(j, *arg);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Handle<i::JSArray> arguments_jsarray =
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      i::Factory::NewJSArrayWithElements(arguments_array);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("arguments"),
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Utils::ToLocal(arguments_jsarray));
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Install the debugger object in the utility scope
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Debug::Load();
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  i::Handle<i::JSObject> debug
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      = i::Handle<i::JSObject>(i::Debug::debug_context()->global());
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  utility_context_->Global()->Set(String::New("$debug"),
4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                  Utils::ToLocal(debug));
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the d8 shell utility script in the utility context
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Vector<const char> shell_source
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      = i::NativesCollection<i::D8>::GetScriptSource(source_index);
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Vector<const char> shell_source_name
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      = i::NativesCollection<i::D8>::GetScriptName(source_index);
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source = String::New(shell_source.start(),
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      shell_source.length());
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> name = String::New(shell_source_name.start(),
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    shell_source_name.length());
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Script> script = Script::Compile(source, name);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the d8 shell script as native to avoid it showing up as normal source
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in the debugger.
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ? i::Handle<i::Script>(i::Script::cast(
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          i::JSFunction::cast(*compiled_script)->shared()->script()))
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : i::Handle<i::Script>(i::Script::cast(
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          i::SharedFunctionInfo::cast(*compiled_script)->script()));
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create the evaluation context
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  evaluation_context_ = Context::New(NULL, global_template);
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  evaluation_context_->SetSecurityToken(Undefined());
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the security token of the debug context to allow access.
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start the debugger agent if requested.
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_debugger_agent) {
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port);
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start the in-process debugger if requested.
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Debug::SetDebugEventListener(HandleDebugEvent);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::OnExit() {
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_dump_counters) {
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ::printf("+----------------------------------------+-------------+\n");
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ::printf("| Name                                   | Value       |\n");
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ::printf("+----------------------------------------+-------------+\n");
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Counter* counter = i.CurrentValue();
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (counter->is_histogram()) {
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ::printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ::printf("| t:%-36s | %11i |\n",
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 i.CurrentKey(),
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 counter->sample_total());
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ::printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ::printf("+----------------------------------------+-------------+\n");
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (counters_file_ != NULL)
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete counters_file_;
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* ReadChars(const char* name, int* size_out) {
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Unlocker unlocker;  // Release the V8 lock while reading files.
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FILE* file = i::OS::FOpen(name, "rb");
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (file == NULL) return NULL;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fseek(file, 0, SEEK_END);
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = ftell(file);
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rewind(file);
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* chars = new char[size + 1];
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  chars[size] = '\0';
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < size;) {
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int read = fread(&chars[i], 1, size - i, file);
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i += read;
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fclose(file);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *size_out = size;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return chars;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* ReadToken(char* data, char token) {
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* next = i::OS::StrChr(data, token);
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (next != NULL) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *next = '\0';
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (next + 1);
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* ReadLine(char* data) {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ReadToken(data, '\n');
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* ReadWord(char* data) {
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ReadToken(data, ' ');
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Reads a file into a v8 string.
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<String> Shell::ReadFile(const char* name) {
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = 0;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* chars = ReadChars(name, &size);
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (chars == NULL) return Handle<String>();
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> result = String::New(chars);
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete[] chars;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Shell::RunShell() {
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LineEditor* editor = LineEditor::Get();
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
5797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (i::FLAG_debugger) {
5807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    printf("JavaScript debugger enabled\n");
5817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  editor->Open();
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Locker locker;
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HandleScope handle_scope;
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope context_scope(evaluation_context_);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (input.is_empty())
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    editor->AddHistory(*input);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> name = String::New("(d8)");
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExecuteString(String::New(*input), name, true, true);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  editor->Close();
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printf("\n");
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ShellThread : public i::Thread {
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ShellThread(int no, i::Vector<const char> files)
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : no_(no), files_(files) { }
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Run();
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int no_;
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Vector<const char> files_;
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ShellThread::Run() {
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prepare the context for this thread.
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Locker locker;
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<ObjectTemplate> global_template = ObjectTemplate::New();
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("print"),
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Print));
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("write"),
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Write));
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("read"),
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Read));
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("readline"),
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::ReadLine));
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("load"),
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Load));
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("yield"),
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Yield));
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  global_template->Set(String::New("version"),
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       FunctionTemplate::New(Shell::Version));
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* ptr = const_cast<char*>(files_.start());
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((ptr != NULL) && (*ptr != '\0')) {
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // For each newline-separated line.
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* next_line = ReadLine(ptr);
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (*ptr == '#') {
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Skip comment lines.
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ptr = next_line;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Persistent<Context> thread_context = Context::New(NULL, global_template);
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    thread_context->SetSecurityToken(Undefined());
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope context_scope(thread_context);
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while ((ptr != NULL) && (*ptr != '\0')) {
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      char* filename = ptr;
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ptr = ReadWord(ptr);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Skip empty strings.
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (strlen(filename) == 0) {
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<String> str = Shell::ReadFile(filename);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (str.IsEmpty()) {
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        printf("WARNING: %s not found\n", filename);
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::ExecuteString(str, String::New(filename), false, false);
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    thread_context.Dispose();
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ptr = next_line;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Shell::Main(int argc, char* argv[]) {
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (i::FLAG_help) {
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1;
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Initialize();
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool run_shell = (argc == 1);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default use preemption if threads are created.
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool use_preemption = true;
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default to use lowest possible thread preemption interval to test as many
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edgecases as possible.
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int preemption_interval = 1;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::List<i::Thread*> threads(1);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Acquire the V8 lock once initialization has finished. Since the thread
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // below may spawn new threads accessing V8 holding the V8 lock here is
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // mandatory.
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Locker locker;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Context::Scope context_scope(evaluation_context_);
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 1; i < argc; i++) {
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      char* str = argv[i];
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (strcmp(str, "--shell") == 0) {
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        run_shell = true;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "--preemption") == 0) {
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        use_preemption = true;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "--no-preemption") == 0) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        use_preemption = false;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "--preemption-interval") == 0) {
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (i + 1 < argc) {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          char* end = NULL;
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          preemption_interval = strtol(argv[++i], &end, 10);  // NOLINT
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return 1;
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          printf("Missing value for --preemption-interval\n");
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       }
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "-f") == 0) {
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Ignore any -f flags for compatibility with other stand-alone
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // JavaScript engines.
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strncmp(str, "--", 2) == 0) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        printf("Warning: unknown flag %s.\nTry --help for options\n", str);
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Execute argument given to -e option directly.
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::HandleScope handle_scope;
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Handle<v8::String> file_name = v8::String::New("unnamed");
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!ExecuteString(source, file_name, false, true)) {
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          OnExit();
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        i++;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int size = 0;
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* files = ReadChars(argv[++i], &size);
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (files == NULL) return 1;
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ShellThread* thread =
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            new ShellThread(threads.length(),
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            i::Vector<const char>(files, size));
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        thread->Start();
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        threads.Add(thread);
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Use all other arguments as names of files to load and run.
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HandleScope handle_scope;
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<String> file_name = v8::String::New(str);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<String> source = ReadFile(str);
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (source.IsEmpty()) {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          printf("Error reading '%s'\n", str);
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!ExecuteString(source, file_name, false, true)) {
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          OnExit();
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Start preemption if threads have been created and preemption is enabled.
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (threads.length() > 0 && use_preemption) {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Locker::StartPreemption(preemption_interval);
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Run the remote debugger if requested.
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i::FLAG_remote_debugger) {
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RunRemoteDebugger(i::FLAG_debugger_port);
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 0;
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (run_shell)
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RunShell();
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < threads.length(); i++) {
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::Thread* thread = threads[i];
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    thread->Join();
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete thread;
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OnExit();
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace v8
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint main(int argc, char* argv[]) {
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return v8::Shell::Main(argc, argv);
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
784