OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 typedef typename C::reverse_iterator reverse_iterator; | 1047 typedef typename C::reverse_iterator reverse_iterator; |
1048 explicit ContainerPointerWrapper(C* container) : container_(container) {} | 1048 explicit ContainerPointerWrapper(C* container) : container_(container) {} |
1049 iterator begin() { return container_->begin(); } | 1049 iterator begin() { return container_->begin(); } |
1050 iterator end() { return container_->end(); } | 1050 iterator end() { return container_->end(); } |
1051 reverse_iterator rbegin() { return container_->rbegin(); } | 1051 reverse_iterator rbegin() { return container_->rbegin(); } |
1052 reverse_iterator rend() { return container_->rend(); } | 1052 reverse_iterator rend() { return container_->rend(); } |
1053 private: | 1053 private: |
1054 C* container_; | 1054 C* container_; |
1055 }; | 1055 }; |
1056 | 1056 |
| 1057 |
| 1058 // ---------------------------------------------------------------------------- |
| 1059 // I/O support. |
| 1060 |
| 1061 #if __GNUC__ >= 4 |
| 1062 // On gcc we can ask the compiler to check the types of %d-style format |
| 1063 // specifiers and their associated arguments. TODO(erikcorry) fix this |
| 1064 // so it works on MacOSX. |
| 1065 #if defined(__MACH__) && defined(__APPLE__) |
| 1066 #define PRINTF_CHECKING |
| 1067 #define FPRINTF_CHECKING |
| 1068 #define PRINTF_METHOD_CHECKING |
| 1069 #define FPRINTF_METHOD_CHECKING |
| 1070 #else // MacOsX. |
| 1071 #define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2))) |
| 1072 #define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3))) |
| 1073 #define PRINTF_METHOD_CHECKING __attribute__ ((format (printf, 2, 3))) |
| 1074 #define FPRINTF_METHOD_CHECKING __attribute__ ((format (printf, 3, 4))) |
| 1075 #endif |
| 1076 #else |
| 1077 #define PRINTF_CHECKING |
| 1078 #define FPRINTF_CHECKING |
| 1079 #define PRINTF_METHOD_CHECKING |
| 1080 #define FPRINTF_METHOD_CHECKING |
| 1081 #endif |
| 1082 |
| 1083 // Our version of printf(). |
| 1084 void PRINTF_CHECKING PrintF(const char* format, ...); |
| 1085 void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...); |
| 1086 |
| 1087 // Prepends the current process ID to the output. |
| 1088 void PRINTF_CHECKING PrintPID(const char* format, ...); |
| 1089 |
| 1090 // Our version of fflush. |
| 1091 void Flush(FILE* out); |
| 1092 |
| 1093 inline void Flush() { |
| 1094 Flush(stdout); |
| 1095 } |
| 1096 |
| 1097 |
| 1098 // Read a line of characters after printing the prompt to stdout. The resulting |
| 1099 // char* needs to be disposed off with DeleteArray by the caller. |
| 1100 char* ReadLine(const char* prompt); |
| 1101 |
| 1102 |
| 1103 // Read and return the raw bytes in a file. the size of the buffer is returned |
| 1104 // in size. |
| 1105 // The returned buffer must be freed by the caller. |
| 1106 byte* ReadBytes(const char* filename, int* size, bool verbose = true); |
| 1107 |
| 1108 |
| 1109 // Append size chars from str to the file given by filename. |
| 1110 // The file is overwritten. Returns the number of chars written. |
| 1111 int AppendChars(const char* filename, |
| 1112 const char* str, |
| 1113 int size, |
| 1114 bool verbose = true); |
| 1115 |
| 1116 |
| 1117 // Write size chars from str to the file given by filename. |
| 1118 // The file is overwritten. Returns the number of chars written. |
| 1119 int WriteChars(const char* filename, |
| 1120 const char* str, |
| 1121 int size, |
| 1122 bool verbose = true); |
| 1123 |
| 1124 |
| 1125 // Write size bytes to the file given by filename. |
| 1126 // The file is overwritten. Returns the number of bytes written. |
| 1127 int WriteBytes(const char* filename, |
| 1128 const byte* bytes, |
| 1129 int size, |
| 1130 bool verbose = true); |
| 1131 |
| 1132 |
| 1133 // Write the C code |
| 1134 // const char* <varname> = "<str>"; |
| 1135 // const int <varname>_len = <len>; |
| 1136 // to the file given by filename. Only the first len chars are written. |
| 1137 int WriteAsCFile(const char* filename, const char* varname, |
| 1138 const char* str, int size, bool verbose = true); |
| 1139 |
| 1140 |
| 1141 // ---------------------------------------------------------------------------- |
| 1142 // Data structures |
| 1143 |
| 1144 template <typename T> |
| 1145 inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms, |
| 1146 int length) { |
| 1147 return Vector< Handle<Object> >( |
| 1148 reinterpret_cast<v8::internal::Handle<Object>*>(elms), length); |
| 1149 } |
| 1150 |
| 1151 |
| 1152 // ---------------------------------------------------------------------------- |
| 1153 // Memory |
| 1154 |
| 1155 // Copies words from |src| to |dst|. The data spans must not overlap. |
| 1156 template <typename T> |
| 1157 inline void CopyWords(T* dst, const T* src, size_t num_words) { |
| 1158 STATIC_ASSERT(sizeof(T) == kPointerSize); |
| 1159 ASSERT(Min(dst, const_cast<T*>(src)) + num_words <= |
| 1160 Max(dst, const_cast<T*>(src))); |
| 1161 ASSERT(num_words > 0); |
| 1162 |
| 1163 // Use block copying OS::MemCopy if the segment we're copying is |
| 1164 // enough to justify the extra call/setup overhead. |
| 1165 static const size_t kBlockCopyLimit = 16; |
| 1166 |
| 1167 if (num_words < kBlockCopyLimit) { |
| 1168 do { |
| 1169 num_words--; |
| 1170 *dst++ = *src++; |
| 1171 } while (num_words > 0); |
| 1172 } else { |
| 1173 OS::MemCopy(dst, src, num_words * kPointerSize); |
| 1174 } |
| 1175 } |
| 1176 |
| 1177 |
| 1178 // Copies words from |src| to |dst|. No restrictions. |
| 1179 template <typename T> |
| 1180 inline void MoveWords(T* dst, const T* src, size_t num_words) { |
| 1181 STATIC_ASSERT(sizeof(T) == kPointerSize); |
| 1182 ASSERT(num_words > 0); |
| 1183 |
| 1184 // Use block copying OS::MemCopy if the segment we're copying is |
| 1185 // enough to justify the extra call/setup overhead. |
| 1186 static const size_t kBlockCopyLimit = 16; |
| 1187 |
| 1188 if (num_words < kBlockCopyLimit && |
| 1189 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) { |
| 1190 T* end = dst + num_words; |
| 1191 do { |
| 1192 num_words--; |
| 1193 *dst++ = *src++; |
| 1194 } while (num_words > 0); |
| 1195 } else { |
| 1196 OS::MemMove(dst, src, num_words * kPointerSize); |
| 1197 } |
| 1198 } |
| 1199 |
| 1200 |
| 1201 // Copies data from |src| to |dst|. The data spans must not overlap. |
| 1202 template <typename T> |
| 1203 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) { |
| 1204 STATIC_ASSERT(sizeof(T) == 1); |
| 1205 ASSERT(Min(dst, const_cast<T*>(src)) + num_bytes <= |
| 1206 Max(dst, const_cast<T*>(src))); |
| 1207 if (num_bytes == 0) return; |
| 1208 |
| 1209 // Use block copying OS::MemCopy if the segment we're copying is |
| 1210 // enough to justify the extra call/setup overhead. |
| 1211 static const int kBlockCopyLimit = OS::kMinComplexMemCopy; |
| 1212 |
| 1213 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) { |
| 1214 do { |
| 1215 num_bytes--; |
| 1216 *dst++ = *src++; |
| 1217 } while (num_bytes > 0); |
| 1218 } else { |
| 1219 OS::MemCopy(dst, src, num_bytes); |
| 1220 } |
| 1221 } |
| 1222 |
| 1223 |
| 1224 template <typename T, typename U> |
| 1225 inline void MemsetPointer(T** dest, U* value, int counter) { |
| 1226 #ifdef DEBUG |
| 1227 T* a = NULL; |
| 1228 U* b = NULL; |
| 1229 a = b; // Fake assignment to check assignability. |
| 1230 USE(a); |
| 1231 #endif // DEBUG |
| 1232 #if V8_HOST_ARCH_IA32 |
| 1233 #define STOS "stosl" |
| 1234 #elif V8_HOST_ARCH_X64 |
| 1235 #define STOS "stosq" |
| 1236 #endif |
| 1237 #if defined(__native_client__) |
| 1238 // This STOS sequence does not validate for x86_64 Native Client. |
| 1239 // Here we #undef STOS to force use of the slower C version. |
| 1240 // TODO(bradchen): Profile V8 and implement a faster REP STOS |
| 1241 // here if the profile indicates it matters. |
| 1242 #undef STOS |
| 1243 #endif |
| 1244 |
| 1245 #if defined(MEMORY_SANITIZER) |
| 1246 // MemorySanitizer does not understand inline assembly. |
| 1247 #undef STOS |
| 1248 #endif |
| 1249 |
| 1250 #if defined(__GNUC__) && defined(STOS) |
| 1251 asm volatile( |
| 1252 "cld;" |
| 1253 "rep ; " STOS |
| 1254 : "+&c" (counter), "+&D" (dest) |
| 1255 : "a" (value) |
| 1256 : "memory", "cc"); |
| 1257 #else |
| 1258 for (int i = 0; i < counter; i++) { |
| 1259 dest[i] = value; |
| 1260 } |
| 1261 #endif |
| 1262 |
| 1263 #undef STOS |
| 1264 } |
| 1265 |
| 1266 |
| 1267 // Simple wrapper that allows an ExternalString to refer to a |
| 1268 // Vector<const char>. Doesn't assume ownership of the data. |
| 1269 class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource { |
| 1270 public: |
| 1271 explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {} |
| 1272 |
| 1273 virtual const char* data() const { return data_.start(); } |
| 1274 |
| 1275 virtual size_t length() const { return data_.length(); } |
| 1276 |
| 1277 private: |
| 1278 Vector<const char> data_; |
| 1279 }; |
| 1280 |
| 1281 |
| 1282 // Simple support to read a file into a 0-terminated C-string. |
| 1283 // The returned buffer must be freed by the caller. |
| 1284 // On return, *exits tells whether the file existed. |
| 1285 Vector<const char> ReadFile(const char* filename, |
| 1286 bool* exists, |
| 1287 bool verbose = true); |
| 1288 Vector<const char> ReadFile(FILE* file, |
| 1289 bool* exists, |
| 1290 bool verbose = true); |
| 1291 |
| 1292 |
| 1293 template <typename sourcechar, typename sinkchar> |
| 1294 INLINE(static void CopyCharsUnsigned(sinkchar* dest, |
| 1295 const sourcechar* src, |
| 1296 int chars)); |
| 1297 #if defined(V8_HOST_ARCH_ARM) |
| 1298 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars)); |
| 1299 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars)); |
| 1300 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars)); |
| 1301 #elif defined(V8_HOST_ARCH_MIPS) |
| 1302 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars)); |
| 1303 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars)); |
| 1304 #endif |
| 1305 |
| 1306 // Copy from ASCII/16bit chars to ASCII/16bit chars. |
| 1307 template <typename sourcechar, typename sinkchar> |
| 1308 INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars)); |
| 1309 |
| 1310 template<typename sourcechar, typename sinkchar> |
| 1311 void CopyChars(sinkchar* dest, const sourcechar* src, int chars) { |
| 1312 ASSERT(sizeof(sourcechar) <= 2); |
| 1313 ASSERT(sizeof(sinkchar) <= 2); |
| 1314 if (sizeof(sinkchar) == 1) { |
| 1315 if (sizeof(sourcechar) == 1) { |
| 1316 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest), |
| 1317 reinterpret_cast<const uint8_t*>(src), |
| 1318 chars); |
| 1319 } else { |
| 1320 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest), |
| 1321 reinterpret_cast<const uint16_t*>(src), |
| 1322 chars); |
| 1323 } |
| 1324 } else { |
| 1325 if (sizeof(sourcechar) == 1) { |
| 1326 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest), |
| 1327 reinterpret_cast<const uint8_t*>(src), |
| 1328 chars); |
| 1329 } else { |
| 1330 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest), |
| 1331 reinterpret_cast<const uint16_t*>(src), |
| 1332 chars); |
| 1333 } |
| 1334 } |
| 1335 } |
| 1336 |
| 1337 template <typename sourcechar, typename sinkchar> |
| 1338 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) { |
| 1339 sinkchar* limit = dest + chars; |
| 1340 #ifdef V8_HOST_CAN_READ_UNALIGNED |
| 1341 if (sizeof(*dest) == sizeof(*src)) { |
| 1342 if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) { |
| 1343 OS::MemCopy(dest, src, chars * sizeof(*dest)); |
| 1344 return; |
| 1345 } |
| 1346 // Number of characters in a uintptr_t. |
| 1347 static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT |
| 1348 ASSERT(dest + kStepSize > dest); // Check for overflow. |
| 1349 while (dest + kStepSize <= limit) { |
| 1350 *reinterpret_cast<uintptr_t*>(dest) = |
| 1351 *reinterpret_cast<const uintptr_t*>(src); |
| 1352 dest += kStepSize; |
| 1353 src += kStepSize; |
| 1354 } |
| 1355 } |
| 1356 #endif |
| 1357 while (dest < limit) { |
| 1358 *dest++ = static_cast<sinkchar>(*src++); |
| 1359 } |
| 1360 } |
| 1361 |
| 1362 |
| 1363 #if defined(V8_HOST_ARCH_ARM) |
| 1364 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) { |
| 1365 switch (static_cast<unsigned>(chars)) { |
| 1366 case 0: |
| 1367 break; |
| 1368 case 1: |
| 1369 *dest = *src; |
| 1370 break; |
| 1371 case 2: |
| 1372 memcpy(dest, src, 2); |
| 1373 break; |
| 1374 case 3: |
| 1375 memcpy(dest, src, 3); |
| 1376 break; |
| 1377 case 4: |
| 1378 memcpy(dest, src, 4); |
| 1379 break; |
| 1380 case 5: |
| 1381 memcpy(dest, src, 5); |
| 1382 break; |
| 1383 case 6: |
| 1384 memcpy(dest, src, 6); |
| 1385 break; |
| 1386 case 7: |
| 1387 memcpy(dest, src, 7); |
| 1388 break; |
| 1389 case 8: |
| 1390 memcpy(dest, src, 8); |
| 1391 break; |
| 1392 case 9: |
| 1393 memcpy(dest, src, 9); |
| 1394 break; |
| 1395 case 10: |
| 1396 memcpy(dest, src, 10); |
| 1397 break; |
| 1398 case 11: |
| 1399 memcpy(dest, src, 11); |
| 1400 break; |
| 1401 case 12: |
| 1402 memcpy(dest, src, 12); |
| 1403 break; |
| 1404 case 13: |
| 1405 memcpy(dest, src, 13); |
| 1406 break; |
| 1407 case 14: |
| 1408 memcpy(dest, src, 14); |
| 1409 break; |
| 1410 case 15: |
| 1411 memcpy(dest, src, 15); |
| 1412 break; |
| 1413 default: |
| 1414 OS::MemCopy(dest, src, chars); |
| 1415 break; |
| 1416 } |
| 1417 } |
| 1418 |
| 1419 |
| 1420 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) { |
| 1421 if (chars >= OS::kMinComplexConvertMemCopy) { |
| 1422 OS::MemCopyUint16Uint8(dest, src, chars); |
| 1423 } else { |
| 1424 OS::MemCopyUint16Uint8Wrapper(dest, src, chars); |
| 1425 } |
| 1426 } |
| 1427 |
| 1428 |
| 1429 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { |
| 1430 switch (static_cast<unsigned>(chars)) { |
| 1431 case 0: |
| 1432 break; |
| 1433 case 1: |
| 1434 *dest = *src; |
| 1435 break; |
| 1436 case 2: |
| 1437 memcpy(dest, src, 4); |
| 1438 break; |
| 1439 case 3: |
| 1440 memcpy(dest, src, 6); |
| 1441 break; |
| 1442 case 4: |
| 1443 memcpy(dest, src, 8); |
| 1444 break; |
| 1445 case 5: |
| 1446 memcpy(dest, src, 10); |
| 1447 break; |
| 1448 case 6: |
| 1449 memcpy(dest, src, 12); |
| 1450 break; |
| 1451 case 7: |
| 1452 memcpy(dest, src, 14); |
| 1453 break; |
| 1454 default: |
| 1455 OS::MemCopy(dest, src, chars * sizeof(*dest)); |
| 1456 break; |
| 1457 } |
| 1458 } |
| 1459 |
| 1460 |
| 1461 #elif defined(V8_HOST_ARCH_MIPS) |
| 1462 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) { |
| 1463 if (chars < OS::kMinComplexMemCopy) { |
| 1464 memcpy(dest, src, chars); |
| 1465 } else { |
| 1466 OS::MemCopy(dest, src, chars); |
| 1467 } |
| 1468 } |
| 1469 |
| 1470 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) { |
| 1471 if (chars < OS::kMinComplexMemCopy) { |
| 1472 memcpy(dest, src, chars * sizeof(*dest)); |
| 1473 } else { |
| 1474 OS::MemCopy(dest, src, chars * sizeof(*dest)); |
| 1475 } |
| 1476 } |
| 1477 #endif |
| 1478 |
| 1479 |
| 1480 class StringBuilder : public SimpleStringBuilder { |
| 1481 public: |
| 1482 explicit StringBuilder(int size) : SimpleStringBuilder(size) { } |
| 1483 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { } |
| 1484 |
| 1485 // Add formatted contents to the builder just like printf(). |
| 1486 void AddFormatted(const char* format, ...); |
| 1487 |
| 1488 // Add formatted contents like printf based on a va_list. |
| 1489 void AddFormattedList(const char* format, va_list list); |
| 1490 private: |
| 1491 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); |
| 1492 }; |
| 1493 |
| 1494 |
1057 } } // namespace v8::internal | 1495 } } // namespace v8::internal |
1058 | 1496 |
1059 #endif // V8_UTILS_H_ | 1497 #endif // V8_UTILS_H_ |
OLD | NEW |