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

Side by Side Diff: src/objects.cc

Issue 11638037: Remove most uses of StringInputBuffer (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cleanup Created 8 years 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 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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 properties()->CopySize(properties()->length() + new_unused + 1); 1531 properties()->CopySize(properties()->length() + new_unused + 1);
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, String* string) {
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 (!buffer->has_more()) return false; 1543 if (string->length() == 0) return false;
1544 if (!cache->IsIdentifierStart(buffer->GetNext())) { 1544 ConsStringIteratorOp op;
1545 StringCharacterStream stream(string, &op);
1546 if (!cache->IsIdentifierStart(stream.GetNext())) {
1545 return false; 1547 return false;
1546 } 1548 }
1547 while (buffer->has_more()) { 1549 while (stream.HasMore()) {
1548 if (!cache->IsIdentifierPart(buffer->GetNext())) { 1550 if (!cache->IsIdentifierPart(stream.GetNext())) {
1549 return false; 1551 return false;
1550 } 1552 }
1551 } 1553 }
1552 return true; 1554 return true;
1553 } 1555 }
1554 1556
1555 1557
1556 MaybeObject* JSObject::AddFastProperty(String* name, 1558 MaybeObject* JSObject::AddFastProperty(String* name,
1557 Object* value, 1559 Object* value,
1558 PropertyAttributes attributes, 1560 PropertyAttributes attributes,
1559 StoreFromKeyed store_mode) { 1561 StoreFromKeyed store_mode) {
1560 ASSERT(!IsJSGlobalProxy()); 1562 ASSERT(!IsJSGlobalProxy());
1561 ASSERT(DescriptorArray::kNotFound == 1563 ASSERT(DescriptorArray::kNotFound ==
1562 map()->instance_descriptors()->Search( 1564 map()->instance_descriptors()->Search(
1563 name, map()->NumberOfOwnDescriptors())); 1565 name, map()->NumberOfOwnDescriptors()));
1564 1566
1565 // Normalize the object if the name is an actual string (not the 1567 // Normalize the object if the name is an actual string (not the
1566 // hidden symbols) and is not a real identifier. 1568 // hidden symbols) and is not a real identifier.
1567 // Normalize the object if it will have too many fast properties. 1569 // Normalize the object if it will have too many fast properties.
1568 Isolate* isolate = GetHeap()->isolate(); 1570 Isolate* isolate = GetHeap()->isolate();
1569 StringInputBuffer buffer(name); 1571 if ((!IsIdentifier(isolate->unicode_cache(), name)
1570 if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
1571 && name != isolate->heap()->hidden_symbol()) || 1572 && name != isolate->heap()->hidden_symbol()) ||
1572 (map()->unused_property_fields() == 0 && 1573 (map()->unused_property_fields() == 0 &&
1573 TooManyFastProperties(properties()->length(), store_mode))) { 1574 TooManyFastProperties(properties()->length(), store_mode))) {
1574 Object* obj; 1575 Object* obj;
1575 MaybeObject* maybe_obj = 1576 MaybeObject* maybe_obj =
1576 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 1577 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1577 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1578 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1578 1579
1579 return AddSlowProperty(name, value, attributes); 1580 return AddSlowProperty(name, value, attributes);
1580 } 1581 }
(...skipping 5006 matching lines...) Expand 10 before | Expand all | Expand 10 after
6587 int* length_return) { 6588 int* length_return) {
6588 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { 6589 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6589 return SmartArrayPointer<char>(NULL); 6590 return SmartArrayPointer<char>(NULL);
6590 } 6591 }
6591 Heap* heap = GetHeap(); 6592 Heap* heap = GetHeap();
6592 6593
6593 // Negative length means the to the end of the string. 6594 // Negative length means the to the end of the string.
6594 if (length < 0) length = kMaxInt - offset; 6595 if (length < 0) length = kMaxInt - offset;
6595 6596
6596 // Compute the size of the UTF-8 string. Start at the specified offset. 6597 // Compute the size of the UTF-8 string. Start at the specified offset.
6597 Access<StringInputBuffer> buffer( 6598 Access<ConsStringIteratorOp> op(
6598 heap->isolate()->objects_string_input_buffer()); 6599 heap->isolate()->objects_string_iterator());
6599 buffer->Reset(offset, this); 6600 StringCharacterStream stream(this, op.value(), offset);
6600 int character_position = offset; 6601 int character_position = offset;
6601 int utf8_bytes = 0; 6602 int utf8_bytes = 0;
6602 int last = unibrow::Utf16::kNoPreviousCharacter; 6603 int last = unibrow::Utf16::kNoPreviousCharacter;
6603 while (buffer->has_more() && character_position++ < offset + length) { 6604 while (stream.HasMore() && character_position++ < offset + length) {
6604 uint16_t character = buffer->GetNext(); 6605 uint16_t character = stream.GetNext();
6605 utf8_bytes += unibrow::Utf8::Length(character, last); 6606 utf8_bytes += unibrow::Utf8::Length(character, last);
6606 last = character; 6607 last = character;
6607 } 6608 }
6608 6609
6609 if (length_return) { 6610 if (length_return) {
6610 *length_return = utf8_bytes; 6611 *length_return = utf8_bytes;
6611 } 6612 }
6612 6613
6613 char* result = NewArray<char>(utf8_bytes + 1); 6614 char* result = NewArray<char>(utf8_bytes + 1);
6614 6615
6615 // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset. 6616 // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
6616 buffer->Rewind(); 6617 stream.Reset(this, offset);
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 (buffer->has_more() && character_position++ < offset + length) { 6621 while (stream.HasMore() && character_position++ < offset + length) {
6622 uint16_t character = buffer->GetNext(); 6622 uint16_t character = stream.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<StringInputBuffer> buffer( 6674 Access<ConsStringIteratorOp> op(
6675 heap->isolate()->objects_string_input_buffer()); 6675 heap->isolate()->objects_string_iterator());
6676 buffer->Reset(this); 6676 StringCharacterStream stream(this, op.value());
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 (buffer->has_more()) { 6681 while (stream.HasMore()) {
6682 uint16_t character = buffer->GetNext(); 6682 uint16_t character = stream.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
7476 // Compares the contents of two strings by reading and comparing 7460 // Compares the contents of two strings by reading and comparing
7477 // int-sized blocks of characters. 7461 // int-sized blocks of characters.
7478 template <typename Char> 7462 template <typename Char>
7479 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) { 7463 static inline bool CompareRawStringContents(const Char* const a,
7480 int length = a.length(); 7464 const Char* const b,
7481 ASSERT_EQ(length, b.length()); 7465 int length) {
7482 const Char* pa = a.start();
7483 const Char* pb = b.start();
7484 int i = 0; 7466 int i = 0;
7485 #ifndef V8_HOST_CAN_READ_UNALIGNED 7467 #ifndef V8_HOST_CAN_READ_UNALIGNED
7486 // If this architecture isn't comfortable reading unaligned ints 7468 // If this architecture isn't comfortable reading unaligned ints
7487 // then we have to check that the strings are aligned before 7469 // then we have to check that the strings are aligned before
7488 // comparing them blockwise. 7470 // comparing them blockwise.
7489 const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT 7471 const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT
7490 uint32_t pa_addr = reinterpret_cast<uint32_t>(pa); 7472 uint32_t pa_addr = reinterpret_cast<uint32_t>(a);
7491 uint32_t pb_addr = reinterpret_cast<uint32_t>(pb); 7473 uint32_t pb_addr = reinterpret_cast<uint32_t>(b);
7492 if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) { 7474 if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
7493 #endif 7475 #endif
7494 const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT 7476 const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT
7495 int endpoint = length - kStepSize; 7477 int endpoint = length - kStepSize;
7496 // Compare blocks until we reach near the end of the string. 7478 // Compare blocks until we reach near the end of the string.
7497 for (; i <= endpoint; i += kStepSize) { 7479 for (; i <= endpoint; i += kStepSize) {
7498 uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i); 7480 uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
7499 uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i); 7481 uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
7500 if (wa != wb) { 7482 if (wa != wb) {
7501 return false; 7483 return false;
7502 } 7484 }
7503 } 7485 }
7504 #ifndef V8_HOST_CAN_READ_UNALIGNED 7486 #ifndef V8_HOST_CAN_READ_UNALIGNED
7505 } 7487 }
7506 #endif 7488 #endif
7507 // Compare the remaining characters that didn't fit into a block. 7489 // Compare the remaining characters that didn't fit into a block.
7508 for (; i < length; i++) { 7490 for (; i < length; i++) {
7509 if (a[i] != b[i]) { 7491 if (a[i] != b[i]) {
7510 return false; 7492 return false;
7511 } 7493 }
7512 } 7494 }
7513 return true; 7495 return true;
7514 } 7496 }
7515 7497
7516 7498
7517 template <typename IteratorA> 7499 template<typename Chars1, typename Chars2>
7518 static inline bool CompareStringContentsPartial(Isolate* isolate, 7500 class RawStringComparator : public AllStatic {
7519 IteratorA* ia, 7501 public:
7520 String* b) { 7502 static inline bool compare(const Chars1* a, const Chars2* b, int len) {
7521 String::FlatContent content = b->GetFlatContent(); 7503 ASSERT(sizeof(Chars1) != sizeof(Chars2));
7522 if (content.IsFlat()) { 7504 for (int i = 0; i < len; i++) {
7523 if (content.IsAscii()) { 7505 if (a[i] != b[i]) {
7524 VectorIterator<char> ib(content.ToAsciiVector()); 7506 return false;
7525 return CompareStringContents(ia, &ib); 7507 }
7526 } else {
7527 VectorIterator<uc16> ib(content.ToUC16Vector());
7528 return CompareStringContents(ia, &ib);
7529 } 7508 }
7530 } else { 7509 return true;
7531 isolate->objects_string_compare_buffer_b()->Reset(0, b);
7532 return CompareStringContents(ia,
7533 isolate->objects_string_compare_buffer_b());
7534 } 7510 }
7535 } 7511 };
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) {}
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;
7571 unsigned length;
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 offset_;
7581 unsigned length_;
7582 union {
7583 const uint8_t* buffer8_;
7584 const uint16_t* buffer16_;
7585 };
7586 DISALLOW_IMPLICIT_CONSTRUCTORS(State);
7587 };
7588
7589 public:
7590 inline StringComparator(ConsStringIteratorOp* op_1,
7591 ConsStringIteratorOp* op_2)
7592 : state_1_(op_1),
7593 state_2_(op_2) {
7594 }
7595
7596 template<typename Chars1, typename Chars2>
7597 static inline bool Equals(State* state_1, State* state_2, unsigned to_check) {
7598 const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
7599 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
7600 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
7601 }
7602
7603 bool Equals(unsigned length, String* string_1, String* string_2) {
7604 ASSERT(length != 0);
7605 state_1_.Init(string_1, length);
7606 state_2_.Init(string_2, length);
7607 while (true) {
7608 unsigned to_check = Min(state_1_.length_, state_2_.length_);
7609 ASSERT(to_check > 0 && to_check <= length);
7610 bool is_equal;
7611 if (state_1_.is_one_byte_) {
7612 if (state_2_.is_one_byte_) {
7613 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
7614 } else {
7615 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
7616 }
7617 } else {
7618 if (state_2_.is_one_byte_) {
7619 is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
7620 } else {
7621 is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
7622 }
7623 }
7624 // Looping done.
7625 if (!is_equal) return false;
7626 length -= to_check;
7627 // Exit condition. Strings are equal.
7628 if (length == 0) return true;
7629 state_1_.Advance(to_check);
7630 state_2_.Advance(to_check);
7631 }
7632 }
7633
7634 private:
7635 State state_1_;
7636 State state_2_;
7637 DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
7638 };
7536 7639
7537 7640
7538 bool String::SlowEquals(String* other) { 7641 bool String::SlowEquals(String* other) {
7539 // Fast check: negative check with lengths. 7642 // Fast check: negative check with lengths.
7540 int len = length(); 7643 int len = length();
7541 if (len != other->length()) return false; 7644 if (len != other->length()) return false;
7542 if (len == 0) return true; 7645 if (len == 0) return true;
7543 7646
7544 // Fast check: if hash code is computed for both strings 7647 // Fast check: if hash code is computed for both strings
7545 // a fast negative check can be performed. 7648 // a fast negative check can be performed.
(...skipping 15 matching lines...) Expand all
7561 if (Hash() != other->Hash()) return false; 7664 if (Hash() != other->Hash()) return false;
7562 } 7665 }
7563 7666
7564 // We know the strings are both non-empty. Compare the first chars 7667 // We know the strings are both non-empty. Compare the first chars
7565 // before we try to flatten the strings. 7668 // before we try to flatten the strings.
7566 if (this->Get(0) != other->Get(0)) return false; 7669 if (this->Get(0) != other->Get(0)) return false;
7567 7670
7568 String* lhs = this->TryFlattenGetString(); 7671 String* lhs = this->TryFlattenGetString();
7569 String* rhs = other->TryFlattenGetString(); 7672 String* rhs = other->TryFlattenGetString();
7570 7673
7674 // TODO(dcarney): Compare all types of flat strings with a Visitor.
7571 if (StringShape(lhs).IsSequentialAscii() && 7675 if (StringShape(lhs).IsSequentialAscii() &&
7572 StringShape(rhs).IsSequentialAscii()) { 7676 StringShape(rhs).IsSequentialAscii()) {
7573 const char* str1 = SeqOneByteString::cast(lhs)->GetChars(); 7677 const char* str1 = SeqOneByteString::cast(lhs)->GetChars();
7574 const char* str2 = SeqOneByteString::cast(rhs)->GetChars(); 7678 const char* str2 = SeqOneByteString::cast(rhs)->GetChars();
7575 return CompareRawStringContents(Vector<const char>(str1, len), 7679 return CompareRawStringContents(str1, str2, len);
7576 Vector<const char>(str2, len));
7577 } 7680 }
7578 7681
7579 Isolate* isolate = GetIsolate(); 7682 Isolate* isolate = GetIsolate();
7580 String::FlatContent lhs_content = lhs->GetFlatContent(); 7683 StringComparator comparator(isolate->objects_string_compare_iterator_a(),
7581 String::FlatContent rhs_content = rhs->GetFlatContent(); 7684 isolate->objects_string_compare_iterator_b());
7582 if (lhs_content.IsFlat()) { 7685
7583 if (lhs_content.IsAscii()) { 7686 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 } 7687 }
7624 7688
7625 7689
7626 bool String::MarkAsUndetectable() { 7690 bool String::MarkAsUndetectable() {
7627 if (StringShape(this).IsSymbol()) return false; 7691 if (StringShape(this).IsSymbol()) return false;
7628 7692
7629 Map* map = this->map(); 7693 Map* map = this->map();
7630 Heap* heap = GetHeap(); 7694 Heap* heap = GetHeap();
7631 if (map == heap->string_map()) { 7695 if (map == heap->string_map()) {
7632 this->set_map(heap->undetectable_string_map()); 7696 this->set_map(heap->undetectable_string_map());
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
7757 set_hash_field(field); 7821 set_hash_field(field);
7758 7822
7759 // Check the hash code is there. 7823 // Check the hash code is there.
7760 ASSERT(HasHashCode()); 7824 ASSERT(HasHashCode());
7761 uint32_t result = field >> kHashShift; 7825 uint32_t result = field >> kHashShift;
7762 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 7826 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
7763 return result; 7827 return result;
7764 } 7828 }
7765 7829
7766 7830
7767 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, 7831 bool String::ComputeArrayIndex(uint32_t* index) {
7768 uint32_t* index, 7832 int length = this->length();
7769 int length) {
7770 if (length == 0 || length > kMaxArrayIndexSize) return false; 7833 if (length == 0 || length > kMaxArrayIndexSize) return false;
7771 uc32 ch = buffer->GetNext(); 7834 ConsStringIteratorOp op;
7835 StringCharacterStream stream(this, &op);
7836 uint16_t ch = stream.GetNext();
7772 7837
7773 // If the string begins with a '0' character, it must only consist 7838 // If the string begins with a '0' character, it must only consist
7774 // of it to be a legal array index. 7839 // of it to be a legal array index.
7775 if (ch == '0') { 7840 if (ch == '0') {
7776 *index = 0; 7841 *index = 0;
7777 return length == 1; 7842 return length == 1;
7778 } 7843 }
7779 7844
7780 // Convert string to uint32 array index; character by character. 7845 // Convert string to uint32 array index; character by character.
7781 int d = ch - '0'; 7846 int d = ch - '0';
7782 if (d < 0 || d > 9) return false; 7847 if (d < 0 || d > 9) return false;
7783 uint32_t result = d; 7848 uint32_t result = d;
7784 while (buffer->has_more()) { 7849 while (stream.HasMore()) {
7785 d = buffer->GetNext() - '0'; 7850 d = stream.GetNext() - '0';
7786 if (d < 0 || d > 9) return false; 7851 if (d < 0 || d > 9) return false;
7787 // Check that the new result is below the 32 bit limit. 7852 // Check that the new result is below the 32 bit limit.
7788 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; 7853 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
7789 result = (result * 10) + d; 7854 result = (result * 10) + d;
7790 } 7855 }
7791 7856
7792 *index = result; 7857 *index = result;
7793 return true; 7858 return true;
7794 } 7859 }
7795 7860
7796 7861
7797 bool String::SlowAsArrayIndex(uint32_t* index) { 7862 bool String::SlowAsArrayIndex(uint32_t* index) {
7798 if (length() <= kMaxCachedArrayIndexLength) { 7863 if (length() <= kMaxCachedArrayIndexLength) {
7799 Hash(); // force computation of hash code 7864 Hash(); // force computation of hash code
7800 uint32_t field = hash_field(); 7865 uint32_t field = hash_field();
7801 if ((field & kIsNotArrayIndexMask) != 0) return false; 7866 if ((field & kIsNotArrayIndexMask) != 0) return false;
7802 // Isolate the array index form the full hash field. 7867 // Isolate the array index form the full hash field.
7803 *index = (kArrayIndexHashMask & field) >> kHashShift; 7868 *index = (kArrayIndexHashMask & field) >> kHashShift;
7804 return true; 7869 return true;
7805 } else { 7870 } else {
7806 StringInputBuffer buffer(this); 7871 return ComputeArrayIndex(index);
7807 return ComputeArrayIndex(&buffer, index, length());
7808 } 7872 }
7809 } 7873 }
7810 7874
7811 7875
7812 String* SeqString::Truncate(int new_length) { 7876 String* SeqString::Truncate(int new_length) {
7813 Heap* heap = GetHeap(); 7877 Heap* heap = GetHeap();
7814 if (new_length <= 0) return heap->empty_string(); 7878 if (new_length <= 0) return heap->empty_string();
7815 7879
7816 int string_size, allocated_string_size; 7880 int string_size, allocated_string_size;
7817 int old_length = length(); 7881 int old_length = length();
(...skipping 6261 matching lines...) Expand 10 before | Expand all | Expand 10 after
14079 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 14143 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
14080 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 14144 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
14081 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 14145 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
14082 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 14146 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
14083 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 14147 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
14084 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 14148 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
14085 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 14149 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
14086 } 14150 }
14087 14151
14088 } } // namespace v8::internal 14152 } } // 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