summaryrefslogtreecommitdiff
path: root/deps/v8/src/d8/d8.cc
diff options
context:
space:
mode:
authorMatheus Marchini <mmarchini@netflix.com>2020-03-05 10:49:19 -0800
committerMatheus Marchini <mmarchini@netflix.com>2020-03-18 16:23:22 -0700
commit2883c855e0105b51e5c8020d21458af109ffe3d4 (patch)
tree26777aad0a398e9f7755c8b65ac76827fe352a81 /deps/v8/src/d8/d8.cc
parent5f0af2af2a67216e00fe07ccda11e889d14abfcd (diff)
downloadnode-new-2883c855e0105b51e5c8020d21458af109ffe3d4.tar.gz
deps: update V8 to 8.1.307.20
PR-URL: https://github.com/nodejs/node/pull/32116 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'deps/v8/src/d8/d8.cc')
-rw-r--r--deps/v8/src/d8/d8.cc318
1 files changed, 234 insertions, 84 deletions
diff --git a/deps/v8/src/d8/d8.cc b/deps/v8/src/d8/d8.cc
index 33f2b70b14..d6d21bf5fa 100644
--- a/deps/v8/src/d8/d8.cc
+++ b/deps/v8/src/d8/d8.cc
@@ -21,6 +21,7 @@
#include "include/libplatform/libplatform.h"
#include "include/libplatform/v8-tracing.h"
#include "include/v8-inspector.h"
+#include "include/v8-profiler.h"
#include "src/api/api-inl.h"
#include "src/base/cpu.h"
#include "src/base/logging.h"
@@ -31,6 +32,7 @@
#include "src/d8/d8-platforms.h"
#include "src/d8/d8.h"
#include "src/debug/debug-interface.h"
+#include "src/deoptimizer/deoptimizer.h"
#include "src/diagnostics/basic-block-profiler.h"
#include "src/execution/vm-state-inl.h"
#include "src/init/v8.h"
@@ -42,8 +44,8 @@
#include "src/parsing/parse-info.h"
#include "src/parsing/parsing.h"
#include "src/parsing/scanner-character-streams.h"
+#include "src/profiler/profile-generator.h"
#include "src/sanitizer/msan.h"
-#include "src/snapshot/natives.h"
#include "src/trap-handler/trap-handler.h"
#include "src/utils/ostreams.h"
#include "src/utils/utils.h"
@@ -57,6 +59,10 @@
#include "unicode/locid.h"
#endif // V8_INTL_SUPPORT
+#ifdef V8_OS_LINUX
+#include <sys/mman.h> // For MultiMappedAllocator.
+#endif
+
#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h> // NOLINT
#else
@@ -129,19 +135,12 @@ class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase {
private:
static constexpr size_t kVMThreshold = 65536;
- static constexpr size_t kTwoGB = 2u * 1024u * 1024u * 1024u;
void* AllocateVM(size_t length) {
DCHECK_LE(kVMThreshold, length);
- // TODO(titzer): allocations should fail if >= 2gb because array buffers
- // store their lengths as a SMI internally.
- if (length >= kTwoGB) return nullptr;
-
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(page_allocator, nullptr, allocated, page_size,
PageAllocator::kReadWrite);
}
@@ -209,6 +208,101 @@ class MockArrayBufferAllocatiorWithLimit : public MockArrayBufferAllocator {
std::atomic<size_t> space_left_;
};
+#ifdef V8_OS_LINUX
+
+// This is a mock allocator variant that provides a huge virtual allocation
+// backed by a small real allocation that is repeatedly mapped. If you create an
+// array on memory allocated by this allocator, you will observe that elements
+// will alias each other as if their indices were modulo-divided by the real
+// allocation length.
+// The purpose is to allow stability-testing of huge (typed) arrays without
+// actually consuming huge amounts of physical memory.
+// This is currently only available on Linux because it relies on {mremap}.
+class MultiMappedAllocator : public ArrayBufferAllocatorBase {
+ protected:
+ void* Allocate(size_t length) override {
+ if (length < kChunkSize) {
+ return ArrayBufferAllocatorBase::Allocate(length);
+ }
+ // We use mmap, which initializes pages to zero anyway.
+ return AllocateUninitialized(length);
+ }
+
+ void* AllocateUninitialized(size_t length) override {
+ if (length < kChunkSize) {
+ return ArrayBufferAllocatorBase::AllocateUninitialized(length);
+ }
+ size_t rounded_length = RoundUp(length, kChunkSize);
+ int prot = PROT_READ | PROT_WRITE;
+ // We have to specify MAP_SHARED to make {mremap} below do what we want.
+ int flags = MAP_SHARED | MAP_ANONYMOUS;
+ void* real_alloc = mmap(nullptr, kChunkSize, prot, flags, -1, 0);
+ if (reinterpret_cast<intptr_t>(real_alloc) == -1) {
+ // If we ran into some limit (physical or virtual memory, or number
+ // of mappings, etc), return {nullptr}, which callers can handle.
+ if (errno == ENOMEM) {
+ return nullptr;
+ }
+ // Other errors may be bugs which we want to learn about.
+ FATAL("mmap (real) failed with error %d: %s", errno, strerror(errno));
+ }
+ void* virtual_alloc =
+ mmap(nullptr, rounded_length, prot, flags | MAP_NORESERVE, -1, 0);
+ if (reinterpret_cast<intptr_t>(virtual_alloc) == -1) {
+ if (errno == ENOMEM) {
+ // Undo earlier, successful mappings.
+ munmap(real_alloc, kChunkSize);
+ return nullptr;
+ }
+ FATAL("mmap (virtual) failed with error %d: %s", errno, strerror(errno));
+ }
+ i::Address virtual_base = reinterpret_cast<i::Address>(virtual_alloc);
+ i::Address virtual_end = virtual_base + rounded_length;
+ for (i::Address to_map = virtual_base; to_map < virtual_end;
+ to_map += kChunkSize) {
+ // Specifying 0 as the "old size" causes the existing map entry to not
+ // get deleted, which is important so that we can remap it again in the
+ // next iteration of this loop.
+ void* result =
+ mremap(real_alloc, 0, kChunkSize, MREMAP_MAYMOVE | MREMAP_FIXED,
+ reinterpret_cast<void*>(to_map));
+ if (reinterpret_cast<intptr_t>(result) == -1) {
+ if (errno == ENOMEM) {
+ // Undo earlier, successful mappings.
+ munmap(real_alloc, kChunkSize);
+ munmap(virtual_alloc, (to_map - virtual_base));
+ return nullptr;
+ }
+ FATAL("mremap failed with error %d: %s", errno, strerror(errno));
+ }
+ }
+ base::MutexGuard lock_guard(&regions_mutex_);
+ regions_[virtual_alloc] = real_alloc;
+ return virtual_alloc;
+ }
+
+ void Free(void* data, size_t length) override {
+ if (length < kChunkSize) {
+ return ArrayBufferAllocatorBase::Free(data, length);
+ }
+ base::MutexGuard lock_guard(&regions_mutex_);
+ void* real_alloc = regions_[data];
+ munmap(real_alloc, kChunkSize);
+ size_t rounded_length = RoundUp(length, kChunkSize);
+ munmap(data, rounded_length);
+ regions_.erase(data);
+ }
+
+ private:
+ // Aiming for a "Huge Page" (2M on Linux x64) to go easy on the TLB.
+ static constexpr size_t kChunkSize = 2 * 1024 * 1024;
+
+ std::unordered_map<void*, void*> regions_;
+ base::Mutex regions_mutex_;
+};
+
+#endif // V8_OS_LINUX
+
v8::Platform* g_default_platform;
std::unique_ptr<v8::Platform> g_platform;
@@ -455,10 +549,10 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
parse_info.set_allow_lazy_parsing();
parse_info.set_language_mode(
i::construct_language_mode(i::FLAG_use_strict));
- parse_info.set_script(
- parse_info.CreateScript(i_isolate, str, options.compile_options));
- if (!i::parsing::ParseProgram(&parse_info, i_isolate)) {
+ i::Handle<i::Script> script =
+ parse_info.CreateScript(i_isolate, str, options.compile_options);
+ if (!i::parsing::ParseProgram(&parse_info, script, i_isolate)) {
fprintf(stderr, "Failed parsing\n");
return false;
}
@@ -467,7 +561,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
HandleScope handle_scope(isolate);
TryCatch try_catch(isolate);
- try_catch.SetVerbose(true);
+ try_catch.SetVerbose(report_exceptions == kReportExceptions);
MaybeLocal<Value> maybe_result;
bool success = true;
@@ -518,8 +612,6 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
Local<Script> script;
if (!maybe_script.ToLocal(&script)) {
- // Print errors that happened during compilation.
- if (report_exceptions) ReportException(isolate, &try_catch);
return false;
}
@@ -546,11 +638,10 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
Local<Value> result;
if (!maybe_result.ToLocal(&result)) {
DCHECK(try_catch.HasCaught());
- // Print errors that happened during execution.
- if (report_exceptions) ReportException(isolate, &try_catch);
return false;
}
- DCHECK(!try_catch.HasCaught());
+ // It's possible that a FinalizationGroup cleanup task threw an error.
+ if (try_catch.HasCaught()) success = false;
if (print_result) {
if (options.test_shell) {
if (!result->IsUndefined()) {
@@ -942,8 +1033,11 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {
std::string absolute_path = NormalizePath(file_name, GetWorkingDirectory());
+ // Use a non-verbose TryCatch and report exceptions manually using
+ // Shell::ReportException, because some errors (such as file errors) are
+ // thrown without entering JS and thus do not trigger
+ // isolate->ReportPendingMessages().
TryCatch try_catch(isolate);
- try_catch.SetVerbose(true);
Local<Module> root_module;
@@ -963,7 +1057,6 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {
Local<Value> result;
if (!maybe_result.ToLocal(&result)) {
DCHECK(try_catch.HasCaught());
- // Print errors that happened during execution.
ReportException(isolate, &try_catch);
return false;
}
@@ -1113,9 +1206,13 @@ void Shell::PerformanceMeasureMemory(
mode = v8::MeasureMemoryMode::kDetailed;
}
}
- v8::MaybeLocal<v8::Promise> result =
- args.GetIsolate()->MeasureMemory(context, mode);
- args.GetReturnValue().Set(result.FromMaybe(v8::Local<v8::Promise>()));
+ Local<v8::Promise::Resolver> promise_resolver =
+ v8::Promise::Resolver::New(context).ToLocalChecked();
+ args.GetIsolate()->MeasureMemory(
+ v8::MeasureMemoryDelegate::Default(isolate, context, promise_resolver,
+ mode),
+ v8::MeasureMemoryExecution::kEager);
+ args.GetReturnValue().Set(promise_resolver->GetPromise());
}
// Realm.current() returns the index of the currently active realm.
@@ -1367,7 +1464,7 @@ void WriteToFile(FILE* file, const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<String> str_obj;
if (arg->IsSymbol()) {
- arg = Local<Symbol>::Cast(arg)->Name();
+ arg = Local<Symbol>::Cast(arg)->Description();
}
if (!arg->ToString(args.GetIsolate()->GetCurrentContext())
.ToLocal(&str_obj)) {
@@ -1659,7 +1756,8 @@ void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
.ToLocalChecked());
}
-void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
+void Shell::ReportException(Isolate* isolate, Local<v8::Message> message,
+ Local<v8::Value> exception_obj) {
HandleScope handle_scope(isolate);
Local<Context> context = isolate->GetCurrentContext();
bool enter_context = context.IsEmpty();
@@ -1672,18 +1770,17 @@ void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
return *value ? *value : "<string conversion failed>";
};
- v8::String::Utf8Value exception(isolate, try_catch->Exception());
+ v8::String::Utf8Value exception(isolate, exception_obj);
const char* exception_string = ToCString(exception);
- Local<Message> message = try_catch->Message();
if (message.IsEmpty()) {
// 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[(function index)]:(offset): (message).
- int function_index = message->GetLineNumber(context).FromJust() - 1;
+ int function_index = message->GetWasmFunctionIndex();
int offset = message->GetStartColumn(context).FromJust();
- printf("wasm-function[%d]:%d: %s\n", function_index, offset,
+ printf("wasm-function[%d]:0x%x: %s\n", function_index, offset,
exception_string);
} else {
// Print (filename):(line number): (message).
@@ -1711,7 +1808,8 @@ void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
}
}
Local<Value> stack_trace_string;
- if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
+ if (v8::TryCatch::StackTrace(context, exception_obj)
+ .ToLocal(&stack_trace_string) &&
stack_trace_string->IsString()) {
v8::String::Utf8Value stack_trace(isolate,
Local<String>::Cast(stack_trace_string));
@@ -1721,6 +1819,10 @@ void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
if (enter_context) context->Exit();
}
+void Shell::ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
+ ReportException(isolate, try_catch->Message(), try_catch->Exception());
+}
+
int32_t* Counter::Bind(const char* name, bool is_histogram) {
int i;
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -2022,12 +2124,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
return global_template;
}
-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.
+static void PrintMessageCallback(Local<Message> message, Local<Value> error) {
switch (message->ErrorLevel()) {
case v8::Isolate::kMessageWarning:
case v8::Isolate::kMessageLog:
@@ -2037,7 +2134,7 @@ static void PrintNonErrorsMessageCallback(Local<Message> message,
}
case v8::Isolate::kMessageError: {
- // Ignore errors, printed elsewhere.
+ Shell::ReportException(message->GetIsolate(), message, error);
return;
}
@@ -2068,7 +2165,7 @@ void Shell::Initialize(Isolate* isolate) {
}
// Disable default message reporting.
isolate->AddMessageListenerWithErrorLevel(
- PrintNonErrorsMessageCallback,
+ PrintMessageCallback,
v8::Isolate::kMessageError | v8::Isolate::kMessageWarning |
v8::Isolate::kMessageInfo | v8::Isolate::kMessageDebug |
v8::Isolate::kMessageLog);
@@ -2082,7 +2179,7 @@ Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
EscapableHandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate, nullptr, global_template);
DCHECK(!context.IsEmpty());
- if (i::FLAG_perf_prof_annotate_wasm) {
+ if (i::FLAG_perf_prof_annotate_wasm || i::FLAG_vtune_prof_annotate_wasm) {
isolate->SetWasmLoadSourceMapCallback(ReadFile);
}
InitializeModuleEmbedderData(context);
@@ -2318,23 +2415,6 @@ static char* ReadChars(const char* name, int* size_out) {
return chars;
}
-struct DataAndPersistent {
- uint8_t* data;
- int byte_length;
- Global<ArrayBuffer> handle;
-};
-
-static void ReadBufferWeakCallback(
- const v8::WeakCallbackInfo<DataAndPersistent>& data) {
- int byte_length = data.GetParameter()->byte_length;
- 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) {
static_assert(sizeof(char) == sizeof(uint8_t),
"char and uint8_t should both have 1 byte");
@@ -2346,19 +2426,20 @@ void Shell::ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
- DataAndPersistent* data = new DataAndPersistent;
- data->data = reinterpret_cast<uint8_t*>(ReadChars(*filename, &length));
- if (data->data == nullptr) {
- delete data;
+ uint8_t* data = reinterpret_cast<uint8_t*>(ReadChars(*filename, &length));
+ if (data == nullptr) {
Throw(isolate, "Error reading file");
return;
}
- data->byte_length = length;
- Local<v8::ArrayBuffer> buffer = ArrayBuffer::New(isolate, data->data, length);
- data->handle.Reset(isolate, buffer);
- data->handle.SetWeak(data, ReadBufferWeakCallback,
- v8::WeakCallbackType::kParameter);
- isolate->AdjustAmountOfExternalAllocatedMemory(length);
+ std::unique_ptr<v8::BackingStore> backing_store =
+ ArrayBuffer::NewBackingStore(
+ data, length,
+ [](void* data, size_t length, void*) {
+ delete[] reinterpret_cast<uint8_t*>(data);
+ },
+ nullptr);
+ Local<v8::ArrayBuffer> buffer =
+ ArrayBuffer::New(isolate, std::move(backing_store));
args.GetReturnValue().Set(buffer);
}
@@ -2515,13 +2596,13 @@ class InspectorClient : public v8_inspector::V8InspectorClient {
if (!callback->IsFunction()) return;
v8::TryCatch try_catch(isolate_);
+ try_catch.SetVerbose(true);
is_paused = true;
while (is_paused) {
USE(Local<Function>::Cast(callback)->Call(context, Undefined(isolate_), 0,
{}));
if (try_catch.HasCaught()) {
- Shell::ReportException(isolate_, &try_catch);
is_paused = false;
}
}
@@ -2872,6 +2953,7 @@ void Worker::ExecuteInThread() {
break;
}
v8::TryCatch try_catch(isolate);
+ try_catch.SetVerbose(true);
HandleScope scope(isolate);
Local<Value> value;
if (Shell::DeserializeValue(isolate, std::move(data))
@@ -2881,9 +2963,6 @@ void Worker::ExecuteInThread() {
onmessage_fun->Call(context, global, 1, argv);
USE(result);
}
- if (try_catch.HasCaught()) {
- Shell::ReportException(isolate, &try_catch);
- }
}
}
}
@@ -2941,9 +3020,6 @@ bool Shell::SetOptions(int argc, char* argv[]) {
strcmp(argv[i], "--no-stress-opt") == 0) {
options.stress_opt = false;
argv[i] = nullptr;
- } else if (strcmp(argv[i], "--stress-deopt") == 0) {
- options.stress_deopt = true;
- argv[i] = nullptr;
} else if (strcmp(argv[i], "--stress-background-compile") == 0) {
options.stress_background_compile = true;
argv[i] = nullptr;
@@ -2955,7 +3031,6 @@ bool Shell::SetOptions(int argc, char* argv[]) {
strcmp(argv[i], "--no-always-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] = nullptr;
@@ -3065,6 +3140,13 @@ bool Shell::SetOptions(int argc, char* argv[]) {
// Delay execution of tasks by 0-100ms randomly (based on --random-seed).
options.stress_delay_tasks = true;
argv[i] = nullptr;
+ } else if (strcmp(argv[i], "--cpu-profiler") == 0) {
+ options.cpu_profiler = true;
+ argv[i] = nullptr;
+ } else if (strcmp(argv[i], "--cpu-profiler-print") == 0) {
+ options.cpu_profiler = true;
+ options.cpu_profiler_print = true;
+ argv[i] = nullptr;
}
}
@@ -3072,6 +3154,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.mock_arraybuffer_allocator = i::FLAG_mock_arraybuffer_allocator;
options.mock_arraybuffer_allocator_limit =
i::FLAG_mock_arraybuffer_allocator_limit;
+#if V8_OS_LINUX
+ options.multi_mapped_mock_allocator = i::FLAG_multi_mapped_mock_allocator;
+#endif
// Set up isolated source groups.
options.isolate_sources = new SourceGroup[options.num_isolates];
@@ -3181,7 +3266,6 @@ bool RunSetTimeoutCallback(Isolate* isolate, bool* did_run) {
try_catch.SetVerbose(true);
Context::Scope context_scope(context);
if (callback->Call(context, Undefined(isolate), 0, nullptr).IsEmpty()) {
- Shell::ReportException(isolate, &try_catch);
return false;
}
*did_run = true;
@@ -3198,7 +3282,6 @@ bool RunCleanupFinalizationGroupCallback(Isolate* isolate, bool* did_run) {
TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
if (FinalizationGroup::Cleanup(fg).IsNothing()) {
- Shell::ReportException(isolate, &try_catch);
return false;
}
}
@@ -3395,9 +3478,6 @@ class Serializer : public ValueSerializer::Delegate {
}
auto backing_store = array_buffer->GetBackingStore();
- if (!array_buffer->IsExternal()) {
- array_buffer->Externalize(backing_store);
- }
data_->backing_stores_.push_back(std::move(backing_store));
array_buffer->Detach();
}
@@ -3468,6 +3548,52 @@ class Deserializer : public ValueDeserializer::Delegate {
DISALLOW_COPY_AND_ASSIGN(Deserializer);
};
+class D8Testing {
+ public:
+ /**
+ * Get the number of runs of a given test that is required to get the full
+ * stress coverage.
+ */
+ static int GetStressRuns() {
+ if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
+#ifdef DEBUG
+ // In debug mode the code runs much slower so stressing will only make two
+ // runs.
+ return 2;
+#else
+ return 5;
+#endif
+ }
+
+ /**
+ * Indicate the number of the run which is about to start. The value of run
+ * should be between 0 and one less than the result from GetStressRuns()
+ */
+ static void PrepareStressRun(int run) {
+ static const char* kLazyOptimizations =
+ "--prepare-always-opt "
+ "--max-inlined-bytecode-size=999999 "
+ "--max-inlined-bytecode-size-cumulative=999999 "
+ "--noalways-opt";
+ static const char* kForcedOptimizations = "--always-opt";
+
+ if (run == GetStressRuns() - 1) {
+ V8::SetFlagsFromString(kForcedOptimizations);
+ } else {
+ V8::SetFlagsFromString(kLazyOptimizations);
+ }
+ }
+
+ /**
+ * Force deoptimization of all functions.
+ */
+ static void DeoptimizeAll(Isolate* isolate) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ i::HandleScope scope(i_isolate);
+ i::Deoptimizer::DeoptimizeAll(i_isolate);
+ }
+};
+
std::unique_ptr<SerializationData> Shell::SerializeValue(
Isolate* isolate, Local<Value> value, Local<Value> transfer) {
bool ok;
@@ -3602,12 +3728,19 @@ int Shell::Main(int argc, char* argv[]) {
memory_limit >= options.mock_arraybuffer_allocator_limit
? memory_limit
: std::numeric_limits<size_t>::max());
+#if V8_OS_LINUX
+ MultiMappedAllocator multi_mapped_mock_allocator;
+#endif // V8_OS_LINUX
if (options.mock_arraybuffer_allocator) {
if (memory_limit) {
Shell::array_buffer_allocator = &mock_arraybuffer_allocator_with_limit;
} else {
Shell::array_buffer_allocator = &mock_arraybuffer_allocator;
}
+#if V8_OS_LINUX
+ } else if (options.multi_mapped_mock_allocator) {
+ Shell::array_buffer_allocator = &multi_mapped_mock_allocator;
+#endif // V8_OS_LINUX
} else {
Shell::array_buffer_allocator = &shell_array_buffer_allocator;
}
@@ -3664,19 +3797,24 @@ int Shell::Main(int argc, char* argv[]) {
tracing_controller->StartTracing(trace_config);
}
- if (options.stress_opt || options.stress_deopt) {
- Testing::SetStressRunType(options.stress_opt ? Testing::kStressTypeOpt
- : Testing::kStressTypeDeopt);
- options.stress_runs = Testing::GetStressRuns();
+ CpuProfiler* cpu_profiler;
+ if (options.cpu_profiler) {
+ cpu_profiler = CpuProfiler::New(isolate);
+ CpuProfilingOptions profile_options;
+ cpu_profiler->StartProfiling(String::Empty(isolate), profile_options);
+ }
+
+ if (options.stress_opt) {
+ options.stress_runs = D8Testing::GetStressRuns();
for (int i = 0; i < options.stress_runs && result == 0; i++) {
printf("============ Stress %d/%d ============\n", i + 1,
options.stress_runs);
- Testing::PrepareStressRun(i);
+ D8Testing::PrepareStressRun(i);
bool last_run = i == options.stress_runs - 1;
result = RunMain(isolate, argc, argv, last_run);
}
printf("======== Full Deoptimization =======\n");
- Testing::DeoptimizeAll(isolate);
+ D8Testing::DeoptimizeAll(isolate);
} else if (i::FLAG_stress_runs > 0) {
options.stress_runs = i::FLAG_stress_runs;
for (int i = 0; i < options.stress_runs && result == 0; i++) {
@@ -3738,6 +3876,18 @@ int Shell::Main(int argc, char* argv[]) {
WriteIgnitionDispatchCountersFile(isolate);
}
+ if (options.cpu_profiler) {
+ CpuProfile* profile = cpu_profiler->StopProfiling(String::Empty(isolate));
+ if (options.cpu_profiler_print) {
+ const internal::ProfileNode* root =
+ reinterpret_cast<const internal::ProfileNode*>(
+ profile->GetTopDownRoot());
+ root->Print(0);
+ }
+ profile->Delete();
+ cpu_profiler->Dispose();
+ }
+
// Shut down contexts and collect garbage.
cached_code_map_.clear();
evaluation_context_.Reset();