From 8f8039574a6b35cf1018c18f1e04e39ff362fad2 Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Fri, 5 Nov 2010 08:18:53 +0000 Subject: [PATCH] Split utils.h into utils.h and v8utils.h where the former is independent of V8. The code in utils.h can be reused outside of v8 propert, as long as the propert ASSERT macros are defined. Review URL: http://codereview.chromium.org/4485001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5772 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 1 - src/ia32/ic-ia32.cc | 1 - src/utils.cc | 36 ------ src/utils.h | 315 ++++++---------------------------------------------- src/v8.h | 2 +- src/v8utils.h | 301 +++++++++++++++++++++++++++++++++++++++++++++++++ src/x64/ic-x64.cc | 1 - 7 files changed, 336 insertions(+), 321 deletions(-) create mode 100644 src/v8utils.h diff --git a/src/api.cc b/src/api.cc index 617922d..ee7ad3a 100644 --- a/src/api.cc +++ b/src/api.cc @@ -43,7 +43,6 @@ #include "serialize.h" #include "snapshot.h" #include "top.h" -#include "utils.h" #include "v8threads.h" #include "version.h" diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index b5f4dee..a0bc086 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -33,7 +33,6 @@ #include "ic-inl.h" #include "runtime.h" #include "stub-cache.h" -#include "utils.h" namespace v8 { namespace internal { diff --git a/src/utils.cc b/src/utils.cc index 45a4cd6..7096ba3 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -37,34 +37,6 @@ namespace v8 { namespace internal { -// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr., -// figure 3-3, page 48, where the function is called clp2. -uint32_t RoundUpToPowerOf2(uint32_t x) { - ASSERT(x <= 0x80000000u); - x = x - 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >> 16); - return x + 1; -} - - -// Thomas Wang, Integer Hash Functions. -// http://www.concentric.net/~Ttwang/tech/inthash.htm -uint32_t ComputeIntegerHash(uint32_t key) { - uint32_t hash = key; - hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; - hash = hash ^ (hash >> 12); - hash = hash + (hash << 2); - hash = hash ^ (hash >> 4); - hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); - hash = hash ^ (hash >> 16); - return hash; -} - - void PrintF(const char* format, ...) { va_list arguments; va_start(arguments, format); @@ -274,12 +246,4 @@ char* StringBuilder::Finalize() { } -int TenToThe(int exponent) { - ASSERT(exponent <= 9); - ASSERT(exponent >= 1); - int answer = 10; - for (int i = 1; i < exponent; i++) answer *= 10; - return answer; -} - } } // namespace v8::internal diff --git a/src/utils.h b/src/utils.h index ffdb639..069be4f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -31,6 +31,8 @@ #include #include +#include "checks.h" + namespace v8 { namespace internal { @@ -142,7 +144,19 @@ static int PointerValueCompare(const T* a, const T* b) { // Returns the smallest power of two which is >= x. If you pass in a // number that is already a power of two, it is returned as is. -uint32_t RoundUpToPowerOf2(uint32_t x); +// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr., +// figure 3-3, page 48, where the function is called clp2. +static inline uint32_t RoundUpToPowerOf2(uint32_t x) { + ASSERT(x <= 0x80000000u); + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x + 1; +} + template @@ -216,65 +230,18 @@ class BitField { // ---------------------------------------------------------------------------- // Hash function. -uint32_t ComputeIntegerHash(uint32_t key); - - -// ---------------------------------------------------------------------------- -// I/O support. - -#if __GNUC__ >= 4 -// On gcc we can ask the compiler to check the types of %d-style format -// specifiers and their associated arguments. TODO(erikcorry) fix this -// so it works on MacOSX. -#if defined(__MACH__) && defined(__APPLE__) -#define PRINTF_CHECKING -#else // MacOsX. -#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2))) -#endif -#else -#define PRINTF_CHECKING -#endif - -// Our version of printf(). -void PRINTF_CHECKING PrintF(const char* format, ...); - -// Our version of fflush. -void Flush(); - - -// Read a line of characters after printing the prompt to stdout. The resulting -// char* needs to be disposed off with DeleteArray by the caller. -char* ReadLine(const char* prompt); - - -// Read and return the raw bytes in a file. the size of the buffer is returned -// in size. -// The returned buffer must be freed by the caller. -byte* ReadBytes(const char* filename, int* size, bool verbose = true); - - -// Write size chars from str to the file given by filename. -// The file is overwritten. Returns the number of chars written. -int WriteChars(const char* filename, - const char* str, - int size, - bool verbose = true); - - -// Write size bytes to the file given by filename. -// The file is overwritten. Returns the number of bytes written. -int WriteBytes(const char* filename, - const byte* bytes, - int size, - bool verbose = true); - - -// Write the C code -// const char* = ""; -// const int _len = ; -// to the file given by filename. Only the first len chars are written. -int WriteAsCFile(const char* filename, const char* varname, - const char* str, int size, bool verbose = true); +// Thomas Wang, Integer Hash Functions. +// http://www.concentric.net/~Ttwang/tech/inthash.htm +static inline uint32_t ComputeIntegerHash(uint32_t key) { + uint32_t hash = key; + hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; + hash = hash ^ (hash >> 12); + hash = hash + (hash << 2); + hash = hash ^ (hash >> 4); + hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); + hash = hash ^ (hash >> 16); + return hash; +} // ---------------------------------------------------------------------------- @@ -416,23 +383,6 @@ class Vector { }; -// A temporary assignment sets a (non-local) variable to a value on -// construction and resets it the value on destruction. -template -class TempAssign { - public: - TempAssign(T* var, T value): var_(var), old_value_(*var) { - *var = value; - } - - ~TempAssign() { *var_ = old_value_; } - - private: - T* var_; - T old_value_; -}; - - template class EmbeddedVector : public Vector { public: @@ -484,13 +434,6 @@ inline Vector MutableCStrVector(char* data, int max) { return Vector(data, (length < max) ? length : max); } -template -inline Vector< Handle > HandleVector(v8::internal::Handle* elms, - int length) { - return Vector< Handle >( - reinterpret_cast*>(elms), length); -} - /* * A class that collects values into a backing store. @@ -699,156 +642,6 @@ class SequenceCollector : public Collector { }; -// Simple support to read a file into a 0-terminated C-string. -// The returned buffer must be freed by the caller. -// On return, *exits tells whether the file existed. -Vector ReadFile(const char* filename, - bool* exists, - bool verbose = true); - - -// Simple wrapper that allows an ExternalString to refer to a -// Vector. Doesn't assume ownership of the data. -class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource { - public: - explicit AsciiStringAdapter(Vector data) : data_(data) {} - - virtual const char* data() const { return data_.start(); } - - virtual size_t length() const { return data_.length(); } - - private: - Vector data_; -}; - - -// Helper class for building result strings in a character buffer. The -// purpose of the class is to use safe operations that checks the -// buffer bounds on all operations in debug mode. -class StringBuilder { - public: - // Create a string builder with a buffer of the given size. The - // buffer is allocated through NewArray and must be - // deallocated by the caller of Finalize(). - explicit StringBuilder(int size); - - StringBuilder(char* buffer, int size) - : buffer_(buffer, size), position_(0) { } - - ~StringBuilder() { if (!is_finalized()) Finalize(); } - - int size() const { return buffer_.length(); } - - // Get the current position in the builder. - int position() const { - ASSERT(!is_finalized()); - return position_; - } - - // Reset the position. - void Reset() { position_ = 0; } - - // Add a single character to the builder. It is not allowed to add - // 0-characters; use the Finalize() method to terminate the string - // instead. - void AddCharacter(char c) { - ASSERT(c != '\0'); - ASSERT(!is_finalized() && position_ < buffer_.length()); - buffer_[position_++] = c; - } - - // Add an entire string to the builder. Uses strlen() internally to - // compute the length of the input string. - void AddString(const char* s); - - // Add the first 'n' characters of the given string 's' to the - // builder. The input string must have enough characters. - void AddSubstring(const char* s, int n); - - // Add formatted contents to the builder just like printf(). - void AddFormatted(const char* format, ...); - - // Add character padding to the builder. If count is non-positive, - // nothing is added to the builder. - void AddPadding(char c, int count); - - // Finalize the string by 0-terminating it and returning the buffer. - char* Finalize(); - - private: - Vector buffer_; - int position_; - - bool is_finalized() const { return position_ < 0; } - - DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); -}; - - -// Custom memcpy implementation for platforms where the standard version -// may not be good enough. -// TODO(lrn): Check whether some IA32 platforms should be excluded. -#if defined(V8_TARGET_ARCH_IA32) - -// TODO(lrn): Extend to other platforms as needed. - -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. -// TODO(lrn): Try to find a more precise value. -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)); - return; - } - // Number of characters in a uintptr_t. - static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT - while (dest <= limit - kStepSize) { - *reinterpret_cast(dest) = - *reinterpret_cast(src); - dest += kStepSize; - src += kStepSize; - } - } -#endif - while (dest < limit) { - *dest++ = static_cast(*src++); - } -} - - // Compare ASCII/16bit chars to ASCII/16bit chars. template static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) { @@ -877,54 +670,14 @@ static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) { } -template -static inline void MemsetPointer(T** dest, T* value, int counter) { -#if defined(V8_HOST_ARCH_IA32) -#define STOS "stosl" -#elif defined(V8_HOST_ARCH_X64) -#define STOS "stosq" -#endif - -#if defined(__GNUC__) && defined(STOS) - asm volatile( - "cld;" - "rep ; " STOS - : "+&c" (counter), "+&D" (dest) - : "a" (value) - : "memory", "cc"); -#else - for (int i = 0; i < counter; i++) { - dest[i] = value; - } -#endif - -#undef STOS -} - - -// Copies data from |src| to |dst|. The data spans MUST not overlap. -inline void CopyWords(Object** dst, Object** src, int num_words) { - ASSERT(Min(dst, src) + num_words <= Max(dst, src)); - ASSERT(num_words > 0); - - // Use block copying memcpy if the segment we're copying is - // enough to justify the extra call/setup overhead. - static const int kBlockCopyLimit = 16; - - if (num_words >= kBlockCopyLimit) { - memcpy(dst, src, num_words * kPointerSize); - } else { - int remaining = num_words; - do { - remaining--; - *dst++ = *src++; - } while (remaining > 0); - } -} - - // Calculate 10^exponent. -int TenToThe(int exponent); +static inline int TenToThe(int exponent) { + ASSERT(exponent <= 9); + ASSERT(exponent >= 1); + int answer = 10; + for (int i = 1; i < exponent; i++) answer *= 10; + return answer; +} // The type-based aliasing rule allows the compiler to assume that pointers of diff --git a/src/v8.h b/src/v8.h index 9dbdf4c..1cb8d2f 100644 --- a/src/v8.h +++ b/src/v8.h @@ -56,7 +56,7 @@ #include "globals.h" #include "checks.h" #include "allocation.h" -#include "utils.h" +#include "v8utils.h" #include "flags.h" // Objects & heap diff --git a/src/v8utils.h b/src/v8utils.h new file mode 100644 index 0000000..3f272dd --- /dev/null +++ b/src/v8utils.h @@ -0,0 +1,301 @@ +// Copyright 2010 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef V8_V8UTILS_H_ +#define V8_V8UTILS_H_ + +#include "utils.h" + +namespace v8 { +namespace internal { + +// ---------------------------------------------------------------------------- +// I/O support. + +#if __GNUC__ >= 4 +// On gcc we can ask the compiler to check the types of %d-style format +// specifiers and their associated arguments. TODO(erikcorry) fix this +// so it works on MacOSX. +#if defined(__MACH__) && defined(__APPLE__) +#define PRINTF_CHECKING +#else // MacOsX. +#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2))) +#endif +#else +#define PRINTF_CHECKING +#endif + +// Our version of printf(). +void PRINTF_CHECKING PrintF(const char* format, ...); + +// Our version of fflush. +void Flush(); + + +// Read a line of characters after printing the prompt to stdout. The resulting +// char* needs to be disposed off with DeleteArray by the caller. +char* ReadLine(const char* prompt); + + +// Read and return the raw bytes in a file. the size of the buffer is returned +// in size. +// The returned buffer must be freed by the caller. +byte* ReadBytes(const char* filename, int* size, bool verbose = true); + + +// Write size chars from str to the file given by filename. +// The file is overwritten. Returns the number of chars written. +int WriteChars(const char* filename, + const char* str, + int size, + bool verbose = true); + + +// Write size bytes to the file given by filename. +// The file is overwritten. Returns the number of bytes written. +int WriteBytes(const char* filename, + const byte* bytes, + int size, + bool verbose = true); + + +// Write the C code +// const char* = ""; +// const int _len = ; +// to the file given by filename. Only the first len chars are written. +int WriteAsCFile(const char* filename, const char* varname, + const char* str, int size, bool verbose = true); + + +// Data structures + +template +inline Vector< Handle > HandleVector(v8::internal::Handle* elms, + int length) { + return Vector< Handle >( + reinterpret_cast*>(elms), length); +} + +// Memory + +// Copies data from |src| to |dst|. The data spans MUST not overlap. +inline void CopyWords(Object** dst, Object** src, int num_words) { + ASSERT(Min(dst, src) + num_words <= Max(dst, src)); + ASSERT(num_words > 0); + + // Use block copying memcpy if the segment we're copying is + // enough to justify the extra call/setup overhead. + static const int kBlockCopyLimit = 16; + + if (num_words >= kBlockCopyLimit) { + memcpy(dst, src, num_words * kPointerSize); + } else { + int remaining = num_words; + do { + remaining--; + *dst++ = *src++; + } while (remaining > 0); + } +} + + +template +static inline void MemsetPointer(T** dest, T* value, int counter) { +#if defined(V8_HOST_ARCH_IA32) +#define STOS "stosl" +#elif defined(V8_HOST_ARCH_X64) +#define STOS "stosq" +#endif + +#if defined(__GNUC__) && defined(STOS) + asm volatile( + "cld;" + "rep ; " STOS + : "+&c" (counter), "+&D" (dest) + : "a" (value) + : "memory", "cc"); +#else + for (int i = 0; i < counter; i++) { + dest[i] = value; + } +#endif + +#undef STOS +} + + +// Simple wrapper that allows an ExternalString to refer to a +// Vector. Doesn't assume ownership of the data. +class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource { + public: + explicit AsciiStringAdapter(Vector data) : data_(data) {} + + virtual const char* data() const { return data_.start(); } + + virtual size_t length() const { return data_.length(); } + + private: + Vector data_; +}; + + +// Simple support to read a file into a 0-terminated C-string. +// The returned buffer must be freed by the caller. +// On return, *exits tells whether the file existed. +Vector ReadFile(const char* filename, + bool* exists, + bool verbose = true); + + +// Helper class for building result strings in a character buffer. The +// purpose of the class is to use safe operations that checks the +// buffer bounds on all operations in debug mode. +class StringBuilder { + public: + // Create a string builder with a buffer of the given size. The + // buffer is allocated through NewArray and must be + // deallocated by the caller of Finalize(). + explicit StringBuilder(int size); + + StringBuilder(char* buffer, int size) + : buffer_(buffer, size), position_(0) { } + + ~StringBuilder() { if (!is_finalized()) buffer_.Dispose(); } + + int size() const { return buffer_.length(); } + + // Get the current position in the builder. + int position() const { + ASSERT(!is_finalized()); + return position_; + } + + // Reset the position. + void Reset() { position_ = 0; } + + // Add a single character to the builder. It is not allowed to add + // 0-characters; use the Finalize() method to terminate the string + // instead. + void AddCharacter(char c) { + ASSERT(c != '\0'); + ASSERT(!is_finalized() && position_ < buffer_.length()); + buffer_[position_++] = c; + } + + // Add an entire string to the builder. Uses strlen() internally to + // compute the length of the input string. + void AddString(const char* s); + + // Add the first 'n' characters of the given string 's' to the + // builder. The input string must have enough characters. + void AddSubstring(const char* s, int n); + + // Add formatted contents to the builder just like printf(). + void AddFormatted(const char* format, ...); + + // Add character padding to the builder. If count is non-positive, + // nothing is added to the builder. + void AddPadding(char c, int count); + + // Finalize the string by 0-terminating it and returning the buffer. + char* Finalize(); + + private: + Vector buffer_; + int position_; + + bool is_finalized() const { return position_ < 0; } + + DISALLOW_IMPLICIT_CONSTRUCTORS(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)); + return; + } + // Number of characters in a uintptr_t. + static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT + while (dest <= limit - kStepSize) { + *reinterpret_cast(dest) = + *reinterpret_cast(src); + dest += kStepSize; + src += kStepSize; + } + } +#endif + while (dest < limit) { + *dest++ = static_cast(*src++); + } +} + +} } // namespace v8::internal + +#endif // V8_V8UTILS_H_ diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index 1d95b7f..9ec7814 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -33,7 +33,6 @@ #include "ic-inl.h" #include "runtime.h" #include "stub-cache.h" -#include "utils.h" namespace v8 { namespace internal { -- 2.7.4