// V8_HOST_ARCH_IA32 on both 32- and 64-bit x86.
#define V8_HOST_ARCH_IA32 1
#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
#else
#define V8_HOST_ARCH_X64 1
#if defined(__x86_64__) && __SIZEOF_POINTER__ == 4 // Check for x32.
#else
#define V8_HOST_ARCH_64_BIT 1
#endif
+#define V8_HOST_CAN_READ_UNALIGNED 1
#endif // __native_client__
#elif defined(_M_IX86) || defined(__i386__)
#define V8_HOST_ARCH_IA32 1
#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
#elif defined(__AARCH64EL__)
#define V8_HOST_ARCH_ARM64 1
#define V8_HOST_ARCH_64_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
#elif defined(__ARMEL__)
#define V8_HOST_ARCH_ARM 1
#define V8_HOST_ARCH_32_BIT 1
static inline double read_double_value(Address p) {
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ return Memory::double_at(p);
+#else // V8_HOST_CAN_READ_UNALIGNED
// Prevent gcc from using load-double (mips ldc1) on (possibly)
// non-64-bit aligned address.
- // We assume that the address is 32-bit aligned.
- DCHECK(IsAligned(reinterpret_cast<intptr_t>(p), kInt32Size));
union conversion {
double d;
uint32_t u[2];
} c;
- c.u[0] = Memory::uint32_at(p);
- c.u[1] = Memory::uint32_at(p + 4);
+ c.u[0] = *reinterpret_cast<uint32_t*>(p);
+ c.u[1] = *reinterpret_cast<uint32_t*>(p + 4);
return c.d;
+#endif // V8_HOST_CAN_READ_UNALIGNED
}
static inline bool CompareRawStringContents(const Char* const a,
const Char* const b,
int length) {
- return CompareChars(a, b, length) == 0;
+ int i = 0;
+#ifndef V8_HOST_CAN_READ_UNALIGNED
+ // If this architecture isn't comfortable reading unaligned ints
+ // then we have to check that the strings are aligned before
+ // comparing them blockwise.
+ const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT
+ uintptr_t pa_addr = reinterpret_cast<uintptr_t>(a);
+ uintptr_t pb_addr = reinterpret_cast<uintptr_t>(b);
+ if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
+#endif
+ const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT
+ int endpoint = length - kStepSize;
+ // Compare blocks until we reach near the end of the string.
+ for (; i <= endpoint; i += kStepSize) {
+ uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
+ uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
+ if (wa != wb) {
+ return false;
+ }
+ }
+#ifndef V8_HOST_CAN_READ_UNALIGNED
+ }
+#endif
+ // Compare the remaining characters that didn't fit into a block.
+ for (; i < length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
}
static inline int NonAsciiStart(const char* chars, int length) {
const char* start = chars;
const char* limit = chars + length;
-
- if (length >= kIntptrSize) {
- // Check unaligned bytes.
- while (!IsAligned(reinterpret_cast<intptr_t>(chars), sizeof(uintptr_t))) {
- if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) {
- return static_cast<int>(chars - start);
- }
- ++chars;
- }
- // Check aligned words.
- DCHECK(unibrow::Utf8::kMaxOneByteChar == 0x7F);
- const uintptr_t non_one_byte_mask = kUintptrAllBitsSet / 0xFF * 0x80;
- while (chars + sizeof(uintptr_t) <= limit) {
- if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) {
- return static_cast<int>(chars - start);
- }
- chars += sizeof(uintptr_t);
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ DCHECK(unibrow::Utf8::kMaxOneByteChar == 0x7F);
+ const uintptr_t non_one_byte_mask = kUintptrAllBitsSet / 0xFF * 0x80;
+ while (chars + sizeof(uintptr_t) <= limit) {
+ if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) {
+ return static_cast<int>(chars - start);
}
+ chars += sizeof(uintptr_t);
}
- // Check remaining unaligned bytes.
+#endif
while (chars < limit) {
if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) {
return static_cast<int>(chars - start);
}
++chars;
}
-
return static_cast<int>(chars - start);
}
virtual ~RegExpMacroAssemblerIrregexp();
// The byte-code interpreter checks on each push anyway.
virtual int stack_limit_slack() { return 1; }
- virtual bool CanReadUnaligned() { return false; }
virtual void Bind(Label* label);
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
virtual void PopCurrentPosition();
}
+bool RegExpMacroAssembler::CanReadUnaligned() {
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ return true;
+#else
+ return false;
+#endif
+}
+
+
#ifndef V8_INTERPRETED_REGEXP // Avoid unused code, e.g., on ARM.
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(Zone* zone)
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
// at least once for every stack_limit() pushes that are executed.
virtual int stack_limit_slack() = 0;
- virtual bool CanReadUnaligned() = 0;
+ virtual bool CanReadUnaligned();
virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change.
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by.
// Continues execution from the position pushed on the top of the backtrack
bool changed = false;
uintptr_t or_acc = 0;
const char* const limit = src + length;
-
- // dst is newly allocated and always aligned.
- DCHECK(IsAligned(reinterpret_cast<intptr_t>(dst), sizeof(uintptr_t)));
- // Only attempt processing one word at a time if src is also aligned.
- if (IsAligned(reinterpret_cast<intptr_t>(src), sizeof(uintptr_t))) {
- // Process the prefix of the input that requires no conversion one aligned
- // (machine) word at a time.
- while (src <= limit - sizeof(uintptr_t)) {
- const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
- or_acc |= w;
- if (AsciiRangeMask(w, lo, hi) != 0) {
- changed = true;
- break;
- }
- *reinterpret_cast<uintptr_t*>(dst) = w;
- src += sizeof(uintptr_t);
- dst += sizeof(uintptr_t);
- }
- // Process the remainder of the input performing conversion when
- // required one word at a time.
- while (src <= limit - sizeof(uintptr_t)) {
- const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
- or_acc |= w;
- uintptr_t m = AsciiRangeMask(w, lo, hi);
- // The mask has high (7th) bit set in every byte that needs
- // conversion and we know that the distance between cases is
- // 1 << 5.
- *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
- src += sizeof(uintptr_t);
- dst += sizeof(uintptr_t);
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ // Process the prefix of the input that requires no conversion one
+ // (machine) word at a time.
+ while (src <= limit - sizeof(uintptr_t)) {
+ const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
+ or_acc |= w;
+ if (AsciiRangeMask(w, lo, hi) != 0) {
+ changed = true;
+ break;
}
+ *reinterpret_cast<uintptr_t*>(dst) = w;
+ src += sizeof(uintptr_t);
+ dst += sizeof(uintptr_t);
+ }
+ // Process the remainder of the input performing conversion when
+ // required one word at a time.
+ while (src <= limit - sizeof(uintptr_t)) {
+ const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
+ or_acc |= w;
+ uintptr_t m = AsciiRangeMask(w, lo, hi);
+ // The mask has high (7th) bit set in every byte that needs
+ // conversion and we know that the distance between cases is
+ // 1 << 5.
+ *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
+ src += sizeof(uintptr_t);
+ dst += sizeof(uintptr_t);
}
+#endif
// Process the last few bytes of the input (or the whole input if
// unaligned access is not supported).
while (src < limit) {
++src;
++dst;
}
-
- if ((or_acc & kAsciiMask) != 0) return false;
+ if ((or_acc & kAsciiMask) != 0) {
+ return false;
+ }
DCHECK(CheckFastAsciiConvert(
saved_dst, saved_src, length, changed, Converter::kIsToLower));
int32_t SnapshotByteSource::GetUnalignedInt() {
DCHECK(position_ < length_); // Require at least one byte left.
+#if defined(V8_HOST_CAN_READ_UNALIGNED) && __BYTE_ORDER == __LITTLE_ENDIAN
+ int32_t answer = *reinterpret_cast<const int32_t*>(data_ + position_);
+#else
int32_t answer = data_[position_];
answer |= data_[position_ + 1] << 8;
answer |= data_[position_ + 2] << 16;
answer |= data_[position_ + 3] << 24;
+#endif
return answer;
}
const rchar* rhs,
int chars) {
const lchar* limit = lhs + chars;
+#ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*lhs) == sizeof(*rhs)) {
- return memcmp(lhs, rhs, sizeof(*lhs) * chars);
+ // Number of characters in a uintptr_t.
+ static const int kStepSize = sizeof(uintptr_t) / sizeof(*lhs); // NOLINT
+ while (lhs <= limit - kStepSize) {
+ if (*reinterpret_cast<const uintptr_t*>(lhs) !=
+ *reinterpret_cast<const uintptr_t*>(rhs)) {
+ break;
+ }
+ lhs += kStepSize;
+ rhs += kStepSize;
+ }
}
+#endif
while (lhs < limit) {
int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
if (r != 0) return r;
template <typename sourcechar, typename sinkchar>
void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
sinkchar* limit = dest + chars;
+#ifdef V8_HOST_CAN_READ_UNALIGNED
if ((sizeof(*dest) == sizeof(*src)) &&
(chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
MemCopy(dest, src, chars * sizeof(*dest));
- } else {
- while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
+ return;
+ }
+#endif
+ while (dest < limit) {
+ *dest++ = static_cast<sinkchar>(*src++);
}
}