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 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 Object* String::TryFlatten() { | 676 Object* String::TryFlatten() { |
677 #ifdef DEBUG | 677 #ifdef DEBUG |
678 // Do not attempt to flatten in debug mode when allocation is not | 678 // Do not attempt to flatten in debug mode when allocation is not |
679 // allowed. This is to avoid an assertion failure when allocating. | 679 // allowed. This is to avoid an assertion failure when allocating. |
680 // Flattening strings is the only case where we always allow | 680 // Flattening strings is the only case where we always allow |
681 // allocation because no GC is performed if the allocation fails. | 681 // allocation because no GC is performed if the allocation fails. |
682 if (!Heap::IsAllocationAllowed()) return this; | 682 if (!Heap::IsAllocationAllowed()) return this; |
683 #endif | 683 #endif |
684 | 684 |
685 switch (StringShape(this).representation_tag()) { | 685 switch (StringShape(this).representation_tag()) { |
686 case kSlicedStringTag: { | |
687 SlicedString* ss = SlicedString::cast(this); | |
688 // The SlicedString constructor should ensure that there are no | |
689 // SlicedStrings that are constructed directly on top of other | |
690 // SlicedStrings. | |
691 String* buf = ss->buffer(); | |
692 ASSERT(!buf->IsSlicedString()); | |
693 Object* ok = buf->TryFlatten(); | |
694 if (ok->IsFailure()) return ok; | |
695 // Under certain circumstances (TryFlattenIfNotFlat fails in | |
696 // String::Slice) we can have a cons string under a slice. | |
697 // In this case we need to get the flat string out of the cons! | |
698 if (StringShape(String::cast(ok)).IsCons()) { | |
699 ss->set_buffer(ConsString::cast(ok)->first()); | |
700 } | |
701 return this; | |
702 } | |
703 case kConsStringTag: { | 686 case kConsStringTag: { |
704 ConsString* cs = ConsString::cast(this); | 687 ConsString* cs = ConsString::cast(this); |
705 if (cs->second()->length() == 0) { | 688 if (cs->second()->length() == 0) { |
706 return this; | 689 return this; |
707 } | 690 } |
708 // There's little point in putting the flat string in new space if the | 691 // There's little point in putting the flat string in new space if the |
709 // cons string is in old space. It can never get GCed until there is | 692 // cons string is in old space. It can never get GCed until there is |
710 // an old space GC. | 693 // an old space GC. |
711 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; | 694 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; |
712 int len = length(); | 695 int len = length(); |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1128 ObjectVisitor* v) { | 1111 ObjectVisitor* v) { |
1129 // Avoiding <Type>::cast(this) because it accesses the map pointer field. | 1112 // Avoiding <Type>::cast(this) because it accesses the map pointer field. |
1130 // During GC, the map pointer field is encoded. | 1113 // During GC, the map pointer field is encoded. |
1131 if (type < FIRST_NONSTRING_TYPE) { | 1114 if (type < FIRST_NONSTRING_TYPE) { |
1132 switch (type & kStringRepresentationMask) { | 1115 switch (type & kStringRepresentationMask) { |
1133 case kSeqStringTag: | 1116 case kSeqStringTag: |
1134 break; | 1117 break; |
1135 case kConsStringTag: | 1118 case kConsStringTag: |
1136 reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v); | 1119 reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v); |
1137 break; | 1120 break; |
1138 case kSlicedStringTag: | |
1139 reinterpret_cast<SlicedString*>(this)->SlicedStringIterateBody(v); | |
1140 break; | |
1141 case kExternalStringTag: | 1121 case kExternalStringTag: |
1142 if ((type & kStringEncodingMask) == kAsciiStringTag) { | 1122 if ((type & kStringEncodingMask) == kAsciiStringTag) { |
1143 reinterpret_cast<ExternalAsciiString*>(this)-> | 1123 reinterpret_cast<ExternalAsciiString*>(this)-> |
1144 ExternalAsciiStringIterateBody(v); | 1124 ExternalAsciiStringIterateBody(v); |
1145 } else { | 1125 } else { |
1146 reinterpret_cast<ExternalTwoByteString*>(this)-> | 1126 reinterpret_cast<ExternalTwoByteString*>(this)-> |
1147 ExternalTwoByteStringIterateBody(v); | 1127 ExternalTwoByteStringIterateBody(v); |
1148 } | 1128 } |
1149 break; | 1129 break; |
1150 } | 1130 } |
(...skipping 2413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3564 | 3544 |
3565 | 3545 |
3566 Vector<const char> String::ToAsciiVector() { | 3546 Vector<const char> String::ToAsciiVector() { |
3567 ASSERT(IsAsciiRepresentation()); | 3547 ASSERT(IsAsciiRepresentation()); |
3568 ASSERT(IsFlat()); | 3548 ASSERT(IsFlat()); |
3569 | 3549 |
3570 int offset = 0; | 3550 int offset = 0; |
3571 int length = this->length(); | 3551 int length = this->length(); |
3572 StringRepresentationTag string_tag = StringShape(this).representation_tag(); | 3552 StringRepresentationTag string_tag = StringShape(this).representation_tag(); |
3573 String* string = this; | 3553 String* string = this; |
3574 if (string_tag == kSlicedStringTag) { | 3554 if (string_tag == kConsStringTag) { |
3575 SlicedString* sliced = SlicedString::cast(string); | |
3576 offset += sliced->start(); | |
3577 string = sliced->buffer(); | |
3578 string_tag = StringShape(string).representation_tag(); | |
3579 } else if (string_tag == kConsStringTag) { | |
3580 ConsString* cons = ConsString::cast(string); | 3555 ConsString* cons = ConsString::cast(string); |
3581 ASSERT(cons->second()->length() == 0); | 3556 ASSERT(cons->second()->length() == 0); |
3582 string = cons->first(); | 3557 string = cons->first(); |
3583 string_tag = StringShape(string).representation_tag(); | 3558 string_tag = StringShape(string).representation_tag(); |
3584 } | 3559 } |
3585 if (string_tag == kSeqStringTag) { | 3560 if (string_tag == kSeqStringTag) { |
3586 SeqAsciiString* seq = SeqAsciiString::cast(string); | 3561 SeqAsciiString* seq = SeqAsciiString::cast(string); |
3587 char* start = seq->GetChars(); | 3562 char* start = seq->GetChars(); |
3588 return Vector<const char>(start + offset, length); | 3563 return Vector<const char>(start + offset, length); |
3589 } | 3564 } |
3590 ASSERT(string_tag == kExternalStringTag); | 3565 ASSERT(string_tag == kExternalStringTag); |
3591 ExternalAsciiString* ext = ExternalAsciiString::cast(string); | 3566 ExternalAsciiString* ext = ExternalAsciiString::cast(string); |
3592 const char* start = ext->resource()->data(); | 3567 const char* start = ext->resource()->data(); |
3593 return Vector<const char>(start + offset, length); | 3568 return Vector<const char>(start + offset, length); |
3594 } | 3569 } |
3595 | 3570 |
3596 | 3571 |
3597 Vector<const uc16> String::ToUC16Vector() { | 3572 Vector<const uc16> String::ToUC16Vector() { |
3598 ASSERT(IsTwoByteRepresentation()); | 3573 ASSERT(IsTwoByteRepresentation()); |
3599 ASSERT(IsFlat()); | 3574 ASSERT(IsFlat()); |
3600 | 3575 |
3601 int offset = 0; | 3576 int offset = 0; |
3602 int length = this->length(); | 3577 int length = this->length(); |
3603 StringRepresentationTag string_tag = StringShape(this).representation_tag(); | 3578 StringRepresentationTag string_tag = StringShape(this).representation_tag(); |
3604 String* string = this; | 3579 String* string = this; |
3605 if (string_tag == kSlicedStringTag) { | 3580 if (string_tag == kConsStringTag) { |
3606 SlicedString* sliced = SlicedString::cast(string); | |
3607 offset += sliced->start(); | |
3608 string = String::cast(sliced->buffer()); | |
3609 string_tag = StringShape(string).representation_tag(); | |
3610 } else if (string_tag == kConsStringTag) { | |
3611 ConsString* cons = ConsString::cast(string); | 3581 ConsString* cons = ConsString::cast(string); |
3612 ASSERT(cons->second()->length() == 0); | 3582 ASSERT(cons->second()->length() == 0); |
3613 string = cons->first(); | 3583 string = cons->first(); |
3614 string_tag = StringShape(string).representation_tag(); | 3584 string_tag = StringShape(string).representation_tag(); |
3615 } | 3585 } |
3616 if (string_tag == kSeqStringTag) { | 3586 if (string_tag == kSeqStringTag) { |
3617 SeqTwoByteString* seq = SeqTwoByteString::cast(string); | 3587 SeqTwoByteString* seq = SeqTwoByteString::cast(string); |
3618 return Vector<const uc16>(seq->GetChars() + offset, length); | 3588 return Vector<const uc16>(seq->GetChars() + offset, length); |
3619 } | 3589 } |
3620 ASSERT(string_tag == kExternalStringTag); | 3590 ASSERT(string_tag == kExternalStringTag); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3691 | 3661 |
3692 | 3662 |
3693 const uc16* String::GetTwoByteData(unsigned start) { | 3663 const uc16* String::GetTwoByteData(unsigned start) { |
3694 ASSERT(!IsAsciiRepresentation()); | 3664 ASSERT(!IsAsciiRepresentation()); |
3695 switch (StringShape(this).representation_tag()) { | 3665 switch (StringShape(this).representation_tag()) { |
3696 case kSeqStringTag: | 3666 case kSeqStringTag: |
3697 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 3667 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
3698 case kExternalStringTag: | 3668 case kExternalStringTag: |
3699 return ExternalTwoByteString::cast(this)-> | 3669 return ExternalTwoByteString::cast(this)-> |
3700 ExternalTwoByteStringGetData(start); | 3670 ExternalTwoByteStringGetData(start); |
3701 case kSlicedStringTag: { | |
3702 SlicedString* sliced_string = SlicedString::cast(this); | |
3703 String* buffer = sliced_string->buffer(); | |
3704 if (StringShape(buffer).IsCons()) { | |
3705 ConsString* cs = ConsString::cast(buffer); | |
3706 // Flattened string. | |
3707 ASSERT(cs->second()->length() == 0); | |
3708 buffer = cs->first(); | |
3709 } | |
3710 return buffer->GetTwoByteData(start + sliced_string->start()); | |
3711 } | |
3712 case kConsStringTag: | 3671 case kConsStringTag: |
3713 UNREACHABLE(); | 3672 UNREACHABLE(); |
3714 return NULL; | 3673 return NULL; |
3715 } | 3674 } |
3716 UNREACHABLE(); | 3675 UNREACHABLE(); |
3717 return NULL; | 3676 return NULL; |
3718 } | 3677 } |
3719 | 3678 |
3720 | 3679 |
3721 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 3680 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3856 rbb, | 3815 rbb, |
3857 &offset, | 3816 &offset, |
3858 max_chars > rbb->capacity ? rbb->capacity : max_chars); | 3817 max_chars > rbb->capacity ? rbb->capacity : max_chars); |
3859 *offset_ptr = offset + offset_correction; | 3818 *offset_ptr = offset + offset_correction; |
3860 return rbb->util_buffer; | 3819 return rbb->util_buffer; |
3861 } | 3820 } |
3862 } | 3821 } |
3863 } | 3822 } |
3864 | 3823 |
3865 | 3824 |
3866 const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb, | |
3867 unsigned* offset_ptr, | |
3868 unsigned max_chars) { | |
3869 String* backing = buffer(); | |
3870 unsigned offset = start() + *offset_ptr; | |
3871 unsigned length = backing->length(); | |
3872 if (max_chars > length - offset) { | |
3873 max_chars = length - offset; | |
3874 } | |
3875 const unibrow::byte* answer = | |
3876 String::ReadBlock(backing, rbb, &offset, max_chars); | |
3877 *offset_ptr = offset - start(); | |
3878 return answer; | |
3879 } | |
3880 | |
3881 | |
3882 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) { | 3825 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) { |
3883 ASSERT(index >= 0 && index < length()); | 3826 ASSERT(index >= 0 && index < length()); |
3884 return resource()->data()[index]; | 3827 return resource()->data()[index]; |
3885 } | 3828 } |
3886 | 3829 |
3887 | 3830 |
3888 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock( | 3831 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock( |
3889 unsigned* remaining, | 3832 unsigned* remaining, |
3890 unsigned* offset_ptr, | 3833 unsigned* offset_ptr, |
3891 unsigned max_chars) { | 3834 unsigned max_chars) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3995 SeqTwoByteString* str = SeqTwoByteString::cast(input); | 3938 SeqTwoByteString* str = SeqTwoByteString::cast(input); |
3996 str->SeqTwoByteStringReadBlockIntoBuffer(rbb, | 3939 str->SeqTwoByteStringReadBlockIntoBuffer(rbb, |
3997 offset_ptr, | 3940 offset_ptr, |
3998 max_chars); | 3941 max_chars); |
3999 return rbb->util_buffer; | 3942 return rbb->util_buffer; |
4000 } | 3943 } |
4001 case kConsStringTag: | 3944 case kConsStringTag: |
4002 return ConsString::cast(input)->ConsStringReadBlock(rbb, | 3945 return ConsString::cast(input)->ConsStringReadBlock(rbb, |
4003 offset_ptr, | 3946 offset_ptr, |
4004 max_chars); | 3947 max_chars); |
4005 case kSlicedStringTag: | |
4006 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, | |
4007 offset_ptr, | |
4008 max_chars); | |
4009 case kExternalStringTag: | 3948 case kExternalStringTag: |
4010 if (input->IsAsciiRepresentation()) { | 3949 if (input->IsAsciiRepresentation()) { |
4011 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( | 3950 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( |
4012 &rbb->remaining, | 3951 &rbb->remaining, |
4013 offset_ptr, | 3952 offset_ptr, |
4014 max_chars); | 3953 max_chars); |
4015 } else { | 3954 } else { |
4016 ExternalTwoByteString::cast(input)-> | 3955 ExternalTwoByteString::cast(input)-> |
4017 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 3956 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
4018 offset_ptr, | 3957 offset_ptr, |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4141 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb, | 4080 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb, |
4142 offset_ptr, | 4081 offset_ptr, |
4143 max_chars); | 4082 max_chars); |
4144 return; | 4083 return; |
4145 } | 4084 } |
4146 case kConsStringTag: | 4085 case kConsStringTag: |
4147 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, | 4086 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, |
4148 offset_ptr, | 4087 offset_ptr, |
4149 max_chars); | 4088 max_chars); |
4150 return; | 4089 return; |
4151 case kSlicedStringTag: | |
4152 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, | |
4153 offset_ptr, | |
4154 max_chars); | |
4155 return; | |
4156 case kExternalStringTag: | 4090 case kExternalStringTag: |
4157 if (input->IsAsciiRepresentation()) { | 4091 if (input->IsAsciiRepresentation()) { |
4158 ExternalAsciiString::cast(input)-> | 4092 ExternalAsciiString::cast(input)-> |
4159 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); | 4093 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); |
4160 } else { | 4094 } else { |
4161 ExternalTwoByteString::cast(input)-> | 4095 ExternalTwoByteString::cast(input)-> |
4162 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 4096 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
4163 offset_ptr, | 4097 offset_ptr, |
4164 max_chars); | 4098 max_chars); |
4165 } | 4099 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4260 offset_correction += left_length; | 4194 offset_correction += left_length; |
4261 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars); | 4195 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars); |
4262 } | 4196 } |
4263 *offset_ptr = offset + offset_correction; | 4197 *offset_ptr = offset + offset_correction; |
4264 return; | 4198 return; |
4265 } | 4199 } |
4266 } | 4200 } |
4267 } | 4201 } |
4268 | 4202 |
4269 | 4203 |
4270 void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, | |
4271 unsigned* offset_ptr, | |
4272 unsigned max_chars) { | |
4273 String* backing = buffer(); | |
4274 unsigned offset = start() + *offset_ptr; | |
4275 unsigned length = backing->length(); | |
4276 if (max_chars > length - offset) { | |
4277 max_chars = length - offset; | |
4278 } | |
4279 String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars); | |
4280 *offset_ptr = offset - start(); | |
4281 } | |
4282 | |
4283 | |
4284 void ConsString::ConsStringIterateBody(ObjectVisitor* v) { | 4204 void ConsString::ConsStringIterateBody(ObjectVisitor* v) { |
4285 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize); | 4205 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize); |
4286 } | 4206 } |
4287 | 4207 |
4288 | 4208 |
4289 void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor* v) { | 4209 void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor* v) { |
4290 IteratePointers(v, kValueOffset, kValueOffset + kPointerSize); | 4210 IteratePointers(v, kValueOffset, kValueOffset + kPointerSize); |
4291 } | 4211 } |
4292 | 4212 |
4293 | 4213 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4352 SeqAsciiString::cast(source)->GetChars() + from, | 4272 SeqAsciiString::cast(source)->GetChars() + from, |
4353 to - from); | 4273 to - from); |
4354 return; | 4274 return; |
4355 } | 4275 } |
4356 case kTwoByteStringTag | kSeqStringTag: { | 4276 case kTwoByteStringTag | kSeqStringTag: { |
4357 CopyChars(sink, | 4277 CopyChars(sink, |
4358 SeqTwoByteString::cast(source)->GetChars() + from, | 4278 SeqTwoByteString::cast(source)->GetChars() + from, |
4359 to - from); | 4279 to - from); |
4360 return; | 4280 return; |
4361 } | 4281 } |
4362 case kAsciiStringTag | kSlicedStringTag: | |
4363 case kTwoByteStringTag | kSlicedStringTag: { | |
4364 SlicedString* sliced_string = SlicedString::cast(source); | |
4365 int start = sliced_string->start(); | |
4366 from += start; | |
4367 to += start; | |
4368 source = String::cast(sliced_string->buffer()); | |
4369 break; | |
4370 } | |
4371 case kAsciiStringTag | kConsStringTag: | 4282 case kAsciiStringTag | kConsStringTag: |
4372 case kTwoByteStringTag | kConsStringTag: { | 4283 case kTwoByteStringTag | kConsStringTag: { |
4373 ConsString* cons_string = ConsString::cast(source); | 4284 ConsString* cons_string = ConsString::cast(source); |
4374 String* first = cons_string->first(); | 4285 String* first = cons_string->first(); |
4375 int boundary = first->length(); | 4286 int boundary = first->length(); |
4376 if (to - boundary >= boundary - from) { | 4287 if (to - boundary >= boundary - from) { |
4377 // Right hand side is longer. Recurse over left. | 4288 // Right hand side is longer. Recurse over left. |
4378 if (from < boundary) { | 4289 if (from < boundary) { |
4379 WriteToFlat(first, sink, from, boundary); | 4290 WriteToFlat(first, sink, from, boundary); |
4380 sink += boundary - from; | 4291 sink += boundary - from; |
(...skipping 15 matching lines...) Expand all Loading... |
4396 } | 4307 } |
4397 source = first; | 4308 source = first; |
4398 } | 4309 } |
4399 break; | 4310 break; |
4400 } | 4311 } |
4401 } | 4312 } |
4402 } | 4313 } |
4403 } | 4314 } |
4404 | 4315 |
4405 | 4316 |
4406 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { | |
4407 IteratePointer(v, kBufferOffset); | |
4408 } | |
4409 | |
4410 #define FIELD_ADDR(p, offset) \ | 4317 #define FIELD_ADDR(p, offset) \ |
4411 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) | 4318 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) |
4412 | 4319 |
4413 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) { | 4320 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) { |
4414 typedef v8::String::ExternalAsciiStringResource Resource; | 4321 typedef v8::String::ExternalAsciiStringResource Resource; |
4415 v->VisitExternalAsciiString( | 4322 v->VisitExternalAsciiString( |
4416 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); | 4323 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); |
4417 } | 4324 } |
4418 | 4325 |
4419 | 4326 |
4420 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) { | 4327 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) { |
4421 typedef v8::String::ExternalStringResource Resource; | 4328 typedef v8::String::ExternalStringResource Resource; |
4422 v->VisitExternalTwoByteString( | 4329 v->VisitExternalTwoByteString( |
4423 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); | 4330 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); |
4424 } | 4331 } |
4425 | 4332 |
4426 #undef FIELD_ADDR | 4333 #undef FIELD_ADDR |
4427 | 4334 |
4428 uint16_t SlicedString::SlicedStringGet(int index) { | |
4429 ASSERT(index >= 0 && index < this->length()); | |
4430 // Delegate to the buffer string. | |
4431 String* underlying = buffer(); | |
4432 return underlying->Get(start() + index); | |
4433 } | |
4434 | |
4435 | |
4436 template <typename IteratorA, typename IteratorB> | 4335 template <typename IteratorA, typename IteratorB> |
4437 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { | 4336 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { |
4438 // General slow case check. We know that the ia and ib iterators | 4337 // General slow case check. We know that the ia and ib iterators |
4439 // have the same length. | 4338 // have the same length. |
4440 while (ia->has_more()) { | 4339 while (ia->has_more()) { |
4441 uc32 ca = ia->GetNext(); | 4340 uc32 ca = ia->GetNext(); |
4442 uc32 cb = ib->GetNext(); | 4341 uc32 cb = ib->GetNext(); |
4443 if (ca != cb) | 4342 if (ca != cb) |
4444 return false; | 4343 return false; |
4445 } | 4344 } |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4724 // Process the remaining characters without updating the array | 4623 // Process the remaining characters without updating the array |
4725 // index. | 4624 // index. |
4726 while (buffer->has_more()) { | 4625 while (buffer->has_more()) { |
4727 hasher.AddCharacterNoIndex(buffer->GetNext()); | 4626 hasher.AddCharacterNoIndex(buffer->GetNext()); |
4728 } | 4627 } |
4729 | 4628 |
4730 return hasher.GetHashField(); | 4629 return hasher.GetHashField(); |
4731 } | 4630 } |
4732 | 4631 |
4733 | 4632 |
4734 Object* String::Slice(int start, int end) { | 4633 Object* String::SubString(int start, int end) { |
4735 if (start == 0 && end == length()) return this; | 4634 if (start == 0 && end == length()) return this; |
4736 if (StringShape(this).representation_tag() == kSlicedStringTag) { | 4635 Object* result = Heap::AllocateSubString(this, start, end); |
4737 // Translate slices of a SlicedString into slices of the | 4636 return result; |
4738 // underlying string buffer. | |
4739 SlicedString* str = SlicedString::cast(this); | |
4740 String* buf = str->buffer(); | |
4741 return Heap::AllocateSlicedString(buf, | |
4742 str->start() + start, | |
4743 str->start() + end); | |
4744 } | |
4745 Object* result = Heap::AllocateSlicedString(this, start, end); | |
4746 if (result->IsFailure()) { | |
4747 return result; | |
4748 } | |
4749 // Due to the way we retry after GC on allocation failure we are not allowed | |
4750 // to fail on allocation after this point. This is the one-allocation rule. | |
4751 | |
4752 // Try to flatten a cons string that is under the sliced string. | |
4753 // This is to avoid memory leaks and possible stack overflows caused by | |
4754 // building 'towers' of sliced strings on cons strings. | |
4755 // This may fail due to an allocation failure (when a GC is needed), but it | |
4756 // will succeed often enough to avoid the problem. We only have to do this | |
4757 // if Heap::AllocateSlicedString actually returned a SlicedString. It will | |
4758 // return flat strings for small slices for efficiency reasons. | |
4759 String* answer = String::cast(result); | |
4760 if (StringShape(answer).IsSliced() && | |
4761 StringShape(this).representation_tag() == kConsStringTag) { | |
4762 TryFlatten(); | |
4763 // If the flatten succeeded we might as well make the sliced string point | |
4764 // to the flat string rather than the cons string. | |
4765 String* second = ConsString::cast(this)->second(); | |
4766 if (second->length() == 0) { | |
4767 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first()); | |
4768 } | |
4769 } | |
4770 return answer; | |
4771 } | 4637 } |
4772 | 4638 |
4773 | 4639 |
4774 void String::PrintOn(FILE* file) { | 4640 void String::PrintOn(FILE* file) { |
4775 int length = this->length(); | 4641 int length = this->length(); |
4776 for (int i = 0; i < length; i++) { | 4642 for (int i = 0; i < length; i++) { |
4777 fprintf(file, "%c", Get(i)); | 4643 fprintf(file, "%c", Get(i)); |
4778 } | 4644 } |
4779 } | 4645 } |
4780 | 4646 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5013 // without any allocation in the heap. | 4879 // without any allocation in the heap. |
5014 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, | 4880 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, |
5015 int max_length) { | 4881 int max_length) { |
5016 // For some native functions there is no source. | 4882 // For some native functions there is no source. |
5017 if (script()->IsUndefined() || | 4883 if (script()->IsUndefined() || |
5018 Script::cast(script())->source()->IsUndefined()) { | 4884 Script::cast(script())->source()->IsUndefined()) { |
5019 accumulator->Add("<No Source>"); | 4885 accumulator->Add("<No Source>"); |
5020 return; | 4886 return; |
5021 } | 4887 } |
5022 | 4888 |
5023 // Get the slice of the source for this function. | 4889 // Get the source for the script which this function came from. |
5024 // Don't use String::cast because we don't want more assertion errors while | 4890 // Don't use String::cast because we don't want more assertion errors while |
5025 // we are already creating a stack dump. | 4891 // we are already creating a stack dump. |
5026 String* script_source = | 4892 String* script_source = |
5027 reinterpret_cast<String*>(Script::cast(script())->source()); | 4893 reinterpret_cast<String*>(Script::cast(script())->source()); |
5028 | 4894 |
5029 if (!script_source->LooksValid()) { | 4895 if (!script_source->LooksValid()) { |
5030 accumulator->Add("<Invalid Source>"); | 4896 accumulator->Add("<Invalid Source>"); |
5031 return; | 4897 return; |
5032 } | 4898 } |
5033 | 4899 |
(...skipping 3299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8333 if (break_point_objects()->IsUndefined()) return 0; | 8199 if (break_point_objects()->IsUndefined()) return 0; |
8334 // Single beak point. | 8200 // Single beak point. |
8335 if (!break_point_objects()->IsFixedArray()) return 1; | 8201 if (!break_point_objects()->IsFixedArray()) return 1; |
8336 // Multiple break points. | 8202 // Multiple break points. |
8337 return FixedArray::cast(break_point_objects())->length(); | 8203 return FixedArray::cast(break_point_objects())->length(); |
8338 } | 8204 } |
8339 #endif | 8205 #endif |
8340 | 8206 |
8341 | 8207 |
8342 } } // namespace v8::internal | 8208 } } // namespace v8::internal |
OLD | NEW |