blob: 1c07ba4c8f45d00f2877af214c1078672bd5eee4 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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 V8_UTILS_H_
29#define V8_UTILS_H_
30
31namespace v8 { namespace internal {
32
33// ----------------------------------------------------------------------------
34// General helper functions
35
36// Returns true iff x is a power of 2. Does not work for zero.
37template <typename T>
38static inline bool IsPowerOf2(T x) {
39 return (x & (x - 1)) == 0;
40}
41
42
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043
44
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000045// The C++ standard leaves the semantics of '>>' undefined for
46// negative signed operands. Most implementations do the right thing,
47// though.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048static inline int ArithmeticShiftRight(int x, int s) {
49 return x >> s;
50}
51
52
53// Compute the 0-relative offset of some absolute value x of type T.
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000054// This allows conversion of Addresses and integral types into
55// 0-relative int offsets.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056template <typename T>
57static inline int OffsetFrom(T x) {
58 return x - static_cast<T>(0);
59}
60
61
62// Compute the absolute value of type T for some 0-relative offset x.
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000063// This allows conversion of 0-relative int offsets into Addresses and
64// integral types.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065template <typename T>
66static inline T AddressFrom(int x) {
67 return static_cast<T>(0) + x;
68}
69
70
71// Return the largest multiple of m which is <= x.
72template <typename T>
73static inline T RoundDown(T x, int m) {
74 ASSERT(IsPowerOf2(m));
75 return AddressFrom<T>(OffsetFrom(x) & -m);
76}
77
78
79// Return the smallest multiple of m which is >= x.
80template <typename T>
81static inline T RoundUp(T x, int m) {
82 return RoundDown(x + m - 1, m);
83}
84
85
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000086// Returns the smallest power of two which is >= x. If you pass in a
87// number that is already a power of two, it is returned as is.
88uint32_t RoundUpToPowerOf2(uint32_t x);
89
90
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091template <typename T>
92static inline bool IsAligned(T value, T alignment) {
93 ASSERT(IsPowerOf2(alignment));
94 return (value & (alignment - 1)) == 0;
95}
96
97
98// Returns true if (addr + offset) is aligned.
99static inline bool IsAddressAligned(Address addr, int alignment, int offset) {
100 int offs = OffsetFrom(addr + offset);
101 return IsAligned(offs, alignment);
102}
103
104
105// Returns the maximum of the two parameters.
106template <typename T>
107static T Max(T a, T b) {
108 return a < b ? b : a;
109}
110
111
112// Returns the minimum of the two parameters.
113template <typename T>
114static T Min(T a, T b) {
115 return a < b ? a : b;
116}
117
118
119// ----------------------------------------------------------------------------
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000120// BitField is a help template for encoding and decode bitfield with
121// unsigned content.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122template<class T, int shift, int size>
123class BitField {
124 public:
125 // Tells whether the provided value fits into the bit field.
126 static bool is_valid(T value) {
127 return (static_cast<uint32_t>(value) & ~((1U << (size)) - 1)) == 0;
128 }
129
130 // Returns a uint32_t mask of bit field.
131 static uint32_t mask() {
132 return (1U << (size + shift)) - (1U << shift);
133 }
134
135 // Returns a uint32_t with the bit field value encoded.
136 static uint32_t encode(T value) {
137 ASSERT(is_valid(value));
138 return static_cast<uint32_t>(value) << shift;
139 }
140
141 // Extracts the bit field from the value.
142 static T decode(uint32_t value) {
143 return static_cast<T>((value >> shift) & ((1U << (size)) - 1));
144 }
145};
146
147
148// ----------------------------------------------------------------------------
149// Support for compressed, machine-independent encoding
150// and decoding of integer values of arbitrary size.
151
152// Encoding and decoding from/to a buffer at position p;
153// the result is the position after the encoded integer.
154// Small signed integers in the range -64 <= x && x < 64
155// are encoded in 1 byte; larger values are encoded in 2
156// or more bytes. At most sizeof(int) + 1 bytes are used
157// in the worst case.
158byte* EncodeInt(byte* p, int x);
159byte* DecodeInt(byte* p, int* x);
160
161
162// Encoding and decoding from/to a buffer at position p - 1
163// moving backward; the result is the position of the last
164// byte written. These routines are useful to read/write
165// into a buffer starting at the end of the buffer.
166byte* EncodeUnsignedIntBackward(byte* p, unsigned int x);
167
168// The decoding function is inlined since its performance is
169// important to mark-sweep garbage collection.
170inline byte* DecodeUnsignedIntBackward(byte* p, unsigned int* x) {
171 byte b = *--p;
172 if (b >= 128) {
173 *x = static_cast<unsigned int>(b) - 128;
174 return p;
175 }
176 unsigned int r = static_cast<unsigned int>(b);
177 unsigned int s = 7;
178 b = *--p;
179 while (b < 128) {
180 r |= static_cast<unsigned int>(b) << s;
181 s += 7;
182 b = *--p;
183 }
184 // b >= 128
185 *x = r | ((static_cast<unsigned int>(b) - 128) << s);
186 return p;
187}
188
189
190// ----------------------------------------------------------------------------
191// I/O support.
192
193// Our version of printf(). Avoids compilation errors that we get
194// with standard printf when attempting to print pointers, etc.
195// (the errors are due to the extra compilation flags, which we
196// want elsewhere).
197void PrintF(const char* format, ...);
198
199// Our version of fflush.
200void Flush();
201
202
203// Read a line of characters after printing the prompt to stdout. The resulting
204// char* needs to be disposed off with DeleteArray by the caller.
205char* ReadLine(const char* prompt);
206
207
208// Read and return the raw chars in a file. the size of the buffer is returned
209// in size.
210// The returned buffer is not 0-terminated. It must be freed by the caller.
211char* ReadChars(const char* filename, int* size, bool verbose = true);
212
213
214// Write size chars from str to the file given by filename.
215// The file is overwritten. Returns the number of chars written.
216int WriteChars(const char* filename,
217 const char* str,
218 int size,
219 bool verbose = true);
220
221
222// Write the C code
223// const char* <varname> = "<str>";
224// const int <varname>_len = <len>;
225// to the file given by filename. Only the first len chars are written.
226int WriteAsCFile(const char* filename, const char* varname,
227 const char* str, int size, bool verbose = true);
228
229
230// ----------------------------------------------------------------------------
231// Miscellaneous
232
233// A static resource holds a static instance that can be reserved in
234// a local scope using an instance of Access. Attempts to re-reserve
235// the instance will cause an error.
236template <typename T>
237class StaticResource {
238 public:
239 StaticResource() : is_reserved_(false) {}
240
241 private:
242 template <typename S> friend class Access;
243 T instance_;
244 bool is_reserved_;
245};
246
247
248// Locally scoped access to a static resource.
249template <typename T>
250class Access {
251 public:
252 explicit Access(StaticResource<T>* resource)
253 : resource_(resource)
254 , instance_(&resource->instance_) {
255 ASSERT(!resource->is_reserved_);
256 resource->is_reserved_ = true;
257 }
258
259 ~Access() {
260 resource_->is_reserved_ = false;
261 resource_ = NULL;
262 instance_ = NULL;
263 }
264
265 T* value() { return instance_; }
266 T* operator -> () { return instance_; }
267
268 private:
269 StaticResource<T>* resource_;
270 T* instance_;
271};
272
273
274template <typename T>
275class Vector {
276 public:
kasper.lund7276f142008-07-30 08:49:36 +0000277 Vector() : start_(NULL), length_(0) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278 Vector(T* data, int length) : start_(data), length_(length) {
279 ASSERT(length == 0 || (length > 0 && data != NULL));
280 }
281
282 // Returns the length of the vector.
283 int length() const { return length_; }
284
285 // Returns whether or not the vector is empty.
286 bool is_empty() const { return length_ == 0; }
287
288 // Returns the pointer to the start of the data in the vector.
289 T* start() const { return start_; }
290
291 // Access individual vector elements - checks bounds in debug mode.
292 T& operator[](int index) const {
293 ASSERT(0 <= index && index < length_);
294 return start_[index];
295 }
296
297 // Returns a clone of this vector with a new backing store.
298 Vector<T> Clone() const {
299 T* result = NewArray<T>(length_);
300 for (int i = 0; i < length_; i++) result[i] = start_[i];
301 return Vector<T>(result, length_);
302 }
303
304 // Releases the array underlying this vector. Once disposed the
305 // vector is empty.
306 void Dispose() {
kasper.lund7276f142008-07-30 08:49:36 +0000307 if (is_empty()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 DeleteArray(start_);
309 start_ = NULL;
310 length_ = 0;
311 }
312
313 // Factory method for creating empty vectors.
314 static Vector<T> empty() { return Vector<T>(NULL, 0); }
315
316 private:
317 T* start_;
318 int length_;
319};
320
321
322inline Vector<const char> CStrVector(const char* data) {
323 return Vector<const char>(data, strlen(data));
324}
325
326inline Vector<char> MutableCStrVector(char* data) {
327 return Vector<char>(data, strlen(data));
328}
329
330template <typename T>
331inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
332 int length) {
333 return Vector< Handle<Object> >(
334 reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
335}
336
337
338// Simple support to read a file into a 0-terminated C-string.
339// The returned buffer must be freed by the caller.
340// On return, *exits tells whether the file exisited.
341Vector<const char> ReadFile(const char* filename,
342 bool* exists,
343 bool verbose = true);
344
345
346// Simple wrapper that allows an ExternalString to refer to a
347// Vector<const char>. Doesn't assume ownership of the data.
348class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
349 public:
350 explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
351
352 virtual const char* data() const { return data_.start(); }
353
354 virtual size_t length() const { return data_.length(); }
355
356 private:
357 Vector<const char> data_;
358};
359
360
kasper.lund7276f142008-07-30 08:49:36 +0000361// Helper class for building result strings in a character buffer. The
362// purpose of the class is to use safe operations that checks the
363// buffer bounds on all operations in debug mode.
364class StringBuilder {
365 public:
366 // Create a string builder with a buffer of the given size. The
367 // buffer is allocated through NewArray<char> and must be
368 // deallocated by the caller of Finalize().
369 explicit StringBuilder(int size);
370
371 StringBuilder(char* buffer, int size)
372 : buffer_(buffer), size_(size), position_(0) { }
373
374 ~StringBuilder() { if (!is_finalized()) Finalize(); }
375
376 int size() const { return size_; }
377
378 // Get the current position in the builder.
379 int position() const {
380 ASSERT(!is_finalized());
381 return position_;
382 }
383
384 // Reset the position.
385 void Reset() { position_ = 0; }
386
387 // Add a single character to the builder. It is not allowed to add
388 // 0-characters; use the Finalize() method to terminate the string
389 // instead.
390 void AddCharacter(char c) {
391 ASSERT(c != '\0');
392 ASSERT(!is_finalized() && position_ < size_);
393 buffer_[position_++] = c;
394 }
395
396 // Add an entire string to the builder. Uses strlen() internally to
397 // compute the length of the input string.
398 void AddString(const char* s);
399
400 // Add the first 'n' characters of the given string 's' to the
401 // builder. The input string must have enough characters.
402 void AddSubstring(const char* s, int n);
403
404 // Add formatted contents to the builder just like printf().
405 void AddFormatted(const char* format, ...);
406
407 // Add character padding to the builder. If count is non-positive,
408 // nothing is added to the builder.
409 void AddPadding(char c, int count);
410
411 // Finalize the string by 0-terminating it and returning the buffer.
412 char* Finalize();
413
414 private:
kasper.lund7276f142008-07-30 08:49:36 +0000415 char* buffer_;
416 int size_;
417 int position_;
418
419 bool is_finalized() const { return position_ < 0; }
mads.s.ager31e71382008-08-13 09:32:07 +0000420
421 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
kasper.lund7276f142008-07-30 08:49:36 +0000422};
423
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000424} } // namespace v8::internal
425
426#endif // V8_UTILS_H_