OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_UTILS_H_ | 5 #ifndef V8_UTILS_H_ |
6 #define V8_UTILS_H_ | 6 #define V8_UTILS_H_ |
7 | 7 |
8 #include <limits.h> | 8 #include <limits.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 | 315 |
316 | 316 |
317 inline uint32_t ComputePointerHash(void* ptr) { | 317 inline uint32_t ComputePointerHash(void* ptr) { |
318 return ComputeIntegerHash( | 318 return ComputeIntegerHash( |
319 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)), | 319 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)), |
320 v8::internal::kZeroHashSeed); | 320 v8::internal::kZeroHashSeed); |
321 } | 321 } |
322 | 322 |
323 | 323 |
324 // ---------------------------------------------------------------------------- | 324 // ---------------------------------------------------------------------------- |
| 325 // Generated memcpy/memmove |
| 326 |
| 327 // Initializes the codegen support that depends on CPU features. This is |
| 328 // called after CPU initialization. |
| 329 void init_memcopy_functions(); |
| 330 |
| 331 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87) |
| 332 // Limit below which the extra overhead of the MemCopy function is likely |
| 333 // to outweigh the benefits of faster copying. |
| 334 const int kMinComplexMemCopy = 64; |
| 335 |
| 336 // Copy memory area. No restrictions. |
| 337 void MemMove(void* dest, const void* src, size_t size); |
| 338 typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size); |
| 339 |
| 340 // Keep the distinction of "move" vs. "copy" for the benefit of other |
| 341 // architectures. |
| 342 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { |
| 343 MemMove(dest, src, size); |
| 344 } |
| 345 #elif defined(V8_HOST_ARCH_ARM) |
| 346 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src, |
| 347 size_t size); |
| 348 MemCopyUint8Function memcopy_uint8_function; |
| 349 void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src, size_t chars) { |
| 350 memcpy(dest, src, chars); |
| 351 } |
| 352 // For values < 16, the assembler function is slower than the inlined C code. |
| 353 const int kMinComplexMemCopy = 16; |
| 354 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { |
| 355 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest), |
| 356 reinterpret_cast<const uint8_t*>(src), size); |
| 357 } |
| 358 V8_INLINE void MemMove(void* dest, const void* src, size_t size) { |
| 359 memmove(dest, src, size); |
| 360 } |
| 361 |
| 362 typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src, |
| 363 size_t size); |
| 364 MemCopyUint16Uint8Function memcopy_uint16_uint8_function; |
| 365 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src, |
| 366 size_t chars); |
| 367 // For values < 12, the assembler function is slower than the inlined C code. |
| 368 const int kMinComplexConvertMemCopy = 12; |
| 369 V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src, |
| 370 size_t size) { |
| 371 (*memcopy_uint16_uint8_function)(dest, src, size); |
| 372 } |
| 373 #elif defined(V8_HOST_ARCH_MIPS) |
| 374 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src, |
| 375 size_t size); |
| 376 MemCopyUint8Function memcopy_uint8_function; |
| 377 V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src, |
| 378 size_t chars) { |
| 379 memcpy(dest, src, chars); |
| 380 } |
| 381 // For values < 16, the assembler function is slower than the inlined C code. |
| 382 const int kMinComplexMemCopy = 16; |
| 383 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { |
| 384 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest), |
| 385 reinterpret_cast<const uint8_t*>(src), size); |
| 386 } |
| 387 V8_INLINE void MemMove(void* dest, const void* src, size_t size) { |
| 388 memmove(dest, src, size); |
| 389 } |
| 390 #else |
| 391 // Copy memory area to disjoint memory area. |
| 392 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { |
| 393 memcpy(dest, src, size); |
| 394 } |
| 395 V8_INLINE void MemMove(void* dest, const void* src, size_t size) { |
| 396 memmove(dest, src, size); |
| 397 } |
| 398 const int kMinComplexMemCopy = 16 * kPointerSize; |
| 399 #endif // V8_TARGET_ARCH_IA32 |
| 400 |
| 401 |
| 402 // ---------------------------------------------------------------------------- |
325 // Miscellaneous | 403 // Miscellaneous |
326 | 404 |
327 // A static resource holds a static instance that can be reserved in | 405 // A static resource holds a static instance that can be reserved in |
328 // a local scope using an instance of Access. Attempts to re-reserve | 406 // a local scope using an instance of Access. Attempts to re-reserve |
329 // the instance will cause an error. | 407 // the instance will cause an error. |
330 template <typename T> | 408 template <typename T> |
331 class StaticResource { | 409 class StaticResource { |
332 public: | 410 public: |
333 StaticResource() : is_reserved_(false) {} | 411 StaticResource() : is_reserved_(false) {} |
334 | 412 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 | 473 |
396 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) { | 474 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) { |
397 for (int i = 0; i < kSize; ++i) { | 475 for (int i = 0; i < kSize; ++i) { |
398 buffer_[i] = initial_value; | 476 buffer_[i] = initial_value; |
399 } | 477 } |
400 } | 478 } |
401 | 479 |
402 // When copying, make underlying Vector to reference our buffer. | 480 // When copying, make underlying Vector to reference our buffer. |
403 EmbeddedVector(const EmbeddedVector& rhs) | 481 EmbeddedVector(const EmbeddedVector& rhs) |
404 : Vector<T>(rhs) { | 482 : Vector<T>(rhs) { |
405 OS::MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); | 483 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); |
406 set_start(buffer_); | 484 set_start(buffer_); |
407 } | 485 } |
408 | 486 |
409 EmbeddedVector& operator=(const EmbeddedVector& rhs) { | 487 EmbeddedVector& operator=(const EmbeddedVector& rhs) { |
410 if (this == &rhs) return *this; | 488 if (this == &rhs) return *this; |
411 Vector<T>::operator=(rhs); | 489 Vector<T>::operator=(rhs); |
412 OS::MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); | 490 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); |
413 this->set_start(buffer_); | 491 this->set_start(buffer_); |
414 return *this; | 492 return *this; |
415 } | 493 } |
416 | 494 |
417 private: | 495 private: |
418 T buffer_[kSize]; | 496 T buffer_[kSize]; |
419 }; | 497 }; |
420 | 498 |
421 | 499 |
422 /* | 500 /* |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 template <typename T> | 1211 template <typename T> |
1134 inline void CopyWords(T* dst, const T* src, size_t num_words) { | 1212 inline void CopyWords(T* dst, const T* src, size_t num_words) { |
1135 STATIC_ASSERT(sizeof(T) == kPointerSize); | 1213 STATIC_ASSERT(sizeof(T) == kPointerSize); |
1136 // TODO(mvstanton): disabled because mac builds are bogus failing on this | 1214 // TODO(mvstanton): disabled because mac builds are bogus failing on this |
1137 // assert. They are doing a signed comparison. Investigate in | 1215 // assert. They are doing a signed comparison. Investigate in |
1138 // the morning. | 1216 // the morning. |
1139 // ASSERT(Min(dst, const_cast<T*>(src)) + num_words <= | 1217 // ASSERT(Min(dst, const_cast<T*>(src)) + num_words <= |
1140 // Max(dst, const_cast<T*>(src))); | 1218 // Max(dst, const_cast<T*>(src))); |
1141 ASSERT(num_words > 0); | 1219 ASSERT(num_words > 0); |
1142 | 1220 |
1143 // Use block copying OS::MemCopy if the segment we're copying is | 1221 // Use block copying MemCopy if the segment we're copying is |
1144 // enough to justify the extra call/setup overhead. | 1222 // enough to justify the extra call/setup overhead. |
1145 static const size_t kBlockCopyLimit = 16; | 1223 static const size_t kBlockCopyLimit = 16; |
1146 | 1224 |
1147 if (num_words < kBlockCopyLimit) { | 1225 if (num_words < kBlockCopyLimit) { |
1148 do { | 1226 do { |
1149 num_words--; | 1227 num_words--; |
1150 *dst++ = *src++; | 1228 *dst++ = *src++; |
1151 } while (num_words > 0); | 1229 } while (num_words > 0); |
1152 } else { | 1230 } else { |
1153 OS::MemCopy(dst, src, num_words * kPointerSize); | 1231 MemCopy(dst, src, num_words * kPointerSize); |
1154 } | 1232 } |
1155 } | 1233 } |
1156 | 1234 |
1157 | 1235 |
1158 // Copies words from |src| to |dst|. No restrictions. | 1236 // Copies words from |src| to |dst|. No restrictions. |
1159 template <typename T> | 1237 template <typename T> |
1160 inline void MoveWords(T* dst, const T* src, size_t num_words) { | 1238 inline void MoveWords(T* dst, const T* src, size_t num_words) { |
1161 STATIC_ASSERT(sizeof(T) == kPointerSize); | 1239 STATIC_ASSERT(sizeof(T) == kPointerSize); |
1162 ASSERT(num_words > 0); | 1240 ASSERT(num_words > 0); |
1163 | 1241 |
1164 // Use block copying OS::MemCopy if the segment we're copying is | 1242 // Use block copying MemCopy if the segment we're copying is |
1165 // enough to justify the extra call/setup overhead. | 1243 // enough to justify the extra call/setup overhead. |
1166 static const size_t kBlockCopyLimit = 16; | 1244 static const size_t kBlockCopyLimit = 16; |
1167 | 1245 |
1168 if (num_words < kBlockCopyLimit && | 1246 if (num_words < kBlockCopyLimit && |
1169 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) { | 1247 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) { |
1170 T* end = dst + num_words; | 1248 T* end = dst + num_words; |
1171 do { | 1249 do { |
1172 num_words--; | 1250 num_words--; |
1173 *dst++ = *src++; | 1251 *dst++ = *src++; |
1174 } while (num_words > 0); | 1252 } while (num_words > 0); |
1175 } else { | 1253 } else { |
1176 OS::MemMove(dst, src, num_words * kPointerSize); | 1254 MemMove(dst, src, num_words * kPointerSize); |
1177 } | 1255 } |
1178 } | 1256 } |
1179 | 1257 |
1180 | 1258 |
1181 // Copies data from |src| to |dst|. The data spans must not overlap. | 1259 // Copies data from |src| to |dst|. The data spans must not overlap. |
1182 template <typename T> | 1260 template <typename T> |
1183 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) { | 1261 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) { |
1184 STATIC_ASSERT(sizeof(T) == 1); | 1262 STATIC_ASSERT(sizeof(T) == 1); |
1185 ASSERT(Min(dst, const_cast<T*>(src)) + num_bytes <= | 1263 ASSERT(Min(dst, const_cast<T*>(src)) + num_bytes <= |
1186 Max(dst, const_cast<T*>(src))); | 1264 Max(dst, const_cast<T*>(src))); |
1187 if (num_bytes == 0) return; | 1265 if (num_bytes == 0) return; |
1188 | 1266 |
1189 // Use block copying OS::MemCopy if the segment we're copying is | 1267 // Use block copying MemCopy if the segment we're copying is |
1190 // enough to justify the extra call/setup overhead. | 1268 // enough to justify the extra call/setup overhead. |
1191 static const int kBlockCopyLimit = OS::kMinComplexMemCopy; | 1269 static const int kBlockCopyLimit = kMinComplexMemCopy; |
1192 | 1270 |
1193 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) { | 1271 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) { |
1194 do { | 1272 do { |
1195 num_bytes--; | 1273 num_bytes--; |
1196 *dst++ = *src++; | 1274 *dst++ = *src++; |
1197 } while (num_bytes > 0); | 1275 } while (num_bytes > 0); |
1198 } else { | 1276 } else { |
1199 OS::MemCopy(dst, src, num_bytes); | 1277 MemCopy(dst, src, num_bytes); |
1200 } | 1278 } |
1201 } | 1279 } |
1202 | 1280 |
1203 | 1281 |
1204 template <typename T, typename U> | 1282 template <typename T, typename U> |
1205 inline void MemsetPointer(T** dest, U* value, int counter) { | 1283 inline void MemsetPointer(T** dest, U* value, int counter) { |
1206 #ifdef DEBUG | 1284 #ifdef DEBUG |
1207 T* a = NULL; | 1285 T* a = NULL; |
1208 U* b = NULL; | 1286 U* b = NULL; |
1209 a = b; // Fake assignment to check assignability. | 1287 a = b; // Fake assignment to check assignability. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 chars); | 1390 chars); |
1313 } | 1391 } |
1314 } | 1392 } |
1315 } | 1393 } |
1316 | 1394 |
1317 template <typename sourcechar, typename sinkchar> | 1395 template <typename sourcechar, typename sinkchar> |
1318 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) { | 1396 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) { |
1319 sinkchar* limit = dest + chars; | 1397 sinkchar* limit = dest + chars; |
1320 #ifdef V8_HOST_CAN_READ_UNALIGNED | 1398 #ifdef V8_HOST_CAN_READ_UNALIGNED |
1321 if (sizeof(*dest) == sizeof(*src)) { | 1399 if (sizeof(*dest) == sizeof(*src)) { |
1322 if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) { | 1400 if (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest))) { |
1323 OS::MemCopy(dest, src, chars * sizeof(*dest)); | 1401 MemCopy(dest, src, chars * sizeof(*dest)); |
1324 return; | 1402 return; |
1325 } | 1403 } |
1326 // Number of characters in a uintptr_t. | 1404 // Number of characters in a uintptr_t. |
1327 static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT | 1405 static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT |
1328 ASSERT(dest + kStepSize > dest); // Check for overflow. | 1406 ASSERT(dest + kStepSize > dest); // Check for overflow. |
1329 while (dest + kStepSize <= limit) { | 1407 while (dest + kStepSize <= limit) { |
1330 *reinterpret_cast<uintptr_t*>(dest) = | 1408 *reinterpret_cast<uintptr_t*>(dest) = |
1331 *reinterpret_cast<const uintptr_t*>(src); | 1409 *reinterpret_cast<const uintptr_t*>(src); |
1332 dest += kStepSize; | 1410 dest += kStepSize; |
1333 src += kStepSize; | 1411 src += kStepSize; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 case 13: | 1462 case 13: |
1385 memcpy(dest, src, 13); | 1463 memcpy(dest, src, 13); |
1386 break; | 1464 break; |
1387 case 14: | 1465 case 14: |
1388 memcpy(dest, src, 14); | 1466 memcpy(dest, src, 14); |
1389 break; | 1467 break; |
1390 case 15: | 1468 case 15: |
1391 memcpy(dest, src, 15); | 1469 memcpy(dest, src, 15); |
1392 break; | 1470 break; |
1393 default: | 1471 default: |
1394 OS::MemCopy(dest, src, chars); | 1472 MemCopy(dest, src, chars); |
1395 break; | 1473 break; |
1396 } | 1474 } |
1397 } | 1475 } |
1398 | 1476 |
1399 | 1477 |
1400 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) { | 1478 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) { |
1401 if (chars >= OS::kMinComplexConvertMemCopy) { | 1479 if (chars >= kMinComplexConvertMemCopy) { |
1402 OS::MemCopyUint16Uint8(dest, src, chars); | 1480 MemCopyUint16Uint8(dest, src, chars); |
1403 } else { | 1481 } else { |
1404 OS::MemCopyUint16Uint8Wrapper(dest, src, chars); | 1482 MemCopyUint16Uint8Wrapper(dest, src, chars); |
1405 } | 1483 } |
1406 } | 1484 } |
1407 | 1485 |
1408 | 1486 |
1409 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { | 1487 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { |
1410 switch (static_cast<unsigned>(chars)) { | 1488 switch (static_cast<unsigned>(chars)) { |
1411 case 0: | 1489 case 0: |
1412 break; | 1490 break; |
1413 case 1: | 1491 case 1: |
1414 *dest = *src; | 1492 *dest = *src; |
(...skipping 10 matching lines...) Expand all Loading... |
1425 case 5: | 1503 case 5: |
1426 memcpy(dest, src, 10); | 1504 memcpy(dest, src, 10); |
1427 break; | 1505 break; |
1428 case 6: | 1506 case 6: |
1429 memcpy(dest, src, 12); | 1507 memcpy(dest, src, 12); |
1430 break; | 1508 break; |
1431 case 7: | 1509 case 7: |
1432 memcpy(dest, src, 14); | 1510 memcpy(dest, src, 14); |
1433 break; | 1511 break; |
1434 default: | 1512 default: |
1435 OS::MemCopy(dest, src, chars * sizeof(*dest)); | 1513 MemCopy(dest, src, chars * sizeof(*dest)); |
1436 break; | 1514 break; |
1437 } | 1515 } |
1438 } | 1516 } |
1439 | 1517 |
1440 | 1518 |
1441 #elif defined(V8_HOST_ARCH_MIPS) | 1519 #elif defined(V8_HOST_ARCH_MIPS) |
1442 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) { | 1520 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) { |
1443 if (chars < OS::kMinComplexMemCopy) { | 1521 if (chars < kMinComplexMemCopy) { |
1444 memcpy(dest, src, chars); | 1522 memcpy(dest, src, chars); |
1445 } else { | 1523 } else { |
1446 OS::MemCopy(dest, src, chars); | 1524 MemCopy(dest, src, chars); |
1447 } | 1525 } |
1448 } | 1526 } |
1449 | 1527 |
1450 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { | 1528 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { |
1451 if (chars < OS::kMinComplexMemCopy) { | 1529 if (chars < kMinComplexMemCopy) { |
1452 memcpy(dest, src, chars * sizeof(*dest)); | 1530 memcpy(dest, src, chars * sizeof(*dest)); |
1453 } else { | 1531 } else { |
1454 OS::MemCopy(dest, src, chars * sizeof(*dest)); | 1532 MemCopy(dest, src, chars * sizeof(*dest)); |
1455 } | 1533 } |
1456 } | 1534 } |
1457 #endif | 1535 #endif |
1458 | 1536 |
1459 | 1537 |
1460 class StringBuilder : public SimpleStringBuilder { | 1538 class StringBuilder : public SimpleStringBuilder { |
1461 public: | 1539 public: |
1462 explicit StringBuilder(int size) : SimpleStringBuilder(size) { } | 1540 explicit StringBuilder(int size) : SimpleStringBuilder(size) { } |
1463 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { } | 1541 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { } |
1464 | 1542 |
1465 // Add formatted contents to the builder just like printf(). | 1543 // Add formatted contents to the builder just like printf(). |
1466 void AddFormatted(const char* format, ...); | 1544 void AddFormatted(const char* format, ...); |
1467 | 1545 |
1468 // Add formatted contents like printf based on a va_list. | 1546 // Add formatted contents like printf based on a va_list. |
1469 void AddFormattedList(const char* format, va_list list); | 1547 void AddFormattedList(const char* format, va_list list); |
1470 private: | 1548 private: |
1471 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); | 1549 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); |
1472 }; | 1550 }; |
1473 | 1551 |
1474 | 1552 |
1475 } } // namespace v8::internal | 1553 } } // namespace v8::internal |
1476 | 1554 |
1477 #endif // V8_UTILS_H_ | 1555 #endif // V8_UTILS_H_ |
OLD | NEW |