Commit 28323284 authored by whesse@chromium.org's avatar whesse@chromium.org

Add thread-safety to creation of MemCopy and modulo functions.

BUG=
TEST=release test-api MultipleIsolatesOnIndividualThreads on Windows X64 build.

Review URL: http://codereview.chromium.org/6777007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7437 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0a6d586d
...@@ -1302,7 +1302,7 @@ ScriptData* ScriptData::New(const char* data, int length) { ...@@ -1302,7 +1302,7 @@ ScriptData* ScriptData::New(const char* data, int length) {
} }
// Copy the data to align it. // Copy the data to align it.
unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length); unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
i::MemCopy(deserialized_data, data, length); i::OS::MemCopy(deserialized_data, data, length);
return new i::ScriptDataImpl( return new i::ScriptDataImpl(
i::Vector<unsigned>(deserialized_data, deserialized_data_length)); i::Vector<unsigned>(deserialized_data, deserialized_data_length));
......
...@@ -10174,7 +10174,7 @@ static void MemCopyWrapper(void* dest, const void* src, size_t size) { ...@@ -10174,7 +10174,7 @@ static void MemCopyWrapper(void* dest, const void* src, size_t size) {
} }
MemCopyFunction CreateMemCopyFunction() { OS::MemCopyFunction CreateMemCopyFunction() {
HandleScope scope; HandleScope scope;
MacroAssembler masm(NULL, 1 * KB); MacroAssembler masm(NULL, 1 * KB);
...@@ -10198,7 +10198,7 @@ MemCopyFunction CreateMemCopyFunction() { ...@@ -10198,7 +10198,7 @@ MemCopyFunction CreateMemCopyFunction() {
if (FLAG_debug_code) { if (FLAG_debug_code) {
__ cmp(Operand(esp, kSizeOffset + stack_offset), __ cmp(Operand(esp, kSizeOffset + stack_offset),
Immediate(kMinComplexMemCopy)); Immediate(OS::kMinComplexMemCopy));
Label ok; Label ok;
__ j(greater_equal, &ok); __ j(greater_equal, &ok);
__ int3(); __ int3();
...@@ -10377,7 +10377,8 @@ MemCopyFunction CreateMemCopyFunction() { ...@@ -10377,7 +10377,8 @@ MemCopyFunction CreateMemCopyFunction() {
if (chunk == NULL) return &MemCopyWrapper; if (chunk == NULL) return &MemCopyWrapper;
memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size);
CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size);
return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress()); MemoryBarrier();
return FUNCTION_CAST<OS::MemCopyFunction>(chunk->GetStartAddress());
} }
#undef __ #undef __
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -205,6 +205,29 @@ int OS::VSNPrintF(Vector<char> str, ...@@ -205,6 +205,29 @@ int OS::VSNPrintF(Vector<char> str,
} }
#if defined(V8_TARGET_ARCH_IA32)
static OS::MemCopyFunction memcopy_function = NULL;
static Mutex* memcopy_function_mutex = OS::CreateMutex();
// Defined in codegen-ia32.cc.
OS::MemCopyFunction CreateMemCopyFunction();
// Copy memory area to disjoint memory area.
void OS::MemCopy(void* dest, const void* src, size_t size) {
if (memcopy_function == NULL) {
ScopedLock lock(memcopy_function_mutex);
Isolate::EnsureDefaultIsolate();
if (memcopy_function == NULL) {
Release_Store(reinterpret_cast<AtomicWord*>(&memcopy_function),
reinterpret_cast<AtomicWord>(CreateMemCopyFunction()));
}
}
(*memcopy_function)(dest, src, size);
#ifdef DEBUG
CHECK_EQ(0, memcmp(dest, src, size));
#endif
}
#endif // V8_TARGET_ARCH_IA32
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// POSIX string support. // POSIX string support.
// //
......
...@@ -176,16 +176,45 @@ double ceiling(double x) { ...@@ -176,16 +176,45 @@ double ceiling(double x) {
static Mutex* limit_mutex = NULL; static Mutex* limit_mutex = NULL;
#if defined(V8_TARGET_ARCH_IA32)
static OS::MemCopyFunction memcopy_function = NULL;
static Mutex* memcopy_function_mutex = OS::CreateMutex();
// Defined in codegen-ia32.cc.
OS::MemCopyFunction CreateMemCopyFunction();
// Copy memory area to disjoint memory area.
void OS::MemCopy(void* dest, const void* src, size_t size) {
if (memcopy_function == NULL) {
ScopedLock lock(memcopy_function_mutex);
Isolate::EnsureDefaultIsolate();
if (memcopy_function == NULL) {
memcopy_function = CreateMemCopyFunction();
}
}
(*memcopy_function)(dest, src, size);
#ifdef DEBUG
CHECK_EQ(0, memcmp(dest, src, size));
#endif
}
#endif // V8_TARGET_ARCH_IA32
#ifdef _WIN64 #ifdef _WIN64
typedef double (*ModuloFunction)(double, double); typedef double (*ModuloFunction)(double, double);
static ModuloFunction modulo_function = NULL;
static Mutex* modulo_function_mutex = OS::CreateMutex();
// Defined in codegen-x64.cc. // Defined in codegen-x64.cc.
ModuloFunction CreateModuloFunction(); ModuloFunction CreateModuloFunction();
double modulo(double x, double y) { double modulo(double x, double y) {
static ModuloFunction function = CreateModuloFunction(); if (modulo_function == NULL) {
return function(x, y); ScopedLock lock(modulo_function_mutex);
Isolate::EnsureDefaultIsolate();
if (modulo_function == NULL) {
Release_Store(reinterpret_cast<AtomicWord*>(&modulo_function),
reinterpret_cast<AtomicWord>(CreateModuloFunction()));
}
}
return (*modulo_function)(x, y);
} }
#else // Win32 #else // Win32
......
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -303,6 +303,21 @@ class OS { ...@@ -303,6 +303,21 @@ class OS {
static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value); static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
#if defined(V8_TARGET_ARCH_IA32)
// Copy memory area to disjoint memory area.
static void MemCopy(void* dest, const void* src, size_t size);
// Limit below which the extra overhead of the MemCopy function is likely
// to outweigh the benefits of faster copying.
static const int kMinComplexMemCopy = 64;
typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
#else // V8_TARGET_ARCH_IA32
static void MemCopy(void* dest, const void* src, size_t size) {
memcpy(dest, src, size);
}
static const int kMinComplexMemCopy = 256;
#endif // V8_TARGET_ARCH_IA32
private: private:
static const int msPerSecond = 1000; static const int msPerSecond = 1000;
......
...@@ -254,51 +254,14 @@ class StringBuilder { ...@@ -254,51 +254,14 @@ class StringBuilder {
}; };
// Custom memcpy implementation for platforms where the standard version
// may not be good enough.
#if defined(V8_TARGET_ARCH_IA32)
// The default memcpy on ia32 architectures is generally not as efficient
// as possible. (If any further ia32 platforms are introduced where the
// memcpy function is efficient, exclude them from this branch).
typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
// Implemented in codegen-<arch>.cc.
MemCopyFunction CreateMemCopyFunction();
// Copy memory area to disjoint memory area.
static inline void MemCopy(void* dest, const void* src, size_t size) {
static MemCopyFunction memcopy = CreateMemCopyFunction();
(*memcopy)(dest, src, size);
#ifdef DEBUG
CHECK_EQ(0, memcmp(dest, src, size));
#endif
}
// Limit below which the extra overhead of the MemCopy function is likely
// to outweigh the benefits of faster copying.
static const int kMinComplexMemCopy = 64;
#else // V8_TARGET_ARCH_IA32
static inline void MemCopy(void* dest, const void* src, size_t size) {
memcpy(dest, src, size);
}
static const int kMinComplexMemCopy = 256;
#endif // V8_TARGET_ARCH_IA32
// Copy from ASCII/16bit chars to ASCII/16bit chars. // Copy from ASCII/16bit chars to ASCII/16bit chars.
template <typename sourcechar, typename sinkchar> template <typename sourcechar, typename sinkchar>
static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) { static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
sinkchar* limit = dest + chars; sinkchar* limit = dest + chars;
#ifdef V8_HOST_CAN_READ_UNALIGNED #ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*dest) == sizeof(*src)) { if (sizeof(*dest) == sizeof(*src)) {
if (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest))) { if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) {
MemCopy(dest, src, chars * sizeof(*dest)); OS::MemCopy(dest, src, chars * sizeof(*dest));
return; return;
} }
// Number of characters in a uintptr_t. // Number of characters in a uintptr_t.
......
...@@ -8824,7 +8824,10 @@ ModuloFunction CreateModuloFunction() { ...@@ -8824,7 +8824,10 @@ ModuloFunction CreateModuloFunction() {
CodeDesc desc; CodeDesc desc;
masm.GetCode(&desc); masm.GetCode(&desc);
// Call the function from C++. // Make sure that the compiled code is visible to all threads before
// returning the pointer to it.
MemoryBarrier();
// Call the function from C++ through this pointer.
return FUNCTION_CAST<ModuloFunction>(buffer); return FUNCTION_CAST<ModuloFunction>(buffer);
} }
......
...@@ -89,8 +89,8 @@ void TestMemCopy(Vector<byte> src, ...@@ -89,8 +89,8 @@ void TestMemCopy(Vector<byte> src,
memset(dst.start(), 0xFF, dst.length()); memset(dst.start(), 0xFF, dst.length());
byte* to = dst.start() + 32 + destination_alignment; byte* to = dst.start() + 32 + destination_alignment;
byte* from = src.start() + source_alignment; byte* from = src.start() + source_alignment;
int length = kMinComplexMemCopy + length_alignment; int length = OS::kMinComplexMemCopy + length_alignment;
MemCopy(to, from, static_cast<size_t>(length)); OS::MemCopy(to, from, static_cast<size_t>(length));
printf("[%d,%d,%d]\n", printf("[%d,%d,%d]\n",
source_alignment, destination_alignment, length_alignment); source_alignment, destination_alignment, length_alignment);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
...@@ -104,7 +104,7 @@ void TestMemCopy(Vector<byte> src, ...@@ -104,7 +104,7 @@ void TestMemCopy(Vector<byte> src,
TEST(MemCopy) { TEST(MemCopy) {
OS::Setup(); OS::Setup();
const int N = kMinComplexMemCopy + 128; const int N = OS::kMinComplexMemCopy + 128;
Vector<byte> buffer1 = Vector<byte>::New(N); Vector<byte> buffer1 = Vector<byte>::New(N);
Vector<byte> buffer2 = Vector<byte>::New(N); Vector<byte> buffer2 = Vector<byte>::New(N);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment