| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3782 if (other->IsEmpty()) return false; | 3782 if (other->IsEmpty()) return false; |
| 3783 if (length() != other->length()) return false; | 3783 if (length() != other->length()) return false; |
| 3784 for (int i = 0; i < length(); ++i) { | 3784 for (int i = 0; i < length(); ++i) { |
| 3785 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; | 3785 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; |
| 3786 } | 3786 } |
| 3787 return GetContentArray()->IsEqualTo(other->GetContentArray()); | 3787 return GetContentArray()->IsEqualTo(other->GetContentArray()); |
| 3788 } | 3788 } |
| 3789 #endif | 3789 #endif |
| 3790 | 3790 |
| 3791 | 3791 |
| 3792 static StaticResource<StringInputBuffer> string_input_buffer; | |
| 3793 | |
| 3794 | |
| 3795 bool String::LooksValid() { | 3792 bool String::LooksValid() { |
| 3796 if (!HEAP->Contains(this)) return false; | 3793 if (!HEAP->Contains(this)) return false; |
| 3797 return true; | 3794 return true; |
| 3798 } | 3795 } |
| 3799 | 3796 |
| 3800 | 3797 |
| 3801 int String::Utf8Length() { | 3798 int String::Utf8Length() { |
| 3802 if (IsAsciiRepresentation()) return length(); | 3799 if (IsAsciiRepresentation()) return length(); |
| 3803 // Attempt to flatten before accessing the string. It probably | 3800 // Attempt to flatten before accessing the string. It probably |
| 3804 // doesn't make Utf8Length faster, but it is very likely that | 3801 // doesn't make Utf8Length faster, but it is very likely that |
| 3805 // the string will be accessed later (for example by WriteUtf8) | 3802 // the string will be accessed later (for example by WriteUtf8) |
| 3806 // so it's still a good idea. | 3803 // so it's still a good idea. |
| 3807 TryFlatten(); | 3804 TryFlatten(); |
| 3808 Access<StringInputBuffer> buffer(&string_input_buffer); | 3805 Access<StringInputBuffer> buffer( |
| 3806 Isolate::Current()->objects_string_input_buffer()); |
| 3809 buffer->Reset(0, this); | 3807 buffer->Reset(0, this); |
| 3810 int result = 0; | 3808 int result = 0; |
| 3811 while (buffer->has_more()) | 3809 while (buffer->has_more()) |
| 3812 result += unibrow::Utf8::Length(buffer->GetNext()); | 3810 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 3813 return result; | 3811 return result; |
| 3814 } | 3812 } |
| 3815 | 3813 |
| 3816 | 3814 |
| 3817 Vector<const char> String::ToAsciiVector() { | 3815 Vector<const char> String::ToAsciiVector() { |
| 3818 ASSERT(IsAsciiRepresentation()); | 3816 ASSERT(IsAsciiRepresentation()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3873 int* length_return) { | 3871 int* length_return) { |
| 3874 ASSERT(NativeAllocationChecker::allocation_allowed()); | 3872 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 3875 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 3873 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 3876 return SmartPointer<char>(NULL); | 3874 return SmartPointer<char>(NULL); |
| 3877 } | 3875 } |
| 3878 | 3876 |
| 3879 // Negative length means the to the end of the string. | 3877 // Negative length means the to the end of the string. |
| 3880 if (length < 0) length = kMaxInt - offset; | 3878 if (length < 0) length = kMaxInt - offset; |
| 3881 | 3879 |
| 3882 // Compute the size of the UTF-8 string. Start at the specified offset. | 3880 // Compute the size of the UTF-8 string. Start at the specified offset. |
| 3883 Access<StringInputBuffer> buffer(&string_input_buffer); | 3881 Access<StringInputBuffer> buffer( |
| 3882 Isolate::Current()->objects_string_input_buffer()); |
| 3884 buffer->Reset(offset, this); | 3883 buffer->Reset(offset, this); |
| 3885 int character_position = offset; | 3884 int character_position = offset; |
| 3886 int utf8_bytes = 0; | 3885 int utf8_bytes = 0; |
| 3887 while (buffer->has_more()) { | 3886 while (buffer->has_more()) { |
| 3888 uint16_t character = buffer->GetNext(); | 3887 uint16_t character = buffer->GetNext(); |
| 3889 if (character_position < offset + length) { | 3888 if (character_position < offset + length) { |
| 3890 utf8_bytes += unibrow::Utf8::Length(character); | 3889 utf8_bytes += unibrow::Utf8::Length(character); |
| 3891 } | 3890 } |
| 3892 character_position++; | 3891 character_position++; |
| 3893 } | 3892 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3948 } | 3947 } |
| 3949 | 3948 |
| 3950 | 3949 |
| 3951 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 3950 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
| 3952 ASSERT(NativeAllocationChecker::allocation_allowed()); | 3951 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 3953 | 3952 |
| 3954 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 3953 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 3955 return SmartPointer<uc16>(); | 3954 return SmartPointer<uc16>(); |
| 3956 } | 3955 } |
| 3957 | 3956 |
| 3958 Access<StringInputBuffer> buffer(&string_input_buffer); | 3957 Access<StringInputBuffer> buffer( |
| 3958 Isolate::Current()->objects_string_input_buffer()); |
| 3959 buffer->Reset(this); | 3959 buffer->Reset(this); |
| 3960 | 3960 |
| 3961 uc16* result = NewArray<uc16>(length() + 1); | 3961 uc16* result = NewArray<uc16>(length() + 1); |
| 3962 | 3962 |
| 3963 int i = 0; | 3963 int i = 0; |
| 3964 while (buffer->has_more()) { | 3964 while (buffer->has_more()) { |
| 3965 uint16_t character = buffer->GetNext(); | 3965 uint16_t character = buffer->GetNext(); |
| 3966 result[i++] = character; | 3966 result[i++] = character; |
| 3967 } | 3967 } |
| 3968 result[i] = 0; | 3968 result[i] = 0; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4231 } | 4231 } |
| 4232 default: | 4232 default: |
| 4233 break; | 4233 break; |
| 4234 } | 4234 } |
| 4235 | 4235 |
| 4236 UNREACHABLE(); | 4236 UNREACHABLE(); |
| 4237 return 0; | 4237 return 0; |
| 4238 } | 4238 } |
| 4239 | 4239 |
| 4240 | 4240 |
| 4241 Relocatable* Relocatable::top_ = NULL; | |
| 4242 | |
| 4243 | |
| 4244 void Relocatable::PostGarbageCollectionProcessing() { | 4241 void Relocatable::PostGarbageCollectionProcessing() { |
| 4245 Relocatable* current = top_; | 4242 Isolate* isolate = Isolate::Current(); |
| 4243 Relocatable* current = isolate->relocatable_top(); |
| 4246 while (current != NULL) { | 4244 while (current != NULL) { |
| 4247 current->PostGarbageCollection(); | 4245 current->PostGarbageCollection(); |
| 4248 current = current->prev_; | 4246 current = current->prev_; |
| 4249 } | 4247 } |
| 4250 } | 4248 } |
| 4251 | 4249 |
| 4252 | 4250 |
| 4253 // Reserve space for statics needing saving and restoring. | 4251 // Reserve space for statics needing saving and restoring. |
| 4254 int Relocatable::ArchiveSpacePerThread() { | 4252 int Relocatable::ArchiveSpacePerThread() { |
| 4255 return sizeof(top_); | 4253 return sizeof(Isolate::Current()->relocatable_top()); |
| 4256 } | 4254 } |
| 4257 | 4255 |
| 4258 | 4256 |
| 4259 // Archive statics that are thread local. | 4257 // Archive statics that are thread local. |
| 4260 char* Relocatable::ArchiveState(char* to) { | 4258 char* Relocatable::ArchiveState(char* to) { |
| 4261 *reinterpret_cast<Relocatable**>(to) = top_; | 4259 Isolate* isolate = Isolate::Current(); |
| 4262 top_ = NULL; | 4260 *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top(); |
| 4261 isolate->set_relocatable_top(NULL); |
| 4263 return to + ArchiveSpacePerThread(); | 4262 return to + ArchiveSpacePerThread(); |
| 4264 } | 4263 } |
| 4265 | 4264 |
| 4266 | 4265 |
| 4267 // Restore statics that are thread local. | 4266 // Restore statics that are thread local. |
| 4268 char* Relocatable::RestoreState(char* from) { | 4267 char* Relocatable::RestoreState(char* from) { |
| 4269 top_ = *reinterpret_cast<Relocatable**>(from); | 4268 Isolate* isolate = Isolate::Current(); |
| 4269 isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from)); |
| 4270 return from + ArchiveSpacePerThread(); | 4270 return from + ArchiveSpacePerThread(); |
| 4271 } | 4271 } |
| 4272 | 4272 |
| 4273 | 4273 |
| 4274 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { | 4274 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 4275 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); | 4275 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); |
| 4276 Iterate(v, top); | 4276 Iterate(v, top); |
| 4277 return thread_storage + ArchiveSpacePerThread(); | 4277 return thread_storage + ArchiveSpacePerThread(); |
| 4278 } | 4278 } |
| 4279 | 4279 |
| 4280 | 4280 |
| 4281 void Relocatable::Iterate(ObjectVisitor* v) { | 4281 void Relocatable::Iterate(ObjectVisitor* v) { |
| 4282 Iterate(v, top_); | 4282 Isolate* isolate = Isolate::Current(); |
| 4283 Iterate(v, isolate->relocatable_top()); |
| 4283 } | 4284 } |
| 4284 | 4285 |
| 4285 | 4286 |
| 4286 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { | 4287 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { |
| 4287 Relocatable* current = top; | 4288 Relocatable* current = top; |
| 4288 while (current != NULL) { | 4289 while (current != NULL) { |
| 4289 current->IterateInstance(v); | 4290 current->IterateInstance(v); |
| 4290 current = current->prev_; | 4291 current = current->prev_; |
| 4291 } | 4292 } |
| 4292 } | 4293 } |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4651 // Compare the remaining characters that didn't fit into a block. | 4652 // Compare the remaining characters that didn't fit into a block. |
| 4652 for (; i < length; i++) { | 4653 for (; i < length; i++) { |
| 4653 if (a[i] != b[i]) { | 4654 if (a[i] != b[i]) { |
| 4654 return false; | 4655 return false; |
| 4655 } | 4656 } |
| 4656 } | 4657 } |
| 4657 return true; | 4658 return true; |
| 4658 } | 4659 } |
| 4659 | 4660 |
| 4660 | 4661 |
| 4661 static StringInputBuffer string_compare_buffer_b; | |
| 4662 | |
| 4663 | |
| 4664 template <typename IteratorA> | 4662 template <typename IteratorA> |
| 4665 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { | 4663 static inline bool CompareStringContentsPartial(Isolate* isolate, |
| 4664 IteratorA* ia, |
| 4665 String* b) { |
| 4666 if (b->IsFlat()) { | 4666 if (b->IsFlat()) { |
| 4667 if (b->IsAsciiRepresentation()) { | 4667 if (b->IsAsciiRepresentation()) { |
| 4668 VectorIterator<char> ib(b->ToAsciiVector()); | 4668 VectorIterator<char> ib(b->ToAsciiVector()); |
| 4669 return CompareStringContents(ia, &ib); | 4669 return CompareStringContents(ia, &ib); |
| 4670 } else { | 4670 } else { |
| 4671 VectorIterator<uc16> ib(b->ToUC16Vector()); | 4671 VectorIterator<uc16> ib(b->ToUC16Vector()); |
| 4672 return CompareStringContents(ia, &ib); | 4672 return CompareStringContents(ia, &ib); |
| 4673 } | 4673 } |
| 4674 } else { | 4674 } else { |
| 4675 string_compare_buffer_b.Reset(0, b); | 4675 isolate->objects_string_compare_buffer_b()->Reset(0, b); |
| 4676 return CompareStringContents(ia, &string_compare_buffer_b); | 4676 return CompareStringContents(ia, |
| 4677 isolate->objects_string_compare_buffer_b()); |
| 4677 } | 4678 } |
| 4678 } | 4679 } |
| 4679 | 4680 |
| 4680 | 4681 |
| 4681 static StringInputBuffer string_compare_buffer_a; | |
| 4682 | |
| 4683 | |
| 4684 bool String::SlowEquals(String* other) { | 4682 bool String::SlowEquals(String* other) { |
| 4685 // Fast check: negative check with lengths. | 4683 // Fast check: negative check with lengths. |
| 4686 int len = length(); | 4684 int len = length(); |
| 4687 if (len != other->length()) return false; | 4685 if (len != other->length()) return false; |
| 4688 if (len == 0) return true; | 4686 if (len == 0) return true; |
| 4689 | 4687 |
| 4690 // Fast check: if hash code is computed for both strings | 4688 // Fast check: if hash code is computed for both strings |
| 4691 // a fast negative check can be performed. | 4689 // a fast negative check can be performed. |
| 4692 if (HasHashCode() && other->HasHashCode()) { | 4690 if (HasHashCode() && other->HasHashCode()) { |
| 4693 if (Hash() != other->Hash()) return false; | 4691 if (Hash() != other->Hash()) return false; |
| 4694 } | 4692 } |
| 4695 | 4693 |
| 4696 // We know the strings are both non-empty. Compare the first chars | 4694 // We know the strings are both non-empty. Compare the first chars |
| 4697 // before we try to flatten the strings. | 4695 // before we try to flatten the strings. |
| 4698 if (this->Get(0) != other->Get(0)) return false; | 4696 if (this->Get(0) != other->Get(0)) return false; |
| 4699 | 4697 |
| 4700 String* lhs = this->TryFlattenGetString(); | 4698 String* lhs = this->TryFlattenGetString(); |
| 4701 String* rhs = other->TryFlattenGetString(); | 4699 String* rhs = other->TryFlattenGetString(); |
| 4702 | 4700 |
| 4703 if (StringShape(lhs).IsSequentialAscii() && | 4701 if (StringShape(lhs).IsSequentialAscii() && |
| 4704 StringShape(rhs).IsSequentialAscii()) { | 4702 StringShape(rhs).IsSequentialAscii()) { |
| 4705 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); | 4703 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); |
| 4706 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); | 4704 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); |
| 4707 return CompareRawStringContents(Vector<const char>(str1, len), | 4705 return CompareRawStringContents(Vector<const char>(str1, len), |
| 4708 Vector<const char>(str2, len)); | 4706 Vector<const char>(str2, len)); |
| 4709 } | 4707 } |
| 4710 | 4708 |
| 4709 Isolate* isolate = Isolate::Current(); |
| 4711 if (lhs->IsFlat()) { | 4710 if (lhs->IsFlat()) { |
| 4712 if (IsAsciiRepresentation()) { | 4711 if (IsAsciiRepresentation()) { |
| 4713 Vector<const char> vec1 = lhs->ToAsciiVector(); | 4712 Vector<const char> vec1 = lhs->ToAsciiVector(); |
| 4714 if (rhs->IsFlat()) { | 4713 if (rhs->IsFlat()) { |
| 4715 if (rhs->IsAsciiRepresentation()) { | 4714 if (rhs->IsAsciiRepresentation()) { |
| 4716 Vector<const char> vec2 = rhs->ToAsciiVector(); | 4715 Vector<const char> vec2 = rhs->ToAsciiVector(); |
| 4717 return CompareRawStringContents(vec1, vec2); | 4716 return CompareRawStringContents(vec1, vec2); |
| 4718 } else { | 4717 } else { |
| 4719 VectorIterator<char> buf1(vec1); | 4718 VectorIterator<char> buf1(vec1); |
| 4720 VectorIterator<uc16> ib(rhs->ToUC16Vector()); | 4719 VectorIterator<uc16> ib(rhs->ToUC16Vector()); |
| 4721 return CompareStringContents(&buf1, &ib); | 4720 return CompareStringContents(&buf1, &ib); |
| 4722 } | 4721 } |
| 4723 } else { | 4722 } else { |
| 4724 VectorIterator<char> buf1(vec1); | 4723 VectorIterator<char> buf1(vec1); |
| 4725 string_compare_buffer_b.Reset(0, rhs); | 4724 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 4726 return CompareStringContents(&buf1, &string_compare_buffer_b); | 4725 return CompareStringContents(&buf1, |
| 4726 isolate->objects_string_compare_buffer_b()); |
| 4727 } | 4727 } |
| 4728 } else { | 4728 } else { |
| 4729 Vector<const uc16> vec1 = lhs->ToUC16Vector(); | 4729 Vector<const uc16> vec1 = lhs->ToUC16Vector(); |
| 4730 if (rhs->IsFlat()) { | 4730 if (rhs->IsFlat()) { |
| 4731 if (rhs->IsAsciiRepresentation()) { | 4731 if (rhs->IsAsciiRepresentation()) { |
| 4732 VectorIterator<uc16> buf1(vec1); | 4732 VectorIterator<uc16> buf1(vec1); |
| 4733 VectorIterator<char> ib(rhs->ToAsciiVector()); | 4733 VectorIterator<char> ib(rhs->ToAsciiVector()); |
| 4734 return CompareStringContents(&buf1, &ib); | 4734 return CompareStringContents(&buf1, &ib); |
| 4735 } else { | 4735 } else { |
| 4736 Vector<const uc16> vec2(rhs->ToUC16Vector()); | 4736 Vector<const uc16> vec2(rhs->ToUC16Vector()); |
| 4737 return CompareRawStringContents(vec1, vec2); | 4737 return CompareRawStringContents(vec1, vec2); |
| 4738 } | 4738 } |
| 4739 } else { | 4739 } else { |
| 4740 VectorIterator<uc16> buf1(vec1); | 4740 VectorIterator<uc16> buf1(vec1); |
| 4741 string_compare_buffer_b.Reset(0, rhs); | 4741 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 4742 return CompareStringContents(&buf1, &string_compare_buffer_b); | 4742 return CompareStringContents(&buf1, |
| 4743 isolate->objects_string_compare_buffer_b()); |
| 4743 } | 4744 } |
| 4744 } | 4745 } |
| 4745 } else { | 4746 } else { |
| 4746 string_compare_buffer_a.Reset(0, lhs); | 4747 isolate->objects_string_compare_buffer_a()->Reset(0, lhs); |
| 4747 return CompareStringContentsPartial(&string_compare_buffer_a, rhs); | 4748 return CompareStringContentsPartial(isolate, |
| 4749 isolate->objects_string_compare_buffer_a(), rhs); |
| 4748 } | 4750 } |
| 4749 } | 4751 } |
| 4750 | 4752 |
| 4751 | 4753 |
| 4752 bool String::MarkAsUndetectable() { | 4754 bool String::MarkAsUndetectable() { |
| 4753 if (StringShape(this).IsSymbol()) return false; | 4755 if (StringShape(this).IsSymbol()) return false; |
| 4754 | 4756 |
| 4755 Map* map = this->map(); | 4757 Map* map = this->map(); |
| 4756 if (map == HEAP->string_map()) { | 4758 if (map == HEAP->string_map()) { |
| 4757 this->set_map(HEAP->undetectable_string_map()); | 4759 this->set_map(HEAP->undetectable_string_map()); |
| (...skipping 3974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8732 if (break_point_objects()->IsUndefined()) return 0; | 8734 if (break_point_objects()->IsUndefined()) return 0; |
| 8733 // Single beak point. | 8735 // Single beak point. |
| 8734 if (!break_point_objects()->IsFixedArray()) return 1; | 8736 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8735 // Multiple break points. | 8737 // Multiple break points. |
| 8736 return FixedArray::cast(break_point_objects())->length(); | 8738 return FixedArray::cast(break_point_objects())->length(); |
| 8737 } | 8739 } |
| 8738 #endif | 8740 #endif |
| 8739 | 8741 |
| 8740 | 8742 |
| 8741 } } // namespace v8::internal | 8743 } } // namespace v8::internal |
| OLD | NEW |