mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
e174a4c18e
The IsPowerOfTwo function is used together with ShiftForPowerOfTwo. Both function do not work with zero. This caused the optimizing compiler to generate invalid code for the expression x ? 0 : 0 where it assumed that if one of the constants is a power-of-two, it can be computed by (1 << n). We check for 0 in a number of places, but instead I decided to fix Utils::IsPowerOfTwo itself and remove unnecessary checks for the zero case. TEST=tests/language/vm/if_conversion_vm_test.dart, runtime/vm/utils_test.cc R=kmillikin@google.com Review URL: https://codereview.chromium.org//23604024 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@27033 260f80e4-7a28-3924-810f-c04153c831b5
198 lines
5.3 KiB
C++
198 lines
5.3 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef PLATFORM_UTILS_H_
|
|
#define PLATFORM_UTILS_H_
|
|
|
|
#include "platform/assert.h"
|
|
#include "platform/globals.h"
|
|
|
|
namespace dart {
|
|
|
|
class Utils {
|
|
public:
|
|
template<typename T>
|
|
static inline T Minimum(T x, T y) {
|
|
return x < y ? x : y;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T Maximum(T x, T y) {
|
|
return x > y ? x : y;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T Abs(T x) {
|
|
if (x < 0) return -x;
|
|
return x;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline bool IsPowerOfTwo(T x) {
|
|
return ((x & (x - 1)) == 0) && (x != 0);
|
|
}
|
|
|
|
template<typename T>
|
|
static inline int ShiftForPowerOfTwo(T x) {
|
|
ASSERT(IsPowerOfTwo(x));
|
|
int num_shifts = 0;
|
|
while (x > 1) {
|
|
num_shifts++;
|
|
x = x >> 1;
|
|
}
|
|
return num_shifts;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline bool IsAligned(T x, int n) {
|
|
ASSERT(IsPowerOfTwo(n));
|
|
return (x & (n - 1)) == 0;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline bool IsAligned(T* x, int n) {
|
|
return IsAligned(reinterpret_cast<uword>(x), n);
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T RoundDown(T x, int n) {
|
|
ASSERT(IsPowerOfTwo(n));
|
|
return (x & -n);
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T* RoundDown(T* x, int n) {
|
|
return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uword>(x), n));
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T RoundUp(T x, int n) {
|
|
return RoundDown(x + n - 1, n);
|
|
}
|
|
|
|
template<typename T>
|
|
static inline T* RoundUp(T* x, int n) {
|
|
return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uword>(x), n));
|
|
}
|
|
|
|
static uint32_t RoundUpToPowerOfTwo(uint32_t x);
|
|
static int CountOneBits(uint32_t x);
|
|
|
|
static int HighestBit(int64_t v);
|
|
|
|
static int CountTrailingZeros(uword x);
|
|
|
|
// Computes a hash value for the given string.
|
|
static uint32_t StringHash(const char* data, int length);
|
|
|
|
// Computes a hash value for the given word.
|
|
static uint32_t WordHash(word key);
|
|
|
|
// Check whether an N-bit two's-complement representation can hold value.
|
|
template<typename T>
|
|
static inline bool IsInt(int N, T value) {
|
|
ASSERT((0 < N) &&
|
|
(static_cast<unsigned int>(N) < (kBitsPerByte * sizeof(value))));
|
|
T limit = static_cast<T>(1) << (N - 1);
|
|
return (-limit <= value) && (value < limit);
|
|
}
|
|
|
|
template<typename T>
|
|
static inline bool IsUint(int N, T value) {
|
|
ASSERT((0 < N) &&
|
|
(static_cast<unsigned int>(N) < (kBitsPerByte * sizeof(value))));
|
|
T limit = static_cast<T>(1) << N;
|
|
return (0 <= value) && (value < limit);
|
|
}
|
|
|
|
// Check whether the magnitude of value fits in N bits, i.e., whether an
|
|
// (N+1)-bit sign-magnitude representation can hold value.
|
|
template<typename T>
|
|
static inline bool IsAbsoluteUint(int N, T value) {
|
|
ASSERT((0 < N) &&
|
|
(static_cast<unsigned int>(N) < (kBitsPerByte * sizeof(value))));
|
|
if (value < 0) value = -value;
|
|
return IsUint(N, value);
|
|
}
|
|
|
|
static inline int32_t Low16Bits(int32_t value) {
|
|
return static_cast<int32_t>(value & 0xffff);
|
|
}
|
|
|
|
static inline int32_t High16Bits(int32_t value) {
|
|
return static_cast<int32_t>(value >> 16);
|
|
}
|
|
|
|
static inline int32_t Low32Bits(int64_t value) {
|
|
return static_cast<int32_t>(value);
|
|
}
|
|
|
|
static inline int32_t High32Bits(int64_t value) {
|
|
return static_cast<int32_t>(value >> 32);
|
|
}
|
|
|
|
static inline int64_t LowHighTo64Bits(uint32_t low, int32_t high) {
|
|
return (static_cast<int64_t>(high) << 32) | (low & 0x0ffffffffLL);
|
|
}
|
|
|
|
static bool IsDecimalDigit(char c) {
|
|
return ('0' <= c) && (c <= '9');
|
|
}
|
|
|
|
static bool IsHexDigit(char c) {
|
|
return IsDecimalDigit(c)
|
|
|| (('A' <= c) && (c <= 'F'))
|
|
|| (('a' <= c) && (c <= 'f'));
|
|
}
|
|
|
|
static int HexDigitToInt(char c) {
|
|
ASSERT(IsHexDigit(c));
|
|
if (IsDecimalDigit(c)) return c - '0';
|
|
if (('A' <= c) && (c <= 'F')) return 10 + (c - 'A');
|
|
return 10 + (c - 'a');
|
|
}
|
|
|
|
static char IntToHexDigit(int i) {
|
|
ASSERT(0 <= i && i < 16);
|
|
if (i < 10) return static_cast<char>('0' + i);
|
|
return static_cast<char>('A' + (i - 10));
|
|
}
|
|
|
|
// Perform a range check, checking if
|
|
// offset + count <= length
|
|
// without the risk of integer overflow.
|
|
static inline bool RangeCheck(intptr_t offset,
|
|
intptr_t count,
|
|
intptr_t length) {
|
|
return offset >= 0 &&
|
|
count >= 0 &&
|
|
length >= 0 &&
|
|
count <= (length - offset);
|
|
}
|
|
|
|
// Utility functions for converting values from host endianess to
|
|
// big or little endian values.
|
|
static uint16_t HostToBigEndian16(uint16_t host_value);
|
|
static uint32_t HostToBigEndian32(uint32_t host_value);
|
|
static uint64_t HostToBigEndian64(uint64_t host_value);
|
|
static uint16_t HostToLittleEndian16(uint16_t host_value);
|
|
static uint32_t HostToLittleEndian32(uint32_t host_value);
|
|
static uint64_t HostToLittleEndian64(uint64_t host_value);
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#if defined(TARGET_OS_ANDROID)
|
|
#include "platform/utils_android.h"
|
|
#elif defined(TARGET_OS_LINUX)
|
|
#include "platform/utils_linux.h"
|
|
#elif defined(TARGET_OS_MACOS)
|
|
#include "platform/utils_macos.h"
|
|
#elif defined(TARGET_OS_WINDOWS)
|
|
#include "platform/utils_win.h"
|
|
#else
|
|
#error Unknown target os.
|
|
#endif
|
|
|
|
#endif // PLATFORM_UTILS_H_
|