summaryrefslogtreecommitdiff
path: root/deps/v8/src/d8.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-03-21 10:16:54 +0100
committerMichaël Zasso <targos@protonmail.com>2017-03-25 09:44:10 +0100
commitc459d8ea5d402c702948c860d9497b2230ff7e8a (patch)
tree56c282fc4d40e5cb613b47cf7be3ea0526ed5b6f /deps/v8/src/d8.cc
parente0bc5a7361b1d29c3ed034155fd779ce6f44fb13 (diff)
downloadandroid-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.gz
android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.bz2
android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.zip
deps: update V8 to 5.7.492.69
PR-URL: https://github.com/nodejs/node/pull/11752 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'deps/v8/src/d8.cc')
-rw-r--r--deps/v8/src/d8.cc305
1 files changed, 236 insertions, 69 deletions
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
index fd9afee808..a34bafcc65 100644
--- a/deps/v8/src/d8.cc
+++ b/deps/v8/src/d8.cc
@@ -27,9 +27,12 @@
#include "src/base/debug/stack_trace.h"
#include "src/base/logging.h"
#include "src/base/platform/platform.h"
+#include "src/base/platform/time.h"
#include "src/base/sys-info.h"
#include "src/basic-block-profiler.h"
#include "src/interpreter/interpreter.h"
+#include "src/msan.h"
+#include "src/objects-inl.h"
#include "src/snapshot/natives.h"
#include "src/utils.h"
#include "src/v8.h"
@@ -62,15 +65,76 @@ namespace {
const int MB = 1024 * 1024;
const int kMaxWorkers = 50;
+#define USE_VM 1
+#define VM_THRESHOLD 65536
+// TODO(titzer): allocations should fail if >= 2gb because of
+// array buffers storing the lengths as a SMI internally.
+#define TWO_GB (2u * 1024u * 1024u * 1024u)
class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) {
+#if USE_VM
+ if (RoundToPageSize(&length)) {
+ void* data = VirtualMemoryAllocate(length);
+#if DEBUG
+ if (data) {
+ // In debug mode, check the memory is zero-initialized.
+ size_t limit = length / sizeof(uint64_t);
+ uint64_t* ptr = reinterpret_cast<uint64_t*>(data);
+ for (size_t i = 0; i < limit; i++) {
+ DCHECK_EQ(0u, ptr[i]);
+ }
+ }
+#endif
+ return data;
+ }
+#endif
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); }
+ virtual void* AllocateUninitialized(size_t length) {
+#if USE_VM
+ if (RoundToPageSize(&length)) return VirtualMemoryAllocate(length);
+#endif
+// Work around for GCC bug on AIX
+// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
+#if V8_OS_AIX && _LINUX_SOURCE_COMPAT
+ return __linux_malloc(length);
+#else
+ return malloc(length);
+#endif
+ }
+ virtual void Free(void* data, size_t length) {
+#if USE_VM
+ if (RoundToPageSize(&length)) {
+ base::VirtualMemory::ReleaseRegion(data, length);
+ return;
+ }
+#endif
+ free(data);
+ }
+ // If {length} is at least {VM_THRESHOLD}, round up to next page size
+ // and return {true}. Otherwise return {false}.
+ bool RoundToPageSize(size_t* length) {
+ const size_t kPageSize = base::OS::CommitPageSize();
+ if (*length >= VM_THRESHOLD && *length < TWO_GB) {
+ *length = ((*length + kPageSize - 1) / kPageSize) * kPageSize;
+ return true;
+ }
+ return false;
+ }
+#if USE_VM
+ void* VirtualMemoryAllocate(size_t length) {
+ void* data = base::VirtualMemory::ReserveRegion(length);
+ if (data && !base::VirtualMemory::CommitRegion(data, length, false)) {
+ base::VirtualMemory::ReleaseRegion(data, length);
+ return nullptr;
+ }
+ MSAN_MEMORY_IS_INITIALIZED(data, length);
+ return data;
+ }
+#endif
};
@@ -366,12 +430,6 @@ bool CounterMap::Match(void* key1, void* key2) {
}
-// Converts a V8 value to a C string.
-const char* Shell::ToCString(const v8::String::Utf8Value& value) {
- return *value ? *value : "<string conversion failed>";
-}
-
-
ScriptCompiler::CachedData* CompileForCachedData(
Local<String> source, Local<Value> name,
ScriptCompiler::CompileOptions compile_options) {
@@ -810,20 +868,24 @@ void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
MaybeLocal<Context> Shell::CreateRealm(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
+ const v8::FunctionCallbackInfo<v8::Value>& args, int index,
+ v8::MaybeLocal<Value> global_object) {
Isolate* isolate = args.GetIsolate();
TryCatch try_catch(isolate);
PerIsolateData* data = PerIsolateData::Get(isolate);
- Global<Context>* old_realms = data->realms_;
- int index = data->realm_count_;
- data->realms_ = new Global<Context>[++data->realm_count_];
- for (int i = 0; i < index; ++i) {
- data->realms_[i].Reset(isolate, old_realms[i]);
- old_realms[i].Reset();
- }
- delete[] old_realms;
+ if (index < 0) {
+ Global<Context>* old_realms = data->realms_;
+ index = data->realm_count_;
+ data->realms_ = new Global<Context>[++data->realm_count_];
+ for (int i = 0; i < index; ++i) {
+ data->realms_[i].Reset(isolate, old_realms[i]);
+ old_realms[i].Reset();
+ }
+ delete[] old_realms;
+ }
Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
- Local<Context> context = Context::New(isolate, NULL, global_template);
+ Local<Context> context =
+ Context::New(isolate, NULL, global_template, global_object);
if (context.IsEmpty()) {
DCHECK(try_catch.HasCaught());
try_catch.ReThrow();
@@ -835,10 +897,20 @@ MaybeLocal<Context> Shell::CreateRealm(
return context;
}
+void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
+ int index) {
+ Isolate* isolate = args.GetIsolate();
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
+ data->realms_[index].Reset();
+ isolate->ContextDisposedNotification();
+ isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
+}
+
// Realm.create() creates a new realm with a distinct security token
// and returns its index.
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
- CreateRealm(args);
+ CreateRealm(args, -1, v8::MaybeLocal<Value>());
}
// Realm.createAllowCrossRealmAccess() creates a new realm with the same
@@ -846,12 +918,26 @@ void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
void Shell::RealmCreateAllowCrossRealmAccess(
const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Context> context;
- if (CreateRealm(args).ToLocal(&context)) {
+ if (CreateRealm(args, -1, v8::MaybeLocal<Value>()).ToLocal(&context)) {
context->SetSecurityToken(
args.GetIsolate()->GetEnteredContext()->GetSecurityToken());
}
}
+// Realm.navigate(i) creates a new realm with a distinct security token
+// in place of realm i.
+void Shell::RealmNavigate(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;
+
+ Local<Context> context = Local<Context>::New(isolate, data->realms_[index]);
+ v8::MaybeLocal<Value> global_object = context->Global();
+ DisposeRealm(args, index);
+ CreateRealm(args, index, global_object);
+}
+
// Realm.dispose(i) disposes the reference to the realm i.
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
@@ -863,10 +949,7 @@ void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
Throw(args.GetIsolate(), "Invalid realm index");
return;
}
- DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
- data->realms_[index].Reset();
- isolate->ContextDisposedNotification();
- isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
+ DisposeRealm(args, index);
}
@@ -1200,12 +1283,17 @@ void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
HandleScope handle_scope(isolate);
- Local<Context> context;
- bool enter_context = !isolate->InContext();
+ Local<Context> context = isolate->GetCurrentContext();
+ bool enter_context = context.IsEmpty();
if (enter_context) {
context = Local<Context>::New(isolate, evaluation_context_);
context->Enter();
}
+ // Converts a V8 value to a C string.
+ auto ToCString = [](const v8::String::Utf8Value& value) {
+ return *value ? *value : "<string conversion failed>";
+ };
+
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception);
Local<Message> message = try_catch->Message();
@@ -1213,40 +1301,40 @@ void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
// V8 didn't provide any extra information about this error; just
// print the exception.
printf("%s\n", exception_string);
+ } else if (message->GetScriptOrigin().Options().IsWasm()) {
+ // Print <WASM>[(function index)]((function name))+(offset): (message).
+ int function_index = message->GetLineNumber(context).FromJust() - 1;
+ int offset = message->GetStartColumn(context).FromJust();
+ printf("<WASM>[%d]+%d: %s\n", function_index, offset, exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
const char* filename_string = ToCString(filename);
- Maybe<int> maybeline = message->GetLineNumber(isolate->GetCurrentContext());
- int linenum = maybeline.IsJust() ? maybeline.FromJust() : -1;
+ int linenum = message->GetLineNumber(context).FromMaybe(-1);
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
Local<String> sourceline;
- if (message->GetSourceLine(isolate->GetCurrentContext())
- .ToLocal(&sourceline)) {
+ if (message->GetSourceLine(context).ToLocal(&sourceline)) {
// Print line of source code.
v8::String::Utf8Value sourcelinevalue(sourceline);
const char* sourceline_string = ToCString(sourcelinevalue);
printf("%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
- int start =
- message->GetStartColumn(isolate->GetCurrentContext()).FromJust();
+ int start = message->GetStartColumn(context).FromJust();
for (int i = 0; i < start; i++) {
printf(" ");
}
- int end = message->GetEndColumn(isolate->GetCurrentContext()).FromJust();
+ int end = message->GetEndColumn(context).FromJust();
for (int i = start; i < end; i++) {
printf("^");
}
printf("\n");
}
- Local<Value> stack_trace_string;
- if (try_catch->StackTrace(isolate->GetCurrentContext())
- .ToLocal(&stack_trace_string) &&
- stack_trace_string->IsString()) {
- v8::String::Utf8Value stack_trace(
- Local<String>::Cast(stack_trace_string));
- printf("%s\n", ToCString(stack_trace));
- }
+ }
+ Local<Value> stack_trace_string;
+ if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
+ stack_trace_string->IsString()) {
+ v8::String::Utf8Value stack_trace(Local<String>::Cast(stack_trace_string));
+ printf("%s\n", ToCString(stack_trace));
}
printf("\n");
if (enter_context) context->Exit();
@@ -1455,6 +1543,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
.ToLocalChecked(),
FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
realm_template->Set(
+ String::NewFromUtf8(isolate, "navigate", NewStringType::kNormal)
+ .ToLocalChecked(),
+ FunctionTemplate::New(isolate, RealmNavigate));
+ realm_template->Set(
String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
.ToLocalChecked(),
FunctionTemplate::New(isolate, RealmDispose));
@@ -1524,9 +1616,43 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
return global_template;
}
-static void EmptyMessageCallback(Local<Message> message, Local<Value> error) {
- // Nothing to be done here, exceptions thrown up to the shell will be reported
+static void PrintNonErrorsMessageCallback(Local<Message> message,
+ Local<Value> error) {
+ // Nothing to do here for errors, exceptions thrown up to the shell will be
+ // reported
// separately by {Shell::ReportException} after they are caught.
+ // Do print other kinds of messages.
+ switch (message->ErrorLevel()) {
+ case v8::Isolate::kMessageWarning:
+ case v8::Isolate::kMessageLog:
+ case v8::Isolate::kMessageInfo:
+ case v8::Isolate::kMessageDebug: {
+ break;
+ }
+
+ case v8::Isolate::kMessageError: {
+ // Ignore errors, printed elsewhere.
+ return;
+ }
+
+ default: {
+ UNREACHABLE();
+ break;
+ }
+ }
+ // Converts a V8 value to a C string.
+ auto ToCString = [](const v8::String::Utf8Value& value) {
+ return *value ? *value : "<string conversion failed>";
+ };
+ Isolate* isolate = Isolate::GetCurrent();
+ v8::String::Utf8Value msg(message->Get());
+ const char* msg_string = ToCString(msg);
+ // Print (filename):(line number): (message).
+ v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
+ const char* filename_string = ToCString(filename);
+ Maybe<int> maybeline = message->GetLineNumber(isolate->GetCurrentContext());
+ int linenum = maybeline.IsJust() ? maybeline.FromJust() : -1;
+ printf("%s:%i: %s\n", filename_string, linenum, msg_string);
}
void Shell::Initialize(Isolate* isolate) {
@@ -1534,7 +1660,11 @@ void Shell::Initialize(Isolate* isolate) {
if (i::StrLength(i::FLAG_map_counters) != 0)
MapCounters(isolate, i::FLAG_map_counters);
// Disable default message reporting.
- isolate->AddMessageListener(EmptyMessageCallback);
+ isolate->AddMessageListenerWithErrorLevel(
+ PrintNonErrorsMessageCallback,
+ v8::Isolate::kMessageError | v8::Isolate::kMessageWarning |
+ v8::Isolate::kMessageInfo | v8::Isolate::kMessageDebug |
+ v8::Isolate::kMessageLog);
}
@@ -1595,7 +1725,7 @@ void Shell::WriteIgnitionDispatchCountersFile(v8::Isolate* isolate) {
void Shell::OnExit(v8::Isolate* isolate) {
- if (i::FLAG_dump_counters) {
+ if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp) {
int number_of_counters = 0;
for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
number_of_counters++;
@@ -1607,24 +1737,44 @@ void Shell::OnExit(v8::Isolate* isolate) {
counters[j].key = i.CurrentKey();
}
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:%-60s | %11i |\n", key, counter->count());
- printf("| t:%-60s | %11i |\n", key, counter->sample_total());
- } else {
- printf("| %-62s | %11i |\n", key, counter->count());
+
+ if (i::FLAG_dump_counters_nvp) {
+ // Dump counters as name-value pairs.
+ 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:%s\"=%i\n", key, counter->count());
+ printf("\"t:%s\"=%i\n", key, counter->sample_total());
+ } else {
+ printf("\"%s\"=%i\n", key, counter->count());
+ }
}
+ } else {
+ // Dump counters in formatted boxes.
+ 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:%-60s | %11i |\n", key, counter->count());
+ printf("| t:%-60s | %11i |\n", key, counter->sample_total());
+ } else {
+ printf("| %-62s | %11i |\n", key, counter->count());
+ }
+ }
+ printf(
+ "+----------------------------------------------------------------+"
+ "-------------+\n");
}
- printf("+----------------------------------------------------------------+"
- "-------------+\n");
delete [] counters;
}
@@ -1771,13 +1921,14 @@ class InspectorFrontend final : public v8_inspector::V8Inspector::Channel {
virtual ~InspectorFrontend() = default;
private:
- void sendProtocolResponse(int callId,
- const v8_inspector::StringView& message) override {
- Send(message);
+ void sendResponse(
+ int callId,
+ std::unique_ptr<v8_inspector::StringBuffer> message) override {
+ Send(message->string());
}
- void sendProtocolNotification(
- const v8_inspector::StringView& message) override {
- Send(message);
+ void sendNotification(
+ std::unique_ptr<v8_inspector::StringBuffer> message) override {
+ Send(message->string());
}
void flushProtocolNotifications() override {}
@@ -1806,7 +1957,21 @@ class InspectorFrontend final : public v8_inspector::V8Inspector::Channel {
Local<Value> args[] = {message};
MaybeLocal<Value> result = Local<Function>::Cast(callback)->Call(
context, Undefined(isolate_), 1, args);
- CHECK(!result.IsEmpty()); // Listeners may not throw.
+#ifdef DEBUG
+ if (try_catch.HasCaught()) {
+ Local<Object> exception = Local<Object>::Cast(try_catch.Exception());
+ Local<String> key = v8::String::NewFromUtf8(isolate_, "message",
+ v8::NewStringType::kNormal)
+ .ToLocalChecked();
+ Local<String> expected =
+ v8::String::NewFromUtf8(isolate_,
+ "Maximum call stack size exceeded",
+ v8::NewStringType::kNormal)
+ .ToLocalChecked();
+ Local<Value> value = exception->Get(context, key).ToLocalChecked();
+ CHECK(value->StrictEquals(expected));
+ }
+#endif
}
}
@@ -2467,6 +2632,8 @@ void Shell::CollectGarbage(Isolate* isolate) {
void Shell::EmptyMessageQueues(Isolate* isolate) {
if (!i::FLAG_verify_predictable) {
while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
+ v8::platform::RunIdleTasks(g_platform, isolate,
+ 50.0 / base::Time::kMillisecondsPerSecond);
}
}
@@ -2854,7 +3021,7 @@ int Shell::Main(int argc, char* argv[]) {
base::SysInfo::AmountOfVirtualMemory());
Shell::counter_map_ = new CounterMap();
- if (i::FLAG_dump_counters || i::FLAG_gc_stats) {
+ if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp || i::FLAG_gc_stats) {
create_params.counter_lookup_callback = LookupCounter;
create_params.create_histogram_callback = CreateHistogram;
create_params.add_histogram_sample_callback = AddHistogramSample;