Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE; | 107 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE; |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 bool Object::IsString() { | 111 bool Object::IsString() { |
| 112 return Object::IsHeapObject() | 112 return Object::IsHeapObject() |
| 113 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE; | 113 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE; |
| 114 } | 114 } |
| 115 | 115 |
| 116 | 116 |
| 117 bool Object::IsSymbol() { | |
| 118 if (this->IsSmi()) return false; | |
| 119 uint32_t type = HeapObject::cast(this)->map()->instance_type(); | |
| 120 return (type & (kIsNotStringMask | kIsSymbolMask)) == | |
| 121 (kStringTag | kSymbolTag); | |
| 122 } | |
| 123 | |
| 124 | |
| 125 bool Object::IsConsString() { | |
| 126 uint32_t type = HeapObject::cast(this)->map()->instance_type(); | |
| 127 return (type & (kIsNotStringMask | kStringRepresentationMask)) == | |
| 128 (kStringTag | kConsStringTag); | |
| 129 } | |
| 130 | |
| 131 | |
| 132 #ifdef DEBUG | |
| 133 // These are for cast checks. If you need one of these in release | |
| 134 // mode you should consider using a StringShape before moving it out | |
| 135 // of the ifdef | |
| 136 | |
| 117 bool Object::IsSeqString() { | 137 bool Object::IsSeqString() { |
|
Mads Ager (chromium)
2008/11/03 08:45:49
Is it too expensive to use StringShapes for these?
| |
| 118 return IsString() | 138 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 119 && (String::cast(this)->representation_tag() == kSeqStringTag); | 139 type &= kIsNotStringMask | kStringRepresentationMask; |
| 140 return type == (kStringTag | kSeqStringTag); | |
| 120 } | 141 } |
| 121 | 142 |
| 122 | 143 |
| 123 bool Object::IsSeqAsciiString() { | 144 bool Object::IsSeqAsciiString() { |
| 124 return IsSeqString() | 145 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 125 && String::cast(this)->IsAsciiRepresentation(); | 146 type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 126 } | 147 return type == (kStringTag | kSeqStringTag | kAsciiStringTag); |
| 127 | |
| 128 | |
| 129 bool String::IsSeqAsciiString() { | |
| 130 return (this->representation_tag() == kSeqStringTag) | |
| 131 && is_ascii_representation(); | |
| 132 } | 148 } |
| 133 | 149 |
| 134 | 150 |
| 135 bool Object::IsSeqTwoByteString() { | 151 bool Object::IsSeqTwoByteString() { |
| 136 return IsSeqString() | 152 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 137 && !String::cast(this)->IsAsciiRepresentation(); | 153 type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 154 return type == (kStringTag | kSeqStringTag | kTwoByteStringTag); | |
| 138 } | 155 } |
| 139 | 156 |
| 140 | 157 |
| 141 bool Object::IsAsciiStringRepresentation() { | 158 bool Object::IsExternalString() { |
| 142 return IsString() && (String::cast(this)->is_ascii_representation()); | 159 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 160 type &= kIsNotStringMask | kStringRepresentationMask; | |
| 161 return type == (kStringTag | kExternalStringTag); | |
| 143 } | 162 } |
| 144 | 163 |
| 145 | 164 |
| 146 bool Object::IsTwoByteStringRepresentation() { | 165 bool Object::IsExternalAsciiString() { |
| 147 return IsString() && (!String::cast(this)->is_ascii_representation()); | 166 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 167 type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | |
| 168 return type == (kStringTag | kExternalStringTag | kAsciiStringTag); | |
| 148 } | 169 } |
| 149 | 170 |
| 150 | 171 |
| 151 bool Object::IsConsString() { | 172 bool Object::IsExternalTwoByteString() { |
| 152 return IsString() | 173 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 153 && (String::cast(this)->representation_tag() == kConsStringTag); | 174 type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 175 return type == (kStringTag | kExternalStringTag | kTwoByteStringTag); | |
| 154 } | 176 } |
| 155 | 177 |
| 156 | 178 |
| 157 bool Object::IsSlicedString() { | 179 bool Object::IsSlicedString() { |
| 158 return IsString() | 180 uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| 159 && (String::cast(this)->representation_tag() == kSlicedStringTag); | 181 type &= kIsNotStringMask | kStringRepresentationMask; |
| 182 return type == (kStringTag | kSlicedStringTag); | |
| 160 } | 183 } |
| 161 | 184 |
| 162 | 185 |
| 163 bool Object::IsExternalString() { | 186 #endif // DEBUG |
| 164 return IsString() | 187 |
| 165 && (String::cast(this)->representation_tag() == kExternalStringTag); | 188 |
| 189 StringShape::StringShape(String* str) : | |
| 190 type_(str->map()->instance_type()) { | |
| 191 ASSERT((type_ & kIsNotStringMask) == kStringTag); | |
| 166 } | 192 } |
| 167 | 193 |
| 168 | 194 |
| 169 bool Object::IsExternalAsciiString() { | 195 StringShape::StringShape(Map* map) : |
| 170 return IsExternalString() && (String::cast(this)->is_ascii_representation()); | 196 type_(map->instance_type()) { |
| 197 ASSERT((type_ & kIsNotStringMask) == kStringTag); | |
| 171 } | 198 } |
| 172 | 199 |
| 173 | 200 |
| 174 bool Object::IsExternalTwoByteString() { | 201 StringShape::StringShape(InstanceType t) : |
| 175 return IsExternalString() && (!String::cast(this)->is_ascii_representation()); | 202 type_(static_cast<uint32_t>(t)) { |
| 203 ASSERT((type_ & kIsNotStringMask) == kStringTag); | |
| 176 } | 204 } |
| 177 | 205 |
| 178 | 206 |
| 179 bool Object::IsShortString() { | 207 bool StringShape::IsSymbol() { |
| 180 return IsString() && (String::cast(this)->size_tag() == kShortStringTag); | 208 return (type_ & kIsSymbolMask) == kSymbolTag; |
| 181 } | 209 } |
| 182 | 210 |
| 183 | 211 |
| 184 bool Object::IsMediumString() { | 212 bool StringShape::IsAsciiRepresentation() { |
| 185 return IsString() && (String::cast(this)->size_tag() == kMediumStringTag); | 213 return (type_ & kStringEncodingMask) == kAsciiStringTag; |
| 186 } | 214 } |
| 187 | 215 |
| 188 | 216 |
| 189 bool Object::IsLongString() { | 217 bool StringShape::IsTwoByteRepresentation() { |
| 190 return IsString() && (String::cast(this)->size_tag() == kLongStringTag); | 218 return (type_ & kStringEncodingMask) == kTwoByteStringTag; |
| 191 } | 219 } |
| 192 | 220 |
| 193 | 221 |
| 194 bool Object::IsSymbol() { | 222 bool StringShape::IsCons() { |
| 195 return IsString() && (String::cast(this)->is_symbol()); | 223 return (type_ & kStringRepresentationMask) == kConsStringTag; |
| 224 } | |
| 225 | |
| 226 | |
| 227 bool StringShape::IsSliced() { | |
| 228 return (type_ & kStringRepresentationMask) == kSlicedStringTag; | |
| 229 } | |
| 230 | |
| 231 | |
| 232 bool StringShape::IsExternal() { | |
| 233 return (type_ & kStringRepresentationMask) == kExternalStringTag; | |
| 234 } | |
| 235 | |
| 236 | |
| 237 bool StringShape::IsSequential() { | |
| 238 return (type_ & kStringRepresentationMask) == kSeqStringTag; | |
| 239 } | |
| 240 | |
| 241 | |
| 242 StringRepresentationTag StringShape::representation_tag() { | |
| 243 uint32_t tag = (type_ & kStringRepresentationMask); | |
| 244 return static_cast<StringRepresentationTag>(tag); | |
| 245 } | |
| 246 | |
| 247 | |
| 248 uint32_t StringShape::full_representation_tag() { | |
| 249 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); | |
| 250 } | |
| 251 | |
| 252 | |
| 253 uint32_t StringShape::size_tag() { | |
| 254 return (type_ & kStringSizeMask); | |
| 255 } | |
| 256 | |
| 257 | |
| 258 bool StringShape::IsSequentialAscii() { | |
| 259 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag); | |
| 260 } | |
| 261 | |
| 262 | |
| 263 bool StringShape::IsSequentialTwoByte() { | |
| 264 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) == | |
| 265 (kSeqStringTag | kTwoByteStringTag); | |
| 266 } | |
| 267 | |
| 268 | |
| 269 bool StringShape::IsExternalAscii() { | |
| 270 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag); | |
| 271 } | |
| 272 | |
| 273 | |
| 274 bool StringShape::IsExternalTwoByte() { | |
| 275 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) == | |
| 276 (kExternalStringTag | kTwoByteStringTag); | |
| 196 } | 277 } |
| 197 | 278 |
| 198 | 279 |
| 199 bool Object::IsNumber() { | 280 bool Object::IsNumber() { |
| 200 return IsSmi() || IsHeapNumber(); | 281 return IsSmi() || IsHeapNumber(); |
| 201 } | 282 } |
| 202 | 283 |
| 203 | 284 |
| 204 bool Object::IsByteArray() { | 285 bool Object::IsByteArray() { |
| 205 return Object::IsHeapObject() | 286 return Object::IsHeapObject() |
| (...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1121 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { | 1202 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { |
| 1122 Object* tmp = array->get(first); | 1203 Object* tmp = array->get(first); |
| 1123 fast_set(array, first, array->get(second)); | 1204 fast_set(array, first, array->get(second)); |
| 1124 fast_set(array, second, tmp); | 1205 fast_set(array, second, tmp); |
| 1125 } | 1206 } |
| 1126 | 1207 |
| 1127 | 1208 |
| 1128 int DescriptorArray::Search(String* name) { | 1209 int DescriptorArray::Search(String* name) { |
| 1129 SLOW_ASSERT(IsSortedNoDuplicates()); | 1210 SLOW_ASSERT(IsSortedNoDuplicates()); |
| 1130 | 1211 |
| 1212 StringShape shape(name); | |
| 1213 | |
| 1131 // Check for empty descriptor array. | 1214 // Check for empty descriptor array. |
| 1132 int nof = number_of_descriptors(); | 1215 int nof = number_of_descriptors(); |
| 1133 if (nof == 0) return kNotFound; | 1216 if (nof == 0) return kNotFound; |
| 1134 | 1217 |
| 1135 // Fast case: do linear search for small arrays. | 1218 // Fast case: do linear search for small arrays. |
| 1136 const int kMaxElementsForLinearSearch = 8; | 1219 const int kMaxElementsForLinearSearch = 8; |
| 1137 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) { | 1220 if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) { |
| 1138 return LinearSearch(name, nof); | 1221 return LinearSearch(name, nof); |
| 1139 } | 1222 } |
| 1140 | 1223 |
| 1141 // Slow case: perform binary search. | 1224 // Slow case: perform binary search. |
| 1142 return BinarySearch(name, 0, nof - 1); | 1225 return BinarySearch(name, 0, nof - 1); |
| 1143 } | 1226 } |
| 1144 | 1227 |
| 1145 | 1228 |
| 1146 | 1229 |
| 1147 String* DescriptorArray::GetKey(int descriptor_number) { | 1230 String* DescriptorArray::GetKey(int descriptor_number) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1261 ASSERT(obj->IsHashTable()); | 1344 ASSERT(obj->IsHashTable()); |
| 1262 return reinterpret_cast<HashTable*>(obj); | 1345 return reinterpret_cast<HashTable*>(obj); |
| 1263 } | 1346 } |
| 1264 | 1347 |
| 1265 | 1348 |
| 1266 INT_ACCESSORS(Array, length, kLengthOffset) | 1349 INT_ACCESSORS(Array, length, kLengthOffset) |
| 1267 | 1350 |
| 1268 | 1351 |
| 1269 bool String::Equals(String* other) { | 1352 bool String::Equals(String* other) { |
| 1270 if (other == this) return true; | 1353 if (other == this) return true; |
| 1271 if (IsSymbol() && other->IsSymbol()) return false; | 1354 StringShape this_shape(this); |
| 1272 return SlowEquals(other); | 1355 StringShape other_shape(other); |
| 1356 if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false; | |
| 1357 return SlowEquals(this_shape, other, other_shape); | |
| 1273 } | 1358 } |
| 1274 | 1359 |
| 1275 | 1360 |
| 1276 int String::length() { | 1361 int String::length(StringShape shape) { |
| 1362 ASSERT(shape.type() == StringShape(this).type()); | |
| 1277 uint32_t len = READ_INT_FIELD(this, kLengthOffset); | 1363 uint32_t len = READ_INT_FIELD(this, kLengthOffset); |
| 1278 | 1364 |
| 1279 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1365 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
| 1280 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1366 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
| 1281 ASSERT(kLongStringTag == 0); | 1367 ASSERT(kLongStringTag == 0); |
| 1282 | 1368 |
| 1283 return len >> (size_tag() + kLongLengthShift); | 1369 return len >> (shape.size_tag() + kLongLengthShift); |
| 1370 } | |
| 1371 | |
| 1372 | |
| 1373 int String::length() { | |
| 1374 return length(StringShape(this)); | |
| 1284 } | 1375 } |
| 1285 | 1376 |
| 1286 | 1377 |
| 1287 void String::set_length(int value) { | 1378 void String::set_length(int value) { |
| 1288 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1379 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
| 1289 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1380 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
| 1290 ASSERT(kLongStringTag == 0); | 1381 ASSERT(kLongStringTag == 0); |
| 1291 | 1382 |
| 1383 StringShape shape(this); | |
| 1292 WRITE_INT_FIELD(this, | 1384 WRITE_INT_FIELD(this, |
| 1293 kLengthOffset, | 1385 kLengthOffset, |
| 1294 value << (size_tag() + kLongLengthShift)); | 1386 value << (shape.size_tag() + kLongLengthShift)); |
| 1295 } | 1387 } |
| 1296 | 1388 |
| 1297 | 1389 |
| 1298 uint32_t String::length_field() { | 1390 uint32_t String::length_field() { |
| 1299 return READ_UINT32_FIELD(this, kLengthOffset); | 1391 return READ_UINT32_FIELD(this, kLengthOffset); |
| 1300 } | 1392 } |
| 1301 | 1393 |
| 1302 | 1394 |
| 1303 void String::set_length_field(uint32_t value) { | 1395 void String::set_length_field(uint32_t value) { |
| 1304 WRITE_UINT32_FIELD(this, kLengthOffset, value); | 1396 WRITE_UINT32_FIELD(this, kLengthOffset, value); |
| 1305 } | 1397 } |
| 1306 | 1398 |
| 1307 | 1399 |
| 1308 void String::TryFlatten() { | 1400 void String::TryFlatten(StringShape shape) { |
| 1401 ASSERT(shape.type() == StringShape(this).type()); | |
| 1309 // We don't need to flatten strings that are already flat. Since this code | 1402 // We don't need to flatten strings that are already flat. Since this code |
| 1310 // is inlined, it can be helpful in the flat case to not call out to Flatten. | 1403 // is inlined, it can be helpful in the flat case to not call out to Flatten. |
| 1311 StringRepresentationTag str_type = representation_tag(); | 1404 if (!IsFlat(shape)) { |
| 1312 if (str_type != kSeqStringTag && str_type != kExternalStringTag) { | 1405 Flatten(shape); |
| 1313 Flatten(); | |
| 1314 } | 1406 } |
| 1315 } | 1407 } |
| 1316 | 1408 |
| 1317 | 1409 |
| 1318 uint16_t String::Get(int index) { | 1410 uint16_t String::Get(StringShape shape, int index) { |
| 1319 ASSERT(index >= 0 && index < length()); | 1411 ASSERT(shape.type() == StringShape(this).type()); |
| 1320 switch (representation_tag()) { | 1412 ASSERT(index >= 0 && index < length(shape)); |
| 1321 case kSeqStringTag: | 1413 switch (shape.full_representation_tag()) { |
| 1322 return is_ascii_representation() | 1414 case kSeqStringTag | kAsciiStringTag: |
| 1323 ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index) | 1415 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); |
| 1324 : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); | 1416 case kSeqStringTag | kTwoByteStringTag: |
| 1325 case kConsStringTag: | 1417 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); |
| 1418 case kConsStringTag | kAsciiStringTag: | |
| 1419 case kConsStringTag | kTwoByteStringTag: | |
| 1326 return ConsString::cast(this)->ConsStringGet(index); | 1420 return ConsString::cast(this)->ConsStringGet(index); |
| 1327 case kSlicedStringTag: | 1421 case kSlicedStringTag | kAsciiStringTag: |
| 1422 case kSlicedStringTag | kTwoByteStringTag: | |
| 1328 return SlicedString::cast(this)->SlicedStringGet(index); | 1423 return SlicedString::cast(this)->SlicedStringGet(index); |
| 1329 case kExternalStringTag: | 1424 case kExternalStringTag | kAsciiStringTag: |
| 1330 return is_ascii_representation() | 1425 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); |
| 1331 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index) | 1426 case kExternalStringTag | kTwoByteStringTag: |
| 1332 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); | 1427 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); |
| 1333 default: | 1428 default: |
| 1334 break; | 1429 break; |
| 1335 } | 1430 } |
| 1336 | 1431 |
| 1337 UNREACHABLE(); | 1432 UNREACHABLE(); |
| 1338 return 0; | 1433 return 0; |
| 1339 } | 1434 } |
| 1340 | 1435 |
| 1341 | 1436 |
| 1342 void String::Set(int index, uint16_t value) { | 1437 void String::Set(StringShape shape, int index, uint16_t value) { |
| 1343 ASSERT(index >= 0 && index < length()); | 1438 ASSERT(shape.type() == StringShape(this).type()); |
| 1344 ASSERT(IsSeqString()); | 1439 ASSERT(shape.type() == StringShape(this).type()); |
| 1440 ASSERT(index >= 0 && index < length(shape)); | |
| 1441 ASSERT(shape.IsSequential()); | |
| 1345 | 1442 |
| 1346 return is_ascii_representation() | 1443 return shape.IsAsciiRepresentation() |
| 1347 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) | 1444 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) |
| 1348 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); | 1445 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); |
| 1349 } | 1446 } |
| 1350 | 1447 |
| 1351 | 1448 |
| 1352 bool String::IsAsciiRepresentation() { | 1449 bool String::IsFlat(StringShape shape) { |
| 1353 return is_ascii_representation(); | 1450 ASSERT(shape.type() == StringShape(this).type()); |
| 1354 } | 1451 switch (shape.representation_tag()) { |
| 1355 | 1452 case kConsStringTag: { |
| 1356 | 1453 String* second = ConsString::cast(this)->second(); |
| 1357 bool String::StringIsConsString() { | |
| 1358 return representation_tag() == kConsStringTag; | |
| 1359 } | |
| 1360 | |
| 1361 | |
| 1362 bool String::StringIsSlicedString() { | |
| 1363 return representation_tag() == kSlicedStringTag; | |
| 1364 } | |
| 1365 | |
| 1366 | |
| 1367 uint32_t String::size_tag() { | |
| 1368 return map_size_tag(map()); | |
| 1369 } | |
| 1370 | |
| 1371 | |
| 1372 uint32_t String::map_size_tag(Map* map) { | |
| 1373 return map->instance_type() & kStringSizeMask; | |
| 1374 } | |
| 1375 | |
| 1376 | |
| 1377 bool String::is_symbol() { | |
| 1378 return is_symbol_map(map()); | |
| 1379 } | |
| 1380 | |
| 1381 | |
| 1382 bool String::is_symbol_map(Map* map) { | |
| 1383 return (map->instance_type() & kIsSymbolMask) != 0; | |
| 1384 } | |
| 1385 | |
| 1386 | |
| 1387 bool String::is_ascii_representation() { | |
| 1388 return is_ascii_representation_map(map()); | |
| 1389 } | |
| 1390 | |
| 1391 | |
| 1392 bool String::is_ascii_representation_map(Map* map) { | |
| 1393 return (map->instance_type() & kStringEncodingMask) != 0; | |
| 1394 } | |
| 1395 | |
| 1396 | |
| 1397 int String::full_representation_tag() { | |
| 1398 return map()->instance_type() & | |
| 1399 (kStringRepresentationMask | kStringEncodingMask); | |
| 1400 } | |
| 1401 | |
| 1402 | |
| 1403 StringRepresentationTag String::representation_tag() { | |
| 1404 return map_representation_tag(map()); | |
| 1405 } | |
| 1406 | |
| 1407 | |
| 1408 StringRepresentationTag String::map_representation_tag(Map* map) { | |
| 1409 uint32_t tag = map->instance_type() & kStringRepresentationMask; | |
| 1410 return static_cast<StringRepresentationTag>(tag); | |
| 1411 } | |
| 1412 | |
| 1413 | |
| 1414 bool String::IsFlat() { | |
| 1415 switch (this->representation_tag()) { | |
| 1416 case kConsStringTag: | |
| 1417 // Only flattened strings have second part empty. | 1454 // Only flattened strings have second part empty. |
| 1418 return String::cast(ConsString::cast(this)->second())->length() == 0; | 1455 return second->length() == 0; |
| 1456 } | |
| 1419 case kSlicedStringTag: { | 1457 case kSlicedStringTag: { |
| 1420 String* slice = String::cast(SlicedString::cast(this)->buffer()); | 1458 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer()); |
| 1421 StringRepresentationTag tag = slice->representation_tag(); | 1459 StringRepresentationTag tag = slice_shape.representation_tag(); |
| 1422 return tag == kSeqStringTag || tag == kExternalStringTag; | 1460 return tag == kSeqStringTag || tag == kExternalStringTag; |
| 1423 } | 1461 } |
| 1424 default: | 1462 default: |
| 1425 return true; | 1463 return true; |
| 1426 } | 1464 } |
| 1427 } | 1465 } |
| 1428 | 1466 |
| 1429 | 1467 |
| 1430 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { | 1468 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { |
| 1431 ASSERT(index >= 0 && index < length()); | 1469 ASSERT(index >= 0 && index < length()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1465 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); | 1503 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); |
| 1466 } | 1504 } |
| 1467 | 1505 |
| 1468 | 1506 |
| 1469 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { | 1507 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { |
| 1470 ASSERT(index >= 0 && index < length()); | 1508 ASSERT(index >= 0 && index < length()); |
| 1471 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); | 1509 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); |
| 1472 } | 1510 } |
| 1473 | 1511 |
| 1474 | 1512 |
| 1475 int SeqTwoByteString::SeqTwoByteStringSize(Map* map) { | 1513 int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) { |
| 1476 uint32_t length = READ_INT_FIELD(this, kLengthOffset); | 1514 uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
| 1477 | 1515 |
| 1478 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1516 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
| 1479 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1517 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
| 1480 ASSERT(kLongStringTag == 0); | 1518 ASSERT(kLongStringTag == 0); |
| 1481 | 1519 |
| 1482 // Use the map (and not 'this') to compute the size tag, since | 1520 // Use the map (and not 'this') to compute the size tag, since |
| 1483 // TwoByteStringSize is called during GC when maps are encoded. | 1521 // TwoByteStringSize is called during GC when maps are encoded. |
| 1484 length >>= map_size_tag(map) + kLongLengthShift; | 1522 length >>= shape.size_tag() + kLongLengthShift; |
| 1485 | 1523 |
| 1486 return SizeFor(length); | 1524 return SizeFor(length); |
| 1487 } | 1525 } |
| 1488 | 1526 |
| 1489 | 1527 |
| 1490 int SeqAsciiString::SeqAsciiStringSize(Map* map) { | 1528 int SeqAsciiString::SeqAsciiStringSize(StringShape shape) { |
| 1491 uint32_t length = READ_INT_FIELD(this, kLengthOffset); | 1529 uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
| 1492 | 1530 |
| 1493 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1531 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
| 1494 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1532 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
| 1495 ASSERT(kLongStringTag == 0); | 1533 ASSERT(kLongStringTag == 0); |
| 1496 | 1534 |
| 1497 // Use the map (and not 'this') to compute the size tag, since | 1535 // Use the map (and not 'this') to compute the size tag, since |
| 1498 // AsciiStringSize is called during GC when maps are encoded. | 1536 // AsciiStringSize is called during GC when maps are encoded. |
| 1499 length >>= map_size_tag(map) + kLongLengthShift; | 1537 length >>= shape.size_tag() + kLongLengthShift; |
| 1500 | 1538 |
| 1501 return SizeFor(length); | 1539 return SizeFor(length); |
| 1502 } | 1540 } |
| 1503 | 1541 |
| 1504 | 1542 |
| 1505 Object* ConsString::first() { | 1543 String* ConsString::first() { |
| 1544 return String::cast(READ_FIELD(this, kFirstOffset)); | |
| 1545 } | |
| 1546 | |
| 1547 | |
| 1548 Object* ConsString::unchecked_first() { | |
| 1506 return READ_FIELD(this, kFirstOffset); | 1549 return READ_FIELD(this, kFirstOffset); |
| 1507 } | 1550 } |
| 1508 | 1551 |
| 1509 | 1552 |
| 1510 void ConsString::set_first(Object* value, WriteBarrierMode mode) { | 1553 void ConsString::set_first(String* value, WriteBarrierMode mode) { |
| 1511 WRITE_FIELD(this, kFirstOffset, value); | 1554 WRITE_FIELD(this, kFirstOffset, value); |
| 1512 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode); | 1555 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode); |
| 1513 } | 1556 } |
| 1514 | 1557 |
| 1515 | 1558 |
| 1516 Object* ConsString::second() { | 1559 String* ConsString::second() { |
| 1560 return String::cast(READ_FIELD(this, kSecondOffset)); | |
| 1561 } | |
| 1562 | |
| 1563 | |
| 1564 Object* ConsString::unchecked_second() { | |
| 1517 return READ_FIELD(this, kSecondOffset); | 1565 return READ_FIELD(this, kSecondOffset); |
| 1518 } | 1566 } |
| 1519 | 1567 |
| 1520 | 1568 |
| 1521 void ConsString::set_second(Object* value, WriteBarrierMode mode) { | 1569 void ConsString::set_second(String* value, WriteBarrierMode mode) { |
| 1522 WRITE_FIELD(this, kSecondOffset, value); | 1570 WRITE_FIELD(this, kSecondOffset, value); |
| 1523 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode); | 1571 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode); |
| 1524 } | 1572 } |
| 1525 | 1573 |
| 1526 | 1574 |
| 1527 Object* SlicedString::buffer() { | 1575 String* SlicedString::buffer() { |
| 1528 return READ_FIELD(this, kBufferOffset); | 1576 return String::cast(READ_FIELD(this, kBufferOffset)); |
| 1529 } | 1577 } |
| 1530 | 1578 |
| 1531 | 1579 |
| 1532 void SlicedString::set_buffer(Object* buffer) { | 1580 void SlicedString::set_buffer(String* buffer) { |
| 1533 WRITE_FIELD(this, kBufferOffset, buffer); | 1581 WRITE_FIELD(this, kBufferOffset, buffer); |
| 1534 WRITE_BARRIER(this, kBufferOffset); | 1582 WRITE_BARRIER(this, kBufferOffset); |
| 1535 } | 1583 } |
| 1536 | 1584 |
| 1537 | 1585 |
| 1538 int SlicedString::start() { | 1586 int SlicedString::start() { |
| 1539 return READ_INT_FIELD(this, kStartOffset); | 1587 return READ_INT_FIELD(this, kStartOffset); |
| 1540 } | 1588 } |
| 1541 | 1589 |
| 1542 | 1590 |
| (...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2360 #undef WRITE_INT_FIELD | 2408 #undef WRITE_INT_FIELD |
| 2361 #undef READ_SHORT_FIELD | 2409 #undef READ_SHORT_FIELD |
| 2362 #undef WRITE_SHORT_FIELD | 2410 #undef WRITE_SHORT_FIELD |
| 2363 #undef READ_BYTE_FIELD | 2411 #undef READ_BYTE_FIELD |
| 2364 #undef WRITE_BYTE_FIELD | 2412 #undef WRITE_BYTE_FIELD |
| 2365 | 2413 |
| 2366 | 2414 |
| 2367 } } // namespace v8::internal | 2415 } } // namespace v8::internal |
| 2368 | 2416 |
| 2369 #endif // V8_OBJECTS_INL_H_ | 2417 #endif // V8_OBJECTS_INL_H_ |
| OLD | NEW |