Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: src/objects.cc

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

Powered by Google App Engine
This is Rietveld 408576698