|
1 // Copyright 2010 the V8 project authors. All rights reserved. |
|
2 // Redistribution and use in source and binary forms, with or without |
|
3 // modification, are permitted provided that the following conditions are |
|
4 // met: |
|
5 // |
|
6 // * Redistributions of source code must retain the above copyright |
|
7 // notice, this list of conditions and the following disclaimer. |
|
8 // * Redistributions in binary form must reproduce the above |
|
9 // copyright notice, this list of conditions and the following |
|
10 // disclaimer in the documentation and/or other materials provided |
|
11 // with the distribution. |
|
12 // * Neither the name of Google Inc. nor the names of its |
|
13 // contributors may be used to endorse or promote products derived |
|
14 // from this software without specific prior written permission. |
|
15 // |
|
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 |
|
28 #ifndef DOUBLE_CONVERSION_UTILS_H_ |
|
29 #define DOUBLE_CONVERSION_UTILS_H_ |
|
30 |
|
31 #include <stdlib.h> |
|
32 #include <string.h> |
|
33 |
|
34 #include "mozilla/Assertions.h" |
|
35 #ifndef ASSERT |
|
36 #define ASSERT(condition) MOZ_ASSERT(condition) |
|
37 #endif |
|
38 #ifndef UNIMPLEMENTED |
|
39 #define UNIMPLEMENTED() MOZ_CRASH() |
|
40 #endif |
|
41 #ifndef UNREACHABLE |
|
42 #define UNREACHABLE() MOZ_CRASH() |
|
43 #endif |
|
44 |
|
45 // Double operations detection based on target architecture. |
|
46 // Linux uses a 80bit wide floating point stack on x86. This induces double |
|
47 // rounding, which in turn leads to wrong results. |
|
48 // An easy way to test if the floating-point operations are correct is to |
|
49 // evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then |
|
50 // the result is equal to 89255e-22. |
|
51 // The best way to test this, is to create a division-function and to compare |
|
52 // the output of the division with the expected result. (Inlining must be |
|
53 // disabled.) |
|
54 // On Linux,x86 89255e-22 != Div_double(89255.0/1e22) |
|
55 #if defined(_M_X64) || defined(__x86_64__) || \ |
|
56 defined(__ARMEL__) || defined(__avr32__) || \ |
|
57 defined(__hppa__) || defined(__ia64__) || \ |
|
58 defined(__mips__) || \ |
|
59 defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ |
|
60 defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ |
|
61 defined(__SH4__) || defined(__alpha__) || \ |
|
62 defined(_MIPS_ARCH_MIPS32R2) || \ |
|
63 defined(__AARCH64EL__) |
|
64 #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 |
|
65 #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) |
|
66 #if defined(_WIN32) |
|
67 // Windows uses a 64bit wide floating point stack. |
|
68 #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 |
|
69 #else |
|
70 #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS |
|
71 #endif // _WIN32 |
|
72 #else |
|
73 #error Target architecture was not detected as supported by Double-Conversion. |
|
74 #endif |
|
75 |
|
76 |
|
77 #include <stdint.h> |
|
78 |
|
79 // The following macro works on both 32 and 64-bit platforms. |
|
80 // Usage: instead of writing 0x1234567890123456 |
|
81 // write UINT64_2PART_C(0x12345678,90123456); |
|
82 #define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u)) |
|
83 |
|
84 |
|
85 // The expression ARRAY_SIZE(a) is a compile-time constant of type |
|
86 // size_t which represents the number of elements of the given |
|
87 // array. You should only use ARRAY_SIZE on statically allocated |
|
88 // arrays. |
|
89 #ifndef ARRAY_SIZE |
|
90 #define ARRAY_SIZE(a) \ |
|
91 ((sizeof(a) / sizeof(*(a))) / \ |
|
92 static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) |
|
93 #endif |
|
94 |
|
95 // A macro to disallow the evil copy constructor and operator= functions |
|
96 // This should be used in the private: declarations for a class |
|
97 #ifndef DISALLOW_COPY_AND_ASSIGN |
|
98 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ |
|
99 TypeName(const TypeName&); \ |
|
100 void operator=(const TypeName&) |
|
101 #endif |
|
102 |
|
103 // A macro to disallow all the implicit constructors, namely the |
|
104 // default constructor, copy constructor and operator= functions. |
|
105 // |
|
106 // This should be used in the private: declarations for a class |
|
107 // that wants to prevent anyone from instantiating it. This is |
|
108 // especially useful for classes containing only static methods. |
|
109 #ifndef DISALLOW_IMPLICIT_CONSTRUCTORS |
|
110 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ |
|
111 TypeName(); \ |
|
112 DISALLOW_COPY_AND_ASSIGN(TypeName) |
|
113 #endif |
|
114 |
|
115 namespace double_conversion { |
|
116 |
|
117 static const int kCharSize = sizeof(char); |
|
118 |
|
119 // Returns the maximum of the two parameters. |
|
120 template <typename T> |
|
121 static T Max(T a, T b) { |
|
122 return a < b ? b : a; |
|
123 } |
|
124 |
|
125 |
|
126 // Returns the minimum of the two parameters. |
|
127 template <typename T> |
|
128 static T Min(T a, T b) { |
|
129 return a < b ? a : b; |
|
130 } |
|
131 |
|
132 |
|
133 inline int StrLength(const char* string) { |
|
134 size_t length = strlen(string); |
|
135 ASSERT(length == static_cast<size_t>(static_cast<int>(length))); |
|
136 return static_cast<int>(length); |
|
137 } |
|
138 |
|
139 // This is a simplified version of V8's Vector class. |
|
140 template <typename T> |
|
141 class Vector { |
|
142 public: |
|
143 Vector() : start_(NULL), length_(0) {} |
|
144 Vector(T* data, int length) : start_(data), length_(length) { |
|
145 ASSERT(length == 0 || (length > 0 && data != NULL)); |
|
146 } |
|
147 |
|
148 // Returns a vector using the same backing storage as this one, |
|
149 // spanning from and including 'from', to but not including 'to'. |
|
150 Vector<T> SubVector(int from, int to) { |
|
151 ASSERT(to <= length_); |
|
152 ASSERT(from < to); |
|
153 ASSERT(0 <= from); |
|
154 return Vector<T>(start() + from, to - from); |
|
155 } |
|
156 |
|
157 // Returns the length of the vector. |
|
158 int length() const { return length_; } |
|
159 |
|
160 // Returns whether or not the vector is empty. |
|
161 bool is_empty() const { return length_ == 0; } |
|
162 |
|
163 // Returns the pointer to the start of the data in the vector. |
|
164 T* start() const { return start_; } |
|
165 |
|
166 // Access individual vector elements - checks bounds in debug mode. |
|
167 T& operator[](int index) const { |
|
168 ASSERT(0 <= index && index < length_); |
|
169 return start_[index]; |
|
170 } |
|
171 |
|
172 T& first() { return start_[0]; } |
|
173 |
|
174 T& last() { return start_[length_ - 1]; } |
|
175 |
|
176 private: |
|
177 T* start_; |
|
178 int length_; |
|
179 }; |
|
180 |
|
181 |
|
182 // Helper class for building result strings in a character buffer. The |
|
183 // purpose of the class is to use safe operations that checks the |
|
184 // buffer bounds on all operations in debug mode. |
|
185 class StringBuilder { |
|
186 public: |
|
187 StringBuilder(char* buffer, int size) |
|
188 : buffer_(buffer, size), position_(0) { } |
|
189 |
|
190 ~StringBuilder() { if (!is_finalized()) Finalize(); } |
|
191 |
|
192 int size() const { return buffer_.length(); } |
|
193 |
|
194 // Get the current position in the builder. |
|
195 int position() const { |
|
196 ASSERT(!is_finalized()); |
|
197 return position_; |
|
198 } |
|
199 |
|
200 // Reset the position. |
|
201 void Reset() { position_ = 0; } |
|
202 |
|
203 // Add a single character to the builder. It is not allowed to add |
|
204 // 0-characters; use the Finalize() method to terminate the string |
|
205 // instead. |
|
206 void AddCharacter(char c) { |
|
207 ASSERT(c != '\0'); |
|
208 ASSERT(!is_finalized() && position_ < buffer_.length()); |
|
209 buffer_[position_++] = c; |
|
210 } |
|
211 |
|
212 // Add an entire string to the builder. Uses strlen() internally to |
|
213 // compute the length of the input string. |
|
214 void AddString(const char* s) { |
|
215 AddSubstring(s, StrLength(s)); |
|
216 } |
|
217 |
|
218 // Add the first 'n' characters of the given string 's' to the |
|
219 // builder. The input string must have enough characters. |
|
220 void AddSubstring(const char* s, int n) { |
|
221 ASSERT(!is_finalized() && position_ + n < buffer_.length()); |
|
222 ASSERT(static_cast<size_t>(n) <= strlen(s)); |
|
223 memmove(&buffer_[position_], s, n * kCharSize); |
|
224 position_ += n; |
|
225 } |
|
226 |
|
227 |
|
228 // Add character padding to the builder. If count is non-positive, |
|
229 // nothing is added to the builder. |
|
230 void AddPadding(char c, int count) { |
|
231 for (int i = 0; i < count; i++) { |
|
232 AddCharacter(c); |
|
233 } |
|
234 } |
|
235 |
|
236 // Finalize the string by 0-terminating it and returning the buffer. |
|
237 char* Finalize() { |
|
238 ASSERT(!is_finalized() && position_ < buffer_.length()); |
|
239 buffer_[position_] = '\0'; |
|
240 // Make sure nobody managed to add a 0-character to the |
|
241 // buffer while building the string. |
|
242 ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); |
|
243 position_ = -1; |
|
244 ASSERT(is_finalized()); |
|
245 return buffer_.start(); |
|
246 } |
|
247 |
|
248 private: |
|
249 Vector<char> buffer_; |
|
250 int position_; |
|
251 |
|
252 bool is_finalized() const { return position_ < 0; } |
|
253 |
|
254 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); |
|
255 }; |
|
256 |
|
257 // The type-based aliasing rule allows the compiler to assume that pointers of |
|
258 // different types (for some definition of different) never alias each other. |
|
259 // Thus the following code does not work: |
|
260 // |
|
261 // float f = foo(); |
|
262 // int fbits = *(int*)(&f); |
|
263 // |
|
264 // The compiler 'knows' that the int pointer can't refer to f since the types |
|
265 // don't match, so the compiler may cache f in a register, leaving random data |
|
266 // in fbits. Using C++ style casts makes no difference, however a pointer to |
|
267 // char data is assumed to alias any other pointer. This is the 'memcpy |
|
268 // exception'. |
|
269 // |
|
270 // Bit_cast uses the memcpy exception to move the bits from a variable of one |
|
271 // type of a variable of another type. Of course the end result is likely to |
|
272 // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) |
|
273 // will completely optimize BitCast away. |
|
274 // |
|
275 // There is an additional use for BitCast. |
|
276 // Recent gccs will warn when they see casts that may result in breakage due to |
|
277 // the type-based aliasing rule. If you have checked that there is no breakage |
|
278 // you can use BitCast to cast one pointer type to another. This confuses gcc |
|
279 // enough that it can no longer see that you have cast one pointer type to |
|
280 // another thus avoiding the warning. |
|
281 template <class Dest, class Source> |
|
282 inline Dest BitCast(const Source& source) { |
|
283 static_assert(sizeof(Dest) == sizeof(Source), |
|
284 "BitCast's source and destination types must be the same size"); |
|
285 |
|
286 Dest dest; |
|
287 memmove(&dest, &source, sizeof(dest)); |
|
288 return dest; |
|
289 } |
|
290 |
|
291 template <class Dest, class Source> |
|
292 inline Dest BitCast(Source* source) { |
|
293 return BitCast<Dest>(reinterpret_cast<uintptr_t>(source)); |
|
294 } |
|
295 |
|
296 } // namespace double_conversion |
|
297 |
|
298 #endif // DOUBLE_CONVERSION_UTILS_H_ |