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

Unified Diff: src/objects.cc

Issue 9038: Create an abstraction for the string type flags so that they can be cached.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/objects.cc
===================================================================
--- src/objects.cc (revision 654)
+++ src/objects.cc (working copy)
@@ -475,25 +475,26 @@
// We don't use the BBC's overcorrect "an historic occasion" though if
// you speak a dialect you may well say "an 'istoric occasion".
static bool AnWord(String* str) {
- if (str->length() == 0) return false; // a nothing
- int c0 = str->Get(0);
- int c1 = str->length() > 1 ? str->Get(1) : 0;
+ StringShape shape(str);
+ if (str->length(shape) == 0) return false; // A nothing.
+ int c0 = str->Get(shape, 0);
+ int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0;
if (c0 == 'U') {
if (c1 > 'Z') {
- return true; // an Umpire, but a UTF8String, a U
+ return true; // An Umpire, but a UTF8String, a U.
}
} else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
- return true; // an Ape, an ABCBook
+ return true; // An Ape, an ABCBook.
} else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
(c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
c0 == 'S' || c0 == 'X')) {
- return true; // an MP3File, an M
+ return true; // An MP3File, an M.
}
return false;
}
-Object* String::Flatten() {
+Object* String::Flatten(StringShape shape) {
#ifdef DEBUG
// Do not attempt to flatten in debug mode when allocation is not
// allowed. This is to avoid an assertion failure when allocating.
@@ -502,44 +503,48 @@
if (!Heap::IsAllocationAllowed()) return this;
#endif
- switch (representation_tag()) {
+ switch (shape.representation_tag()) {
case kSlicedStringTag: {
SlicedString* ss = SlicedString::cast(this);
// The SlicedString constructor should ensure that there are no
// SlicedStrings that are constructed directly on top of other
// SlicedStrings.
- ASSERT(!ss->buffer()->IsSlicedString());
- Object* ok = String::cast(ss->buffer())->Flatten();
+ String* buf = ss->buffer();
+ ASSERT(!buf->IsSlicedString());
+ Object* ok = buf->Flatten(StringShape(buf));
if (ok->IsFailure()) return ok;
// Under certain circumstances (TryFlatten fails in String::Slice)
// we can have a cons string under a slice. In this case we need
// to get the flat string out of the cons!
- if (String::cast(ok)->StringIsConsString()) {
+ if (StringShape(String::cast(ok)).IsCons()) {
ss->set_buffer(ConsString::cast(ok)->first());
}
return this;
}
case kConsStringTag: {
ConsString* cs = ConsString::cast(this);
- if (String::cast(cs->second())->length() == 0) {
+ if (cs->second()->length() == 0) {
return this;
}
// There's little point in putting the flat string in new space if the
// cons string is in old space. It can never get GCed until there is
// an old space GC.
PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
- int len = length();
+ int len = length(shape);
Object* object;
String* result;
- if (IsAsciiRepresentation()) {
+ if (shape.IsAsciiRepresentation()) {
object = Heap::AllocateRawAsciiString(len, tenure);
if (object->IsFailure()) return object;
result = String::cast(object);
- String* first = String::cast(cs->first());
- int first_length = first->length();
+ String* first = cs->first();
+ StringShape first_shape(first);
+ int first_length = first->length(first_shape);
char* dest = SeqAsciiString::cast(result)->GetChars();
- WriteToFlat(first, dest, 0, first_length);
- WriteToFlat(String::cast(cs->second()),
+ WriteToFlat(first, first_shape, dest, 0, first_length);
+ String* second = cs->second();
+ WriteToFlat(second,
+ StringShape(second),
dest + first_length,
0,
len - first_length);
@@ -548,10 +553,13 @@
if (object->IsFailure()) return object;
result = String::cast(object);
uc16* dest = SeqTwoByteString::cast(result)->GetChars();
- String* first = String::cast(cs->first());
- int first_length = first->length();
- WriteToFlat(first, dest, 0, first_length);
- WriteToFlat(String::cast(cs->second()),
+ String* first = cs->first();
+ StringShape first_shape(first);
+ int first_length = first->length(first_shape);
+ WriteToFlat(first, first_shape, dest, 0, first_length);
+ String* second = cs->second();
+ WriteToFlat(second,
+ StringShape(second),
dest + first_length,
0,
len - first_length);
@@ -567,7 +575,8 @@
void String::StringShortPrint(StringStream* accumulator) {
- int len = length();
+ StringShape shape(this);
+ int len = length(shape);
if (len > kMaxMediumStringSize) {
accumulator->Add("<Very long string[%u]>", len);
return;
@@ -595,7 +604,7 @@
}
buf.Reset(this);
if (ascii) {
- accumulator->Add("<String[%u]: ", length());
+ accumulator->Add("<String[%u]: ", length(shape));
for (int i = 0; i < len; i++) {
accumulator->Put(buf.GetNext());
}
@@ -603,7 +612,7 @@
} else {
// Backslash indicates that the string contains control
// characters and that backslashes are therefore escaped.
- accumulator->Add("<String[%u]\\: ", length());
+ accumulator->Add("<String[%u]\\: ", length(shape));
for (int i = 0; i < len; i++) {
int c = buf.GetNext();
if (c == '\n') {
@@ -781,13 +790,13 @@
InstanceType instance_type = map->instance_type();
if (instance_type < FIRST_NONSTRING_TYPE
- && (reinterpret_cast<String*>(this)->map_representation_tag(map)
- == kSeqStringTag)) {
- if (reinterpret_cast<String*>(this)->is_ascii_representation_map(map)) {
- return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(map);
+ && (StringShape(instance_type).IsSequential())) {
+ StringShape shape(instance_type);
+ if (shape.IsAsciiRepresentation()) {
+ return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(shape);
} else {
SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
- return self->SeqTwoByteStringSize(map);
+ return self->SeqTwoByteStringSize(shape);
}
}
@@ -2279,7 +2288,7 @@
}
// TryFlatten before operating on the string.
- name->TryFlatten();
+ name->TryFlatten(StringShape(name));
// Make sure name is not an index.
uint32_t index;
@@ -2902,27 +2911,21 @@
bool String::LooksValid() {
- if (!Heap::Contains(this))
- return false;
- switch (representation_tag()) {
- case kSeqStringTag:
- case kConsStringTag:
- case kSlicedStringTag:
- case kExternalStringTag:
- return true;
- default:
- return false;
- }
+ if (!Heap::Contains(this)) return false;
+ return true;
Mads Ager (chromium) 2008/11/03 08:45:49 Doesn't it make sense to check that the representa
Erik Corry 2008/11/03 09:33:54 It makes no sense because all bit combinations are
}
int String::Utf8Length() {
- if (is_ascii_representation()) return length();
+ StringShape shape(this);
+ if (shape.IsAsciiRepresentation()) return length(shape);
// Attempt to flatten before accessing the string. It probably
// doesn't make Utf8Length faster, but it is very likely that
// the string will be accessed later (for example by WriteUtf8)
// so it's still a good idea.
- TryFlatten();
+ if (!IsFlat(shape)) {
+ TryFlatten(shape); // shape is now no longer valid.
+ }
Access<StringInputBuffer> buffer(&string_input_buffer);
buffer->Reset(0, this);
int result = 0;
@@ -2933,23 +2936,26 @@
Vector<const char> String::ToAsciiVector() {
- ASSERT(IsAsciiRepresentation());
- ASSERT(IsFlat());
+ StringShape shape(this);
+ ASSERT(shape.IsAsciiRepresentation());
+ ASSERT(IsFlat(shape));
int offset = 0;
- int length = this->length();
- StringRepresentationTag string_tag = representation_tag();
+ int length = this->length(shape);
+ StringRepresentationTag string_tag = shape.representation_tag();
String* string = this;
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
- string = String::cast(sliced->buffer());
- string_tag = string->representation_tag();
+ string = sliced->buffer();
+ shape = StringShape(string);
+ string_tag = shape.representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
- ASSERT(String::cast(cons->second())->length() == 0);
- string = String::cast(cons->first());
- string_tag = string->representation_tag();
+ ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+ string = cons->first();
+ shape = StringShape(string);
+ string_tag = shape.representation_tag();
}
if (string_tag == kSeqStringTag) {
SeqAsciiString* seq = SeqAsciiString::cast(string);
@@ -2964,23 +2970,26 @@
Vector<const uc16> String::ToUC16Vector() {
- ASSERT(IsTwoByteStringRepresentation());
- ASSERT(IsFlat());
+ StringShape shape(this);
+ ASSERT(shape.IsTwoByteRepresentation());
+ ASSERT(IsFlat(shape));
int offset = 0;
- int length = this->length();
- StringRepresentationTag string_tag = representation_tag();
+ int length = this->length(shape);
+ StringRepresentationTag string_tag = shape.representation_tag();
String* string = this;
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
string = String::cast(sliced->buffer());
- string_tag = string->representation_tag();
+ shape = StringShape(string);
+ string_tag = shape.representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
- ASSERT(String::cast(cons->second())->length() == 0);
- string = String::cast(cons->first());
- string_tag = string->representation_tag();
+ ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+ string = cons->first();
+ shape = StringShape(string);
+ string_tag = shape.representation_tag();
}
if (string_tag == kSeqStringTag) {
SeqTwoByteString* seq = SeqTwoByteString::cast(string);
@@ -3060,8 +3069,9 @@
const uc16* String::GetTwoByteData(unsigned start) {
- ASSERT(!IsAsciiRepresentation());
- switch (representation_tag()) {
+ StringShape shape(this);
+ ASSERT(!shape.IsAsciiRepresentation());
+ switch (shape.representation_tag()) {
case kSeqStringTag:
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
case kExternalStringTag:
@@ -3069,12 +3079,12 @@
ExternalTwoByteStringGetData(start);
case kSlicedStringTag: {
SlicedString* sliced_string = SlicedString::cast(this);
- String* buffer = String::cast(sliced_string->buffer());
- if (buffer->StringIsConsString()) {
- ConsString* cons_string = ConsString::cast(buffer);
+ String* buffer = sliced_string->buffer();
+ if (StringShape(buffer).IsCons()) {
+ ConsString* cs = ConsString::cast(buffer);
// Flattened string.
- ASSERT(String::cast(cons_string->second())->length() == 0);
- buffer = String::cast(cons_string->first());
+ ASSERT(cs->second()->length(StringShape(cs->second())) == 0);
+ buffer = cs->first();
}
return buffer->GetTwoByteData(start + sliced_string->start());
}
@@ -3175,8 +3185,9 @@
int offset_correction = 0;
while (true) {
- String* left = String::cast(current->first());
- unsigned left_length = (unsigned)left->length();
+ String* left = current->first();
+ StringShape left_shape(left);
+ unsigned left_length = (unsigned)left->length(left_shape);
if (left_length > offset &&
(max_chars <= left_length - offset ||
(rbb->capacity <= left_length - offset &&
@@ -3188,7 +3199,7 @@
// the point where we switch to the -IntoBuffer routines (below) in order
// to maximize the chances of delegating a big chunk of work to the
// efficient *AsciiStringReadBlock routines.
- if (left->StringIsConsString()) {
+ if (left_shape.IsCons()) {
current = ConsString::cast(left);
continue;
} else {
@@ -3200,10 +3211,10 @@
} else if (left_length <= offset) {
// Right hand side only - iterate unless we have reached the bottom of
// the cons tree.
- String* right = String::cast(current->second());
+ String* right = current->second();
offset -= left_length;
offset_correction += left_length;
- if (right->StringIsConsString()) {
+ if (StringShape(right).IsCons()) {
current = ConsString::cast(right);
continue;
} else {
@@ -3235,7 +3246,7 @@
const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
- String* backing = String::cast(buffer());
+ String* backing = buffer();
unsigned offset = start() + *offset_ptr;
unsigned length = backing->length();
if (max_chars > length - offset) {
@@ -3353,9 +3364,10 @@
rbb->remaining = 0;
return NULL;
}
- switch (input->representation_tag()) {
+ StringShape shape(input);
+ switch (shape.representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii_representation()) {
+ if (shape.IsAsciiRepresentation()) {
SeqAsciiString* str = SeqAsciiString::cast(input);
return str->SeqAsciiStringReadBlock(&rbb->remaining,
offset_ptr,
@@ -3376,7 +3388,7 @@
offset_ptr,
max_chars);
case kExternalStringTag:
- if (input->is_ascii_representation()) {
+ if (shape.IsAsciiRepresentation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
@@ -3415,12 +3427,13 @@
ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
- ASSERT(*offset_ptr <= (unsigned)input->length());
+ StringShape shape(input);
+ ASSERT(*offset_ptr <= (unsigned)input->length(shape));
if (max_chars == 0) return;
- switch (input->representation_tag()) {
+ switch (shape.representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii_representation()) {
+ if (shape.IsAsciiRepresentation()) {
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
@@ -3442,7 +3455,7 @@
max_chars);
return;
case kExternalStringTag:
- if (input->is_ascii_representation()) {
+ if (shape.IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
@@ -3466,11 +3479,12 @@
unsigned capacity,
unsigned* remaining,
unsigned* offset_ptr) {
- ASSERT(*offset_ptr <= (unsigned)input->length());
- unsigned chars = input->length() - *offset_ptr;
+ StringShape shape(input);
+ ASSERT(*offset_ptr <= (unsigned)input->length(shape));
+ unsigned chars = input->length(shape) - *offset_ptr;
ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
- ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
+ ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
*remaining = rbb.remaining;
return answer;
}
@@ -3481,13 +3495,14 @@
unsigned capacity,
unsigned* remaining,
unsigned* offset_ptr) {
+ StringShape shape(*raw_input);
Handle<String> input(raw_input);
- ASSERT(*offset_ptr <= (unsigned)input->length());
- unsigned chars = input->length() - *offset_ptr;
+ ASSERT(*offset_ptr <= (unsigned)input->length(shape));
+ unsigned chars = input->length(shape) - *offset_ptr;
if (chars > capacity) chars = capacity;
ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
- ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
+ ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
*remaining = rbb.remaining;
return rbb.util_buffer;
}
@@ -3506,13 +3521,14 @@
int offset_correction = 0;
while (true) {
- String* left = String::cast(current->first());
- unsigned left_length = (unsigned)left->length();
+ String* left = current->first();
+ StringShape left_shape(left);
+ unsigned left_length = (unsigned)left->length(left_shape);
if (left_length > offset &&
max_chars <= left_length - offset) {
// Left hand side only - iterate unless we have reached the bottom of
// the cons tree.
- if (left->StringIsConsString()) {
+ if (left_shape.IsCons()) {
current = ConsString::cast(left);
continue;
} else {
@@ -3525,8 +3541,8 @@
// the cons tree.
offset -= left_length;
offset_correction += left_length;
- String* right = String::cast(current->second());
- if (right->StringIsConsString()) {
+ String* right = current->second();
+ if (StringShape(right).IsCons()) {
current = ConsString::cast(right);
continue;
} else {
@@ -3558,7 +3574,7 @@
void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
- String* backing = String::cast(buffer());
+ String* backing = buffer();
unsigned offset = start() + *offset_ptr;
unsigned length = backing->length();
if (max_chars > length - offset) {
@@ -3578,24 +3594,29 @@
ASSERT(index >= 0 && index < this->length());
// Check for a flattened cons string
- if (String::cast(second())->length() == 0) {
- return String::cast(first())->Get(index);
+ if (second()->length() == 0) {
+ String* left = first();
+ return left->Get(StringShape(left), index);
}
String* string = String::cast(this);
+ StringShape shape(string);
while (true) {
- if (string->StringIsConsString()) {
+ if (shape.IsCons()) {
ConsString* cons_string = ConsString::cast(string);
- String* left = String::cast(cons_string->first());
- if (left->length() > index) {
+ String* left = cons_string->first();
+ StringShape left_shape(left);
+ if (left->length(left_shape) > index) {
string = left;
+ shape = left_shape;
} else {
- index -= left->length();
- string = String::cast(cons_string->second());
+ index -= left->length(left_shape);
+ string = cons_string->second();
+ shape = StringShape(string);
}
} else {
- return string->Get(index);
+ return string->Get(shape, index);
}
}
@@ -3609,9 +3630,10 @@
// SlicedStrings that are constructed directly on top of other
// SlicedStrings.
String* buf = String::cast(buffer());
- ASSERT(!buf->StringIsSlicedString());
- if (buf->StringIsConsString()) {
- Object* ok = buf->Flatten();
+ StringShape buf_shape(buf);
+ ASSERT(!buf_shape.IsSliced());
+ if (buf_shape.IsCons()) {
+ Object* ok = buf->Flatten(buf_shape);
if (ok->IsFailure()) return ok;
}
return this;
@@ -3620,15 +3642,17 @@
template <typename sinkchar>
void String::WriteToFlat(String* src,
+ StringShape src_shape,
sinkchar* sink,
int f,
int t) {
String* source = src;
+ StringShape shape = src_shape;
int from = f;
int to = t;
while (true) {
- ASSERT(0 <= from && from <= to && to <= source->length());
- switch (source->full_representation_tag()) {
+ ASSERT(0 <= from && from <= to && to <= source->length(shape));
+ switch (shape.full_representation_tag()) {
case kAsciiStringTag | kExternalStringTag: {
CopyChars(sink,
ExternalAsciiString::cast(source)->resource()->data() + from,
@@ -3662,35 +3686,40 @@
from += start;
to += start;
source = String::cast(sliced_string->buffer());
+ shape = StringShape(source);
break;
}
case kAsciiStringTag | kConsStringTag:
case kTwoByteStringTag | kConsStringTag: {
ConsString* cons_string = ConsString::cast(source);
- String* first = String::cast(cons_string->first());
- int boundary = first->length();
+ String* first = cons_string->first();
+ StringShape first_shape(first);
+ int boundary = first->length(first_shape);
if (to - boundary >= boundary - from) {
// Right hand side is longer. Recurse over left.
if (from < boundary) {
- WriteToFlat(first, sink, from, boundary);
+ WriteToFlat(first, first_shape, sink, from, boundary);
sink += boundary - from;
from = 0;
} else {
from -= boundary;
}
to -= boundary;
- source = String::cast(cons_string->second());
+ source = cons_string->second();
+ shape = StringShape(source);
} else {
// Left hand side is longer. Recurse over right.
if (to > boundary) {
- String* second = String::cast(cons_string->second());
+ String* second = cons_string->second();
WriteToFlat(second,
+ StringShape(second),
sink + boundary - from,
0,
to - boundary);
to = boundary;
}
source = first;
+ shape = first_shape;
}
break;
}
@@ -3707,7 +3736,8 @@
uint16_t SlicedString::SlicedStringGet(int index) {
ASSERT(index >= 0 && index < this->length());
// Delegate to the buffer string.
- return String::cast(buffer())->Get(start() + index);
+ String* underlying = buffer();
+ return underlying->Get(StringShape(underlying), start() + index);
}
@@ -3771,8 +3801,9 @@
template <typename IteratorA>
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
- if (b->IsFlat()) {
- if (b->IsAsciiRepresentation()) {
+ StringShape b_shape(b);
+ if (b->IsFlat(b_shape)) {
+ if (b_shape.IsAsciiRepresentation()) {
VectorIterator<char> ib(b->ToAsciiVector());
return CompareStringContents(ia, &ib);
} else {
@@ -3789,10 +3820,12 @@
static StringInputBuffer string_compare_buffer_a;
-bool String::SlowEquals(String* other) {
+bool String::SlowEquals(StringShape this_shape,
+ String* other,
+ StringShape other_shape) {
// Fast check: negative check with lengths.
- int len = length();
- if (len != other->length()) return false;
+ int len = length(this_shape);
+ if (len != other->length(other_shape)) return false;
if (len == 0) return true;
// Fast check: if hash code is computed for both strings
@@ -3801,18 +3834,18 @@
if (Hash() != other->Hash()) return false;
}
- if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) {
+ if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) {
const char* str1 = SeqAsciiString::cast(this)->GetChars();
const char* str2 = SeqAsciiString::cast(other)->GetChars();
return CompareRawStringContents(Vector<const char>(str1, len),
Vector<const char>(str2, len));
}
- if (this->IsFlat()) {
- if (this->IsAsciiRepresentation()) {
+ if (this->IsFlat(this_shape)) {
+ if (this_shape.IsAsciiRepresentation()) {
Vector<const char> vec1 = this->ToAsciiVector();
- if (other->IsFlat()) {
- if (other->IsAsciiRepresentation()) {
+ if (other->IsFlat(other_shape)) {
+ if (other_shape.IsAsciiRepresentation()) {
Vector<const char> vec2 = other->ToAsciiVector();
return CompareRawStringContents(vec1, vec2);
} else {
@@ -3827,8 +3860,8 @@
}
} else {
Vector<const uc16> vec1 = this->ToUC16Vector();
- if (other->IsFlat()) {
- if (other->IsAsciiRepresentation()) {
+ if (other->IsFlat(other_shape)) {
+ if (other_shape.IsAsciiRepresentation()) {
VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(other->ToAsciiVector());
return CompareStringContents(&buf1, &ib);
@@ -3850,7 +3883,8 @@
bool String::MarkAsUndetectable() {
- if (this->IsSymbol()) return false;
+ StringShape shape(this);
+ if (shape.IsSymbol()) return false;
Map* map = this->map();
if (map == Heap::short_string_map()) {
@@ -3878,13 +3912,14 @@
bool String::IsEqualTo(Vector<const char> str) {
- int slen = length();
+ StringShape this_shape(this);
+ int slen = length(this_shape);
Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
decoder->Reset(str.start(), str.length());
int i;
for (i = 0; i < slen && decoder->has_more(); i++) {
uc32 r = decoder->GetNext();
- if (Get(i) != r) return false;
+ if (Get(this_shape, i) != r) return false;
}
return i == slen && !decoder->has_more();
}
@@ -3938,7 +3973,8 @@
bool String::SlowAsArrayIndex(uint32_t* index) {
- if (length() <= kMaxCachedArrayIndexLength) {
+ StringShape shape(this);
+ if (length(shape) <= kMaxCachedArrayIndexLength) {
Hash(); // force computation of hash code
uint32_t field = length_field();
if ((field & kIsArrayIndexMask) == 0) return false;
@@ -3946,7 +3982,7 @@
return true;
} else {
StringInputBuffer buffer(this);
- return ComputeArrayIndex(&buffer, index, length());
+ return ComputeArrayIndex(&buffer, index, length(shape));
}
}
@@ -4006,20 +4042,21 @@
}
-Object* String::Slice(int start, int end) {
- if (start == 0 && end == length()) return this;
- int representation = representation_tag();
- if (representation == kSlicedStringTag) {
+Object* String::Slice(StringShape shape, int start, int end) {
+ if (start == 0 && end == length(shape)) return this;
+ if (shape.representation_tag() == kSlicedStringTag) {
// Translate slices of a SlicedString into slices of the
// underlying string buffer.
SlicedString* str = SlicedString::cast(this);
- return Heap::AllocateSlicedString(String::cast(str->buffer()),
+ String* buf = str->buffer();
+ return Heap::AllocateSlicedString(buf,
+ StringShape(buf),
str->start() + start,
str->start() + end);
}
- Object* answer = Heap::AllocateSlicedString(this, start, end);
- if (answer->IsFailure()) {
- return answer;
+ Object* result = Heap::AllocateSlicedString(this, shape, start, end);
+ if (result->IsFailure()) {
+ return result;
}
// Due to the way we retry after GC on allocation failure we are not allowed
// to fail on allocation after this point. This is the one-allocation rule.
@@ -4031,12 +4068,15 @@
// will succeed often enough to avoid the problem. We only have to do this
// if Heap::AllocateSlicedString actually returned a SlicedString. It will
// return flat strings for small slices for efficiency reasons.
- if (String::cast(answer)->StringIsSlicedString() &&
- representation == kConsStringTag) {
- TryFlatten();
+ String* answer = String::cast(result);
+ StringShape answer_shape(answer);
+ if (answer_shape.IsSliced() &&
+ shape.representation_tag() == kConsStringTag) {
+ TryFlatten(shape);
// If the flatten succeeded we might as well make the sliced string point
// to the flat string rather than the cons string.
- if (String::cast(ConsString::cast(this)->second())->length() == 0) {
+ String* second = ConsString::cast(this)->second();
+ if (second->length(StringShape(second)) == 0) {
SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
}
}
@@ -4045,9 +4085,10 @@
void String::PrintOn(FILE* file) {
- int length = this->length();
+ StringShape shape(this);
+ int length = this->length(shape);
for (int i = 0; i < length; i++) {
- fprintf(file, "%c", Get(i));
+ fprintf(file, "%c", Get(shape, i));
}
}
@@ -5532,12 +5573,13 @@
Object* val = JSValue::cast(this)->value();
if (val->IsString()) {
String* str = String::cast(val);
+ StringShape shape(str);
if (storage) {
- for (int i = 0; i < str->length(); i++) {
+ for (int i = 0; i < str->length(shape); i++) {
storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
}
}
- counter += str->length();
+ counter += str->length(shape);
}
}
ASSERT(!storage || storage->length() == counter);
@@ -5722,11 +5764,12 @@
Object* GetObject() {
// If the string is a cons string, attempt to flatten it so that
// symbols will most often be flat strings.
- if (string_->IsConsString()) {
+ StringShape shape(string_);
+ if (shape.IsCons()) {
ConsString* cons_string = ConsString::cast(string_);
- cons_string->TryFlatten();
+ cons_string->TryFlatten(shape);
if (cons_string->second() == Heap::empty_string()) {
- string_ = String::cast(cons_string->first());
+ string_ = cons_string->first();
}
}
// Transform string to symbol if possible.
@@ -5884,7 +5927,7 @@
return false;
} else {
String* result = String::cast(KeyAt(entry));
- ASSERT(result->is_symbol());
+ ASSERT(StringShape(result).IsSymbol());
*symbol = result;
return true;
}

Powered by Google App Engine
This is Rietveld 408576698