summaryrefslogtreecommitdiff
path: root/deps/v8/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/base')
-rw-r--r--deps/v8/src/base/OWNERS2
-rw-r--r--deps/v8/src/base/adapters.h55
-rw-r--r--deps/v8/src/base/cpu.cc71
-rw-r--r--deps/v8/src/base/file-utils.cc26
-rw-r--r--deps/v8/src/base/file-utils.h6
-rw-r--r--deps/v8/src/base/free_deleter.h1
-rw-r--r--deps/v8/src/base/iterator.h20
-rw-r--r--deps/v8/src/base/macros.h22
-rw-r--r--deps/v8/src/base/optional.h17
-rw-r--r--deps/v8/src/base/platform/mutex.h1
-rw-r--r--deps/v8/src/base/platform/platform-openbsd.cc4
-rw-r--r--deps/v8/src/base/platform/platform-posix.cc1
-rw-r--r--deps/v8/src/base/platform/semaphore.cc49
-rw-r--r--deps/v8/src/base/platform/semaphore.h4
-rw-r--r--deps/v8/src/base/template-utils.h81
-rw-r--r--deps/v8/src/base/ubsan.cc50
16 files changed, 157 insertions, 253 deletions
diff --git a/deps/v8/src/base/OWNERS b/deps/v8/src/base/OWNERS
index 9c6fd3c859..3654b400ad 100644
--- a/deps/v8/src/base/OWNERS
+++ b/deps/v8/src/base/OWNERS
@@ -1,4 +1,4 @@
-clemensh@chromium.org
+clemensb@chromium.org
mlippautz@chromium.org
# COMPONENT: Blink>JavaScript
diff --git a/deps/v8/src/base/adapters.h b/deps/v8/src/base/adapters.h
deleted file mode 100644
index f684b52ccb..0000000000
--- a/deps/v8/src/base/adapters.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Slightly adapted for inclusion in V8.
-// Copyright 2014 the V8 project authors. All rights reserved.
-
-#ifndef V8_BASE_ADAPTERS_H_
-#define V8_BASE_ADAPTERS_H_
-
-#include <iterator>
-
-#include "src/base/macros.h"
-
-namespace v8 {
-namespace base {
-
-// Internal adapter class for implementing base::Reversed.
-template <typename T>
-class ReversedAdapter {
- public:
- using Iterator =
- std::reverse_iterator<decltype(std::begin(std::declval<T>()))>;
-
- explicit ReversedAdapter(T& t) : t_(t) {}
- ReversedAdapter(const ReversedAdapter& ra) V8_NOEXCEPT = default;
-
- // TODO(clemensh): Use std::rbegin/std::rend once we have C++14 support.
- Iterator begin() const { return Iterator(std::end(t_)); }
- Iterator end() const { return Iterator(std::begin(t_)); }
-
- private:
- T& t_;
-
- DISALLOW_ASSIGN(ReversedAdapter);
-};
-
-// Reversed returns a container adapter usable in a range-based "for" statement
-// for iterating a reversible container in reverse order.
-//
-// Example:
-//
-// std::vector<int> v = ...;
-// for (int i : base::Reversed(v)) {
-// // iterates through v from back to front
-// }
-template <typename T>
-ReversedAdapter<T> Reversed(T&& t) {
- return ReversedAdapter<T>(t);
-}
-
-} // namespace base
-} // namespace v8
-
-#endif // V8_BASE_ADAPTERS_H_
diff --git a/deps/v8/src/base/cpu.cc b/deps/v8/src/base/cpu.cc
index 6ab0ffee29..4f4ac2b328 100644
--- a/deps/v8/src/base/cpu.cc
+++ b/deps/v8/src/base/cpu.cc
@@ -9,6 +9,7 @@
#endif
#if V8_OS_LINUX
#include <linux/auxvec.h> // AT_HWCAP
+extern "C" char** environ;
#endif
#if V8_GLIBC_PREREQ(2, 16)
#include <sys/auxv.h> // getauxval()
@@ -16,7 +17,7 @@
#if V8_OS_QNX
#include <sys/syspage.h> // cpuinfo
#endif
-#if V8_OS_LINUX && V8_HOST_ARCH_PPC
+#if (V8_OS_LINUX && V8_HOST_ARCH_PPC) || V8_OS_ANDROID
#include <elf.h>
#endif
#if V8_OS_AIX
@@ -109,28 +110,25 @@ static V8_INLINE void __cpuid(int cpu_info[4], int info_type) {
#define HWCAP_LPAE (1 << 20)
static uint32_t ReadELFHWCaps() {
- uint32_t result = 0;
#if V8_GLIBC_PREREQ(2, 16)
- result = static_cast<uint32_t>(getauxval(AT_HWCAP));
+ return static_cast<uint32_t>(getauxval(AT_HWCAP));
#else
- // Read the ELF HWCAP flags by parsing /proc/self/auxv.
- FILE* fp = fopen("/proc/self/auxv", "r");
- if (fp != nullptr) {
- struct { uint32_t tag; uint32_t value; } entry;
- for (;;) {
- size_t n = fread(&entry, sizeof(entry), 1, fp);
- if (n == 0 || (entry.tag == 0 && entry.value == 0)) {
- break;
- }
- if (entry.tag == AT_HWCAP) {
- result = entry.value;
- break;
- }
+ char** head = environ;
+ while (*head++ != nullptr) {
+ }
+#ifdef __LP64__
+ using elf_auxv_t = Elf64_auxv_t;
+#else
+ using elf_auxv_t = Elf32_auxv_t;
+#endif
+ for (elf_auxv_t* entry = reinterpret_cast<elf_auxv_t*>(head);
+ entry->a_type != AT_NULL; ++entry) {
+ if (entry->a_type == AT_HWCAP) {
+ return entry->a_un.a_val;
}
- fclose(fp);
}
+ return 0u;
#endif
- return result;
}
#endif // V8_HOST_ARCH_ARM
@@ -608,33 +606,28 @@ CPU::CPU()
#ifndef USE_SIMULATOR
#if V8_OS_LINUX
- // Read processor info from /proc/self/auxv.
char* auxv_cpu_type = nullptr;
- FILE* fp = fopen("/proc/self/auxv", "r");
- if (fp != nullptr) {
+ char** head = environ;
+ while (*head++ != nullptr) {
+ }
#if V8_TARGET_ARCH_PPC64
- Elf64_auxv_t entry;
+ using elf_auxv_t = Elf64_auxv_t;
#else
- Elf32_auxv_t entry;
+ using elf_auxv_t = Elf32_auxv_t;
#endif
- for (;;) {
- size_t n = fread(&entry, sizeof(entry), 1, fp);
- if (n == 0 || entry.a_type == AT_NULL) {
+ for (elf_auxv_t* entry = reinterpret_cast<elf_auxv_t*>(head);
+ entry->a_type != AT_NULL; ++entry) {
+ switch (entry->a_type) {
+ case AT_PLATFORM:
+ auxv_cpu_type = reinterpret_cast<char*>(entry->a_un.a_val);
+ break;
+ case AT_ICACHEBSIZE:
+ icache_line_size_ = entry->a_un.a_val;
+ break;
+ case AT_DCACHEBSIZE:
+ dcache_line_size_ = entry->a_un.a_val;
break;
- }
- switch (entry.a_type) {
- case AT_PLATFORM:
- auxv_cpu_type = reinterpret_cast<char*>(entry.a_un.a_val);
- break;
- case AT_ICACHEBSIZE:
- icache_line_size_ = entry.a_un.a_val;
- break;
- case AT_DCACHEBSIZE:
- dcache_line_size_ = entry.a_un.a_val;
- break;
- }
}
- fclose(fp);
}
part_ = -1;
diff --git a/deps/v8/src/base/file-utils.cc b/deps/v8/src/base/file-utils.cc
index 31b1b41190..6e1c492144 100644
--- a/deps/v8/src/base/file-utils.cc
+++ b/deps/v8/src/base/file-utils.cc
@@ -12,24 +12,18 @@
namespace v8 {
namespace base {
-char* RelativePath(char** buffer, const char* exec_path, const char* name) {
+std::unique_ptr<char[]> RelativePath(const char* exec_path, const char* name) {
DCHECK(exec_path);
- int path_separator = static_cast<int>(strlen(exec_path)) - 1;
- while (path_separator >= 0 &&
- !OS::isDirectorySeparator(exec_path[path_separator])) {
- path_separator--;
+ size_t basename_start = strlen(exec_path);
+ while (basename_start > 0 &&
+ !OS::isDirectorySeparator(exec_path[basename_start - 1])) {
+ --basename_start;
}
- if (path_separator >= 0) {
- int name_length = static_cast<int>(strlen(name));
- *buffer =
- reinterpret_cast<char*>(calloc(path_separator + name_length + 2, 1));
- *buffer[0] = '\0';
- strncat(*buffer, exec_path, path_separator + 1);
- strncat(*buffer, name, name_length);
- } else {
- *buffer = strdup(name);
- }
- return *buffer;
+ size_t name_length = strlen(name);
+ auto buffer = std::make_unique<char[]>(basename_start + name_length + 1);
+ if (basename_start > 0) memcpy(buffer.get(), exec_path, basename_start);
+ memcpy(buffer.get() + basename_start, name, name_length);
+ return buffer;
}
} // namespace base
diff --git a/deps/v8/src/base/file-utils.h b/deps/v8/src/base/file-utils.h
index afd9a1fc25..84b57fb40b 100644
--- a/deps/v8/src/base/file-utils.h
+++ b/deps/v8/src/base/file-utils.h
@@ -5,6 +5,8 @@
#ifndef V8_BASE_FILE_UTILS_H_
#define V8_BASE_FILE_UTILS_H_
+#include <memory>
+
#include "src/base/base-export.h"
namespace v8 {
@@ -12,8 +14,8 @@ namespace base {
// Helper functions to manipulate file paths.
-V8_BASE_EXPORT char* RelativePath(char** buffer, const char* exec_path,
- const char* name);
+V8_BASE_EXPORT
+std::unique_ptr<char[]> RelativePath(const char* exec_path, const char* name);
} // namespace base
} // namespace v8
diff --git a/deps/v8/src/base/free_deleter.h b/deps/v8/src/base/free_deleter.h
index 77e4f0ed14..a556926685 100644
--- a/deps/v8/src/base/free_deleter.h
+++ b/deps/v8/src/base/free_deleter.h
@@ -9,6 +9,7 @@
#define V8_BASE_FREE_DELETER_H_
#include <stdlib.h>
+#include <memory>
namespace v8 {
namespace base {
diff --git a/deps/v8/src/base/iterator.h b/deps/v8/src/base/iterator.h
index b081af62ae..baaf324e21 100644
--- a/deps/v8/src/base/iterator.h
+++ b/deps/v8/src/base/iterator.h
@@ -59,6 +59,26 @@ class iterator_range {
const_iterator const end_;
};
+template <typename ForwardIterator>
+auto make_iterator_range(ForwardIterator&& begin, ForwardIterator&& end) {
+ return iterator_range<ForwardIterator>{std::forward<ForwardIterator>(begin),
+ std::forward<ForwardIterator>(end)};
+}
+
+// {Reversed} returns a container adapter usable in a range-based "for"
+// statement for iterating a reversible container in reverse order.
+//
+// Example:
+//
+// std::vector<int> v = ...;
+// for (int i : base::Reversed(v)) {
+// // iterates through v from back to front
+// }
+template <typename T>
+auto Reversed(T& t) { // NOLINT(runtime/references): match {rbegin} and {rend}
+ return make_iterator_range(std::rbegin(t), std::rend(t));
+}
+
} // namespace base
} // namespace v8
diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h
index ad70e9820d..72ef64cfbe 100644
--- a/deps/v8/src/base/macros.h
+++ b/deps/v8/src/base/macros.h
@@ -232,35 +232,16 @@ struct is_trivially_copyable {
// the standard does not, so let's skip this check.)
// Trivial non-deleted destructor.
std::is_trivially_destructible<T>::value;
-
-#elif defined(__GNUC__) && __GNUC__ < 5
- // WARNING:
- // On older libstdc++ versions, there is no way to correctly implement
- // is_trivially_copyable. The workaround below is an approximation (neither
- // over- nor underapproximation). E.g. it wrongly returns true if the move
- // constructor is non-trivial, and it wrongly returns false if the copy
- // constructor is deleted, but copy assignment is trivial.
- // TODO(rongjie) Remove this workaround once we require gcc >= 5.0
- static constexpr bool value =
- __has_trivial_copy(T) && __has_trivial_destructor(T);
-
#else
static constexpr bool value = std::is_trivially_copyable<T>::value;
#endif
};
-#if defined(__GNUC__) && __GNUC__ < 5
-// On older libstdc++ versions, base::is_trivially_copyable<T>::value is only an
-// approximation (see above), so make ASSERT_{NOT_,}TRIVIALLY_COPYABLE a noop.
-#define ASSERT_TRIVIALLY_COPYABLE(T) static_assert(true, "check disabled")
-#define ASSERT_NOT_TRIVIALLY_COPYABLE(T) static_assert(true, "check disabled")
-#else
#define ASSERT_TRIVIALLY_COPYABLE(T) \
static_assert(::v8::base::is_trivially_copyable<T>::value, \
#T " should be trivially copyable")
#define ASSERT_NOT_TRIVIALLY_COPYABLE(T) \
static_assert(!::v8::base::is_trivially_copyable<T>::value, \
#T " should not be trivially copyable")
-#endif
// The USE(x, ...) template is used to silence C++ compiler warnings
// issued for (yet) unused variables (typically parameters).
@@ -407,6 +388,9 @@ bool is_inbounds(float_t v) {
constexpr bool kUpperBoundIsMax =
static_cast<biggest_int_t>(kUpperBound) ==
static_cast<biggest_int_t>(std::numeric_limits<int_t>::max());
+ // Using USE(var) is only a workaround for a GCC 8.1 bug.
+ USE(kLowerBoundIsMin);
+ USE(kUpperBoundIsMax);
return (kLowerBoundIsMin ? (kLowerBound <= v) : (kLowerBound < v)) &&
(kUpperBoundIsMax ? (v <= kUpperBound) : (v < kUpperBound));
}
diff --git a/deps/v8/src/base/optional.h b/deps/v8/src/base/optional.h
index b8df88d844..6610c7ffc3 100644
--- a/deps/v8/src/base/optional.h
+++ b/deps/v8/src/base/optional.h
@@ -131,21 +131,8 @@ struct OptionalStorageBase<T, true /* trivially destructible */> {
// the condition of constexpr-ness is satisfied because the base class also has
// compiler generated constexpr {copy,move} constructors). Note that
// placement-new is prohibited in constexpr.
-#if defined(__GNUC__) && __GNUC__ < 5
-// gcc <5 does not implement std::is_trivially_copy_constructible.
-// Conservatively assume false for this configuration.
-// TODO(clemensh): Remove this once we drop support for gcc <5.
-#define TRIVIALLY_COPY_CONSTRUCTIBLE(T) false
-#define TRIVIALLY_MOVE_CONSTRUCTIBLE(T) false
-#else
-#define TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- std::is_trivially_copy_constructible<T>::value
-#define TRIVIALLY_MOVE_CONSTRUCTIBLE(T) \
- std::is_trivially_move_constructible<T>::value
-#endif
-template <typename T, bool = TRIVIALLY_COPY_CONSTRUCTIBLE(T),
- bool = TRIVIALLY_MOVE_CONSTRUCTIBLE(T)>
-#undef TRIVIALLY_COPY_CONSTRUCTIBLE
+template <typename T, bool = std::is_trivially_copy_constructible<T>::value,
+ bool = std::is_trivially_move_constructible<T>::value>
struct OptionalStorage : OptionalStorageBase<T> {
// This is no trivially {copy,move} constructible case. Other cases are
// defined below as specializations.
diff --git a/deps/v8/src/base/platform/mutex.h b/deps/v8/src/base/platform/mutex.h
index c48cf8d339..5b3b31ec1e 100644
--- a/deps/v8/src/base/platform/mutex.h
+++ b/deps/v8/src/base/platform/mutex.h
@@ -290,6 +290,7 @@ class LockGuard final {
};
using MutexGuard = LockGuard<Mutex>;
+using RecursiveMutexGuard = LockGuard<RecursiveMutex>;
enum MutexSharedType : bool { kShared = true, kExclusive = false };
diff --git a/deps/v8/src/base/platform/platform-openbsd.cc b/deps/v8/src/base/platform/platform-openbsd.cc
index c133ffb68d..e4a3cb6f35 100644
--- a/deps/v8/src/base/platform/platform-openbsd.cc
+++ b/deps/v8/src/base/platform/platform-openbsd.cc
@@ -107,7 +107,7 @@ void OS::SignalCodeMovingGC() {
// it. This injects a GC marker into the stream of events generated
// by the kernel and allows us to synchronize V8 code log and the
// kernel log.
- int size = sysconf(_SC_PAGESIZE);
+ long size = sysconf(_SC_PAGESIZE); // NOLINT: type more fit than uint64_t
FILE* f = fopen(OS::GetGCFakeMMapFile(), "w+");
if (f == nullptr) {
OS::PrintError("Failed to open %s\n", OS::GetGCFakeMMapFile());
@@ -116,7 +116,7 @@ void OS::SignalCodeMovingGC() {
void* addr =
mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0);
DCHECK(addr != MAP_FAILED);
- OS::Free(addr, size);
+ CHECK(OS::Free(addr, size));
fclose(f);
}
diff --git a/deps/v8/src/base/platform/platform-posix.cc b/deps/v8/src/base/platform/platform-posix.cc
index c50cdd7a98..99abcd5568 100644
--- a/deps/v8/src/base/platform/platform-posix.cc
+++ b/deps/v8/src/base/platform/platform-posix.cc
@@ -48,6 +48,7 @@
#if V8_OS_MACOSX
#include <dlfcn.h>
+#include <mach/mach.h>
#endif
#if V8_OS_LINUX
diff --git a/deps/v8/src/base/platform/semaphore.cc b/deps/v8/src/base/platform/semaphore.cc
index a7e50f5880..66464d8258 100644
--- a/deps/v8/src/base/platform/semaphore.cc
+++ b/deps/v8/src/base/platform/semaphore.cc
@@ -5,8 +5,7 @@
#include "src/base/platform/semaphore.h"
#if V8_OS_MACOSX
-#include <mach/mach_init.h>
-#include <mach/task.h>
+#include <dispatch/dispatch.h>
#endif
#include <errno.h>
@@ -21,53 +20,23 @@ namespace base {
#if V8_OS_MACOSX
Semaphore::Semaphore(int count) {
- kern_return_t result = semaphore_create(
- mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count);
- DCHECK_EQ(KERN_SUCCESS, result);
- USE(result);
+ native_handle_ = dispatch_semaphore_create(count);
+ DCHECK(native_handle_);
}
+Semaphore::~Semaphore() { dispatch_release(native_handle_); }
-Semaphore::~Semaphore() {
- kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
- DCHECK_EQ(KERN_SUCCESS, result);
- USE(result);
-}
-
-void Semaphore::Signal() {
- kern_return_t result = semaphore_signal(native_handle_);
- DCHECK_EQ(KERN_SUCCESS, result);
- USE(result);
-}
-
+void Semaphore::Signal() { dispatch_semaphore_signal(native_handle_); }
void Semaphore::Wait() {
- while (true) {
- kern_return_t result = semaphore_wait(native_handle_);
- if (result == KERN_SUCCESS) return; // Semaphore was signalled.
- DCHECK_EQ(KERN_ABORTED, result);
- }
+ dispatch_semaphore_wait(native_handle_, DISPATCH_TIME_FOREVER);
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
- TimeTicks now = TimeTicks::Now();
- TimeTicks end = now + rel_time;
- while (true) {
- mach_timespec_t ts;
- if (now >= end) {
- // Return immediately if semaphore was not signalled.
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- } else {
- ts = (end - now).ToMachTimespec();
- }
- kern_return_t result = semaphore_timedwait(native_handle_, ts);
- if (result == KERN_SUCCESS) return true; // Semaphore was signalled.
- if (result == KERN_OPERATION_TIMED_OUT) return false; // Timeout.
- DCHECK_EQ(KERN_ABORTED, result);
- now = TimeTicks::Now();
- }
+ dispatch_time_t timeout =
+ dispatch_time(DISPATCH_TIME_NOW, rel_time.InNanoseconds());
+ return dispatch_semaphore_wait(native_handle_, timeout) == 0;
}
#elif V8_OS_POSIX
diff --git a/deps/v8/src/base/platform/semaphore.h b/deps/v8/src/base/platform/semaphore.h
index 11ff0b9199..c4937acadd 100644
--- a/deps/v8/src/base/platform/semaphore.h
+++ b/deps/v8/src/base/platform/semaphore.h
@@ -12,7 +12,7 @@
#endif
#if V8_OS_MACOSX
-#include <mach/semaphore.h> // NOLINT
+#include <dispatch/dispatch.h> // NOLINT
#elif V8_OS_POSIX
#include <semaphore.h> // NOLINT
#endif
@@ -50,7 +50,7 @@ class V8_BASE_EXPORT Semaphore final {
bool WaitFor(const TimeDelta& rel_time) V8_WARN_UNUSED_RESULT;
#if V8_OS_MACOSX
- using NativeHandle = semaphore_t;
+ using NativeHandle = dispatch_semaphore_t;
#elif V8_OS_POSIX
using NativeHandle = sem_t;
#elif V8_OS_WIN
diff --git a/deps/v8/src/base/template-utils.h b/deps/v8/src/base/template-utils.h
index 530114a8e2..146f8d6e6a 100644
--- a/deps/v8/src/base/template-utils.h
+++ b/deps/v8/src/base/template-utils.h
@@ -6,32 +6,20 @@
#define V8_BASE_TEMPLATE_UTILS_H_
#include <array>
-#include <memory>
+#include <type_traits>
+#include <utility>
namespace v8 {
namespace base {
namespace detail {
-// make_array_helper statically iteratively creates the index list 0 .. Size-1.
-// A specialization for the base case (first index is 0) finally constructs the
-// array.
-// TODO(clemensh): Use std::index_sequence once we have C++14 support.
-template <class Function, std::size_t... Indexes>
-struct make_array_helper;
-
-template <class Function, std::size_t... Indexes>
-struct make_array_helper<Function, 0, Indexes...> {
- constexpr static std::array<typename std::result_of<Function(size_t)>::type,
- sizeof...(Indexes) + 1>
- make_array(Function f) {
- return {{f(0), f(Indexes)...}};
- }
-};
-
-template <class Function, std::size_t FirstIndex, std::size_t... Indexes>
-struct make_array_helper<Function, FirstIndex, Indexes...>
- : make_array_helper<Function, FirstIndex - 1, FirstIndex, Indexes...> {};
+template <typename Function, std::size_t... Indexes>
+constexpr inline auto make_array_helper(Function f,
+ std::index_sequence<Indexes...>)
+ -> std::array<decltype(f(0)), sizeof...(Indexes)> {
+ return {{f(Indexes)...}};
+}
} // namespace detail
@@ -42,18 +30,8 @@ struct make_array_helper<Function, FirstIndex, Indexes...>
// [](std::size_t i) { return static_cast<int>(2 * i); });
// The resulting array will be constexpr if the passed function is constexpr.
template <std::size_t Size, class Function>
-constexpr std::array<typename std::result_of<Function(size_t)>::type, Size>
-make_array(Function f) {
- static_assert(Size > 0, "Can only create non-empty arrays");
- return detail::make_array_helper<Function, Size - 1>::make_array(f);
-}
-
-// base::make_unique<T>: Construct an object of type T and wrap it in a
-// std::unique_ptr.
-// Replacement for C++14's std::make_unique.
-template <typename T, typename... Args>
-std::unique_ptr<T> make_unique(Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+constexpr auto make_array(Function f) {
+ return detail::make_array_helper(f, std::make_index_sequence<Size>{});
}
// Helper to determine how to pass values: Pass scalars and arrays by value,
@@ -80,38 +58,17 @@ struct has_output_operator<T, decltype(void(std::declval<std::ostream&>()
<< std::declval<T>()))>
: std::true_type {};
-namespace detail {
-
-template <typename Func, typename T, typename... Ts>
-struct fold_helper {
- static_assert(sizeof...(Ts) == 0, "this is the base case");
- using result_t = typename std::remove_reference<T>::type;
- static constexpr T&& fold(Func func, T&& first) {
- return std::forward<T>(first);
- }
-};
+// Fold all arguments from left to right with a given function.
+template <typename Func, typename T>
+constexpr auto fold(Func func, T&& t) {
+ return std::forward<T>(t);
+}
template <typename Func, typename T1, typename T2, typename... Ts>
-struct fold_helper<Func, T1, T2, Ts...> {
- using folded_t = typename std::result_of<Func(T1, T2)>::type;
- using next_fold_helper = fold_helper<Func, folded_t&&, Ts...>;
- using result_t = typename next_fold_helper::result_t;
- static constexpr result_t fold(Func func, T1&& first, T2&& second,
- Ts&&... more) {
- return next_fold_helper::fold(
- func, func(std::forward<T1>(first), std::forward<T2>(second)),
- std::forward<Ts>(more)...);
- }
-};
-
-} // namespace detail
-
-// Fold all arguments from left to right with a given function.
-template <typename Func, typename... Ts>
-constexpr auto fold(Func func, Ts&&... more) ->
- typename detail::fold_helper<Func, Ts...>::result_t {
- return detail::fold_helper<Func, Ts...>::fold(func,
- std::forward<Ts>(more)...);
+constexpr auto fold(Func func, T1&& first, T2&& second, Ts&&... more) {
+ auto&& folded = func(std::forward<T1>(first), std::forward<T2>(second));
+ return fold(std::move(func), std::forward<decltype(folded)>(folded),
+ std::forward<Ts>(more)...);
}
// {is_same<Ts...>::value} is true if all Ts are the same, false otherwise.
diff --git a/deps/v8/src/base/ubsan.cc b/deps/v8/src/base/ubsan.cc
new file mode 100644
index 0000000000..fc77156eb1
--- /dev/null
+++ b/deps/v8/src/base/ubsan.cc
@@ -0,0 +1,50 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <limits>
+
+#include "src/base/build_config.h"
+
+#if !defined(UNDEFINED_SANITIZER) || !defined(V8_TARGET_ARCH_32_BIT)
+#error "This file is only needed for 32-bit UBSan builds."
+#endif
+
+// Compiling with -fsanitize=undefined on 32-bit platforms requires __mulodi4
+// to be available. Usually it comes from libcompiler_rt, which our build
+// doesn't provide, so here is a custom implementation (inspired by digit_mul
+// in src/objects/bigint.cc).
+extern "C" int64_t __mulodi4(int64_t a, int64_t b, int* overflow) {
+ // Multiply in 32-bit chunks.
+ // For inputs [AH AL]*[BH BL], the result is:
+ //
+ // [AL*BL] // r_low
+ // + [AL*BH] // r_mid1
+ // + [AH*BL] // r_mid2
+ // + [AH*BH] // r_high
+ // = [R4 R3 R2 R1] // high = [R4 R3], low = [R2 R1]
+ //
+ // Where of course we must be careful with carries between the columns.
+ uint64_t a_low = a & 0xFFFFFFFFu;
+ uint64_t a_high = static_cast<uint64_t>(a) >> 32;
+ uint64_t b_low = b & 0xFFFFFFFFu;
+ uint64_t b_high = static_cast<uint64_t>(b) >> 32;
+
+ uint64_t r_low = a_low * b_low;
+ uint64_t r_mid1 = a_low * b_high;
+ uint64_t r_mid2 = a_high * b_low;
+ uint64_t r_high = a_high * b_high;
+
+ uint64_t result1 = r_low + (r_mid1 << 32);
+ if (result1 < r_low) r_high++;
+ uint64_t result2 = result1 + (r_mid2 << 32);
+ if (result2 < result1) r_high++;
+ r_high += (r_mid1 >> 32) + (r_mid2 >> 32);
+ int64_t result = static_cast<int64_t>(result2);
+ uint64_t result_sign = (result >> 63);
+ uint64_t expected_result_sign = (a >> 63) ^ (b >> 63);
+
+ *overflow = (r_high > 0 || result_sign != expected_result_sign) ? 1 : 0;
+ return result;
+}