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 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1041 if (len > kMaxShortPrintLength) { | 1041 if (len > kMaxShortPrintLength) { |
1042 accumulator->Add("<Very long string[%u]>", len); | 1042 accumulator->Add("<Very long string[%u]>", len); |
1043 return; | 1043 return; |
1044 } | 1044 } |
1045 | 1045 |
1046 if (!LooksValid()) { | 1046 if (!LooksValid()) { |
1047 accumulator->Add("<Invalid String>"); | 1047 accumulator->Add("<Invalid String>"); |
1048 return; | 1048 return; |
1049 } | 1049 } |
1050 | 1050 |
1051 StringInputBuffer buf(this); | 1051 ConsStringIteratorOp op; |
1052 StringCharacterStream stream(this, &op); | |
1052 | 1053 |
1053 bool truncated = false; | 1054 bool truncated = false; |
1054 if (len > kMaxShortPrintLength) { | 1055 if (len > kMaxShortPrintLength) { |
1055 len = kMaxShortPrintLength; | 1056 len = kMaxShortPrintLength; |
1056 truncated = true; | 1057 truncated = true; |
1057 } | 1058 } |
1058 bool ascii = true; | 1059 bool ascii = true; |
1059 for (int i = 0; i < len; i++) { | 1060 for (int i = 0; i < len; i++) { |
1060 int c = buf.GetNext(); | 1061 uint16_t c = stream.GetNext(); |
1061 | 1062 |
1062 if (c < 32 || c >= 127) { | 1063 if (c < 32 || c >= 127) { |
1063 ascii = false; | 1064 ascii = false; |
1064 } | 1065 } |
1065 } | 1066 } |
1066 buf.Reset(this); | 1067 stream.Reset(this); |
1067 if (ascii) { | 1068 if (ascii) { |
1068 accumulator->Add("<String[%u]: ", length()); | 1069 accumulator->Add("<String[%u]: ", length()); |
1069 for (int i = 0; i < len; i++) { | 1070 for (int i = 0; i < len; i++) { |
1070 accumulator->Put(buf.GetNext()); | 1071 accumulator->Put(stream.GetNext()); |
1071 } | 1072 } |
1072 accumulator->Put('>'); | 1073 accumulator->Put('>'); |
1073 } else { | 1074 } else { |
1074 // Backslash indicates that the string contains control | 1075 // Backslash indicates that the string contains control |
1075 // characters and that backslashes are therefore escaped. | 1076 // characters and that backslashes are therefore escaped. |
1076 accumulator->Add("<String[%u]\\: ", length()); | 1077 accumulator->Add("<String[%u]\\: ", length()); |
1077 for (int i = 0; i < len; i++) { | 1078 for (int i = 0; i < len; i++) { |
1078 int c = buf.GetNext(); | 1079 uint16_t c = stream.GetNext(); |
1079 if (c == '\n') { | 1080 if (c == '\n') { |
1080 accumulator->Add("\\n"); | 1081 accumulator->Add("\\n"); |
1081 } else if (c == '\r') { | 1082 } else if (c == '\r') { |
1082 accumulator->Add("\\r"); | 1083 accumulator->Add("\\r"); |
1083 } else if (c == '\\') { | 1084 } else if (c == '\\') { |
1084 accumulator->Add("\\\\"); | 1085 accumulator->Add("\\\\"); |
1085 } else if (c < 32 || c > 126) { | 1086 } else if (c < 32 || c > 126) { |
1086 accumulator->Add("\\x%02x", c); | 1087 accumulator->Add("\\x%02x", c); |
1087 } else { | 1088 } else { |
1088 accumulator->Put(c); | 1089 accumulator->Put(c); |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1531 if (!maybe_values->To(&values)) return maybe_values; | 1532 if (!maybe_values->To(&values)) return maybe_values; |
1532 } | 1533 } |
1533 set_properties(values); | 1534 set_properties(values); |
1534 } | 1535 } |
1535 set_map(new_map); | 1536 set_map(new_map); |
1536 return FastPropertyAtPut(field_index, value); | 1537 return FastPropertyAtPut(field_index, value); |
1537 } | 1538 } |
1538 | 1539 |
1539 | 1540 |
1540 static bool IsIdentifier(UnicodeCache* cache, | 1541 static bool IsIdentifier(UnicodeCache* cache, |
1541 unibrow::CharacterStream* buffer) { | 1542 String* string) { |
Yang
2012/12/21 09:21:48
no line break necessary anymore.
| |
1542 // Checks whether the buffer contains an identifier (no escape). | 1543 // Checks whether the buffer contains an identifier (no escape). |
1543 if (!buffer->has_more()) return false; | 1544 if (string->length() == 0) return false; |
1544 if (!cache->IsIdentifierStart(buffer->GetNext())) { | 1545 ConsStringIteratorOp op; |
1546 StringCharacterStream stream(string, &op); | |
1547 if (!cache->IsIdentifierStart(stream.GetNext())) { | |
1545 return false; | 1548 return false; |
1546 } | 1549 } |
1547 while (buffer->has_more()) { | 1550 while (stream.HasMore()) { |
1548 if (!cache->IsIdentifierPart(buffer->GetNext())) { | 1551 if (!cache->IsIdentifierPart(stream.GetNext())) { |
1549 return false; | 1552 return false; |
1550 } | 1553 } |
1551 } | 1554 } |
1552 return true; | 1555 return true; |
1553 } | 1556 } |
1554 | 1557 |
1555 | 1558 |
1556 MaybeObject* JSObject::AddFastProperty(String* name, | 1559 MaybeObject* JSObject::AddFastProperty(String* name, |
1557 Object* value, | 1560 Object* value, |
1558 PropertyAttributes attributes, | 1561 PropertyAttributes attributes, |
1559 StoreFromKeyed store_mode) { | 1562 StoreFromKeyed store_mode) { |
1560 ASSERT(!IsJSGlobalProxy()); | 1563 ASSERT(!IsJSGlobalProxy()); |
1561 ASSERT(DescriptorArray::kNotFound == | 1564 ASSERT(DescriptorArray::kNotFound == |
1562 map()->instance_descriptors()->Search( | 1565 map()->instance_descriptors()->Search( |
1563 name, map()->NumberOfOwnDescriptors())); | 1566 name, map()->NumberOfOwnDescriptors())); |
1564 | 1567 |
1565 // Normalize the object if the name is an actual string (not the | 1568 // Normalize the object if the name is an actual string (not the |
1566 // hidden symbols) and is not a real identifier. | 1569 // hidden symbols) and is not a real identifier. |
1567 // Normalize the object if it will have too many fast properties. | 1570 // Normalize the object if it will have too many fast properties. |
1568 Isolate* isolate = GetHeap()->isolate(); | 1571 Isolate* isolate = GetHeap()->isolate(); |
1569 StringInputBuffer buffer(name); | 1572 if ((!IsIdentifier(isolate->unicode_cache(), name) |
1570 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) | |
1571 && name != isolate->heap()->hidden_symbol()) || | 1573 && name != isolate->heap()->hidden_symbol()) || |
1572 (map()->unused_property_fields() == 0 && | 1574 (map()->unused_property_fields() == 0 && |
1573 TooManyFastProperties(properties()->length(), store_mode))) { | 1575 TooManyFastProperties(properties()->length(), store_mode))) { |
1574 Object* obj; | 1576 Object* obj; |
1575 MaybeObject* maybe_obj = | 1577 MaybeObject* maybe_obj = |
1576 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1578 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1577 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1579 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1578 | 1580 |
1579 return AddSlowProperty(name, value, attributes); | 1581 return AddSlowProperty(name, value, attributes); |
1580 } | 1582 } |
(...skipping 5006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6587 int* length_return) { | 6589 int* length_return) { |
6588 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 6590 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
6589 return SmartArrayPointer<char>(NULL); | 6591 return SmartArrayPointer<char>(NULL); |
6590 } | 6592 } |
6591 Heap* heap = GetHeap(); | 6593 Heap* heap = GetHeap(); |
6592 | 6594 |
6593 // Negative length means the to the end of the string. | 6595 // Negative length means the to the end of the string. |
6594 if (length < 0) length = kMaxInt - offset; | 6596 if (length < 0) length = kMaxInt - offset; |
6595 | 6597 |
6596 // Compute the size of the UTF-8 string. Start at the specified offset. | 6598 // Compute the size of the UTF-8 string. Start at the specified offset. |
6597 Access<StringInputBuffer> buffer( | 6599 Access<ConsStringIteratorOp> op( |
6598 heap->isolate()->objects_string_input_buffer()); | 6600 heap->isolate()->objects_string_iterator()); |
6599 buffer->Reset(offset, this); | 6601 StringCharacterStream stream(this, offset, op.value()); |
6600 int character_position = offset; | 6602 int character_position = offset; |
6601 int utf8_bytes = 0; | 6603 int utf8_bytes = 0; |
6602 int last = unibrow::Utf16::kNoPreviousCharacter; | 6604 int last = unibrow::Utf16::kNoPreviousCharacter; |
6603 while (buffer->has_more() && character_position++ < offset + length) { | 6605 while (stream.HasMore() && character_position++ < offset + length) { |
6604 uint16_t character = buffer->GetNext(); | 6606 uint16_t character = stream.GetNext(); |
6605 utf8_bytes += unibrow::Utf8::Length(character, last); | 6607 utf8_bytes += unibrow::Utf8::Length(character, last); |
6606 last = character; | 6608 last = character; |
6607 } | 6609 } |
6608 | 6610 |
6609 if (length_return) { | 6611 if (length_return) { |
6610 *length_return = utf8_bytes; | 6612 *length_return = utf8_bytes; |
6611 } | 6613 } |
6612 | 6614 |
6613 char* result = NewArray<char>(utf8_bytes + 1); | 6615 char* result = NewArray<char>(utf8_bytes + 1); |
6614 | 6616 |
6615 // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset. | 6617 // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset. |
6616 buffer->Rewind(); | 6618 stream.Reset(this, offset); |
6617 buffer->Seek(offset); | |
6618 character_position = offset; | 6619 character_position = offset; |
6619 int utf8_byte_position = 0; | 6620 int utf8_byte_position = 0; |
6620 last = unibrow::Utf16::kNoPreviousCharacter; | 6621 last = unibrow::Utf16::kNoPreviousCharacter; |
6621 while (buffer->has_more() && character_position++ < offset + length) { | 6622 while (stream.HasMore() && character_position++ < offset + length) { |
6622 uint16_t character = buffer->GetNext(); | 6623 uint16_t character = stream.GetNext(); |
6623 if (allow_nulls == DISALLOW_NULLS && character == 0) { | 6624 if (allow_nulls == DISALLOW_NULLS && character == 0) { |
6624 character = ' '; | 6625 character = ' '; |
6625 } | 6626 } |
6626 utf8_byte_position += | 6627 utf8_byte_position += |
6627 unibrow::Utf8::Encode(result + utf8_byte_position, character, last); | 6628 unibrow::Utf8::Encode(result + utf8_byte_position, character, last); |
6628 last = character; | 6629 last = character; |
6629 } | 6630 } |
6630 result[utf8_byte_position] = 0; | 6631 result[utf8_byte_position] = 0; |
6631 return SmartArrayPointer<char>(result); | 6632 return SmartArrayPointer<char>(result); |
6632 } | 6633 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6664 return NULL; | 6665 return NULL; |
6665 } | 6666 } |
6666 | 6667 |
6667 | 6668 |
6668 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 6669 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
6669 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 6670 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
6670 return SmartArrayPointer<uc16>(); | 6671 return SmartArrayPointer<uc16>(); |
6671 } | 6672 } |
6672 Heap* heap = GetHeap(); | 6673 Heap* heap = GetHeap(); |
6673 | 6674 |
6674 Access<StringInputBuffer> buffer( | 6675 Access<ConsStringIteratorOp> op( |
6675 heap->isolate()->objects_string_input_buffer()); | 6676 heap->isolate()->objects_string_iterator()); |
6676 buffer->Reset(this); | 6677 StringCharacterStream stream(this, op.value()); |
6677 | 6678 |
6678 uc16* result = NewArray<uc16>(length() + 1); | 6679 uc16* result = NewArray<uc16>(length() + 1); |
6679 | 6680 |
6680 int i = 0; | 6681 int i = 0; |
6681 while (buffer->has_more()) { | 6682 while (stream.HasMore()) { |
6682 uint16_t character = buffer->GetNext(); | 6683 uint16_t character = stream.GetNext(); |
6683 result[i++] = character; | 6684 result[i++] = character; |
6684 } | 6685 } |
6685 result[i] = 0; | 6686 result[i] = 0; |
6686 return SmartArrayPointer<uc16>(result); | 6687 return SmartArrayPointer<uc16>(result); |
6687 } | 6688 } |
6688 | 6689 |
6689 | 6690 |
6690 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { | 6691 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { |
6691 return reinterpret_cast<uc16*>( | 6692 return reinterpret_cast<uc16*>( |
6692 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start; | 6693 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start; |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7450 SlicedString* slice = SlicedString::cast(source); | 7451 SlicedString* slice = SlicedString::cast(source); |
7451 unsigned offset = slice->offset(); | 7452 unsigned offset = slice->offset(); |
7452 WriteToFlat(slice->parent(), sink, from + offset, to + offset); | 7453 WriteToFlat(slice->parent(), sink, from + offset, to + offset); |
7453 return; | 7454 return; |
7454 } | 7455 } |
7455 } | 7456 } |
7456 } | 7457 } |
7457 } | 7458 } |
7458 | 7459 |
7459 | 7460 |
7460 template <typename IteratorA, typename IteratorB> | |
7461 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { | |
7462 // General slow case check. We know that the ia and ib iterators | |
7463 // have the same length. | |
7464 while (ia->has_more()) { | |
7465 uint32_t ca = ia->GetNext(); | |
7466 uint32_t cb = ib->GetNext(); | |
7467 ASSERT(ca <= unibrow::Utf16::kMaxNonSurrogateCharCode); | |
7468 ASSERT(cb <= unibrow::Utf16::kMaxNonSurrogateCharCode); | |
7469 if (ca != cb) | |
7470 return false; | |
7471 } | |
7472 return true; | |
7473 } | |
7474 | |
7475 | |
7476 // Compares the contents of two strings by reading and comparing | 7461 // Compares the contents of two strings by reading and comparing |
7477 // int-sized blocks of characters. | 7462 // int-sized blocks of characters. |
7478 template <typename Char> | 7463 template <typename Char> |
7479 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) { | 7464 static inline bool CompareRawStringContents(const Char* const a, |
7480 int length = a.length(); | 7465 const Char* const b, |
7481 ASSERT_EQ(length, b.length()); | 7466 int length) { |
7482 const Char* pa = a.start(); | |
7483 const Char* pb = b.start(); | |
7484 int i = 0; | 7467 int i = 0; |
7485 #ifndef V8_HOST_CAN_READ_UNALIGNED | 7468 #ifndef V8_HOST_CAN_READ_UNALIGNED |
7486 // If this architecture isn't comfortable reading unaligned ints | 7469 // If this architecture isn't comfortable reading unaligned ints |
7487 // then we have to check that the strings are aligned before | 7470 // then we have to check that the strings are aligned before |
7488 // comparing them blockwise. | 7471 // comparing them blockwise. |
7489 const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT | 7472 const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT |
7490 uint32_t pa_addr = reinterpret_cast<uint32_t>(pa); | 7473 uint32_t pa_addr = reinterpret_cast<uint32_t>(a); |
7491 uint32_t pb_addr = reinterpret_cast<uint32_t>(pb); | 7474 uint32_t pb_addr = reinterpret_cast<uint32_t>(b); |
7492 if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) { | 7475 if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) { |
7493 #endif | 7476 #endif |
7494 const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT | 7477 const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT |
7495 int endpoint = length - kStepSize; | 7478 int endpoint = length - kStepSize; |
7496 // Compare blocks until we reach near the end of the string. | 7479 // Compare blocks until we reach near the end of the string. |
7497 for (; i <= endpoint; i += kStepSize) { | 7480 for (; i <= endpoint; i += kStepSize) { |
7498 uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i); | 7481 uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i); |
7499 uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i); | 7482 uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i); |
7500 if (wa != wb) { | 7483 if (wa != wb) { |
7501 return false; | 7484 return false; |
7502 } | 7485 } |
7503 } | 7486 } |
7504 #ifndef V8_HOST_CAN_READ_UNALIGNED | 7487 #ifndef V8_HOST_CAN_READ_UNALIGNED |
7505 } | 7488 } |
7506 #endif | 7489 #endif |
7507 // Compare the remaining characters that didn't fit into a block. | 7490 // Compare the remaining characters that didn't fit into a block. |
7508 for (; i < length; i++) { | 7491 for (; i < length; i++) { |
7509 if (a[i] != b[i]) { | 7492 if (a[i] != b[i]) { |
7510 return false; | 7493 return false; |
7511 } | 7494 } |
7512 } | 7495 } |
7513 return true; | 7496 return true; |
7514 } | 7497 } |
7515 | 7498 |
7516 | 7499 |
7517 template <typename IteratorA> | 7500 template<typename Chars1, typename Chars2> |
7518 static inline bool CompareStringContentsPartial(Isolate* isolate, | 7501 class RawStringComparator { |
Yang
2012/12/21 09:21:48
You could derive this class from AllStatic.
| |
7519 IteratorA* ia, | 7502 public: |
7520 String* b) { | 7503 static inline bool compare(const Chars1* a, const Chars2* b, int len) { |
7521 String::FlatContent content = b->GetFlatContent(); | 7504 ASSERT(sizeof(Chars1) != sizeof(Chars2)); |
7522 if (content.IsFlat()) { | 7505 for (int i = 0; i < len; i++) { |
7523 if (content.IsAscii()) { | 7506 if (a[i] != b[i]) { |
7524 VectorIterator<char> ib(content.ToAsciiVector()); | 7507 return false; |
7525 return CompareStringContents(ia, &ib); | 7508 } |
7526 } else { | |
7527 VectorIterator<uc16> ib(content.ToUC16Vector()); | |
7528 return CompareStringContents(ia, &ib); | |
7529 } | 7509 } |
7530 } else { | 7510 return true; |
7531 isolate->objects_string_compare_buffer_b()->Reset(0, b); | |
7532 return CompareStringContents(ia, | |
7533 isolate->objects_string_compare_buffer_b()); | |
7534 } | 7511 } |
7535 } | 7512 }; |
7513 | |
7514 | |
7515 template<> | |
7516 class RawStringComparator<uint16_t, uint16_t> { | |
7517 public: | |
7518 static inline bool compare(const uint16_t* a, const uint16_t* b, int len) { | |
7519 return CompareRawStringContents(a, b, len); | |
7520 } | |
7521 }; | |
7522 | |
7523 | |
7524 template<> | |
7525 class RawStringComparator<uint8_t, uint8_t> { | |
7526 public: | |
7527 static inline bool compare(const uint8_t* a, const uint8_t* b, int len) { | |
7528 return CompareRawStringContents(a, b, len); | |
7529 } | |
7530 }; | |
7531 | |
7532 | |
7533 class StringComparator { | |
7534 class State { | |
Yang
2012/12/21 09:21:48
Since this is another visitor, I was wondering whe
| |
7535 public: | |
7536 explicit inline State(ConsStringIteratorOp* op) | |
7537 : op_(op) {} | |
7538 | |
7539 inline void Init(String* string, unsigned len) { | |
7540 op_->Reset(); | |
7541 int32_t type = string->map()->instance_type(); | |
7542 String::Visit(string, 0, *this, *op_, type, len); | |
7543 } | |
7544 | |
7545 inline void VisitOneByteString(const uint8_t* chars, unsigned length) { | |
7546 is_one_byte_ = true; | |
7547 buffer8_ = chars; | |
7548 length_ = length; | |
7549 } | |
7550 | |
7551 inline void VisitTwoByteString(const uint16_t* chars, unsigned length) { | |
7552 is_one_byte_ = false; | |
7553 buffer16_ = chars; | |
7554 length_ = length; | |
7555 } | |
7556 | |
7557 void Advance(unsigned consumed) { | |
7558 ASSERT(consumed <= length_); | |
7559 // Still in buffer. | |
7560 if (length_ != consumed) { | |
7561 if (is_one_byte_) { | |
7562 buffer8_ += consumed; | |
7563 } else { | |
7564 buffer16_ += consumed; | |
7565 } | |
7566 length_ -= consumed; | |
7567 return; | |
7568 } | |
7569 // Advance state. | |
7570 ASSERT(op_->HasMore()); | |
7571 int32_t type; | |
7572 unsigned length; | |
7573 String* next = op_->ContinueOperation(&type, &length); | |
7574 ASSERT(next != NULL); | |
7575 ConsStringNullOp null_op; | |
7576 String::Visit(next, 0, *this, null_op, type, length); | |
7577 } | |
7578 | |
7579 ConsStringIteratorOp* const op_; | |
7580 bool is_one_byte_; | |
7581 unsigned offset_; | |
7582 unsigned length_; | |
7583 union { | |
7584 const uint8_t* buffer8_; | |
7585 const uint16_t* buffer16_; | |
7586 }; | |
7587 DISALLOW_IMPLICIT_CONSTRUCTORS(State); | |
7588 }; | |
7589 | |
7590 public: | |
7591 inline StringComparator(ConsStringIteratorOp* op_1, | |
7592 ConsStringIteratorOp* op_2) | |
7593 : state_1_(op_1), | |
7594 state_2_(op_2) { | |
7595 } | |
7596 | |
7597 template<typename Chars1, typename Chars2> | |
7598 static inline bool Equals(State* state_1, State* state_2, unsigned to_check) { | |
7599 const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_); | |
7600 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); | |
7601 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); | |
7602 } | |
7603 | |
7604 bool Equals(unsigned length, String* string_1, String* string_2) { | |
7605 ASSERT(length != 0); | |
7606 state_1_.Init(string_1, length); | |
7607 state_2_.Init(string_2, length); | |
7608 while (true) { | |
7609 unsigned to_check = Min(state_1_.length_, state_2_.length_); | |
7610 ASSERT(to_check > 0 && to_check <= length); | |
7611 bool is_equal; | |
7612 if (state_1_.is_one_byte_) { | |
7613 if (state_2_.is_one_byte_) { | |
7614 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check); | |
7615 } else { | |
7616 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check); | |
7617 } | |
7618 } else { | |
7619 if (state_2_.is_one_byte_) { | |
7620 is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check); | |
7621 } else { | |
7622 is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check); | |
7623 } | |
7624 } | |
7625 // Looping done. | |
7626 if (!is_equal) return false; | |
7627 length -= to_check; | |
7628 // Exit condition. Strings are equal. | |
7629 if (length == 0) return true; | |
7630 state_1_.Advance(to_check); | |
7631 state_2_.Advance(to_check); | |
7632 } | |
7633 } | |
7634 | |
7635 private: | |
7636 State state_1_; | |
7637 State state_2_; | |
7638 DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator); | |
7639 }; | |
7536 | 7640 |
7537 | 7641 |
7538 bool String::SlowEquals(String* other) { | 7642 bool String::SlowEquals(String* other) { |
7539 // Fast check: negative check with lengths. | 7643 // Fast check: negative check with lengths. |
7540 int len = length(); | 7644 int len = length(); |
7541 if (len != other->length()) return false; | 7645 if (len != other->length()) return false; |
7542 if (len == 0) return true; | 7646 if (len == 0) return true; |
7543 | 7647 |
7544 // Fast check: if hash code is computed for both strings | 7648 // Fast check: if hash code is computed for both strings |
7545 // a fast negative check can be performed. | 7649 // a fast negative check can be performed. |
(...skipping 15 matching lines...) Expand all Loading... | |
7561 if (Hash() != other->Hash()) return false; | 7665 if (Hash() != other->Hash()) return false; |
7562 } | 7666 } |
7563 | 7667 |
7564 // We know the strings are both non-empty. Compare the first chars | 7668 // We know the strings are both non-empty. Compare the first chars |
7565 // before we try to flatten the strings. | 7669 // before we try to flatten the strings. |
7566 if (this->Get(0) != other->Get(0)) return false; | 7670 if (this->Get(0) != other->Get(0)) return false; |
7567 | 7671 |
7568 String* lhs = this->TryFlattenGetString(); | 7672 String* lhs = this->TryFlattenGetString(); |
7569 String* rhs = other->TryFlattenGetString(); | 7673 String* rhs = other->TryFlattenGetString(); |
7570 | 7674 |
7675 // TODO(dcarney): Compare all types of flat strings with a Visitor. | |
7571 if (StringShape(lhs).IsSequentialAscii() && | 7676 if (StringShape(lhs).IsSequentialAscii() && |
7572 StringShape(rhs).IsSequentialAscii()) { | 7677 StringShape(rhs).IsSequentialAscii()) { |
7573 const char* str1 = SeqOneByteString::cast(lhs)->GetChars(); | 7678 const char* str1 = SeqOneByteString::cast(lhs)->GetChars(); |
7574 const char* str2 = SeqOneByteString::cast(rhs)->GetChars(); | 7679 const char* str2 = SeqOneByteString::cast(rhs)->GetChars(); |
7575 return CompareRawStringContents(Vector<const char>(str1, len), | 7680 return CompareRawStringContents(str1, str2, len); |
7576 Vector<const char>(str2, len)); | |
7577 } | 7681 } |
7578 | 7682 |
7579 Isolate* isolate = GetIsolate(); | 7683 Isolate* isolate = GetIsolate(); |
7580 String::FlatContent lhs_content = lhs->GetFlatContent(); | 7684 StringComparator comparator(isolate->objects_string_compare_iterator_a(), |
7581 String::FlatContent rhs_content = rhs->GetFlatContent(); | 7685 isolate->objects_string_compare_iterator_b()); |
7582 if (lhs_content.IsFlat()) { | 7686 |
7583 if (lhs_content.IsAscii()) { | 7687 return comparator.Equals(static_cast<unsigned>(len), lhs, rhs); |
7584 Vector<const char> vec1 = lhs_content.ToAsciiVector(); | |
7585 if (rhs_content.IsFlat()) { | |
7586 if (rhs_content.IsAscii()) { | |
7587 Vector<const char> vec2 = rhs_content.ToAsciiVector(); | |
7588 return CompareRawStringContents(vec1, vec2); | |
7589 } else { | |
7590 VectorIterator<char> buf1(vec1); | |
7591 VectorIterator<uc16> ib(rhs_content.ToUC16Vector()); | |
7592 return CompareStringContents(&buf1, &ib); | |
7593 } | |
7594 } else { | |
7595 VectorIterator<char> buf1(vec1); | |
7596 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); | |
7597 return CompareStringContents(&buf1, | |
7598 isolate->objects_string_compare_buffer_b()); | |
7599 } | |
7600 } else { | |
7601 Vector<const uc16> vec1 = lhs_content.ToUC16Vector(); | |
7602 if (rhs_content.IsFlat()) { | |
7603 if (rhs_content.IsAscii()) { | |
7604 VectorIterator<uc16> buf1(vec1); | |
7605 VectorIterator<char> ib(rhs_content.ToAsciiVector()); | |
7606 return CompareStringContents(&buf1, &ib); | |
7607 } else { | |
7608 Vector<const uc16> vec2(rhs_content.ToUC16Vector()); | |
7609 return CompareRawStringContents(vec1, vec2); | |
7610 } | |
7611 } else { | |
7612 VectorIterator<uc16> buf1(vec1); | |
7613 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); | |
7614 return CompareStringContents(&buf1, | |
7615 isolate->objects_string_compare_buffer_b()); | |
7616 } | |
7617 } | |
7618 } else { | |
7619 isolate->objects_string_compare_buffer_a()->Reset(0, lhs); | |
7620 return CompareStringContentsPartial(isolate, | |
7621 isolate->objects_string_compare_buffer_a(), rhs); | |
7622 } | |
7623 } | 7688 } |
7624 | 7689 |
7625 | 7690 |
7626 bool String::MarkAsUndetectable() { | 7691 bool String::MarkAsUndetectable() { |
7627 if (StringShape(this).IsSymbol()) return false; | 7692 if (StringShape(this).IsSymbol()) return false; |
7628 | 7693 |
7629 Map* map = this->map(); | 7694 Map* map = this->map(); |
7630 Heap* heap = GetHeap(); | 7695 Heap* heap = GetHeap(); |
7631 if (map == heap->string_map()) { | 7696 if (map == heap->string_map()) { |
7632 this->set_map(heap->undetectable_string_map()); | 7697 this->set_map(heap->undetectable_string_map()); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7757 set_hash_field(field); | 7822 set_hash_field(field); |
7758 | 7823 |
7759 // Check the hash code is there. | 7824 // Check the hash code is there. |
7760 ASSERT(HasHashCode()); | 7825 ASSERT(HasHashCode()); |
7761 uint32_t result = field >> kHashShift; | 7826 uint32_t result = field >> kHashShift; |
7762 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 7827 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
7763 return result; | 7828 return result; |
7764 } | 7829 } |
7765 | 7830 |
7766 | 7831 |
7767 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, | 7832 bool String::ComputeArrayIndex(uint32_t* index) { |
7768 uint32_t* index, | 7833 int length = this->length(); |
7769 int length) { | |
7770 if (length == 0 || length > kMaxArrayIndexSize) return false; | 7834 if (length == 0 || length > kMaxArrayIndexSize) return false; |
7771 uc32 ch = buffer->GetNext(); | 7835 ConsStringIteratorOp op; |
7836 StringCharacterStream stream(this, &op); | |
7837 uint16_t ch = stream.GetNext(); | |
7772 | 7838 |
7773 // If the string begins with a '0' character, it must only consist | 7839 // If the string begins with a '0' character, it must only consist |
7774 // of it to be a legal array index. | 7840 // of it to be a legal array index. |
7775 if (ch == '0') { | 7841 if (ch == '0') { |
7776 *index = 0; | 7842 *index = 0; |
7777 return length == 1; | 7843 return length == 1; |
7778 } | 7844 } |
7779 | 7845 |
7780 // Convert string to uint32 array index; character by character. | 7846 // Convert string to uint32 array index; character by character. |
7781 int d = ch - '0'; | 7847 int d = ch - '0'; |
7782 if (d < 0 || d > 9) return false; | 7848 if (d < 0 || d > 9) return false; |
7783 uint32_t result = d; | 7849 uint32_t result = d; |
7784 while (buffer->has_more()) { | 7850 while (stream.HasMore()) { |
7785 d = buffer->GetNext() - '0'; | 7851 d = stream.GetNext() - '0'; |
7786 if (d < 0 || d > 9) return false; | 7852 if (d < 0 || d > 9) return false; |
7787 // Check that the new result is below the 32 bit limit. | 7853 // Check that the new result is below the 32 bit limit. |
7788 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; | 7854 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; |
7789 result = (result * 10) + d; | 7855 result = (result * 10) + d; |
7790 } | 7856 } |
7791 | 7857 |
7792 *index = result; | 7858 *index = result; |
7793 return true; | 7859 return true; |
7794 } | 7860 } |
7795 | 7861 |
7796 | 7862 |
7797 bool String::SlowAsArrayIndex(uint32_t* index) { | 7863 bool String::SlowAsArrayIndex(uint32_t* index) { |
7798 if (length() <= kMaxCachedArrayIndexLength) { | 7864 if (length() <= kMaxCachedArrayIndexLength) { |
7799 Hash(); // force computation of hash code | 7865 Hash(); // force computation of hash code |
7800 uint32_t field = hash_field(); | 7866 uint32_t field = hash_field(); |
7801 if ((field & kIsNotArrayIndexMask) != 0) return false; | 7867 if ((field & kIsNotArrayIndexMask) != 0) return false; |
7802 // Isolate the array index form the full hash field. | 7868 // Isolate the array index form the full hash field. |
7803 *index = (kArrayIndexHashMask & field) >> kHashShift; | 7869 *index = (kArrayIndexHashMask & field) >> kHashShift; |
7804 return true; | 7870 return true; |
7805 } else { | 7871 } else { |
7806 StringInputBuffer buffer(this); | 7872 return ComputeArrayIndex(index); |
7807 return ComputeArrayIndex(&buffer, index, length()); | |
7808 } | 7873 } |
7809 } | 7874 } |
7810 | 7875 |
7811 | 7876 |
7812 String* SeqString::Truncate(int new_length) { | 7877 String* SeqString::Truncate(int new_length) { |
7813 Heap* heap = GetHeap(); | 7878 Heap* heap = GetHeap(); |
7814 if (new_length <= 0) return heap->empty_string(); | 7879 if (new_length <= 0) return heap->empty_string(); |
7815 | 7880 |
7816 int string_size, allocated_string_size; | 7881 int string_size, allocated_string_size; |
7817 int old_length = length(); | 7882 int old_length = length(); |
(...skipping 6242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14060 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 14125 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
14061 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 14126 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
14062 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 14127 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
14063 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 14128 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
14064 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 14129 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
14065 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 14130 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
14066 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 14131 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
14067 } | 14132 } |
14068 | 14133 |
14069 } } // namespace v8::internal | 14134 } } // namespace v8::internal |
OLD | NEW |