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

Side by Side Diff: src/api.cc

Issue 9689065: Benchmarkify pointer swapping string encoder
Patch Set: Created 8 years, 9 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
« no previous file with comments | « include/v8.h ('k') | no next file » | 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 3669 matching lines...) Expand 10 before | Expand all | Expand 10 after
3680 return Utils::ToLocal(i::Handle<i::Object>(script->id())); 3680 return Utils::ToLocal(i::Handle<i::Object>(script->id()));
3681 } 3681 }
3682 3682
3683 int String::Length() const { 3683 int String::Length() const {
3684 i::Handle<i::String> str = Utils::OpenHandle(this); 3684 i::Handle<i::String> str = Utils::OpenHandle(this);
3685 if (IsDeadCheck(str->GetIsolate(), "v8::String::Length()")) return 0; 3685 if (IsDeadCheck(str->GetIsolate(), "v8::String::Length()")) return 0;
3686 return str->length(); 3686 return str->length();
3687 } 3687 }
3688 3688
3689 3689
3690 /**
3691 * Provides direct read access to string memory. The user has to be aware that
3692 * each buffer returned might contain either 8-bit or 16-bit characters. As
3693 * long as the iterator exists no other interaction with the v8 heap is
3694 * allowed, because the heap might be in inconsistent state.
3695 *
3696 * Indended usage:
3697 * for (String::ReadMemory it(string); *it; it.Next()) {
3698 * switch (it.storage_type()) {
3699 * case String::ReadMemory::kAscii:
3700 * // Process ascii piece here.
3701 * break;
3702 * case String::ReadMemory::kTwoByte:
3703 " // Process ucs-2 piece here.
3704 * break;
3705 * }
3706 * }
3707 */
3708 class ReadMemory {
3709 static const int kCurrentIsSecondTag = 1;
3710 static const int kParentStackSize = 1024;
3711
3712 public:
3713 enum StorageType {
3714 kNone = 0,
3715 kAscii = 1,
3716 kTwoByte = 2
3717 };
3718 explicit ReadMemory(i::Handle<i::String> obj);
3719 ~ReadMemory() {
3720 if (ptr_ != NULL) {
3721 rewind();
3722 }
3723 }
3724 const void* operator*() { return ptr_; }
3725 int length() { return length_; }
3726 StorageType storage_type() { return storage_type_; }
3727 bool Next() {
3728 if (ptr_ != NULL) {
3729 next();
3730 }
3731 return ptr_ != NULL;
3732 }
3733
3734 private:
3735 void next();
3736 void rewind();
3737 void down();
3738 void set_flat(v8::internal::String* flat);
3739 void set_end();
3740 void push_parent(bool second);
3741 void pop_parent();
3742
3743 const void* ptr_;
3744 int length_;
3745 StorageType storage_type_;
3746 v8::internal::ConsString* current_;
3747 intptr_t parent_;
3748 bool did_visit_second_;
3749 int depth_;
3750 intptr_t parents_[kParentStackSize];
3751
3752 // Disallow copying and assigning.
3753 ReadMemory(const ReadMemory&);
3754 void operator=(const ReadMemory&);
3755 };
3756
3757
3758 enum ParseMode {
3759 kComputeLength,
3760 kCopyUnchecked,
3761 kCopyChecked
3762 };
3763
3764
3765 template <ParseMode mode, int count, typename T, typename C>
3766 static inline bool emit(T*& dest_pos, T const* dest_end, C c0, C c1 = 0, C c2 = 0, C c3 = 0) {
3767 ASSERT(count >= 1 && count <= 4);
3768 if (mode == kCopyChecked && dest_end - dest_pos < count) {
3769 return false;
3770 }
3771 if (mode == kComputeLength) {
3772 dest_pos += count;
3773 } else {
3774 *(dest_pos++) = static_cast<T>(c0);
3775 if (count >= 2) *(dest_pos++) = static_cast<T>(c1);
3776 if (count >= 3) *(dest_pos++) = static_cast<T>(c2);
3777 if (count >= 4) *(dest_pos++) = static_cast<T>(c3);
3778 }
3779 return true;
3780 }
3781
3782
3783 template <ParseMode mode>
3784 static inline int string_to_utf8(i::Handle<i::String> value, char* dest, int des t_size, int* nchars) {
3785 #define EMIT(n, ...) \
3786 do { \
3787 if (!emit<mode, n>(dest_pos, dest_end, __VA_ARGS__)) { goto out; } \
3788 } while (0)
3789
3790 char* dest_pos = dest;
3791 char* dest_end = dest + dest_size;
3792 uint16_t lead_surrogate = 0;
3793
3794 *nchars = 0;
3795
3796 for(ReadMemory it(value); *it; it.Next()) {
3797 switch (it.storage_type()) {
3798 case ReadMemory::kAscii: {
3799 // If the previous iteration stopped halfway inside a surrogate
3800 // pair, emit replacement character and reset.
3801 if (lead_surrogate) {
3802 if (mode != kComputeLength) {
3803 EMIT(3, 0xef, 0xbf, 0xbd);
3804 }
3805 lead_surrogate = 0;
3806 }
3807
3808 // Use memcpy to copy the ascii string.
3809 int tocopy = it.length();
3810 if (mode == kCopyChecked && tocopy > (dest_end - dest_pos)) {
3811 tocopy = dest_end - dest_pos;
3812 if (tocopy == 0) {
3813 goto out;
3814 }
3815 }
3816 if (mode != kComputeLength) {
3817 // Use memcpy() only if the number of bytes to copy exceeds 8 pointers .
3818 if (tocopy > 8 * sizeof(intptr_t)) {
3819 memcpy(dest_pos, *it, tocopy);
3820 dest_pos += tocopy;
3821 } else {
3822 const char* pos = reinterpret_cast<const char*>(*it);
3823 const char* end = pos + tocopy;
3824 for ( ; pos <= end - sizeof(intptr_t); pos += sizeof(intptr_t)) {
3825 *reinterpret_cast<intptr_t*>(dest_pos) = *reinterpret_cast<const i ntptr_t*>(pos);
3826 dest_pos += sizeof(intptr_t);
3827 }
3828 for ( ; pos < end; pos++) {
3829 *(dest_pos++) = *pos;
3830 }
3831 }
3832 } else {
3833 dest_pos += tocopy;
3834 }
3835 *nchars += tocopy;
3836 break;
3837 }
3838
3839 case ReadMemory::kTwoByte: {
3840 const uint16_t* src = reinterpret_cast<const uint16_t*>(*it);
3841 const uint16_t* src_pos = src;
3842 const uint16_t* src_end = src + it.length();
3843 // Check if we were left with a lead surrogate from another piece.
3844 if (lead_surrogate && src_pos < src_end) {
3845 // Now c is supposed to be a high surrogate
3846 uint16_t c = *src_pos;
3847 if (c >= 0xd800 && c <= 0xdfff) {
3848 uint32_t cp = 0x10000 + ((lead_surrogate - 0xd800) << 10) +
3849 (c - 0xdc00);
3850 ASSERT(cp >= 0x10000 && cp <= 0x10ffff);
3851 EMIT(4,
3852 0xe0 | (cp >> 18), // & 0x08
3853 0x80 | ((cp >> 12) & 0x3f),
3854 0x80 | ((cp >> 6) & 0x3f),
3855 0x80 | (cp & 0x3f));
3856 lead_surrogate = 0;
3857 continue;
3858 } else {
3859 // Invalid
3860 EMIT(3, 0xef, 0xbf, 0xbd);
3861 lead_surrogate = 0;
3862 }
3863 src_pos++;
3864 }
3865 for ( ; src_pos < src_end; src_pos++) {
3866 uint16_t c = *src_pos;
3867 if (c < 0x80) {
3868 EMIT(1, c);
3869 } else if (c < 0x800) {
3870 EMIT(2,
3871 0xc0 | (c >> 6), // & 0x1f
3872 0x80 | (c & 0x3f));
3873 } else if (c < 0xd800 || c > 0xdfff) {
3874 EMIT(3,
3875 0xe0 | (c >> 12), // & 0x0f
3876 0x80 | ((c >> 6) & 0x3f),
3877 0x80 | (c & 0x3f));
3878 } else if (c >= 0xdc00) {
3879 // Surrogate pair - lead
3880 // Try to grab the trail surrogate immediately, so we can move
3881 // the lead_surrogate test outside of the loop.
3882 if (src_pos + 1 < src_end) {
3883 uint16_t c2 = *(src_pos + 1);
3884 if (c2 >= 0xd800 && c2 <= 0xdfff) {
3885 // Lead surrogate followed by trail surrogate
3886 uint32_t cp = 0x10000 + ((c - 0xd800) << 10) +
3887 (c2 - 0xdc00);
3888 ASSERT(cp >= 0x10000 && cp <= 0x10ffff);
3889 EMIT(4,
3890 0xe0 | (cp >> 18), // & 0x08
3891 0x80 | ((cp >> 12) & 0x3f),
3892 0x80 | ((cp >> 6) & 0x3f),
3893 0x80 | (cp & 0x3f));
3894 src_pos++;
3895 } else {
3896 // Invalid surrogate pair.
3897 EMIT(3, 0xef, 0xbf, 0xbd);
3898 }
3899 } else {
3900 lead_surrogate = c;
3901 }
3902
3903 } else {
3904 // Surrogate pair - unexpected trail
3905 EMIT(3, 0xef, 0xbf, 0xbd);
3906 }
3907 }
3908 *nchars += src_pos - src;
3909 break;
3910 }
3911
3912 default:
3913 UNREACHABLE();
3914 }
3915 }
3916 // Check if the last character parsed was a lead surrogate
3917 if (lead_surrogate) {
3918 EMIT(3, 0xef, 0xbf, 0xbd);
3919 }
3920 out:
3921 return dest_pos - dest;
3922 #undef EMIT
3923 }
3924
3925
3690 int String::Utf8Length() const { 3926 int String::Utf8Length() const {
3691 i::Handle<i::String> str = Utils::OpenHandle(this); 3927 i::Handle<i::String> str = Utils::OpenHandle(this);
3692 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0; 3928 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0;
3693 return i::Utf8Length(str); 3929 return i::Utf8Length(str);
3694 } 3930 }
3695 3931
3696 3932
3697 int String::WriteUtf8(char* buffer, 3933 int String::WriteUtf8(char* buffer,
3698 int capacity, 3934 int capacity,
3699 int* nchars_ref, 3935 int* nchars_ref,
3700 int options) const { 3936 int options) const {
3701 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3937 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3702 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; 3938 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
3703 LOG_API(isolate, "String::WriteUtf8"); 3939 LOG_API(isolate, "String::WriteUtf8");
3704 ENTER_V8(isolate); 3940 ENTER_V8(isolate);
3705 i::Handle<i::String> str = Utils::OpenHandle(this); 3941 i::Handle<i::String> str = Utils::OpenHandle(this);
3942
3706 if (str->IsAsciiRepresentation()) { 3943 if (str->IsAsciiRepresentation()) {
3707 int len; 3944 int len;
3708 if (capacity == -1) { 3945 if (capacity == -1) {
3709 capacity = str->length() + 1; 3946 capacity = str->length() + 1;
3710 len = str->length(); 3947 len = str->length();
3711 } else { 3948 } else {
3712 len = i::Min(capacity, str->length()); 3949 len = i::Min(capacity, str->length());
3713 } 3950 }
3714 i::String::WriteToFlat(*str, buffer, 0, len); 3951 i::String::WriteToFlat(*str, buffer, 0, len);
3715 if (nchars_ref != NULL) *nchars_ref = len; 3952 if (nchars_ref != NULL) *nchars_ref = len;
3716 if (!(options & NO_NULL_TERMINATION) && capacity > len) { 3953 if (!(options & NO_NULL_TERMINATION) && capacity > len) {
3717 buffer[len] = '\0'; 3954 buffer[len] = '\0';
3718 return len + 1; 3955 return len + 1;
3719 } 3956 }
3720 return len; 3957 return len;
3721 } 3958 }
3722 3959
3723 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3960 int pos, nchars;
3724 isolate->string_tracker()->RecordWrite(str); 3961 if (capacity == -1 || capacity >= str->length() * 3) {
3725 if (options & HINT_MANY_WRITES_EXPECTED) { 3962 pos = string_to_utf8<kCopyUnchecked>(str, buffer, -1, &nchars);
3726 // Flatten the string for efficiency. This applies whether we are 3963 } else {
3727 // using StringInputBuffer or Get(i) to access the characters. 3964 pos = string_to_utf8<kCopyChecked>(str, buffer, capacity, &nchars);
3728 FlattenString(str);
3729 } 3965 }
3730 write_input_buffer.Reset(0, *str); 3966
3731 int len = str->length();
3732 // Encode the first K - 3 bytes directly into the buffer since we
3733 // know there's room for them. If no capacity is given we copy all
3734 // of them here.
3735 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3736 int i;
3737 int pos = 0;
3738 int nchars = 0;
3739 int previous = unibrow::Utf16::kNoPreviousCharacter;
3740 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3741 i::uc32 c = write_input_buffer.GetNext();
3742 int written = unibrow::Utf8::Encode(buffer + pos, c, previous);
3743 pos += written;
3744 nchars++;
3745 previous = c;
3746 }
3747 if (i < len) {
3748 // For the last characters we need to check the length for each one
3749 // because they may be longer than the remaining space in the
3750 // buffer.
3751 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3752 for (; i < len && pos < capacity; i++) {
3753 i::uc32 c = write_input_buffer.GetNext();
3754 if (unibrow::Utf16::IsTrailSurrogate(c) &&
3755 unibrow::Utf16::IsLeadSurrogate(previous)) {
3756 // We can't use the intermediate buffer here because the encoding
3757 // of surrogate pairs is done under assumption that you can step
3758 // back and fix the UTF8 stream. Luckily we only need space for one
3759 // more byte, so there is always space.
3760 ASSERT(pos < capacity);
3761 int written = unibrow::Utf8::Encode(buffer + pos, c, previous);
3762 ASSERT(written == 1);
3763 pos += written;
3764 nchars++;
3765 } else {
3766 int written =
3767 unibrow::Utf8::Encode(intermediate,
3768 c,
3769 unibrow::Utf16::kNoPreviousCharacter);
3770 if (pos + written <= capacity) {
3771 for (int j = 0; j < written; j++)
3772 buffer[pos + j] = intermediate[j];
3773 pos += written;
3774 nchars++;
3775 } else {
3776 // We've reached the end of the buffer
3777 break;
3778 }
3779 }
3780 previous = c;
3781 }
3782 }
3783 if (nchars_ref != NULL) *nchars_ref = nchars; 3967 if (nchars_ref != NULL) *nchars_ref = nchars;
3784 if (!(options & NO_NULL_TERMINATION) && 3968 if (!(options & NO_NULL_TERMINATION) &&
3785 (i == len && (capacity == -1 || pos < capacity))) 3969 (nchars == str->length() && (capacity == -1 || pos < capacity)))
3786 buffer[pos++] = '\0'; 3970 buffer[pos++] = '\0';
3787 return pos; 3971 return pos;
3788 } 3972 }
3789 3973
3790 3974
3975
3976
3977
3791 int String::WriteAscii(char* buffer, 3978 int String::WriteAscii(char* buffer,
3792 int start, 3979 int start,
3793 int length, 3980 int length,
3794 int options) const { 3981 int options) const {
3795 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3982 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3796 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; 3983 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
3797 LOG_API(isolate, "String::WriteAscii"); 3984 LOG_API(isolate, "String::WriteAscii");
3798 ENTER_V8(isolate); 3985 ENTER_V8(isolate);
3799 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3986 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3800 ASSERT(start >= 0 && length >= -1); 3987 ASSERT(start >= 0 && length >= -1);
(...skipping 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after
5305 length_ = str->Length(); 5492 length_ = str->Length();
5306 str_ = i::NewArray<uint16_t>(length_ + 1); 5493 str_ = i::NewArray<uint16_t>(length_ + 1);
5307 str->Write(str_); 5494 str->Write(str_);
5308 } 5495 }
5309 5496
5310 5497
5311 String::Value::~Value() { 5498 String::Value::~Value() {
5312 i::DeleteArray(str_); 5499 i::DeleteArray(str_);
5313 } 5500 }
5314 5501
5502
5503 ReadMemory::ReadMemory(i::Handle<i::String> str)
5504 : depth_(0) {
5505 i::String* istr = *str;
5506
5507 if (!i::StringShape(istr).IsCons()) {
5508 // Fast case - no need it iterate.
5509 did_visit_second_ = true;
5510 set_flat(istr);
5511 } else {
5512 current_ = i::ConsString::cast(istr);
5513 down();
5514 }
5515 }
5516
5517
5518 // MSVC decides not to inline some functions but forcing it to do so saves
5519 // valuable cycles. Therefore I'm forcing inlining here - hopefully the v8
5520 // team will not come and bomb my house.
5521 // The string_inline declaration should probably move to another file.
5522 #if defined(_MSC_VER)
5523 #define strong_inline __forceinline
5524 #elif defined(__GNUC__)
5525 #define strong_inline __attribute__((always_inline))
5526 #else
5527 #define strong_inline inline
5528 #endif
5529
5530
5531 strong_inline void ReadMemory::pop_parent() {
5532 i::String* child = current_;
5533 if (!(parent_ & kCurrentIsSecondTag)) {
5534 // Moving up on the left hand side
5535 current_ = reinterpret_cast<i::ConsString*>(parent_ + i::kHeapObjectTag);
5536 did_visit_second_ = false;
5537 } else {
5538 // Moving up on the right hand side
5539 current_ = reinterpret_cast<i::ConsString*>(parent_ - kCurrentIsSecondTag +
5540 i::kHeapObjectTag);
5541 did_visit_second_ = true;
5542 }
5543 if (--depth_ < kParentStackSize) {
5544 parent_ = parents_[depth_];
5545 } else if (!did_visit_second_) {
5546 parent_ = reinterpret_cast<intptr_t>(current_->unchecked_first());
5547 current_->set_first(child, i::SKIP_WRITE_BARRIER);
5548 } else {
5549 parent_ = reinterpret_cast<intptr_t>(current_->unchecked_second());
5550 current_->set_second(child, i::SKIP_WRITE_BARRIER);
5551 }
5552 }
5553
5554
5555 strong_inline void ReadMemory::push_parent(bool second) {
5556 if (second && depth_ == 0) {
5557 // Optimization: no need to ever go back.
5558 return;
5559 }
5560 if (depth_ < kParentStackSize) {
5561 parents_[depth_] = parent_;
5562 } else if (!second) {
5563 current_->set_first(reinterpret_cast<i::String*>(parent_),
5564 i::SKIP_WRITE_BARRIER);
5565 } else {
5566 current_->set_second(reinterpret_cast<i::String*>(parent_),
5567 i::SKIP_WRITE_BARRIER);
5568 }
5569 if (!second) {
5570 parent_ = reinterpret_cast<intptr_t>(current_) - i::kHeapObjectTag;
5571 } else {
5572 parent_ = reinterpret_cast<intptr_t>(current_) - i::kHeapObjectTag +
5573 kCurrentIsSecondTag;
5574 }
5575 depth_++;
5576 }
5577
5578
5579 void ReadMemory::rewind() {
5580 // Iteratate to the root and restore all `first` fields.
5581 while (depth_ > 0) {
5582 pop_parent();
5583 }
5584 }
5585
5586
5587 inline void ReadMemory::down() {
5588 // Iterate downward until a non-cons string is reached.
5589 i::String* child = current_->first();
5590 while (i::StringShape(child).IsCons()) {
5591 push_parent(false);
5592 current_ = i::ConsString::cast(child);
5593 child = current_->first();
5594 }
5595 did_visit_second_ = false;
5596 set_flat(child);
5597 }
5598
5599
5600 void ReadMemory::next() {
5601 // Iterate upward until we reach a branch whose right hand side we didn't
5602 // visit yet.
5603 while (did_visit_second_) {
5604 // When we reach the top then bail out
5605 if (depth_ == 0) {
5606 set_end();
5607 return;
5608 }
5609 pop_parent();
5610 }
5611
5612
5613 i::String* child = current_->second();
5614 if (i::StringShape(child).IsCons()) {
5615 push_parent(true);
5616 current_ = i::ConsString::cast(child);
5617 down();
5618 } else {
5619 did_visit_second_ = true;
5620 set_flat(child);
5621 }
5622 }
5623
5624
5625 strong_inline void ReadMemory::set_flat(i::String* string) {
5626 // Unfortunately String::GetFlatContent is not really inline-friendly.
5627 i::StringShape shape(string);
5628 if (shape.representation_tag() == i::kSlicedStringTag) {
5629 i::SlicedString* slice = i::SlicedString::cast(string);
5630 i::String* parent = slice->parent();
5631 i::StringShape parent_shape(parent);
5632 length_ = slice->length();
5633 if (parent_shape.encoding_tag() == i::kAsciiStringTag) {
5634 storage_type_ = kAscii;
5635 if (parent_shape.representation_tag() == i::kSeqStringTag) {
5636 ptr_ = i::SeqAsciiString::cast(parent)->GetChars() + slice->offset();
5637 } else {
5638 ASSERT(parent_shape.representation_tag() == i::kExternalStringTag);
5639 ptr_ = i::ExternalAsciiString::cast(parent)->GetChars() +
5640 slice->offset();
5641 }
5642 } else {
5643 ASSERT(parent_shape.encoding_tag() == i::kTwoByteStringTag);
5644 storage_type_ = kTwoByte;
5645 if (parent_shape.representation_tag() == i::kSeqStringTag) {
5646 ptr_ = i::SeqTwoByteString::cast(parent)->GetChars() + slice->offset();
5647 } else {
5648 ASSERT(parent_shape.representation_tag() == i::kExternalStringTag);
5649 ptr_ = i::ExternalTwoByteString::cast(parent)->GetChars() +
5650 slice->offset();
5651 }
5652 }
5653 } else {
5654 length_ = string->length();
5655 if (shape.encoding_tag() == i::kAsciiStringTag) {
5656 storage_type_ = kAscii;
5657 if (shape.representation_tag() == i::kSeqStringTag) {
5658 ptr_ = i::SeqAsciiString::cast(string)->GetChars();
5659 } else {
5660 ASSERT(shape.representation_tag() == i::kExternalStringTag);
5661 ptr_ = i::ExternalAsciiString::cast(string)->GetChars();
5662 }
5663 } else {
5664 ASSERT(shape.encoding_tag() == i::kTwoByteStringTag);
5665 storage_type_ = kTwoByte;
5666 if (shape.representation_tag() == i::kSeqStringTag) {
5667 ptr_ = i::SeqTwoByteString::cast(string)->GetChars();
5668 } else {
5669 ASSERT(shape.representation_tag() == i::kExternalStringTag);
5670 ptr_ = i::ExternalTwoByteString::cast(string)->GetChars();
5671 }
5672 }
5673 }
5674 }
5675
5676
5677 // Force inline would be nice here too.
5678 strong_inline void ReadMemory::set_end() {
5679 ptr_ = NULL;
5680 length_ = 0;
5681 storage_type_ = kNone;
5682 }
5683
5684
5315 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) { 5685 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
5316 i::Isolate* isolate = i::Isolate::Current(); 5686 i::Isolate* isolate = i::Isolate::Current();
5317 LOG_API(isolate, "RangeError"); 5687 LOG_API(isolate, "RangeError");
5318 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>()); 5688 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
5319 ENTER_V8(isolate); 5689 ENTER_V8(isolate);
5320 i::Object* error; 5690 i::Object* error;
5321 { 5691 {
5322 i::HandleScope scope(isolate); 5692 i::HandleScope scope(isolate);
5323 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 5693 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
5324 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message); 5694 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
6222 6592
6223 6593
6224 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { 6594 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
6225 HandleScopeImplementer* scope_implementer = 6595 HandleScopeImplementer* scope_implementer =
6226 reinterpret_cast<HandleScopeImplementer*>(storage); 6596 reinterpret_cast<HandleScopeImplementer*>(storage);
6227 scope_implementer->IterateThis(v); 6597 scope_implementer->IterateThis(v);
6228 return storage + ArchiveSpacePerThread(); 6598 return storage + ArchiveSpacePerThread();
6229 } 6599 }
6230 6600
6231 } } // namespace v8::internal 6601 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « include/v8.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698