| 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 | 
|---|