diff options
Diffstat (limited to 'deps/v8/src/d8.cc')
-rw-r--r-- | deps/v8/src/d8.cc | 159 |
1 files changed, 128 insertions, 31 deletions
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc index 349021d38c..5295f3957c 100644 --- a/deps/v8/src/d8.cc +++ b/deps/v8/src/d8.cc @@ -62,7 +62,7 @@ namespace { const int kMB = 1024 * 1024; -const int kMaxWorkers = 50; +const int kMaxWorkers = 100; const int kMaxSerializerMemoryUsage = 1 * kMB; // Arbitrary maximum for testing. @@ -118,23 +118,26 @@ class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase { // store their lengths as a SMI internally. if (length >= kTwoGB) return nullptr; - size_t page_size = i::AllocatePageSize(); + v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator(); + size_t page_size = page_allocator->AllocatePageSize(); size_t allocated = RoundUp(length, page_size); // Rounding up could go over the limit. if (allocated >= kTwoGB) return nullptr; - return i::AllocatePages(nullptr, allocated, page_size, + return i::AllocatePages(page_allocator, nullptr, allocated, page_size, PageAllocator::kReadWrite); } void FreeVM(void* data, size_t length) { - size_t page_size = i::AllocatePageSize(); + v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator(); + size_t page_size = page_allocator->AllocatePageSize(); size_t allocated = RoundUp(length, page_size); - CHECK(i::FreePages(data, allocated)); + CHECK(i::FreePages(page_allocator, data, allocated)); } }; // ArrayBuffer allocator that never allocates over 10MB. class MockArrayBufferAllocator : public ArrayBufferAllocatorBase { + protected: void* Allocate(size_t length) override { return ArrayBufferAllocatorBase::Allocate(Adjust(length)); } @@ -154,6 +157,39 @@ class MockArrayBufferAllocator : public ArrayBufferAllocatorBase { } }; +// ArrayBuffer allocator that can be equipped with a limit to simulate system +// OOM. +class MockArrayBufferAllocatiorWithLimit : public MockArrayBufferAllocator { + public: + explicit MockArrayBufferAllocatiorWithLimit(size_t allocation_limit) + : space_left_(allocation_limit) {} + + protected: + void* Allocate(size_t length) override { + if (length > space_left_) { + return nullptr; + } + space_left_ -= length; + return MockArrayBufferAllocator::Allocate(length); + } + + void* AllocateUninitialized(size_t length) override { + if (length > space_left_) { + return nullptr; + } + space_left_ -= length; + return MockArrayBufferAllocator::AllocateUninitialized(length); + } + + void Free(void* data, size_t length) override { + space_left_ += length; + return MockArrayBufferAllocator::Free(data, length); + } + + private: + std::atomic<size_t> space_left_; +}; + // Predictable v8::Platform implementation. Worker threads are disabled, idle // tasks are disallowed, and the time reported by {MonotonicallyIncreasingTime} // is deterministic. @@ -195,12 +231,14 @@ class PredictablePlatform : public Platform { } void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override { - platform_->CallOnForegroundThread(isolate, task); + // This is a deprecated function and should not be called anymore. + UNREACHABLE(); } void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task, double delay_in_seconds) override { - platform_->CallDelayedOnForegroundThread(isolate, task, delay_in_seconds); + // This is a deprecated function and should not be called anymore. + UNREACHABLE(); } void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override { @@ -244,6 +282,14 @@ static Local<Value> Throw(Isolate* isolate, const char* message) { .ToLocalChecked()); } +static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context, + Local<v8::Object> object, const char* property) { + Local<String> v8_str = + String::NewFromUtf8(isolate, property, NewStringType::kNormal) + .ToLocalChecked(); + return object->Get(context, v8_str).ToLocalChecked(); +} + Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) { if (object->InternalFieldCount() != 1) { Throw(isolate, "this is not a Worker"); @@ -319,8 +365,7 @@ class TraceConfigParser { Local<v8::Object> object, const char* property) { Local<Value> value = GetValue(isolate, context, object, property); if (value->IsNumber()) { - Local<Boolean> v8_boolean = value->ToBoolean(context).ToLocalChecked(); - return v8_boolean->Value(); + return value->BooleanValue(isolate); } return false; } @@ -361,14 +406,6 @@ class TraceConfigParser { } return platform::tracing::TraceRecordMode::RECORD_UNTIL_FULL; } - - static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context, - Local<v8::Object> object, const char* property) { - Local<String> v8_str = - String::NewFromUtf8(isolate, property, NewStringType::kNormal) - .ToLocalChecked(); - return object->Get(context, v8_str).ToLocalChecked(); - } }; } // namespace @@ -433,7 +470,7 @@ class DummySourceStream : public v8::ScriptCompiler::ExternalSourceStream { source_length_); } - virtual size_t GetMoreData(const uint8_t** src) { + size_t GetMoreData(const uint8_t** src) override { if (done_) { return 0; } @@ -1405,6 +1442,39 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) { return; } + // d8 honors `options={type: string}`, which means the first argument is + // not a filename but string of script to be run. + bool load_from_file = true; + if (args.Length() > 1 && args[1]->IsObject()) { + Local<Object> object = args[1].As<Object>(); + Local<Context> context = isolate->GetCurrentContext(); + Local<Value> value = GetValue(args.GetIsolate(), context, object, "type"); + if (value->IsString()) { + Local<String> worker_type = value->ToString(context).ToLocalChecked(); + String::Utf8Value str(isolate, worker_type); + if (strcmp("string", *str) == 0) { + load_from_file = false; + } else if (strcmp("classic", *str) == 0) { + load_from_file = true; + } else { + Throw(args.GetIsolate(), "Unsupported worker type"); + return; + } + } + } + + Local<Value> source; + if (load_from_file) { + String::Utf8Value filename(args.GetIsolate(), args[0]); + source = ReadFile(args.GetIsolate(), *filename); + if (source.IsEmpty()) { + Throw(args.GetIsolate(), "Error loading worker script"); + return; + } + } else { + source = args[0]; + } + if (!args.IsConstructCall()) { Throw(args.GetIsolate(), "Worker must be constructed with new"); return; @@ -1428,7 +1498,7 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) { args.Holder()->SetAlignedPointerInInternalField(0, worker); workers_.push_back(worker); - String::Utf8Value script(args.GetIsolate(), args[0]); + String::Utf8Value script(args.GetIsolate(), source); if (!*script) { Throw(args.GetIsolate(), "Can't get worker script"); return; @@ -2016,8 +2086,9 @@ void WriteLcovDataForRange(std::vector<uint32_t>& lines, int start_line, } void WriteLcovDataForNamedRange(std::ostream& sink, - std::vector<uint32_t>& lines, std::string name, - int start_line, int end_line, uint32_t count) { + std::vector<uint32_t>& lines, + const std::string& name, int start_line, + int end_line, uint32_t count) { WriteLcovDataForRange(lines, start_line, end_line, count); sink << "FN:" << start_line + 1 << "," << name << std::endl; sink << "FNDA:" << count << "," << name << std::endl; @@ -2295,7 +2366,7 @@ class InspectorFrontend final : public v8_inspector::V8Inspector::Channel { isolate_ = context->GetIsolate(); context_.Reset(isolate_, context); } - virtual ~InspectorFrontend() = default; + ~InspectorFrontend() override = default; private: void sendResponse( @@ -2904,6 +2975,8 @@ bool Shell::SetOptions(int argc, char* argv[]) { v8::V8::SetFlagsFromCommandLine(&argc, argv, true); options.mock_arraybuffer_allocator = i::FLAG_mock_arraybuffer_allocator; + options.mock_arraybuffer_allocator_limit = + i::FLAG_mock_arraybuffer_allocator_limit; // Set up isolated source groups. options.isolate_sources = new SourceGroup[options.num_isolates]; @@ -3001,10 +3074,15 @@ void Shell::SetWaitUntilDone(Isolate* isolate, bool value) { } namespace { -bool ProcessMessages(Isolate* isolate, - std::function<platform::MessageLoopBehavior()> behavior) { +bool ProcessMessages( + Isolate* isolate, + const std::function<platform::MessageLoopBehavior()>& behavior) { Platform* platform = GetDefaultPlatform(); while (true) { + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + i::SaveContext saved_context(i_isolate); + i_isolate->set_context(nullptr); + SealHandleScope shs(isolate); while (v8::platform::PumpMessageLoop(platform, isolate, behavior())) { isolate->RunMicrotasks(); } @@ -3156,6 +3234,14 @@ class Serializer : public ValueSerializer::Delegate { } Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(element); + + if (std::find(array_buffers_.begin(), array_buffers_.end(), + array_buffer) != array_buffers_.end()) { + Throw(isolate_, + "ArrayBuffer occurs in the transfer array more than once"); + return Nothing<bool>(); + } + serializer_.TransferArrayBuffer( static_cast<uint32_t>(array_buffers_.size()), array_buffer); array_buffers_.emplace_back(isolate_, array_buffer); @@ -3344,6 +3430,12 @@ int Shell::Main(int argc, char* argv[]) { g_platform.reset(new PredictablePlatform(std::move(g_platform))); } + if (i::FLAG_trace_turbo_cfg_file == nullptr) { + SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg"); + } + if (i::FLAG_redirect_code_traces_to == nullptr) { + SetFlagsFromString("--redirect-code-traces-to=code.asm"); + } v8::V8::InitializePlatform(g_platform.get()); v8::V8::Initialize(); if (options.natives_blob || options.snapshot_blob) { @@ -3352,18 +3444,22 @@ int Shell::Main(int argc, char* argv[]) { } else { v8::V8::InitializeExternalStartupData(argv[0]); } - if (i::FLAG_trace_turbo_cfg_file == nullptr) { - SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg"); - } - if (i::FLAG_redirect_code_traces_to == nullptr) { - SetFlagsFromString("--redirect-code-traces-to=code.asm"); - } int result = 0; Isolate::CreateParams create_params; ShellArrayBufferAllocator shell_array_buffer_allocator; MockArrayBufferAllocator mock_arraybuffer_allocator; + const size_t memory_limit = + options.mock_arraybuffer_allocator_limit * options.num_isolates; + MockArrayBufferAllocatiorWithLimit mock_arraybuffer_allocator_with_limit( + memory_limit >= options.mock_arraybuffer_allocator_limit + ? memory_limit + : std::numeric_limits<size_t>::max()); if (options.mock_arraybuffer_allocator) { - Shell::array_buffer_allocator = &mock_arraybuffer_allocator; + if (memory_limit) { + Shell::array_buffer_allocator = &mock_arraybuffer_allocator_with_limit; + } else { + Shell::array_buffer_allocator = &mock_arraybuffer_allocator; + } } else { Shell::array_buffer_allocator = &shell_array_buffer_allocator; } @@ -3454,6 +3550,7 @@ int Shell::Main(int argc, char* argv[]) { Shell::HostInitializeImportMetaObject); { D8Console console(isolate2); + Initialize(isolate2); debug::SetConsoleDelegate(isolate2, &console); PerIsolateData data(isolate2); Isolate::Scope isolate_scope(isolate2); |