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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 // of the ifdef | 136 // of the ifdef |
137 | 137 |
138 bool Object::IsSeqString() { | 138 bool Object::IsSeqString() { |
139 if (!IsString()) return false; | 139 if (!IsString()) return false; |
140 return StringShape(String::cast(this)).IsSequential(); | 140 return StringShape(String::cast(this)).IsSequential(); |
141 } | 141 } |
142 | 142 |
143 | 143 |
144 bool Object::IsSeqAsciiString() { | 144 bool Object::IsSeqAsciiString() { |
145 if (!IsString()) return false; | 145 if (!IsString()) return false; |
146 StringShape shape(String::cast(this)); | 146 return StringShape(String::cast(this)).IsSequential() && |
147 return shape.IsSequential() && shape.IsAsciiRepresentation(); | 147 StringShape(String::cast(this)).IsAsciiRepresentation(); |
148 } | 148 } |
149 | 149 |
150 | 150 |
151 bool Object::IsSeqTwoByteString() { | 151 bool Object::IsSeqTwoByteString() { |
152 if (!IsString()) return false; | 152 if (!IsString()) return false; |
153 StringShape shape(String::cast(this)); | 153 return StringShape(String::cast(this)).IsSequential() && |
154 return shape.IsSequential() && shape.IsTwoByteRepresentation(); | 154 StringShape(String::cast(this)).IsTwoByteRepresentation(); |
155 } | 155 } |
156 | 156 |
157 | 157 |
158 bool Object::IsExternalString() { | 158 bool Object::IsExternalString() { |
159 if (!IsString()) return false; | 159 if (!IsString()) return false; |
160 return StringShape(String::cast(this)).IsExternal(); | 160 return StringShape(String::cast(this)).IsExternal(); |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 bool Object::IsExternalAsciiString() { | 164 bool Object::IsExternalAsciiString() { |
165 if (!IsString()) return false; | 165 if (!IsString()) return false; |
166 StringShape shape(String::cast(this)); | 166 return StringShape(String::cast(this)).IsExternal() && |
167 return shape.IsExternal() && shape.IsAsciiRepresentation(); | 167 StringShape(String::cast(this)).IsAsciiRepresentation(); |
168 } | 168 } |
169 | 169 |
170 | 170 |
171 bool Object::IsExternalTwoByteString() { | 171 bool Object::IsExternalTwoByteString() { |
172 if (!IsString()) return false; | 172 if (!IsString()) return false; |
173 StringShape shape(String::cast(this)); | 173 return StringShape(String::cast(this)).IsExternal() && |
174 return shape.IsExternal() && shape.IsTwoByteRepresentation(); | 174 StringShape(String::cast(this)).IsTwoByteRepresentation(); |
175 } | 175 } |
176 | 176 |
177 | 177 |
178 bool Object::IsSlicedString() { | 178 bool Object::IsSlicedString() { |
179 if (!IsString()) return false; | 179 if (!IsString()) return false; |
180 return StringShape(String::cast(this)).IsSliced(); | 180 return StringShape(String::cast(this)).IsSliced(); |
181 } | 181 } |
182 | 182 |
183 | 183 |
184 #endif // DEBUG | 184 #endif // DEBUG |
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { | 1236 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { |
1237 Object* tmp = array->get(first); | 1237 Object* tmp = array->get(first); |
1238 fast_set(array, first, array->get(second)); | 1238 fast_set(array, first, array->get(second)); |
1239 fast_set(array, second, tmp); | 1239 fast_set(array, second, tmp); |
1240 } | 1240 } |
1241 | 1241 |
1242 | 1242 |
1243 int DescriptorArray::Search(String* name) { | 1243 int DescriptorArray::Search(String* name) { |
1244 SLOW_ASSERT(IsSortedNoDuplicates()); | 1244 SLOW_ASSERT(IsSortedNoDuplicates()); |
1245 | 1245 |
1246 StringShape shape(name); | |
1247 | |
1248 // Check for empty descriptor array. | 1246 // Check for empty descriptor array. |
1249 int nof = number_of_descriptors(); | 1247 int nof = number_of_descriptors(); |
1250 if (nof == 0) return kNotFound; | 1248 if (nof == 0) return kNotFound; |
1251 | 1249 |
1252 // Fast case: do linear search for small arrays. | 1250 // Fast case: do linear search for small arrays. |
1253 const int kMaxElementsForLinearSearch = 8; | 1251 const int kMaxElementsForLinearSearch = 8; |
1254 if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) { | 1252 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { |
1255 return LinearSearch(name, nof); | 1253 return LinearSearch(name, nof); |
1256 } | 1254 } |
1257 | 1255 |
1258 // Slow case: perform binary search. | 1256 // Slow case: perform binary search. |
1259 return BinarySearch(name, 0, nof - 1); | 1257 return BinarySearch(name, 0, nof - 1); |
1260 } | 1258 } |
1261 | 1259 |
1262 | 1260 |
1263 | 1261 |
1264 String* DescriptorArray::GetKey(int descriptor_number) { | 1262 String* DescriptorArray::GetKey(int descriptor_number) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 ASSERT(obj->IsHashTable()); | 1383 ASSERT(obj->IsHashTable()); |
1386 return reinterpret_cast<HashTable*>(obj); | 1384 return reinterpret_cast<HashTable*>(obj); |
1387 } | 1385 } |
1388 | 1386 |
1389 | 1387 |
1390 INT_ACCESSORS(Array, length, kLengthOffset) | 1388 INT_ACCESSORS(Array, length, kLengthOffset) |
1391 | 1389 |
1392 | 1390 |
1393 bool String::Equals(String* other) { | 1391 bool String::Equals(String* other) { |
1394 if (other == this) return true; | 1392 if (other == this) return true; |
1395 StringShape this_shape(this); | 1393 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) { |
1396 StringShape other_shape(other); | 1394 return false; |
1397 if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false; | 1395 } |
1398 return SlowEquals(this_shape, other, other_shape); | 1396 return SlowEquals(other); |
1399 } | 1397 } |
1400 | 1398 |
1401 | 1399 |
1402 int String::length(StringShape shape) { | 1400 int String::length() { |
1403 ASSERT(shape.type() == StringShape(this).type()); | |
1404 uint32_t len = READ_INT_FIELD(this, kLengthOffset); | 1401 uint32_t len = READ_INT_FIELD(this, kLengthOffset); |
1405 | 1402 |
1406 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1403 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
1407 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1404 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
1408 ASSERT(kLongStringTag == 0); | 1405 ASSERT(kLongStringTag == 0); |
1409 | 1406 |
1410 return len >> (shape.size_tag() + kLongLengthShift); | 1407 return len >> (StringShape(this).size_tag() + kLongLengthShift); |
1411 } | |
1412 | |
1413 | |
1414 int String::length() { | |
1415 return length(StringShape(this)); | |
1416 } | 1408 } |
1417 | 1409 |
1418 | 1410 |
1419 void String::set_length(int value) { | 1411 void String::set_length(int value) { |
1420 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1412 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
1421 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1413 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
1422 ASSERT(kLongStringTag == 0); | 1414 ASSERT(kLongStringTag == 0); |
1423 | 1415 |
1424 StringShape shape(this); | |
1425 WRITE_INT_FIELD(this, | 1416 WRITE_INT_FIELD(this, |
1426 kLengthOffset, | 1417 kLengthOffset, |
1427 value << (shape.size_tag() + kLongLengthShift)); | 1418 value << (StringShape(this).size_tag() + kLongLengthShift)); |
1428 } | 1419 } |
1429 | 1420 |
1430 | 1421 |
1431 uint32_t String::length_field() { | 1422 uint32_t String::length_field() { |
1432 return READ_UINT32_FIELD(this, kLengthOffset); | 1423 return READ_UINT32_FIELD(this, kLengthOffset); |
1433 } | 1424 } |
1434 | 1425 |
1435 | 1426 |
1436 void String::set_length_field(uint32_t value) { | 1427 void String::set_length_field(uint32_t value) { |
1437 WRITE_UINT32_FIELD(this, kLengthOffset, value); | 1428 WRITE_UINT32_FIELD(this, kLengthOffset, value); |
1438 } | 1429 } |
1439 | 1430 |
1440 | 1431 |
1441 Object* String::TryFlattenIfNotFlat(StringShape shape) { | 1432 Object* String::TryFlattenIfNotFlat() { |
1442 ASSERT(shape.type() == StringShape(this).type()); | |
1443 // We don't need to flatten strings that are already flat. Since this code | 1433 // We don't need to flatten strings that are already flat. Since this code |
1444 // is inlined, it can be helpful in the flat case to not call out to Flatten. | 1434 // is inlined, it can be helpful in the flat case to not call out to Flatten. |
1445 if (!IsFlat(shape)) { | 1435 if (!IsFlat()) { |
1446 return TryFlatten(shape); | 1436 return TryFlatten(); |
1447 } | 1437 } |
1448 return this; | 1438 return this; |
1449 } | 1439 } |
1450 | 1440 |
1451 | 1441 |
1452 uint16_t String::Get(StringShape shape, int index) { | 1442 uint16_t String::Get(int index) { |
1453 ASSERT(shape.type() == StringShape(this).type()); | 1443 ASSERT(index >= 0 && index < length()); |
1454 ASSERT(index >= 0 && index < length(shape)); | 1444 switch (StringShape(this).full_representation_tag()) { |
1455 switch (shape.full_representation_tag()) { | |
1456 case kSeqStringTag | kAsciiStringTag: | 1445 case kSeqStringTag | kAsciiStringTag: |
1457 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); | 1446 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); |
1458 case kSeqStringTag | kTwoByteStringTag: | 1447 case kSeqStringTag | kTwoByteStringTag: |
1459 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); | 1448 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); |
1460 case kConsStringTag | kAsciiStringTag: | 1449 case kConsStringTag | kAsciiStringTag: |
1461 case kConsStringTag | kTwoByteStringTag: | 1450 case kConsStringTag | kTwoByteStringTag: |
1462 return ConsString::cast(this)->ConsStringGet(index); | 1451 return ConsString::cast(this)->ConsStringGet(index); |
1463 case kSlicedStringTag | kAsciiStringTag: | 1452 case kSlicedStringTag | kAsciiStringTag: |
1464 case kSlicedStringTag | kTwoByteStringTag: | 1453 case kSlicedStringTag | kTwoByteStringTag: |
1465 return SlicedString::cast(this)->SlicedStringGet(index); | 1454 return SlicedString::cast(this)->SlicedStringGet(index); |
1466 case kExternalStringTag | kAsciiStringTag: | 1455 case kExternalStringTag | kAsciiStringTag: |
1467 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); | 1456 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); |
1468 case kExternalStringTag | kTwoByteStringTag: | 1457 case kExternalStringTag | kTwoByteStringTag: |
1469 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); | 1458 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); |
1470 default: | 1459 default: |
1471 break; | 1460 break; |
1472 } | 1461 } |
1473 | 1462 |
1474 UNREACHABLE(); | 1463 UNREACHABLE(); |
1475 return 0; | 1464 return 0; |
1476 } | 1465 } |
1477 | 1466 |
1478 | 1467 |
1479 void String::Set(StringShape shape, int index, uint16_t value) { | 1468 void String::Set(int index, uint16_t value) { |
1480 ASSERT(shape.type() == StringShape(this).type()); | 1469 ASSERT(index >= 0 && index < length()); |
1481 ASSERT(shape.type() == StringShape(this).type()); | 1470 ASSERT(StringShape(this).IsSequential()); |
1482 ASSERT(index >= 0 && index < length(shape)); | |
1483 ASSERT(shape.IsSequential()); | |
1484 | 1471 |
1485 return shape.IsAsciiRepresentation() | 1472 return StringShape(this).IsAsciiRepresentation() |
1486 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) | 1473 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) |
1487 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); | 1474 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); |
1488 } | 1475 } |
1489 | 1476 |
1490 | 1477 |
1491 bool String::IsFlat(StringShape shape) { | 1478 bool String::IsFlat() { |
1492 ASSERT(shape.type() == StringShape(this).type()); | 1479 switch (StringShape(this).representation_tag()) { |
1493 switch (shape.representation_tag()) { | |
1494 case kConsStringTag: { | 1480 case kConsStringTag: { |
1495 String* second = ConsString::cast(this)->second(); | 1481 String* second = ConsString::cast(this)->second(); |
1496 // Only flattened strings have second part empty. | 1482 // Only flattened strings have second part empty. |
1497 return second->length() == 0; | 1483 return second->length() == 0; |
1498 } | 1484 } |
1499 case kSlicedStringTag: { | 1485 case kSlicedStringTag: { |
1500 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer()); | 1486 StringRepresentationTag tag = |
1501 StringRepresentationTag tag = slice_shape.representation_tag(); | 1487 StringShape(SlicedString::cast(this)->buffer()).representation_tag(); |
1502 return tag == kSeqStringTag || tag == kExternalStringTag; | 1488 return tag == kSeqStringTag || tag == kExternalStringTag; |
1503 } | 1489 } |
1504 default: | 1490 default: |
1505 return true; | 1491 return true; |
1506 } | 1492 } |
1507 } | 1493 } |
1508 | 1494 |
1509 | 1495 |
1510 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { | 1496 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { |
1511 ASSERT(index >= 0 && index < length()); | 1497 ASSERT(index >= 0 && index < length()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1545 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); | 1531 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); |
1546 } | 1532 } |
1547 | 1533 |
1548 | 1534 |
1549 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { | 1535 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { |
1550 ASSERT(index >= 0 && index < length()); | 1536 ASSERT(index >= 0 && index < length()); |
1551 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); | 1537 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); |
1552 } | 1538 } |
1553 | 1539 |
1554 | 1540 |
1555 int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) { | 1541 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { |
1556 uint32_t length = READ_INT_FIELD(this, kLengthOffset); | 1542 uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
1557 | 1543 |
1558 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1544 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
1559 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1545 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
1560 ASSERT(kLongStringTag == 0); | 1546 ASSERT(kLongStringTag == 0); |
1561 | 1547 |
1562 // Use the map (and not 'this') to compute the size tag, since | 1548 // Use the map (and not 'this') to compute the size tag, since |
1563 // TwoByteStringSize is called during GC when maps are encoded. | 1549 // TwoByteStringSize is called during GC when maps are encoded. |
1564 length >>= shape.size_tag() + kLongLengthShift; | 1550 length >>= StringShape(instance_type).size_tag() + kLongLengthShift; |
1565 | 1551 |
1566 return SizeFor(length); | 1552 return SizeFor(length); |
1567 } | 1553 } |
1568 | 1554 |
1569 | 1555 |
1570 int SeqAsciiString::SeqAsciiStringSize(StringShape shape) { | 1556 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { |
1571 uint32_t length = READ_INT_FIELD(this, kLengthOffset); | 1557 uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
1572 | 1558 |
1573 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); | 1559 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
1574 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); | 1560 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
1575 ASSERT(kLongStringTag == 0); | 1561 ASSERT(kLongStringTag == 0); |
1576 | 1562 |
1577 // Use the map (and not 'this') to compute the size tag, since | 1563 // Use the map (and not 'this') to compute the size tag, since |
1578 // AsciiStringSize is called during GC when maps are encoded. | 1564 // AsciiStringSize is called during GC when maps are encoded. |
1579 length >>= shape.size_tag() + kLongLengthShift; | 1565 length >>= StringShape(instance_type).size_tag() + kLongLengthShift; |
1580 | 1566 |
1581 return SizeFor(length); | 1567 return SizeFor(length); |
1582 } | 1568 } |
1583 | 1569 |
1584 | 1570 |
1585 String* ConsString::first() { | 1571 String* ConsString::first() { |
1586 return String::cast(READ_FIELD(this, kFirstOffset)); | 1572 return String::cast(READ_FIELD(this, kFirstOffset)); |
1587 } | 1573 } |
1588 | 1574 |
1589 | 1575 |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2580 #undef WRITE_INT_FIELD | 2566 #undef WRITE_INT_FIELD |
2581 #undef READ_SHORT_FIELD | 2567 #undef READ_SHORT_FIELD |
2582 #undef WRITE_SHORT_FIELD | 2568 #undef WRITE_SHORT_FIELD |
2583 #undef READ_BYTE_FIELD | 2569 #undef READ_BYTE_FIELD |
2584 #undef WRITE_BYTE_FIELD | 2570 #undef WRITE_BYTE_FIELD |
2585 | 2571 |
2586 | 2572 |
2587 } } // namespace v8::internal | 2573 } } // namespace v8::internal |
2588 | 2574 |
2589 #endif // V8_OBJECTS_INL_H_ | 2575 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |