[iwyu] Extract src/memcopy.h from src/utils.h

This CL moves a number of memory-related methods out of utils into its
own header, since utils.h is included in many places that do not need
these methods.

R=clemensh@chromium.org,mstarzinger@chromium.org

Change-Id: I5155baf329844784286413408c05c7108b789020
Reviewed-on: https://chromium-review.googlesource.com/c/1354889
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57948}
This commit is contained in:
Ben L. Titzer 2018-11-29 17:59:26 +01:00 committed by Commit Bot
parent 3d2bc5d041
commit cb242eded6
16 changed files with 588 additions and 566 deletions

View File

@ -2252,6 +2252,8 @@ v8_source_set("v8_base") {
"src/math-random.h",
"src/maybe-handles-inl.h",
"src/maybe-handles.h",
"src/memcopy.cc",
"src/memcopy.h",
"src/message-template.h",
"src/messages.cc",
"src/messages.h",

View File

@ -11,8 +11,9 @@
#include "src/base/lsan-page-allocator.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h"
#include "src/utils.h"
#include "src/memcopy.h"
#include "src/v8.h"
#include "src/vector.h"
#if V8_LIBC_BIONIC
#include <malloc.h> // NOLINT

View File

@ -35,7 +35,6 @@
#include "src/globals.h"
#include "src/heap/factory.h"
#include "src/isolate.h"
#include "src/utils.h"
// Ast(Raw|Cons)String and AstValueFactory are for storing strings and
// values independent of the V8 heap and internalizing them later. During

View File

@ -20,9 +20,9 @@
#include "src/lsan.h"
#include "src/machine-type.h"
#include "src/macro-assembler.h"
#include "src/memcopy.h"
#include "src/objects-inl.h"
#include "src/objects/smi.h"
#include "src/utils.h"
#include "src/zone/zone.h"
namespace v8 {

View File

@ -13,8 +13,8 @@
#include "src/assembler.h"
#include "src/base/functional.h"
#include "src/base/platform/platform.h"
#include "src/memcopy.h"
#include "src/ostreams.h"
#include "src/utils.h"
#include "src/wasm/wasm-limits.h"
namespace v8 {

View File

@ -15,13 +15,13 @@
#include "src/heap/heap-inl.h"
#include "src/heap/mark-compact.h"
#include "src/isolate.h"
#include "src/memcopy.h"
#include "src/objects/compilation-cache-inl.h"
#include "src/objects/heap-object.h"
#include "src/objects/js-collection-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/slots.h"
#include "src/objects/templates.h"
#include "src/utils.h"
namespace v8 {
namespace internal {

View File

@ -21,6 +21,7 @@
#include "src/libsampler/sampler.h"
#include "src/log-inl.h"
#include "src/macro-assembler.h"
#include "src/memcopy.h"
#include "src/objects/api-callbacks.h"
#include "src/perf-jit.h"
#include "src/profiler/tick-sample.h"
@ -34,7 +35,6 @@
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/utils.h"
#include "src/version.h"
namespace v8 {

74
src/memcopy.cc Normal file
View File

@ -0,0 +1,74 @@
// Copyright 2018 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 "src/memcopy.h"
namespace v8 {
namespace internal {
#if V8_TARGET_ARCH_IA32
static void MemMoveWrapper(void* dest, const void* src, size_t size) {
memmove(dest, src, size);
}
// Initialize to library version so we can call this at any time during startup.
static MemMoveFunction memmove_function = &MemMoveWrapper;
// Defined in codegen-ia32.cc.
MemMoveFunction CreateMemMoveFunction();
// Copy memory area to disjoint memory area.
V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size) {
if (size == 0) return;
// Note: here we rely on dependent reads being ordered. This is true
// on all architectures we currently support.
(*memmove_function)(dest, src, size);
}
#elif V8_OS_POSIX && V8_HOST_ARCH_ARM
void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
size_t chars) {
uint16_t* limit = dest + chars;
while (dest < limit) {
*dest++ = static_cast<uint16_t>(*src++);
}
}
V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
&MemCopyUint8Wrapper;
MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
&MemCopyUint16Uint8Wrapper;
// Defined in codegen-arm.cc.
MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
MemCopyUint16Uint8Function stub);
#elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
&MemCopyUint8Wrapper;
// Defined in codegen-mips.cc.
MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
#endif
static bool g_memcopy_functions_initialized = false;
void init_memcopy_functions() {
if (g_memcopy_functions_initialized) return;
g_memcopy_functions_initialized = true;
#if V8_TARGET_ARCH_IA32
MemMoveFunction generated_memmove = CreateMemMoveFunction();
if (generated_memmove != nullptr) {
memmove_function = generated_memmove;
}
#elif V8_OS_POSIX && V8_HOST_ARCH_ARM
memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
memcopy_uint16_uint8_function =
CreateMemCopyUint16Uint8Function(&MemCopyUint16Uint8Wrapper);
#elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
#endif
}
} // namespace internal
} // namespace v8

497
src/memcopy.h Normal file
View File

@ -0,0 +1,497 @@
// Copyright 2018 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.
#ifndef V8_MEMCOPY_H_
#define V8_MEMCOPY_H_
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "src/base/logging.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
typedef uintptr_t Address;
// ----------------------------------------------------------------------------
// Generated memcpy/memmove
// Initializes the codegen support that depends on CPU features.
void init_memcopy_functions();
#if defined(V8_TARGET_ARCH_IA32)
// Limit below which the extra overhead of the MemCopy function is likely
// to outweigh the benefits of faster copying.
const int kMinComplexMemCopy = 64;
// Copy memory area. No restrictions.
V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size);
typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
// Keep the distinction of "move" vs. "copy" for the benefit of other
// architectures.
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
MemMove(dest, src, size);
}
#elif defined(V8_HOST_ARCH_ARM)
typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
size_t size);
V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
size_t chars) {
memcpy(dest, src, chars);
}
// For values < 16, the assembler function is slower than the inlined C code.
const int kMinComplexMemCopy = 16;
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
(*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src), size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
size_t size);
extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
size_t chars);
// For values < 12, the assembler function is slower than the inlined C code.
const int kMinComplexConvertMemCopy = 12;
V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
size_t size) {
(*memcopy_uint16_uint8_function)(dest, src, size);
}
#elif defined(V8_HOST_ARCH_MIPS)
typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
size_t size);
V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
size_t chars) {
memcpy(dest, src, chars);
}
// For values < 16, the assembler function is slower than the inlined C code.
const int kMinComplexMemCopy = 16;
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
(*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src), size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
#else
// Copy memory area to disjoint memory area.
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
memcpy(dest, src, size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
const int kMinComplexMemCopy = 8;
#endif // V8_TARGET_ARCH_IA32
// Copies words from |src| to |dst|. The data spans must not overlap.
// |src| and |dst| must be kPointerSize-aligned.
inline void CopyWords(Address dst, const Address src, size_t num_words) {
constexpr int kPointerSize = sizeof(void*); // to avoid src/globals.h
DCHECK(IsAligned(dst, kPointerSize));
DCHECK(IsAligned(src, kPointerSize));
DCHECK(((src <= dst) && ((src + num_words * kPointerSize) <= dst)) ||
((dst <= src) && ((dst + num_words * kPointerSize) <= src)));
// Use block copying MemCopy if the segment we're copying is
// enough to justify the extra call/setup overhead.
static const size_t kBlockCopyLimit = 16;
Address* dst_ptr = reinterpret_cast<Address*>(dst);
Address* src_ptr = reinterpret_cast<Address*>(src);
if (num_words < kBlockCopyLimit) {
do {
num_words--;
*dst_ptr++ = *src_ptr++;
} while (num_words > 0);
} else {
MemCopy(dst_ptr, src_ptr, num_words * kPointerSize);
}
}
// Copies data from |src| to |dst|. The data spans must not overlap.
template <typename T>
inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
STATIC_ASSERT(sizeof(T) == 1);
DCHECK(((src <= dst) && ((src + num_bytes) <= dst)) ||
((dst <= src) && ((dst + num_bytes) <= src)));
if (num_bytes == 0) return;
// Use block copying MemCopy if the segment we're copying is
// enough to justify the extra call/setup overhead.
static const int kBlockCopyLimit = kMinComplexMemCopy;
if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
do {
num_bytes--;
*dst++ = *src++;
} while (num_bytes > 0);
} else {
MemCopy(dst, src, num_bytes);
}
}
inline void MemsetPointer(Address* dest, Address value, size_t counter) {
#if V8_HOST_ARCH_IA32
#define STOS "stosl"
#elif V8_HOST_ARCH_X64
#if V8_HOST_ARCH_32_BIT
#define STOS "addr32 stosl"
#else
#define STOS "stosq"
#endif
#endif
#if defined(MEMORY_SANITIZER)
// MemorySanitizer does not understand inline assembly.
#undef STOS
#endif
#if defined(__GNUC__) && defined(STOS)
asm volatile(
"cld;"
"rep ; " STOS
: "+&c"(counter), "+&D"(dest)
: "a"(value)
: "memory", "cc");
#else
for (size_t i = 0; i < counter; i++) {
dest[i] = value;
}
#endif
#undef STOS
}
template <typename T, typename U>
inline void MemsetPointer(T** dest, U* value, size_t counter) {
#ifdef DEBUG
T* a = nullptr;
U* b = nullptr;
a = b; // Fake assignment to check assignability.
USE(a);
#endif // DEBUG
MemsetPointer(reinterpret_cast<Address*>(dest),
reinterpret_cast<Address>(value), counter);
}
template <typename sourcechar, typename sinkchar>
V8_INLINE static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
size_t chars);
#if defined(V8_HOST_ARCH_ARM)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#elif defined(V8_HOST_ARCH_MIPS)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#endif
// Copy from 8bit/16bit chars to 8bit/16bit chars.
template <typename sourcechar, typename sinkchar>
V8_INLINE void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars);
template <typename sourcechar, typename sinkchar>
void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
DCHECK_LE(sizeof(sourcechar), 2);
DCHECK_LE(sizeof(sinkchar), 2);
if (sizeof(sinkchar) == 1) {
if (sizeof(sourcechar) == 1) {
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src), chars);
} else {
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint16_t*>(src), chars);
}
} else {
if (sizeof(sourcechar) == 1) {
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
reinterpret_cast<const uint8_t*>(src), chars);
} else {
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
reinterpret_cast<const uint16_t*>(src), chars);
}
}
}
template <typename sourcechar, typename sinkchar>
void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
sinkchar* limit = dest + chars;
if ((sizeof(*dest) == sizeof(*src)) &&
(chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
MemCopy(dest, src, chars * sizeof(*dest));
} else {
while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
}
}
#if defined(V8_HOST_ARCH_ARM)
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
case 2:
memcpy(dest, src, 2);
break;
case 3:
memcpy(dest, src, 3);
break;
case 4:
memcpy(dest, src, 4);
break;
case 5:
memcpy(dest, src, 5);
break;
case 6:
memcpy(dest, src, 6);
break;
case 7:
memcpy(dest, src, 7);
break;
case 8:
memcpy(dest, src, 8);
break;
case 9:
memcpy(dest, src, 9);
break;
case 10:
memcpy(dest, src, 10);
break;
case 11:
memcpy(dest, src, 11);
break;
case 12:
memcpy(dest, src, 12);
break;
case 13:
memcpy(dest, src, 13);
break;
case 14:
memcpy(dest, src, 14);
break;
case 15:
memcpy(dest, src, 15);
break;
default:
MemCopy(dest, src, chars);
break;
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
MemCopyUint16Uint8(dest, src, chars);
} else {
MemCopyUint16Uint8Wrapper(dest, src, chars);
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
case 2:
memcpy(dest, src, 4);
break;
case 3:
memcpy(dest, src, 6);
break;
case 4:
memcpy(dest, src, 8);
break;
case 5:
memcpy(dest, src, 10);
break;
case 6:
memcpy(dest, src, 12);
break;
case 7:
memcpy(dest, src, 14);
break;
default:
MemCopy(dest, src, chars * sizeof(*dest));
break;
}
}
#elif defined(V8_HOST_ARCH_MIPS)
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
if (chars < kMinComplexMemCopy) {
memcpy(dest, src, chars);
} else {
MemCopy(dest, src, chars);
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
if (chars < kMinComplexMemCopy) {
memcpy(dest, src, chars * sizeof(*dest));
} else {
MemCopy(dest, src, chars * sizeof(*dest));
}
}
#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
#define CASE(n) \
case n: \
memcpy(dest, src, n); \
break
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
CASE(2);
CASE(3);
CASE(4);
CASE(5);
CASE(6);
CASE(7);
CASE(8);
CASE(9);
CASE(10);
CASE(11);
CASE(12);
CASE(13);
CASE(14);
CASE(15);
CASE(16);
CASE(17);
CASE(18);
CASE(19);
CASE(20);
CASE(21);
CASE(22);
CASE(23);
CASE(24);
CASE(25);
CASE(26);
CASE(27);
CASE(28);
CASE(29);
CASE(30);
CASE(31);
CASE(32);
CASE(33);
CASE(34);
CASE(35);
CASE(36);
CASE(37);
CASE(38);
CASE(39);
CASE(40);
CASE(41);
CASE(42);
CASE(43);
CASE(44);
CASE(45);
CASE(46);
CASE(47);
CASE(48);
CASE(49);
CASE(50);
CASE(51);
CASE(52);
CASE(53);
CASE(54);
CASE(55);
CASE(56);
CASE(57);
CASE(58);
CASE(59);
CASE(60);
CASE(61);
CASE(62);
CASE(63);
CASE(64);
default:
memcpy(dest, src, chars);
break;
}
}
#undef CASE
#define CASE(n) \
case n: \
memcpy(dest, src, n * 2); \
break
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
CASE(2);
CASE(3);
CASE(4);
CASE(5);
CASE(6);
CASE(7);
CASE(8);
CASE(9);
CASE(10);
CASE(11);
CASE(12);
CASE(13);
CASE(14);
CASE(15);
CASE(16);
CASE(17);
CASE(18);
CASE(19);
CASE(20);
CASE(21);
CASE(22);
CASE(23);
CASE(24);
CASE(25);
CASE(26);
CASE(27);
CASE(28);
CASE(29);
CASE(30);
CASE(31);
CASE(32);
default:
memcpy(dest, src, chars * 2);
break;
}
}
#undef CASE
#endif
} // namespace internal
} // namespace v8
#endif // V8_MEMCOPY_H_

