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