Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/src/d8.cc b/src/d8.cc
index 45781cf..9db7744 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1,32 +1,10 @@
// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#ifdef USING_V8_SHARED // Defined when linking against shared lib on Windows.
+// Defined when linking against shared lib on Windows.
+#if defined(USING_V8_SHARED) && !defined(V8_SHARED)
#define V8_SHARED
#endif
@@ -41,95 +19,155 @@
#ifdef V8_SHARED
#include <assert.h>
-#include "../include/v8-testing.h"
#endif // V8_SHARED
-#include "d8.h"
-
#ifndef V8_SHARED
-#include "api.h"
-#include "checks.h"
-#include "d8-debug.h"
-#include "debug.h"
-#include "natives.h"
-#include "platform.h"
-#include "v8.h"
+#include <algorithm>
+#endif // !V8_SHARED
+
+#ifdef V8_SHARED
+#include "include/v8-testing.h"
#endif // V8_SHARED
+#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
+#include "src/gdb-jit.h"
+#endif
+
+#ifdef ENABLE_VTUNE_JIT_INTERFACE
+#include "src/third_party/vtune/v8-vtune.h"
+#endif
+
+#include "src/d8.h"
+
+#include "include/libplatform/libplatform.h"
+#ifndef V8_SHARED
+#include "src/api.h"
+#include "src/base/cpu.h"
+#include "src/base/logging.h"
+#include "src/base/platform/platform.h"
+#include "src/base/sys-info.h"
+#include "src/d8-debug.h"
+#include "src/debug.h"
+#include "src/natives.h"
+#include "src/v8.h"
+#endif // !V8_SHARED
+
#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h> // NOLINT
-#endif
+#else
+#include <windows.h> // NOLINT
+#if defined(_MSC_VER)
+#include <crtdbg.h> // NOLINT
+#endif // defined(_MSC_VER)
+#endif // !defined(_WIN32) && !defined(_WIN64)
-#ifndef ASSERT
-#define ASSERT(condition) assert(condition)
+#ifndef DCHECK
+#define DCHECK(condition) assert(condition)
#endif
namespace v8 {
-LineEditor *LineEditor::first_ = NULL;
-
-LineEditor::LineEditor(Type type, const char* name)
- : type_(type),
- name_(name),
- next_(first_) {
- first_ = this;
+static Handle<Value> Throw(Isolate* isolate, const char* message) {
+ return isolate->ThrowException(String::NewFromUtf8(isolate, message));
}
-LineEditor* LineEditor::Get() {
- LineEditor* current = first_;
- LineEditor* best = current;
- while (current != NULL) {
- if (current->type_ > best->type_)
- best = current;
- current = current->next_;
+
+class PerIsolateData {
+ public:
+ explicit PerIsolateData(Isolate* isolate) : isolate_(isolate), realms_(NULL) {
+ HandleScope scope(isolate);
+ isolate->SetData(0, this);
}
- return best;
+
+ ~PerIsolateData() {
+ isolate_->SetData(0, NULL); // Not really needed, just to be sure...
+ }
+
+ inline static PerIsolateData* Get(Isolate* isolate) {
+ return reinterpret_cast<PerIsolateData*>(isolate->GetData(0));
+ }
+
+ class RealmScope {
+ public:
+ explicit RealmScope(PerIsolateData* data);
+ ~RealmScope();
+ private:
+ PerIsolateData* data_;
+ };
+
+ private:
+ friend class Shell;
+ friend class RealmScope;
+ Isolate* isolate_;
+ int realm_count_;
+ int realm_current_;
+ int realm_switch_;
+ Persistent<Context>* realms_;
+ Persistent<Value> realm_shared_;
+
+ int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
+ int arg_offset);
+ int RealmFind(Handle<Context> context);
+};
+
+
+LineEditor *LineEditor::current_ = NULL;
+
+
+LineEditor::LineEditor(Type type, const char* name)
+ : type_(type), name_(name) {
+ if (current_ == NULL || current_->type_ < type) current_ = this;
}
class DumbLineEditor: public LineEditor {
public:
- DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
+ explicit DumbLineEditor(Isolate* isolate)
+ : LineEditor(LineEditor::DUMB, "dumb"), isolate_(isolate) { }
virtual Handle<String> Prompt(const char* prompt);
+ private:
+ Isolate* isolate_;
};
-static DumbLineEditor dumb_line_editor;
-
-
Handle<String> DumbLineEditor::Prompt(const char* prompt) {
printf("%s", prompt);
- return Shell::ReadFromStdin();
+#if defined(__native_client__)
+ // Native Client libc is used to being embedded in Chrome and
+ // has trouble recognizing when to flush.
+ fflush(stdout);
+#endif
+ return Shell::ReadFromStdin(isolate_);
}
#ifndef V8_SHARED
CounterMap* Shell::counter_map_;
-i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
+base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_;
-i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
+base::Mutex Shell::context_mutex_;
+const base::TimeTicks Shell::kInitialTicks =
+ base::TimeTicks::HighResolutionNow();
Persistent<Context> Shell::utility_context_;
-#endif // V8_SHARED
+#endif // !V8_SHARED
-LineEditor* Shell::console = NULL;
Persistent<Context> Shell::evaluation_context_;
ShellOptions Shell::options;
const char* Shell::kPrompt = "d8> ";
+#ifndef V8_SHARED
const int MB = 1024 * 1024;
-
-#ifndef V8_SHARED
bool CounterMap::Match(void* key1, void* key2) {
const char* name1 = reinterpret_cast<const char*>(key1);
const char* name2 = reinterpret_cast<const char*>(key2);
return strcmp(name1, name2) == 0;
}
-#endif // V8_SHARED
+#endif // !V8_SHARED
// Converts a V8 value to a C string.
@@ -138,46 +176,106 @@
}
+// Compile a string within the current v8 context.
+Local<UnboundScript> Shell::CompileString(
+ Isolate* isolate, Local<String> source, Local<Value> name,
+ v8::ScriptCompiler::CompileOptions compile_options) {
+ ScriptOrigin origin(name);
+ ScriptCompiler::Source script_source(source, origin);
+ Local<UnboundScript> script =
+ ScriptCompiler::CompileUnbound(isolate, &script_source, compile_options);
+
+ // Was caching requested & successful? Then compile again, now with cache.
+ if (script_source.GetCachedData()) {
+ if (compile_options == ScriptCompiler::kProduceCodeCache) {
+ compile_options = ScriptCompiler::kConsumeCodeCache;
+ } else if (compile_options == ScriptCompiler::kProduceParserCache) {
+ compile_options = ScriptCompiler::kConsumeParserCache;
+ } else {
+ DCHECK(false); // A new compile option?
+ }
+ ScriptCompiler::Source cached_source(
+ source, origin, new v8::ScriptCompiler::CachedData(
+ script_source.GetCachedData()->data,
+ script_source.GetCachedData()->length,
+ v8::ScriptCompiler::CachedData::BufferNotOwned));
+ script = ScriptCompiler::CompileUnbound(isolate, &cached_source,
+ compile_options);
+ }
+ return script;
+}
+
+
// Executes a string within the current v8 context.
-bool Shell::ExecuteString(Handle<String> source,
+bool Shell::ExecuteString(Isolate* isolate,
+ Handle<String> source,
Handle<Value> name,
bool print_result,
bool report_exceptions) {
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+#ifndef V8_SHARED
bool FLAG_debugger = i::FLAG_debugger;
#else
bool FLAG_debugger = false;
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
- HandleScope handle_scope;
+#endif // !V8_SHARED
+ HandleScope handle_scope(isolate);
TryCatch try_catch;
options.script_executed = true;
if (FLAG_debugger) {
// When debugging make exceptions appear to be uncaught.
try_catch.SetVerbose(true);
}
- Handle<Script> script = Script::Compile(source, name);
+
+ Handle<UnboundScript> script =
+ Shell::CompileString(isolate, source, name, options.compile_options);
if (script.IsEmpty()) {
// Print errors that happened during compilation.
if (report_exceptions && !FLAG_debugger)
- ReportException(&try_catch);
+ ReportException(isolate, &try_catch);
return false;
} else {
- Handle<Value> result = script->Run();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ Local<Context> realm =
+ Local<Context>::New(isolate, data->realms_[data->realm_current_]);
+ realm->Enter();
+ Handle<Value> result = script->BindToCurrentContext()->Run();
+ realm->Exit();
+ data->realm_current_ = data->realm_switch_;
if (result.IsEmpty()) {
- ASSERT(try_catch.HasCaught());
+ DCHECK(try_catch.HasCaught());
// Print errors that happened during execution.
if (report_exceptions && !FLAG_debugger)
- ReportException(&try_catch);
+ ReportException(isolate, &try_catch);
return false;
} else {
- ASSERT(!try_catch.HasCaught());
- if (print_result && !result->IsUndefined()) {
- // If all went well and the result wasn't undefined then print
- // the returned value.
- v8::String::Utf8Value str(result);
- size_t count = fwrite(*str, sizeof(**str), str.length(), stdout);
- (void) count; // Silence GCC-4.5.x "unused result" warning.
- printf("\n");
+ DCHECK(!try_catch.HasCaught());
+ if (print_result) {
+#if !defined(V8_SHARED)
+ if (options.test_shell) {
+#endif
+ if (!result->IsUndefined()) {
+ // If all went well and the result wasn't undefined then print
+ // the returned value.
+ v8::String::Utf8Value str(result);
+ fwrite(*str, sizeof(**str), str.length(), stdout);
+ printf("\n");
+ }
+#if !defined(V8_SHARED)
+ } else {
+ v8::TryCatch try_catch;
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate, utility_context_);
+ v8::Context::Scope context_scope(context);
+ Handle<Object> global = context->Global();
+ Handle<Value> fun =
+ global->Get(String::NewFromUtf8(isolate, "Stringify"));
+ Handle<Value> argv[1] = { result };
+ Handle<Value> s = Handle<Function>::Cast(fun)->Call(global, 1, argv);
+ if (try_catch.HasCaught()) return true;
+ v8::String::Utf8Value str(s);
+ fwrite(*str, sizeof(**str), str.length(), stdout);
+ printf("\n");
+ }
+#endif
}
return true;
}
@@ -185,359 +283,316 @@
}
-Handle<Value> Shell::Print(const Arguments& args) {
- Handle<Value> val = Write(args);
- printf("\n");
- fflush(stdout);
- return val;
+PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
+ data_->realm_count_ = 1;
+ data_->realm_current_ = 0;
+ data_->realm_switch_ = 0;
+ data_->realms_ = new Persistent<Context>[1];
+ data_->realms_[0].Reset(data_->isolate_,
+ data_->isolate_->GetEnteredContext());
}
-Handle<Value> Shell::Write(const Arguments& args) {
+PerIsolateData::RealmScope::~RealmScope() {
+ // Drop realms to avoid keeping them alive.
+ for (int i = 0; i < data_->realm_count_; ++i)
+ data_->realms_[i].Reset();
+ delete[] data_->realms_;
+ if (!data_->realm_shared_.IsEmpty())
+ data_->realm_shared_.Reset();
+}
+
+
+int PerIsolateData::RealmFind(Handle<Context> context) {
+ for (int i = 0; i < realm_count_; ++i) {
+ if (realms_[i] == context) return i;
+ }
+ return -1;
+}
+
+
+int PerIsolateData::RealmIndexOrThrow(
+ const v8::FunctionCallbackInfo<v8::Value>& args,
+ int arg_offset) {
+ if (args.Length() < arg_offset || !args[arg_offset]->IsNumber()) {
+ Throw(args.GetIsolate(), "Invalid argument");
+ return -1;
+ }
+ int index = args[arg_offset]->Int32Value();
+ if (index < 0 ||
+ index >= realm_count_ ||
+ realms_[index].IsEmpty()) {
+ Throw(args.GetIsolate(), "Invalid realm index");
+ return -1;
+ }
+ return index;
+}
+
+
+#ifndef V8_SHARED
+// performance.now() returns a time stamp as double, measured in milliseconds.
+// When FLAG_verify_predictable mode is enabled it returns current value
+// of Heap::allocations_count().
+void Shell::PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (i::FLAG_verify_predictable) {
+ Isolate* v8_isolate = args.GetIsolate();
+ i::Heap* heap = reinterpret_cast<i::Isolate*>(v8_isolate)->heap();
+ args.GetReturnValue().Set(heap->synthetic_time());
+ } else {
+ base::TimeDelta delta =
+ base::TimeTicks::HighResolutionNow() - kInitialTicks;
+ args.GetReturnValue().Set(delta.InMillisecondsF());
+ }
+}
+#endif // !V8_SHARED
+
+
+// Realm.current() returns the index of the currently active realm.
+void Shell::RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ int index = data->RealmFind(isolate->GetEnteredContext());
+ if (index == -1) return;
+ args.GetReturnValue().Set(index);
+}
+
+
+// Realm.owner(o) returns the index of the realm that created o.
+void Shell::RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ if (args.Length() < 1 || !args[0]->IsObject()) {
+ Throw(args.GetIsolate(), "Invalid argument");
+ return;
+ }
+ int index = data->RealmFind(args[0]->ToObject()->CreationContext());
+ if (index == -1) return;
+ args.GetReturnValue().Set(index);
+}
+
+
+// Realm.global(i) returns the global object of realm i.
+// (Note that properties of global objects cannot be read/written cross-realm.)
+void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ PerIsolateData* data = PerIsolateData::Get(args.GetIsolate());
+ int index = data->RealmIndexOrThrow(args, 0);
+ if (index == -1) return;
+ args.GetReturnValue().Set(
+ Local<Context>::New(args.GetIsolate(), data->realms_[index])->Global());
+}
+
+
+// Realm.create() creates a new realm and returns its index.
+void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ Persistent<Context>* old_realms = data->realms_;
+ int index = data->realm_count_;
+ data->realms_ = new Persistent<Context>[++data->realm_count_];
+ for (int i = 0; i < index; ++i) {
+ data->realms_[i].Reset(isolate, old_realms[i]);
+ }
+ delete[] old_realms;
+ Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
+ data->realms_[index].Reset(
+ isolate, Context::New(isolate, NULL, global_template));
+ args.GetReturnValue().Set(index);
+}
+
+
+// Realm.dispose(i) disposes the reference to the realm i.
+void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ int index = data->RealmIndexOrThrow(args, 0);
+ if (index == -1) return;
+ if (index == 0 ||
+ index == data->realm_current_ || index == data->realm_switch_) {
+ Throw(args.GetIsolate(), "Invalid realm index");
+ return;
+ }
+ data->realms_[index].Reset();
+}
+
+
+// Realm.switch(i) switches to the realm i for consecutive interactive inputs.
+void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ int index = data->RealmIndexOrThrow(args, 0);
+ if (index == -1) return;
+ data->realm_switch_ = index;
+}
+
+
+// Realm.eval(i, s) evaluates s in realm i and returns the result.
+void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ int index = data->RealmIndexOrThrow(args, 0);
+ if (index == -1) return;
+ if (args.Length() < 2 || !args[1]->IsString()) {
+ Throw(args.GetIsolate(), "Invalid argument");
+ return;
+ }
+ ScriptCompiler::Source script_source(args[1]->ToString());
+ Handle<UnboundScript> script = ScriptCompiler::CompileUnbound(
+ isolate, &script_source);
+ if (script.IsEmpty()) return;
+ Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]);
+ realm->Enter();
+ Handle<Value> result = script->BindToCurrentContext()->Run();
+ realm->Exit();
+ args.GetReturnValue().Set(result);
+}
+
+
+// Realm.shared is an accessor for a single shared value across realms.
+void Shell::RealmSharedGet(Local<String> property,
+ const PropertyCallbackInfo<Value>& info) {
+ Isolate* isolate = info.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ if (data->realm_shared_.IsEmpty()) return;
+ info.GetReturnValue().Set(data->realm_shared_);
+}
+
+void Shell::RealmSharedSet(Local<String> property,
+ Local<Value> value,
+ const PropertyCallbackInfo<void>& info) {
+ Isolate* isolate = info.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ data->realm_shared_.Reset(isolate, value);
+}
+
+
+void Shell::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Write(args);
+ printf("\n");
+ fflush(stdout);
+}
+
+
+void Shell::Write(const v8::FunctionCallbackInfo<v8::Value>& args) {
for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
+ HandleScope handle_scope(args.GetIsolate());
if (i != 0) {
printf(" ");
}
- v8::String::Utf8Value str(args[i]);
+
+ // Explicitly catch potential exceptions in toString().
+ v8::TryCatch try_catch;
+ Handle<String> str_obj = args[i]->ToString();
+ if (try_catch.HasCaught()) {
+ try_catch.ReThrow();
+ return;
+ }
+
+ v8::String::Utf8Value str(str_obj);
int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
if (n != str.length()) {
printf("Error in fwrite\n");
Exit(1);
}
}
- return Undefined();
}
-Handle<Value> Shell::EnableProfiler(const Arguments& args) {
- V8::ResumeProfiler();
- return Undefined();
-}
-
-
-Handle<Value> Shell::DisableProfiler(const Arguments& args) {
- V8::PauseProfiler();
- return Undefined();
-}
-
-
-Handle<Value> Shell::Read(const Arguments& args) {
+void Shell::Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
String::Utf8Value file(args[0]);
if (*file == NULL) {
- return ThrowException(String::New("Error loading file"));
+ Throw(args.GetIsolate(), "Error loading file");
+ return;
}
- Handle<String> source = ReadFile(*file);
+ Handle<String> source = ReadFile(args.GetIsolate(), *file);
if (source.IsEmpty()) {
- return ThrowException(String::New("Error loading file"));
+ Throw(args.GetIsolate(), "Error loading file");
+ return;
}
- return source;
+ args.GetReturnValue().Set(source);
}
-Handle<String> Shell::ReadFromStdin() {
+Handle<String> Shell::ReadFromStdin(Isolate* isolate) {
static const int kBufferSize = 256;
char buffer[kBufferSize];
- Handle<String> accumulator = String::New("");
+ Handle<String> accumulator = String::NewFromUtf8(isolate, "");
int length;
while (true) {
// Continue reading if the line ends with an escape '\\' or the line has
// not been fully read into the buffer yet (does not end with '\n').
// If fgets gets an error, just give up.
char* input = NULL;
- { // Release lock for blocking input.
- Unlocker unlock(Isolate::GetCurrent());
- input = fgets(buffer, kBufferSize, stdin);
- }
+ input = fgets(buffer, kBufferSize, stdin);
if (input == NULL) return Handle<String>();
length = static_cast<int>(strlen(buffer));
if (length == 0) {
return accumulator;
} else if (buffer[length-1] != '\n') {
- accumulator = String::Concat(accumulator, String::New(buffer, length));
+ accumulator = String::Concat(
+ accumulator,
+ String::NewFromUtf8(isolate, buffer, String::kNormalString, length));
} else if (length > 1 && buffer[length-2] == '\\') {
buffer[length-2] = '\n';
- accumulator = String::Concat(accumulator, String::New(buffer, length-1));
+ accumulator = String::Concat(
+ accumulator, String::NewFromUtf8(isolate, buffer,
+ String::kNormalString, length - 1));
} else {
- return String::Concat(accumulator, String::New(buffer, length-1));
+ return String::Concat(
+ accumulator, String::NewFromUtf8(isolate, buffer,
+ String::kNormalString, length - 1));
}
}
}
-Handle<Value> Shell::Load(const Arguments& args) {
+void Shell::Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
+ HandleScope handle_scope(args.GetIsolate());
String::Utf8Value file(args[i]);
if (*file == NULL) {
- return ThrowException(String::New("Error loading file"));
+ Throw(args.GetIsolate(), "Error loading file");
+ return;
}
- Handle<String> source = ReadFile(*file);
+ Handle<String> source = ReadFile(args.GetIsolate(), *file);
if (source.IsEmpty()) {
- return ThrowException(String::New("Error loading file"));
+ Throw(args.GetIsolate(), "Error loading file");
+ return;
}
- if (!ExecuteString(source, String::New(*file), false, true)) {
- return ThrowException(String::New("Error executing file"));
+ if (!ExecuteString(args.GetIsolate(),
+ source,
+ String::NewFromUtf8(args.GetIsolate(), *file),
+ false,
+ true)) {
+ Throw(args.GetIsolate(), "Error executing file");
+ return;
}
}
- return Undefined();
-}
-
-static size_t convertToUint(Local<Value> value_in, TryCatch* try_catch) {
- if (value_in->IsUint32()) {
- return value_in->Uint32Value();
- }
-
- Local<Value> number = value_in->ToNumber();
- if (try_catch->HasCaught()) return 0;
-
- ASSERT(number->IsNumber());
- Local<Int32> int32 = number->ToInt32();
- if (try_catch->HasCaught() || int32.IsEmpty()) return 0;
-
- int32_t raw_value = int32->Int32Value();
- if (try_catch->HasCaught()) return 0;
-
- if (raw_value < 0) {
- ThrowException(String::New("Array length must not be negative."));
- return 0;
- }
-
- static const int kMaxLength = 0x3fffffff;
-#ifndef V8_SHARED
- ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
-#endif // V8_SHARED
- if (raw_value > static_cast<int32_t>(kMaxLength)) {
- ThrowException(
- String::New("Array length exceeds maximum length."));
- }
- return static_cast<size_t>(raw_value);
}
-const char kArrayBufferReferencePropName[] = "_is_array_buffer_";
-const char kArrayBufferMarkerPropName[] = "_array_buffer_ref_";
-
-
-Handle<Value> Shell::CreateExternalArray(const Arguments& args,
- ExternalArrayType type,
- size_t element_size) {
- TryCatch try_catch;
- bool is_array_buffer_construct = element_size == 0;
- if (is_array_buffer_construct) {
- type = v8::kExternalByteArray;
- element_size = 1;
- }
- ASSERT(element_size == 1 || element_size == 2 || element_size == 4 ||
- element_size == 8);
- if (args.Length() == 0) {
- return ThrowException(
- String::New("Array constructor must have at least one "
- "parameter."));
- }
- bool first_arg_is_array_buffer =
- args[0]->IsObject() &&
- args[0]->ToObject()->Get(
- String::New(kArrayBufferMarkerPropName))->IsTrue();
- // Currently, only the following constructors are supported:
- // TypedArray(unsigned long length)
- // TypedArray(ArrayBuffer buffer,
- // optional unsigned long byteOffset,
- // optional unsigned long length)
- if (args.Length() > 3) {
- return ThrowException(
- String::New("Array constructor from ArrayBuffer must "
- "have 1-3 parameters."));
- }
-
- Local<Value> length_value = (args.Length() < 3)
- ? (first_arg_is_array_buffer
- ? args[0]->ToObject()->Get(String::New("length"))
- : args[0])
- : args[2];
- size_t length = convertToUint(length_value, &try_catch);
- if (try_catch.HasCaught()) return try_catch.Exception();
-
- void* data = NULL;
- size_t offset = 0;
-
- Handle<Object> array = Object::New();
- if (first_arg_is_array_buffer) {
- Handle<Object> derived_from = args[0]->ToObject();
- data = derived_from->GetIndexedPropertiesExternalArrayData();
-
- size_t array_buffer_length = convertToUint(
- derived_from->Get(String::New("length")),
- &try_catch);
- if (try_catch.HasCaught()) return try_catch.Exception();
-
- if (data == NULL && array_buffer_length != 0) {
- return ThrowException(
- String::New("ArrayBuffer doesn't have data"));
- }
-
- if (args.Length() > 1) {
- offset = convertToUint(args[1], &try_catch);
- if (try_catch.HasCaught()) return try_catch.Exception();
-
- // The given byteOffset must be a multiple of the element size of the
- // specific type, otherwise an exception is raised.
- if (offset % element_size != 0) {
- return ThrowException(
- String::New("offset must be multiple of element_size"));
- }
- }
-
- if (offset > array_buffer_length) {
- return ThrowException(
- String::New("byteOffset must be less than ArrayBuffer length."));
- }
-
- if (args.Length() == 2) {
- // If length is not explicitly specified, the length of the ArrayBuffer
- // minus the byteOffset must be a multiple of the element size of the
- // specific type, or an exception is raised.
- length = array_buffer_length - offset;
- }
-
- if (args.Length() != 3) {
- if (length % element_size != 0) {
- return ThrowException(
- String::New("ArrayBuffer length minus the byteOffset must be a "
- "multiple of the element size"));
- }
- length /= element_size;
- }
-
- // If a given byteOffset and length references an area beyond the end of
- // the ArrayBuffer an exception is raised.
- if (offset + (length * element_size) > array_buffer_length) {
- return ThrowException(
- String::New("length references an area beyond the end of the "
- "ArrayBuffer"));
- }
-
- // Hold a reference to the ArrayBuffer so its buffer doesn't get collected.
- array->Set(String::New(kArrayBufferReferencePropName), args[0], ReadOnly);
- }
-
- if (is_array_buffer_construct) {
- array->Set(String::New(kArrayBufferMarkerPropName), True(), ReadOnly);
- }
-
- Persistent<Object> persistent_array = Persistent<Object>::New(array);
- persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
- persistent_array.MarkIndependent();
- if (data == NULL && length != 0) {
- data = calloc(length, element_size);
- if (data == NULL) {
- return ThrowException(String::New("Memory allocation failed."));
- }
- }
-
- array->SetIndexedPropertiesToExternalArrayData(
- reinterpret_cast<uint8_t*>(data) + offset, type,
- static_cast<int>(length));
- array->Set(String::New("length"),
- Int32::New(static_cast<int32_t>(length)), ReadOnly);
- array->Set(String::New("BYTES_PER_ELEMENT"),
- Int32::New(static_cast<int32_t>(element_size)));
- return array;
-}
-
-
-void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) {
- HandleScope scope;
- Handle<String> prop_name = String::New(kArrayBufferReferencePropName);
- Handle<Object> converted_object = object->ToObject();
- Local<Value> prop_value = converted_object->Get(prop_name);
- if (data != NULL && !prop_value->IsObject()) {
- free(data);
- }
- object.Dispose();
-}
-
-
-Handle<Value> Shell::ArrayBuffer(const Arguments& args) {
- return CreateExternalArray(args, v8::kExternalByteArray, 0);
-}
-
-
-Handle<Value> Shell::Int8Array(const Arguments& args) {
- return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t));
-}
-
-
-Handle<Value> Shell::Uint8Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalUnsignedByteArray, sizeof(uint8_t));
-}
-
-
-Handle<Value> Shell::Int16Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalShortArray, sizeof(int16_t));
-}
-
-
-Handle<Value> Shell::Uint16Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalUnsignedShortArray,
- sizeof(uint16_t));
-}
-
-
-Handle<Value> Shell::Int32Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalIntArray, sizeof(int32_t));
-}
-
-
-Handle<Value> Shell::Uint32Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalUnsignedIntArray, sizeof(uint32_t));
-}
-
-
-Handle<Value> Shell::Float32Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalFloatArray,
- sizeof(float)); // NOLINT
-}
-
-
-Handle<Value> Shell::Float64Array(const Arguments& args) {
- return CreateExternalArray(args, kExternalDoubleArray,
- sizeof(double)); // NOLINT
-}
-
-
-Handle<Value> Shell::PixelArray(const Arguments& args) {
- return CreateExternalArray(args, kExternalPixelArray, sizeof(uint8_t));
-}
-
-
-Handle<Value> Shell::Yield(const Arguments& args) {
- v8::Unlocker unlocker;
- return Undefined();
-}
-
-
-Handle<Value> Shell::Quit(const Arguments& args) {
+void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
int exit_code = args[0]->Int32Value();
-#ifndef V8_SHARED
OnExit();
-#endif // V8_SHARED
exit(exit_code);
- return Undefined();
}
-Handle<Value> Shell::Version(const Arguments& args) {
- return String::New(V8::GetVersion());
+void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ args.GetReturnValue().Set(
+ String::NewFromUtf8(args.GetIsolate(), V8::GetVersion()));
}
-void Shell::ReportException(v8::TryCatch* try_catch) {
- HandleScope handle_scope;
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
- bool enter_context = !Context::InContext();
- if (enter_context) utility_context_->Enter();
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
+void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
+ HandleScope handle_scope(isolate);
+#ifndef V8_SHARED
+ Handle<Context> utility_context;
+ bool enter_context = !isolate->InContext();
+ if (enter_context) {
+ utility_context = Local<Context>::New(isolate, utility_context_);
+ utility_context->Enter();
+ }
+#endif // !V8_SHARED
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception);
Handle<Message> message = try_catch->Message();
@@ -547,7 +602,7 @@
printf("%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
- v8::String::Utf8Value filename(message->GetScriptResourceName());
+ v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
const char* filename_string = ToCString(filename);
int linenum = message->GetLineNumber();
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
@@ -572,57 +627,64 @@
}
}
printf("\n");
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
- if (enter_context) utility_context_->Exit();
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
+#ifndef V8_SHARED
+ if (enter_context) utility_context->Exit();
+#endif // !V8_SHARED
}
#ifndef V8_SHARED
-Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
- HandleScope handle_scope;
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("GetCompletions"));
+Handle<Array> Shell::GetCompletions(Isolate* isolate,
+ Handle<String> text,
+ Handle<String> full) {
+ EscapableHandleScope handle_scope(isolate);
+ v8::Local<v8::Context> utility_context =
+ v8::Local<v8::Context>::New(isolate, utility_context_);
+ v8::Context::Scope context_scope(utility_context);
+ Handle<Object> global = utility_context->Global();
+ Local<Value> fun =
+ global->Get(String::NewFromUtf8(isolate, "GetCompletions"));
static const int kArgc = 3;
- Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
- Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return handle_scope.Close(Handle<Array>::Cast(val));
+ v8::Local<v8::Context> evaluation_context =
+ v8::Local<v8::Context>::New(isolate, evaluation_context_);
+ Handle<Value> argv[kArgc] = { evaluation_context->Global(), text, full };
+ Local<Value> val = Local<Function>::Cast(fun)->Call(global, kArgc, argv);
+ return handle_scope.Escape(Local<Array>::Cast(val));
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
-Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
+Local<Object> Shell::DebugMessageDetails(Isolate* isolate,
+ Handle<String> message) {
+ EscapableHandleScope handle_scope(isolate);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate, utility_context_);
+ v8::Context::Scope context_scope(context);
+ Handle<Object> global = context->Global();
+ Handle<Value> fun =
+ global->Get(String::NewFromUtf8(isolate, "DebugMessageDetails"));
static const int kArgc = 1;
Handle<Value> argv[kArgc] = { message };
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return Handle<Object>::Cast(val);
+ return handle_scope.Escape(Local<Object>(Handle<Object>::Cast(val)));
}
-Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
+Local<Value> Shell::DebugCommandToJSONRequest(Isolate* isolate,
+ Handle<String> command) {
+ EscapableHandleScope handle_scope(isolate);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate, utility_context_);
+ v8::Context::Scope context_scope(context);
+ Handle<Object> global = context->Global();
+ Handle<Value> fun =
+ global->Get(String::NewFromUtf8(isolate, "DebugCommandToJSONRequest"));
static const int kArgc = 1;
Handle<Value> argv[kArgc] = { command };
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return val;
+ return handle_scope.Escape(Local<Value>(val));
}
-void Shell::DispatchDebugMessages() {
- v8::Context::Scope scope(Shell::evaluation_context_);
- v8::Debug::ProcessDebugMessages();
-}
-#endif // ENABLE_DEBUGGER_SUPPORT
-#endif // V8_SHARED
-
-
-#ifndef V8_SHARED
int32_t* Counter::Bind(const char* name, bool is_histogram) {
int i;
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -653,8 +715,8 @@
}
-void Shell::MapCounters(const char* name) {
- counters_file_ = i::OS::MemoryMappedFile::create(
+void Shell::MapCounters(v8::Isolate* isolate, const char* name) {
+ counters_file_ = base::OS::MemoryMappedFile::create(
name, sizeof(CounterCollection), &local_counters_);
void* memory = (counters_file_ == NULL) ?
NULL : counters_file_->memory();
@@ -663,9 +725,9 @@
Exit(1);
}
counters_ = static_cast<CounterCollection*>(memory);
- V8::SetCounterFunction(LookupCounter);
- V8::SetCreateHistogramFunction(CreateHistogram);
- V8::SetAddHistogramSampleFunction(AddHistogramSample);
+ isolate->SetCounterFunction(LookupCounter);
+ isolate->SetCreateHistogramFunction(CreateHistogram);
+ isolate->SetAddHistogramSampleFunction(AddHistogramSample);
}
@@ -690,7 +752,7 @@
counter->Bind(name, is_histogram);
}
} else {
- ASSERT(counter->is_histogram() == is_histogram);
+ DCHECK(counter->is_histogram() == is_histogram);
}
return counter;
}
@@ -721,26 +783,29 @@
}
-void Shell::InstallUtilityScript() {
- Locker lock;
- HandleScope scope;
+void Shell::InstallUtilityScript(Isolate* isolate) {
+ HandleScope scope(isolate);
// If we use the utility context, we have to set the security tokens so that
// utility, evaluation and debug context can all access each other.
- utility_context_->SetSecurityToken(Undefined());
- evaluation_context_->SetSecurityToken(Undefined());
- Context::Scope utility_scope(utility_context_);
+ v8::Local<v8::Context> utility_context =
+ v8::Local<v8::Context>::New(isolate, utility_context_);
+ v8::Local<v8::Context> evaluation_context =
+ v8::Local<v8::Context>::New(isolate, evaluation_context_);
+ utility_context->SetSecurityToken(Undefined(isolate));
+ evaluation_context->SetSecurityToken(Undefined(isolate));
+ v8::Context::Scope context_scope(utility_context);
-#ifdef ENABLE_DEBUGGER_SUPPORT
if (i::FLAG_debugger) printf("JavaScript debugger enabled\n");
// Install the debugger object in the utility scope
- i::Debug* debug = i::Isolate::Current()->debug();
+ i::Debug* debug = reinterpret_cast<i::Isolate*>(isolate)->debug();
debug->Load();
+ i::Handle<i::Context> debug_context = debug->debug_context();
i::Handle<i::JSObject> js_debug
- = i::Handle<i::JSObject>(debug->debug_context()->global());
- utility_context_->Global()->Set(String::New("$debug"),
- Utils::ToLocal(js_debug));
- debug->debug_context()->set_security_token(HEAP->undefined_value());
-#endif // ENABLE_DEBUGGER_SUPPORT
+ = i::Handle<i::JSObject>(debug_context->global_object());
+ utility_context->Global()->Set(String::NewFromUtf8(isolate, "$debug"),
+ Utils::ToLocal(js_debug));
+ debug_context->set_security_token(
+ reinterpret_cast<i::Isolate*>(isolate)->heap()->undefined_value());
// Run the d8 shell utility script in the utility context
int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@@ -748,11 +813,14 @@
i::NativesCollection<i::D8>::GetRawScriptSource(source_index);
i::Vector<const char> shell_source_name =
i::NativesCollection<i::D8>::GetScriptName(source_index);
- Handle<String> source = String::New(shell_source.start(),
- shell_source.length());
- Handle<String> name = String::New(shell_source_name.start(),
- shell_source_name.length());
- Handle<Script> script = Script::Compile(source, name);
+ Handle<String> source =
+ String::NewFromUtf8(isolate, shell_source.start(), String::kNormalString,
+ shell_source.length());
+ Handle<String> name =
+ String::NewFromUtf8(isolate, shell_source_name.start(),
+ String::kNormalString, shell_source_name.length());
+ ScriptOrigin origin(name);
+ Handle<Script> script = Script::Compile(source, &origin);
script->Run();
// Mark the d8 shell script as native to avoid it showing up as normal source
// in the debugger.
@@ -764,14 +832,10 @@
i::SharedFunctionInfo::cast(*compiled_script)->script()));
script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
-#ifdef ENABLE_DEBUGGER_SUPPORT
// Start the in-process debugger if requested.
- if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
- v8::Debug::SetDebugEventListener(HandleDebugEvent);
- }
-#endif // ENABLE_DEBUGGER_SUPPORT
+ if (i::FLAG_debugger) v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
-#endif // V8_SHARED
+#endif // !V8_SHARED
#ifdef COMPRESS_STARTUP_DATA_BZ2
@@ -784,7 +848,7 @@
int* raw_data_size,
const char* compressed_data,
int compressed_data_size) {
- ASSERT_EQ(v8::StartupData::kBZip2,
+ DCHECK_EQ(v8::StartupData::kBZip2,
v8::V8::GetCompressedStartupDataAlgorithm());
unsigned int decompressed_size = *raw_data_size;
int result =
@@ -801,62 +865,63 @@
};
#endif
-Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
- Handle<ObjectTemplate> global_template = ObjectTemplate::New();
- global_template->Set(String::New("print"), FunctionTemplate::New(Print));
- global_template->Set(String::New("write"), FunctionTemplate::New(Write));
- global_template->Set(String::New("read"), FunctionTemplate::New(Read));
- global_template->Set(String::New("readbinary"),
- FunctionTemplate::New(ReadBinary));
- global_template->Set(String::New("readline"),
- FunctionTemplate::New(ReadLine));
- global_template->Set(String::New("load"), FunctionTemplate::New(Load));
- global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
- global_template->Set(String::New("version"), FunctionTemplate::New(Version));
- global_template->Set(String::New("enableProfiler"),
- FunctionTemplate::New(EnableProfiler));
- global_template->Set(String::New("disableProfiler"),
- FunctionTemplate::New(DisableProfiler));
- // Bind the handlers for external arrays.
- global_template->Set(String::New("ArrayBuffer"),
- FunctionTemplate::New(ArrayBuffer));
- global_template->Set(String::New("Int8Array"),
- FunctionTemplate::New(Int8Array));
- global_template->Set(String::New("Uint8Array"),
- FunctionTemplate::New(Uint8Array));
- global_template->Set(String::New("Int16Array"),
- FunctionTemplate::New(Int16Array));
- global_template->Set(String::New("Uint16Array"),
- FunctionTemplate::New(Uint16Array));
- global_template->Set(String::New("Int32Array"),
- FunctionTemplate::New(Int32Array));
- global_template->Set(String::New("Uint32Array"),
- FunctionTemplate::New(Uint32Array));
- global_template->Set(String::New("Float32Array"),
- FunctionTemplate::New(Float32Array));
- global_template->Set(String::New("Float64Array"),
- FunctionTemplate::New(Float64Array));
- global_template->Set(String::New("PixelArray"),
- FunctionTemplate::New(PixelArray));
+Handle<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
+ Handle<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
+ global_template->Set(String::NewFromUtf8(isolate, "print"),
+ FunctionTemplate::New(isolate, Print));
+ global_template->Set(String::NewFromUtf8(isolate, "write"),
+ FunctionTemplate::New(isolate, Write));
+ global_template->Set(String::NewFromUtf8(isolate, "read"),
+ FunctionTemplate::New(isolate, Read));
+ global_template->Set(String::NewFromUtf8(isolate, "readbuffer"),
+ FunctionTemplate::New(isolate, ReadBuffer));
+ global_template->Set(String::NewFromUtf8(isolate, "readline"),
+ FunctionTemplate::New(isolate, ReadLine));
+ global_template->Set(String::NewFromUtf8(isolate, "load"),
+ FunctionTemplate::New(isolate, Load));
+ global_template->Set(String::NewFromUtf8(isolate, "quit"),
+ FunctionTemplate::New(isolate, Quit));
+ global_template->Set(String::NewFromUtf8(isolate, "version"),
+ FunctionTemplate::New(isolate, Version));
-#ifdef LIVE_OBJECT_LIST
- global_template->Set(String::New("lol_is_enabled"), True());
-#else
- global_template->Set(String::New("lol_is_enabled"), False());
-#endif
+ // Bind the Realm object.
+ Handle<ObjectTemplate> realm_template = ObjectTemplate::New(isolate);
+ realm_template->Set(String::NewFromUtf8(isolate, "current"),
+ FunctionTemplate::New(isolate, RealmCurrent));
+ realm_template->Set(String::NewFromUtf8(isolate, "owner"),
+ FunctionTemplate::New(isolate, RealmOwner));
+ realm_template->Set(String::NewFromUtf8(isolate, "global"),
+ FunctionTemplate::New(isolate, RealmGlobal));
+ realm_template->Set(String::NewFromUtf8(isolate, "create"),
+ FunctionTemplate::New(isolate, RealmCreate));
+ realm_template->Set(String::NewFromUtf8(isolate, "dispose"),
+ FunctionTemplate::New(isolate, RealmDispose));
+ realm_template->Set(String::NewFromUtf8(isolate, "switch"),
+ FunctionTemplate::New(isolate, RealmSwitch));
+ realm_template->Set(String::NewFromUtf8(isolate, "eval"),
+ FunctionTemplate::New(isolate, RealmEval));
+ realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"),
+ RealmSharedGet, RealmSharedSet);
+ global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template);
-#if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64)
- Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
- AddOSMethods(os_templ);
- global_template->Set(String::New("os"), os_templ);
-#endif // V8_SHARED
+#ifndef V8_SHARED
+ Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate);
+ performance_template->Set(String::NewFromUtf8(isolate, "now"),
+ FunctionTemplate::New(isolate, PerformanceNow));
+ global_template->Set(String::NewFromUtf8(isolate, "performance"),
+ performance_template);
+#endif // !V8_SHARED
+
+ Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
+ AddOSMethods(isolate, os_templ);
+ global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ);
return global_template;
}
-void Shell::Initialize() {
+void Shell::Initialize(Isolate* isolate) {
#ifdef COMPRESS_STARTUP_DATA_BZ2
BZip2Decompressor startup_data_decompressor;
int bz2_result = startup_data_decompressor.Decompress();
@@ -870,58 +935,55 @@
Shell::counter_map_ = new CounterMap();
// Set up counters
if (i::StrLength(i::FLAG_map_counters) != 0)
- MapCounters(i::FLAG_map_counters);
- if (i::FLAG_dump_counters) {
- V8::SetCounterFunction(LookupCounter);
- V8::SetCreateHistogramFunction(CreateHistogram);
- V8::SetAddHistogramSampleFunction(AddHistogramSample);
+ MapCounters(isolate, i::FLAG_map_counters);
+ if (i::FLAG_dump_counters || i::FLAG_track_gc_object_stats) {
+ isolate->SetCounterFunction(LookupCounter);
+ isolate->SetCreateHistogramFunction(CreateHistogram);
+ isolate->SetAddHistogramSampleFunction(AddHistogramSample);
}
-#endif // V8_SHARED
- if (options.test_shell) return;
-
-#ifndef V8_SHARED
- Locker lock;
- HandleScope scope;
- Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
- utility_context_ = Context::New(NULL, global_template);
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Start the debugger agent if requested.
- if (i::FLAG_debugger_agent) {
- v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
- v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
- }
-#endif // ENABLE_DEBUGGER_SUPPORT
-#endif // V8_SHARED
+#endif // !V8_SHARED
}
-Persistent<Context> Shell::CreateEvaluationContext() {
+void Shell::InitializeDebugger(Isolate* isolate) {
+ if (options.test_shell) return;
+#ifndef V8_SHARED
+ HandleScope scope(isolate);
+ Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
+ utility_context_.Reset(isolate,
+ Context::New(isolate, NULL, global_template));
+#endif // !V8_SHARED
+}
+
+
+Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
#ifndef V8_SHARED
// This needs to be a critical section since this is not thread-safe
- i::ScopedLock lock(context_mutex_);
-#endif // V8_SHARED
+ base::LockGuard<base::Mutex> lock_guard(&context_mutex_);
+#endif // !V8_SHARED
// Initialize the global objects
- Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
- Persistent<Context> context = Context::New(NULL, global_template);
- ASSERT(!context.IsEmpty());
+ Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
+ EscapableHandleScope handle_scope(isolate);
+ Local<Context> context = Context::New(isolate, NULL, global_template);
+ DCHECK(!context.IsEmpty());
Context::Scope scope(context);
#ifndef V8_SHARED
+ i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory();
i::JSArguments js_args = i::FLAG_js_arguments;
i::Handle<i::FixedArray> arguments_array =
- FACTORY->NewFixedArray(js_args.argc());
- for (int j = 0; j < js_args.argc(); j++) {
+ factory->NewFixedArray(js_args.argc);
+ for (int j = 0; j < js_args.argc; j++) {
i::Handle<i::String> arg =
- FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
+ factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked();
arguments_array->set(j, *arg);
}
i::Handle<i::JSArray> arguments_jsarray =
- FACTORY->NewJSArrayWithElements(arguments_array);
- context->Global()->Set(String::New("arguments"),
+ factory->NewJSArrayWithElements(arguments_array);
+ context->Global()->Set(String::NewFromUtf8(isolate, "arguments"),
Utils::ToLocal(arguments_jsarray));
-#endif // V8_SHARED
- return context;
+#endif // !V8_SHARED
+ return handle_scope.Escape(context);
}
@@ -941,14 +1003,16 @@
};
-int CompareKeys(const void* a, const void* b) {
- return strcmp(static_cast<const CounterAndKey*>(a)->key,
- static_cast<const CounterAndKey*>(b)->key);
+inline bool operator<(const CounterAndKey& lhs, const CounterAndKey& rhs) {
+ return strcmp(lhs.key, rhs.key) < 0;
}
+#endif // !V8_SHARED
void Shell::OnExit() {
- if (console != NULL) console->Close();
+ LineEditor* line_editor = LineEditor::Get();
+ if (line_editor) line_editor->Close();
+#ifndef V8_SHARED
if (i::FLAG_dump_counters) {
int number_of_counters = 0;
for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
@@ -960,27 +1024,32 @@
counters[j].counter = i.CurrentValue();
counters[j].key = i.CurrentKey();
}
- qsort(counters, number_of_counters, sizeof(counters[0]), CompareKeys);
- printf("+--------------------------------------------+-------------+\n");
- printf("| Name | Value |\n");
- printf("+--------------------------------------------+-------------+\n");
+ std::sort(counters, counters + number_of_counters);
+ printf("+----------------------------------------------------------------+"
+ "-------------+\n");
+ printf("| Name |"
+ " Value |\n");
+ printf("+----------------------------------------------------------------+"
+ "-------------+\n");
for (j = 0; j < number_of_counters; j++) {
Counter* counter = counters[j].counter;
const char* key = counters[j].key;
if (counter->is_histogram()) {
- printf("| c:%-40s | %11i |\n", key, counter->count());
- printf("| t:%-40s | %11i |\n", key, counter->sample_total());
+ printf("| c:%-60s | %11i |\n", key, counter->count());
+ printf("| t:%-60s | %11i |\n", key, counter->sample_total());
} else {
- printf("| %-42s | %11i |\n", key, counter->count());
+ printf("| %-62s | %11i |\n", key, counter->count());
}
}
- printf("+--------------------------------------------+-------------+\n");
+ printf("+----------------------------------------------------------------+"
+ "-------------+\n");
delete [] counters;
}
- if (counters_file_ != NULL)
- delete counters_file_;
+ delete counters_file_;
+ delete counter_map_;
+#endif // !V8_SHARED
}
-#endif // V8_SHARED
+
static FILE* FOpen(const char* path, const char* mode) {
@@ -1004,9 +1073,7 @@
}
-static char* ReadChars(const char* name, int* size_out) {
- // Release the V8 lock while reading files.
- v8::Unlocker unlocker(Isolate::GetCurrent());
+static char* ReadChars(Isolate* isolate, const char* name, int* size_out) {
FILE* file = FOpen(name, "rb");
if (file == NULL) return NULL;
@@ -1026,218 +1093,182 @@
}
-Handle<Value> Shell::ReadBinary(const Arguments& args) {
+struct DataAndPersistent {
+ uint8_t* data;
+ Persistent<ArrayBuffer> handle;
+};
+
+
+static void ReadBufferWeakCallback(
+ const v8::WeakCallbackData<ArrayBuffer, DataAndPersistent>& data) {
+ size_t byte_length = data.GetValue()->ByteLength();
+ data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(
+ -static_cast<intptr_t>(byte_length));
+
+ delete[] data.GetParameter()->data;
+ data.GetParameter()->handle.Reset();
+ delete data.GetParameter();
+}
+
+
+void Shell::ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ DCHECK(sizeof(char) == sizeof(uint8_t)); // NOLINT
String::Utf8Value filename(args[0]);
- int size;
+ int length;
if (*filename == NULL) {
- return ThrowException(String::New("Error loading file"));
- }
- char* chars = ReadChars(*filename, &size);
- if (chars == NULL) {
- return ThrowException(String::New("Error reading file"));
- }
- // We skip checking the string for UTF8 characters and use it raw as
- // backing store for the external string with 8-bit characters.
- BinaryResource* resource = new BinaryResource(chars, size);
- return String::NewExternal(resource);
-}
-
-
-#ifndef V8_SHARED
-static char* ReadToken(char* data, char token) {
- char* next = i::OS::StrChr(data, token);
- if (next != NULL) {
- *next = '\0';
- return (next + 1);
+ Throw(args.GetIsolate(), "Error loading file");
+ return;
}
- return NULL;
+ Isolate* isolate = args.GetIsolate();
+ DataAndPersistent* data = new DataAndPersistent;
+ data->data = reinterpret_cast<uint8_t*>(
+ ReadChars(args.GetIsolate(), *filename, &length));
+ if (data->data == NULL) {
+ delete data;
+ Throw(args.GetIsolate(), "Error reading file");
+ return;
+ }
+ Handle<v8::ArrayBuffer> buffer =
+ ArrayBuffer::New(isolate, data->data, length);
+ data->handle.Reset(isolate, buffer);
+ data->handle.SetWeak(data, ReadBufferWeakCallback);
+ data->handle.MarkIndependent();
+ isolate->AdjustAmountOfExternalAllocatedMemory(length);
+
+ args.GetReturnValue().Set(buffer);
}
-static char* ReadLine(char* data) {
- return ReadToken(data, '\n');
-}
-
-
-static char* ReadWord(char* data) {
- return ReadToken(data, ' ');
-}
-#endif // V8_SHARED
-
-
// Reads a file into a v8 string.
-Handle<String> Shell::ReadFile(const char* name) {
+Handle<String> Shell::ReadFile(Isolate* isolate, const char* name) {
int size = 0;
- char* chars = ReadChars(name, &size);
+ char* chars = ReadChars(isolate, name, &size);
if (chars == NULL) return Handle<String>();
- Handle<String> result = String::New(chars);
+ Handle<String> result =
+ String::NewFromUtf8(isolate, chars, String::kNormalString, size);
delete[] chars;
return result;
}
-void Shell::RunShell() {
- Locker locker;
- Context::Scope context_scope(evaluation_context_);
- HandleScope outer_scope;
- Handle<String> name = String::New("(d8)");
- console = LineEditor::Get();
+void Shell::RunShell(Isolate* isolate) {
+ HandleScope outer_scope(isolate);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate, evaluation_context_);
+ v8::Context::Scope context_scope(context);
+ PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
+ Handle<String> name = String::NewFromUtf8(isolate, "(d8)");
+ LineEditor* console = LineEditor::Get();
printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name());
- console->Open();
+ console->Open(isolate);
while (true) {
- HandleScope inner_scope;
+ HandleScope inner_scope(isolate);
Handle<String> input = console->Prompt(Shell::kPrompt);
if (input.IsEmpty()) break;
- ExecuteString(input, name, true, true);
+ ExecuteString(isolate, input, name, true, true);
}
printf("\n");
}
-#ifndef V8_SHARED
-class ShellThread : public i::Thread {
- public:
- // Takes ownership of the underlying char array of |files|.
- ShellThread(int no, char* files)
- : Thread("d8:ShellThread"),
- no_(no), files_(files) { }
-
- ~ShellThread() {
- delete[] files_;
- }
-
- virtual void Run();
- private:
- int no_;
- char* files_;
-};
-
-
-void ShellThread::Run() {
- char* ptr = files_;
- while ((ptr != NULL) && (*ptr != '\0')) {
- // For each newline-separated line.
- char* next_line = ReadLine(ptr);
-
- if (*ptr == '#') {
- // Skip comment lines.
- ptr = next_line;
- continue;
- }
-
- // Prepare the context for this thread.
- Locker locker;
- HandleScope outer_scope;
- Persistent<Context> thread_context = Shell::CreateEvaluationContext();
- Context::Scope context_scope(thread_context);
-
- while ((ptr != NULL) && (*ptr != '\0')) {
- HandleScope inner_scope;
- char* filename = ptr;
- ptr = ReadWord(ptr);
-
- // Skip empty strings.
- if (strlen(filename) == 0) {
- continue;
- }
-
- Handle<String> str = Shell::ReadFile(filename);
- if (str.IsEmpty()) {
- printf("File '%s' not found\n", filename);
- Shell::Exit(1);
- }
-
- Shell::ExecuteString(str, String::New(filename), false, false);
- }
-
- thread_context.Dispose();
- ptr = next_line;
- }
-}
-#endif // V8_SHARED
-
-
SourceGroup::~SourceGroup() {
#ifndef V8_SHARED
- delete next_semaphore_;
- next_semaphore_ = NULL;
- delete done_semaphore_;
- done_semaphore_ = NULL;
delete thread_;
thread_ = NULL;
-#endif // V8_SHARED
+#endif // !V8_SHARED
}
-void SourceGroup::Execute() {
+void SourceGroup::Execute(Isolate* isolate) {
+ bool exception_was_thrown = false;
for (int i = begin_offset_; i < end_offset_; ++i) {
const char* arg = argv_[i];
if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
// Execute argument given to -e option directly.
- HandleScope handle_scope;
- Handle<String> file_name = String::New("unnamed");
- Handle<String> source = String::New(argv_[i + 1]);
- if (!Shell::ExecuteString(source, file_name, false, true)) {
- Shell::Exit(1);
+ HandleScope handle_scope(isolate);
+ Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
+ Handle<String> source = String::NewFromUtf8(isolate, argv_[i + 1]);
+ if (!Shell::ExecuteString(isolate, source, file_name, false, true)) {
+ exception_was_thrown = true;
+ break;
}
++i;
} else if (arg[0] == '-') {
// Ignore other options. They have been parsed already.
} else {
// Use all other arguments as names of files to load and run.
- HandleScope handle_scope;
- Handle<String> file_name = String::New(arg);
- Handle<String> source = ReadFile(arg);
+ HandleScope handle_scope(isolate);
+ Handle<String> file_name = String::NewFromUtf8(isolate, arg);
+ Handle<String> source = ReadFile(isolate, arg);
if (source.IsEmpty()) {
printf("Error reading '%s'\n", arg);
Shell::Exit(1);
}
- if (!Shell::ExecuteString(source, file_name, false, true)) {
- Shell::Exit(1);
+ if (!Shell::ExecuteString(isolate, source, file_name, false, true)) {
+ exception_was_thrown = true;
+ break;
}
}
}
+ if (exception_was_thrown != Shell::options.expected_to_throw) {
+ Shell::Exit(1);
+ }
}
-Handle<String> SourceGroup::ReadFile(const char* name) {
+Handle<String> SourceGroup::ReadFile(Isolate* isolate, const char* name) {
int size;
- const char* chars = ReadChars(name, &size);
+ char* chars = ReadChars(isolate, name, &size);
if (chars == NULL) return Handle<String>();
- Handle<String> result = String::New(chars, size);
+ Handle<String> result =
+ String::NewFromUtf8(isolate, chars, String::kNormalString, size);
delete[] chars;
return result;
}
#ifndef V8_SHARED
-i::Thread::Options SourceGroup::GetThreadOptions() {
+base::Thread::Options SourceGroup::GetThreadOptions() {
// On some systems (OSX 10.6) the stack size default is 0.5Mb or less
// which is not enough to parse the big literal expressions used in tests.
// The stack size should be at least StackGuard::kLimitSize + some
// OS-specific padding for thread startup code. 2Mbytes seems to be enough.
- return i::Thread::Options("IsolateThread", 2 * MB);
+ return base::Thread::Options("IsolateThread", 2 * MB);
}
void SourceGroup::ExecuteInThread() {
Isolate* isolate = Isolate::New();
do {
- if (next_semaphore_ != NULL) next_semaphore_->Wait();
+ next_semaphore_.Wait();
{
Isolate::Scope iscope(isolate);
- Locker lock(isolate);
- HandleScope scope;
- Persistent<Context> context = Shell::CreateEvaluationContext();
{
- Context::Scope cscope(context);
- Execute();
+ HandleScope scope(isolate);
+ PerIsolateData data(isolate);
+ Local<Context> context = Shell::CreateEvaluationContext(isolate);
+ {
+ Context::Scope cscope(context);
+ PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
+ Execute(isolate);
+ }
}
- context.Dispose();
+ if (Shell::options.send_idle_notification) {
+ const int kLongIdlePauseInMs = 1000;
+ isolate->ContextDisposedNotification();
+ isolate->IdleNotification(kLongIdlePauseInMs);
+ }
+ if (Shell::options.invoke_weak_callbacks) {
+ // By sending a low memory notifications, we will try hard to collect
+ // all garbage and will therefore also invoke all weak callbacks of
+ // actually unreachable persistent handles.
+ isolate->LowMemoryNotification();
+ }
}
- if (done_semaphore_ != NULL) done_semaphore_->Signal();
+ done_semaphore_.Signal();
} while (!Shell::options.last_run);
+
isolate->Dispose();
}
@@ -1247,7 +1278,7 @@
thread_ = new IsolateThread(this);
thread_->Start();
}
- next_semaphore_->Signal();
+ next_semaphore_.Signal();
}
@@ -1256,67 +1287,53 @@
if (Shell::options.last_run) {
thread_->Join();
} else {
- done_semaphore_->Wait();
+ done_semaphore_.Wait();
}
}
-#endif // V8_SHARED
+#endif // !V8_SHARED
+
+
+void SetFlagsFromString(const char* flags) {
+ v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
+}
bool Shell::SetOptions(int argc, char* argv[]) {
+ bool logfile_per_isolate = false;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--stress-opt") == 0) {
options.stress_opt = true;
argv[i] = NULL;
+ } else if (strcmp(argv[i], "--nostress-opt") == 0) {
+ options.stress_opt = false;
+ argv[i] = NULL;
} else if (strcmp(argv[i], "--stress-deopt") == 0) {
options.stress_deopt = true;
argv[i] = NULL;
+ } else if (strcmp(argv[i], "--mock-arraybuffer-allocator") == 0) {
+ options.mock_arraybuffer_allocator = true;
+ argv[i] = NULL;
} else if (strcmp(argv[i], "--noalways-opt") == 0) {
// No support for stressing if we can't use --always-opt.
options.stress_opt = false;
options.stress_deopt = false;
+ } else if (strcmp(argv[i], "--logfile-per-isolate") == 0) {
+ logfile_per_isolate = true;
+ argv[i] = NULL;
} else if (strcmp(argv[i], "--shell") == 0) {
options.interactive_shell = true;
argv[i] = NULL;
} else if (strcmp(argv[i], "--test") == 0) {
options.test_shell = true;
argv[i] = NULL;
- } else if (strcmp(argv[i], "--preemption") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- options.use_preemption = true;
+ } else if (strcmp(argv[i], "--send-idle-notification") == 0) {
+ options.send_idle_notification = true;
argv[i] = NULL;
-#endif // V8_SHARED
- } else if (strcmp(argv[i], "--nopreemption") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- options.use_preemption = false;
+ } else if (strcmp(argv[i], "--invoke-weak-callbacks") == 0) {
+ options.invoke_weak_callbacks = true;
+ // TODO(jochen) See issue 3351
+ options.send_idle_notification = true;
argv[i] = NULL;
-#endif // V8_SHARED
- } else if (strcmp(argv[i], "--preemption-interval") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- if (++i < argc) {
- argv[i-1] = NULL;
- char* end = NULL;
- options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
- if (options.preemption_interval <= 0
- || *end != '\0'
- || errno == ERANGE) {
- printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
- return false;
- }
- argv[i] = NULL;
- } else {
- printf("Missing value for --preemption-interval\n");
- return false;
- }
-#endif // V8_SHARED
} else if (strcmp(argv[i], "-f") == 0) {
// Ignore any -f flags for compatibility with other stand-alone
// JavaScript engines.
@@ -1327,48 +1344,52 @@
return false;
#endif // V8_SHARED
options.num_isolates++;
- } else if (strcmp(argv[i], "-p") == 0) {
+ } else if (strcmp(argv[i], "--dump-heap-constants") == 0) {
#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
+ printf("D8 with shared library does not support constant dumping\n");
return false;
#else
- options.num_parallel_files++;
+ options.dump_heap_constants = true;
+ argv[i] = NULL;
#endif // V8_SHARED
- }
+ } else if (strcmp(argv[i], "--throws") == 0) {
+ options.expected_to_throw = true;
+ argv[i] = NULL;
+ } else if (strncmp(argv[i], "--icu-data-file=", 16) == 0) {
+ options.icu_data_file = argv[i] + 16;
+ argv[i] = NULL;
#ifdef V8_SHARED
- else if (strcmp(argv[i], "--dump-counters") == 0) {
+ } else if (strcmp(argv[i], "--dump-counters") == 0) {
printf("D8 with shared library does not include counters\n");
return false;
} else if (strcmp(argv[i], "--debugger") == 0) {
printf("Javascript debugger not included\n");
return false;
- }
#endif // V8_SHARED
- }
-
-#ifndef V8_SHARED
- // Run parallel threads if we are not using --isolate
- options.parallel_files = new char*[options.num_parallel_files];
- int parallel_files_set = 0;
- for (int i = 1; i < argc; i++) {
- if (argv[i] == NULL) continue;
- if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
- if (options.num_isolates > 1) {
- printf("-p is not compatible with --isolate\n");
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ } else if (strncmp(argv[i], "--natives_blob=", 15) == 0) {
+ options.natives_blob = argv[i] + 15;
+ argv[i] = NULL;
+ } else if (strncmp(argv[i], "--snapshot_blob=", 16) == 0) {
+ options.snapshot_blob = argv[i] + 16;
+ argv[i] = NULL;
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+ } else if (strcmp(argv[i], "--cache") == 0 ||
+ strncmp(argv[i], "--cache=", 8) == 0) {
+ const char* value = argv[i] + 7;
+ if (!*value || strncmp(value, "=code", 6) == 0) {
+ options.compile_options = v8::ScriptCompiler::kProduceCodeCache;
+ } else if (strncmp(value, "=parse", 7) == 0) {
+ options.compile_options = v8::ScriptCompiler::kProduceParserCache;
+ } else if (strncmp(value, "=none", 6) == 0) {
+ options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
+ } else {
+ printf("Unknown option to --cache.\n");
return false;
}
argv[i] = NULL;
- i++;
- options.parallel_files[parallel_files_set] = argv[i];
- parallel_files_set++;
- argv[i] = NULL;
}
}
- if (parallel_files_set != options.num_parallel_files) {
- printf("-p requires a file containing a list of files as parameter\n");
- return false;
- }
-#endif // V8_SHARED
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
@@ -1388,152 +1409,303 @@
}
current->End(argc);
+ if (!logfile_per_isolate && options.num_isolates) {
+ SetFlagsFromString("--nologfile_per_isolate");
+ }
+
return true;
}
-int Shell::RunMain(int argc, char* argv[]) {
+int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) {
#ifndef V8_SHARED
- i::List<i::Thread*> threads(1);
- if (options.parallel_files != NULL) {
- for (int i = 0; i < options.num_parallel_files; i++) {
- char* files = NULL;
- { Locker lock(Isolate::GetCurrent());
- int size = 0;
- files = ReadChars(options.parallel_files[i], &size);
- }
- if (files == NULL) {
- printf("File list '%s' not found\n", options.parallel_files[i]);
- Exit(1);
- }
- ShellThread* thread = new ShellThread(threads.length(), files);
- thread->Start();
- threads.Add(thread);
- }
- }
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].StartExecuteInThread();
}
-#endif // V8_SHARED
- { // NOLINT
- Locker lock;
- HandleScope scope;
- Persistent<Context> context = CreateEvaluationContext();
- if (options.last_run) {
+#endif // !V8_SHARED
+ {
+ HandleScope scope(isolate);
+ Local<Context> context = CreateEvaluationContext(isolate);
+ if (options.last_run && options.use_interactive_shell()) {
// Keep using the same context in the interactive shell.
- evaluation_context_ = context;
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+ evaluation_context_.Reset(isolate, context);
+#ifndef V8_SHARED
// If the interactive debugger is enabled make sure to activate
// it before running the files passed on the command line.
if (i::FLAG_debugger) {
- InstallUtilityScript();
- }
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
- }
- {
- Context::Scope cscope(context);
- options.isolate_sources[0].Execute();
- }
- if (!options.last_run) {
- context.Dispose();
-#if !defined(V8_SHARED)
- if (i::FLAG_send_idle_notification) {
- const int kLongIdlePauseInMs = 1000;
- V8::ContextDisposedNotification();
- V8::IdleNotification(kLongIdlePauseInMs);
+ InstallUtilityScript(isolate);
}
#endif // !V8_SHARED
}
-
-#ifndef V8_SHARED
- // Start preemption if threads have been created and preemption is enabled.
- if (threads.length() > 0
- && options.use_preemption) {
- Locker::StartPreemption(options.preemption_interval);
+ {
+ Context::Scope cscope(context);
+ PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
+ options.isolate_sources[0].Execute(isolate);
}
-#endif // V8_SHARED
+ }
+ if (options.send_idle_notification) {
+ const int kLongIdlePauseInMs = 1000;
+ isolate->ContextDisposedNotification();
+ isolate->IdleNotification(kLongIdlePauseInMs);
+ }
+ if (options.invoke_weak_callbacks) {
+ // By sending a low memory notifications, we will try hard to collect all
+ // garbage and will therefore also invoke all weak callbacks of actually
+ // unreachable persistent handles.
+ isolate->LowMemoryNotification();
}
#ifndef V8_SHARED
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].WaitForThread();
}
-
- for (int i = 0; i < threads.length(); i++) {
- i::Thread* thread = threads[i];
- thread->Join();
- delete thread;
- }
-
- if (threads.length() > 0 && options.use_preemption) {
- Locker lock;
- Locker::StopPreemption();
- }
-#endif // V8_SHARED
+#endif // !V8_SHARED
return 0;
}
+#ifndef V8_SHARED
+static void DumpHeapConstants(i::Isolate* isolate) {
+ i::Heap* heap = isolate->heap();
+
+ // Dump the INSTANCE_TYPES table to the console.
+ printf("# List of known V8 instance types.\n");
+#define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
+ printf("INSTANCE_TYPES = {\n");
+ INSTANCE_TYPE_LIST(DUMP_TYPE)
+ printf("}\n");
+#undef DUMP_TYPE
+
+ // Dump the KNOWN_MAP table to the console.
+ printf("\n# List of known V8 maps.\n");
+#define ROOT_LIST_CASE(type, name, camel_name) \
+ if (n == NULL && o == heap->name()) n = #camel_name;
+#define STRUCT_LIST_CASE(upper_name, camel_name, name) \
+ if (n == NULL && o == heap->name##_map()) n = #camel_name "Map";
+ i::HeapObjectIterator it(heap->map_space());
+ printf("KNOWN_MAPS = {\n");
+ for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
+ i::Map* m = i::Map::cast(o);
+ const char* n = NULL;
+ intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
+ int t = m->instance_type();
+ ROOT_LIST(ROOT_LIST_CASE)
+ STRUCT_LIST(STRUCT_LIST_CASE)
+ if (n == NULL) continue;
+ printf(" 0x%05" V8PRIxPTR ": (%d, \"%s\"),\n", p, t, n);
+ }
+ printf("}\n");
+#undef STRUCT_LIST_CASE
+#undef ROOT_LIST_CASE
+
+ // Dump the KNOWN_OBJECTS table to the console.
+ printf("\n# List of known V8 objects.\n");
+#define ROOT_LIST_CASE(type, name, camel_name) \
+ if (n == NULL && o == heap->name()) n = #camel_name;
+ i::OldSpaces spit(heap);
+ printf("KNOWN_OBJECTS = {\n");
+ for (i::PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
+ i::HeapObjectIterator it(s);
+ const char* sname = AllocationSpaceName(s->identity());
+ for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
+ const char* n = NULL;
+ intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
+ ROOT_LIST(ROOT_LIST_CASE)
+ if (n == NULL) continue;
+ printf(" (\"%s\", 0x%05" V8PRIxPTR "): \"%s\",\n", sname, p, n);
+ }
+ }
+ printf("}\n");
+#undef ROOT_LIST_CASE
+}
+#endif // !V8_SHARED
+
+
+class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ public:
+ virtual void* Allocate(size_t length) {
+ void* data = AllocateUninitialized(length);
+ return data == NULL ? data : memset(data, 0, length);
+ }
+ virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
+ virtual void Free(void* data, size_t) { free(data); }
+};
+
+
+class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ public:
+ virtual void* Allocate(size_t) OVERRIDE {
+ return malloc(0);
+ }
+ virtual void* AllocateUninitialized(size_t length) OVERRIDE {
+ return malloc(0);
+ }
+ virtual void Free(void* p, size_t) OVERRIDE {
+ free(p);
+ }
+};
+
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+class StartupDataHandler {
+ public:
+ StartupDataHandler(const char* natives_blob,
+ const char* snapshot_blob) {
+ Load(natives_blob, &natives_, v8::V8::SetNativesDataBlob);
+ Load(snapshot_blob, &snapshot_, v8::V8::SetSnapshotDataBlob);
+ }
+
+ ~StartupDataHandler() {
+ delete[] natives_.data;
+ delete[] snapshot_.data;
+ }
+
+ private:
+ void Load(const char* blob_file,
+ v8::StartupData* startup_data,
+ void (*setter_fn)(v8::StartupData*)) {
+ startup_data->data = NULL;
+ startup_data->compressed_size = 0;
+ startup_data->raw_size = 0;
+
+ if (!blob_file)
+ return;
+
+ FILE* file = fopen(blob_file, "rb");
+ if (!file)
+ return;
+
+ fseek(file, 0, SEEK_END);
+ startup_data->raw_size = ftell(file);
+ rewind(file);
+
+ startup_data->data = new char[startup_data->raw_size];
+ startup_data->compressed_size = fread(
+ const_cast<char*>(startup_data->data), 1, startup_data->raw_size,
+ file);
+ fclose(file);
+
+ if (startup_data->raw_size == startup_data->compressed_size)
+ (*setter_fn)(startup_data);
+ }
+
+ v8::StartupData natives_;
+ v8::StartupData snapshot_;
+
+ // Disallow copy & assign.
+ StartupDataHandler(const StartupDataHandler& other);
+ void operator=(const StartupDataHandler& other);
+};
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+
+
int Shell::Main(int argc, char* argv[]) {
+#if (defined(_WIN32) || defined(_WIN64))
+ UINT new_flags =
+ SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
+ UINT existing_flags = SetErrorMode(new_flags);
+ SetErrorMode(existing_flags | new_flags);
+#if defined(_MSC_VER)
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+ _set_error_mode(_OUT_TO_STDERR);
+#endif // defined(_MSC_VER)
+#endif // defined(_WIN32) || defined(_WIN64)
if (!SetOptions(argc, argv)) return 1;
- Initialize();
-
- int result = 0;
- if (options.stress_opt || options.stress_deopt) {
- Testing::SetStressRunType(
- options.stress_opt ? Testing::kStressTypeOpt
- : Testing::kStressTypeDeopt);
- int stress_runs = Testing::GetStressRuns();
- for (int i = 0; i < stress_runs && result == 0; i++) {
- printf("============ Stress %d/%d ============\n", i + 1, stress_runs);
- Testing::PrepareStressRun(i);
- options.last_run = (i == stress_runs - 1);
- result = RunMain(argc, argv);
- }
- printf("======== Full Deoptimization =======\n");
- Testing::DeoptimizeAll();
-#if !defined(V8_SHARED)
- } else if (i::FLAG_stress_runs > 0) {
- int stress_runs = i::FLAG_stress_runs;
- for (int i = 0; i < stress_runs && result == 0; i++) {
- printf("============ Run %d/%d ============\n", i + 1, stress_runs);
- options.last_run = (i == stress_runs - 1);
- result = RunMain(argc, argv);
- }
+ v8::V8::InitializeICU(options.icu_data_file);
+ v8::Platform* platform = v8::platform::CreateDefaultPlatform();
+ v8::V8::InitializePlatform(platform);
+ v8::V8::Initialize();
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ StartupDataHandler startup_data(options.natives_blob, options.snapshot_blob);
#endif
+ SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg");
+ SetFlagsFromString("--redirect-code-traces-to=code.asm");
+ ShellArrayBufferAllocator array_buffer_allocator;
+ MockArrayBufferAllocator mock_arraybuffer_allocator;
+ if (options.mock_arraybuffer_allocator) {
+ v8::V8::SetArrayBufferAllocator(&mock_arraybuffer_allocator);
} else {
- result = RunMain(argc, argv);
+ v8::V8::SetArrayBufferAllocator(&array_buffer_allocator);
}
-
-
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
- // Run remote debugger if requested, but never on --test
- if (i::FLAG_remote_debugger && !options.test_shell) {
- InstallUtilityScript();
- RunRemoteDebugger(i::FLAG_debugger_port);
- return 0;
+ int result = 0;
+ Isolate::CreateParams create_params;
+#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
+ if (i::FLAG_gdbjit) {
+ create_params.code_event_handler = i::GDBJITInterface::EventHandler;
}
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
-
- // Run interactive shell if explicitly requested or if no script has been
- // executed, but never on --test
-
- if (( options.interactive_shell
- || !options.script_executed )
- && !options.test_shell ) {
-#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
- if (!i::FLAG_debugger) {
- InstallUtilityScript();
- }
-#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
- RunShell();
- }
-
- V8::Dispose();
+#endif
+#ifdef ENABLE_VTUNE_JIT_INTERFACE
+ vTune::InitializeVtuneForV8(create_params);
+#endif
+#ifndef V8_SHARED
+ create_params.constraints.ConfigureDefaults(
+ base::SysInfo::AmountOfPhysicalMemory(),
+ base::SysInfo::AmountOfVirtualMemory(),
+ base::SysInfo::NumberOfProcessors());
+#endif
+ Isolate* isolate = Isolate::New(create_params);
+ DumbLineEditor dumb_line_editor(isolate);
+ {
+ Isolate::Scope scope(isolate);
+ Initialize(isolate);
+ PerIsolateData data(isolate);
+ InitializeDebugger(isolate);
#ifndef V8_SHARED
+ if (options.dump_heap_constants) {
+ DumpHeapConstants(reinterpret_cast<i::Isolate*>(isolate));
+ return 0;
+ }
+#endif
+
+ if (options.stress_opt || options.stress_deopt) {
+ Testing::SetStressRunType(options.stress_opt
+ ? Testing::kStressTypeOpt
+ : Testing::kStressTypeDeopt);
+ int stress_runs = Testing::GetStressRuns();
+ for (int i = 0; i < stress_runs && result == 0; i++) {
+ printf("============ Stress %d/%d ============\n", i + 1, stress_runs);
+ Testing::PrepareStressRun(i);
+ options.last_run = (i == stress_runs - 1);
+ result = RunMain(isolate, argc, argv);
+ }
+ printf("======== Full Deoptimization =======\n");
+ Testing::DeoptimizeAll();
+#if !defined(V8_SHARED)
+ } else if (i::FLAG_stress_runs > 0) {
+ int stress_runs = i::FLAG_stress_runs;
+ for (int i = 0; i < stress_runs && result == 0; i++) {
+ printf("============ Run %d/%d ============\n", i + 1, stress_runs);
+ options.last_run = (i == stress_runs - 1);
+ result = RunMain(isolate, argc, argv);
+ }
+#endif
+ } else {
+ result = RunMain(isolate, argc, argv);
+ }
+
+ // Run interactive shell if explicitly requested or if no script has been
+ // executed, but never on --test
+ if (options.use_interactive_shell()) {
+#ifndef V8_SHARED
+ if (!i::FLAG_debugger) {
+ InstallUtilityScript(isolate);
+ }
+#endif // !V8_SHARED
+ RunShell(isolate);
+ }
+ }
+ isolate->Dispose();
+ V8::Dispose();
+ V8::ShutdownPlatform();
+ delete platform;
+
OnExit();
-#endif // V8_SHARED
return result;
}