View File

@ -8,6 +8,7 @@
#include "src/objects/slots.h"
#include "src/base/atomic-utils.h"
#include "src/memcopy.h"
#include "src/objects.h"
#include "src/objects/heap-object.h"
#include "src/objects/maybe-object.h"
@ -88,6 +89,10 @@ void HeapObjectSlot::store(HeapObjectReference value) const {
*location() = value.ptr();
}
inline void MemsetPointer(ObjectSlot start, Object* value, size_t counter) {
MemsetPointer(start.location(), reinterpret_cast<Address>(value), counter);
}
} // namespace internal
} // namespace v8

View File

@ -7,7 +7,6 @@
#include "src/allocation.h"
#include "src/assert-scope.h"
#include "src/utils.h"
#include "src/v8memory.h"
#include "src/zone/zone-chunk-list.h"
#include "src/zone/zone.h"

View File

@ -8,8 +8,8 @@
#include <sys/types.h>
#include <algorithm>
#include "src/globals.h"
#include "src/memcopy.h"
#include "src/unicode.h"
#include "src/utils.h"
#include "src/vector.h"
namespace unibrow {

View File

@ -11,6 +11,7 @@
#include "src/base/functional.h"
#include "src/base/logging.h"
#include "src/base/platform/platform.h"
#include "src/memcopy.h"
namespace v8 {
namespace internal {
@ -335,71 +336,6 @@ void StringBuilder::AddFormattedList(const char* format, va_list list) {
}
}
#if V8_TARGET_ARCH_IA32
static void MemMoveWrapper(void* dest, const void* src, size_t size) {
memmove(dest, src, size);
}
// Initialize to library version so we can call this at any time during startup.
static MemMoveFunction memmove_function = &MemMoveWrapper;
// Defined in codegen-ia32.cc.
MemMoveFunction CreateMemMoveFunction();
// Copy memory area to disjoint memory area.
void MemMove(void* dest, const void* src, size_t size) {
if (size == 0) return;
// Note: here we rely on dependent reads being ordered. This is true
// on all architectures we currently support.
(*memmove_function)(dest, src, size);
}
#elif V8_OS_POSIX && V8_HOST_ARCH_ARM
void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
size_t chars) {
uint16_t* limit = dest + chars;
while (dest < limit) {
*dest++ = static_cast<uint16_t>(*src++);
}
}
V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
&MemCopyUint8Wrapper;
MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
&MemCopyUint16Uint8Wrapper;
// Defined in codegen-arm.cc.
MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
MemCopyUint16Uint8Function stub);
#elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
&MemCopyUint8Wrapper;
// Defined in codegen-mips.cc.
MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
#endif
static bool g_memcopy_functions_initialized = false;
void init_memcopy_functions() {
if (g_memcopy_functions_initialized) return;
g_memcopy_functions_initialized = true;
#if V8_TARGET_ARCH_IA32
MemMoveFunction generated_memmove = CreateMemMoveFunction();
if (generated_memmove != nullptr) {
memmove_function = generated_memmove;
}
#elif V8_OS_POSIX && V8_HOST_ARCH_ARM
memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
memcopy_uint16_uint8_function =
CreateMemCopyUint16Uint8Function(&MemCopyUint16Uint8Wrapper);
#elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
#endif
}
// Returns false iff d is NaN, +0, or -0.
bool DoubleToBoolean(double d) {
IeeeDoubleArchType u;

View File

@ -1,4 +1,3 @@
// Copyright 2012 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.
@ -517,87 +516,6 @@ inline uint32_t ComputeAddressHash(Address address) {
return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
}
// ----------------------------------------------------------------------------
// Generated memcpy/memmove
// Initializes the codegen support that depends on CPU features.
void init_memcopy_functions();
#if defined(V8_TARGET_ARCH_IA32)
// Limit below which the extra overhead of the MemCopy function is likely
// to outweigh the benefits of faster copying.
const int kMinComplexMemCopy = 64;
// Copy memory area. No restrictions.
V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size);
typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
// Keep the distinction of "move" vs. "copy" for the benefit of other
// architectures.
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
MemMove(dest, src, size);
}
#elif defined(V8_HOST_ARCH_ARM)
typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
size_t size);
V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
size_t chars) {
memcpy(dest, src, chars);
}
// For values < 16, the assembler function is slower than the inlined C code.
const int kMinComplexMemCopy = 16;
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
(*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src), size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
size_t size);
extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
size_t chars);
// For values < 12, the assembler function is slower than the inlined C code.
const int kMinComplexConvertMemCopy = 12;
V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
size_t size) {
(*memcopy_uint16_uint8_function)(dest, src, size);
}
#elif defined(V8_HOST_ARCH_MIPS)
typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
size_t size);
V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
size_t chars) {
memcpy(dest, src, chars);
}
// For values < 16, the assembler function is slower than the inlined C code.
const int kMinComplexMemCopy = 16;
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
(*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src), size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
#else
// Copy memory area to disjoint memory area.
V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
memcpy(dest, src, size);
}
V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
size_t size) {
memmove(dest, src, size);
}
const int kMinComplexMemCopy = 8;
#endif // V8_TARGET_ARCH_IA32
// ----------------------------------------------------------------------------
// Miscellaneous
@ -1132,421 +1050,12 @@ int WriteAsCFile(const char* filename, const char* varname,
const char* str, int size, bool verbose = true);
// ----------------------------------------------------------------------------
// Memory
// Copies words from |src| to |dst|. The data spans must not overlap.
// |src| and |dst| must be kPointerSize-aligned.
inline void CopyWords(Address dst, const Address src, size_t num_words) {
DCHECK(IsAligned(dst, kPointerSize));
DCHECK(IsAligned(src, kPointerSize));
DCHECK(Min(dst, src) + num_words * kPointerSize <= Max(dst, src));
DCHECK_GT(num_words, 0);
// Use block copying MemCopy if the segment we're copying is
// enough to justify the extra call/setup overhead.
static const size_t kBlockCopyLimit = 16;
Address* dst_ptr = reinterpret_cast<Address*>(dst);
Address* src_ptr = reinterpret_cast<Address*>(src);
if (num_words < kBlockCopyLimit) {
do {
num_words--;
*dst_ptr++ = *src_ptr++;
} while (num_words > 0);
} else {
MemCopy(dst_ptr, src_ptr, num_words * kPointerSize);
}
}
// Copies data from |src| to |dst|. The data spans must not overlap.
template <typename T>
inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
STATIC_ASSERT(sizeof(T) == 1);
DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
Max(dst, const_cast<T*>(src)));
if (num_bytes == 0) return;
// Use block copying MemCopy if the segment we're copying is
// enough to justify the extra call/setup overhead.
static const int kBlockCopyLimit = kMinComplexMemCopy;
if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
do {
num_bytes--;
*dst++ = *src++;
} while (num_bytes > 0);
} else {
MemCopy(dst, src, num_bytes);
}
}
inline void MemsetPointer(Address* dest, Address value, size_t counter) {
#if V8_HOST_ARCH_IA32
#define STOS "stosl"
#elif V8_HOST_ARCH_X64
#if V8_HOST_ARCH_32_BIT
#define STOS "addr32 stosl"
#else
#define STOS "stosq"
#endif
#endif
#if defined(MEMORY_SANITIZER)
// MemorySanitizer does not understand inline assembly.
#undef STOS
#endif
#if defined(__GNUC__) && defined(STOS)
asm volatile(
"cld;"
"rep ; " STOS
: "+&c" (counter), "+&D" (dest)
: "a" (value)
: "memory", "cc");
#else
for (size_t i = 0; i < counter; i++) {
dest[i] = value;
}
#endif
#undef STOS
}
template <typename T, typename U>
inline void MemsetPointer(T** dest, U* value, size_t counter) {
#ifdef DEBUG
T* a = nullptr;
U* b = nullptr;
a = b; // Fake assignment to check assignability.
USE(a);
#endif // DEBUG
MemsetPointer(reinterpret_cast<Address*>(dest),
reinterpret_cast<Address>(value), counter);
}
inline void MemsetPointer(ObjectSlot start, Object* value, size_t counter) {
MemsetPointer(start.location(), reinterpret_cast<Address>(value), counter);
}
// Simple support to read a file into std::string.
// On return, *exits tells whether the file existed.
V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists,
bool verbose = true);
std::string ReadFile(FILE* file, bool* exists, bool verbose = true);
template <typename sourcechar, typename sinkchar>
V8_INLINE static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
size_t chars);
#if defined(V8_HOST_ARCH_ARM)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#elif defined(V8_HOST_ARCH_MIPS)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
size_t chars);
V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
size_t chars);
#endif
// Copy from 8bit/16bit chars to 8bit/16bit chars.
template <typename sourcechar, typename sinkchar>
V8_INLINE void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars);
template <typename sourcechar, typename sinkchar>
void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
DCHECK_LE(sizeof(sourcechar), 2);
DCHECK_LE(sizeof(sinkchar), 2);
if (sizeof(sinkchar) == 1) {
if (sizeof(sourcechar) == 1) {
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint8_t*>(src),
chars);
} else {
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
reinterpret_cast<const uint16_t*>(src),
chars);
}
} else {
if (sizeof(sourcechar) == 1) {
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
reinterpret_cast<const uint8_t*>(src),
chars);
} else {
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
reinterpret_cast<const uint16_t*>(src),
chars);
}
}
}
template <typename sourcechar, typename sinkchar>
void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
sinkchar* limit = dest + chars;
if ((sizeof(*dest) == sizeof(*src)) &&
(chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
MemCopy(dest, src, chars * sizeof(*dest));
} else {
while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
}
}
#if defined(V8_HOST_ARCH_ARM)
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
case 2:
memcpy(dest, src, 2);
break;
case 3:
memcpy(dest, src, 3);
break;
case 4:
memcpy(dest, src, 4);
break;
case 5:
memcpy(dest, src, 5);
break;
case 6:
memcpy(dest, src, 6);
break;
case 7:
memcpy(dest, src, 7);
break;
case 8:
memcpy(dest, src, 8);
break;
case 9:
memcpy(dest, src, 9);
break;
case 10:
memcpy(dest, src, 10);
break;
case 11:
memcpy(dest, src, 11);
break;
case 12:
memcpy(dest, src, 12);
break;
case 13:
memcpy(dest, src, 13);
break;
case 14:
memcpy(dest, src, 14);
break;
case 15:
memcpy(dest, src, 15);
break;
default:
MemCopy(dest, src, chars);
break;
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
MemCopyUint16Uint8(dest, src, chars);
} else {
MemCopyUint16Uint8Wrapper(dest, src, chars);
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
case 2:
memcpy(dest, src, 4);
break;
case 3:
memcpy(dest, src, 6);
break;
case 4:
memcpy(dest, src, 8);
break;
case 5:
memcpy(dest, src, 10);
break;
case 6:
memcpy(dest, src, 12);
break;
case 7:
memcpy(dest, src, 14);
break;
default:
MemCopy(dest, src, chars * sizeof(*dest));
break;
}
}
#elif defined(V8_HOST_ARCH_MIPS)
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
if (chars < kMinComplexMemCopy) {
memcpy(dest, src, chars);
} else {
MemCopy(dest, src, chars);
}
}
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
if (chars < kMinComplexMemCopy) {
memcpy(dest, src, chars * sizeof(*dest));
} else {
MemCopy(dest, src, chars * sizeof(*dest));
}
}
#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
#define CASE(n) \
case n: \
memcpy(dest, src, n); \
break
void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
CASE(2);
CASE(3);
CASE(4);
CASE(5);
CASE(6);
CASE(7);
CASE(8);
CASE(9);
CASE(10);
CASE(11);
CASE(12);
CASE(13);
CASE(14);
CASE(15);
CASE(16);
CASE(17);
CASE(18);
CASE(19);
CASE(20);
CASE(21);
CASE(22);
CASE(23);
CASE(24);
CASE(25);
CASE(26);
CASE(27);
CASE(28);
CASE(29);
CASE(30);
CASE(31);
CASE(32);
CASE(33);
CASE(34);
CASE(35);
CASE(36);
CASE(37);
CASE(38);
CASE(39);
CASE(40);
CASE(41);
CASE(42);
CASE(43);
CASE(44);
CASE(45);
CASE(46);
CASE(47);
CASE(48);
CASE(49);
CASE(50);
CASE(51);
CASE(52);
CASE(53);
CASE(54);
CASE(55);
CASE(56);
CASE(57);
CASE(58);
CASE(59);
CASE(60);
CASE(61);
CASE(62);
CASE(63);
CASE(64);
default:
memcpy(dest, src, chars);
break;
}
}
#undef CASE
#define CASE(n) \
case n: \
memcpy(dest, src, n * 2); \
break
void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
switch (static_cast<unsigned>(chars)) {
case 0:
break;
case 1:
*dest = *src;
break;
CASE(2);
CASE(3);
CASE(4);
CASE(5);
CASE(6);
CASE(7);
CASE(8);
CASE(9);
CASE(10);
CASE(11);
CASE(12);
CASE(13);
CASE(14);
CASE(15);
CASE(16);
CASE(17);
CASE(18);
CASE(19);
CASE(20);
CASE(21);
CASE(22);
CASE(23);
CASE(24);
CASE(25);
CASE(26);
CASE(27);
CASE(28);
CASE(29);
CASE(30);
CASE(31);
CASE(32);
default:
memcpy(dest, src, chars * 2);
break;
}
}
#undef CASE
#endif
class StringBuilder : public SimpleStringBuilder {
public:
explicit StringBuilder(int size) : SimpleStringBuilder(size) { }

View File

@ -6,7 +6,7 @@
#include "src/base/iterator.h"
#include "src/globals.h"
#include "src/utils.h"
#include "src/memcopy.h"
#include "src/zone/zone.h"
#ifndef V8_ZONE_ZONE_CHUNK_LIST_H_

View File

@ -9,7 +9,7 @@
#include "src/base/macros.h"
#include "src/base/platform/platform.h"
#include "src/utils.h"
#include "src/memcopy.h"
namespace v8 {
namespace internal {