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

Side by Side Diff: src/objects.cc

Issue 9038: Create an abstraction for the string type flags so that they can be cached.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 1 month 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 | Annotate | Revision Log
OLDNEW
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 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 return Construct(RETRY_AFTER_GC, value); 468 return Construct(RETRY_AFTER_GC, value);
469 } 469 }
470 470
471 471
472 // Should a word be prefixed by 'a' or 'an' in order to read naturally in 472 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
473 // English? Returns false for non-ASCII or words that don't start with 473 // English? Returns false for non-ASCII or words that don't start with
474 // a capital letter. The a/an rule follows pronunciation in English. 474 // a capital letter. The a/an rule follows pronunciation in English.
475 // We don't use the BBC's overcorrect "an historic occasion" though if 475 // We don't use the BBC's overcorrect "an historic occasion" though if
476 // you speak a dialect you may well say "an 'istoric occasion". 476 // you speak a dialect you may well say "an 'istoric occasion".
477 static bool AnWord(String* str) { 477 static bool AnWord(String* str) {
478 if (str->length() == 0) return false; // a nothing 478 StringShape shape(str);
479 int c0 = str->Get(0); 479 if (str->length(shape) == 0) return false; // A nothing.
480 int c1 = str->length() > 1 ? str->Get(1) : 0; 480 int c0 = str->Get(shape, 0);
481 int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0;
481 if (c0 == 'U') { 482 if (c0 == 'U') {
482 if (c1 > 'Z') { 483 if (c1 > 'Z') {
483 return true; // an Umpire, but a UTF8String, a U 484 return true; // An Umpire, but a UTF8String, a U.
484 } 485 }
485 } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') { 486 } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
486 return true; // an Ape, an ABCBook 487 return true; // An Ape, an ABCBook.
487 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && 488 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
488 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || 489 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
489 c0 == 'S' || c0 == 'X')) { 490 c0 == 'S' || c0 == 'X')) {
490 return true; // an MP3File, an M 491 return true; // An MP3File, an M.
491 } 492 }
492 return false; 493 return false;
493 } 494 }
494 495
495 496
496 Object* String::Flatten() { 497 Object* String::Flatten(StringShape shape) {
497 #ifdef DEBUG 498 #ifdef DEBUG
498 // Do not attempt to flatten in debug mode when allocation is not 499 // Do not attempt to flatten in debug mode when allocation is not
499 // allowed. This is to avoid an assertion failure when allocating. 500 // allowed. This is to avoid an assertion failure when allocating.
500 // Flattening strings is the only case where we always allow 501 // Flattening strings is the only case where we always allow
501 // allocation because no GC is performed if the allocation fails. 502 // allocation because no GC is performed if the allocation fails.
502 if (!Heap::IsAllocationAllowed()) return this; 503 if (!Heap::IsAllocationAllowed()) return this;
503 #endif 504 #endif
504 505
505 switch (representation_tag()) { 506 switch (shape.representation_tag()) {
506 case kSlicedStringTag: { 507 case kSlicedStringTag: {
507 SlicedString* ss = SlicedString::cast(this); 508 SlicedString* ss = SlicedString::cast(this);
508 // The SlicedString constructor should ensure that there are no 509 // The SlicedString constructor should ensure that there are no
509 // SlicedStrings that are constructed directly on top of other 510 // SlicedStrings that are constructed directly on top of other
510 // SlicedStrings. 511 // SlicedStrings.
511 ASSERT(!ss->buffer()->IsSlicedString()); 512 String* buf = ss->buffer();
512 Object* ok = String::cast(ss->buffer())->Flatten(); 513 ASSERT(!buf->IsSlicedString());
514 Object* ok = buf->Flatten(StringShape(buf));
513 if (ok->IsFailure()) return ok; 515 if (ok->IsFailure()) return ok;
514 // Under certain circumstances (TryFlatten fails in String::Slice) 516 // Under certain circumstances (TryFlatten fails in String::Slice)
515 // we can have a cons string under a slice. In this case we need 517 // we can have a cons string under a slice. In this case we need
516 // to get the flat string out of the cons! 518 // to get the flat string out of the cons!
517 if (String::cast(ok)->StringIsConsString()) { 519 if (StringShape(String::cast(ok)).IsCons()) {
518 ss->set_buffer(ConsString::cast(ok)->first()); 520 ss->set_buffer(ConsString::cast(ok)->first());
519 } 521 }
520 return this; 522 return this;
521 } 523 }
522 case kConsStringTag: { 524 case kConsStringTag: {
523 ConsString* cs = ConsString::cast(this); 525 ConsString* cs = ConsString::cast(this);
524 if (String::cast(cs->second())->length() == 0) { 526 if (cs->second()->length() == 0) {
525 return this; 527 return this;
526 } 528 }
527 // There's little point in putting the flat string in new space if the 529 // There's little point in putting the flat string in new space if the
528 // cons string is in old space. It can never get GCed until there is 530 // cons string is in old space. It can never get GCed until there is
529 // an old space GC. 531 // an old space GC.
530 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; 532 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
531 int len = length(); 533 int len = length(shape);
532 Object* object; 534 Object* object;
533 String* result; 535 String* result;
534 if (IsAsciiRepresentation()) { 536 if (shape.IsAsciiRepresentation()) {
535 object = Heap::AllocateRawAsciiString(len, tenure); 537 object = Heap::AllocateRawAsciiString(len, tenure);
536 if (object->IsFailure()) return object; 538 if (object->IsFailure()) return object;
537 result = String::cast(object); 539 result = String::cast(object);
538 String* first = String::cast(cs->first()); 540 String* first = cs->first();
539 int first_length = first->length(); 541 StringShape first_shape(first);
542 int first_length = first->length(first_shape);
540 char* dest = SeqAsciiString::cast(result)->GetChars(); 543 char* dest = SeqAsciiString::cast(result)->GetChars();
541 WriteToFlat(first, dest, 0, first_length); 544 WriteToFlat(first, first_shape, dest, 0, first_length);
542 WriteToFlat(String::cast(cs->second()), 545 String* second = cs->second();
546 WriteToFlat(second,
547 StringShape(second),
543 dest + first_length, 548 dest + first_length,
544 0, 549 0,
545 len - first_length); 550 len - first_length);
546 } else { 551 } else {
547 object = Heap::AllocateRawTwoByteString(len, tenure); 552 object = Heap::AllocateRawTwoByteString(len, tenure);
548 if (object->IsFailure()) return object; 553 if (object->IsFailure()) return object;
549 result = String::cast(object); 554 result = String::cast(object);
550 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); 555 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
551 String* first = String::cast(cs->first()); 556 String* first = cs->first();
552 int first_length = first->length(); 557 StringShape first_shape(first);
553 WriteToFlat(first, dest, 0, first_length); 558 int first_length = first->length(first_shape);
554 WriteToFlat(String::cast(cs->second()), 559 WriteToFlat(first, first_shape, dest, 0, first_length);
560 String* second = cs->second();
561 WriteToFlat(second,
562 StringShape(second),
555 dest + first_length, 563 dest + first_length,
556 0, 564 0,
557 len - first_length); 565 len - first_length);
558 } 566 }
559 cs->set_first(result); 567 cs->set_first(result);
560 cs->set_second(Heap::empty_string()); 568 cs->set_second(Heap::empty_string());
561 return this; 569 return this;
562 } 570 }
563 default: 571 default:
564 return this; 572 return this;
565 } 573 }
566 } 574 }
567 575
568 576
569 void String::StringShortPrint(StringStream* accumulator) { 577 void String::StringShortPrint(StringStream* accumulator) {
570 int len = length(); 578 StringShape shape(this);
579 int len = length(shape);
571 if (len > kMaxMediumStringSize) { 580 if (len > kMaxMediumStringSize) {
572 accumulator->Add("<Very long string[%u]>", len); 581 accumulator->Add("<Very long string[%u]>", len);
573 return; 582 return;
574 } 583 }
575 584
576 if (!LooksValid()) { 585 if (!LooksValid()) {
577 accumulator->Add("<Invalid String>"); 586 accumulator->Add("<Invalid String>");
578 return; 587 return;
579 } 588 }
580 589
581 StringInputBuffer buf(this); 590 StringInputBuffer buf(this);
582 591
583 bool truncated = false; 592 bool truncated = false;
584 if (len > kMaxShortPrintLength) { 593 if (len > kMaxShortPrintLength) {
585 len = kMaxShortPrintLength; 594 len = kMaxShortPrintLength;
586 truncated = true; 595 truncated = true;
587 } 596 }
588 bool ascii = true; 597 bool ascii = true;
589 for (int i = 0; i < len; i++) { 598 for (int i = 0; i < len; i++) {
590 int c = buf.GetNext(); 599 int c = buf.GetNext();
591 600
592 if (c < 32 || c >= 127) { 601 if (c < 32 || c >= 127) {
593 ascii = false; 602 ascii = false;
594 } 603 }
595 } 604 }
596 buf.Reset(this); 605 buf.Reset(this);
597 if (ascii) { 606 if (ascii) {
598 accumulator->Add("<String[%u]: ", length()); 607 accumulator->Add("<String[%u]: ", length(shape));
599 for (int i = 0; i < len; i++) { 608 for (int i = 0; i < len; i++) {
600 accumulator->Put(buf.GetNext()); 609 accumulator->Put(buf.GetNext());
601 } 610 }
602 accumulator->Put('>'); 611 accumulator->Put('>');
603 } else { 612 } else {
604 // Backslash indicates that the string contains control 613 // Backslash indicates that the string contains control
605 // characters and that backslashes are therefore escaped. 614 // characters and that backslashes are therefore escaped.
606 accumulator->Add("<String[%u]\\: ", length()); 615 accumulator->Add("<String[%u]\\: ", length(shape));
607 for (int i = 0; i < len; i++) { 616 for (int i = 0; i < len; i++) {
608 int c = buf.GetNext(); 617 int c = buf.GetNext();
609 if (c == '\n') { 618 if (c == '\n') {
610 accumulator->Add("\\n"); 619 accumulator->Add("\\n");
611 } else if (c == '\r') { 620 } else if (c == '\r') {
612 accumulator->Add("\\r"); 621 accumulator->Add("\\r");
613 } else if (c == '\\') { 622 } else if (c == '\\') {
614 accumulator->Add("\\\\"); 623 accumulator->Add("\\\\");
615 } else if (c < 32 || c > 126) { 624 } else if (c < 32 || c > 126) {
616 accumulator->Add("\\x%02x", c); 625 accumulator->Add("\\x%02x", c);
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 } 783 }
775 } 784 }
776 785
777 786
778 int HeapObject::SlowSizeFromMap(Map* map) { 787 int HeapObject::SlowSizeFromMap(Map* map) {
779 // Avoid calling functions such as FixedArray::cast during GC, which 788 // Avoid calling functions such as FixedArray::cast during GC, which
780 // read map pointer of this object again. 789 // read map pointer of this object again.
781 InstanceType instance_type = map->instance_type(); 790 InstanceType instance_type = map->instance_type();
782 791
783 if (instance_type < FIRST_NONSTRING_TYPE 792 if (instance_type < FIRST_NONSTRING_TYPE
784 && (reinterpret_cast<String*>(this)->map_representation_tag(map) 793 && (StringShape(instance_type).IsSequential())) {
785 == kSeqStringTag)) { 794 StringShape shape(instance_type);
786 if (reinterpret_cast<String*>(this)->is_ascii_representation_map(map)) { 795 if (shape.IsAsciiRepresentation()) {
787 return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(map); 796 return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(shape);
788 } else { 797 } else {
789 SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this); 798 SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
790 return self->SeqTwoByteStringSize(map); 799 return self->SeqTwoByteStringSize(shape);
791 } 800 }
792 } 801 }
793 802
794 switch (instance_type) { 803 switch (instance_type) {
795 case FIXED_ARRAY_TYPE: 804 case FIXED_ARRAY_TYPE:
796 return reinterpret_cast<FixedArray*>(this)->FixedArraySize(); 805 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
797 case BYTE_ARRAY_TYPE: 806 case BYTE_ARRAY_TYPE:
798 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 807 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
799 case CODE_TYPE: 808 case CODE_TYPE:
800 return reinterpret_cast<Code*>(this)->CodeSize(); 809 return reinterpret_cast<Code*>(this)->CodeSize();
(...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after
2272 AssertNoContextChange ncc; 2281 AssertNoContextChange ncc;
2273 2282
2274 // Check access rights if needed. 2283 // Check access rights if needed.
2275 if (IsAccessCheckNeeded() && 2284 if (IsAccessCheckNeeded() &&
2276 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { 2285 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
2277 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 2286 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
2278 return Heap::undefined_value(); 2287 return Heap::undefined_value();
2279 } 2288 }
2280 2289
2281 // TryFlatten before operating on the string. 2290 // TryFlatten before operating on the string.
2282 name->TryFlatten(); 2291 name->TryFlatten(StringShape(name));
2283 2292
2284 // Make sure name is not an index. 2293 // Make sure name is not an index.
2285 uint32_t index; 2294 uint32_t index;
2286 if (name->AsArrayIndex(&index)) return Heap::undefined_value(); 2295 if (name->AsArrayIndex(&index)) return Heap::undefined_value();
2287 2296
2288 // Lookup the name. 2297 // Lookup the name.
2289 LookupResult result; 2298 LookupResult result;
2290 LocalLookup(name, &result); 2299 LocalLookup(name, &result);
2291 if (result.IsValid()) { 2300 if (result.IsValid()) {
2292 if (result.IsReadOnly()) return Heap::undefined_value(); 2301 if (result.IsReadOnly()) return Heap::undefined_value();
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
2895 } 2904 }
2896 return GetContentArray()->IsEqualTo(other->GetContentArray()); 2905 return GetContentArray()->IsEqualTo(other->GetContentArray());
2897 } 2906 }
2898 #endif 2907 #endif
2899 2908
2900 2909
2901 static StaticResource<StringInputBuffer> string_input_buffer; 2910 static StaticResource<StringInputBuffer> string_input_buffer;
2902 2911
2903 2912
2904 bool String::LooksValid() { 2913 bool String::LooksValid() {
2905 if (!Heap::Contains(this)) 2914 if (!Heap::Contains(this)) return false;
2906 return false; 2915 return true;
Mads Ager (chromium) 2008/11/03 08:45:49 Doesn't it make sense to check that the representa
Erik Corry 2008/11/03 09:33:54 It makes no sense because all bit combinations are
2907 switch (representation_tag()) {
2908 case kSeqStringTag:
2909 case kConsStringTag:
2910 case kSlicedStringTag:
2911 case kExternalStringTag:
2912 return true;
2913 default:
2914 return false;
2915 }
2916 } 2916 }
2917 2917
2918 2918
2919 int String::Utf8Length() { 2919 int String::Utf8Length() {
2920 if (is_ascii_representation()) return length(); 2920 StringShape shape(this);
2921 if (shape.IsAsciiRepresentation()) return length(shape);
2921 // Attempt to flatten before accessing the string. It probably 2922 // Attempt to flatten before accessing the string. It probably
2922 // doesn't make Utf8Length faster, but it is very likely that 2923 // doesn't make Utf8Length faster, but it is very likely that
2923 // the string will be accessed later (for example by WriteUtf8) 2924 // the string will be accessed later (for example by WriteUtf8)
2924 // so it's still a good idea. 2925 // so it's still a good idea.
2925 TryFlatten(); 2926 if (!IsFlat(shape)) {
2927 TryFlatten(shape); // shape is now no longer valid.
2928 }
2926 Access<StringInputBuffer> buffer(&string_input_buffer); 2929 Access<StringInputBuffer> buffer(&string_input_buffer);
2927 buffer->Reset(0, this); 2930 buffer->Reset(0, this);
2928 int result = 0; 2931 int result = 0;
2929 while (buffer->has_more()) 2932 while (buffer->has_more())
2930 result += unibrow::Utf8::Length(buffer->GetNext()); 2933 result += unibrow::Utf8::Length(buffer->GetNext());
2931 return result; 2934 return result;
2932 } 2935 }
2933 2936
2934 2937
2935 Vector<const char> String::ToAsciiVector() { 2938 Vector<const char> String::ToAsciiVector() {
2936 ASSERT(IsAsciiRepresentation()); 2939 StringShape shape(this);
2937 ASSERT(IsFlat()); 2940 ASSERT(shape.IsAsciiRepresentation());
2941 ASSERT(IsFlat(shape));
2938 2942
2939 int offset = 0; 2943 int offset = 0;
2940 int length = this->length(); 2944 int length = this->length(shape);
2941 StringRepresentationTag string_tag = representation_tag(); 2945 StringRepresentationTag string_tag = shape.representation_tag();
2942 String* string = this; 2946 String* string = this;
2943 if (string_tag == kSlicedStringTag) { 2947 if (string_tag == kSlicedStringTag) {
2944 SlicedString* sliced = SlicedString::cast(string); 2948 SlicedString* sliced = SlicedString::cast(string);
2945 offset += sliced->start(); 2949 offset += sliced->start();
2946 string = String::cast(sliced->buffer()); 2950 string = sliced->buffer();
2947 string_tag = string->representation_tag(); 2951 shape = StringShape(string);
2952 string_tag = shape.representation_tag();
2948 } else if (string_tag == kConsStringTag) { 2953 } else if (string_tag == kConsStringTag) {
2949 ConsString* cons = ConsString::cast(string); 2954 ConsString* cons = ConsString::cast(string);
2950 ASSERT(String::cast(cons->second())->length() == 0); 2955 ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
2951 string = String::cast(cons->first()); 2956 string = cons->first();
2952 string_tag = string->representation_tag(); 2957 shape = StringShape(string);
2958 string_tag = shape.representation_tag();
2953 } 2959 }
2954 if (string_tag == kSeqStringTag) { 2960 if (string_tag == kSeqStringTag) {
2955 SeqAsciiString* seq = SeqAsciiString::cast(string); 2961 SeqAsciiString* seq = SeqAsciiString::cast(string);
2956 char* start = seq->GetChars(); 2962 char* start = seq->GetChars();
2957 return Vector<const char>(start + offset, length); 2963 return Vector<const char>(start + offset, length);
2958 } 2964 }
2959 ASSERT(string_tag == kExternalStringTag); 2965 ASSERT(string_tag == kExternalStringTag);
2960 ExternalAsciiString* ext = ExternalAsciiString::cast(string); 2966 ExternalAsciiString* ext = ExternalAsciiString::cast(string);
2961 const char* start = ext->resource()->data(); 2967 const char* start = ext->resource()->data();
2962 return Vector<const char>(start + offset, length); 2968 return Vector<const char>(start + offset, length);
2963 } 2969 }
2964 2970
2965 2971
2966 Vector<const uc16> String::ToUC16Vector() { 2972 Vector<const uc16> String::ToUC16Vector() {
2967 ASSERT(IsTwoByteStringRepresentation()); 2973 StringShape shape(this);
2968 ASSERT(IsFlat()); 2974 ASSERT(shape.IsTwoByteRepresentation());
2975 ASSERT(IsFlat(shape));
2969 2976
2970 int offset = 0; 2977 int offset = 0;
2971 int length = this->length(); 2978 int length = this->length(shape);
2972 StringRepresentationTag string_tag = representation_tag(); 2979 StringRepresentationTag string_tag = shape.representation_tag();
2973 String* string = this; 2980 String* string = this;
2974 if (string_tag == kSlicedStringTag) { 2981 if (string_tag == kSlicedStringTag) {
2975 SlicedString* sliced = SlicedString::cast(string); 2982 SlicedString* sliced = SlicedString::cast(string);
2976 offset += sliced->start(); 2983 offset += sliced->start();
2977 string = String::cast(sliced->buffer()); 2984 string = String::cast(sliced->buffer());
2978 string_tag = string->representation_tag(); 2985 shape = StringShape(string);
2986 string_tag = shape.representation_tag();
2979 } else if (string_tag == kConsStringTag) { 2987 } else if (string_tag == kConsStringTag) {
2980 ConsString* cons = ConsString::cast(string); 2988 ConsString* cons = ConsString::cast(string);
2981 ASSERT(String::cast(cons->second())->length() == 0); 2989 ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
2982 string = String::cast(cons->first()); 2990 string = cons->first();
2983 string_tag = string->representation_tag(); 2991 shape = StringShape(string);
2992 string_tag = shape.representation_tag();
2984 } 2993 }
2985 if (string_tag == kSeqStringTag) { 2994 if (string_tag == kSeqStringTag) {
2986 SeqTwoByteString* seq = SeqTwoByteString::cast(string); 2995 SeqTwoByteString* seq = SeqTwoByteString::cast(string);
2987 return Vector<const uc16>(seq->GetChars() + offset, length); 2996 return Vector<const uc16>(seq->GetChars() + offset, length);
2988 } 2997 }
2989 ASSERT(string_tag == kExternalStringTag); 2998 ASSERT(string_tag == kExternalStringTag);
2990 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); 2999 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
2991 const uc16* start = 3000 const uc16* start =
2992 reinterpret_cast<const uc16*>(ext->resource()->data()); 3001 reinterpret_cast<const uc16*>(ext->resource()->data());
2993 return Vector<const uc16>(start + offset, length); 3002 return Vector<const uc16>(start + offset, length);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3053 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); 3062 return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
3054 } 3063 }
3055 3064
3056 3065
3057 const uc16* String::GetTwoByteData() { 3066 const uc16* String::GetTwoByteData() {
3058 return GetTwoByteData(0); 3067 return GetTwoByteData(0);
3059 } 3068 }
3060 3069
3061 3070
3062 const uc16* String::GetTwoByteData(unsigned start) { 3071 const uc16* String::GetTwoByteData(unsigned start) {
3063 ASSERT(!IsAsciiRepresentation()); 3072 StringShape shape(this);
3064 switch (representation_tag()) { 3073 ASSERT(!shape.IsAsciiRepresentation());
3074 switch (shape.representation_tag()) {
3065 case kSeqStringTag: 3075 case kSeqStringTag:
3066 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 3076 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
3067 case kExternalStringTag: 3077 case kExternalStringTag:
3068 return ExternalTwoByteString::cast(this)-> 3078 return ExternalTwoByteString::cast(this)->
3069 ExternalTwoByteStringGetData(start); 3079 ExternalTwoByteStringGetData(start);
3070 case kSlicedStringTag: { 3080 case kSlicedStringTag: {
3071 SlicedString* sliced_string = SlicedString::cast(this); 3081 SlicedString* sliced_string = SlicedString::cast(this);
3072 String* buffer = String::cast(sliced_string->buffer()); 3082 String* buffer = sliced_string->buffer();
3073 if (buffer->StringIsConsString()) { 3083 if (StringShape(buffer).IsCons()) {
3074 ConsString* cons_string = ConsString::cast(buffer); 3084 ConsString* cs = ConsString::cast(buffer);
3075 // Flattened string. 3085 // Flattened string.
3076 ASSERT(String::cast(cons_string->second())->length() == 0); 3086 ASSERT(cs->second()->length(StringShape(cs->second())) == 0);
3077 buffer = String::cast(cons_string->first()); 3087 buffer = cs->first();
3078 } 3088 }
3079 return buffer->GetTwoByteData(start + sliced_string->start()); 3089 return buffer->GetTwoByteData(start + sliced_string->start());
3080 } 3090 }
3081 case kConsStringTag: 3091 case kConsStringTag:
3082 UNREACHABLE(); 3092 UNREACHABLE();
3083 return NULL; 3093 return NULL;
3084 } 3094 }
3085 UNREACHABLE(); 3095 UNREACHABLE();
3086 return NULL; 3096 return NULL;
3087 } 3097 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
3168 // -IntoBuffer method it can delegate to one of the efficient 3178 // -IntoBuffer method it can delegate to one of the efficient
3169 // *AsciiStringReadBlock routines. 3179 // *AsciiStringReadBlock routines.
3170 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb, 3180 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
3171 unsigned* offset_ptr, 3181 unsigned* offset_ptr,
3172 unsigned max_chars) { 3182 unsigned max_chars) {
3173 ConsString* current = this; 3183 ConsString* current = this;
3174 unsigned offset = *offset_ptr; 3184 unsigned offset = *offset_ptr;
3175 int offset_correction = 0; 3185 int offset_correction = 0;
3176 3186
3177 while (true) { 3187 while (true) {
3178 String* left = String::cast(current->first()); 3188 String* left = current->first();
3179 unsigned left_length = (unsigned)left->length(); 3189 StringShape left_shape(left);
3190 unsigned left_length = (unsigned)left->length(left_shape);
3180 if (left_length > offset && 3191 if (left_length > offset &&
3181 (max_chars <= left_length - offset || 3192 (max_chars <= left_length - offset ||
3182 (rbb->capacity <= left_length - offset && 3193 (rbb->capacity <= left_length - offset &&
3183 (max_chars = left_length - offset, true)))) { // comma operator! 3194 (max_chars = left_length - offset, true)))) { // comma operator!
3184 // Left hand side only - iterate unless we have reached the bottom of 3195 // Left hand side only - iterate unless we have reached the bottom of
3185 // the cons tree. The assignment on the left of the comma operator is 3196 // the cons tree. The assignment on the left of the comma operator is
3186 // in order to make use of the fact that the -IntoBuffer routines can 3197 // in order to make use of the fact that the -IntoBuffer routines can
3187 // produce at most 'capacity' characters. This enables us to postpone 3198 // produce at most 'capacity' characters. This enables us to postpone
3188 // the point where we switch to the -IntoBuffer routines (below) in order 3199 // the point where we switch to the -IntoBuffer routines (below) in order
3189 // to maximize the chances of delegating a big chunk of work to the 3200 // to maximize the chances of delegating a big chunk of work to the
3190 // efficient *AsciiStringReadBlock routines. 3201 // efficient *AsciiStringReadBlock routines.
3191 if (left->StringIsConsString()) { 3202 if (left_shape.IsCons()) {
3192 current = ConsString::cast(left); 3203 current = ConsString::cast(left);
3193 continue; 3204 continue;
3194 } else { 3205 } else {
3195 const unibrow::byte* answer = 3206 const unibrow::byte* answer =
3196 String::ReadBlock(left, rbb, &offset, max_chars); 3207 String::ReadBlock(left, rbb, &offset, max_chars);
3197 *offset_ptr = offset + offset_correction; 3208 *offset_ptr = offset + offset_correction;
3198 return answer; 3209 return answer;
3199 } 3210 }
3200 } else if (left_length <= offset) { 3211 } else if (left_length <= offset) {
3201 // Right hand side only - iterate unless we have reached the bottom of 3212 // Right hand side only - iterate unless we have reached the bottom of
3202 // the cons tree. 3213 // the cons tree.
3203 String* right = String::cast(current->second()); 3214 String* right = current->second();
3204 offset -= left_length; 3215 offset -= left_length;
3205 offset_correction += left_length; 3216 offset_correction += left_length;
3206 if (right->StringIsConsString()) { 3217 if (StringShape(right).IsCons()) {
3207 current = ConsString::cast(right); 3218 current = ConsString::cast(right);
3208 continue; 3219 continue;
3209 } else { 3220 } else {
3210 const unibrow::byte* answer = 3221 const unibrow::byte* answer =
3211 String::ReadBlock(right, rbb, &offset, max_chars); 3222 String::ReadBlock(right, rbb, &offset, max_chars);
3212 *offset_ptr = offset + offset_correction; 3223 *offset_ptr = offset + offset_correction;
3213 return answer; 3224 return answer;
3214 } 3225 }
3215 } else { 3226 } else {
3216 // The block to be read spans two sides of the ConsString, so we call the 3227 // The block to be read spans two sides of the ConsString, so we call the
(...skipping 11 matching lines...) Expand all
3228 *offset_ptr = offset + offset_correction; 3239 *offset_ptr = offset + offset_correction;
3229 return rbb->util_buffer; 3240 return rbb->util_buffer;
3230 } 3241 }
3231 } 3242 }
3232 } 3243 }
3233 3244
3234 3245
3235 const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb, 3246 const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb,
3236 unsigned* offset_ptr, 3247 unsigned* offset_ptr,
3237 unsigned max_chars) { 3248 unsigned max_chars) {
3238 String* backing = String::cast(buffer()); 3249 String* backing = buffer();
3239 unsigned offset = start() + *offset_ptr; 3250 unsigned offset = start() + *offset_ptr;
3240 unsigned length = backing->length(); 3251 unsigned length = backing->length();
3241 if (max_chars > length - offset) { 3252 if (max_chars > length - offset) {
3242 max_chars = length - offset; 3253 max_chars = length - offset;
3243 } 3254 }
3244 const unibrow::byte* answer = 3255 const unibrow::byte* answer =
3245 String::ReadBlock(backing, rbb, &offset, max_chars); 3256 String::ReadBlock(backing, rbb, &offset, max_chars);
3246 *offset_ptr = offset - start(); 3257 *offset_ptr = offset - start();
3247 return answer; 3258 return answer;
3248 } 3259 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
3346 // (see AsciiStringReadBlock). 3357 // (see AsciiStringReadBlock).
3347 const unibrow::byte* String::ReadBlock(String* input, 3358 const unibrow::byte* String::ReadBlock(String* input,
3348 ReadBlockBuffer* rbb, 3359 ReadBlockBuffer* rbb,
3349 unsigned* offset_ptr, 3360 unsigned* offset_ptr,
3350 unsigned max_chars) { 3361 unsigned max_chars) {
3351 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length())); 3362 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
3352 if (max_chars == 0) { 3363 if (max_chars == 0) {
3353 rbb->remaining = 0; 3364 rbb->remaining = 0;
3354 return NULL; 3365 return NULL;
3355 } 3366 }
3356 switch (input->representation_tag()) { 3367 StringShape shape(input);
3368 switch (shape.representation_tag()) {
3357 case kSeqStringTag: 3369 case kSeqStringTag:
3358 if (input->is_ascii_representation()) { 3370 if (shape.IsAsciiRepresentation()) {
3359 SeqAsciiString* str = SeqAsciiString::cast(input); 3371 SeqAsciiString* str = SeqAsciiString::cast(input);
3360 return str->SeqAsciiStringReadBlock(&rbb->remaining, 3372 return str->SeqAsciiStringReadBlock(&rbb->remaining,
3361 offset_ptr, 3373 offset_ptr,
3362 max_chars); 3374 max_chars);
3363 } else { 3375 } else {
3364 SeqTwoByteString* str = SeqTwoByteString::cast(input); 3376 SeqTwoByteString* str = SeqTwoByteString::cast(input);
3365 str->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3377 str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3366 offset_ptr, 3378 offset_ptr,
3367 max_chars); 3379 max_chars);
3368 return rbb->util_buffer; 3380 return rbb->util_buffer;
3369 } 3381 }
3370 case kConsStringTag: 3382 case kConsStringTag:
3371 return ConsString::cast(input)->ConsStringReadBlock(rbb, 3383 return ConsString::cast(input)->ConsStringReadBlock(rbb,
3372 offset_ptr, 3384 offset_ptr,
3373 max_chars); 3385 max_chars);
3374 case kSlicedStringTag: 3386 case kSlicedStringTag:
3375 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, 3387 return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
3376 offset_ptr, 3388 offset_ptr,
3377 max_chars); 3389 max_chars);
3378 case kExternalStringTag: 3390 case kExternalStringTag:
3379 if (input->is_ascii_representation()) { 3391 if (shape.IsAsciiRepresentation()) {
3380 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( 3392 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
3381 &rbb->remaining, 3393 &rbb->remaining,
3382 offset_ptr, 3394 offset_ptr,
3383 max_chars); 3395 max_chars);
3384 } else { 3396 } else {
3385 ExternalTwoByteString::cast(input)-> 3397 ExternalTwoByteString::cast(input)->
3386 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3398 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3387 offset_ptr, 3399 offset_ptr,
3388 max_chars); 3400 max_chars);
3389 return rbb->util_buffer; 3401 return rbb->util_buffer;
(...skipping 18 matching lines...) Expand all
3408 3420
3409 3421
3410 // This method determines the type of string involved and then copies 3422 // This method determines the type of string involved and then copies
3411 // a whole chunk of characters into a buffer. It can be used with strings 3423 // a whole chunk of characters into a buffer. It can be used with strings
3412 // that have been glued together to form a ConsString and which must cooperate 3424 // that have been glued together to form a ConsString and which must cooperate
3413 // to fill up a buffer. 3425 // to fill up a buffer.
3414 void String::ReadBlockIntoBuffer(String* input, 3426 void String::ReadBlockIntoBuffer(String* input,
3415 ReadBlockBuffer* rbb, 3427 ReadBlockBuffer* rbb,
3416 unsigned* offset_ptr, 3428 unsigned* offset_ptr,
3417 unsigned max_chars) { 3429 unsigned max_chars) {
3418 ASSERT(*offset_ptr <= (unsigned)input->length()); 3430 StringShape shape(input);
3431 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3419 if (max_chars == 0) return; 3432 if (max_chars == 0) return;
3420 3433
3421 switch (input->representation_tag()) { 3434 switch (shape.representation_tag()) {
3422 case kSeqStringTag: 3435 case kSeqStringTag:
3423 if (input->is_ascii_representation()) { 3436 if (shape.IsAsciiRepresentation()) {
3424 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb, 3437 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
3425 offset_ptr, 3438 offset_ptr,
3426 max_chars); 3439 max_chars);
3427 return; 3440 return;
3428 } else { 3441 } else {
3429 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3442 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3430 offset_ptr, 3443 offset_ptr,
3431 max_chars); 3444 max_chars);
3432 return; 3445 return;
3433 } 3446 }
3434 case kConsStringTag: 3447 case kConsStringTag:
3435 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, 3448 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
3436 offset_ptr, 3449 offset_ptr,
3437 max_chars); 3450 max_chars);
3438 return; 3451 return;
3439 case kSlicedStringTag: 3452 case kSlicedStringTag:
3440 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, 3453 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
3441 offset_ptr, 3454 offset_ptr,
3442 max_chars); 3455 max_chars);
3443 return; 3456 return;
3444 case kExternalStringTag: 3457 case kExternalStringTag:
3445 if (input->is_ascii_representation()) { 3458 if (shape.IsAsciiRepresentation()) {
3446 ExternalAsciiString::cast(input)-> 3459 ExternalAsciiString::cast(input)->
3447 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); 3460 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
3448 } else { 3461 } else {
3449 ExternalTwoByteString::cast(input)-> 3462 ExternalTwoByteString::cast(input)->
3450 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3463 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3451 offset_ptr, 3464 offset_ptr,
3452 max_chars); 3465 max_chars);
3453 } 3466 }
3454 return; 3467 return;
3455 default: 3468 default:
3456 break; 3469 break;
3457 } 3470 }
3458 3471
3459 UNREACHABLE(); 3472 UNREACHABLE();
3460 return; 3473 return;
3461 } 3474 }
3462 3475
3463 3476
3464 const unibrow::byte* String::ReadBlock(String* input, 3477 const unibrow::byte* String::ReadBlock(String* input,
3465 unibrow::byte* util_buffer, 3478 unibrow::byte* util_buffer,
3466 unsigned capacity, 3479 unsigned capacity,
3467 unsigned* remaining, 3480 unsigned* remaining,
3468 unsigned* offset_ptr) { 3481 unsigned* offset_ptr) {
3469 ASSERT(*offset_ptr <= (unsigned)input->length()); 3482 StringShape shape(input);
3470 unsigned chars = input->length() - *offset_ptr; 3483 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3484 unsigned chars = input->length(shape) - *offset_ptr;
3471 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3485 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3472 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars); 3486 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
3473 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length())); 3487 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
3474 *remaining = rbb.remaining; 3488 *remaining = rbb.remaining;
3475 return answer; 3489 return answer;
3476 } 3490 }
3477 3491
3478 3492
3479 const unibrow::byte* String::ReadBlock(String** raw_input, 3493 const unibrow::byte* String::ReadBlock(String** raw_input,
3480 unibrow::byte* util_buffer, 3494 unibrow::byte* util_buffer,
3481 unsigned capacity, 3495 unsigned capacity,
3482 unsigned* remaining, 3496 unsigned* remaining,
3483 unsigned* offset_ptr) { 3497 unsigned* offset_ptr) {
3498 StringShape shape(*raw_input);
3484 Handle<String> input(raw_input); 3499 Handle<String> input(raw_input);
3485 ASSERT(*offset_ptr <= (unsigned)input->length()); 3500 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3486 unsigned chars = input->length() - *offset_ptr; 3501 unsigned chars = input->length(shape) - *offset_ptr;
3487 if (chars > capacity) chars = capacity; 3502 if (chars > capacity) chars = capacity;
3488 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3503 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3489 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars); 3504 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
3490 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length())); 3505 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
3491 *remaining = rbb.remaining; 3506 *remaining = rbb.remaining;
3492 return rbb.util_buffer; 3507 return rbb.util_buffer;
3493 } 3508 }
3494 3509
3495 3510
3496 // This will iterate unless the block of string data spans two 'halves' of 3511 // This will iterate unless the block of string data spans two 'halves' of
3497 // a ConsString, in which case it will recurse. Since the block of string 3512 // a ConsString, in which case it will recurse. Since the block of string
3498 // data to be read has a maximum size this limits the maximum recursion 3513 // data to be read has a maximum size this limits the maximum recursion
3499 // depth to something sane. Since C++ does not have tail call recursion 3514 // depth to something sane. Since C++ does not have tail call recursion
3500 // elimination, the iteration must be explicit. 3515 // elimination, the iteration must be explicit.
3501 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, 3516 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3502 unsigned* offset_ptr, 3517 unsigned* offset_ptr,
3503 unsigned max_chars) { 3518 unsigned max_chars) {
3504 ConsString* current = this; 3519 ConsString* current = this;
3505 unsigned offset = *offset_ptr; 3520 unsigned offset = *offset_ptr;
3506 int offset_correction = 0; 3521 int offset_correction = 0;
3507 3522
3508 while (true) { 3523 while (true) {
3509 String* left = String::cast(current->first()); 3524 String* left = current->first();
3510 unsigned left_length = (unsigned)left->length(); 3525 StringShape left_shape(left);
3526 unsigned left_length = (unsigned)left->length(left_shape);
3511 if (left_length > offset && 3527 if (left_length > offset &&
3512 max_chars <= left_length - offset) { 3528 max_chars <= left_length - offset) {
3513 // Left hand side only - iterate unless we have reached the bottom of 3529 // Left hand side only - iterate unless we have reached the bottom of
3514 // the cons tree. 3530 // the cons tree.
3515 if (left->StringIsConsString()) { 3531 if (left_shape.IsCons()) {
3516 current = ConsString::cast(left); 3532 current = ConsString::cast(left);
3517 continue; 3533 continue;
3518 } else { 3534 } else {
3519 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars); 3535 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
3520 *offset_ptr = offset + offset_correction; 3536 *offset_ptr = offset + offset_correction;
3521 return; 3537 return;
3522 } 3538 }
3523 } else if (left_length <= offset) { 3539 } else if (left_length <= offset) {
3524 // Right hand side only - iterate unless we have reached the bottom of 3540 // Right hand side only - iterate unless we have reached the bottom of
3525 // the cons tree. 3541 // the cons tree.
3526 offset -= left_length; 3542 offset -= left_length;
3527 offset_correction += left_length; 3543 offset_correction += left_length;
3528 String* right = String::cast(current->second()); 3544 String* right = current->second();
3529 if (right->StringIsConsString()) { 3545 if (StringShape(right).IsCons()) {
3530 current = ConsString::cast(right); 3546 current = ConsString::cast(right);
3531 continue; 3547 continue;
3532 } else { 3548 } else {
3533 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars); 3549 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
3534 *offset_ptr = offset + offset_correction; 3550 *offset_ptr = offset + offset_correction;
3535 return; 3551 return;
3536 } 3552 }
3537 } else { 3553 } else {
3538 // The block to be read spans two sides of the ConsString, so we recurse. 3554 // The block to be read spans two sides of the ConsString, so we recurse.
3539 // First recurse on the left. 3555 // First recurse on the left.
(...skipping 11 matching lines...) Expand all
3551 *offset_ptr = offset + offset_correction; 3567 *offset_ptr = offset + offset_correction;
3552 return; 3568 return;
3553 } 3569 }
3554 } 3570 }
3555 } 3571 }
3556 3572
3557 3573
3558 void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, 3574 void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3559 unsigned* offset_ptr, 3575 unsigned* offset_ptr,
3560 unsigned max_chars) { 3576 unsigned max_chars) {
3561 String* backing = String::cast(buffer()); 3577 String* backing = buffer();
3562 unsigned offset = start() + *offset_ptr; 3578 unsigned offset = start() + *offset_ptr;
3563 unsigned length = backing->length(); 3579 unsigned length = backing->length();
3564 if (max_chars > length - offset) { 3580 if (max_chars > length - offset) {
3565 max_chars = length - offset; 3581 max_chars = length - offset;
3566 } 3582 }
3567 String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars); 3583 String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars);
3568 *offset_ptr = offset - start(); 3584 *offset_ptr = offset - start();
3569 } 3585 }
3570 3586
3571 3587
3572 void ConsString::ConsStringIterateBody(ObjectVisitor* v) { 3588 void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
3573 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize); 3589 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
3574 } 3590 }
3575 3591
3576 3592
3577 uint16_t ConsString::ConsStringGet(int index) { 3593 uint16_t ConsString::ConsStringGet(int index) {
3578 ASSERT(index >= 0 && index < this->length()); 3594 ASSERT(index >= 0 && index < this->length());
3579 3595
3580 // Check for a flattened cons string 3596 // Check for a flattened cons string
3581 if (String::cast(second())->length() == 0) { 3597 if (second()->length() == 0) {
3582 return String::cast(first())->Get(index); 3598 String* left = first();
3599 return left->Get(StringShape(left), index);
3583 } 3600 }
3584 3601
3585 String* string = String::cast(this); 3602 String* string = String::cast(this);
3603 StringShape shape(string);
3586 3604
3587 while (true) { 3605 while (true) {
3588 if (string->StringIsConsString()) { 3606 if (shape.IsCons()) {
3589 ConsString* cons_string = ConsString::cast(string); 3607 ConsString* cons_string = ConsString::cast(string);
3590 String* left = String::cast(cons_string->first()); 3608 String* left = cons_string->first();
3591 if (left->length() > index) { 3609 StringShape left_shape(left);
3610 if (left->length(left_shape) > index) {
3592 string = left; 3611 string = left;
3612 shape = left_shape;
3593 } else { 3613 } else {
3594 index -= left->length(); 3614 index -= left->length(left_shape);
3595 string = String::cast(cons_string->second()); 3615 string = cons_string->second();
3616 shape = StringShape(string);
3596 } 3617 }
3597 } else { 3618 } else {
3598 return string->Get(index); 3619 return string->Get(shape, index);
3599 } 3620 }
3600 } 3621 }
3601 3622
3602 UNREACHABLE(); 3623 UNREACHABLE();
3603 return 0; 3624 return 0;
3604 } 3625 }
3605 3626
3606 3627
3607 Object* SlicedString::SlicedStringFlatten() { 3628 Object* SlicedString::SlicedStringFlatten() {
3608 // The SlicedString constructor should ensure that there are no 3629 // The SlicedString constructor should ensure that there are no
3609 // SlicedStrings that are constructed directly on top of other 3630 // SlicedStrings that are constructed directly on top of other
3610 // SlicedStrings. 3631 // SlicedStrings.
3611 String* buf = String::cast(buffer()); 3632 String* buf = String::cast(buffer());
3612 ASSERT(!buf->StringIsSlicedString()); 3633 StringShape buf_shape(buf);
3613 if (buf->StringIsConsString()) { 3634 ASSERT(!buf_shape.IsSliced());
3614 Object* ok = buf->Flatten(); 3635 if (buf_shape.IsCons()) {
3636 Object* ok = buf->Flatten(buf_shape);
3615 if (ok->IsFailure()) return ok; 3637 if (ok->IsFailure()) return ok;
3616 } 3638 }
3617 return this; 3639 return this;
3618 } 3640 }
3619 3641
3620 3642
3621 template <typename sinkchar> 3643 template <typename sinkchar>
3622 void String::WriteToFlat(String* src, 3644 void String::WriteToFlat(String* src,
3645 StringShape src_shape,
3623 sinkchar* sink, 3646 sinkchar* sink,
3624 int f, 3647 int f,
3625 int t) { 3648 int t) {
3626 String* source = src; 3649 String* source = src;
3650 StringShape shape = src_shape;
3627 int from = f; 3651 int from = f;
3628 int to = t; 3652 int to = t;
3629 while (true) { 3653 while (true) {
3630 ASSERT(0 <= from && from <= to && to <= source->length()); 3654 ASSERT(0 <= from && from <= to && to <= source->length(shape));
3631 switch (source->full_representation_tag()) { 3655 switch (shape.full_representation_tag()) {
3632 case kAsciiStringTag | kExternalStringTag: { 3656 case kAsciiStringTag | kExternalStringTag: {
3633 CopyChars(sink, 3657 CopyChars(sink,
3634 ExternalAsciiString::cast(source)->resource()->data() + from, 3658 ExternalAsciiString::cast(source)->resource()->data() + from,
3635 to - from); 3659 to - from);
3636 return; 3660 return;
3637 } 3661 }
3638 case kTwoByteStringTag | kExternalStringTag: { 3662 case kTwoByteStringTag | kExternalStringTag: {
3639 const uc16* data = 3663 const uc16* data =
3640 ExternalTwoByteString::cast(source)->resource()->data(); 3664 ExternalTwoByteString::cast(source)->resource()->data();
3641 CopyChars(sink, 3665 CopyChars(sink,
(...skipping 13 matching lines...) Expand all
3655 to - from); 3679 to - from);
3656 return; 3680 return;
3657 } 3681 }
3658 case kAsciiStringTag | kSlicedStringTag: 3682 case kAsciiStringTag | kSlicedStringTag:
3659 case kTwoByteStringTag | kSlicedStringTag: { 3683 case kTwoByteStringTag | kSlicedStringTag: {
3660 SlicedString* sliced_string = SlicedString::cast(source); 3684 SlicedString* sliced_string = SlicedString::cast(source);
3661 int start = sliced_string->start(); 3685 int start = sliced_string->start();
3662 from += start; 3686 from += start;
3663 to += start; 3687 to += start;
3664 source = String::cast(sliced_string->buffer()); 3688 source = String::cast(sliced_string->buffer());
3689 shape = StringShape(source);
3665 break; 3690 break;
3666 } 3691 }
3667 case kAsciiStringTag | kConsStringTag: 3692 case kAsciiStringTag | kConsStringTag:
3668 case kTwoByteStringTag | kConsStringTag: { 3693 case kTwoByteStringTag | kConsStringTag: {
3669 ConsString* cons_string = ConsString::cast(source); 3694 ConsString* cons_string = ConsString::cast(source);
3670 String* first = String::cast(cons_string->first()); 3695 String* first = cons_string->first();
3671 int boundary = first->length(); 3696 StringShape first_shape(first);
3697 int boundary = first->length(first_shape);
3672 if (to - boundary >= boundary - from) { 3698 if (to - boundary >= boundary - from) {
3673 // Right hand side is longer. Recurse over left. 3699 // Right hand side is longer. Recurse over left.
3674 if (from < boundary) { 3700 if (from < boundary) {
3675 WriteToFlat(first, sink, from, boundary); 3701 WriteToFlat(first, first_shape, sink, from, boundary);
3676 sink += boundary - from; 3702 sink += boundary - from;
3677 from = 0; 3703 from = 0;
3678 } else { 3704 } else {
3679 from -= boundary; 3705 from -= boundary;
3680 } 3706 }
3681 to -= boundary; 3707 to -= boundary;
3682 source = String::cast(cons_string->second()); 3708 source = cons_string->second();
3709 shape = StringShape(source);
3683 } else { 3710 } else {
3684 // Left hand side is longer. Recurse over right. 3711 // Left hand side is longer. Recurse over right.
3685 if (to > boundary) { 3712 if (to > boundary) {
3686 String* second = String::cast(cons_string->second()); 3713 String* second = cons_string->second();
3687 WriteToFlat(second, 3714 WriteToFlat(second,
3715 StringShape(second),
3688 sink + boundary - from, 3716 sink + boundary - from,
3689 0, 3717 0,
3690 to - boundary); 3718 to - boundary);
3691 to = boundary; 3719 to = boundary;
3692 } 3720 }
3693 source = first; 3721 source = first;
3722 shape = first_shape;
3694 } 3723 }
3695 break; 3724 break;
3696 } 3725 }
3697 } 3726 }
3698 } 3727 }
3699 } 3728 }
3700 3729
3701 3730
3702 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { 3731 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
3703 IteratePointer(v, kBufferOffset); 3732 IteratePointer(v, kBufferOffset);
3704 } 3733 }
3705 3734
3706 3735
3707 uint16_t SlicedString::SlicedStringGet(int index) { 3736 uint16_t SlicedString::SlicedStringGet(int index) {
3708 ASSERT(index >= 0 && index < this->length()); 3737 ASSERT(index >= 0 && index < this->length());
3709 // Delegate to the buffer string. 3738 // Delegate to the buffer string.
3710 return String::cast(buffer())->Get(start() + index); 3739 String* underlying = buffer();
3740 return underlying->Get(StringShape(underlying), start() + index);
3711 } 3741 }
3712 3742
3713 3743
3714 template <typename IteratorA, typename IteratorB> 3744 template <typename IteratorA, typename IteratorB>
3715 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { 3745 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
3716 // General slow case check. We know that the ia and ib iterators 3746 // General slow case check. We know that the ia and ib iterators
3717 // have the same length. 3747 // have the same length.
3718 while (ia->has_more()) { 3748 while (ia->has_more()) {
3719 uc32 ca = ia->GetNext(); 3749 uc32 ca = ia->GetNext();
3720 uc32 cb = ib->GetNext(); 3750 uc32 cb = ib->GetNext();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3764 } 3794 }
3765 return true; 3795 return true;
3766 } 3796 }
3767 3797
3768 3798
3769 static StringInputBuffer string_compare_buffer_b; 3799 static StringInputBuffer string_compare_buffer_b;
3770 3800
3771 3801
3772 template <typename IteratorA> 3802 template <typename IteratorA>
3773 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { 3803 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
3774 if (b->IsFlat()) { 3804 StringShape b_shape(b);
3775 if (b->IsAsciiRepresentation()) { 3805 if (b->IsFlat(b_shape)) {
3806 if (b_shape.IsAsciiRepresentation()) {
3776 VectorIterator<char> ib(b->ToAsciiVector()); 3807 VectorIterator<char> ib(b->ToAsciiVector());
3777 return CompareStringContents(ia, &ib); 3808 return CompareStringContents(ia, &ib);
3778 } else { 3809 } else {
3779 VectorIterator<uc16> ib(b->ToUC16Vector()); 3810 VectorIterator<uc16> ib(b->ToUC16Vector());
3780 return CompareStringContents(ia, &ib); 3811 return CompareStringContents(ia, &ib);
3781 } 3812 }
3782 } else { 3813 } else {
3783 string_compare_buffer_b.Reset(0, b); 3814 string_compare_buffer_b.Reset(0, b);
3784 return CompareStringContents(ia, &string_compare_buffer_b); 3815 return CompareStringContents(ia, &string_compare_buffer_b);
3785 } 3816 }
3786 } 3817 }
3787 3818
3788 3819
3789 static StringInputBuffer string_compare_buffer_a; 3820 static StringInputBuffer string_compare_buffer_a;
3790 3821
3791 3822
3792 bool String::SlowEquals(String* other) { 3823 bool String::SlowEquals(StringShape this_shape,
3824 String* other,
3825 StringShape other_shape) {
3793 // Fast check: negative check with lengths. 3826 // Fast check: negative check with lengths.
3794 int len = length(); 3827 int len = length(this_shape);
3795 if (len != other->length()) return false; 3828 if (len != other->length(other_shape)) return false;
3796 if (len == 0) return true; 3829 if (len == 0) return true;
3797 3830
3798 // Fast check: if hash code is computed for both strings 3831 // Fast check: if hash code is computed for both strings
3799 // a fast negative check can be performed. 3832 // a fast negative check can be performed.
3800 if (HasHashCode() && other->HasHashCode()) { 3833 if (HasHashCode() && other->HasHashCode()) {
3801 if (Hash() != other->Hash()) return false; 3834 if (Hash() != other->Hash()) return false;
3802 } 3835 }
3803 3836
3804 if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) { 3837 if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) {
3805 const char* str1 = SeqAsciiString::cast(this)->GetChars(); 3838 const char* str1 = SeqAsciiString::cast(this)->GetChars();
3806 const char* str2 = SeqAsciiString::cast(other)->GetChars(); 3839 const char* str2 = SeqAsciiString::cast(other)->GetChars();
3807 return CompareRawStringContents(Vector<const char>(str1, len), 3840 return CompareRawStringContents(Vector<const char>(str1, len),
3808 Vector<const char>(str2, len)); 3841 Vector<const char>(str2, len));
3809 } 3842 }
3810 3843
3811 if (this->IsFlat()) { 3844 if (this->IsFlat(this_shape)) {
3812 if (this->IsAsciiRepresentation()) { 3845 if (this_shape.IsAsciiRepresentation()) {
3813 Vector<const char> vec1 = this->ToAsciiVector(); 3846 Vector<const char> vec1 = this->ToAsciiVector();
3814 if (other->IsFlat()) { 3847 if (other->IsFlat(other_shape)) {
3815 if (other->IsAsciiRepresentation()) { 3848 if (other_shape.IsAsciiRepresentation()) {
3816 Vector<const char> vec2 = other->ToAsciiVector(); 3849 Vector<const char> vec2 = other->ToAsciiVector();
3817 return CompareRawStringContents(vec1, vec2); 3850 return CompareRawStringContents(vec1, vec2);
3818 } else { 3851 } else {
3819 VectorIterator<char> buf1(vec1); 3852 VectorIterator<char> buf1(vec1);
3820 VectorIterator<uc16> ib(other->ToUC16Vector()); 3853 VectorIterator<uc16> ib(other->ToUC16Vector());
3821 return CompareStringContents(&buf1, &ib); 3854 return CompareStringContents(&buf1, &ib);
3822 } 3855 }
3823 } else { 3856 } else {
3824 VectorIterator<char> buf1(vec1); 3857 VectorIterator<char> buf1(vec1);
3825 string_compare_buffer_b.Reset(0, other); 3858 string_compare_buffer_b.Reset(0, other);
3826 return CompareStringContents(&buf1, &string_compare_buffer_b); 3859 return CompareStringContents(&buf1, &string_compare_buffer_b);
3827 } 3860 }
3828 } else { 3861 } else {
3829 Vector<const uc16> vec1 = this->ToUC16Vector(); 3862 Vector<const uc16> vec1 = this->ToUC16Vector();
3830 if (other->IsFlat()) { 3863 if (other->IsFlat(other_shape)) {
3831 if (other->IsAsciiRepresentation()) { 3864 if (other_shape.IsAsciiRepresentation()) {
3832 VectorIterator<uc16> buf1(vec1); 3865 VectorIterator<uc16> buf1(vec1);
3833 VectorIterator<char> ib(other->ToAsciiVector()); 3866 VectorIterator<char> ib(other->ToAsciiVector());
3834 return CompareStringContents(&buf1, &ib); 3867 return CompareStringContents(&buf1, &ib);
3835 } else { 3868 } else {
3836 Vector<const uc16> vec2(other->ToUC16Vector()); 3869 Vector<const uc16> vec2(other->ToUC16Vector());
3837 return CompareRawStringContents(vec1, vec2); 3870 return CompareRawStringContents(vec1, vec2);
3838 } 3871 }
3839 } else { 3872 } else {
3840 VectorIterator<uc16> buf1(vec1); 3873 VectorIterator<uc16> buf1(vec1);
3841 string_compare_buffer_b.Reset(0, other); 3874 string_compare_buffer_b.Reset(0, other);
3842 return CompareStringContents(&buf1, &string_compare_buffer_b); 3875 return CompareStringContents(&buf1, &string_compare_buffer_b);
3843 } 3876 }
3844 } 3877 }
3845 } else { 3878 } else {
3846 string_compare_buffer_a.Reset(0, this); 3879 string_compare_buffer_a.Reset(0, this);
3847 return CompareStringContentsPartial(&string_compare_buffer_a, other); 3880 return CompareStringContentsPartial(&string_compare_buffer_a, other);
3848 } 3881 }
3849 } 3882 }
3850 3883
3851 3884
3852 bool String::MarkAsUndetectable() { 3885 bool String::MarkAsUndetectable() {
3853 if (this->IsSymbol()) return false; 3886 StringShape shape(this);
3887 if (shape.IsSymbol()) return false;
3854 3888
3855 Map* map = this->map(); 3889 Map* map = this->map();
3856 if (map == Heap::short_string_map()) { 3890 if (map == Heap::short_string_map()) {
3857 this->set_map(Heap::undetectable_short_string_map()); 3891 this->set_map(Heap::undetectable_short_string_map());
3858 return true; 3892 return true;
3859 } else if (map == Heap::medium_string_map()) { 3893 } else if (map == Heap::medium_string_map()) {
3860 this->set_map(Heap::undetectable_medium_string_map()); 3894 this->set_map(Heap::undetectable_medium_string_map());
3861 return true; 3895 return true;
3862 } else if (map == Heap::long_string_map()) { 3896 } else if (map == Heap::long_string_map()) {
3863 this->set_map(Heap::undetectable_long_string_map()); 3897 this->set_map(Heap::undetectable_long_string_map());
3864 return true; 3898 return true;
3865 } else if (map == Heap::short_ascii_string_map()) { 3899 } else if (map == Heap::short_ascii_string_map()) {
3866 this->set_map(Heap::undetectable_short_ascii_string_map()); 3900 this->set_map(Heap::undetectable_short_ascii_string_map());
3867 return true; 3901 return true;
3868 } else if (map == Heap::medium_ascii_string_map()) { 3902 } else if (map == Heap::medium_ascii_string_map()) {
3869 this->set_map(Heap::undetectable_medium_ascii_string_map()); 3903 this->set_map(Heap::undetectable_medium_ascii_string_map());
3870 return true; 3904 return true;
3871 } else if (map == Heap::long_ascii_string_map()) { 3905 } else if (map == Heap::long_ascii_string_map()) {
3872 this->set_map(Heap::undetectable_long_ascii_string_map()); 3906 this->set_map(Heap::undetectable_long_ascii_string_map());
3873 return true; 3907 return true;
3874 } 3908 }
3875 // Rest cannot be marked as undetectable 3909 // Rest cannot be marked as undetectable
3876 return false; 3910 return false;
3877 } 3911 }
3878 3912
3879 3913
3880 bool String::IsEqualTo(Vector<const char> str) { 3914 bool String::IsEqualTo(Vector<const char> str) {
3881 int slen = length(); 3915 StringShape this_shape(this);
3916 int slen = length(this_shape);
3882 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); 3917 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
3883 decoder->Reset(str.start(), str.length()); 3918 decoder->Reset(str.start(), str.length());
3884 int i; 3919 int i;
3885 for (i = 0; i < slen && decoder->has_more(); i++) { 3920 for (i = 0; i < slen && decoder->has_more(); i++) {
3886 uc32 r = decoder->GetNext(); 3921 uc32 r = decoder->GetNext();
3887 if (Get(i) != r) return false; 3922 if (Get(this_shape, i) != r) return false;
3888 } 3923 }
3889 return i == slen && !decoder->has_more(); 3924 return i == slen && !decoder->has_more();
3890 } 3925 }
3891 3926
3892 3927
3893 uint32_t String::ComputeAndSetHash() { 3928 uint32_t String::ComputeAndSetHash() {
3894 // Should only be call if hash code has not yet been computed. 3929 // Should only be call if hash code has not yet been computed.
3895 ASSERT(!(length_field() & kHashComputedMask)); 3930 ASSERT(!(length_field() & kHashComputedMask));
3896 3931
3897 // Compute the hash code. 3932 // Compute the hash code.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3931 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; 3966 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
3932 result = (result * 10) + d; 3967 result = (result * 10) + d;
3933 } 3968 }
3934 3969
3935 *index = result; 3970 *index = result;
3936 return true; 3971 return true;
3937 } 3972 }
3938 3973
3939 3974
3940 bool String::SlowAsArrayIndex(uint32_t* index) { 3975 bool String::SlowAsArrayIndex(uint32_t* index) {
3941 if (length() <= kMaxCachedArrayIndexLength) { 3976 StringShape shape(this);
3977 if (length(shape) <= kMaxCachedArrayIndexLength) {
3942 Hash(); // force computation of hash code 3978 Hash(); // force computation of hash code
3943 uint32_t field = length_field(); 3979 uint32_t field = length_field();
3944 if ((field & kIsArrayIndexMask) == 0) return false; 3980 if ((field & kIsArrayIndexMask) == 0) return false;
3945 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift; 3981 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift;
3946 return true; 3982 return true;
3947 } else { 3983 } else {
3948 StringInputBuffer buffer(this); 3984 StringInputBuffer buffer(this);
3949 return ComputeArrayIndex(&buffer, index, length()); 3985 return ComputeArrayIndex(&buffer, index, length(shape));
3950 } 3986 }
3951 } 3987 }
3952 3988
3953 3989
3954 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { 3990 static inline uint32_t HashField(uint32_t hash, bool is_array_index) {
3955 uint32_t result = 3991 uint32_t result =
3956 (hash << String::kLongLengthShift) | String::kHashComputedMask; 3992 (hash << String::kLongLengthShift) | String::kHashComputedMask;
3957 if (is_array_index) result |= String::kIsArrayIndexMask; 3993 if (is_array_index) result |= String::kIsArrayIndexMask;
3958 return result; 3994 return result;
3959 } 3995 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3999 // Process the remaining characters without updating the array 4035 // Process the remaining characters without updating the array
4000 // index. 4036 // index.
4001 while (buffer->has_more()) { 4037 while (buffer->has_more()) {
4002 hasher.AddCharacterNoIndex(buffer->GetNext()); 4038 hasher.AddCharacterNoIndex(buffer->GetNext());
4003 } 4039 }
4004 4040
4005 return hasher.GetHashField(); 4041 return hasher.GetHashField();
4006 } 4042 }
4007 4043
4008 4044
4009 Object* String::Slice(int start, int end) { 4045 Object* String::Slice(StringShape shape, int start, int end) {
4010 if (start == 0 && end == length()) return this; 4046 if (start == 0 && end == length(shape)) return this;
4011 int representation = representation_tag(); 4047 if (shape.representation_tag() == kSlicedStringTag) {
4012 if (representation == kSlicedStringTag) {
4013 // Translate slices of a SlicedString into slices of the 4048 // Translate slices of a SlicedString into slices of the
4014 // underlying string buffer. 4049 // underlying string buffer.
4015 SlicedString* str = SlicedString::cast(this); 4050 SlicedString* str = SlicedString::cast(this);
4016 return Heap::AllocateSlicedString(String::cast(str->buffer()), 4051 String* buf = str->buffer();
4052 return Heap::AllocateSlicedString(buf,
4053 StringShape(buf),
4017 str->start() + start, 4054 str->start() + start,
4018 str->start() + end); 4055 str->start() + end);
4019 } 4056 }
4020 Object* answer = Heap::AllocateSlicedString(this, start, end); 4057 Object* result = Heap::AllocateSlicedString(this, shape, start, end);
4021 if (answer->IsFailure()) { 4058 if (result->IsFailure()) {
4022 return answer; 4059 return result;
4023 } 4060 }
4024 // Due to the way we retry after GC on allocation failure we are not allowed 4061 // Due to the way we retry after GC on allocation failure we are not allowed
4025 // to fail on allocation after this point. This is the one-allocation rule. 4062 // to fail on allocation after this point. This is the one-allocation rule.
4026 4063
4027 // Try to flatten a cons string that is under the sliced string. 4064 // Try to flatten a cons string that is under the sliced string.
4028 // This is to avoid memory leaks and possible stack overflows caused by 4065 // This is to avoid memory leaks and possible stack overflows caused by
4029 // building 'towers' of sliced strings on cons strings. 4066 // building 'towers' of sliced strings on cons strings.
4030 // This may fail due to an allocation failure (when a GC is needed), but it 4067 // This may fail due to an allocation failure (when a GC is needed), but it
4031 // will succeed often enough to avoid the problem. We only have to do this 4068 // will succeed often enough to avoid the problem. We only have to do this
4032 // if Heap::AllocateSlicedString actually returned a SlicedString. It will 4069 // if Heap::AllocateSlicedString actually returned a SlicedString. It will
4033 // return flat strings for small slices for efficiency reasons. 4070 // return flat strings for small slices for efficiency reasons.
4034 if (String::cast(answer)->StringIsSlicedString() && 4071 String* answer = String::cast(result);
4035 representation == kConsStringTag) { 4072 StringShape answer_shape(answer);
4036 TryFlatten(); 4073 if (answer_shape.IsSliced() &&
4074 shape.representation_tag() == kConsStringTag) {
4075 TryFlatten(shape);
4037 // If the flatten succeeded we might as well make the sliced string point 4076 // If the flatten succeeded we might as well make the sliced string point
4038 // to the flat string rather than the cons string. 4077 // to the flat string rather than the cons string.
4039 if (String::cast(ConsString::cast(this)->second())->length() == 0) { 4078 String* second = ConsString::cast(this)->second();
4079 if (second->length(StringShape(second)) == 0) {
4040 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first()); 4080 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
4041 } 4081 }
4042 } 4082 }
4043 return answer; 4083 return answer;
4044 } 4084 }
4045 4085
4046 4086
4047 void String::PrintOn(FILE* file) { 4087 void String::PrintOn(FILE* file) {
4048 int length = this->length(); 4088 StringShape shape(this);
4089 int length = this->length(shape);
4049 for (int i = 0; i < length; i++) { 4090 for (int i = 0; i < length; i++) {
4050 fprintf(file, "%c", Get(i)); 4091 fprintf(file, "%c", Get(shape, i));
4051 } 4092 }
4052 } 4093 }
4053 4094
4054 4095
4055 void Map::CreateBackPointers() { 4096 void Map::CreateBackPointers() {
4056 DescriptorArray* descriptors = instance_descriptors(); 4097 DescriptorArray* descriptors = instance_descriptors();
4057 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) { 4098 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) {
4058 if (r.type() == MAP_TRANSITION) { 4099 if (r.type() == MAP_TRANSITION) {
4059 // Get target. 4100 // Get target.
4060 Map* target = Map::cast(r.GetValue()); 4101 Map* target = Map::cast(r.GetValue());
(...skipping 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after
5525 if (storage) { 5566 if (storage) {
5526 element_dictionary()->CopyKeysTo(storage, filter); 5567 element_dictionary()->CopyKeysTo(storage, filter);
5527 } 5568 }
5528 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 5569 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
5529 } 5570 }
5530 5571
5531 if (this->IsJSValue()) { 5572 if (this->IsJSValue()) {
5532 Object* val = JSValue::cast(this)->value(); 5573 Object* val = JSValue::cast(this)->value();
5533 if (val->IsString()) { 5574 if (val->IsString()) {
5534 String* str = String::cast(val); 5575 String* str = String::cast(val);
5576 StringShape shape(str);
5535 if (storage) { 5577 if (storage) {
5536 for (int i = 0; i < str->length(); i++) { 5578 for (int i = 0; i < str->length(shape); i++) {
5537 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); 5579 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
5538 } 5580 }
5539 } 5581 }
5540 counter += str->length(); 5582 counter += str->length(shape);
5541 } 5583 }
5542 } 5584 }
5543 ASSERT(!storage || storage->length() == counter); 5585 ASSERT(!storage || storage->length() == counter);
5544 return counter; 5586 return counter;
5545 } 5587 }
5546 5588
5547 5589
5548 int JSObject::GetEnumElementKeys(FixedArray* storage) { 5590 int JSObject::GetEnumElementKeys(FixedArray* storage) {
5549 return GetLocalElementKeys(storage, 5591 return GetLocalElementKeys(storage,
5550 static_cast<PropertyAttributes>(DONT_ENUM)); 5592 static_cast<PropertyAttributes>(DONT_ENUM));
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
5715 5757
5716 bool IsMatch(Object* string) { 5758 bool IsMatch(Object* string) {
5717 return String::cast(string)->Equals(string_); 5759 return String::cast(string)->Equals(string_);
5718 } 5760 }
5719 5761
5720 uint32_t Hash() { return string_->Hash(); } 5762 uint32_t Hash() { return string_->Hash(); }
5721 5763
5722 Object* GetObject() { 5764 Object* GetObject() {
5723 // If the string is a cons string, attempt to flatten it so that 5765 // If the string is a cons string, attempt to flatten it so that
5724 // symbols will most often be flat strings. 5766 // symbols will most often be flat strings.
5725 if (string_->IsConsString()) { 5767 StringShape shape(string_);
5768 if (shape.IsCons()) {
5726 ConsString* cons_string = ConsString::cast(string_); 5769 ConsString* cons_string = ConsString::cast(string_);
5727 cons_string->TryFlatten(); 5770 cons_string->TryFlatten(shape);
5728 if (cons_string->second() == Heap::empty_string()) { 5771 if (cons_string->second() == Heap::empty_string()) {
5729 string_ = String::cast(cons_string->first()); 5772 string_ = cons_string->first();
5730 } 5773 }
5731 } 5774 }
5732 // Transform string to symbol if possible. 5775 // Transform string to symbol if possible.
5733 Map* map = Heap::SymbolMapForString(string_); 5776 Map* map = Heap::SymbolMapForString(string_);
5734 if (map != NULL) { 5777 if (map != NULL) {
5735 string_->set_map(map); 5778 string_->set_map(map);
5736 return string_; 5779 return string_;
5737 } 5780 }
5738 // Otherwise allocate a new symbol. 5781 // Otherwise allocate a new symbol.
5739 StringInputBuffer buffer(string_); 5782 StringInputBuffer buffer(string_);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5877 } 5920 }
5878 5921
5879 5922
5880 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { 5923 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
5881 SymbolKey key(string); 5924 SymbolKey key(string);
5882 int entry = FindEntry(&key); 5925 int entry = FindEntry(&key);
5883 if (entry == -1) { 5926 if (entry == -1) {
5884 return false; 5927 return false;
5885 } else { 5928 } else {
5886 String* result = String::cast(KeyAt(entry)); 5929 String* result = String::cast(KeyAt(entry));
5887 ASSERT(result->is_symbol()); 5930 ASSERT(StringShape(result).IsSymbol());
5888 *symbol = result; 5931 *symbol = result;
5889 return true; 5932 return true;
5890 } 5933 }
5891 } 5934 }
5892 5935
5893 5936
5894 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { 5937 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
5895 Utf8SymbolKey key(str); 5938 Utf8SymbolKey key(str);
5896 return LookupKey(&key, s); 5939 return LookupKey(&key, s);
5897 } 5940 }
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
6785 // No break point. 6828 // No break point.
6786 if (break_point_objects()->IsUndefined()) return 0; 6829 if (break_point_objects()->IsUndefined()) return 0;
6787 // Single beak point. 6830 // Single beak point.
6788 if (!break_point_objects()->IsFixedArray()) return 1; 6831 if (!break_point_objects()->IsFixedArray()) return 1;
6789 // Multiple break points. 6832 // Multiple break points.
6790 return FixedArray::cast(break_point_objects())->length(); 6833 return FixedArray::cast(break_point_objects())->length();
6791 } 6834 }
6792 6835
6793 6836
6794 } } // namespace v8::internal 6837 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698