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 19 matching lines...) Expand all Loading... |
30 #include "api.h" | 30 #include "api.h" |
31 #include "arguments.h" | 31 #include "arguments.h" |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "debug.h" | 33 #include "debug.h" |
34 #include "execution.h" | 34 #include "execution.h" |
35 #include "objects-inl.h" | 35 #include "objects-inl.h" |
36 #include "macro-assembler.h" | 36 #include "macro-assembler.h" |
37 #include "scanner.h" | 37 #include "scanner.h" |
38 #include "scopeinfo.h" | 38 #include "scopeinfo.h" |
39 #include "string-stream.h" | 39 #include "string-stream.h" |
| 40 #include "utils.h" |
40 | 41 |
41 #ifdef ENABLE_DISASSEMBLER | 42 #ifdef ENABLE_DISASSEMBLER |
42 #include "disassembler.h" | 43 #include "disassembler.h" |
43 #endif | 44 #endif |
44 | 45 |
45 | 46 |
46 namespace v8 { | 47 namespace v8 { |
47 namespace internal { | 48 namespace internal { |
48 | 49 |
49 // Getters and setters are stored in a fixed array property. These are | 50 // Getters and setters are stored in a fixed array property. These are |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 | 748 |
748 int size = this->Size(); // Byte size of the original string. | 749 int size = this->Size(); // Byte size of the original string. |
749 if (size < ExternalString::kSize) { | 750 if (size < ExternalString::kSize) { |
750 // The string is too small to fit an external String in its place. This can | 751 // The string is too small to fit an external String in its place. This can |
751 // only happen for zero length strings. | 752 // only happen for zero length strings. |
752 return false; | 753 return false; |
753 } | 754 } |
754 ASSERT(size >= ExternalString::kSize); | 755 ASSERT(size >= ExternalString::kSize); |
755 bool is_symbol = this->IsSymbol(); | 756 bool is_symbol = this->IsSymbol(); |
756 int length = this->length(); | 757 int length = this->length(); |
| 758 int hash_field = this->hash_field(); |
757 | 759 |
758 // Morph the object to an external string by adjusting the map and | 760 // Morph the object to an external string by adjusting the map and |
759 // reinitializing the fields. | 761 // reinitializing the fields. |
760 this->set_map(ExternalTwoByteString::StringMap(length)); | 762 this->set_map(Heap::external_string_map()); |
761 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); | 763 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
762 self->set_length(length); | 764 self->set_length(length); |
| 765 self->set_hash_field(hash_field); |
763 self->set_resource(resource); | 766 self->set_resource(resource); |
764 // Additionally make the object into an external symbol if the original string | 767 // Additionally make the object into an external symbol if the original string |
765 // was a symbol to start with. | 768 // was a symbol to start with. |
766 if (is_symbol) { | 769 if (is_symbol) { |
767 self->Hash(); // Force regeneration of the hash value. | 770 self->Hash(); // Force regeneration of the hash value. |
768 // Now morph this external string into a external symbol. | 771 // Now morph this external string into a external symbol. |
769 self->set_map(ExternalTwoByteString::SymbolMap(length)); | 772 this->set_map(Heap::external_symbol_map()); |
770 } | 773 } |
771 | 774 |
772 // Fill the remainder of the string with dead wood. | 775 // Fill the remainder of the string with dead wood. |
773 int new_size = this->Size(); // Byte size of the external String object. | 776 int new_size = this->Size(); // Byte size of the external String object. |
774 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 777 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); |
775 return true; | 778 return true; |
776 } | 779 } |
777 | 780 |
778 | 781 |
779 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 782 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
(...skipping 11 matching lines...) Expand all Loading... |
791 | 794 |
792 int size = this->Size(); // Byte size of the original string. | 795 int size = this->Size(); // Byte size of the original string. |
793 if (size < ExternalString::kSize) { | 796 if (size < ExternalString::kSize) { |
794 // The string is too small to fit an external String in its place. This can | 797 // The string is too small to fit an external String in its place. This can |
795 // only happen for zero length strings. | 798 // only happen for zero length strings. |
796 return false; | 799 return false; |
797 } | 800 } |
798 ASSERT(size >= ExternalString::kSize); | 801 ASSERT(size >= ExternalString::kSize); |
799 bool is_symbol = this->IsSymbol(); | 802 bool is_symbol = this->IsSymbol(); |
800 int length = this->length(); | 803 int length = this->length(); |
| 804 int hash_field = this->hash_field(); |
801 | 805 |
802 // Morph the object to an external string by adjusting the map and | 806 // Morph the object to an external string by adjusting the map and |
803 // reinitializing the fields. | 807 // reinitializing the fields. |
804 this->set_map(ExternalAsciiString::StringMap(length)); | 808 this->set_map(Heap::external_ascii_string_map()); |
805 ExternalAsciiString* self = ExternalAsciiString::cast(this); | 809 ExternalAsciiString* self = ExternalAsciiString::cast(this); |
806 self->set_length(length); | 810 self->set_length(length); |
| 811 self->set_hash_field(hash_field); |
807 self->set_resource(resource); | 812 self->set_resource(resource); |
808 // Additionally make the object into an external symbol if the original string | 813 // Additionally make the object into an external symbol if the original string |
809 // was a symbol to start with. | 814 // was a symbol to start with. |
810 if (is_symbol) { | 815 if (is_symbol) { |
811 self->Hash(); // Force regeneration of the hash value. | 816 self->Hash(); // Force regeneration of the hash value. |
812 // Now morph this external string into a external symbol. | 817 // Now morph this external string into a external symbol. |
813 self->set_map(ExternalAsciiString::SymbolMap(length)); | 818 this->set_map(Heap::external_ascii_symbol_map()); |
814 } | 819 } |
815 | 820 |
816 // Fill the remainder of the string with dead wood. | 821 // Fill the remainder of the string with dead wood. |
817 int new_size = this->Size(); // Byte size of the external String object. | 822 int new_size = this->Size(); // Byte size of the external String object. |
818 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 823 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); |
819 return true; | 824 return true; |
820 } | 825 } |
821 | 826 |
822 | 827 |
823 void String::StringShortPrint(StringStream* accumulator) { | 828 void String::StringShortPrint(StringStream* accumulator) { |
824 int len = length(); | 829 int len = length(); |
825 if (len > kMaxMediumSize) { | 830 if (len > kMaxShortPrintLength) { |
826 accumulator->Add("<Very long string[%u]>", len); | 831 accumulator->Add("<Very long string[%u]>", len); |
827 return; | 832 return; |
828 } | 833 } |
829 | 834 |
830 if (!LooksValid()) { | 835 if (!LooksValid()) { |
831 accumulator->Add("<Invalid String>"); | 836 accumulator->Add("<Invalid String>"); |
832 return; | 837 return; |
833 } | 838 } |
834 | 839 |
835 StringInputBuffer buf(this); | 840 StringInputBuffer buf(this); |
(...skipping 3641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4477 string_compare_buffer_a.Reset(0, this); | 4482 string_compare_buffer_a.Reset(0, this); |
4478 return CompareStringContentsPartial(&string_compare_buffer_a, other); | 4483 return CompareStringContentsPartial(&string_compare_buffer_a, other); |
4479 } | 4484 } |
4480 } | 4485 } |
4481 | 4486 |
4482 | 4487 |
4483 bool String::MarkAsUndetectable() { | 4488 bool String::MarkAsUndetectable() { |
4484 if (StringShape(this).IsSymbol()) return false; | 4489 if (StringShape(this).IsSymbol()) return false; |
4485 | 4490 |
4486 Map* map = this->map(); | 4491 Map* map = this->map(); |
4487 if (map == Heap::short_string_map()) { | 4492 if (map == Heap::string_map()) { |
4488 this->set_map(Heap::undetectable_short_string_map()); | 4493 this->set_map(Heap::undetectable_string_map()); |
4489 return true; | 4494 return true; |
4490 } else if (map == Heap::medium_string_map()) { | 4495 } else if (map == Heap::ascii_string_map()) { |
4491 this->set_map(Heap::undetectable_medium_string_map()); | 4496 this->set_map(Heap::undetectable_ascii_string_map()); |
4492 return true; | |
4493 } else if (map == Heap::long_string_map()) { | |
4494 this->set_map(Heap::undetectable_long_string_map()); | |
4495 return true; | |
4496 } else if (map == Heap::short_ascii_string_map()) { | |
4497 this->set_map(Heap::undetectable_short_ascii_string_map()); | |
4498 return true; | |
4499 } else if (map == Heap::medium_ascii_string_map()) { | |
4500 this->set_map(Heap::undetectable_medium_ascii_string_map()); | |
4501 return true; | |
4502 } else if (map == Heap::long_ascii_string_map()) { | |
4503 this->set_map(Heap::undetectable_long_ascii_string_map()); | |
4504 return true; | 4497 return true; |
4505 } | 4498 } |
4506 // Rest cannot be marked as undetectable | 4499 // Rest cannot be marked as undetectable |
4507 return false; | 4500 return false; |
4508 } | 4501 } |
4509 | 4502 |
4510 | 4503 |
4511 bool String::IsEqualTo(Vector<const char> str) { | 4504 bool String::IsEqualTo(Vector<const char> str) { |
4512 int slen = length(); | 4505 int slen = length(); |
4513 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); | 4506 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); |
4514 decoder->Reset(str.start(), str.length()); | 4507 decoder->Reset(str.start(), str.length()); |
4515 int i; | 4508 int i; |
4516 for (i = 0; i < slen && decoder->has_more(); i++) { | 4509 for (i = 0; i < slen && decoder->has_more(); i++) { |
4517 uc32 r = decoder->GetNext(); | 4510 uc32 r = decoder->GetNext(); |
4518 if (Get(i) != r) return false; | 4511 if (Get(i) != r) return false; |
4519 } | 4512 } |
4520 return i == slen && !decoder->has_more(); | 4513 return i == slen && !decoder->has_more(); |
4521 } | 4514 } |
4522 | 4515 |
4523 | 4516 |
4524 uint32_t String::ComputeAndSetHash() { | 4517 uint32_t String::ComputeAndSetHash() { |
4525 // Should only be called if hash code has not yet been computed. | 4518 // Should only be called if hash code has not yet been computed. |
4526 ASSERT(!(length_field() & kHashComputedMask)); | 4519 ASSERT(!(hash_field() & kHashComputedMask)); |
4527 | 4520 |
4528 // Compute the hash code. | 4521 // Compute the hash code. |
4529 StringInputBuffer buffer(this); | 4522 StringInputBuffer buffer(this); |
4530 uint32_t field = ComputeLengthAndHashField(&buffer, length()); | 4523 uint32_t field = ComputeHashField(&buffer, length()); |
4531 | 4524 |
4532 // Store the hash code in the object. | 4525 // Store the hash code in the object. |
4533 set_length_field(field); | 4526 set_hash_field(field); |
4534 | 4527 |
4535 // Check the hash code is there. | 4528 // Check the hash code is there. |
4536 ASSERT(length_field() & kHashComputedMask); | 4529 ASSERT(hash_field() & kHashComputedMask); |
4537 uint32_t result = field >> kHashShift; | 4530 uint32_t result = field >> kHashShift; |
4538 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 4531 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
4539 return result; | 4532 return result; |
4540 } | 4533 } |
4541 | 4534 |
4542 | 4535 |
4543 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, | 4536 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, |
4544 uint32_t* index, | 4537 uint32_t* index, |
4545 int length) { | 4538 int length) { |
4546 if (length == 0 || length > kMaxArrayIndexSize) return false; | 4539 if (length == 0 || length > kMaxArrayIndexSize) return false; |
(...skipping 19 matching lines...) Expand all Loading... |
4566 } | 4559 } |
4567 | 4560 |
4568 *index = result; | 4561 *index = result; |
4569 return true; | 4562 return true; |
4570 } | 4563 } |
4571 | 4564 |
4572 | 4565 |
4573 bool String::SlowAsArrayIndex(uint32_t* index) { | 4566 bool String::SlowAsArrayIndex(uint32_t* index) { |
4574 if (length() <= kMaxCachedArrayIndexLength) { | 4567 if (length() <= kMaxCachedArrayIndexLength) { |
4575 Hash(); // force computation of hash code | 4568 Hash(); // force computation of hash code |
4576 uint32_t field = length_field(); | 4569 uint32_t field = hash_field(); |
4577 if ((field & kIsArrayIndexMask) == 0) return false; | 4570 if ((field & kIsArrayIndexMask) == 0) return false; |
4578 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift; | 4571 // Isolate the array index form the full hash field. |
| 4572 *index = (kArrayIndexHashMask & field) >> kHashShift; |
4579 return true; | 4573 return true; |
4580 } else { | 4574 } else { |
4581 StringInputBuffer buffer(this); | 4575 StringInputBuffer buffer(this); |
4582 return ComputeArrayIndex(&buffer, index, length()); | 4576 return ComputeArrayIndex(&buffer, index, length()); |
4583 } | 4577 } |
4584 } | 4578 } |
4585 | 4579 |
4586 | 4580 |
4587 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { | 4581 static inline uint32_t HashField(uint32_t hash, |
| 4582 bool is_array_index, |
| 4583 int length = -1) { |
4588 uint32_t result = | 4584 uint32_t result = |
4589 (hash << String::kLongLengthShift) | String::kHashComputedMask; | 4585 (hash << String::kHashShift) | String::kHashComputedMask; |
4590 if (is_array_index) result |= String::kIsArrayIndexMask; | 4586 if (is_array_index) { |
| 4587 // For array indexes mix the length into the hash as an array index could |
| 4588 // be zero. |
| 4589 ASSERT(length > 0); |
| 4590 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
| 4591 (1 << String::kArrayIndexValueBits)); |
| 4592 result |= String::kIsArrayIndexMask; |
| 4593 result |= length << String::kArrayIndexHashLengthShift; |
| 4594 } |
4591 return result; | 4595 return result; |
4592 } | 4596 } |
4593 | 4597 |
4594 | 4598 |
4595 uint32_t StringHasher::GetHashField() { | 4599 uint32_t StringHasher::GetHashField() { |
4596 ASSERT(is_valid()); | 4600 ASSERT(is_valid()); |
4597 if (length_ <= String::kMaxShortSize) { | 4601 if (length_ <= String::kMaxHashCalcLength) { |
4598 uint32_t payload; | |
4599 if (is_array_index()) { | 4602 if (is_array_index()) { |
4600 payload = v8::internal::HashField(array_index(), true); | 4603 return v8::internal::HashField(array_index(), true, length_); |
4601 } else { | 4604 } else { |
4602 payload = v8::internal::HashField(GetHash(), false); | 4605 return v8::internal::HashField(GetHash(), false); |
4603 } | 4606 } |
4604 return (payload & ((1 << String::kShortLengthShift) - 1)) | | |
4605 (length_ << String::kShortLengthShift); | |
4606 } else if (length_ <= String::kMaxMediumSize) { | |
4607 uint32_t payload = v8::internal::HashField(GetHash(), false); | 4607 uint32_t payload = v8::internal::HashField(GetHash(), false); |
4608 return (payload & ((1 << String::kMediumLengthShift) - 1)) | | 4608 return payload; |
4609 (length_ << String::kMediumLengthShift); | |
4610 } else { | 4609 } else { |
4611 return v8::internal::HashField(length_, false); | 4610 return v8::internal::HashField(length_, false); |
4612 } | 4611 } |
4613 } | 4612 } |
4614 | 4613 |
4615 | 4614 |
4616 uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, | 4615 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, |
4617 int length) { | 4616 int length) { |
4618 StringHasher hasher(length); | 4617 StringHasher hasher(length); |
4619 | 4618 |
4620 // Very long strings have a trivial hash that doesn't inspect the | 4619 // Very long strings have a trivial hash that doesn't inspect the |
4621 // string contents. | 4620 // string contents. |
4622 if (hasher.has_trivial_hash()) { | 4621 if (hasher.has_trivial_hash()) { |
4623 return hasher.GetHashField(); | 4622 return hasher.GetHashField(); |
4624 } | 4623 } |
4625 | 4624 |
4626 // Do the iterative array index computation as long as there is a | 4625 // Do the iterative array index computation as long as there is a |
4627 // chance this is an array index. | 4626 // chance this is an array index. |
(...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6170 LookupResult result; | 6169 LookupResult result; |
6171 LocalLookupRealNamedProperty(name, &result); | 6170 LocalLookupRealNamedProperty(name, &result); |
6172 if (result.IsValid()) return GetProperty(receiver, &result, name, attributes); | 6171 if (result.IsValid()) return GetProperty(receiver, &result, name, attributes); |
6173 // Continue searching via the prototype chain. | 6172 // Continue searching via the prototype chain. |
6174 Object* pt = GetPrototype(); | 6173 Object* pt = GetPrototype(); |
6175 *attributes = ABSENT; | 6174 *attributes = ABSENT; |
6176 if (pt == Heap::null_value()) return Heap::undefined_value(); | 6175 if (pt == Heap::null_value()) return Heap::undefined_value(); |
6177 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 6176 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
6178 } | 6177 } |
6179 | 6178 |
| 6179 |
6180 Object* JSObject::GetLocalPropertyPostInterceptor( | 6180 Object* JSObject::GetLocalPropertyPostInterceptor( |
6181 JSObject* receiver, | 6181 JSObject* receiver, |
6182 String* name, | 6182 String* name, |
6183 PropertyAttributes* attributes) { | 6183 PropertyAttributes* attributes) { |
6184 // Check local property in holder, ignore interceptor. | 6184 // Check local property in holder, ignore interceptor. |
6185 LookupResult result; | 6185 LookupResult result; |
6186 LocalLookupRealNamedProperty(name, &result); | 6186 LocalLookupRealNamedProperty(name, &result); |
6187 if (!result.IsValid()) return Heap::undefined_value(); | 6187 if (!result.IsValid()) return Heap::undefined_value(); |
6188 return GetProperty(receiver, &result, name, attributes); | 6188 return GetProperty(receiver, &result, name, attributes); |
6189 } | 6189 } |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6730 } | 6730 } |
6731 | 6731 |
6732 String* string_; | 6732 String* string_; |
6733 Smi* flags_; | 6733 Smi* flags_; |
6734 }; | 6734 }; |
6735 | 6735 |
6736 // Utf8SymbolKey carries a vector of chars as key. | 6736 // Utf8SymbolKey carries a vector of chars as key. |
6737 class Utf8SymbolKey : public HashTableKey { | 6737 class Utf8SymbolKey : public HashTableKey { |
6738 public: | 6738 public: |
6739 explicit Utf8SymbolKey(Vector<const char> string) | 6739 explicit Utf8SymbolKey(Vector<const char> string) |
6740 : string_(string), length_field_(0) { } | 6740 : string_(string), hash_field_(0) { } |
6741 | 6741 |
6742 bool IsMatch(Object* string) { | 6742 bool IsMatch(Object* string) { |
6743 return String::cast(string)->IsEqualTo(string_); | 6743 return String::cast(string)->IsEqualTo(string_); |
6744 } | 6744 } |
6745 | 6745 |
6746 uint32_t Hash() { | 6746 uint32_t Hash() { |
6747 if (length_field_ != 0) return length_field_ >> String::kHashShift; | 6747 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; |
6748 unibrow::Utf8InputBuffer<> buffer(string_.start(), | 6748 unibrow::Utf8InputBuffer<> buffer(string_.start(), |
6749 static_cast<unsigned>(string_.length())); | 6749 static_cast<unsigned>(string_.length())); |
6750 chars_ = buffer.Length(); | 6750 chars_ = buffer.Length(); |
6751 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); | 6751 hash_field_ = String::ComputeHashField(&buffer, chars_); |
6752 uint32_t result = length_field_ >> String::kHashShift; | 6752 uint32_t result = hash_field_ >> String::kHashShift; |
6753 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 6753 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
6754 return result; | 6754 return result; |
6755 } | 6755 } |
6756 | 6756 |
6757 uint32_t HashForObject(Object* other) { | 6757 uint32_t HashForObject(Object* other) { |
6758 return String::cast(other)->Hash(); | 6758 return String::cast(other)->Hash(); |
6759 } | 6759 } |
6760 | 6760 |
6761 Object* AsObject() { | 6761 Object* AsObject() { |
6762 if (length_field_ == 0) Hash(); | 6762 if (hash_field_ == 0) Hash(); |
6763 return Heap::AllocateSymbol(string_, chars_, length_field_); | 6763 return Heap::AllocateSymbol(string_, chars_, hash_field_); |
6764 } | 6764 } |
6765 | 6765 |
6766 Vector<const char> string_; | 6766 Vector<const char> string_; |
6767 uint32_t length_field_; | 6767 uint32_t hash_field_; |
6768 int chars_; // Caches the number of characters when computing the hash code. | 6768 int chars_; // Caches the number of characters when computing the hash code. |
6769 }; | 6769 }; |
6770 | 6770 |
6771 | 6771 |
6772 // SymbolKey carries a string/symbol object as key. | 6772 // SymbolKey carries a string/symbol object as key. |
6773 class SymbolKey : public HashTableKey { | 6773 class SymbolKey : public HashTableKey { |
6774 public: | 6774 public: |
6775 explicit SymbolKey(String* string) : string_(string) { } | 6775 explicit SymbolKey(String* string) : string_(string) { } |
6776 | 6776 |
6777 bool IsMatch(Object* string) { | 6777 bool IsMatch(Object* string) { |
(...skipping 20 matching lines...) Expand all Loading... |
6798 Map* map = Heap::SymbolMapForString(string_); | 6798 Map* map = Heap::SymbolMapForString(string_); |
6799 if (map != NULL) { | 6799 if (map != NULL) { |
6800 string_->set_map(map); | 6800 string_->set_map(map); |
6801 ASSERT(string_->IsSymbol()); | 6801 ASSERT(string_->IsSymbol()); |
6802 return string_; | 6802 return string_; |
6803 } | 6803 } |
6804 // Otherwise allocate a new symbol. | 6804 // Otherwise allocate a new symbol. |
6805 StringInputBuffer buffer(string_); | 6805 StringInputBuffer buffer(string_); |
6806 return Heap::AllocateInternalSymbol(&buffer, | 6806 return Heap::AllocateInternalSymbol(&buffer, |
6807 string_->length(), | 6807 string_->length(), |
6808 string_->length_field()); | 6808 string_->hash_field()); |
6809 } | 6809 } |
6810 | 6810 |
6811 static uint32_t StringHash(Object* obj) { | 6811 static uint32_t StringHash(Object* obj) { |
6812 return String::cast(obj)->Hash(); | 6812 return String::cast(obj)->Hash(); |
6813 } | 6813 } |
6814 | 6814 |
6815 String* string_; | 6815 String* string_; |
6816 }; | 6816 }; |
6817 | 6817 |
6818 | 6818 |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8288 if (break_point_objects()->IsUndefined()) return 0; | 8288 if (break_point_objects()->IsUndefined()) return 0; |
8289 // Single beak point. | 8289 // Single beak point. |
8290 if (!break_point_objects()->IsFixedArray()) return 1; | 8290 if (!break_point_objects()->IsFixedArray()) return 1; |
8291 // Multiple break points. | 8291 // Multiple break points. |
8292 return FixedArray::cast(break_point_objects())->length(); | 8292 return FixedArray::cast(break_point_objects())->length(); |
8293 } | 8293 } |
8294 #endif | 8294 #endif |
8295 | 8295 |
8296 | 8296 |
8297 } } // namespace v8::internal | 8297 } } // namespace v8::internal |
OLD | NEW |