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 | |
1495 } } // namespace v8::internal | 1057 } } // namespace v8::internal |
1496 | 1058 |
1497 #endif // V8_UTILS_H_ | 1059 #endif // V8_UTILS_H_ |
OLD | NEW |