diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-03-21 10:16:54 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-03-25 09:44:10 +0100 |
commit | c459d8ea5d402c702948c860d9497b2230ff7e8a (patch) | |
tree | 56c282fc4d40e5cb613b47cf7be3ea0526ed5b6f /deps/v8/src/d8.cc | |
parent | e0bc5a7361b1d29c3ed034155fd779ce6f44fb13 (diff) | |
download | android-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.cc | 305 |
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; |