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

Side by Side Diff: src/objects.cc

Issue 45010: Remove all uses of StringShape variables, since that has proven... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 months 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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 return Construct(RETRY_AFTER_GC, value); 568 return Construct(RETRY_AFTER_GC, value);
569 } 569 }
570 570
571 571
572 // Should a word be prefixed by 'a' or 'an' in order to read naturally in 572 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
573 // English? Returns false for non-ASCII or words that don't start with 573 // English? Returns false for non-ASCII or words that don't start with
574 // a capital letter. The a/an rule follows pronunciation in English. 574 // a capital letter. The a/an rule follows pronunciation in English.
575 // We don't use the BBC's overcorrect "an historic occasion" though if 575 // We don't use the BBC's overcorrect "an historic occasion" though if
576 // you speak a dialect you may well say "an 'istoric occasion". 576 // you speak a dialect you may well say "an 'istoric occasion".
577 static bool AnWord(String* str) { 577 static bool AnWord(String* str) {
578 StringShape shape(str); 578 if (str->length() == 0) return false; // A nothing.
579 if (str->length(shape) == 0) return false; // A nothing. 579 int c0 = str->Get(0);
580 int c0 = str->Get(shape, 0); 580 int c1 = str->length() > 1 ? str->Get(1) : 0;
581 int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0;
582 if (c0 == 'U') { 581 if (c0 == 'U') {
583 if (c1 > 'Z') { 582 if (c1 > 'Z') {
584 return true; // An Umpire, but a UTF8String, a U. 583 return true; // An Umpire, but a UTF8String, a U.
585 } 584 }
586 } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') { 585 } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
587 return true; // An Ape, an ABCBook. 586 return true; // An Ape, an ABCBook.
588 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && 587 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
589 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || 588 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
590 c0 == 'S' || c0 == 'X')) { 589 c0 == 'S' || c0 == 'X')) {
591 return true; // An MP3File, an M. 590 return true; // An MP3File, an M.
592 } 591 }
593 return false; 592 return false;
594 } 593 }
595 594
596 595
597 Object* String::TryFlatten(StringShape shape) { 596 Object* String::TryFlatten() {
598 #ifdef DEBUG 597 #ifdef DEBUG
599 // Do not attempt to flatten in debug mode when allocation is not 598 // Do not attempt to flatten in debug mode when allocation is not
600 // allowed. This is to avoid an assertion failure when allocating. 599 // allowed. This is to avoid an assertion failure when allocating.
601 // Flattening strings is the only case where we always allow 600 // Flattening strings is the only case where we always allow
602 // allocation because no GC is performed if the allocation fails. 601 // allocation because no GC is performed if the allocation fails.
603 if (!Heap::IsAllocationAllowed()) return this; 602 if (!Heap::IsAllocationAllowed()) return this;
604 #endif 603 #endif
605 604
606 switch (shape.representation_tag()) { 605 switch (StringShape(this).representation_tag()) {
607 case kSlicedStringTag: { 606 case kSlicedStringTag: {
608 SlicedString* ss = SlicedString::cast(this); 607 SlicedString* ss = SlicedString::cast(this);
609 // The SlicedString constructor should ensure that there are no 608 // The SlicedString constructor should ensure that there are no
610 // SlicedStrings that are constructed directly on top of other 609 // SlicedStrings that are constructed directly on top of other
611 // SlicedStrings. 610 // SlicedStrings.
612 String* buf = ss->buffer(); 611 String* buf = ss->buffer();
613 ASSERT(!buf->IsSlicedString()); 612 ASSERT(!buf->IsSlicedString());
614 Object* ok = buf->TryFlatten(StringShape(buf)); 613 Object* ok = buf->TryFlatten();
615 if (ok->IsFailure()) return ok; 614 if (ok->IsFailure()) return ok;
616 // Under certain circumstances (TryFlattenIfNotFlat fails in 615 // Under certain circumstances (TryFlattenIfNotFlat fails in
617 // String::Slice) we can have a cons string under a slice. 616 // String::Slice) we can have a cons string under a slice.
618 // In this case we need to get the flat string out of the cons! 617 // In this case we need to get the flat string out of the cons!
619 if (StringShape(String::cast(ok)).IsCons()) { 618 if (StringShape(String::cast(ok)).IsCons()) {
620 ss->set_buffer(ConsString::cast(ok)->first()); 619 ss->set_buffer(ConsString::cast(ok)->first());
621 } 620 }
622 return this; 621 return this;
623 } 622 }
624 case kConsStringTag: { 623 case kConsStringTag: {
625 ConsString* cs = ConsString::cast(this); 624 ConsString* cs = ConsString::cast(this);
626 if (cs->second()->length() == 0) { 625 if (cs->second()->length() == 0) {
627 return this; 626 return this;
628 } 627 }
629 // There's little point in putting the flat string in new space if the 628 // There's little point in putting the flat string in new space if the
630 // cons string is in old space. It can never get GCed until there is 629 // cons string is in old space. It can never get GCed until there is
631 // an old space GC. 630 // an old space GC.
632 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; 631 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
633 int len = length(shape); 632 int len = length();
634 Object* object; 633 Object* object;
635 String* result; 634 String* result;
636 if (shape.IsAsciiRepresentation()) { 635 if (StringShape(this).IsAsciiRepresentation()) {
637 object = Heap::AllocateRawAsciiString(len, tenure); 636 object = Heap::AllocateRawAsciiString(len, tenure);
638 if (object->IsFailure()) return object; 637 if (object->IsFailure()) return object;
639 result = String::cast(object); 638 result = String::cast(object);
640 String* first = cs->first(); 639 String* first = cs->first();
641 StringShape first_shape(first); 640 int first_length = first->length();
642 int first_length = first->length(first_shape);
643 char* dest = SeqAsciiString::cast(result)->GetChars(); 641 char* dest = SeqAsciiString::cast(result)->GetChars();
644 WriteToFlat(first, first_shape, dest, 0, first_length); 642 WriteToFlat(first, dest, 0, first_length);
645 String* second = cs->second(); 643 String* second = cs->second();
646 WriteToFlat(second, 644 WriteToFlat(second,
647 StringShape(second),
648 dest + first_length, 645 dest + first_length,
649 0, 646 0,
650 len - first_length); 647 len - first_length);
651 } else { 648 } else {
652 object = Heap::AllocateRawTwoByteString(len, tenure); 649 object = Heap::AllocateRawTwoByteString(len, tenure);
653 if (object->IsFailure()) return object; 650 if (object->IsFailure()) return object;
654 result = String::cast(object); 651 result = String::cast(object);
655 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); 652 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
656 String* first = cs->first(); 653 String* first = cs->first();
657 StringShape first_shape(first); 654 int first_length = first->length();
658 int first_length = first->length(first_shape); 655 WriteToFlat(first, dest, 0, first_length);
659 WriteToFlat(first, first_shape, dest, 0, first_length);
660 String* second = cs->second(); 656 String* second = cs->second();
661 WriteToFlat(second, 657 WriteToFlat(second,
662 StringShape(second),
663 dest + first_length, 658 dest + first_length,
664 0, 659 0,
665 len - first_length); 660 len - first_length);
666 } 661 }
667 cs->set_first(result); 662 cs->set_first(result);
668 cs->set_second(Heap::empty_string()); 663 cs->set_second(Heap::empty_string());
669 return this; 664 return this;
670 } 665 }
671 default: 666 default:
672 return this; 667 return this;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 } 749 }
755 750
756 // Fill the remainder of the string with dead wood. 751 // Fill the remainder of the string with dead wood.
757 int new_size = this->Size(); // Byte size of the external String object. 752 int new_size = this->Size(); // Byte size of the external String object.
758 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); 753 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
759 return true; 754 return true;
760 } 755 }
761 756
762 757
763 void String::StringShortPrint(StringStream* accumulator) { 758 void String::StringShortPrint(StringStream* accumulator) {
764 StringShape shape(this); 759 int len = length();
765 int len = length(shape);
766 if (len > kMaxMediumStringSize) { 760 if (len > kMaxMediumStringSize) {
767 accumulator->Add("<Very long string[%u]>", len); 761 accumulator->Add("<Very long string[%u]>", len);
768 return; 762 return;
769 } 763 }
770 764
771 if (!LooksValid()) { 765 if (!LooksValid()) {
772 accumulator->Add("<Invalid String>"); 766 accumulator->Add("<Invalid String>");
773 return; 767 return;
774 } 768 }
775 769
776 StringInputBuffer buf(this); 770 StringInputBuffer buf(this);
777 771
778 bool truncated = false; 772 bool truncated = false;
779 if (len > kMaxShortPrintLength) { 773 if (len > kMaxShortPrintLength) {
780 len = kMaxShortPrintLength; 774 len = kMaxShortPrintLength;
781 truncated = true; 775 truncated = true;
782 } 776 }
783 bool ascii = true; 777 bool ascii = true;
784 for (int i = 0; i < len; i++) { 778 for (int i = 0; i < len; i++) {
785 int c = buf.GetNext(); 779 int c = buf.GetNext();
786 780
787 if (c < 32 || c >= 127) { 781 if (c < 32 || c >= 127) {
788 ascii = false; 782 ascii = false;
789 } 783 }
790 } 784 }
791 buf.Reset(this); 785 buf.Reset(this);
792 if (ascii) { 786 if (ascii) {
793 accumulator->Add("<String[%u]: ", length(shape)); 787 accumulator->Add("<String[%u]: ", length());
794 for (int i = 0; i < len; i++) { 788 for (int i = 0; i < len; i++) {
795 accumulator->Put(buf.GetNext()); 789 accumulator->Put(buf.GetNext());
796 } 790 }
797 accumulator->Put('>'); 791 accumulator->Put('>');
798 } else { 792 } else {
799 // Backslash indicates that the string contains control 793 // Backslash indicates that the string contains control
800 // characters and that backslashes are therefore escaped. 794 // characters and that backslashes are therefore escaped.
801 accumulator->Add("<String[%u]\\: ", length(shape)); 795 accumulator->Add("<String[%u]\\: ", length());
802 for (int i = 0; i < len; i++) { 796 for (int i = 0; i < len; i++) {
803 int c = buf.GetNext(); 797 int c = buf.GetNext();
804 if (c == '\n') { 798 if (c == '\n') {
805 accumulator->Add("\\n"); 799 accumulator->Add("\\n");
806 } else if (c == '\r') { 800 } else if (c == '\r') {
807 accumulator->Add("\\r"); 801 accumulator->Add("\\r");
808 } else if (c == '\\') { 802 } else if (c == '\\') {
809 accumulator->Add("\\\\"); 803 accumulator->Add("\\\\");
810 } else if (c < 32 || c > 126) { 804 } else if (c < 32 || c > 126) {
811 accumulator->Add("\\x%02x", c); 805 accumulator->Add("\\x%02x", c);
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 } 966 }
973 967
974 968
975 int HeapObject::SlowSizeFromMap(Map* map) { 969 int HeapObject::SlowSizeFromMap(Map* map) {
976 // Avoid calling functions such as FixedArray::cast during GC, which 970 // Avoid calling functions such as FixedArray::cast during GC, which
977 // read map pointer of this object again. 971 // read map pointer of this object again.
978 InstanceType instance_type = map->instance_type(); 972 InstanceType instance_type = map->instance_type();
979 973
980 if (instance_type < FIRST_NONSTRING_TYPE 974 if (instance_type < FIRST_NONSTRING_TYPE
981 && (StringShape(instance_type).IsSequential())) { 975 && (StringShape(instance_type).IsSequential())) {
982 StringShape shape(instance_type); 976 if (StringShape(instance_type).IsAsciiRepresentation()) {
983 if (shape.IsAsciiRepresentation()) { 977 SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
984 return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(shape); 978 return seq_ascii_this->SeqAsciiStringSize(instance_type);
985 } else { 979 } else {
986 SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this); 980 SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
987 return self->SeqTwoByteStringSize(shape); 981 return self->SeqTwoByteStringSize(instance_type);
988 } 982 }
989 } 983 }
990 984
991 switch (instance_type) { 985 switch (instance_type) {
992 case FIXED_ARRAY_TYPE: 986 case FIXED_ARRAY_TYPE:
993 return reinterpret_cast<FixedArray*>(this)->FixedArraySize(); 987 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
994 case BYTE_ARRAY_TYPE: 988 case BYTE_ARRAY_TYPE:
995 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 989 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
996 case CODE_TYPE: 990 case CODE_TYPE:
997 return reinterpret_cast<Code*>(this)->CodeSize(); 991 return reinterpret_cast<Code*>(this)->CodeSize();
(...skipping 1554 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 AssertNoContextChange ncc; 2546 AssertNoContextChange ncc;
2553 2547
2554 // Check access rights if needed. 2548 // Check access rights if needed.
2555 if (IsAccessCheckNeeded() && 2549 if (IsAccessCheckNeeded() &&
2556 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { 2550 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
2557 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 2551 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
2558 return Heap::undefined_value(); 2552 return Heap::undefined_value();
2559 } 2553 }
2560 2554
2561 // Try to flatten before operating on the string. 2555 // Try to flatten before operating on the string.
2562 name->TryFlattenIfNotFlat(StringShape(name)); 2556 name->TryFlattenIfNotFlat();
2563 2557
2564 // Check if there is an API defined callback object which prohibits 2558 // Check if there is an API defined callback object which prohibits
2565 // callback overwriting in this object or it's prototype chain. 2559 // callback overwriting in this object or it's prototype chain.
2566 // This mechanism is needed for instance in a browser setting, where 2560 // This mechanism is needed for instance in a browser setting, where
2567 // certain accessors such as window.location should not be allowed 2561 // certain accessors such as window.location should not be allowed
2568 // to be overwritten because allowing overwriting could potentially 2562 // to be overwritten because allowing overwriting could potentially
2569 // cause security problems. 2563 // cause security problems.
2570 LookupResult callback_result; 2564 LookupResult callback_result;
2571 LookupCallback(name, &callback_result); 2565 LookupCallback(name, &callback_result);
2572 if (callback_result.IsValid()) { 2566 if (callback_result.IsValid()) {
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
3267 static StaticResource<StringInputBuffer> string_input_buffer; 3261 static StaticResource<StringInputBuffer> string_input_buffer;
3268 3262
3269 3263
3270 bool String::LooksValid() { 3264 bool String::LooksValid() {
3271 if (!Heap::Contains(this)) return false; 3265 if (!Heap::Contains(this)) return false;
3272 return true; 3266 return true;
3273 } 3267 }
3274 3268
3275 3269
3276 int String::Utf8Length() { 3270 int String::Utf8Length() {
3277 StringShape shape(this); 3271 if (StringShape(this).IsAsciiRepresentation()) return length();
3278 if (shape.IsAsciiRepresentation()) return length(shape);
3279 // Attempt to flatten before accessing the string. It probably 3272 // Attempt to flatten before accessing the string. It probably
3280 // doesn't make Utf8Length faster, but it is very likely that 3273 // doesn't make Utf8Length faster, but it is very likely that
3281 // the string will be accessed later (for example by WriteUtf8) 3274 // the string will be accessed later (for example by WriteUtf8)
3282 // so it's still a good idea. 3275 // so it's still a good idea.
3283 TryFlattenIfNotFlat(shape); // shape is now no longer valid. 3276 TryFlattenIfNotFlat();
3284 Access<StringInputBuffer> buffer(&string_input_buffer); 3277 Access<StringInputBuffer> buffer(&string_input_buffer);
3285 buffer->Reset(0, this); 3278 buffer->Reset(0, this);
3286 int result = 0; 3279 int result = 0;
3287 while (buffer->has_more()) 3280 while (buffer->has_more())
3288 result += unibrow::Utf8::Length(buffer->GetNext()); 3281 result += unibrow::Utf8::Length(buffer->GetNext());
3289 return result; 3282 return result;
3290 } 3283 }
3291 3284
3292 3285
3293 Vector<const char> String::ToAsciiVector() { 3286 Vector<const char> String::ToAsciiVector() {
3294 StringShape shape(this); 3287 ASSERT(StringShape(this).IsAsciiRepresentation());
3295 ASSERT(shape.IsAsciiRepresentation()); 3288 ASSERT(IsFlat());
3296 ASSERT(IsFlat(shape));
3297 3289
3298 int offset = 0; 3290 int offset = 0;
3299 int length = this->length(shape); 3291 int length = this->length();
3300 StringRepresentationTag string_tag = shape.representation_tag(); 3292 StringRepresentationTag string_tag = StringShape(this).representation_tag();
3301 String* string = this; 3293 String* string = this;
3302 if (string_tag == kSlicedStringTag) { 3294 if (string_tag == kSlicedStringTag) {
3303 SlicedString* sliced = SlicedString::cast(string); 3295 SlicedString* sliced = SlicedString::cast(string);
3304 offset += sliced->start(); 3296 offset += sliced->start();
3305 string = sliced->buffer(); 3297 string = sliced->buffer();
3306 shape = StringShape(string); 3298 string_tag = StringShape(string).representation_tag();
3307 string_tag = shape.representation_tag();
3308 } else if (string_tag == kConsStringTag) { 3299 } else if (string_tag == kConsStringTag) {
3309 ConsString* cons = ConsString::cast(string); 3300 ConsString* cons = ConsString::cast(string);
3310 ASSERT(cons->second()->length(StringShape(cons->second())) == 0); 3301 ASSERT(cons->second()->length() == 0);
3311 string = cons->first(); 3302 string = cons->first();
3312 shape = StringShape(string); 3303 string_tag = StringShape(string).representation_tag();
3313 string_tag = shape.representation_tag();
3314 } 3304 }
3315 if (string_tag == kSeqStringTag) { 3305 if (string_tag == kSeqStringTag) {
3316 SeqAsciiString* seq = SeqAsciiString::cast(string); 3306 SeqAsciiString* seq = SeqAsciiString::cast(string);
3317 char* start = seq->GetChars(); 3307 char* start = seq->GetChars();
3318 return Vector<const char>(start + offset, length); 3308 return Vector<const char>(start + offset, length);
3319 } 3309 }
3320 ASSERT(string_tag == kExternalStringTag); 3310 ASSERT(string_tag == kExternalStringTag);
3321 ExternalAsciiString* ext = ExternalAsciiString::cast(string); 3311 ExternalAsciiString* ext = ExternalAsciiString::cast(string);
3322 const char* start = ext->resource()->data(); 3312 const char* start = ext->resource()->data();
3323 return Vector<const char>(start + offset, length); 3313 return Vector<const char>(start + offset, length);
3324 } 3314 }
3325 3315
3326 3316
3327 Vector<const uc16> String::ToUC16Vector() { 3317 Vector<const uc16> String::ToUC16Vector() {
3328 StringShape shape(this); 3318 ASSERT(StringShape(this).IsTwoByteRepresentation());
3329 ASSERT(shape.IsTwoByteRepresentation()); 3319 ASSERT(IsFlat());
3330 ASSERT(IsFlat(shape));
3331 3320
3332 int offset = 0; 3321 int offset = 0;
3333 int length = this->length(shape); 3322 int length = this->length();
3334 StringRepresentationTag string_tag = shape.representation_tag(); 3323 StringRepresentationTag string_tag = StringShape(this).representation_tag();
3335 String* string = this; 3324 String* string = this;
3336 if (string_tag == kSlicedStringTag) { 3325 if (string_tag == kSlicedStringTag) {
3337 SlicedString* sliced = SlicedString::cast(string); 3326 SlicedString* sliced = SlicedString::cast(string);
3338 offset += sliced->start(); 3327 offset += sliced->start();
3339 string = String::cast(sliced->buffer()); 3328 string = String::cast(sliced->buffer());
3340 shape = StringShape(string); 3329 string_tag = StringShape(string).representation_tag();
3341 string_tag = shape.representation_tag();
3342 } else if (string_tag == kConsStringTag) { 3330 } else if (string_tag == kConsStringTag) {
3343 ConsString* cons = ConsString::cast(string); 3331 ConsString* cons = ConsString::cast(string);
3344 ASSERT(cons->second()->length(StringShape(cons->second())) == 0); 3332 ASSERT(cons->second()->length() == 0);
3345 string = cons->first(); 3333 string = cons->first();
3346 shape = StringShape(string); 3334 string_tag = StringShape(string).representation_tag();
3347 string_tag = shape.representation_tag();
3348 } 3335 }
3349 if (string_tag == kSeqStringTag) { 3336 if (string_tag == kSeqStringTag) {
3350 SeqTwoByteString* seq = SeqTwoByteString::cast(string); 3337 SeqTwoByteString* seq = SeqTwoByteString::cast(string);
3351 return Vector<const uc16>(seq->GetChars() + offset, length); 3338 return Vector<const uc16>(seq->GetChars() + offset, length);
3352 } 3339 }
3353 ASSERT(string_tag == kExternalStringTag); 3340 ASSERT(string_tag == kExternalStringTag);
3354 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); 3341 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
3355 const uc16* start = 3342 const uc16* start =
3356 reinterpret_cast<const uc16*>(ext->resource()->data()); 3343 reinterpret_cast<const uc16*>(ext->resource()->data());
3357 return Vector<const uc16>(start + offset, length); 3344 return Vector<const uc16>(start + offset, length);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3417 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); 3404 return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
3418 } 3405 }
3419 3406
3420 3407
3421 const uc16* String::GetTwoByteData() { 3408 const uc16* String::GetTwoByteData() {
3422 return GetTwoByteData(0); 3409 return GetTwoByteData(0);
3423 } 3410 }
3424 3411
3425 3412
3426 const uc16* String::GetTwoByteData(unsigned start) { 3413 const uc16* String::GetTwoByteData(unsigned start) {
3427 StringShape shape(this); 3414 ASSERT(!StringShape(this).IsAsciiRepresentation());
3428 ASSERT(!shape.IsAsciiRepresentation()); 3415 switch (StringShape(this).representation_tag()) {
3429 switch (shape.representation_tag()) {
3430 case kSeqStringTag: 3416 case kSeqStringTag:
3431 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 3417 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
3432 case kExternalStringTag: 3418 case kExternalStringTag:
3433 return ExternalTwoByteString::cast(this)-> 3419 return ExternalTwoByteString::cast(this)->
3434 ExternalTwoByteStringGetData(start); 3420 ExternalTwoByteStringGetData(start);
3435 case kSlicedStringTag: { 3421 case kSlicedStringTag: {
3436 SlicedString* sliced_string = SlicedString::cast(this); 3422 SlicedString* sliced_string = SlicedString::cast(this);
3437 String* buffer = sliced_string->buffer(); 3423 String* buffer = sliced_string->buffer();
3438 if (StringShape(buffer).IsCons()) { 3424 if (StringShape(buffer).IsCons()) {
3439 ConsString* cs = ConsString::cast(buffer); 3425 ConsString* cs = ConsString::cast(buffer);
3440 // Flattened string. 3426 // Flattened string.
3441 ASSERT(cs->second()->length(StringShape(cs->second())) == 0); 3427 ASSERT(cs->second()->length() == 0);
3442 buffer = cs->first(); 3428 buffer = cs->first();
3443 } 3429 }
3444 return buffer->GetTwoByteData(start + sliced_string->start()); 3430 return buffer->GetTwoByteData(start + sliced_string->start());
3445 } 3431 }
3446 case kConsStringTag: 3432 case kConsStringTag:
3447 UNREACHABLE(); 3433 UNREACHABLE();
3448 return NULL; 3434 return NULL;
3449 } 3435 }
3450 UNREACHABLE(); 3436 UNREACHABLE();
3451 return NULL; 3437 return NULL;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
3534 // *AsciiStringReadBlock routines. 3520 // *AsciiStringReadBlock routines.
3535 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb, 3521 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
3536 unsigned* offset_ptr, 3522 unsigned* offset_ptr,
3537 unsigned max_chars) { 3523 unsigned max_chars) {
3538 ConsString* current = this; 3524 ConsString* current = this;
3539 unsigned offset = *offset_ptr; 3525 unsigned offset = *offset_ptr;
3540 int offset_correction = 0; 3526 int offset_correction = 0;
3541 3527
3542 while (true) { 3528 while (true) {
3543 String* left = current->first(); 3529 String* left = current->first();
3544 StringShape left_shape(left); 3530 unsigned left_length = (unsigned)left->length();
3545 unsigned left_length = (unsigned)left->length(left_shape);
3546 if (left_length > offset && 3531 if (left_length > offset &&
3547 (max_chars <= left_length - offset || 3532 (max_chars <= left_length - offset ||
3548 (rbb->capacity <= left_length - offset && 3533 (rbb->capacity <= left_length - offset &&
3549 (max_chars = left_length - offset, true)))) { // comma operator! 3534 (max_chars = left_length - offset, true)))) { // comma operator!
3550 // Left hand side only - iterate unless we have reached the bottom of 3535 // Left hand side only - iterate unless we have reached the bottom of
3551 // the cons tree. The assignment on the left of the comma operator is 3536 // the cons tree. The assignment on the left of the comma operator is
3552 // in order to make use of the fact that the -IntoBuffer routines can 3537 // in order to make use of the fact that the -IntoBuffer routines can
3553 // produce at most 'capacity' characters. This enables us to postpone 3538 // produce at most 'capacity' characters. This enables us to postpone
3554 // the point where we switch to the -IntoBuffer routines (below) in order 3539 // the point where we switch to the -IntoBuffer routines (below) in order
3555 // to maximize the chances of delegating a big chunk of work to the 3540 // to maximize the chances of delegating a big chunk of work to the
3556 // efficient *AsciiStringReadBlock routines. 3541 // efficient *AsciiStringReadBlock routines.
3557 if (left_shape.IsCons()) { 3542 if (StringShape(left).IsCons()) {
3558 current = ConsString::cast(left); 3543 current = ConsString::cast(left);
3559 continue; 3544 continue;
3560 } else { 3545 } else {
3561 const unibrow::byte* answer = 3546 const unibrow::byte* answer =
3562 String::ReadBlock(left, rbb, &offset, max_chars); 3547 String::ReadBlock(left, rbb, &offset, max_chars);
3563 *offset_ptr = offset + offset_correction; 3548 *offset_ptr = offset + offset_correction;
3564 return answer; 3549 return answer;
3565 } 3550 }
3566 } else if (left_length <= offset) { 3551 } else if (left_length <= offset) {
3567 // Right hand side only - iterate unless we have reached the bottom of 3552 // Right hand side only - iterate unless we have reached the bottom of
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
3712 // (see AsciiStringReadBlock). 3697 // (see AsciiStringReadBlock).
3713 const unibrow::byte* String::ReadBlock(String* input, 3698 const unibrow::byte* String::ReadBlock(String* input,
3714 ReadBlockBuffer* rbb, 3699 ReadBlockBuffer* rbb,
3715 unsigned* offset_ptr, 3700 unsigned* offset_ptr,
3716 unsigned max_chars) { 3701 unsigned max_chars) {
3717 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length())); 3702 ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
3718 if (max_chars == 0) { 3703 if (max_chars == 0) {
3719 rbb->remaining = 0; 3704 rbb->remaining = 0;
3720 return NULL; 3705 return NULL;
3721 } 3706 }
3722 StringShape shape(input); 3707 switch (StringShape(input).representation_tag()) {
3723 switch (shape.representation_tag()) {
3724 case kSeqStringTag: 3708 case kSeqStringTag:
3725 if (shape.IsAsciiRepresentation()) { 3709 if (StringShape(input).IsAsciiRepresentation()) {
3726 SeqAsciiString* str = SeqAsciiString::cast(input); 3710 SeqAsciiString* str = SeqAsciiString::cast(input);
3727 return str->SeqAsciiStringReadBlock(&rbb->remaining, 3711 return str->SeqAsciiStringReadBlock(&rbb->remaining,
3728 offset_ptr, 3712 offset_ptr,
3729 max_chars); 3713 max_chars);
3730 } else { 3714 } else {
3731 SeqTwoByteString* str = SeqTwoByteString::cast(input); 3715 SeqTwoByteString* str = SeqTwoByteString::cast(input);
3732 str->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3716 str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3733 offset_ptr, 3717 offset_ptr,
3734 max_chars); 3718 max_chars);
3735 return rbb->util_buffer; 3719 return rbb->util_buffer;
3736 } 3720 }
3737 case kConsStringTag: 3721 case kConsStringTag:
3738 return ConsString::cast(input)->ConsStringReadBlock(rbb, 3722 return ConsString::cast(input)->ConsStringReadBlock(rbb,
3739 offset_ptr, 3723 offset_ptr,
3740 max_chars); 3724 max_chars);
3741 case kSlicedStringTag: 3725 case kSlicedStringTag:
3742 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, 3726 return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
3743 offset_ptr, 3727 offset_ptr,
3744 max_chars); 3728 max_chars);
3745 case kExternalStringTag: 3729 case kExternalStringTag:
3746 if (shape.IsAsciiRepresentation()) { 3730 if (StringShape(input).IsAsciiRepresentation()) {
3747 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( 3731 return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
3748 &rbb->remaining, 3732 &rbb->remaining,
3749 offset_ptr, 3733 offset_ptr,
3750 max_chars); 3734 max_chars);
3751 } else { 3735 } else {
3752 ExternalTwoByteString::cast(input)-> 3736 ExternalTwoByteString::cast(input)->
3753 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3737 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3754 offset_ptr, 3738 offset_ptr,
3755 max_chars); 3739 max_chars);
3756 return rbb->util_buffer; 3740 return rbb->util_buffer;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3788 3772
3789 FlatStringReader::~FlatStringReader() { 3773 FlatStringReader::~FlatStringReader() {
3790 ASSERT_EQ(top_, this); 3774 ASSERT_EQ(top_, this);
3791 top_ = prev_; 3775 top_ = prev_;
3792 } 3776 }
3793 3777
3794 3778
3795 void FlatStringReader::RefreshState() { 3779 void FlatStringReader::RefreshState() {
3796 if (str_ == NULL) return; 3780 if (str_ == NULL) return;
3797 Handle<String> str(str_); 3781 Handle<String> str(str_);
3798 StringShape shape(*str); 3782 ASSERT(str->IsFlat());
3799 ASSERT(str->IsFlat(shape)); 3783 is_ascii_ = StringShape(*str).IsAsciiRepresentation();
3800 is_ascii_ = shape.IsAsciiRepresentation();
3801 if (is_ascii_) { 3784 if (is_ascii_) {
3802 start_ = str->ToAsciiVector().start(); 3785 start_ = str->ToAsciiVector().start();
3803 } else { 3786 } else {
3804 start_ = str->ToUC16Vector().start(); 3787 start_ = str->ToUC16Vector().start();
3805 } 3788 }
3806 } 3789 }
3807 3790
3808 3791
3809 void FlatStringReader::PostGarbageCollectionProcessing() { 3792 void FlatStringReader::PostGarbageCollectionProcessing() {
3810 FlatStringReader* current = top_; 3793 FlatStringReader* current = top_;
(...skipping 15 matching lines...) Expand all
3826 3809
3827 3810
3828 // This method determines the type of string involved and then copies 3811 // This method determines the type of string involved and then copies
3829 // a whole chunk of characters into a buffer. It can be used with strings 3812 // a whole chunk of characters into a buffer. It can be used with strings
3830 // that have been glued together to form a ConsString and which must cooperate 3813 // that have been glued together to form a ConsString and which must cooperate
3831 // to fill up a buffer. 3814 // to fill up a buffer.
3832 void String::ReadBlockIntoBuffer(String* input, 3815 void String::ReadBlockIntoBuffer(String* input,
3833 ReadBlockBuffer* rbb, 3816 ReadBlockBuffer* rbb,
3834 unsigned* offset_ptr, 3817 unsigned* offset_ptr,
3835 unsigned max_chars) { 3818 unsigned max_chars) {
3836 StringShape shape(input); 3819 ASSERT(*offset_ptr <= (unsigned)input->length());
3837 ASSERT(*offset_ptr <= (unsigned)input->length(shape));
3838 if (max_chars == 0) return; 3820 if (max_chars == 0) return;
3839 3821
3840 switch (shape.representation_tag()) { 3822 switch (StringShape(input).representation_tag()) {
3841 case kSeqStringTag: 3823 case kSeqStringTag:
3842 if (shape.IsAsciiRepresentation()) { 3824 if (StringShape(input).IsAsciiRepresentation()) {
3843 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb, 3825 SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
3844 offset_ptr, 3826 offset_ptr,
3845 max_chars); 3827 max_chars);
3846 return; 3828 return;
3847 } else { 3829 } else {
3848 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb, 3830 SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3849 offset_ptr, 3831 offset_ptr,
3850 max_chars); 3832 max_chars);
3851 return; 3833 return;
3852 } 3834 }
3853 case kConsStringTag: 3835 case kConsStringTag:
3854 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb, 3836 ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
3855 offset_ptr, 3837 offset_ptr,
3856 max_chars); 3838 max_chars);
3857 return; 3839 return;
3858 case kSlicedStringTag: 3840 case kSlicedStringTag:
3859 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, 3841 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
3860 offset_ptr, 3842 offset_ptr,
3861 max_chars); 3843 max_chars);
3862 return; 3844 return;
3863 case kExternalStringTag: 3845 case kExternalStringTag:
3864 if (shape.IsAsciiRepresentation()) { 3846 if (StringShape(input).IsAsciiRepresentation()) {
3865 ExternalAsciiString::cast(input)-> 3847 ExternalAsciiString::cast(input)->
3866 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); 3848 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
3867 } else { 3849 } else {
3868 ExternalTwoByteString::cast(input)-> 3850 ExternalTwoByteString::cast(input)->
3869 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 3851 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3870 offset_ptr, 3852 offset_ptr,
3871 max_chars); 3853 max_chars);
3872 } 3854 }
3873 return; 3855 return;
3874 default: 3856 default:
3875 break; 3857 break;
3876 } 3858 }
3877 3859
3878 UNREACHABLE(); 3860 UNREACHABLE();
3879 return; 3861 return;
3880 } 3862 }
3881 3863
3882 3864
3883 const unibrow::byte* String::ReadBlock(String* input, 3865 const unibrow::byte* String::ReadBlock(String* input,
3884 unibrow::byte* util_buffer, 3866 unibrow::byte* util_buffer,
3885 unsigned capacity, 3867 unsigned capacity,
3886 unsigned* remaining, 3868 unsigned* remaining,
3887 unsigned* offset_ptr) { 3869 unsigned* offset_ptr) {
3888 StringShape shape(input); 3870 ASSERT(*offset_ptr <= (unsigned)input->length());
3889 ASSERT(*offset_ptr <= (unsigned)input->length(shape)); 3871 unsigned chars = input->length() - *offset_ptr;
3890 unsigned chars = input->length(shape) - *offset_ptr;
3891 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3872 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3892 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars); 3873 const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
3893 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape))); 3874 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
3894 *remaining = rbb.remaining; 3875 *remaining = rbb.remaining;
3895 return answer; 3876 return answer;
3896 } 3877 }
3897 3878
3898 3879
3899 const unibrow::byte* String::ReadBlock(String** raw_input, 3880 const unibrow::byte* String::ReadBlock(String** raw_input,
3900 unibrow::byte* util_buffer, 3881 unibrow::byte* util_buffer,
3901 unsigned capacity, 3882 unsigned capacity,
3902 unsigned* remaining, 3883 unsigned* remaining,
3903 unsigned* offset_ptr) { 3884 unsigned* offset_ptr) {
3904 StringShape shape(*raw_input);
3905 Handle<String> input(raw_input); 3885 Handle<String> input(raw_input);
3906 ASSERT(*offset_ptr <= (unsigned)input->length(shape)); 3886 ASSERT(*offset_ptr <= (unsigned)input->length());
3907 unsigned chars = input->length(shape) - *offset_ptr; 3887 unsigned chars = input->length() - *offset_ptr;
3908 if (chars > capacity) chars = capacity; 3888 if (chars > capacity) chars = capacity;
3909 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); 3889 ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
3910 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars); 3890 ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
3911 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape))); 3891 ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
3912 *remaining = rbb.remaining; 3892 *remaining = rbb.remaining;
3913 return rbb.util_buffer; 3893 return rbb.util_buffer;
3914 } 3894 }
3915 3895
3916 3896
3917 // This will iterate unless the block of string data spans two 'halves' of 3897 // This will iterate unless the block of string data spans two 'halves' of
3918 // a ConsString, in which case it will recurse. Since the block of string 3898 // a ConsString, in which case it will recurse. Since the block of string
3919 // data to be read has a maximum size this limits the maximum recursion 3899 // data to be read has a maximum size this limits the maximum recursion
3920 // depth to something sane. Since C++ does not have tail call recursion 3900 // depth to something sane. Since C++ does not have tail call recursion
3921 // elimination, the iteration must be explicit. 3901 // elimination, the iteration must be explicit.
3922 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, 3902 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3923 unsigned* offset_ptr, 3903 unsigned* offset_ptr,
3924 unsigned max_chars) { 3904 unsigned max_chars) {
3925 ConsString* current = this; 3905 ConsString* current = this;
3926 unsigned offset = *offset_ptr; 3906 unsigned offset = *offset_ptr;
3927 int offset_correction = 0; 3907 int offset_correction = 0;
3928 3908
3929 while (true) { 3909 while (true) {
3930 String* left = current->first(); 3910 String* left = current->first();
3931 StringShape left_shape(left); 3911 unsigned left_length = (unsigned)left->length();
3932 unsigned left_length = (unsigned)left->length(left_shape);
3933 if (left_length > offset && 3912 if (left_length > offset &&
3934 max_chars <= left_length - offset) { 3913 max_chars <= left_length - offset) {
3935 // Left hand side only - iterate unless we have reached the bottom of 3914 // Left hand side only - iterate unless we have reached the bottom of
3936 // the cons tree. 3915 // the cons tree.
3937 if (left_shape.IsCons()) { 3916 if (StringShape(left).IsCons()) {
3938 current = ConsString::cast(left); 3917 current = ConsString::cast(left);
3939 continue; 3918 continue;
3940 } else { 3919 } else {
3941 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars); 3920 String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
3942 *offset_ptr = offset + offset_correction; 3921 *offset_ptr = offset + offset_correction;
3943 return; 3922 return;
3944 } 3923 }
3945 } else if (left_length <= offset) { 3924 } else if (left_length <= offset) {
3946 // Right hand side only - iterate unless we have reached the bottom of 3925 // Right hand side only - iterate unless we have reached the bottom of
3947 // the cons tree. 3926 // the cons tree.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3995 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize); 3974 IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
3996 } 3975 }
3997 3976
3998 3977
3999 uint16_t ConsString::ConsStringGet(int index) { 3978 uint16_t ConsString::ConsStringGet(int index) {
4000 ASSERT(index >= 0 && index < this->length()); 3979 ASSERT(index >= 0 && index < this->length());
4001 3980
4002 // Check for a flattened cons string 3981 // Check for a flattened cons string
4003 if (second()->length() == 0) { 3982 if (second()->length() == 0) {
4004 String* left = first(); 3983 String* left = first();
4005 return left->Get(StringShape(left), index); 3984 return left->Get(index);
4006 } 3985 }
4007 3986
4008 String* string = String::cast(this); 3987 String* string = String::cast(this);
4009 StringShape shape(string);
4010 3988
4011 while (true) { 3989 while (true) {
4012 if (shape.IsCons()) { 3990 if (StringShape(string).IsCons()) {
4013 ConsString* cons_string = ConsString::cast(string); 3991 ConsString* cons_string = ConsString::cast(string);
4014 String* left = cons_string->first(); 3992 String* left = cons_string->first();
4015 StringShape left_shape(left); 3993 if (left->length() > index) {
4016 if (left->length(left_shape) > index) {
4017 string = left; 3994 string = left;
4018 shape = left_shape;
4019 } else { 3995 } else {
4020 index -= left->length(left_shape); 3996 index -= left->length();
4021 string = cons_string->second(); 3997 string = cons_string->second();
4022 shape = StringShape(string);
4023 } 3998 }
4024 } else { 3999 } else {
4025 return string->Get(shape, index); 4000 return string->Get(index);
4026 } 4001 }
4027 } 4002 }
4028 4003
4029 UNREACHABLE(); 4004 UNREACHABLE();
4030 return 0; 4005 return 0;
4031 } 4006 }
4032 4007
4033 4008
4034 template <typename sinkchar> 4009 template <typename sinkchar>
4035 void String::WriteToFlat(String* src, 4010 void String::WriteToFlat(String* src,
4036 StringShape src_shape,
4037 sinkchar* sink, 4011 sinkchar* sink,
4038 int f, 4012 int f,
4039 int t) { 4013 int t) {
4040 String* source = src; 4014 String* source = src;
4041 StringShape shape = src_shape;
4042 int from = f; 4015 int from = f;
4043 int to = t; 4016 int to = t;
4044 while (true) { 4017 while (true) {
4045 ASSERT(0 <= from && from <= to && to <= source->length(shape)); 4018 ASSERT(0 <= from && from <= to && to <= source->length());
4046 switch (shape.full_representation_tag()) { 4019 switch (StringShape(source).full_representation_tag()) {
4047 case kAsciiStringTag | kExternalStringTag: { 4020 case kAsciiStringTag | kExternalStringTag: {
4048 CopyChars(sink, 4021 CopyChars(sink,
4049 ExternalAsciiString::cast(source)->resource()->data() + from, 4022 ExternalAsciiString::cast(source)->resource()->data() + from,
4050 to - from); 4023 to - from);
4051 return; 4024 return;
4052 } 4025 }
4053 case kTwoByteStringTag | kExternalStringTag: { 4026 case kTwoByteStringTag | kExternalStringTag: {
4054 const uc16* data = 4027 const uc16* data =
4055 ExternalTwoByteString::cast(source)->resource()->data(); 4028 ExternalTwoByteString::cast(source)->resource()->data();
4056 CopyChars(sink, 4029 CopyChars(sink,
(...skipping 13 matching lines...) Expand all
4070 to - from); 4043 to - from);
4071 return; 4044 return;
4072 } 4045 }
4073 case kAsciiStringTag | kSlicedStringTag: 4046 case kAsciiStringTag | kSlicedStringTag:
4074 case kTwoByteStringTag | kSlicedStringTag: { 4047 case kTwoByteStringTag | kSlicedStringTag: {
4075 SlicedString* sliced_string = SlicedString::cast(source); 4048 SlicedString* sliced_string = SlicedString::cast(source);
4076 int start = sliced_string->start(); 4049 int start = sliced_string->start();
4077 from += start; 4050 from += start;
4078 to += start; 4051 to += start;
4079 source = String::cast(sliced_string->buffer()); 4052 source = String::cast(sliced_string->buffer());
4080 shape = StringShape(source);
4081 break; 4053 break;
4082 } 4054 }
4083 case kAsciiStringTag | kConsStringTag: 4055 case kAsciiStringTag | kConsStringTag:
4084 case kTwoByteStringTag | kConsStringTag: { 4056 case kTwoByteStringTag | kConsStringTag: {
4085 ConsString* cons_string = ConsString::cast(source); 4057 ConsString* cons_string = ConsString::cast(source);
4086 String* first = cons_string->first(); 4058 String* first = cons_string->first();
4087 StringShape first_shape(first); 4059 int boundary = first->length();
4088 int boundary = first->length(first_shape);
4089 if (to - boundary >= boundary - from) { 4060 if (to - boundary >= boundary - from) {
4090 // Right hand side is longer. Recurse over left. 4061 // Right hand side is longer. Recurse over left.
4091 if (from < boundary) { 4062 if (from < boundary) {
4092 WriteToFlat(first, first_shape, sink, from, boundary); 4063 WriteToFlat(first, sink, from, boundary);
4093 sink += boundary - from; 4064 sink += boundary - from;
4094 from = 0; 4065 from = 0;
4095 } else { 4066 } else {
4096 from -= boundary; 4067 from -= boundary;
4097 } 4068 }
4098 to -= boundary; 4069 to -= boundary;
4099 source = cons_string->second(); 4070 source = cons_string->second();
4100 shape = StringShape(source);
4101 } else { 4071 } else {
4102 // Left hand side is longer. Recurse over right. 4072 // Left hand side is longer. Recurse over right.
4103 if (to > boundary) { 4073 if (to > boundary) {
4104 String* second = cons_string->second(); 4074 String* second = cons_string->second();
4105 WriteToFlat(second, 4075 WriteToFlat(second,
4106 StringShape(second),
4107 sink + boundary - from, 4076 sink + boundary - from,
4108 0, 4077 0,
4109 to - boundary); 4078 to - boundary);
4110 to = boundary; 4079 to = boundary;
4111 } 4080 }
4112 source = first; 4081 source = first;
4113 shape = first_shape;
4114 } 4082 }
4115 break; 4083 break;
4116 } 4084 }
4117 } 4085 }
4118 } 4086 }
4119 } 4087 }
4120 4088
4121 4089
4122 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { 4090 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
4123 IteratePointer(v, kBufferOffset); 4091 IteratePointer(v, kBufferOffset);
4124 } 4092 }
4125 4093
4126 4094
4127 uint16_t SlicedString::SlicedStringGet(int index) { 4095 uint16_t SlicedString::SlicedStringGet(int index) {
4128 ASSERT(index >= 0 && index < this->length()); 4096 ASSERT(index >= 0 && index < this->length());
4129 // Delegate to the buffer string. 4097 // Delegate to the buffer string.
4130 String* underlying = buffer(); 4098 String* underlying = buffer();
4131 return underlying->Get(StringShape(underlying), start() + index); 4099 return underlying->Get(start() + index);
4132 } 4100 }
4133 4101
4134 4102
4135 template <typename IteratorA, typename IteratorB> 4103 template <typename IteratorA, typename IteratorB>
4136 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { 4104 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
4137 // General slow case check. We know that the ia and ib iterators 4105 // General slow case check. We know that the ia and ib iterators
4138 // have the same length. 4106 // have the same length.
4139 while (ia->has_more()) { 4107 while (ia->has_more()) {
4140 uc32 ca = ia->GetNext(); 4108 uc32 ca = ia->GetNext();
4141 uc32 cb = ib->GetNext(); 4109 uc32 cb = ib->GetNext();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4185 } 4153 }
4186 return true; 4154 return true;
4187 } 4155 }
4188 4156
4189 4157
4190 static StringInputBuffer string_compare_buffer_b; 4158 static StringInputBuffer string_compare_buffer_b;
4191 4159
4192 4160
4193 template <typename IteratorA> 4161 template <typename IteratorA>
4194 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { 4162 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
4195 StringShape b_shape(b); 4163 if (b->IsFlat()) {
4196 if (b->IsFlat(b_shape)) { 4164 if (StringShape(b).IsAsciiRepresentation()) {
4197 if (b_shape.IsAsciiRepresentation()) {
4198 VectorIterator<char> ib(b->ToAsciiVector()); 4165 VectorIterator<char> ib(b->ToAsciiVector());
4199 return CompareStringContents(ia, &ib); 4166 return CompareStringContents(ia, &ib);
4200 } else { 4167 } else {
4201 VectorIterator<uc16> ib(b->ToUC16Vector()); 4168 VectorIterator<uc16> ib(b->ToUC16Vector());
4202 return CompareStringContents(ia, &ib); 4169 return CompareStringContents(ia, &ib);
4203 } 4170 }
4204 } else { 4171 } else {
4205 string_compare_buffer_b.Reset(0, b); 4172 string_compare_buffer_b.Reset(0, b);
4206 return CompareStringContents(ia, &string_compare_buffer_b); 4173 return CompareStringContents(ia, &string_compare_buffer_b);
4207 } 4174 }
4208 } 4175 }
4209 4176
4210 4177
4211 static StringInputBuffer string_compare_buffer_a; 4178 static StringInputBuffer string_compare_buffer_a;
4212 4179
4213 4180
4214 bool String::SlowEquals(StringShape this_shape, 4181 bool String::SlowEquals(String* other) {
4215 String* other,
4216 StringShape other_shape) {
4217 // Fast check: negative check with lengths. 4182 // Fast check: negative check with lengths.
4218 int len = length(this_shape); 4183 int len = length();
4219 if (len != other->length(other_shape)) return false; 4184 if (len != other->length()) return false;
4220 if (len == 0) return true; 4185 if (len == 0) return true;
4221 4186
4222 // Fast check: if hash code is computed for both strings 4187 // Fast check: if hash code is computed for both strings
4223 // a fast negative check can be performed. 4188 // a fast negative check can be performed.
4224 if (HasHashCode() && other->HasHashCode()) { 4189 if (HasHashCode() && other->HasHashCode()) {
4225 if (Hash() != other->Hash()) return false; 4190 if (Hash() != other->Hash()) return false;
4226 } 4191 }
4227 4192
4228 if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) { 4193 if (StringShape(this).IsSequentialAscii() && StringShape(other).IsSequentialAs cii()) {
4229 const char* str1 = SeqAsciiString::cast(this)->GetChars(); 4194 const char* str1 = SeqAsciiString::cast(this)->GetChars();
4230 const char* str2 = SeqAsciiString::cast(other)->GetChars(); 4195 const char* str2 = SeqAsciiString::cast(other)->GetChars();
4231 return CompareRawStringContents(Vector<const char>(str1, len), 4196 return CompareRawStringContents(Vector<const char>(str1, len),
4232 Vector<const char>(str2, len)); 4197 Vector<const char>(str2, len));
4233 } 4198 }
4234 4199
4235 if (this->IsFlat(this_shape)) { 4200 if (this->IsFlat()) {
4236 if (this_shape.IsAsciiRepresentation()) { 4201 if (StringShape(this).IsAsciiRepresentation()) {
4237 Vector<const char> vec1 = this->ToAsciiVector(); 4202 Vector<const char> vec1 = this->ToAsciiVector();
4238 if (other->IsFlat(other_shape)) { 4203 if (other->IsFlat()) {
4239 if (other_shape.IsAsciiRepresentation()) { 4204 if (StringShape(other).IsAsciiRepresentation()) {
4240 Vector<const char> vec2 = other->ToAsciiVector(); 4205 Vector<const char> vec2 = other->ToAsciiVector();
4241 return CompareRawStringContents(vec1, vec2); 4206 return CompareRawStringContents(vec1, vec2);
4242 } else { 4207 } else {
4243 VectorIterator<char> buf1(vec1); 4208 VectorIterator<char> buf1(vec1);
4244 VectorIterator<uc16> ib(other->ToUC16Vector()); 4209 VectorIterator<uc16> ib(other->ToUC16Vector());
4245 return CompareStringContents(&buf1, &ib); 4210 return CompareStringContents(&buf1, &ib);
4246 } 4211 }
4247 } else { 4212 } else {
4248 VectorIterator<char> buf1(vec1); 4213 VectorIterator<char> buf1(vec1);
4249 string_compare_buffer_b.Reset(0, other); 4214 string_compare_buffer_b.Reset(0, other);
4250 return CompareStringContents(&buf1, &string_compare_buffer_b); 4215 return CompareStringContents(&buf1, &string_compare_buffer_b);
4251 } 4216 }
4252 } else { 4217 } else {
4253 Vector<const uc16> vec1 = this->ToUC16Vector(); 4218 Vector<const uc16> vec1 = this->ToUC16Vector();
4254 if (other->IsFlat(other_shape)) { 4219 if (other->IsFlat()) {
4255 if (other_shape.IsAsciiRepresentation()) { 4220 if (StringShape(other).IsAsciiRepresentation()) {
4256 VectorIterator<uc16> buf1(vec1); 4221 VectorIterator<uc16> buf1(vec1);
4257 VectorIterator<char> ib(other->ToAsciiVector()); 4222 VectorIterator<char> ib(other->ToAsciiVector());
4258 return CompareStringContents(&buf1, &ib); 4223 return CompareStringContents(&buf1, &ib);
4259 } else { 4224 } else {
4260 Vector<const uc16> vec2(other->ToUC16Vector()); 4225 Vector<const uc16> vec2(other->ToUC16Vector());
4261 return CompareRawStringContents(vec1, vec2); 4226 return CompareRawStringContents(vec1, vec2);
4262 } 4227 }
4263 } else { 4228 } else {
4264 VectorIterator<uc16> buf1(vec1); 4229 VectorIterator<uc16> buf1(vec1);
4265 string_compare_buffer_b.Reset(0, other); 4230 string_compare_buffer_b.Reset(0, other);
(...skipping 29 matching lines...) Expand all
4295 } else if (map == Heap::long_ascii_string_map()) { 4260 } else if (map == Heap::long_ascii_string_map()) {
4296 this->set_map(Heap::undetectable_long_ascii_string_map()); 4261 this->set_map(Heap::undetectable_long_ascii_string_map());
4297 return true; 4262 return true;
4298 } 4263 }
4299 // Rest cannot be marked as undetectable 4264 // Rest cannot be marked as undetectable
4300 return false; 4265 return false;
4301 } 4266 }
4302 4267
4303 4268
4304 bool String::IsEqualTo(Vector<const char> str) { 4269 bool String::IsEqualTo(Vector<const char> str) {
4305 StringShape this_shape(this); 4270 int slen = length();
4306 int slen = length(this_shape);
4307 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); 4271 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
4308 decoder->Reset(str.start(), str.length()); 4272 decoder->Reset(str.start(), str.length());
4309 int i; 4273 int i;
4310 for (i = 0; i < slen && decoder->has_more(); i++) { 4274 for (i = 0; i < slen && decoder->has_more(); i++) {
4311 uc32 r = decoder->GetNext(); 4275 uc32 r = decoder->GetNext();
4312 if (Get(this_shape, i) != r) return false; 4276 if (Get(i) != r) return false;
4313 } 4277 }
4314 return i == slen && !decoder->has_more(); 4278 return i == slen && !decoder->has_more();
4315 } 4279 }
4316 4280
4317 4281
4318 uint32_t String::ComputeAndSetHash() { 4282 uint32_t String::ComputeAndSetHash() {
4319 // Should only be call if hash code has not yet been computed. 4283 // Should only be call if hash code has not yet been computed.
4320 ASSERT(!(length_field() & kHashComputedMask)); 4284 ASSERT(!(length_field() & kHashComputedMask));
4321 4285
4322 // Compute the hash code. 4286 // Compute the hash code.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4356 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false; 4320 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
4357 result = (result * 10) + d; 4321 result = (result * 10) + d;
4358 } 4322 }
4359 4323
4360 *index = result; 4324 *index = result;
4361 return true; 4325 return true;
4362 } 4326 }
4363 4327
4364 4328
4365 bool String::SlowAsArrayIndex(uint32_t* index) { 4329 bool String::SlowAsArrayIndex(uint32_t* index) {
4366 StringShape shape(this); 4330 if (length() <= kMaxCachedArrayIndexLength) {
4367 if (length(shape) <= kMaxCachedArrayIndexLength) {
4368 Hash(); // force computation of hash code 4331 Hash(); // force computation of hash code
4369 uint32_t field = length_field(); 4332 uint32_t field = length_field();
4370 if ((field & kIsArrayIndexMask) == 0) return false; 4333 if ((field & kIsArrayIndexMask) == 0) return false;
4371 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift; 4334 *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift;
4372 return true; 4335 return true;
4373 } else { 4336 } else {
4374 StringInputBuffer buffer(this); 4337 StringInputBuffer buffer(this);
4375 return ComputeArrayIndex(&buffer, index, length(shape)); 4338 return ComputeArrayIndex(&buffer, index, length());
4376 } 4339 }
4377 } 4340 }
4378 4341
4379 4342
4380 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { 4343 static inline uint32_t HashField(uint32_t hash, bool is_array_index) {
4381 uint32_t result = 4344 uint32_t result =
4382 (hash << String::kLongLengthShift) | String::kHashComputedMask; 4345 (hash << String::kLongLengthShift) | String::kHashComputedMask;
4383 if (is_array_index) result |= String::kIsArrayIndexMask; 4346 if (is_array_index) result |= String::kIsArrayIndexMask;
4384 return result; 4347 return result;
4385 } 4348 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
4426 // index. 4389 // index.
4427 while (buffer->has_more()) { 4390 while (buffer->has_more()) {
4428 hasher.AddCharacterNoIndex(buffer->GetNext()); 4391 hasher.AddCharacterNoIndex(buffer->GetNext());
4429 } 4392 }
4430 4393
4431 return hasher.GetHashField(); 4394 return hasher.GetHashField();
4432 } 4395 }
4433 4396
4434 4397
4435 Object* String::Slice(int start, int end) { 4398 Object* String::Slice(int start, int end) {
4436 StringShape shape(this); 4399 if (start == 0 && end == length()) return this;
4437 if (start == 0 && end == length(shape)) return this; 4400 if (StringShape(this).representation_tag() == kSlicedStringTag) {
4438 if (shape.representation_tag() == kSlicedStringTag) {
4439 // Translate slices of a SlicedString into slices of the 4401 // Translate slices of a SlicedString into slices of the
4440 // underlying string buffer. 4402 // underlying string buffer.
4441 SlicedString* str = SlicedString::cast(this); 4403 SlicedString* str = SlicedString::cast(this);
4442 String* buf = str->buffer(); 4404 String* buf = str->buffer();
4443 return Heap::AllocateSlicedString(buf, 4405 return Heap::AllocateSlicedString(buf,
4444 str->start() + start, 4406 str->start() + start,
4445 str->start() + end); 4407 str->start() + end);
4446 } 4408 }
4447 Object* result = Heap::AllocateSlicedString(this, start, end); 4409 Object* result = Heap::AllocateSlicedString(this, start, end);
4448 if (result->IsFailure()) { 4410 if (result->IsFailure()) {
4449 return result; 4411 return result;
4450 } 4412 }
4451 // Due to the way we retry after GC on allocation failure we are not allowed 4413 // Due to the way we retry after GC on allocation failure we are not allowed
4452 // to fail on allocation after this point. This is the one-allocation rule. 4414 // to fail on allocation after this point. This is the one-allocation rule.
4453 4415
4454 // Try to flatten a cons string that is under the sliced string. 4416 // Try to flatten a cons string that is under the sliced string.
4455 // This is to avoid memory leaks and possible stack overflows caused by 4417 // This is to avoid memory leaks and possible stack overflows caused by
4456 // building 'towers' of sliced strings on cons strings. 4418 // building 'towers' of sliced strings on cons strings.
4457 // This may fail due to an allocation failure (when a GC is needed), but it 4419 // This may fail due to an allocation failure (when a GC is needed), but it
4458 // will succeed often enough to avoid the problem. We only have to do this 4420 // will succeed often enough to avoid the problem. We only have to do this
4459 // if Heap::AllocateSlicedString actually returned a SlicedString. It will 4421 // if Heap::AllocateSlicedString actually returned a SlicedString. It will
4460 // return flat strings for small slices for efficiency reasons. 4422 // return flat strings for small slices for efficiency reasons.
4461 String* answer = String::cast(result); 4423 String* answer = String::cast(result);
4462 StringShape answer_shape(answer); 4424 if (StringShape(answer).IsSliced() &&
4463 if (answer_shape.IsSliced() && 4425 StringShape(this).representation_tag() == kConsStringTag) {
4464 shape.representation_tag() == kConsStringTag) { 4426 TryFlatten();
4465 TryFlatten(shape);
4466 // If the flatten succeeded we might as well make the sliced string point 4427 // If the flatten succeeded we might as well make the sliced string point
4467 // to the flat string rather than the cons string. 4428 // to the flat string rather than the cons string.
4468 String* second = ConsString::cast(this)->second(); 4429 String* second = ConsString::cast(this)->second();
4469 if (second->length(StringShape(second)) == 0) { 4430 if (second->length() == 0) {
4470 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first()); 4431 SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
4471 } 4432 }
4472 } 4433 }
4473 return answer; 4434 return answer;
4474 } 4435 }
4475 4436
4476 4437
4477 void String::PrintOn(FILE* file) { 4438 void String::PrintOn(FILE* file) {
4478 StringShape shape(this); 4439 int length = this->length();
4479 int length = this->length(shape);
4480 for (int i = 0; i < length; i++) { 4440 for (int i = 0; i < length; i++) {
4481 fprintf(file, "%c", Get(shape, i)); 4441 fprintf(file, "%c", Get(i));
4482 } 4442 }
4483 } 4443 }
4484 4444
4485 4445
4486 void Map::CreateBackPointers() { 4446 void Map::CreateBackPointers() {
4487 DescriptorArray* descriptors = instance_descriptors(); 4447 DescriptorArray* descriptors = instance_descriptors();
4488 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) { 4448 for (DescriptorReader r(descriptors); !r.eos(); r.advance()) {
4489 if (r.type() == MAP_TRANSITION) { 4449 if (r.type() == MAP_TRANSITION) {
4490 // Get target. 4450 // Get target.
4491 Map* target = Map::cast(r.GetValue()); 4451 Map* target = Map::cast(r.GetValue());
(...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
6027 if (storage) { 5987 if (storage) {
6028 element_dictionary()->CopyKeysTo(storage, filter); 5988 element_dictionary()->CopyKeysTo(storage, filter);
6029 } 5989 }
6030 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 5990 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
6031 } 5991 }
6032 5992
6033 if (this->IsJSValue()) { 5993 if (this->IsJSValue()) {
6034 Object* val = JSValue::cast(this)->value(); 5994 Object* val = JSValue::cast(this)->value();
6035 if (val->IsString()) { 5995 if (val->IsString()) {
6036 String* str = String::cast(val); 5996 String* str = String::cast(val);
6037 StringShape shape(str);
6038 if (storage) { 5997 if (storage) {
6039 for (int i = 0; i < str->length(shape); i++) { 5998 for (int i = 0; i < str->length(); i++) {
6040 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); 5999 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
6041 } 6000 }
6042 } 6001 }
6043 counter += str->length(shape); 6002 counter += str->length();
6044 } 6003 }
6045 } 6004 }
6046 ASSERT(!storage || storage->length() == counter); 6005 ASSERT(!storage || storage->length() == counter);
6047 return counter; 6006 return counter;
6048 } 6007 }
6049 6008
6050 6009
6051 int JSObject::GetEnumElementKeys(FixedArray* storage) { 6010 int JSObject::GetEnumElementKeys(FixedArray* storage) {
6052 return GetLocalElementKeys(storage, 6011 return GetLocalElementKeys(storage,
6053 static_cast<PropertyAttributes>(DONT_ENUM)); 6012 static_cast<PropertyAttributes>(DONT_ENUM));
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
6281 6240
6282 bool IsMatch(Object* string) { 6241 bool IsMatch(Object* string) {
6283 return String::cast(string)->Equals(string_); 6242 return String::cast(string)->Equals(string_);
6284 } 6243 }
6285 6244
6286 uint32_t Hash() { return string_->Hash(); } 6245 uint32_t Hash() { return string_->Hash(); }
6287 6246
6288 Object* GetObject() { 6247 Object* GetObject() {
6289 // If the string is a cons string, attempt to flatten it so that 6248 // If the string is a cons string, attempt to flatten it so that
6290 // symbols will most often be flat strings. 6249 // symbols will most often be flat strings.
6291 StringShape shape(string_); 6250 if (StringShape(string_).IsCons()) {
6292 if (shape.IsCons()) {
6293 ConsString* cons_string = ConsString::cast(string_); 6251 ConsString* cons_string = ConsString::cast(string_);
6294 cons_string->TryFlatten(shape); 6252 cons_string->TryFlatten();
6295 if (cons_string->second() == Heap::empty_string()) { 6253 if (cons_string->second() == Heap::empty_string()) {
6296 string_ = cons_string->first(); 6254 string_ = cons_string->first();
6297 } 6255 }
6298 } 6256 }
6299 // Transform string to symbol if possible. 6257 // Transform string to symbol if possible.
6300 Map* map = Heap::SymbolMapForString(string_); 6258 Map* map = Heap::SymbolMapForString(string_);
6301 if (map != NULL) { 6259 if (map != NULL) {
6302 string_->set_map(map); 6260 string_->set_map(map);
6303 return string_; 6261 return string_;
6304 } 6262 }
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
7405 // No break point. 7363 // No break point.
7406 if (break_point_objects()->IsUndefined()) return 0; 7364 if (break_point_objects()->IsUndefined()) return 0;
7407 // Single beak point. 7365 // Single beak point.
7408 if (!break_point_objects()->IsFixedArray()) return 1; 7366 if (!break_point_objects()->IsFixedArray()) return 1;
7409 // Multiple break points. 7367 // Multiple break points.
7410 return FixedArray::cast(break_point_objects())->length(); 7368 return FixedArray::cast(break_point_objects())->length();
7411 } 7369 }
7412 7370
7413 7371
7414 } } // namespace v8::internal 7372 } } // 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