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

Side by Side Diff: src/objects.cc

Issue 9320: Semi-weekly merge from bleeding_edge to the toiger branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
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
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 AssertNoContextChange ncc; 2291 AssertNoContextChange ncc;
2283 2292
2284 // Check access rights if needed. 2293 // Check access rights if needed.
2285 if (IsAccessCheckNeeded() && 2294 if (IsAccessCheckNeeded() &&
2286 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { 2295 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
2287 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 2296 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
2288 return Heap::undefined_value(); 2297 return Heap::undefined_value();
2289 } 2298 }
2290 2299
2291 // TryFlatten before operating on the string. 2300 // TryFlatten before operating on the string.
2292 name->TryFlatten(); 2301 name->TryFlatten(StringShape(name));
2293 2302
2294 // Make sure name is not an index. 2303 // Make sure name is not an index.
2295 uint32_t index; 2304 uint32_t index;
2296 if (name->AsArrayIndex(&index)) return Heap::undefined_value(); 2305 if (name->AsArrayIndex(&index)) return Heap::undefined_value();
2297 2306
2298 // Check if there is an API defined callback object which prohibits 2307 // Check if there is an API defined callback object which prohibits
2299 // callback overwriting in this object or it's prototype chain. 2308 // callback overwriting in this object or it's prototype chain.
2300 // This mechanism is needed for instance in a browser setting, where 2309 // This mechanism is needed for instance in a browser setting, where
2301 // certain accessors such as window.location should not be allowed 2310 // certain accessors such as window.location should not be allowed
2302 // to be overwriten because allowing overwriting could potentially 2311 // to be overwriten because allowing overwriting could potentially
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after
2921 } 2930 }
2922 return GetContentArray()->IsEqualTo(other->GetContentArray()); 2931 return GetContentArray()->IsEqualTo(other->GetContentArray());
2923 } 2932 }
2924 #endif 2933 #endif
2925 2934
2926 2935
2927 static StaticResource<StringInputBuffer> string_input_buffer; 2936 static StaticResource<StringInputBuffer> string_input_buffer;
2928 2937
2929 2938
2930 bool String::LooksValid() { 2939 bool String::LooksValid() {
2931 if (!Heap::Contains(this)) 2940 if (!Heap::Contains(this)) return false;
2932 return false; 2941 return true;
2933 switch (representation_tag()) {
2934 case kSeqStringTag:
2935 case kConsStringTag:
2936 case kSlicedStringTag:
2937 case kExternalStringTag:
2938 return true;
2939 default:
2940 return false;
2941 }
2942 } 2942 }
2943 2943
2944 2944
2945 int String::Utf8Length() { 2945 int String::Utf8Length() {
2946 if (is_ascii_representation()) return length(); 2946 StringShape shape(this);
2947 if (shape.IsAsciiRepresentation()) return length(shape);
2947 // Attempt to flatten before accessing the string. It probably 2948 // Attempt to flatten before accessing the string. It probably
2948 // doesn't make Utf8Length faster, but it is very likely that 2949 // doesn't make Utf8Length faster, but it is very likely that
2949 // the string will be accessed later (for example by WriteUtf8) 2950 // the string will be accessed later (for example by WriteUtf8)
2950 // so it's still a good idea. 2951 // so it's still a good idea.
2951 TryFlatten(); 2952 if (!IsFlat(shape)) {
2953 TryFlatten(shape); // shape is now no longer valid.
2954 }
2952 Access<StringInputBuffer> buffer(&string_input_buffer); 2955 Access<StringInputBuffer> buffer(&string_input_buffer);
2953 buffer->Reset(0, this); 2956 buffer->Reset(0, this);
2954 int result = 0; 2957 int result = 0;
2955 while (buffer->has_more()) 2958 while (buffer->has_more())
2956 result += unibrow::Utf8::Length(buffer->GetNext()); 2959 result += unibrow::Utf8::Length(buffer->GetNext());
2957 return result; 2960 return result;
2958 } 2961 }
2959 2962
2960 2963
2961 Vector<const char> String::ToAsciiVector() { 2964 Vector<const char> String::ToAsciiVector() {
2962 ASSERT(IsAsciiRepresentation()); 2965 StringShape shape(this);
2963 ASSERT(IsFlat()); 2966 ASSERT(shape.IsAsciiRepresentation());
2967 ASSERT(IsFlat(shape));
2964 2968
2965 int offset = 0; 2969 int offset = 0;
2966 int length = this->length(); 2970 int length = this->length(shape);
2967 StringRepresentationTag string_tag = representation_tag(); 2971 StringRepresentationTag string_tag = shape.representation_tag();
2968 String* string = this; 2972 String* string = this;
2969 if (string_tag == kSlicedStringTag) { 2973 if (string_tag == kSlicedStringTag) {
2970 SlicedString* sliced = SlicedString::cast(string); 2974 SlicedString* sliced = SlicedString::cast(string);
2971 offset += sliced->start(); 2975 offset += sliced->start();
2972 string = String::cast(sliced->buffer()); 2976 string = sliced->buffer();
2973 string_tag = string->representation_tag(); 2977 shape = StringShape(string);
2978 string_tag = shape.representation_tag();
2974 } else if (string_tag == kConsStringTag) { 2979 } else if (string_tag == kConsStringTag) {
2975 ConsString* cons = ConsString::cast(string); 2980 ConsString* cons = ConsString::cast(string);
2976 ASSERT(String::cast(cons->second())->length() == 0); 2981 ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
2977 string = String::cast(cons->first()); 2982 string = cons->first();
2978 string_tag = string->representation_tag(); 2983 shape = StringShape(string);
2984 string_tag = shape.representation_tag();
2979 } 2985 }
2980 if (string_tag == kSeqStringTag) { 2986 if (string_tag == kSeqStringTag) {
2981 SeqAsciiString* seq = SeqAsciiString::cast(string); 2987 SeqAsciiString* seq = SeqAsciiString::cast(string);
2982 char* start = seq->GetChars(); 2988 char* start = seq->GetChars();
2983 return Vector<const char>(start + offset, length); 2989 return Vector<const char>(start + offset, length);
2984 } 2990 }
2985 ASSERT(string_tag == kExternalStringTag); 2991 ASSERT(string_tag == kExternalStringTag);
2986 ExternalAsciiString* ext = ExternalAsciiString::cast(string); 2992 ExternalAsciiString* ext = ExternalAsciiString::cast(string);
2987 const char* start = ext->resource()->data(); 2993 const char* start = ext->resource()->data();
2988 return Vector<const char>(start + offset, length); 2994 return Vector<const char>(start + offset, length);
2989 } 2995 }
2990 2996
2991 2997
2992 Vector<const uc16> String::ToUC16Vector() { 2998 Vector<const uc16> String::ToUC16Vector() {
2993 ASSERT(IsTwoByteStringRepresentation()); 2999 StringShape shape(this);
2994 ASSERT(IsFlat()); 3000 ASSERT(shape.IsTwoByteRepresentation());
3001 ASSERT(IsFlat(shape));
2995 3002
2996 int offset = 0; 3003 int offset = 0;
2997 int length = this->length(); 3004 int length = this->length(shape);
2998 StringRepresentationTag string_tag = representation_tag(); 3005 StringRepresentationTag string_tag = shape.representation_tag();
2999 String* string = this; 3006 String* string = this;
3000 if (string_tag == kSlicedStringTag) { 3007 if (string_tag == kSlicedStringTag) {
3001 SlicedString* sliced = SlicedString::cast(string); 3008 SlicedString* sliced = SlicedString::cast(string);
3002 offset += sliced->start(); 3009 offset += sliced->start();
3003 string = String::cast(sliced->buffer()); 3010 string = String::cast(sliced->buffer());
3004 string_tag = string->representation_tag(); 3011 shape = StringShape(string);
3012 string_tag = shape.representation_tag();
3005 } else if (string_tag == kConsStringTag) { 3013 } else if (string_tag == kConsStringTag) {
3006 ConsString* cons = ConsString::cast(string); 3014 ConsString* cons = ConsString::cast(string);
3007 ASSERT(String::cast(cons->second())->length() == 0); 3015 ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
3008 string = String::cast(cons->first()); 3016 string = cons->first();
3009 string_tag = string->representation_tag(); 3017 shape = StringShape(string);
3018 string_tag = shape.representation_tag();
3010 } 3019 }
3011 if (string_tag == kSeqStringTag) { 3020 if (string_tag == kSeqStringTag) {
3012 SeqTwoByteString* seq = SeqTwoByteString::cast(string); 3021 SeqTwoByteString* seq = SeqTwoByteString::cast(string);
3013 return Vector<const uc16>(seq->GetChars() + offset, length); 3022 return Vector<const uc16>(seq->GetChars() + offset, length);
3014 } 3023 }
3015 ASSERT(string_tag == kExternalStringTag); 3024 ASSERT(string_tag == kExternalStringTag);
3016 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); 3025 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
3017 const uc16* start = 3026 const uc16* start =
3018 reinterpret_cast<const uc16*>(ext->resource()->data()); 3027 reinterpret_cast<const uc16*>(ext->resource()->data());
3019 return Vector<const uc16>(start + offset, length); 3028 return Vector<const uc16>(start + offset, length);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3079 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); 3088 return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
3080 } 3089 }
3081 3090
3082 3091
3083 const uc16* String::GetTwoByteData() { 3092 const uc16* String::GetTwoByteData() {
3084 return GetTwoByteData(0); 3093 return GetTwoByteData(0);
3085 } 3094 }
3086 3095
3087 3096
3088 const uc16* String::GetTwoByteData(unsigned start) { 3097 const uc16* String::GetTwoByteData(unsigned start) {
3089 ASSERT(!IsAsciiRepresentation()); 3098 StringShape shape(this);
3090 switch (representation_tag()) { 3099 ASSERT(!shape.IsAsciiRepresentation());
3100 switch (shape.representation_tag()) {
3091 case kSeqStringTag: 3101 case kSeqStringTag:
3092 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 3102 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
3093 case kExternalStringTag: 3103 case kExternalStringTag:
3094 return ExternalTwoByteString::cast(this)-> 3104 return ExternalTwoByteString::cast(this)->
3095 ExternalTwoByteStringGetData(start); 3105 ExternalTwoByteStringGetData(start);
3096 case kSlicedStringTag: { 3106 case kSlicedStringTag: {
3097 SlicedString* sliced_string = SlicedString::cast(this); 3107 SlicedString* sliced_string = SlicedString::cast(this);
3098 String* buffer = String::cast(sliced_string->buffer()); 3108 String* buffer = sliced_string->buffer();
3099 if (buffer->StringIsConsString()) { 3109 if (StringShape(buffer).IsCons()) {
3100 ConsString* cons_string = ConsString::cast(buffer); 3110 ConsString* cs = ConsString::cast(buffer);
3101 // Flattened string. 3111 // Flattened string.
3102 ASSERT(String::cast(cons_string->second())->length() == 0); 3112 ASSERT(cs->second()->length(StringShape(cs->second())) == 0);
3103 buffer = String::cast(cons_string->first()); 3113 buffer = cs->first();
3104 } 3114 }
3105 return buffer->GetTwoByteData(start + sliced_string->start()); 3115 return buffer->GetTwoByteData(start + sliced_string->start());
3106 } 3116 }
3107 case kConsStringTag: 3117 case kConsStringTag:
3108 UNREACHABLE(); 3118 UNREACHABLE();
3109 return NULL; 3119 return NULL;
3110 } 3120 }
3111 UNREACHABLE(); 3121 UNREACHABLE();
3112 return NULL; 3122 return NULL;
3113 } 3123 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
3194 // -IntoBuffer method it can delegate to one of the efficient 3204 // -IntoBuffer method it can delegate to one of the efficient
3195 // *AsciiStringReadBlock routines. 3205 // *AsciiStringReadBlock routines.
3196 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb, 3206 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
3197 unsigned* offset_ptr, 3207 unsigned* offset_ptr,
3198 unsigned max_chars) { 3208 unsigned max_chars) {
3199 ConsString* current = this; 3209 ConsString* current = this;
3200 unsigned offset = *offset_ptr; 3210 unsigned offset = *offset_ptr;
3201 int offset_correction = 0; 3211 int offset_correction = 0;
3202 3212
3203 while (true) { 3213 while (true) {
3204 String* left = String::cast(current->first()); 3214 String* left = current->first();
3205 unsigned left_length = (unsigned)left->length(); 3215 StringShape left_shape(left);
3216 unsigned left_length = (unsigned)left->length(left_shape);
3206 if (left_length > offset && 3217 if (left_length > offset &&
3207 (max_chars <= left_length - offset || 3218 (max_chars <= left_length - offset ||
3208 (rbb->capacity <= left_length - offset && 3219 (rbb->capacity <= left_length - offset &&
3209 (max_chars = left_length - offset, true)))) { // comma operator! 3220 (max_chars = left_length - offset, true)))) { // comma operator!
3210 // Left hand side only - iterate unless we have reached the bottom of 3221 // Left hand side only - iterate unless we have reached the bottom of
3211 // the cons tree. The assignment on the left of the comma operator is 3222 // the cons tree. The assignment on the left of the comma operator is
3212 // in order to make use of the fact that the -IntoBuffer routines can 3223 // in order to make use of the fact that the -IntoBuffer routines can
3213 // produce at most 'capacity' characters. This enables us to postpone 3224 // produce at most 'capacity' characters. This enables us to postpone
3214 // the point where we switch to the -IntoBuffer routines (below) in order 3225 // the point where we switch to the -IntoBuffer routines (below) in order
3215 // to maximize the chances of delegating a big chunk of work to the 3226 // to maximize the chances of delegating a big chunk of work to the
3216 // efficient *AsciiStringReadBlock routines. 3227 // efficient *AsciiStringReadBlock routines.
3217 if (left->StringIsConsString()) { 3228 if (left_shape.IsCons()) {
3218 current = ConsString::cast(left); 3229 current = ConsString::cast(left);
3219 continue; 3230 continue;
3220 } else { 3231 } else {
3221 const unibrow::byte* answer = 3232 const unibrow::byte* answer =
3222 String::ReadBlock(left, rbb, &offset, max_chars); 3233 String::ReadBlock(left, rbb, &offset, max_chars);
3223 *offset_ptr = offset + offset_correction; 3234 *offset_ptr = offset + offset_correction;
3224 return answer; 3235 return answer;
3225 } 3236 }
3226 } else if (left_length <= offset) { 3237 } else if (left_length <= offset) {
3227 // Right hand side only - iterate unless we have reached the bottom of 3238 // Right hand side only - iterate unless we have reached the bottom of
3228 // the cons tree. 3239 // the cons tree.
3229 String* right = String::cast(current->second()); 3240 String* right = current->second();
3230 offset -= left_length; 3241 offset -= left_length;
3231 offset_correction += left_length; 3242 offset_correction += left_length;
3232 if (right->StringIsConsString()) { 3243 if (StringShape(right).IsCons()) {
3233 current = ConsString::cast(right); 3244 current = ConsString::cast(right);
3234 continue; 3245 continue;
3235 } else { 3246 } else {
3236 const unibrow::byte* answer = 3247 const unibrow::byte* answer =
3237 String::ReadBlock(right, rbb, &offset, max_chars); 3248 String::ReadBlock(right, rbb, &offset, max_chars);
3238 *offset_ptr = offset + offset_correction; 3249 *offset_ptr = offset + offset_correction;
3239 return answer; 3250 return answer;
3240 } 3251 }
3241 } else { 3252 } else {
3242 // The block to be read spans two sides of the ConsString, so we call the 3253 // The block to be read spans two sides of the ConsString, so we call the
(...skipping 11 matching lines...) Expand all
3254 *offset_ptr = offset + offset_correction; 3265 *offset_ptr = offset + offset_correction;
3255 return rbb->util_buffer; 3266 return rbb->util_buffer;
3256 } 3267 }
3257 } 3268 }
3258 } 3269 }
3259 3270
3260 3271
3261 const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb, 3272 const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb,
3262 unsigned* offset_ptr, 3273 unsigned* offset_ptr,
3263 unsigned max_chars) { 3274 unsigned max_chars) {
3264 String* backing = String::cast(buffer()); 3275 String* backing = buffer();
3265 unsigned offset = start() + *offset_ptr; 3276 unsigned offset = start() + *offset_ptr;
3266 unsigned length = backing->length(); 3277 unsigned length = backing->length();
3267 if (max_chars > length - offset) { 3278 if (max_chars > length - offset) {
3268 max_chars = length - offset; 3279 max_chars = length - offset;
3269 } 3280 }
3270 const unibrow::byte* answer = 3281 const unibrow::byte* answer =
3271 String::ReadBlock(backing, rbb, &offset, max_chars); 3282 String::ReadBlock(backing, rbb, &offset, max_chars);
3272 *offset_ptr = offset - start(); 3283 *offset_ptr = offset - start();
3273 return answer; 3284 return answer;
3274 } 3285 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
3372 // (see AsciiStringReadBlock). 3383 // (see AsciiStringReadBlock).
3373 const unibrow::byte* String::ReadBlock(String* input, 3384 const unibrow::byte* String::ReadBlock(String* input,
3374 ReadBlockBuffer* rbb, 3385 ReadBlockBuffer* rbb,
3375 unsigned* offset_ptr, 3386 unsigned* offset_ptr,
3376 unsigned max_chars) { 3387 unsigned max_chars) {
3377 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length())); 3388 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
3378 if (max_chars == 0) { 3389 if (max_chars == 0) {
3379 rbb->remaining = 0; 3390 rbb->remaining = 0;
3380 return NULL; 3391 return NULL;
3381 } 3392 }
3382 switch (input->representation_tag()) { 3393 StringShape shape(input);
3394 switch (shape.representation_tag()) {
3383 case kSeqStringTag: 3395 case kSeqStringTag:
3384 if (input->is_ascii_representation()) { 3396 if (shape.IsAsciiRepresentation()) {
3385 SeqAsciiString* str = SeqAsciiString::cast(input); 3397 SeqAsciiString* str = SeqAsciiString::cast(input);
3386 return str->SeqAsciiStringReadBlock(&rbb->remaining, 3398 return str->SeqAsciiStringReadBlock(&rbb->remaining,
3387 offset_ptr, 3399 offset_ptr,
3388 max_chars); 3400 max_chars);
3389 } else { 3401 } else {
3390 SeqTwoByteString* str = SeqTwoByteString::cast(input); 3402 SeqTwoByteString* str = SeqTwoByteString::cast(input);
3391 str->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3403 str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3392 offset_ptr, 3404 offset_ptr,
3393 max_chars); 3405 max_chars);
3394 return rbb->util_buffer; 3406 return rbb->util_buffer;
3395 } 3407 }
3396 case kConsStringTag: 3408 case kConsStringTag:
3397 return ConsString::cast(input)->ConsStringReadBlock(rbb, 3409 return ConsString::cast(input)->ConsStringReadBlock(rbb,
3398 offset_ptr, 3410 offset_ptr,
3399 max_chars); 3411 max_chars);
3400 case kSlicedStringTag: 3412 case kSlicedStringTag:
3401 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, 3413 return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
3402 offset_ptr, 3414 offset_ptr,
3403 max_chars); 3415 max_chars);
3404 case kExternalStringTag: 3416 case kExternalStringTag:
3405 if (input->is_ascii_representation()) { 3417 if (shape.IsAsciiRepresentation()) {
3406 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( 3418 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
3407 &rbb->remaining, 3419 &rbb->remaining,
3408 offset_ptr, 3420 offset_ptr,
3409 max_chars); 3421 max_chars);
3410 } else { 3422 } else {
3411 ExternalTwoByteString::cast(input)-> 3423 ExternalTwoByteString::cast(input)->
3412 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3424 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3413 offset_ptr, 3425 offset_ptr,
3414 max_chars); 3426 max_chars);
3415 return rbb->util_buffer; 3427 return rbb->util_buffer;
(...skipping 18 matching lines...) Expand all
3434 3446
3435 3447
3436 // This method determines the type of string involved and then copies 3448 // This method determines the type of string involved and then copies
3437 // a whole chunk of characters into a buffer. It can be used with strings 3449 // a whole chunk of characters into a buffer. It can be used with strings
3438 // that have been glued together to form a ConsString and which must cooperate 3450 // that have been glued together to form a ConsString and which must cooperate
3439 // to fill up a buffer. 3451 // to fill up a buffer.
3440 void String::ReadBlockIntoBuffer(String* input, 3452 void String::ReadBlockIntoBuffer(String* input,
3441 ReadBlockBuffer* rbb, 3453 ReadBlockBuffer* rbb,
3442 unsigned* offset_ptr, 3454 unsigned* offset_ptr,
3443 unsigned max_chars) { 3455 unsigned max_chars) {
3444 ASSERT(*offset_ptr <= (unsigned)input->length()); 3456 StringShape shape(input);
3457 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3445 if (max_chars == 0) return; 3458 if (max_chars == 0) return;
3446 3459
3447 switch (input->representation_tag()) { 3460 switch (shape.representation_tag()) {
3448 case kSeqStringTag: 3461 case kSeqStringTag:
3449 if (input->is_ascii_representation()) { 3462 if (shape.IsAsciiRepresentation()) {
3450 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb, 3463 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
3451 offset_ptr, 3464 offset_ptr,
3452 max_chars); 3465 max_chars);
3453 return; 3466 return;
3454 } else { 3467 } else {
3455 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3468 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3456 offset_ptr, 3469 offset_ptr,
3457 max_chars); 3470 max_chars);
3458 return; 3471 return;
3459 } 3472 }
3460 case kConsStringTag: 3473 case kConsStringTag:
3461 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, 3474 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
3462 offset_ptr, 3475 offset_ptr,
3463 max_chars); 3476 max_chars);
3464 return; 3477 return;
3465 case kSlicedStringTag: 3478 case kSlicedStringTag:
3466 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, 3479 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
3467 offset_ptr, 3480 offset_ptr,
3468 max_chars); 3481 max_chars);
3469 return; 3482 return;
3470 case kExternalStringTag: 3483 case kExternalStringTag:
3471 if (input->is_ascii_representation()) { 3484 if (shape.IsAsciiRepresentation()) {
3472 ExternalAsciiString::cast(input)-> 3485 ExternalAsciiString::cast(input)->
3473 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); 3486 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
3474 } else { 3487 } else {
3475 ExternalTwoByteString::cast(input)-> 3488 ExternalTwoByteString::cast(input)->
3476 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3489 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3477 offset_ptr, 3490 offset_ptr,
3478 max_chars); 3491 max_chars);
3479 } 3492 }
3480 return; 3493 return;
3481 default: 3494 default:
3482 break; 3495 break;
3483 } 3496 }
3484 3497
3485 UNREACHABLE(); 3498 UNREACHABLE();
3486 return; 3499 return;
3487 } 3500 }
3488 3501
3489 3502
3490 const unibrow::byte* String::ReadBlock(String* input, 3503 const unibrow::byte* String::ReadBlock(String* input,
3491 unibrow::byte* util_buffer, 3504 unibrow::byte* util_buffer,
3492 unsigned capacity, 3505 unsigned capacity,
3493 unsigned* remaining, 3506 unsigned* remaining,
3494 unsigned* offset_ptr) { 3507 unsigned* offset_ptr) {
3495 ASSERT(*offset_ptr <= (unsigned)input->length()); 3508 StringShape shape(input);
3496 unsigned chars = input->length() - *offset_ptr; 3509 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3510 unsigned chars = input->length(shape) - *offset_ptr;
3497 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3511 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3498 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars); 3512 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
3499 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length())); 3513 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
3500 *remaining = rbb.remaining; 3514 *remaining = rbb.remaining;
3501 return answer; 3515 return answer;
3502 } 3516 }
3503 3517
3504 3518
3505 const unibrow::byte* String::ReadBlock(String** raw_input, 3519 const unibrow::byte* String::ReadBlock(String** raw_input,
3506 unibrow::byte* util_buffer, 3520 unibrow::byte* util_buffer,
3507 unsigned capacity, 3521 unsigned capacity,
3508 unsigned* remaining, 3522 unsigned* remaining,
3509 unsigned* offset_ptr) { 3523 unsigned* offset_ptr) {
3524 StringShape shape(*raw_input);
3510 Handle<String> input(raw_input); 3525 Handle<String> input(raw_input);
3511 ASSERT(*offset_ptr <= (unsigned)input->length()); 3526 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3512 unsigned chars = input->length() - *offset_ptr; 3527 unsigned chars = input->length(shape) - *offset_ptr;
3513 if (chars > capacity) chars = capacity; 3528 if (chars > capacity) chars = capacity;
3514 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3529 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3515 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars); 3530 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
3516 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length())); 3531 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
3517 *remaining = rbb.remaining; 3532 *remaining = rbb.remaining;
3518 return rbb.util_buffer; 3533 return rbb.util_buffer;
3519 } 3534 }
3520 3535
3521 3536
3522 // This will iterate unless the block of string data spans two 'halves' of 3537 // This will iterate unless the block of string data spans two 'halves' of
3523 // a ConsString, in which case it will recurse. Since the block of string 3538 // a ConsString, in which case it will recurse. Since the block of string
3524 // data to be read has a maximum size this limits the maximum recursion 3539 // data to be read has a maximum size this limits the maximum recursion
3525 // depth to something sane. Since C++ does not have tail call recursion 3540 // depth to something sane. Since C++ does not have tail call recursion
3526 // elimination, the iteration must be explicit. 3541 // elimination, the iteration must be explicit.
3527 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, 3542 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3528 unsigned* offset_ptr, 3543 unsigned* offset_ptr,
3529 unsigned max_chars) { 3544 unsigned max_chars) {
3530 ConsString* current = this; 3545 ConsString* current = this;
3531 unsigned offset = *offset_ptr; 3546 unsigned offset = *offset_ptr;
3532 int offset_correction = 0; 3547 int offset_correction = 0;
3533 3548
3534 while (true) { 3549 while (true) {
3535 String* left = String::cast(current->first()); 3550 String* left = current->first();
3536 unsigned left_length = (unsigned)left->length(); 3551 StringShape left_shape(left);
3552 unsigned left_length = (unsigned)left->length(left_shape);
3537 if (left_length > offset && 3553 if (left_length > offset &&
3538 max_chars <= left_length - offset) { 3554 max_chars <= left_length - offset) {
3539 // Left hand side only - iterate unless we have reached the bottom of 3555 // Left hand side only - iterate unless we have reached the bottom of
3540 // the cons tree. 3556 // the cons tree.
3541 if (left->StringIsConsString()) { 3557 if (left_shape.IsCons()) {
3542 current = ConsString::cast(left); 3558 current = ConsString::cast(left);
3543 continue; 3559 continue;
3544 } else { 3560 } else {
3545 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars); 3561 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
3546 *offset_ptr = offset + offset_correction; 3562 *offset_ptr = offset + offset_correction;
3547 return; 3563 return;
3548 } 3564 }
3549 } else if (left_length <= offset) { 3565 } else if (left_length <= offset) {
3550 // Right hand side only - iterate unless we have reached the bottom of 3566 // Right hand side only - iterate unless we have reached the bottom of
3551 // the cons tree. 3567 // the cons tree.
3552 offset -= left_length; 3568 offset -= left_length;
3553 offset_correction += left_length; 3569 offset_correction += left_length;
3554 String* right = String::cast(current->second()); 3570 String* right = current->second();
3555 if (right->StringIsConsString()) { 3571 if (StringShape(right).IsCons()) {
3556 current = ConsString::cast(right); 3572 current = ConsString::cast(right);
3557 continue; 3573 continue;
3558 } else { 3574 } else {
3559 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars); 3575 String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
3560 *offset_ptr = offset + offset_correction; 3576 *offset_ptr = offset + offset_correction;
3561 return; 3577 return;
3562 } 3578 }
3563 } else { 3579 } else {
3564 // The block to be read spans two sides of the ConsString, so we recurse. 3580 // The block to be read spans two sides of the ConsString, so we recurse.
3565 // First recurse on the left. 3581 // First recurse on the left.
(...skipping 11 matching lines...) Expand all
3577 *offset_ptr = offset + offset_correction; 3593 *offset_ptr = offset + offset_correction;
3578 return; 3594 return;
3579 } 3595 }
3580 } 3596 }
3581 } 3597 }
3582 3598
3583 3599
3584 void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, 3600 void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3585 unsigned* offset_ptr, 3601 unsigned* offset_ptr,
3586 unsigned max_chars) { 3602 unsigned max_chars) {
3587 String* backing = String::cast(buffer()); 3603 String* backing = buffer();
3588 unsigned offset = start() + *offset_ptr; 3604 unsigned offset = start() + *offset_ptr;
3589 unsigned length = backing->length(); 3605 unsigned length = backing->length();
3590 if (max_chars > length - offset) { 3606 if (max_chars > length - offset) {
3591 max_chars = length - offset; 3607 max_chars = length - offset;
3592 } 3608 }
3593 String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars); 3609 String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars);
3594 *offset_ptr = offset - start(); 3610 *offset_ptr = offset - start();
3595 } 3611 }
3596 3612
3597 3613
3598 void ConsString::ConsStringIterateBody(ObjectVisitor* v) { 3614 void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
3599 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize); 3615 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
3600 } 3616 }
3601 3617
3602 3618
3603 uint16_t ConsString::ConsStringGet(int index) { 3619 uint16_t ConsString::ConsStringGet(int index) {
3604 ASSERT(index >= 0 && index < this->length()); 3620 ASSERT(index >= 0 && index < this->length());
3605 3621
3606 // Check for a flattened cons string 3622 // Check for a flattened cons string
3607 if (String::cast(second())->length() == 0) { 3623 if (second()->length() == 0) {
3608 return String::cast(first())->Get(index); 3624 String* left = first();
3625 return left->Get(StringShape(left), index);
3609 } 3626 }
3610 3627
3611 String* string = String::cast(this); 3628 String* string = String::cast(this);
3629 StringShape shape(string);
3612 3630
3613 while (true) { 3631 while (true) {
3614 if (string->StringIsConsString()) { 3632 if (shape.IsCons()) {
3615 ConsString* cons_string = ConsString::cast(string); 3633 ConsString* cons_string = ConsString::cast(string);
3616 String* left = String::cast(cons_string->first()); 3634 String* left = cons_string->first();
3617 if (left->length() > index) { 3635 StringShape left_shape(left);
3636 if (left->length(left_shape) > index) {
3618 string = left; 3637 string = left;
3638 shape = left_shape;
3619 } else { 3639 } else {
3620 index -= left->length(); 3640 index -= left->length(left_shape);
3621 string = String::cast(cons_string->second()); 3641 string = cons_string->second();
3642 shape = StringShape(string);
3622 } 3643 }
3623 } else { 3644 } else {
3624 return string->Get(index); 3645 return string->Get(shape, index);
3625 } 3646 }
3626 } 3647 }
3627 3648
3628 UNREACHABLE(); 3649 UNREACHABLE();
3629 return 0; 3650 return 0;
3630 } 3651 }
3631 3652
3632 3653
3633 Object* SlicedString::SlicedStringFlatten() { 3654 Object* SlicedString::SlicedStringFlatten() {
3634 // The SlicedString constructor should ensure that there are no 3655 // The SlicedString constructor should ensure that there are no
3635 // SlicedStrings that are constructed directly on top of other 3656 // SlicedStrings that are constructed directly on top of other
3636 // SlicedStrings. 3657 // SlicedStrings.
3637 String* buf = String::cast(buffer()); 3658 String* buf = String::cast(buffer());
3638 ASSERT(!buf->StringIsSlicedString()); 3659 StringShape buf_shape(buf);
3639 if (buf->StringIsConsString()) { 3660 ASSERT(!buf_shape.IsSliced());
3640 Object* ok = buf->Flatten(); 3661 if (buf_shape.IsCons()) {
3662 Object* ok = buf->Flatten(buf_shape);
3641 if (ok->IsFailure()) return ok; 3663 if (ok->IsFailure()) return ok;
3642 } 3664 }
3643 return this; 3665 return this;
3644 } 3666 }
3645 3667
3646 3668
3647 template <typename sinkchar> 3669 template <typename sinkchar>
3648 void String::WriteToFlat(String* src, 3670 void String::WriteToFlat(String* src,
3671 StringShape src_shape,
3649 sinkchar* sink, 3672 sinkchar* sink,
3650 int f, 3673 int f,
3651 int t) { 3674 int t) {
3652 String* source = src; 3675 String* source = src;
3676 StringShape shape = src_shape;
3653 int from = f; 3677 int from = f;
3654 int to = t; 3678 int to = t;
3655 while (true) { 3679 while (true) {
3656 ASSERT(0 <= from && from <= to && to <= source->length()); 3680 ASSERT(0 <= from && from <= to && to <= source->length(shape));
3657 switch (source->full_representation_tag()) { 3681 switch (shape.full_representation_tag()) {
3658 case kAsciiStringTag | kExternalStringTag: { 3682 case kAsciiStringTag | kExternalStringTag: {
3659 CopyChars(sink, 3683 CopyChars(sink,
3660 ExternalAsciiString::cast(source)->resource()->data() + from, 3684 ExternalAsciiString::cast(source)->resource()->data() + from,
3661 to - from); 3685 to - from);
3662 return; 3686 return;
3663 } 3687 }
3664 case kTwoByteStringTag | kExternalStringTag: { 3688 case kTwoByteStringTag | kExternalStringTag: {
3665 const uc16* data = 3689 const uc16* data =
3666 ExternalTwoByteString::cast(source)->resource()->data(); 3690 ExternalTwoByteString::cast(source)->resource()->data();
3667 CopyChars(sink, 3691 CopyChars(sink,
(...skipping 13 matching lines...) Expand all
3681 to - from); 3705 to - from);
3682 return; 3706 return;
3683 } 3707 }
3684 case kAsciiStringTag | kSlicedStringTag: 3708 case kAsciiStringTag | kSlicedStringTag:
3685 case kTwoByteStringTag | kSlicedStringTag: { 3709 case kTwoByteStringTag | kSlicedStringTag: {
3686 SlicedString* sliced_string = SlicedString::cast(source); 3710 SlicedString* sliced_string = SlicedString::cast(source);
3687 int start = sliced_string->start(); 3711 int start = sliced_string->start();
3688 from += start; 3712 from += start;
3689 to += start; 3713 to += start;
3690 source = String::cast(sliced_string->buffer()); 3714 source = String::cast(sliced_string->buffer());
3715 shape = StringShape(source);
3691 break; 3716 break;
3692 } 3717 }
3693 case kAsciiStringTag | kConsStringTag: 3718 case kAsciiStringTag | kConsStringTag:
3694 case kTwoByteStringTag | kConsStringTag: { 3719 case kTwoByteStringTag | kConsStringTag: {
3695 ConsString* cons_string = ConsString::cast(source); 3720 ConsString* cons_string = ConsString::cast(source);
3696 String* first = String::cast(cons_string->first()); 3721 String* first = cons_string->first();
3697 int boundary = first->length(); 3722 StringShape first_shape(first);
3723 int boundary = first->length(first_shape);
3698 if (to - boundary >= boundary - from) { 3724 if (to - boundary >= boundary - from) {
3699 // Right hand side is longer. Recurse over left. 3725 // Right hand side is longer. Recurse over left.
3700 if (from < boundary) { 3726 if (from < boundary) {
3701 WriteToFlat(first, sink, from, boundary); 3727 WriteToFlat(first, first_shape, sink, from, boundary);
3702 sink += boundary - from; 3728 sink += boundary - from;
3703 from = 0; 3729 from = 0;
3704 } else { 3730 } else {
3705 from -= boundary; 3731 from -= boundary;
3706 } 3732 }
3707 to -= boundary; 3733 to -= boundary;
3708 source = String::cast(cons_string->second()); 3734 source = cons_string->second();
3735 shape = StringShape(source);
3709 } else { 3736 } else {
3710 // Left hand side is longer. Recurse over right. 3737 // Left hand side is longer. Recurse over right.
3711 if (to > boundary) { 3738 if (to > boundary) {
3712 String* second = String::cast(cons_string->second()); 3739 String* second = cons_string->second();
3713 WriteToFlat(second, 3740 WriteToFlat(second,
3741 StringShape(second),
3714 sink + boundary - from, 3742 sink + boundary - from,
3715 0, 3743 0,
3716 to - boundary); 3744 to - boundary);
3717 to = boundary; 3745 to = boundary;
3718 } 3746 }
3719 source = first; 3747 source = first;
3748 shape = first_shape;
3720 } 3749 }
3721 break; 3750 break;
3722 } 3751 }
3723 } 3752 }
3724 } 3753 }
3725 } 3754 }
3726 3755
3727 3756
3728 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { 3757 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
3729 IteratePointer(v, kBufferOffset); 3758 IteratePointer(v, kBufferOffset);
3730 } 3759 }
3731 3760
3732 3761
3733 uint16_t SlicedString::SlicedStringGet(int index) { 3762 uint16_t SlicedString::SlicedStringGet(int index) {
3734 ASSERT(index >= 0 && index < this->length()); 3763 ASSERT(index >= 0 && index < this->length());
3735 // Delegate to the buffer string. 3764 // Delegate to the buffer string.
3736 return String::cast(buffer())->Get(start() + index); 3765 String* underlying = buffer();
3766 return underlying->Get(StringShape(underlying), start() + index);
3737 } 3767 }
3738 3768
3739 3769
3740 template <typename IteratorA, typename IteratorB> 3770 template <typename IteratorA, typename IteratorB>
3741 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { 3771 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
3742 // General slow case check. We know that the ia and ib iterators 3772 // General slow case check. We know that the ia and ib iterators
3743 // have the same length. 3773 // have the same length.
3744 while (ia->has_more()) { 3774 while (ia->has_more()) {
3745 uc32 ca = ia->GetNext(); 3775 uc32 ca = ia->GetNext();
3746 uc32 cb = ib->GetNext(); 3776 uc32 cb = ib->GetNext();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3790 } 3820 }
3791 return true; 3821 return true;
3792 } 3822 }
3793 3823
3794 3824
3795 static StringInputBuffer string_compare_buffer_b; 3825 static StringInputBuffer string_compare_buffer_b;
3796 3826
3797 3827
3798 template <typename IteratorA> 3828 template <typename IteratorA>
3799 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { 3829 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
3800 if (b->IsFlat()) { 3830 StringShape b_shape(b);
3801 if (b->IsAsciiRepresentation()) { 3831 if (b->IsFlat(b_shape)) {
3832 if (b_shape.IsAsciiRepresentation()) {
3802 VectorIterator<char> ib(b->ToAsciiVector()); 3833 VectorIterator<char> ib(b->ToAsciiVector());
3803 return CompareStringContents(ia, &ib); 3834 return CompareStringContents(ia, &ib);
3804 } else { 3835 } else {
3805 VectorIterator<uc16> ib(b->ToUC16Vector()); 3836 VectorIterator<uc16> ib(b->ToUC16Vector());
3806 return CompareStringContents(ia, &ib); 3837 return CompareStringContents(ia, &ib);
3807 } 3838 }
3808 } else { 3839 } else {
3809 string_compare_buffer_b.Reset(0, b); 3840 string_compare_buffer_b.Reset(0, b);
3810 return CompareStringContents(ia, &string_compare_buffer_b); 3841 return CompareStringContents(ia, &string_compare_buffer_b);
3811 } 3842 }
3812 } 3843 }
3813 3844
3814 3845
3815 static StringInputBuffer string_compare_buffer_a; 3846 static StringInputBuffer string_compare_buffer_a;
3816 3847
3817 3848
3818 bool String::SlowEquals(String* other) { 3849 bool String::SlowEquals(StringShape this_shape,
3850 String* other,
3851 StringShape other_shape) {
3819 // Fast check: negative check with lengths. 3852 // Fast check: negative check with lengths.
3820 int len = length(); 3853 int len = length(this_shape);
3821 if (len != other->length()) return false; 3854 if (len != other->length(other_shape)) return false;
3822 if (len == 0) return true; 3855 if (len == 0) return true;
3823 3856
3824 // Fast check: if hash code is computed for both strings 3857 // Fast check: if hash code is computed for both strings
3825 // a fast negative check can be performed. 3858 // a fast negative check can be performed.
3826 if (HasHashCode() && other->HasHashCode()) { 3859 if (HasHashCode() && other->HasHashCode()) {
3827 if (Hash() != other->Hash()) return false; 3860 if (Hash() != other->Hash()) return false;
3828 } 3861 }
3829 3862
3830 if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) { 3863 if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) {
3831 const char* str1 = SeqAsciiString::cast(this)->GetChars(); 3864 const char* str1 = SeqAsciiString::cast(this)->GetChars();
3832 const char* str2 = SeqAsciiString::cast(other)->GetChars(); 3865 const char* str2 = SeqAsciiString::cast(other)->GetChars();
3833 return CompareRawStringContents(Vector<const char>(str1, len), 3866 return CompareRawStringContents(Vector<const char>(str1, len),
3834 Vector<const char>(str2, len)); 3867 Vector<const char>(str2, len));
3835 } 3868 }
3836 3869
3837 if (this->IsFlat()) { 3870 if (this->IsFlat(this_shape)) {
3838 if (this->IsAsciiRepresentation()) { 3871 if (this_shape.IsAsciiRepresentation()) {
3839 Vector<const char> vec1 = this->ToAsciiVector(); 3872 Vector<const char> vec1 = this->ToAsciiVector();
3840 if (other->IsFlat()) { 3873 if (other->IsFlat(other_shape)) {
3841 if (other->IsAsciiRepresentation()) { 3874 if (other_shape.IsAsciiRepresentation()) {
3842 Vector<const char> vec2 = other->ToAsciiVector(); 3875 Vector<const char> vec2 = other->ToAsciiVector();
3843 return CompareRawStringContents(vec1, vec2); 3876 return CompareRawStringContents(vec1, vec2);
3844 } else { 3877 } else {
3845 VectorIterator<char> buf1(vec1); 3878 VectorIterator<char> buf1(vec1);
3846 VectorIterator<uc16> ib(other->ToUC16Vector()); 3879 VectorIterator<uc16> ib(other->ToUC16Vector());
3847 return CompareStringContents(&buf1, &ib); 3880 return CompareStringContents(&buf1, &ib);
3848 } 3881 }
3849 } else { 3882 } else {
3850 VectorIterator<char> buf1(vec1); 3883 VectorIterator<char> buf1(vec1);
3851 string_compare_buffer_b.Reset(0, other); 3884 string_compare_buffer_b.Reset(0, other);
3852 return CompareStringContents(&buf1, &string_compare_buffer_b); 3885 return CompareStringContents(&buf1, &string_compare_buffer_b);
3853 } 3886 }
3854 } else { 3887 } else {
3855 Vector<const uc16> vec1 = this->ToUC16Vector(); 3888 Vector<const uc16> vec1 = this->ToUC16Vector();
3856 if (other->IsFlat()) { 3889 if (other->IsFlat(other_shape)) {
3857 if (other->IsAsciiRepresentation()) { 3890 if (other_shape.IsAsciiRepresentation()) {
3858 VectorIterator<uc16> buf1(vec1); 3891 VectorIterator<uc16> buf1(vec1);
3859 VectorIterator<char> ib(other->ToAsciiVector()); 3892 VectorIterator<char> ib(other->ToAsciiVector());
3860 return CompareStringContents(&buf1, &ib); 3893 return CompareStringContents(&buf1, &ib);
3861 } else { 3894 } else {
3862 Vector<const uc16> vec2(other->ToUC16Vector()); 3895 Vector<const uc16> vec2(other->ToUC16Vector());
3863 return CompareRawStringContents(vec1, vec2); 3896 return CompareRawStringContents(vec1, vec2);
3864 } 3897 }
3865 } else { 3898 } else {
3866 VectorIterator<uc16> buf1(vec1); 3899 VectorIterator<uc16> buf1(vec1);
3867 string_compare_buffer_b.Reset(0, other); 3900 string_compare_buffer_b.Reset(0, other);
3868 return CompareStringContents(&buf1, &string_compare_buffer_b); 3901 return CompareStringContents(&buf1, &string_compare_buffer_b);
3869 } 3902 }
3870 } 3903 }
3871 } else { 3904 } else {
3872 string_compare_buffer_a.Reset(0, this); 3905 string_compare_buffer_a.Reset(0, this);
3873 return CompareStringContentsPartial(&string_compare_buffer_a, other); 3906 return CompareStringContentsPartial(&string_compare_buffer_a, other);
3874 } 3907 }
3875 } 3908 }
3876 3909
3877 3910
3878 bool String::MarkAsUndetectable() { 3911 bool String::MarkAsUndetectable() {
3879 if (this->IsSymbol()) return false; 3912 StringShape shape(this);
3913 if (shape.IsSymbol()) return false;
3880 3914
3881 Map* map = this->map(); 3915 Map* map = this->map();
3882 if (map == Heap::short_string_map()) { 3916 if (map == Heap::short_string_map()) {
3883 this->set_map(Heap::undetectable_short_string_map()); 3917 this->set_map(Heap::undetectable_short_string_map());
3884 return true; 3918 return true;
3885 } else if (map == Heap::medium_string_map()) { 3919 } else if (map == Heap::medium_string_map()) {
3886 this->set_map(Heap::undetectable_medium_string_map()); 3920 this->set_map(Heap::undetectable_medium_string_map());
3887 return true; 3921 return true;
3888 } else if (map == Heap::long_string_map()) { 3922 } else if (map == Heap::long_string_map()) {
3889 this->set_map(Heap::undetectable_long_string_map()); 3923 this->set_map(Heap::undetectable_long_string_map());
3890 return true; 3924 return true;
3891 } else if (map == Heap::short_ascii_string_map()) { 3925 } else if (map == Heap::short_ascii_string_map()) {
3892 this->set_map(Heap::undetectable_short_ascii_string_map()); 3926 this->set_map(Heap::undetectable_short_ascii_string_map());
3893 return true; 3927 return true;
3894 } else if (map == Heap::medium_ascii_string_map()) { 3928 } else if (map == Heap::medium_ascii_string_map()) {
3895 this->set_map(Heap::undetectable_medium_ascii_string_map()); 3929 this->set_map(Heap::undetectable_medium_ascii_string_map());
3896 return true; 3930 return true;
3897 } else if (map == Heap::long_ascii_string_map()) { 3931 } else if (map == Heap::long_ascii_string_map()) {
3898 this->set_map(Heap::undetectable_long_ascii_string_map()); 3932 this->set_map(Heap::undetectable_long_ascii_string_map());
3899 return true; 3933 return true;
3900 } 3934 }
3901 // Rest cannot be marked as undetectable 3935 // Rest cannot be marked as undetectable
3902 return false; 3936 return false;
3903 } 3937 }
3904 3938
3905 3939
3906 bool String::IsEqualTo(Vector<const char> str) { 3940 bool String::IsEqualTo(Vector<const char> str) {
3907 int slen = length(); 3941 StringShape this_shape(this);
3942 int slen = length(this_shape);
3908 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); 3943 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
3909 decoder->Reset(str.start(), str.length()); 3944 decoder->Reset(str.start(), str.length());
3910 int i; 3945 int i;
3911 for (i = 0; i < slen && decoder->has_more(); i++) { 3946 for (i = 0; i < slen && decoder->has_more(); i++) {
3912 uc32 r = decoder->GetNext(); 3947 uc32 r = decoder->GetNext();
3913 if (Get(i) != r) return false; 3948 if (Get(this_shape, i) != r) return false;
3914 } 3949 }
3915 return i == slen && !decoder->has_more(); 3950 return i == slen && !decoder->has_more();
3916 } 3951 }
3917 3952
3918 3953
3919 uint32_t String::ComputeAndSetHash() { 3954 uint32_t String::ComputeAndSetHash() {
3920 // Should only be call if hash code has not yet been computed. 3955 // Should only be call if hash code has not yet been computed.
3921 ASSERT(!(length_field() & kHashComputedMask)); 3956 ASSERT(!(length_field() & kHashComputedMask));
3922 3957
3923 // Compute the hash code. 3958 // Compute the hash code.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3957 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; 3992 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
3958 result = (result * 10) + d; 3993 result = (result * 10) + d;
3959 } 3994 }
3960 3995
3961 *index = result; 3996 *index = result;
3962 return true; 3997 return true;
3963 } 3998 }
3964 3999
3965 4000
3966 bool String::SlowAsArrayIndex(uint32_t* index) { 4001 bool String::SlowAsArrayIndex(uint32_t* index) {
3967 if (length() <= kMaxCachedArrayIndexLength) { 4002 StringShape shape(this);
4003 if (length(shape) <= kMaxCachedArrayIndexLength) {
3968 Hash(); // force computation of hash code 4004 Hash(); // force computation of hash code
3969 uint32_t field = length_field(); 4005 uint32_t field = length_field();
3970 if ((field & kIsArrayIndexMask) == 0) return false; 4006 if ((field & kIsArrayIndexMask) == 0) return false;
3971 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift; 4007 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift;
3972 return true; 4008 return true;
3973 } else { 4009 } else {
3974 StringInputBuffer buffer(this); 4010 StringInputBuffer buffer(this);
3975 return ComputeArrayIndex(&buffer, index, length()); 4011 return ComputeArrayIndex(&buffer, index, length(shape));
3976 } 4012 }
3977 } 4013 }
3978 4014
3979 4015
3980 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { 4016 static inline uint32_t HashField(uint32_t hash, bool is_array_index) {
3981 uint32_t result = 4017 uint32_t result =
3982 (hash << String::kLongLengthShift) | String::kHashComputedMask; 4018 (hash << String::kLongLengthShift) | String::kHashComputedMask;
3983 if (is_array_index) result |= String::kIsArrayIndexMask; 4019 if (is_array_index) result |= String::kIsArrayIndexMask;
3984 return result; 4020 return result;
3985 } 4021 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4025 // Process the remaining characters without updating the array 4061 // Process the remaining characters without updating the array
4026 // index. 4062 // index.
4027 while (buffer->has_more()) { 4063 while (buffer->has_more()) {
4028 hasher.AddCharacterNoIndex(buffer->GetNext()); 4064 hasher.AddCharacterNoIndex(buffer->GetNext());
4029 } 4065 }
4030 4066
4031 return hasher.GetHashField(); 4067 return hasher.GetHashField();
4032 } 4068 }
4033 4069
4034 4070
4035 Object* String::Slice(int start, int end) { 4071 Object* String::Slice(StringShape shape, int start, int end) {
4036 if (start == 0 && end == length()) return this; 4072 if (start == 0 && end == length(shape)) return this;
4037 int representation = representation_tag(); 4073 if (shape.representation_tag() == kSlicedStringTag) {
4038 if (representation == kSlicedStringTag) {
4039 // Translate slices of a SlicedString into slices of the 4074 // Translate slices of a SlicedString into slices of the
4040 // underlying string buffer. 4075 // underlying string buffer.
4041 SlicedString* str = SlicedString::cast(this); 4076 SlicedString* str = SlicedString::cast(this);
4042 return Heap::AllocateSlicedString(String::cast(str->buffer()), 4077 String* buf = str->buffer();
4078 return Heap::AllocateSlicedString(buf,
4079 StringShape(buf),
4043 str->start() + start, 4080 str->start() + start,
4044 str->start() + end); 4081 str->start() + end);
4045 } 4082 }
4046 Object* answer = Heap::AllocateSlicedString(this, start, end); 4083 Object* result = Heap::AllocateSlicedString(this, shape, start, end);
4047 if (answer->IsFailure()) { 4084 if (result->IsFailure()) {
4048 return answer; 4085 return result;
4049 } 4086 }
4050 // Due to the way we retry after GC on allocation failure we are not allowed 4087 // Due to the way we retry after GC on allocation failure we are not allowed
4051 // to fail on allocation after this point. This is the one-allocation rule. 4088 // to fail on allocation after this point. This is the one-allocation rule.
4052 4089
4053 // Try to flatten a cons string that is under the sliced string. 4090 // Try to flatten a cons string that is under the sliced string.
4054 // This is to avoid memory leaks and possible stack overflows caused by 4091 // This is to avoid memory leaks and possible stack overflows caused by
4055 // building 'towers' of sliced strings on cons strings. 4092 // building 'towers' of sliced strings on cons strings.
4056 // This may fail due to an allocation failure (when a GC is needed), but it 4093 // This may fail due to an allocation failure (when a GC is needed), but it
4057 // will succeed often enough to avoid the problem. We only have to do this 4094 // will succeed often enough to avoid the problem. We only have to do this
4058 // if Heap::AllocateSlicedString actually returned a SlicedString. It will 4095 // if Heap::AllocateSlicedString actually returned a SlicedString. It will
4059 // return flat strings for small slices for efficiency reasons. 4096 // return flat strings for small slices for efficiency reasons.
4060 if (String::cast(answer)->StringIsSlicedString() && 4097 String* answer = String::cast(result);
4061 representation == kConsStringTag) { 4098 StringShape answer_shape(answer);
4062 TryFlatten(); 4099 if (answer_shape.IsSliced() &&
4100 shape.representation_tag() == kConsStringTag) {
4101 TryFlatten(shape);
4063 // If the flatten succeeded we might as well make the sliced string point 4102 // If the flatten succeeded we might as well make the sliced string point
4064 // to the flat string rather than the cons string. 4103 // to the flat string rather than the cons string.
4065 if (String::cast(ConsString::cast(this)->second())->length() == 0) { 4104 String* second = ConsString::cast(this)->second();
4105 if (second->length(StringShape(second)) == 0) {
4066 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first()); 4106 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
4067 } 4107 }
4068 } 4108 }
4069 return answer; 4109 return answer;
4070 } 4110 }
4071 4111
4072 4112
4073 void String::PrintOn(FILE* file) { 4113 void String::PrintOn(FILE* file) {
4074 int length = this->length(); 4114 StringShape shape(this);
4115 int length = this->length(shape);
4075 for (int i = 0; i < length; i++) { 4116 for (int i = 0; i < length; i++) {
4076 fprintf(file, "%c", Get(i)); 4117 fprintf(file, "%c", Get(shape, i));
4077 } 4118 }
4078 } 4119 }
4079 4120
4080 4121
4081 void Map::CreateBackPointers() { 4122 void Map::CreateBackPointers() {
4082 DescriptorArray* descriptors = instance_descriptors(); 4123 DescriptorArray* descriptors = instance_descriptors();
4083 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) { 4124 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) {
4084 if (r.type() == MAP_TRANSITION) { 4125 if (r.type() == MAP_TRANSITION) {
4085 // Get target. 4126 // Get target.
4086 Map* target = Map::cast(r.GetValue()); 4127 Map* target = Map::cast(r.GetValue());
(...skipping 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after
5551 if (storage) { 5592 if (storage) {
5552 element_dictionary()->CopyKeysTo(storage, filter); 5593 element_dictionary()->CopyKeysTo(storage, filter);
5553 } 5594 }
5554 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 5595 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
5555 } 5596 }
5556 5597
5557 if (this->IsJSValue()) { 5598 if (this->IsJSValue()) {
5558 Object* val = JSValue::cast(this)->value(); 5599 Object* val = JSValue::cast(this)->value();
5559 if (val->IsString()) { 5600 if (val->IsString()) {
5560 String* str = String::cast(val); 5601 String* str = String::cast(val);
5602 StringShape shape(str);
5561 if (storage) { 5603 if (storage) {
5562 for (int i = 0; i < str->length(); i++) { 5604 for (int i = 0; i < str->length(shape); i++) {
5563 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); 5605 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
5564 } 5606 }
5565 } 5607 }
5566 counter += str->length(); 5608 counter += str->length(shape);
5567 } 5609 }
5568 } 5610 }
5569 ASSERT(!storage || storage->length() == counter); 5611 ASSERT(!storage || storage->length() == counter);
5570 return counter; 5612 return counter;
5571 } 5613 }
5572 5614
5573 5615
5574 int JSObject::GetEnumElementKeys(FixedArray* storage) { 5616 int JSObject::GetEnumElementKeys(FixedArray* storage) {
5575 return GetLocalElementKeys(storage, 5617 return GetLocalElementKeys(storage,
5576 static_cast<PropertyAttributes>(DONT_ENUM)); 5618 static_cast<PropertyAttributes>(DONT_ENUM));
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
5741 5783
5742 bool IsMatch(Object* string) { 5784 bool IsMatch(Object* string) {
5743 return String::cast(string)->Equals(string_); 5785 return String::cast(string)->Equals(string_);
5744 } 5786 }
5745 5787
5746 uint32_t Hash() { return string_->Hash(); } 5788 uint32_t Hash() { return string_->Hash(); }
5747 5789
5748 Object* GetObject() { 5790 Object* GetObject() {
5749 // If the string is a cons string, attempt to flatten it so that 5791 // If the string is a cons string, attempt to flatten it so that
5750 // symbols will most often be flat strings. 5792 // symbols will most often be flat strings.
5751 if (string_->IsConsString()) { 5793 StringShape shape(string_);
5794 if (shape.IsCons()) {
5752 ConsString* cons_string = ConsString::cast(string_); 5795 ConsString* cons_string = ConsString::cast(string_);
5753 cons_string->TryFlatten(); 5796 cons_string->TryFlatten(shape);
5754 if (cons_string->second() == Heap::empty_string()) { 5797 if (cons_string->second() == Heap::empty_string()) {
5755 string_ = String::cast(cons_string->first()); 5798 string_ = cons_string->first();
5756 } 5799 }
5757 } 5800 }
5758 // Transform string to symbol if possible. 5801 // Transform string to symbol if possible.
5759 Map* map = Heap::SymbolMapForString(string_); 5802 Map* map = Heap::SymbolMapForString(string_);
5760 if (map != NULL) { 5803 if (map != NULL) {
5761 string_->set_map(map); 5804 string_->set_map(map);
5762 return string_; 5805 return string_;
5763 } 5806 }
5764 // Otherwise allocate a new symbol. 5807 // Otherwise allocate a new symbol.
5765 StringInputBuffer buffer(string_); 5808 StringInputBuffer buffer(string_);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5903 } 5946 }
5904 5947
5905 5948
5906 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { 5949 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
5907 SymbolKey key(string); 5950 SymbolKey key(string);
5908 int entry = FindEntry(&key); 5951 int entry = FindEntry(&key);
5909 if (entry == -1) { 5952 if (entry == -1) {
5910 return false; 5953 return false;
5911 } else { 5954 } else {
5912 String* result = String::cast(KeyAt(entry)); 5955 String* result = String::cast(KeyAt(entry));
5913 ASSERT(result->is_symbol()); 5956 ASSERT(StringShape(result).IsSymbol());
5914 *symbol = result; 5957 *symbol = result;
5915 return true; 5958 return true;
5916 } 5959 }
5917 } 5960 }
5918 5961
5919 5962
5920 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { 5963 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
5921 Utf8SymbolKey key(str); 5964 Utf8SymbolKey key(str);
5922 return LookupKey(&key, s); 5965 return LookupKey(&key, s);
5923 } 5966 }
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
6811 // No break point. 6854 // No break point.
6812 if (break_point_objects()->IsUndefined()) return 0; 6855 if (break_point_objects()->IsUndefined()) return 0;
6813 // Single beak point. 6856 // Single beak point.
6814 if (!break_point_objects()->IsFixedArray()) return 1; 6857 if (!break_point_objects()->IsFixedArray()) return 1;
6815 // Multiple break points. 6858 // Multiple break points.
6816 return FixedArray::cast(break_point_objects())->length(); 6859 return FixedArray::cast(break_point_objects())->length();
6817 } 6860 }
6818 6861
6819 6862
6820 } } // namespace v8::internal 6863 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698