| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 case kConsStringTag: { | 515 case kConsStringTag: { |
| 516 ConsString* cs = ConsString::cast(this); | 516 ConsString* cs = ConsString::cast(this); |
| 517 if (String::cast(cs->second())->length() == 0) { | 517 if (String::cast(cs->second())->length() == 0) { |
| 518 return this; | 518 return this; |
| 519 } | 519 } |
| 520 // There's little point in putting the flat string in new space if the | 520 // There's little point in putting the flat string in new space if the |
| 521 // cons string is in old space. It can never get GCed until there is | 521 // cons string is in old space. It can never get GCed until there is |
| 522 // an old space GC. | 522 // an old space GC. |
| 523 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; | 523 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; |
| 524 int len = length(); | 524 int len = length(); |
| 525 Object* object = IsAscii() ? | 525 Object* object = IsAsciiRepresentation() ? |
| 526 Heap::AllocateRawAsciiString(len, tenure) : | 526 Heap::AllocateRawAsciiString(len, tenure) : |
| 527 Heap::AllocateRawTwoByteString(len, tenure); | 527 Heap::AllocateRawTwoByteString(len, tenure); |
| 528 if (object->IsFailure()) return object; | 528 if (object->IsFailure()) return object; |
| 529 String* result = String::cast(object); | 529 String* result = String::cast(object); |
| 530 Flatten(this, result, 0, len, 0); | 530 Flatten(this, result, 0, len, 0); |
| 531 cs->set_first(result); | 531 cs->set_first(result); |
| 532 cs->set_second(Heap::empty_string()); | 532 cs->set_second(Heap::empty_string()); |
| 533 return this; | 533 return this; |
| 534 } | 534 } |
| 535 default: | 535 default: |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 | 748 |
| 749 | 749 |
| 750 int HeapObject::SlowSizeFromMap(Map* map) { | 750 int HeapObject::SlowSizeFromMap(Map* map) { |
| 751 // Avoid calling functions such as FixedArray::cast during GC, which | 751 // Avoid calling functions such as FixedArray::cast during GC, which |
| 752 // read map pointer of this object again. | 752 // read map pointer of this object again. |
| 753 InstanceType instance_type = map->instance_type(); | 753 InstanceType instance_type = map->instance_type(); |
| 754 | 754 |
| 755 if (instance_type < FIRST_NONSTRING_TYPE | 755 if (instance_type < FIRST_NONSTRING_TYPE |
| 756 && (reinterpret_cast<String*>(this)->map_representation_tag(map) | 756 && (reinterpret_cast<String*>(this)->map_representation_tag(map) |
| 757 == kSeqStringTag)) { | 757 == kSeqStringTag)) { |
| 758 if (reinterpret_cast<String*>(this)->is_ascii_map(map)) { | 758 if (reinterpret_cast<String*>(this)->is_ascii_representation_map(map)) { |
| 759 return reinterpret_cast<AsciiString*>(this)->AsciiStringSize(map); | 759 return reinterpret_cast<SeqAsciiString*>(this)->AsciiStringSize(map); |
| 760 } else { | 760 } else { |
| 761 return reinterpret_cast<TwoByteString*>(this)->TwoByteStringSize(map); | 761 return reinterpret_cast<SeqTwoByteString*>(this)->TwoByteStringSize(map); |
| 762 } | 762 } |
| 763 } | 763 } |
| 764 | 764 |
| 765 switch (instance_type) { | 765 switch (instance_type) { |
| 766 case FIXED_ARRAY_TYPE: | 766 case FIXED_ARRAY_TYPE: |
| 767 return reinterpret_cast<FixedArray*>(this)->FixedArraySize(); | 767 return reinterpret_cast<FixedArray*>(this)->FixedArraySize(); |
| 768 case BYTE_ARRAY_TYPE: | 768 case BYTE_ARRAY_TYPE: |
| 769 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); | 769 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); |
| 770 case CODE_TYPE: | 770 case CODE_TYPE: |
| 771 return reinterpret_cast<Code*>(this)->CodeSize(); | 771 return reinterpret_cast<Code*>(this)->CodeSize(); |
| (...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2963 case kSlicedStringTag: | 2963 case kSlicedStringTag: |
| 2964 case kExternalStringTag: | 2964 case kExternalStringTag: |
| 2965 return true; | 2965 return true; |
| 2966 default: | 2966 default: |
| 2967 return false; | 2967 return false; |
| 2968 } | 2968 } |
| 2969 } | 2969 } |
| 2970 | 2970 |
| 2971 | 2971 |
| 2972 int String::Utf8Length() { | 2972 int String::Utf8Length() { |
| 2973 if (is_ascii()) return length(); | 2973 if (is_ascii_representation()) return length(); |
| 2974 // Attempt to flatten before accessing the string. It probably | 2974 // Attempt to flatten before accessing the string. It probably |
| 2975 // doesn't make Utf8Length faster, but it is very likely that | 2975 // doesn't make Utf8Length faster, but it is very likely that |
| 2976 // the string will be accessed later (for example by WriteUtf8) | 2976 // the string will be accessed later (for example by WriteUtf8) |
| 2977 // so it's still a good idea. | 2977 // so it's still a good idea. |
| 2978 TryFlatten(); | 2978 TryFlatten(); |
| 2979 Access<StringInputBuffer> buffer(&string_input_buffer); | 2979 Access<StringInputBuffer> buffer(&string_input_buffer); |
| 2980 buffer->Reset(0, this); | 2980 buffer->Reset(0, this); |
| 2981 int result = 0; | 2981 int result = 0; |
| 2982 while (buffer->has_more()) | 2982 while (buffer->has_more()) |
| 2983 result += unibrow::Utf8::Length(buffer->GetNext()); | 2983 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 2984 return result; | 2984 return result; |
| 2985 } | 2985 } |
| 2986 | 2986 |
| 2987 | 2987 |
| 2988 Vector<const char> String::ToAsciiVector() { |
| 2989 ASSERT(IsAsciiRepresentation()); |
| 2990 ASSERT(IsFlat()); |
| 2991 |
| 2992 int offset = 0; |
| 2993 int length = this->length(); |
| 2994 StringRepresentationTag string_tag = representation_tag(); |
| 2995 String* string = this; |
| 2996 if (string_tag == kSlicedStringTag) { |
| 2997 SlicedString* sliced = SlicedString::cast(string); |
| 2998 offset += sliced->start(); |
| 2999 string = String::cast(sliced->buffer()); |
| 3000 string_tag = string->representation_tag(); |
| 3001 } else if (string_tag == kConsStringTag) { |
| 3002 ConsString* cons = ConsString::cast(string); |
| 3003 ASSERT(String::cast(cons->second())->length() == 0); |
| 3004 string = String::cast(cons->first()); |
| 3005 string_tag = string->representation_tag(); |
| 3006 } |
| 3007 if (string_tag == kSeqStringTag) { |
| 3008 SeqAsciiString* seq = SeqAsciiString::cast(string); |
| 3009 char* start = reinterpret_cast<char*>(seq->GetCharsAddress()); |
| 3010 return Vector<const char>(start + offset, length); |
| 3011 } |
| 3012 ASSERT(string_tag == kExternalStringTag); |
| 3013 ExternalAsciiString* ext = ExternalAsciiString::cast(string); |
| 3014 const char* start = ext->resource()->data(); |
| 3015 return Vector<const char>(start + offset, length); |
| 3016 } |
| 3017 |
| 3018 |
| 3019 Vector<const uc16> String::ToUC16Vector() { |
| 3020 ASSERT(IsTwoByteStringRepresentation()); |
| 3021 ASSERT(IsFlat()); |
| 3022 |
| 3023 int offset = 0; |
| 3024 int length = this->length(); |
| 3025 StringRepresentationTag string_tag = representation_tag(); |
| 3026 String* string = this; |
| 3027 if (string_tag == kSlicedStringTag) { |
| 3028 SlicedString* sliced = SlicedString::cast(string); |
| 3029 offset += sliced->start(); |
| 3030 string = String::cast(sliced->buffer()); |
| 3031 string_tag = string->representation_tag(); |
| 3032 } else if (string_tag == kConsStringTag) { |
| 3033 ConsString* cons = ConsString::cast(string); |
| 3034 ASSERT(String::cast(cons->second())->length() == 0); |
| 3035 string = String::cast(cons->first()); |
| 3036 string_tag = string->representation_tag(); |
| 3037 } |
| 3038 if (string_tag == kSeqStringTag) { |
| 3039 SeqTwoByteString* seq = SeqTwoByteString::cast(string); |
| 3040 uc16* start = reinterpret_cast<uc16*>(seq->GetCharsAddress()); |
| 3041 return Vector<const uc16>(start + offset, length); |
| 3042 } |
| 3043 ASSERT(string_tag == kExternalStringTag); |
| 3044 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); |
| 3045 const uc16* start = |
| 3046 reinterpret_cast<const uc16*>(ext->resource()->data()); |
| 3047 return Vector<const uc16>(start + offset, length); |
| 3048 } |
| 3049 |
| 3050 |
| 2988 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 3051 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 2989 RobustnessFlag robust_flag, | 3052 RobustnessFlag robust_flag, |
| 2990 int offset, | 3053 int offset, |
| 2991 int length, | 3054 int length, |
| 2992 int* length_return) { | 3055 int* length_return) { |
| 2993 ASSERT(NativeAllocationChecker::allocation_allowed()); | 3056 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 2994 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 3057 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 2995 return SmartPointer<char>(NULL); | 3058 return SmartPointer<char>(NULL); |
| 2996 } | 3059 } |
| 2997 | 3060 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3044 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); | 3107 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); |
| 3045 } | 3108 } |
| 3046 | 3109 |
| 3047 | 3110 |
| 3048 const uc16* String::GetTwoByteData() { | 3111 const uc16* String::GetTwoByteData() { |
| 3049 return GetTwoByteData(0); | 3112 return GetTwoByteData(0); |
| 3050 } | 3113 } |
| 3051 | 3114 |
| 3052 | 3115 |
| 3053 const uc16* String::GetTwoByteData(unsigned start) { | 3116 const uc16* String::GetTwoByteData(unsigned start) { |
| 3054 ASSERT(!IsAscii()); | 3117 ASSERT(!IsAsciiRepresentation()); |
| 3055 switch (representation_tag()) { | 3118 switch (representation_tag()) { |
| 3056 case kSeqStringTag: | 3119 case kSeqStringTag: |
| 3057 return TwoByteString::cast(this)->TwoByteStringGetData(start); | 3120 return SeqTwoByteString::cast(this)->TwoByteStringGetData(start); |
| 3058 case kExternalStringTag: | 3121 case kExternalStringTag: |
| 3059 return ExternalTwoByteString::cast(this)-> | 3122 return ExternalTwoByteString::cast(this)-> |
| 3060 ExternalTwoByteStringGetData(start); | 3123 ExternalTwoByteStringGetData(start); |
| 3061 case kSlicedStringTag: { | 3124 case kSlicedStringTag: { |
| 3062 SlicedString* sliced_string = SlicedString::cast(this); | 3125 SlicedString* sliced_string = SlicedString::cast(this); |
| 3063 String* buffer = String::cast(sliced_string->buffer()); | 3126 String* buffer = String::cast(sliced_string->buffer()); |
| 3064 if (buffer->StringIsConsString()) { | 3127 if (buffer->StringIsConsString()) { |
| 3065 ConsString* cons_string = ConsString::cast(buffer); | 3128 ConsString* cons_string = ConsString::cast(buffer); |
| 3066 // Flattened string. | 3129 // Flattened string. |
| 3067 ASSERT(String::cast(cons_string->second())->length() == 0); | 3130 ASSERT(String::cast(cons_string->second())->length() == 0); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3093 int i = 0; | 3156 int i = 0; |
| 3094 while (buffer->has_more()) { | 3157 while (buffer->has_more()) { |
| 3095 uint16_t character = buffer->GetNext(); | 3158 uint16_t character = buffer->GetNext(); |
| 3096 result[i++] = character; | 3159 result[i++] = character; |
| 3097 } | 3160 } |
| 3098 result[i] = 0; | 3161 result[i] = 0; |
| 3099 return SmartPointer<uc16>(result); | 3162 return SmartPointer<uc16>(result); |
| 3100 } | 3163 } |
| 3101 | 3164 |
| 3102 | 3165 |
| 3103 const uc16* TwoByteString::TwoByteStringGetData(unsigned start) { | 3166 const uc16* SeqTwoByteString::TwoByteStringGetData(unsigned start) { |
| 3104 return reinterpret_cast<uc16*>( | 3167 return reinterpret_cast<uc16*>( |
| 3105 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start; | 3168 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start; |
| 3106 } | 3169 } |
| 3107 | 3170 |
| 3108 | 3171 |
| 3109 void TwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, | 3172 void SeqTwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, |
| 3110 unsigned* offset_ptr, | 3173 unsigned* offset_ptr, |
| 3111 unsigned max_chars) { | 3174 unsigned max_chars) { |
| 3112 unsigned chars_read = 0; | 3175 unsigned chars_read = 0; |
| 3113 unsigned offset = *offset_ptr; | 3176 unsigned offset = *offset_ptr; |
| 3114 while (chars_read < max_chars) { | 3177 while (chars_read < max_chars) { |
| 3115 uint16_t c = *reinterpret_cast<uint16_t*>( | 3178 uint16_t c = *reinterpret_cast<uint16_t*>( |
| 3116 reinterpret_cast<char*>(this) - | 3179 reinterpret_cast<char*>(this) - |
| 3117 kHeapObjectTag + kHeaderSize + offset * kShortSize); | 3180 kHeapObjectTag + kHeaderSize + offset * kShortSize); |
| 3118 if (c <= kMaxAsciiCharCode) { | 3181 if (c <= kMaxAsciiCharCode) { |
| 3119 // Fast case for ASCII characters. Cursor is an input output argument. | 3182 // Fast case for ASCII characters. Cursor is an input output argument. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3132 } | 3195 } |
| 3133 } | 3196 } |
| 3134 offset++; | 3197 offset++; |
| 3135 chars_read++; | 3198 chars_read++; |
| 3136 } | 3199 } |
| 3137 *offset_ptr = offset; | 3200 *offset_ptr = offset; |
| 3138 rbb->remaining += chars_read; | 3201 rbb->remaining += chars_read; |
| 3139 } | 3202 } |
| 3140 | 3203 |
| 3141 | 3204 |
| 3142 const unibrow::byte* AsciiString::AsciiStringReadBlock(unsigned* remaining, | 3205 const unibrow::byte* SeqAsciiString::AsciiStringReadBlock(unsigned* remaining, |
| 3143 unsigned* offset_ptr, | 3206 unsigned* offset_ptr, |
| 3144 unsigned max_chars) { | 3207 unsigned max_chars) { |
| 3145 // Cast const char* to unibrow::byte* (signedness difference). | 3208 // Cast const char* to unibrow::byte* (signedness difference). |
| 3146 const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) - | 3209 const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) - |
| 3147 kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize; | 3210 kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize; |
| 3148 *remaining = max_chars; | 3211 *remaining = max_chars; |
| 3149 *offset_ptr += max_chars; | 3212 *offset_ptr += max_chars; |
| 3150 return b; | 3213 return b; |
| 3151 } | 3214 } |
| 3152 | 3215 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3294 break; | 3357 break; |
| 3295 } | 3358 } |
| 3296 offset++; | 3359 offset++; |
| 3297 chars_read++; | 3360 chars_read++; |
| 3298 } | 3361 } |
| 3299 *offset_ptr = offset; | 3362 *offset_ptr = offset; |
| 3300 rbb->remaining += chars_read; | 3363 rbb->remaining += chars_read; |
| 3301 } | 3364 } |
| 3302 | 3365 |
| 3303 | 3366 |
| 3304 void AsciiString::AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, | 3367 void SeqAsciiString::AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, |
| 3305 unsigned* offset_ptr, | 3368 unsigned* offset_ptr, |
| 3306 unsigned max_chars) { | 3369 unsigned max_chars) { |
| 3307 unsigned capacity = rbb->capacity - rbb->cursor; | 3370 unsigned capacity = rbb->capacity - rbb->cursor; |
| 3308 if (max_chars > capacity) max_chars = capacity; | 3371 if (max_chars > capacity) max_chars = capacity; |
| 3309 memcpy(rbb->util_buffer + rbb->cursor, | 3372 memcpy(rbb->util_buffer + rbb->cursor, |
| 3310 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize + | 3373 reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize + |
| 3311 *offset_ptr * kCharSize, | 3374 *offset_ptr * kCharSize, |
| 3312 max_chars); | 3375 max_chars); |
| 3313 rbb->remaining += max_chars; | 3376 rbb->remaining += max_chars; |
| 3314 *offset_ptr += max_chars; | 3377 *offset_ptr += max_chars; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3339 ReadBlockBuffer* rbb, | 3402 ReadBlockBuffer* rbb, |
| 3340 unsigned* offset_ptr, | 3403 unsigned* offset_ptr, |
| 3341 unsigned max_chars) { | 3404 unsigned max_chars) { |
| 3342 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length())); | 3405 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length())); |
| 3343 if (max_chars == 0) { | 3406 if (max_chars == 0) { |
| 3344 rbb->remaining = 0; | 3407 rbb->remaining = 0; |
| 3345 return NULL; | 3408 return NULL; |
| 3346 } | 3409 } |
| 3347 switch (input->representation_tag()) { | 3410 switch (input->representation_tag()) { |
| 3348 case kSeqStringTag: | 3411 case kSeqStringTag: |
| 3349 if (input->is_ascii()) { | 3412 if (input->is_ascii_representation()) { |
| 3350 return AsciiString::cast(input)->AsciiStringReadBlock(&rbb->remaining, | 3413 return SeqAsciiString::cast(input)->AsciiStringReadBlock(&rbb->remaining
, |
| 3351 offset_ptr, | 3414 offset_ptr, |
| 3352 max_chars); | 3415 max_chars); |
| 3353 } else { | 3416 } else { |
| 3354 TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb, | 3417 SeqTwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb, |
| 3355 offset_ptr, | 3418 offset_ptr, |
| 3356 max_chars); | 3419 max_chars); |
| 3357 return rbb->util_buffer; | 3420 return rbb->util_buffer; |
| 3358 } | 3421 } |
| 3359 case kConsStringTag: | 3422 case kConsStringTag: |
| 3360 return ConsString::cast(input)->ConsStringReadBlock(rbb, | 3423 return ConsString::cast(input)->ConsStringReadBlock(rbb, |
| 3361 offset_ptr, | 3424 offset_ptr, |
| 3362 max_chars); | 3425 max_chars); |
| 3363 case kSlicedStringTag: | 3426 case kSlicedStringTag: |
| 3364 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, | 3427 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, |
| 3365 offset_ptr, | 3428 offset_ptr, |
| 3366 max_chars); | 3429 max_chars); |
| 3367 case kExternalStringTag: | 3430 case kExternalStringTag: |
| 3368 if (input->is_ascii()) { | 3431 if (input->is_ascii_representation()) { |
| 3369 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( | 3432 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( |
| 3370 &rbb->remaining, | 3433 &rbb->remaining, |
| 3371 offset_ptr, | 3434 offset_ptr, |
| 3372 max_chars); | 3435 max_chars); |
| 3373 } else { | 3436 } else { |
| 3374 ExternalTwoByteString::cast(input)-> | 3437 ExternalTwoByteString::cast(input)-> |
| 3375 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 3438 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
| 3376 offset_ptr, | 3439 offset_ptr, |
| 3377 max_chars); | 3440 max_chars); |
| 3378 return rbb->util_buffer; | 3441 return rbb->util_buffer; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3402 // to fill up a buffer. | 3465 // to fill up a buffer. |
| 3403 void String::ReadBlockIntoBuffer(String* input, | 3466 void String::ReadBlockIntoBuffer(String* input, |
| 3404 ReadBlockBuffer* rbb, | 3467 ReadBlockBuffer* rbb, |
| 3405 unsigned* offset_ptr, | 3468 unsigned* offset_ptr, |
| 3406 unsigned max_chars) { | 3469 unsigned max_chars) { |
| 3407 ASSERT(*offset_ptr <= (unsigned)input->length()); | 3470 ASSERT(*offset_ptr <= (unsigned)input->length()); |
| 3408 if (max_chars == 0) return; | 3471 if (max_chars == 0) return; |
| 3409 | 3472 |
| 3410 switch (input->representation_tag()) { | 3473 switch (input->representation_tag()) { |
| 3411 case kSeqStringTag: | 3474 case kSeqStringTag: |
| 3412 if (input->is_ascii()) { | 3475 if (input->is_ascii_representation()) { |
| 3413 AsciiString::cast(input)->AsciiStringReadBlockIntoBuffer(rbb, | 3476 SeqAsciiString::cast(input)->AsciiStringReadBlockIntoBuffer(rbb, |
| 3414 offset_ptr, | 3477 offset_ptr, |
| 3415 max_chars); | 3478 max_chars); |
| 3416 return; | 3479 return; |
| 3417 } else { | 3480 } else { |
| 3418 TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb, | 3481 SeqTwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb, |
| 3419 offset_ptr, | 3482 offset_ptr, |
| 3420 max_chars); | 3483 max_chars); |
| 3421 return; | 3484 return; |
| 3422 } | 3485 } |
| 3423 case kConsStringTag: | 3486 case kConsStringTag: |
| 3424 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, | 3487 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, |
| 3425 offset_ptr, | 3488 offset_ptr, |
| 3426 max_chars); | 3489 max_chars); |
| 3427 return; | 3490 return; |
| 3428 case kSlicedStringTag: | 3491 case kSlicedStringTag: |
| 3429 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, | 3492 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, |
| 3430 offset_ptr, | 3493 offset_ptr, |
| 3431 max_chars); | 3494 max_chars); |
| 3432 return; | 3495 return; |
| 3433 case kExternalStringTag: | 3496 case kExternalStringTag: |
| 3434 if (input->is_ascii()) { | 3497 if (input->is_ascii_representation()) { |
| 3435 ExternalAsciiString::cast(input)-> | 3498 ExternalAsciiString::cast(input)-> |
| 3436 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); | 3499 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); |
| 3437 } else { | 3500 } else { |
| 3438 ExternalTwoByteString::cast(input)-> | 3501 ExternalTwoByteString::cast(input)-> |
| 3439 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 3502 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
| 3440 offset_ptr, | 3503 offset_ptr, |
| 3441 max_chars); | 3504 max_chars); |
| 3442 } | 3505 } |
| 3443 return; | 3506 return; |
| 3444 default: | 3507 default: |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3681 } | 3744 } |
| 3682 | 3745 |
| 3683 | 3746 |
| 3684 uint16_t SlicedString::SlicedStringGet(int index) { | 3747 uint16_t SlicedString::SlicedStringGet(int index) { |
| 3685 ASSERT(index >= 0 && index < this->length()); | 3748 ASSERT(index >= 0 && index < this->length()); |
| 3686 // Delegate to the buffer string. | 3749 // Delegate to the buffer string. |
| 3687 return String::cast(buffer())->Get(start() + index); | 3750 return String::cast(buffer())->Get(start() + index); |
| 3688 } | 3751 } |
| 3689 | 3752 |
| 3690 | 3753 |
| 3754 template <typename IteratorA, typename IteratorB> |
| 3755 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { |
| 3756 // General slow case check. We know that the ia and ib iterators |
| 3757 // have the same length. |
| 3758 while (ia->has_more()) { |
| 3759 uc32 ca = ia->GetNext(); |
| 3760 uc32 cb = ib->GetNext(); |
| 3761 if (ca != cb) |
| 3762 return false; |
| 3763 } |
| 3764 return true; |
| 3765 } |
| 3766 |
| 3767 |
| 3768 static StringInputBuffer string_compare_buffer_b; |
| 3769 |
| 3770 |
| 3771 template <typename IteratorA> |
| 3772 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { |
| 3773 if (b->IsFlat()) { |
| 3774 if (b->IsAsciiRepresentation()) { |
| 3775 VectorIterator<const char> ib(b->ToAsciiVector()); |
| 3776 return CompareStringContents(ia, &ib); |
| 3777 } else { |
| 3778 VectorIterator<const uc16> ib(b->ToUC16Vector()); |
| 3779 return CompareStringContents(ia, &ib); |
| 3780 } |
| 3781 } else { |
| 3782 string_compare_buffer_b.Reset(0, b); |
| 3783 return CompareStringContents(ia, &string_compare_buffer_b); |
| 3784 } |
| 3785 } |
| 3786 |
| 3787 |
| 3788 static StringInputBuffer string_compare_buffer_a; |
| 3789 |
| 3790 |
| 3691 bool String::SlowEquals(String* other) { | 3791 bool String::SlowEquals(String* other) { |
| 3692 // Fast check: negative check with lengths. | 3792 // Fast check: negative check with lengths. |
| 3693 int len = length(); | 3793 int len = length(); |
| 3694 if (len != other->length()) return false; | 3794 if (len != other->length()) return false; |
| 3695 if (len == 0) return true; | 3795 if (len == 0) return true; |
| 3696 | 3796 |
| 3697 // Fast check: if hash code is computed for both strings | 3797 // Fast check: if hash code is computed for both strings |
| 3698 // a fast negative check can be performed. | 3798 // a fast negative check can be performed. |
| 3699 if (HasHashCode() && other->HasHashCode()) { | 3799 if (HasHashCode() && other->HasHashCode()) { |
| 3700 if (Hash() != other->Hash()) return false; | 3800 if (Hash() != other->Hash()) return false; |
| 3701 } | 3801 } |
| 3702 | 3802 |
| 3703 // Fast case: avoid input buffers for small strings. | 3803 if (this->IsFlat()) { |
| 3704 const int kMaxLenthForFastCaseCheck = 5; | 3804 if (this->IsAsciiRepresentation()) { |
| 3705 for (int i = 0; i < kMaxLenthForFastCaseCheck; i++) { | 3805 VectorIterator<const char> buf1(this->ToAsciiVector()); |
| 3706 if (Get(i) != other->Get(i)) return false; | 3806 return CompareStringContentsPartial(&buf1, other); |
| 3707 if (i + 1 == len) return true; | 3807 } else { |
| 3808 VectorIterator<const uc16> buf1(this->ToUC16Vector()); |
| 3809 return CompareStringContentsPartial(&buf1, other); |
| 3810 } |
| 3811 } else { |
| 3812 string_compare_buffer_a.Reset(0, this); |
| 3813 return CompareStringContentsPartial(&string_compare_buffer_a, other); |
| 3708 } | 3814 } |
| 3709 | |
| 3710 // General slow case check. | |
| 3711 static StringInputBuffer buf1; | |
| 3712 static StringInputBuffer buf2; | |
| 3713 buf1.Reset(kMaxLenthForFastCaseCheck, this); | |
| 3714 buf2.Reset(kMaxLenthForFastCaseCheck, other); | |
| 3715 while (buf1.has_more()) { | |
| 3716 if (buf1.GetNext() != buf2.GetNext()) { | |
| 3717 return false; | |
| 3718 } | |
| 3719 } | |
| 3720 return true; | |
| 3721 } | 3815 } |
| 3722 | 3816 |
| 3723 | 3817 |
| 3724 bool String::MarkAsUndetectable() { | 3818 bool String::MarkAsUndetectable() { |
| 3725 if (this->IsSymbol()) return false; | 3819 if (this->IsSymbol()) return false; |
| 3726 | 3820 |
| 3727 Map* map = this->map(); | 3821 Map* map = this->map(); |
| 3728 if (map == Heap::short_string_map()) { | 3822 if (map == Heap::short_string_map()) { |
| 3729 this->set_map(Heap::undetectable_short_string_map()); | 3823 this->set_map(Heap::undetectable_short_string_map()); |
| 3730 return true; | 3824 return true; |
| (...skipping 2713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6444 // No break point. | 6538 // No break point. |
| 6445 if (break_point_objects()->IsUndefined()) return 0; | 6539 if (break_point_objects()->IsUndefined()) return 0; |
| 6446 // Single beak point. | 6540 // Single beak point. |
| 6447 if (!break_point_objects()->IsFixedArray()) return 1; | 6541 if (!break_point_objects()->IsFixedArray()) return 1; |
| 6448 // Multiple break points. | 6542 // Multiple break points. |
| 6449 return FixedArray::cast(break_point_objects())->length(); | 6543 return FixedArray::cast(break_point_objects())->length(); |
| 6450 } | 6544 } |
| 6451 | 6545 |
| 6452 | 6546 |
| 6453 } } // namespace v8::internal | 6547 } } // namespace v8::internal |
| OLD | NEW |