From: whesse@chromium.org Date: Wed, 30 Mar 2011 14:04:26 +0000 (+0000) Subject: Add thread-safety to creation of MemCopy and modulo functions. X-Git-Tag: upstream/4.7.83~19757 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=28323284c0f5f373e752833c00f75dd9c9f2e10c;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/api.cc b/src/api.cc index fb827f2..61838e3 100644 --- a/src/api.cc +++ b/src/api.cc @@ -1302,7 +1302,7 @@ ScriptData* ScriptData::New(const char* data, int length) { } // Copy the data to align it. unsigned* deserialized_data = i::NewArray(deserialized_data_length); - i::MemCopy(deserialized_data, data, length); + i::OS::MemCopy(deserialized_data, data, length); return new i::ScriptDataImpl( i::Vector(deserialized_data, deserialized_data_length)); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index cf990a0..2d17a72 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -10174,7 +10174,7 @@ static void MemCopyWrapper(void* dest, const void* src, size_t size) { } -MemCopyFunction CreateMemCopyFunction() { +OS::MemCopyFunction CreateMemCopyFunction() { HandleScope scope; MacroAssembler masm(NULL, 1 * KB); @@ -10198,7 +10198,7 @@ MemCopyFunction CreateMemCopyFunction() { if (FLAG_debug_code) { __ cmp(Operand(esp, kSizeOffset + stack_offset), - Immediate(kMinComplexMemCopy)); + Immediate(OS::kMinComplexMemCopy)); Label ok; __ j(greater_equal, &ok); __ int3(); @@ -10377,7 +10377,8 @@ MemCopyFunction CreateMemCopyFunction() { if (chunk == NULL) return &MemCopyWrapper; memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); - return FUNCTION_CAST(chunk->GetStartAddress()); + MemoryBarrier(); + return FUNCTION_CAST(chunk->GetStartAddress()); } #undef __ diff --git a/src/platform-posix.cc b/src/platform-posix.cc index 1dd486e..8365352 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -1,4 +1,4 @@ -// 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 // modification, are permitted provided that the following conditions are // met: @@ -205,6 +205,29 @@ int OS::VSNPrintF(Vector 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(&memcopy_function), + reinterpret_cast(CreateMemCopyFunction())); + } + } + (*memcopy_function)(dest, src, size); +#ifdef DEBUG + CHECK_EQ(0, memcmp(dest, src, size)); +#endif +} +#endif // V8_TARGET_ARCH_IA32 + // ---------------------------------------------------------------------------- // POSIX string support. // diff --git a/src/platform-win32.cc b/src/platform-win32.cc index 50a9e5b..0901fca 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -176,16 +176,45 @@ double ceiling(double x) { 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 typedef double (*ModuloFunction)(double, double); - +static ModuloFunction modulo_function = NULL; +static Mutex* modulo_function_mutex = OS::CreateMutex(); // Defined in codegen-x64.cc. ModuloFunction CreateModuloFunction(); double modulo(double x, double y) { - static ModuloFunction function = CreateModuloFunction(); - return function(x, y); + if (modulo_function == NULL) { + ScopedLock lock(modulo_function_mutex); + Isolate::EnsureDefaultIsolate(); + if (modulo_function == NULL) { + Release_Store(reinterpret_cast(&modulo_function), + reinterpret_cast(CreateModuloFunction())); + } + } + return (*modulo_function)(x, y); } #else // Win32 diff --git a/src/platform.h b/src/platform.h index 09a28a5..a5b804e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,4 +1,4 @@ -// 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 // modification, are permitted provided that the following conditions are // met: @@ -303,6 +303,21 @@ class OS { 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: static const int msPerSecond = 1000; diff --git a/src/v8utils.h b/src/v8utils.h index 0aa53ca..87c5e7f 100644 --- a/src/v8utils.h +++ b/src/v8utils.h @@ -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-.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. template static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) { sinkchar* limit = dest + chars; #ifdef V8_HOST_CAN_READ_UNALIGNED if (sizeof(*dest) == sizeof(*src)) { - if (chars >= static_cast(kMinComplexMemCopy / sizeof(*dest))) { - MemCopy(dest, src, chars * sizeof(*dest)); + if (chars >= static_cast(OS::kMinComplexMemCopy / sizeof(*dest))) { + OS::MemCopy(dest, src, chars * sizeof(*dest)); return; } // Number of characters in a uintptr_t. diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index dc999b5..c8f1c04 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -8824,7 +8824,10 @@ ModuloFunction CreateModuloFunction() { CodeDesc 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(buffer); } diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc index 018018a..e96fcd1 100644 --- a/test/cctest/test-utils.cc +++ b/test/cctest/test-utils.cc @@ -89,8 +89,8 @@ void TestMemCopy(Vector src, memset(dst.start(), 0xFF, dst.length()); byte* to = dst.start() + 32 + destination_alignment; byte* from = src.start() + source_alignment; - int length = kMinComplexMemCopy + length_alignment; - MemCopy(to, from, static_cast(length)); + int length = OS::kMinComplexMemCopy + length_alignment; + OS::MemCopy(to, from, static_cast(length)); printf("[%d,%d,%d]\n", source_alignment, destination_alignment, length_alignment); for (int i = 0; i < length; i++) { @@ -104,7 +104,7 @@ void TestMemCopy(Vector src, TEST(MemCopy) { OS::Setup(); - const int N = kMinComplexMemCopy + 128; + const int N = OS::kMinComplexMemCopy + 128; Vector buffer1 = Vector::New(N); Vector buffer2 = Vector::New(N);