blob: 45781cf0d4a4d0c30961505381e3acc2fed7d8cf [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
Ben Murdoch69a99ed2011-11-30 16:03:39 +000029#ifdef USING_V8_SHARED // Defined when linking against shared lib on Windows.
30#define V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000031#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000032
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033#ifdef COMPRESS_STARTUP_DATA_BZ2
34#include <bzlib.h>
35#endif
36
37#include <errno.h>
38#include <stdlib.h>
39#include <string.h>
Ben Murdoch69a99ed2011-11-30 16:03:39 +000040#include <sys/stat.h>
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000041
Ben Murdoch69a99ed2011-11-30 16:03:39 +000042#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000043#include <assert.h>
44#include "../include/v8-testing.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000045#endif // V8_SHARED
Steve Block44f0eee2011-05-26 01:26:41 +010046
Steve Blocka7e24c12009-10-30 11:49:00 +000047#include "d8.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000048
Ben Murdoch69a99ed2011-11-30 16:03:39 +000049#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000050#include "api.h"
51#include "checks.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000052#include "d8-debug.h"
53#include "debug.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000054#include "natives.h"
55#include "platform.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000056#include "v8.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000057#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +000058
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000059#if !defined(_WIN32) && !defined(_WIN64)
60#include <unistd.h> // NOLINT
61#endif
62
Ben Murdoch69a99ed2011-11-30 16:03:39 +000063#ifndef ASSERT
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000064#define ASSERT(condition) assert(condition)
Ben Murdoch69a99ed2011-11-30 16:03:39 +000065#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000066
67namespace v8 {
68
Steve Blocka7e24c12009-10-30 11:49:00 +000069LineEditor *LineEditor::first_ = NULL;
70
71
72LineEditor::LineEditor(Type type, const char* name)
73 : type_(type),
74 name_(name),
75 next_(first_) {
76 first_ = this;
77}
78
79
80LineEditor* LineEditor::Get() {
81 LineEditor* current = first_;
82 LineEditor* best = current;
83 while (current != NULL) {
84 if (current->type_ > best->type_)
85 best = current;
86 current = current->next_;
87 }
88 return best;
89}
90
91
92class DumbLineEditor: public LineEditor {
93 public:
94 DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010095 virtual Handle<String> Prompt(const char* prompt);
Steve Blocka7e24c12009-10-30 11:49:00 +000096};
97
98
99static DumbLineEditor dumb_line_editor;
100
101
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100102Handle<String> DumbLineEditor::Prompt(const char* prompt) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 printf("%s", prompt);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100104 return Shell::ReadFromStdin();
Steve Blocka7e24c12009-10-30 11:49:00 +0000105}
106
107
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100108#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000109CounterMap* Shell::counter_map_;
110i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
111CounterCollection Shell::local_counters_;
112CounterCollection* Shell::counters_ = &local_counters_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000113i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
Steve Blocka7e24c12009-10-30 11:49:00 +0000114Persistent<Context> Shell::utility_context_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000115#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000116
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100117LineEditor* Shell::console = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000118Persistent<Context> Shell::evaluation_context_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000119ShellOptions Shell::options;
120const char* Shell::kPrompt = "d8> ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000121
122
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100123const int MB = 1024 * 1024;
124
125
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000126#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000127bool CounterMap::Match(void* key1, void* key2) {
128 const char* name1 = reinterpret_cast<const char*>(key1);
129 const char* name2 = reinterpret_cast<const char*>(key2);
130 return strcmp(name1, name2) == 0;
131}
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000132#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
134
135// Converts a V8 value to a C string.
Steve Block6ded16b2010-05-10 14:33:55 +0100136const char* Shell::ToCString(const v8::String::Utf8Value& value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 return *value ? *value : "<string conversion failed>";
138}
139
140
141// Executes a string within the current v8 context.
142bool Shell::ExecuteString(Handle<String> source,
143 Handle<Value> name,
144 bool print_result,
145 bool report_exceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100146#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000147 bool FLAG_debugger = i::FLAG_debugger;
148#else
149 bool FLAG_debugger = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100150#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000151 HandleScope handle_scope;
152 TryCatch try_catch;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000153 options.script_executed = true;
154 if (FLAG_debugger) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 // When debugging make exceptions appear to be uncaught.
156 try_catch.SetVerbose(true);
157 }
158 Handle<Script> script = Script::Compile(source, name);
159 if (script.IsEmpty()) {
160 // Print errors that happened during compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000161 if (report_exceptions && !FLAG_debugger)
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 ReportException(&try_catch);
163 return false;
164 } else {
165 Handle<Value> result = script->Run();
166 if (result.IsEmpty()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100167 ASSERT(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +0000168 // Print errors that happened during execution.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000169 if (report_exceptions && !FLAG_debugger)
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 ReportException(&try_catch);
171 return false;
172 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100173 ASSERT(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 if (print_result && !result->IsUndefined()) {
175 // If all went well and the result wasn't undefined then print
176 // the returned value.
177 v8::String::Utf8Value str(result);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100178 size_t count = fwrite(*str, sizeof(**str), str.length(), stdout);
179 (void) count; // Silence GCC-4.5.x "unused result" warning.
Ben Murdoch589d6972011-11-30 16:04:58 +0000180 printf("\n");
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 }
182 return true;
183 }
184 }
185}
186
187
188Handle<Value> Shell::Print(const Arguments& args) {
189 Handle<Value> val = Write(args);
190 printf("\n");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000191 fflush(stdout);
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 return val;
193}
194
195
196Handle<Value> Shell::Write(const Arguments& args) {
197 for (int i = 0; i < args.Length(); i++) {
198 HandleScope handle_scope;
199 if (i != 0) {
200 printf(" ");
201 }
202 v8::String::Utf8Value str(args[i]);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000203 int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
Steve Blockd0582a62009-12-15 09:54:21 +0000204 if (n != str.length()) {
205 printf("Error in fwrite\n");
Ben Murdoch589d6972011-11-30 16:04:58 +0000206 Exit(1);
Steve Blockd0582a62009-12-15 09:54:21 +0000207 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 }
209 return Undefined();
210}
211
212
Ben Murdoch589d6972011-11-30 16:04:58 +0000213Handle<Value> Shell::EnableProfiler(const Arguments& args) {
214 V8::ResumeProfiler();
215 return Undefined();
216}
217
218
219Handle<Value> Shell::DisableProfiler(const Arguments& args) {
220 V8::PauseProfiler();
221 return Undefined();
222}
223
224
Steve Blocka7e24c12009-10-30 11:49:00 +0000225Handle<Value> Shell::Read(const Arguments& args) {
226 String::Utf8Value file(args[0]);
227 if (*file == NULL) {
228 return ThrowException(String::New("Error loading file"));
229 }
230 Handle<String> source = ReadFile(*file);
231 if (source.IsEmpty()) {
232 return ThrowException(String::New("Error loading file"));
233 }
234 return source;
235}
236
237
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100238Handle<String> Shell::ReadFromStdin() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000239 static const int kBufferSize = 256;
240 char buffer[kBufferSize];
241 Handle<String> accumulator = String::New("");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000242 int length;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000243 while (true) {
244 // Continue reading if the line ends with an escape '\\' or the line has
245 // not been fully read into the buffer yet (does not end with '\n').
246 // If fgets gets an error, just give up.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100247 char* input = NULL;
248 { // Release lock for blocking input.
249 Unlocker unlock(Isolate::GetCurrent());
250 input = fgets(buffer, kBufferSize, stdin);
251 }
252 if (input == NULL) return Handle<String>();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000253 length = static_cast<int>(strlen(buffer));
254 if (length == 0) {
255 return accumulator;
256 } else if (buffer[length-1] != '\n') {
257 accumulator = String::Concat(accumulator, String::New(buffer, length));
258 } else if (length > 1 && buffer[length-2] == '\\') {
259 buffer[length-2] = '\n';
260 accumulator = String::Concat(accumulator, String::New(buffer, length-1));
261 } else {
262 return String::Concat(accumulator, String::New(buffer, length-1));
263 }
264 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000265}
266
267
268Handle<Value> Shell::Load(const Arguments& args) {
269 for (int i = 0; i < args.Length(); i++) {
270 HandleScope handle_scope;
271 String::Utf8Value file(args[i]);
272 if (*file == NULL) {
273 return ThrowException(String::New("Error loading file"));
274 }
275 Handle<String> source = ReadFile(*file);
276 if (source.IsEmpty()) {
277 return ThrowException(String::New("Error loading file"));
278 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000279 if (!ExecuteString(source, String::New(*file), false, true)) {
Steve Blockd0582a62009-12-15 09:54:21 +0000280 return ThrowException(String::New("Error executing file"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000281 }
282 }
283 return Undefined();
284}
285
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286static size_t convertToUint(Local<Value> value_in, TryCatch* try_catch) {
287 if (value_in->IsUint32()) {
288 return value_in->Uint32Value();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000289 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100290
291 Local<Value> number = value_in->ToNumber();
292 if (try_catch->HasCaught()) return 0;
293
294 ASSERT(number->IsNumber());
295 Local<Int32> int32 = number->ToInt32();
296 if (try_catch->HasCaught() || int32.IsEmpty()) return 0;
297
298 int32_t raw_value = int32->Int32Value();
299 if (try_catch->HasCaught()) return 0;
300
301 if (raw_value < 0) {
302 ThrowException(String::New("Array length must not be negative."));
303 return 0;
304 }
305
Ben Murdoch85b71792012-04-11 18:30:58 +0100306 static const int kMaxLength = 0x3fffffff;
307#ifndef V8_SHARED
308 ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
309#endif // V8_SHARED
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100310 if (raw_value > static_cast<int32_t>(kMaxLength)) {
311 ThrowException(
312 String::New("Array length exceeds maximum length."));
Ben Murdochc7cc0282012-03-05 14:35:55 +0000313 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100314 return static_cast<size_t>(raw_value);
315}
316
317
318const char kArrayBufferReferencePropName[] = "_is_array_buffer_";
319const char kArrayBufferMarkerPropName[] = "_array_buffer_ref_";
320
321
322Handle<Value> Shell::CreateExternalArray(const Arguments& args,
323 ExternalArrayType type,
324 size_t element_size) {
325 TryCatch try_catch;
326 bool is_array_buffer_construct = element_size == 0;
327 if (is_array_buffer_construct) {
328 type = v8::kExternalByteArray;
329 element_size = 1;
Ben Murdoch85b71792012-04-11 18:30:58 +0100330 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331 ASSERT(element_size == 1 || element_size == 2 || element_size == 4 ||
332 element_size == 8);
333 if (args.Length() == 0) {
334 return ThrowException(
335 String::New("Array constructor must have at least one "
336 "parameter."));
Ben Murdoch85b71792012-04-11 18:30:58 +0100337 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100338 bool first_arg_is_array_buffer =
339 args[0]->IsObject() &&
340 args[0]->ToObject()->Get(
341 String::New(kArrayBufferMarkerPropName))->IsTrue();
342 // Currently, only the following constructors are supported:
343 // TypedArray(unsigned long length)
344 // TypedArray(ArrayBuffer buffer,
345 // optional unsigned long byteOffset,
346 // optional unsigned long length)
347 if (args.Length() > 3) {
348 return ThrowException(
349 String::New("Array constructor from ArrayBuffer must "
350 "have 1-3 parameters."));
351 }
352
353 Local<Value> length_value = (args.Length() < 3)
354 ? (first_arg_is_array_buffer
355 ? args[0]->ToObject()->Get(String::New("length"))
356 : args[0])
357 : args[2];
358 size_t length = convertToUint(length_value, &try_catch);
359 if (try_catch.HasCaught()) return try_catch.Exception();
360
361 void* data = NULL;
362 size_t offset = 0;
363
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000364 Handle<Object> array = Object::New();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100365 if (first_arg_is_array_buffer) {
366 Handle<Object> derived_from = args[0]->ToObject();
367 data = derived_from->GetIndexedPropertiesExternalArrayData();
368
369 size_t array_buffer_length = convertToUint(
370 derived_from->Get(String::New("length")),
371 &try_catch);
372 if (try_catch.HasCaught()) return try_catch.Exception();
373
374 if (data == NULL && array_buffer_length != 0) {
375 return ThrowException(
376 String::New("ArrayBuffer doesn't have data"));
377 }
378
379 if (args.Length() > 1) {
380 offset = convertToUint(args[1], &try_catch);
381 if (try_catch.HasCaught()) return try_catch.Exception();
382
383 // The given byteOffset must be a multiple of the element size of the
384 // specific type, otherwise an exception is raised.
385 if (offset % element_size != 0) {
386 return ThrowException(
387 String::New("offset must be multiple of element_size"));
388 }
389 }
390
391 if (offset > array_buffer_length) {
392 return ThrowException(
393 String::New("byteOffset must be less than ArrayBuffer length."));
394 }
395
396 if (args.Length() == 2) {
397 // If length is not explicitly specified, the length of the ArrayBuffer
398 // minus the byteOffset must be a multiple of the element size of the
399 // specific type, or an exception is raised.
400 length = array_buffer_length - offset;
401 }
402
403 if (args.Length() != 3) {
404 if (length % element_size != 0) {
405 return ThrowException(
406 String::New("ArrayBuffer length minus the byteOffset must be a "
407 "multiple of the element size"));
408 }
409 length /= element_size;
410 }
411
412 // If a given byteOffset and length references an area beyond the end of
413 // the ArrayBuffer an exception is raised.
414 if (offset + (length * element_size) > array_buffer_length) {
415 return ThrowException(
416 String::New("length references an area beyond the end of the "
417 "ArrayBuffer"));
418 }
419
420 // Hold a reference to the ArrayBuffer so its buffer doesn't get collected.
421 array->Set(String::New(kArrayBufferReferencePropName), args[0], ReadOnly);
422 }
423
424 if (is_array_buffer_construct) {
425 array->Set(String::New(kArrayBufferMarkerPropName), True(), ReadOnly);
426 }
427
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000428 Persistent<Object> persistent_array = Persistent<Object>::New(array);
429 persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
430 persistent_array.MarkIndependent();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100431 if (data == NULL && length != 0) {
432 data = calloc(length, element_size);
433 if (data == NULL) {
434 return ThrowException(String::New("Memory allocation failed."));
435 }
436 }
437
438 array->SetIndexedPropertiesToExternalArrayData(
439 reinterpret_cast<uint8_t*>(data) + offset, type,
440 static_cast<int>(length));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000441 array->Set(String::New("length"),
442 Int32::New(static_cast<int32_t>(length)), ReadOnly);
443 array->Set(String::New("BYTES_PER_ELEMENT"),
444 Int32::New(static_cast<int32_t>(element_size)));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000445 return array;
446}
447
448
449void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100450 HandleScope scope;
451 Handle<String> prop_name = String::New(kArrayBufferReferencePropName);
452 Handle<Object> converted_object = object->ToObject();
453 Local<Value> prop_value = converted_object->Get(prop_name);
454 if (data != NULL && !prop_value->IsObject()) {
455 free(data);
456 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000457 object.Dispose();
458}
459
460
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100461Handle<Value> Shell::ArrayBuffer(const Arguments& args) {
462 return CreateExternalArray(args, v8::kExternalByteArray, 0);
463}
464
465
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000466Handle<Value> Shell::Int8Array(const Arguments& args) {
467 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t));
468}
469
470
471Handle<Value> Shell::Uint8Array(const Arguments& args) {
472 return CreateExternalArray(args, kExternalUnsignedByteArray, sizeof(uint8_t));
473}
474
475
476Handle<Value> Shell::Int16Array(const Arguments& args) {
477 return CreateExternalArray(args, kExternalShortArray, sizeof(int16_t));
478}
479
480
481Handle<Value> Shell::Uint16Array(const Arguments& args) {
482 return CreateExternalArray(args, kExternalUnsignedShortArray,
483 sizeof(uint16_t));
484}
485
486
487Handle<Value> Shell::Int32Array(const Arguments& args) {
488 return CreateExternalArray(args, kExternalIntArray, sizeof(int32_t));
489}
490
491
492Handle<Value> Shell::Uint32Array(const Arguments& args) {
493 return CreateExternalArray(args, kExternalUnsignedIntArray, sizeof(uint32_t));
494}
495
496
497Handle<Value> Shell::Float32Array(const Arguments& args) {
498 return CreateExternalArray(args, kExternalFloatArray,
499 sizeof(float)); // NOLINT
500}
501
502
503Handle<Value> Shell::Float64Array(const Arguments& args) {
504 return CreateExternalArray(args, kExternalDoubleArray,
505 sizeof(double)); // NOLINT
506}
507
508
509Handle<Value> Shell::PixelArray(const Arguments& args) {
510 return CreateExternalArray(args, kExternalPixelArray, sizeof(uint8_t));
511}
512
513
Steve Blocka7e24c12009-10-30 11:49:00 +0000514Handle<Value> Shell::Yield(const Arguments& args) {
515 v8::Unlocker unlocker;
516 return Undefined();
517}
518
519
520Handle<Value> Shell::Quit(const Arguments& args) {
521 int exit_code = args[0]->Int32Value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000522#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000523 OnExit();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000524#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 exit(exit_code);
526 return Undefined();
527}
528
529
530Handle<Value> Shell::Version(const Arguments& args) {
531 return String::New(V8::GetVersion());
532}
533
534
535void Shell::ReportException(v8::TryCatch* try_catch) {
536 HandleScope handle_scope;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100537#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
538 bool enter_context = !Context::InContext();
539 if (enter_context) utility_context_->Enter();
540#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000541 v8::String::Utf8Value exception(try_catch->Exception());
542 const char* exception_string = ToCString(exception);
543 Handle<Message> message = try_catch->Message();
544 if (message.IsEmpty()) {
545 // V8 didn't provide any extra information about this error; just
546 // print the exception.
547 printf("%s\n", exception_string);
548 } else {
549 // Print (filename):(line number): (message).
550 v8::String::Utf8Value filename(message->GetScriptResourceName());
551 const char* filename_string = ToCString(filename);
552 int linenum = message->GetLineNumber();
553 printf("%s:%i: %s\n", filename_string, linenum, exception_string);
554 // Print line of source code.
555 v8::String::Utf8Value sourceline(message->GetSourceLine());
556 const char* sourceline_string = ToCString(sourceline);
557 printf("%s\n", sourceline_string);
558 // Print wavy underline (GetUnderline is deprecated).
559 int start = message->GetStartColumn();
560 for (int i = 0; i < start; i++) {
561 printf(" ");
562 }
563 int end = message->GetEndColumn();
564 for (int i = start; i < end; i++) {
565 printf("^");
566 }
567 printf("\n");
Ben Murdoch257744e2011-11-30 15:57:28 +0000568 v8::String::Utf8Value stack_trace(try_catch->StackTrace());
569 if (stack_trace.length() > 0) {
570 const char* stack_trace_string = ToCString(stack_trace);
571 printf("%s\n", stack_trace_string);
572 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000574 printf("\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100575#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
576 if (enter_context) utility_context_->Exit();
577#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000578}
579
580
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000581#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000582Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
583 HandleScope handle_scope;
584 Context::Scope context_scope(utility_context_);
585 Handle<Object> global = utility_context_->Global();
586 Handle<Value> fun = global->Get(String::New("GetCompletions"));
587 static const int kArgc = 3;
588 Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
589 Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
590 return handle_scope.Close(Handle<Array>::Cast(val));
591}
592
593
594#ifdef ENABLE_DEBUGGER_SUPPORT
595Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
596 Context::Scope context_scope(utility_context_);
597 Handle<Object> global = utility_context_->Global();
598 Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
599 static const int kArgc = 1;
600 Handle<Value> argv[kArgc] = { message };
601 Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
602 return Handle<Object>::Cast(val);
603}
604
605
606Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
607 Context::Scope context_scope(utility_context_);
608 Handle<Object> global = utility_context_->Global();
609 Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
610 static const int kArgc = 1;
611 Handle<Value> argv[kArgc] = { command };
612 Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
613 return val;
614}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100615
616
617void Shell::DispatchDebugMessages() {
618 v8::Context::Scope scope(Shell::evaluation_context_);
619 v8::Debug::ProcessDebugMessages();
620}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000621#endif // ENABLE_DEBUGGER_SUPPORT
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000622#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000623
624
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000625#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +0000626int32_t* Counter::Bind(const char* name, bool is_histogram) {
627 int i;
628 for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
629 name_[i] = static_cast<char>(name[i]);
630 name_[i] = '\0';
631 is_histogram_ = is_histogram;
632 return ptr();
633}
634
635
636void Counter::AddSample(int32_t sample) {
637 count_++;
638 sample_total_ += sample;
639}
640
641
642CounterCollection::CounterCollection() {
643 magic_number_ = 0xDEADFACE;
644 max_counters_ = kMaxCounters;
645 max_name_size_ = Counter::kMaxNameSize;
646 counters_in_use_ = 0;
647}
648
649
650Counter* CounterCollection::GetNextCounter() {
651 if (counters_in_use_ == kMaxCounters) return NULL;
652 return &counters_[counters_in_use_++];
653}
654
655
656void Shell::MapCounters(const char* name) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000657 counters_file_ = i::OS::MemoryMappedFile::create(
658 name, sizeof(CounterCollection), &local_counters_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 void* memory = (counters_file_ == NULL) ?
660 NULL : counters_file_->memory();
661 if (memory == NULL) {
662 printf("Could not map counters file %s\n", name);
Ben Murdoch589d6972011-11-30 16:04:58 +0000663 Exit(1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 }
665 counters_ = static_cast<CounterCollection*>(memory);
666 V8::SetCounterFunction(LookupCounter);
667 V8::SetCreateHistogramFunction(CreateHistogram);
668 V8::SetAddHistogramSampleFunction(AddHistogramSample);
669}
670
671
672int CounterMap::Hash(const char* name) {
673 int h = 0;
674 int c;
675 while ((c = *name++) != 0) {
676 h += h << 5;
677 h += c;
678 }
679 return h;
680}
681
682
683Counter* Shell::GetCounter(const char* name, bool is_histogram) {
684 Counter* counter = counter_map_->Lookup(name);
685
686 if (counter == NULL) {
687 counter = counters_->GetNextCounter();
688 if (counter != NULL) {
689 counter_map_->Set(name, counter);
690 counter->Bind(name, is_histogram);
691 }
692 } else {
693 ASSERT(counter->is_histogram() == is_histogram);
694 }
695 return counter;
696}
697
698
699int* Shell::LookupCounter(const char* name) {
700 Counter* counter = GetCounter(name, false);
701
702 if (counter != NULL) {
703 return counter->ptr();
704 } else {
705 return NULL;
706 }
707}
708
709
710void* Shell::CreateHistogram(const char* name,
711 int min,
712 int max,
713 size_t buckets) {
714 return GetCounter(name, true);
715}
716
717
718void Shell::AddHistogramSample(void* histogram, int sample) {
719 Counter* counter = reinterpret_cast<Counter*>(histogram);
720 counter->AddSample(sample);
721}
722
723
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000724void Shell::InstallUtilityScript() {
725 Locker lock;
Steve Blocka7e24c12009-10-30 11:49:00 +0000726 HandleScope scope;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000727 // If we use the utility context, we have to set the security tokens so that
728 // utility, evaluation and debug context can all access each other.
Steve Blocka7e24c12009-10-30 11:49:00 +0000729 utility_context_->SetSecurityToken(Undefined());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000730 evaluation_context_->SetSecurityToken(Undefined());
Steve Blocka7e24c12009-10-30 11:49:00 +0000731 Context::Scope utility_scope(utility_context_);
732
Steve Blocka7e24c12009-10-30 11:49:00 +0000733#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100734 if (i::FLAG_debugger) printf("JavaScript debugger enabled\n");
Steve Blocka7e24c12009-10-30 11:49:00 +0000735 // Install the debugger object in the utility scope
Steve Block44f0eee2011-05-26 01:26:41 +0100736 i::Debug* debug = i::Isolate::Current()->debug();
737 debug->Load();
738 i::Handle<i::JSObject> js_debug
739 = i::Handle<i::JSObject>(debug->debug_context()->global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000740 utility_context_->Global()->Set(String::New("$debug"),
Steve Block44f0eee2011-05-26 01:26:41 +0100741 Utils::ToLocal(js_debug));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000742 debug->debug_context()->set_security_token(HEAP->undefined_value());
743#endif // ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000744
745 // Run the d8 shell utility script in the utility context
746 int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000747 i::Vector<const char> shell_source =
748 i::NativesCollection<i::D8>::GetRawScriptSource(source_index);
749 i::Vector<const char> shell_source_name =
750 i::NativesCollection<i::D8>::GetScriptName(source_index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 Handle<String> source = String::New(shell_source.start(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000752 shell_source.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000753 Handle<String> name = String::New(shell_source_name.start(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000754 shell_source_name.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000755 Handle<Script> script = Script::Compile(source, name);
756 script->Run();
Steve Blocka7e24c12009-10-30 11:49:00 +0000757 // Mark the d8 shell script as native to avoid it showing up as normal source
758 // in the debugger.
Steve Block6ded16b2010-05-10 14:33:55 +0100759 i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
760 i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
761 ? i::Handle<i::Script>(i::Script::cast(
762 i::JSFunction::cast(*compiled_script)->shared()->script()))
763 : i::Handle<i::Script>(i::Script::cast(
764 i::SharedFunctionInfo::cast(*compiled_script)->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
766
Steve Blocka7e24c12009-10-30 11:49:00 +0000767#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000768 // Start the in-process debugger if requested.
769 if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
770 v8::Debug::SetDebugEventListener(HandleDebugEvent);
771 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000772#endif // ENABLE_DEBUGGER_SUPPORT
773}
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000774#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000775
776
777#ifdef COMPRESS_STARTUP_DATA_BZ2
778class BZip2Decompressor : public v8::StartupDataDecompressor {
779 public:
780 virtual ~BZip2Decompressor() { }
781
782 protected:
783 virtual int DecompressData(char* raw_data,
784 int* raw_data_size,
785 const char* compressed_data,
786 int compressed_data_size) {
787 ASSERT_EQ(v8::StartupData::kBZip2,
788 v8::V8::GetCompressedStartupDataAlgorithm());
789 unsigned int decompressed_size = *raw_data_size;
790 int result =
791 BZ2_bzBuffToBuffDecompress(raw_data,
792 &decompressed_size,
793 const_cast<char*>(compressed_data),
794 compressed_data_size,
795 0, 1);
796 if (result == BZ_OK) {
797 *raw_data_size = decompressed_size;
798 }
799 return result;
800 }
801};
Steve Blocka7e24c12009-10-30 11:49:00 +0000802#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000803
804Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
805 Handle<ObjectTemplate> global_template = ObjectTemplate::New();
806 global_template->Set(String::New("print"), FunctionTemplate::New(Print));
807 global_template->Set(String::New("write"), FunctionTemplate::New(Write));
808 global_template->Set(String::New("read"), FunctionTemplate::New(Read));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100809 global_template->Set(String::New("readbinary"),
810 FunctionTemplate::New(ReadBinary));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000811 global_template->Set(String::New("readline"),
812 FunctionTemplate::New(ReadLine));
813 global_template->Set(String::New("load"), FunctionTemplate::New(Load));
814 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
815 global_template->Set(String::New("version"), FunctionTemplate::New(Version));
Ben Murdoch589d6972011-11-30 16:04:58 +0000816 global_template->Set(String::New("enableProfiler"),
817 FunctionTemplate::New(EnableProfiler));
818 global_template->Set(String::New("disableProfiler"),
819 FunctionTemplate::New(DisableProfiler));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000820
821 // Bind the handlers for external arrays.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 global_template->Set(String::New("ArrayBuffer"),
823 FunctionTemplate::New(ArrayBuffer));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000824 global_template->Set(String::New("Int8Array"),
825 FunctionTemplate::New(Int8Array));
826 global_template->Set(String::New("Uint8Array"),
827 FunctionTemplate::New(Uint8Array));
828 global_template->Set(String::New("Int16Array"),
829 FunctionTemplate::New(Int16Array));
830 global_template->Set(String::New("Uint16Array"),
831 FunctionTemplate::New(Uint16Array));
832 global_template->Set(String::New("Int32Array"),
833 FunctionTemplate::New(Int32Array));
834 global_template->Set(String::New("Uint32Array"),
835 FunctionTemplate::New(Uint32Array));
836 global_template->Set(String::New("Float32Array"),
837 FunctionTemplate::New(Float32Array));
838 global_template->Set(String::New("Float64Array"),
839 FunctionTemplate::New(Float64Array));
840 global_template->Set(String::New("PixelArray"),
841 FunctionTemplate::New(PixelArray));
842
843#ifdef LIVE_OBJECT_LIST
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000844 global_template->Set(String::New("lol_is_enabled"), True());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000845#else
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000846 global_template->Set(String::New("lol_is_enabled"), False());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000847#endif
848
Ben Murdoch589d6972011-11-30 16:04:58 +0000849#if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000850 Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
851 AddOSMethods(os_templ);
852 global_template->Set(String::New("os"), os_templ);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000853#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000854
855 return global_template;
Steve Blocka7e24c12009-10-30 11:49:00 +0000856}
857
858
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000859void Shell::Initialize() {
860#ifdef COMPRESS_STARTUP_DATA_BZ2
861 BZip2Decompressor startup_data_decompressor;
862 int bz2_result = startup_data_decompressor.Decompress();
863 if (bz2_result != BZ_OK) {
864 fprintf(stderr, "bzip error code: %d\n", bz2_result);
Ben Murdoch589d6972011-11-30 16:04:58 +0000865 Exit(1);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000866 }
867#endif
868
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000869#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000870 Shell::counter_map_ = new CounterMap();
871 // Set up counters
872 if (i::StrLength(i::FLAG_map_counters) != 0)
873 MapCounters(i::FLAG_map_counters);
874 if (i::FLAG_dump_counters) {
875 V8::SetCounterFunction(LookupCounter);
876 V8::SetCreateHistogramFunction(CreateHistogram);
877 V8::SetAddHistogramSampleFunction(AddHistogramSample);
878 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000879#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000880 if (options.test_shell) return;
881
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000882#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000883 Locker lock;
884 HandleScope scope;
885 Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
886 utility_context_ = Context::New(NULL, global_template);
887
888#ifdef ENABLE_DEBUGGER_SUPPORT
889 // Start the debugger agent if requested.
890 if (i::FLAG_debugger_agent) {
891 v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100892 v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000893 }
894#endif // ENABLE_DEBUGGER_SUPPORT
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000895#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000896}
897
898
899Persistent<Context> Shell::CreateEvaluationContext() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000900#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000901 // This needs to be a critical section since this is not thread-safe
902 i::ScopedLock lock(context_mutex_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000903#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000904 // Initialize the global objects
905 Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
906 Persistent<Context> context = Context::New(NULL, global_template);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100907 ASSERT(!context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000908 Context::Scope scope(context);
909
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000910#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000911 i::JSArguments js_args = i::FLAG_js_arguments;
912 i::Handle<i::FixedArray> arguments_array =
913 FACTORY->NewFixedArray(js_args.argc());
914 for (int j = 0; j < js_args.argc(); j++) {
915 i::Handle<i::String> arg =
916 FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
917 arguments_array->set(j, *arg);
918 }
919 i::Handle<i::JSArray> arguments_jsarray =
920 FACTORY->NewJSArrayWithElements(arguments_array);
921 context->Global()->Set(String::New("arguments"),
922 Utils::ToLocal(arguments_jsarray));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000923#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000924 return context;
925}
926
927
Ben Murdoch589d6972011-11-30 16:04:58 +0000928void Shell::Exit(int exit_code) {
929 // Use _exit instead of exit to avoid races between isolate
930 // threads and static destructors.
931 fflush(stdout);
932 fflush(stderr);
933 _exit(exit_code);
934}
935
936
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000937#ifndef V8_SHARED
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100938struct CounterAndKey {
939 Counter* counter;
940 const char* key;
941};
942
943
944int CompareKeys(const void* a, const void* b) {
945 return strcmp(static_cast<const CounterAndKey*>(a)->key,
946 static_cast<const CounterAndKey*>(b)->key);
947}
948
949
Steve Blocka7e24c12009-10-30 11:49:00 +0000950void Shell::OnExit() {
Ben Murdoch589d6972011-11-30 16:04:58 +0000951 if (console != NULL) console->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 if (i::FLAG_dump_counters) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100953 int number_of_counters = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000954 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100955 number_of_counters++;
956 }
957 CounterAndKey* counters = new CounterAndKey[number_of_counters];
958 int j = 0;
959 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) {
960 counters[j].counter = i.CurrentValue();
961 counters[j].key = i.CurrentKey();
962 }
963 qsort(counters, number_of_counters, sizeof(counters[0]), CompareKeys);
964 printf("+--------------------------------------------+-------------+\n");
965 printf("| Name | Value |\n");
966 printf("+--------------------------------------------+-------------+\n");
967 for (j = 0; j < number_of_counters; j++) {
968 Counter* counter = counters[j].counter;
969 const char* key = counters[j].key;
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 if (counter->is_histogram()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100971 printf("| c:%-40s | %11i |\n", key, counter->count());
972 printf("| t:%-40s | %11i |\n", key, counter->sample_total());
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100974 printf("| %-42s | %11i |\n", key, counter->count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 }
976 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100977 printf("+--------------------------------------------+-------------+\n");
978 delete [] counters;
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 }
980 if (counters_file_ != NULL)
981 delete counters_file_;
982}
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000983#endif // V8_SHARED
984
985
986static FILE* FOpen(const char* path, const char* mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100987#if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000988 FILE* result;
989 if (fopen_s(&result, path, mode) == 0) {
990 return result;
991 } else {
992 return NULL;
993 }
994#else
995 FILE* file = fopen(path, mode);
996 if (file == NULL) return NULL;
997 struct stat file_stat;
998 if (fstat(fileno(file), &file_stat) != 0) return NULL;
999 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
1000 if (is_regular_file) return file;
1001 fclose(file);
1002 return NULL;
1003#endif
1004}
Steve Blocka7e24c12009-10-30 11:49:00 +00001005
1006
1007static char* ReadChars(const char* name, int* size_out) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001008 // Release the V8 lock while reading files.
1009 v8::Unlocker unlocker(Isolate::GetCurrent());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001010 FILE* file = FOpen(name, "rb");
Steve Blocka7e24c12009-10-30 11:49:00 +00001011 if (file == NULL) return NULL;
1012
1013 fseek(file, 0, SEEK_END);
1014 int size = ftell(file);
1015 rewind(file);
1016
1017 char* chars = new char[size + 1];
1018 chars[size] = '\0';
1019 for (int i = 0; i < size;) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001020 int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 i += read;
1022 }
1023 fclose(file);
1024 *size_out = size;
1025 return chars;
1026}
1027
1028
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001029Handle<Value> Shell::ReadBinary(const Arguments& args) {
1030 String::Utf8Value filename(args[0]);
1031 int size;
1032 if (*filename == NULL) {
1033 return ThrowException(String::New("Error loading file"));
1034 }
1035 char* chars = ReadChars(*filename, &size);
1036 if (chars == NULL) {
1037 return ThrowException(String::New("Error reading file"));
1038 }
1039 // We skip checking the string for UTF8 characters and use it raw as
1040 // backing store for the external string with 8-bit characters.
1041 BinaryResource* resource = new BinaryResource(chars, size);
1042 return String::NewExternal(resource);
1043}
1044
1045
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001046#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001047static char* ReadToken(char* data, char token) {
1048 char* next = i::OS::StrChr(data, token);
1049 if (next != NULL) {
1050 *next = '\0';
1051 return (next + 1);
1052 }
1053
1054 return NULL;
1055}
1056
1057
1058static char* ReadLine(char* data) {
1059 return ReadToken(data, '\n');
1060}
1061
1062
1063static char* ReadWord(char* data) {
1064 return ReadToken(data, ' ');
1065}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001066#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001067
1068
1069// Reads a file into a v8 string.
1070Handle<String> Shell::ReadFile(const char* name) {
1071 int size = 0;
1072 char* chars = ReadChars(name, &size);
1073 if (chars == NULL) return Handle<String>();
1074 Handle<String> result = String::New(chars);
1075 delete[] chars;
1076 return result;
1077}
1078
1079
1080void Shell::RunShell() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001081 Locker locker;
1082 Context::Scope context_scope(evaluation_context_);
Ben Murdoch589d6972011-11-30 16:04:58 +00001083 HandleScope outer_scope;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001084 Handle<String> name = String::New("(d8)");
Ben Murdoch589d6972011-11-30 16:04:58 +00001085 console = LineEditor::Get();
1086 printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name());
Ben Murdoch589d6972011-11-30 16:04:58 +00001087 console->Open();
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 while (true) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001089 HandleScope inner_scope;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001090 Handle<String> input = console->Prompt(Shell::kPrompt);
1091 if (input.IsEmpty()) break;
1092 ExecuteString(input, name, true, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001093 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 printf("\n");
1095}
1096
1097
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001098#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001099class ShellThread : public i::Thread {
1100 public:
Ben Murdoch589d6972011-11-30 16:04:58 +00001101 // Takes ownership of the underlying char array of |files|.
1102 ShellThread(int no, char* files)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001103 : Thread("d8:ShellThread"),
1104 no_(no), files_(files) { }
Ben Murdoch589d6972011-11-30 16:04:58 +00001105
1106 ~ShellThread() {
1107 delete[] files_;
1108 }
1109
Steve Blocka7e24c12009-10-30 11:49:00 +00001110 virtual void Run();
1111 private:
1112 int no_;
Ben Murdoch589d6972011-11-30 16:04:58 +00001113 char* files_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001114};
1115
1116
1117void ShellThread::Run() {
Ben Murdoch589d6972011-11-30 16:04:58 +00001118 char* ptr = files_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 while ((ptr != NULL) && (*ptr != '\0')) {
1120 // For each newline-separated line.
1121 char* next_line = ReadLine(ptr);
1122
1123 if (*ptr == '#') {
1124 // Skip comment lines.
1125 ptr = next_line;
1126 continue;
1127 }
1128
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001129 // Prepare the context for this thread.
1130 Locker locker;
Ben Murdoch589d6972011-11-30 16:04:58 +00001131 HandleScope outer_scope;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001132 Persistent<Context> thread_context = Shell::CreateEvaluationContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00001133 Context::Scope context_scope(thread_context);
1134
1135 while ((ptr != NULL) && (*ptr != '\0')) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001136 HandleScope inner_scope;
Steve Blocka7e24c12009-10-30 11:49:00 +00001137 char* filename = ptr;
1138 ptr = ReadWord(ptr);
1139
1140 // Skip empty strings.
1141 if (strlen(filename) == 0) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001142 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001143 }
1144
1145 Handle<String> str = Shell::ReadFile(filename);
1146 if (str.IsEmpty()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001147 printf("File '%s' not found\n", filename);
1148 Shell::Exit(1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 }
1150
1151 Shell::ExecuteString(str, String::New(filename), false, false);
1152 }
1153
1154 thread_context.Dispose();
1155 ptr = next_line;
1156 }
1157}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001158#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001159
1160
Ben Murdoch589d6972011-11-30 16:04:58 +00001161SourceGroup::~SourceGroup() {
1162#ifndef V8_SHARED
1163 delete next_semaphore_;
1164 next_semaphore_ = NULL;
1165 delete done_semaphore_;
1166 done_semaphore_ = NULL;
1167 delete thread_;
1168 thread_ = NULL;
1169#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001170}
Steve Blocka7e24c12009-10-30 11:49:00 +00001171
Steve Blocka7e24c12009-10-30 11:49:00 +00001172
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001173void SourceGroup::Execute() {
1174 for (int i = begin_offset_; i < end_offset_; ++i) {
1175 const char* arg = argv_[i];
1176 if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
1177 // Execute argument given to -e option directly.
1178 HandleScope handle_scope;
1179 Handle<String> file_name = String::New("unnamed");
1180 Handle<String> source = String::New(argv_[i + 1]);
1181 if (!Shell::ExecuteString(source, file_name, false, true)) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001182 Shell::Exit(1);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001183 }
1184 ++i;
1185 } else if (arg[0] == '-') {
1186 // Ignore other options. They have been parsed already.
1187 } else {
1188 // Use all other arguments as names of files to load and run.
1189 HandleScope handle_scope;
1190 Handle<String> file_name = String::New(arg);
1191 Handle<String> source = ReadFile(arg);
1192 if (source.IsEmpty()) {
1193 printf("Error reading '%s'\n", arg);
Ben Murdoch589d6972011-11-30 16:04:58 +00001194 Shell::Exit(1);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001195 }
1196 if (!Shell::ExecuteString(source, file_name, false, true)) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001197 Shell::Exit(1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 }
1199 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001200 }
1201}
Steve Blocka7e24c12009-10-30 11:49:00 +00001202
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001203
1204Handle<String> SourceGroup::ReadFile(const char* name) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001205 int size;
1206 const char* chars = ReadChars(name, &size);
1207 if (chars == NULL) return Handle<String>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001208 Handle<String> result = String::New(chars, size);
1209 delete[] chars;
1210 return result;
1211}
1212
1213
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001214#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001215i::Thread::Options SourceGroup::GetThreadOptions() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001216 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
1217 // which is not enough to parse the big literal expressions used in tests.
1218 // The stack size should be at least StackGuard::kLimitSize + some
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001219 // OS-specific padding for thread startup code. 2Mbytes seems to be enough.
1220 return i::Thread::Options("IsolateThread", 2 * MB);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001221}
1222
1223
1224void SourceGroup::ExecuteInThread() {
1225 Isolate* isolate = Isolate::New();
1226 do {
1227 if (next_semaphore_ != NULL) next_semaphore_->Wait();
1228 {
1229 Isolate::Scope iscope(isolate);
1230 Locker lock(isolate);
1231 HandleScope scope;
1232 Persistent<Context> context = Shell::CreateEvaluationContext();
1233 {
1234 Context::Scope cscope(context);
1235 Execute();
1236 }
1237 context.Dispose();
1238 }
1239 if (done_semaphore_ != NULL) done_semaphore_->Signal();
1240 } while (!Shell::options.last_run);
1241 isolate->Dispose();
1242}
1243
1244
1245void SourceGroup::StartExecuteInThread() {
1246 if (thread_ == NULL) {
1247 thread_ = new IsolateThread(this);
1248 thread_->Start();
1249 }
1250 next_semaphore_->Signal();
1251}
1252
1253
1254void SourceGroup::WaitForThread() {
1255 if (thread_ == NULL) return;
1256 if (Shell::options.last_run) {
1257 thread_->Join();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001258 } else {
1259 done_semaphore_->Wait();
1260 }
1261}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001262#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001263
1264
1265bool Shell::SetOptions(int argc, char* argv[]) {
1266 for (int i = 0; i < argc; i++) {
1267 if (strcmp(argv[i], "--stress-opt") == 0) {
1268 options.stress_opt = true;
1269 argv[i] = NULL;
1270 } else if (strcmp(argv[i], "--stress-deopt") == 0) {
1271 options.stress_deopt = true;
1272 argv[i] = NULL;
1273 } else if (strcmp(argv[i], "--noalways-opt") == 0) {
1274 // No support for stressing if we can't use --always-opt.
1275 options.stress_opt = false;
1276 options.stress_deopt = false;
1277 } else if (strcmp(argv[i], "--shell") == 0) {
1278 options.interactive_shell = true;
1279 argv[i] = NULL;
1280 } else if (strcmp(argv[i], "--test") == 0) {
1281 options.test_shell = true;
1282 argv[i] = NULL;
1283 } else if (strcmp(argv[i], "--preemption") == 0) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001284#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001285 printf("D8 with shared library does not support multi-threading\n");
1286 return false;
1287#else
1288 options.use_preemption = true;
1289 argv[i] = NULL;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001290#endif // V8_SHARED
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001291 } else if (strcmp(argv[i], "--nopreemption") == 0) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001292#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001293 printf("D8 with shared library does not support multi-threading\n");
1294 return false;
1295#else
1296 options.use_preemption = false;
1297 argv[i] = NULL;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001298#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001299 } else if (strcmp(argv[i], "--preemption-interval") == 0) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001300#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001301 printf("D8 with shared library does not support multi-threading\n");
1302 return false;
1303#else
1304 if (++i < argc) {
1305 argv[i-1] = NULL;
1306 char* end = NULL;
1307 options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
1308 if (options.preemption_interval <= 0
1309 || *end != '\0'
1310 || errno == ERANGE) {
1311 printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
1312 return false;
1313 }
1314 argv[i] = NULL;
1315 } else {
1316 printf("Missing value for --preemption-interval\n");
1317 return false;
1318 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001319#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001320 } else if (strcmp(argv[i], "-f") == 0) {
1321 // Ignore any -f flags for compatibility with other stand-alone
1322 // JavaScript engines.
1323 continue;
1324 } else if (strcmp(argv[i], "--isolate") == 0) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001325#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001326 printf("D8 with shared library does not support multi-threading\n");
1327 return false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001328#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001329 options.num_isolates++;
Ben Murdoch589d6972011-11-30 16:04:58 +00001330 } else if (strcmp(argv[i], "-p") == 0) {
1331#ifdef V8_SHARED
1332 printf("D8 with shared library does not support multi-threading\n");
1333 return false;
1334#else
1335 options.num_parallel_files++;
1336#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001337 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001338#ifdef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001339 else if (strcmp(argv[i], "--dump-counters") == 0) {
1340 printf("D8 with shared library does not include counters\n");
1341 return false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001342 } else if (strcmp(argv[i], "--debugger") == 0) {
1343 printf("Javascript debugger not included\n");
1344 return false;
1345 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001346#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001347 }
1348
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001349#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001350 // Run parallel threads if we are not using --isolate
Ben Murdoch589d6972011-11-30 16:04:58 +00001351 options.parallel_files = new char*[options.num_parallel_files];
1352 int parallel_files_set = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001353 for (int i = 1; i < argc; i++) {
1354 if (argv[i] == NULL) continue;
1355 if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
1356 if (options.num_isolates > 1) {
1357 printf("-p is not compatible with --isolate\n");
1358 return false;
1359 }
1360 argv[i] = NULL;
Ben Murdoch589d6972011-11-30 16:04:58 +00001361 i++;
1362 options.parallel_files[parallel_files_set] = argv[i];
1363 parallel_files_set++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001364 argv[i] = NULL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001365 }
1366 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001367 if (parallel_files_set != options.num_parallel_files) {
1368 printf("-p requires a file containing a list of files as parameter\n");
1369 return false;
1370 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001371#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001372
1373 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
1374
Ben Murdoch589d6972011-11-30 16:04:58 +00001375 // Set up isolated source groups.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001376 options.isolate_sources = new SourceGroup[options.num_isolates];
1377 SourceGroup* current = options.isolate_sources;
1378 current->Begin(argv, 1);
1379 for (int i = 1; i < argc; i++) {
1380 const char* str = argv[i];
1381 if (strcmp(str, "--isolate") == 0) {
1382 current->End(i);
1383 current++;
1384 current->Begin(argv, i + 1);
1385 } else if (strncmp(argv[i], "--", 2) == 0) {
1386 printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]);
1387 }
1388 }
1389 current->End(argc);
1390
1391 return true;
1392}
1393
1394
1395int Shell::RunMain(int argc, char* argv[]) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001396#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001397 i::List<i::Thread*> threads(1);
Ben Murdoch589d6972011-11-30 16:04:58 +00001398 if (options.parallel_files != NULL) {
1399 for (int i = 0; i < options.num_parallel_files; i++) {
1400 char* files = NULL;
1401 { Locker lock(Isolate::GetCurrent());
1402 int size = 0;
1403 files = ReadChars(options.parallel_files[i], &size);
1404 }
1405 if (files == NULL) {
1406 printf("File list '%s' not found\n", options.parallel_files[i]);
1407 Exit(1);
1408 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001409 ShellThread* thread = new ShellThread(threads.length(), files);
1410 thread->Start();
1411 threads.Add(thread);
1412 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001413 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001414 for (int i = 1; i < options.num_isolates; ++i) {
1415 options.isolate_sources[i].StartExecuteInThread();
1416 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001417#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001418 { // NOLINT
1419 Locker lock;
1420 HandleScope scope;
1421 Persistent<Context> context = CreateEvaluationContext();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001422 if (options.last_run) {
1423 // Keep using the same context in the interactive shell.
1424 evaluation_context_ = context;
1425#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
1426 // If the interactive debugger is enabled make sure to activate
1427 // it before running the files passed on the command line.
1428 if (i::FLAG_debugger) {
1429 InstallUtilityScript();
1430 }
1431#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
1432 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001433 {
1434 Context::Scope cscope(context);
1435 options.isolate_sources[0].Execute();
1436 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001437 if (!options.last_run) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001438 context.Dispose();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001439#if !defined(V8_SHARED)
1440 if (i::FLAG_send_idle_notification) {
1441 const int kLongIdlePauseInMs = 1000;
1442 V8::ContextDisposedNotification();
1443 V8::IdleNotification(kLongIdlePauseInMs);
1444 }
1445#endif // !V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001446 }
1447
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001448#ifndef V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001449 // Start preemption if threads have been created and preemption is enabled.
Ben Murdoch589d6972011-11-30 16:04:58 +00001450 if (threads.length() > 0
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001451 && options.use_preemption) {
1452 Locker::StartPreemption(options.preemption_interval);
1453 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001454#endif // V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001455 }
1456
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001457#ifndef V8_SHARED
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001458 for (int i = 1; i < options.num_isolates; ++i) {
1459 options.isolate_sources[i].WaitForThread();
1460 }
1461
Ben Murdoch589d6972011-11-30 16:04:58 +00001462 for (int i = 0; i < threads.length(); i++) {
1463 i::Thread* thread = threads[i];
1464 thread->Join();
1465 delete thread;
1466 }
1467
1468 if (threads.length() > 0 && options.use_preemption) {
1469 Locker lock;
1470 Locker::StopPreemption();
1471 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001472#endif // V8_SHARED
Steve Blocka7e24c12009-10-30 11:49:00 +00001473 return 0;
1474}
1475
1476
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001477int Shell::Main(int argc, char* argv[]) {
1478 if (!SetOptions(argc, argv)) return 1;
1479 Initialize();
1480
1481 int result = 0;
1482 if (options.stress_opt || options.stress_deopt) {
1483 Testing::SetStressRunType(
1484 options.stress_opt ? Testing::kStressTypeOpt
1485 : Testing::kStressTypeDeopt);
1486 int stress_runs = Testing::GetStressRuns();
1487 for (int i = 0; i < stress_runs && result == 0; i++) {
1488 printf("============ Stress %d/%d ============\n", i + 1, stress_runs);
1489 Testing::PrepareStressRun(i);
1490 options.last_run = (i == stress_runs - 1);
1491 result = RunMain(argc, argv);
1492 }
1493 printf("======== Full Deoptimization =======\n");
1494 Testing::DeoptimizeAll();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001495#if !defined(V8_SHARED)
1496 } else if (i::FLAG_stress_runs > 0) {
1497 int stress_runs = i::FLAG_stress_runs;
1498 for (int i = 0; i < stress_runs && result == 0; i++) {
1499 printf("============ Run %d/%d ============\n", i + 1, stress_runs);
1500 options.last_run = (i == stress_runs - 1);
1501 result = RunMain(argc, argv);
1502 }
1503#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001504 } else {
1505 result = RunMain(argc, argv);
1506 }
1507
1508
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001509#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001510 // Run remote debugger if requested, but never on --test
1511 if (i::FLAG_remote_debugger && !options.test_shell) {
1512 InstallUtilityScript();
1513 RunRemoteDebugger(i::FLAG_debugger_port);
1514 return 0;
1515 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001516#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001517
1518 // Run interactive shell if explicitly requested or if no script has been
1519 // executed, but never on --test
1520
1521 if (( options.interactive_shell
1522 || !options.script_executed )
1523 && !options.test_shell ) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001524#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
1525 if (!i::FLAG_debugger) {
1526 InstallUtilityScript();
1527 }
1528#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001529 RunShell();
1530 }
1531
1532 V8::Dispose();
1533
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001534#ifndef V8_SHARED
1535 OnExit();
1536#endif // V8_SHARED
1537
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001538 return result;
1539}
1540
Steve Blocka7e24c12009-10-30 11:49:00 +00001541} // namespace v8
1542
1543
Ben Murdoch257744e2011-11-30 15:57:28 +00001544#ifndef GOOGLE3
Steve Blocka7e24c12009-10-30 11:49:00 +00001545int main(int argc, char* argv[]) {
1546 return v8::Shell::Main(argc, argv);
1547}
Ben Murdoch257744e2011-11-30 15:57:28 +00001548#endif