Chromium Code Reviews| Index: src/objects-inl.h |
| diff --git a/src/objects-inl.h b/src/objects-inl.h |
| index 53a3183694cbfdfc87f16524888036e27d434d14..68ff51f51a256bea7f9010f20731aafc52ee1ddf 100644 |
| --- a/src/objects-inl.h |
| +++ b/src/objects-inl.h |
| @@ -177,10 +177,14 @@ bool Object::IsSymbol() { |
| bool Object::IsConsString() { |
| - if (!this->IsHeapObject()) return false; |
| - uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
| - return (type & (kIsNotStringMask | kStringRepresentationMask)) == |
| - (kStringTag | kConsStringTag); |
| + if (!IsString()) return false; |
| + return StringShape(String::cast(this)).IsCons(); |
| +} |
| + |
| + |
| +bool Object::IsSlicedString() { |
| + if (!IsString()) return false; |
| + return StringShape(String::cast(this)).IsSliced(); |
| } |
| @@ -268,6 +272,38 @@ bool String::IsTwoByteRepresentation() { |
| } |
| +bool String::IsAsciiRepresentationUnderneath() { |
| + uint32_t type = map()->instance_type(); |
| + STATIC_ASSERT(kIsIndirectStringTag != 0); |
| + STATIC_ASSERT(kIsIndirectStringMask != kStringEncodingMask); |
|
Vitaly Repeshko
2011/08/19 16:27:40
Maybe (kIsIndirectStringMask & kStringEncodingMask
|
| + ASSERT(IsFlat()); |
| + switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { |
| + case kAsciiStringTag: |
| + return true; |
| + case kTwoByteStringTag: |
| + return false; |
| + default: // Cons or sliced string. Need to go deeper. |
| + return GetUnderlying()->IsAsciiRepresentation(); |
| + } |
| +} |
| + |
| + |
| +bool String::IsTwoByteRepresentationUnderneath() { |
| + uint32_t type = map()->instance_type(); |
| + STATIC_ASSERT(kIsIndirectStringTag != 0); |
| + STATIC_ASSERT(kIsIndirectStringMask != kStringEncodingMask); |
|
Vitaly Repeshko
2011/08/19 16:27:40
Ditto.
|
| + ASSERT(IsFlat()); |
| + switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { |
| + case kAsciiStringTag: |
| + return false; |
| + case kTwoByteStringTag: |
| + return true; |
| + default: // Cons or sliced string. Need to go deeper. |
| + return GetUnderlying()->IsTwoByteRepresentation(); |
| + } |
| +} |
| + |
| + |
| bool String::HasOnlyAsciiChars() { |
| uint32_t type = map()->instance_type(); |
| return (type & kStringEncodingMask) == kAsciiStringTag || |
| @@ -280,6 +316,16 @@ bool StringShape::IsCons() { |
| } |
| +bool StringShape::IsSliced() { |
| + return (type_ & kStringRepresentationMask) == kSlicedStringTag; |
| +} |
| + |
| + |
| +bool StringShape::IsIndirect() { |
| + return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; |
| +} |
| + |
| + |
| bool StringShape::IsExternal() { |
| return (type_ & kStringRepresentationMask) == kExternalStringTag; |
| } |
| @@ -2041,6 +2087,7 @@ CAST_ACCESSOR(String) |
| CAST_ACCESSOR(SeqString) |
| CAST_ACCESSOR(SeqAsciiString) |
| CAST_ACCESSOR(SeqTwoByteString) |
| +CAST_ACCESSOR(SlicedString) |
| CAST_ACCESSOR(ConsString) |
| CAST_ACCESSOR(ExternalString) |
| CAST_ACCESSOR(ExternalAsciiString) |
| @@ -2127,7 +2174,7 @@ bool String::Equals(String* other) { |
| MaybeObject* String::TryFlatten(PretenureFlag pretenure) { |
| if (!StringShape(this).IsCons()) return this; |
| ConsString* cons = ConsString::cast(this); |
| - if (cons->second()->length() == 0) return cons->first(); |
| + if (cons->IsFlat()) return cons->first(); |
| return SlowTryFlatten(pretenure); |
| } |
| @@ -2135,10 +2182,8 @@ MaybeObject* String::TryFlatten(PretenureFlag pretenure) { |
| String* String::TryFlattenGetString(PretenureFlag pretenure) { |
| MaybeObject* flat = TryFlatten(pretenure); |
| Object* successfully_flattened; |
| - if (flat->ToObject(&successfully_flattened)) { |
| - return String::cast(successfully_flattened); |
| - } |
| - return this; |
| + if (!flat->ToObject(&successfully_flattened)) return this; |
| + return String::cast(successfully_flattened); |
| } |
| @@ -2156,6 +2201,9 @@ uint16_t String::Get(int index) { |
| return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); |
| case kExternalStringTag | kTwoByteStringTag: |
| return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); |
| + case kSlicedStringTag | kAsciiStringTag: |
| + case kSlicedStringTag | kTwoByteStringTag: |
| + return SlicedString::cast(this)->SlicedStringGet(index); |
| default: |
| break; |
| } |
| @@ -2176,15 +2224,19 @@ void String::Set(int index, uint16_t value) { |
| bool String::IsFlat() { |
| - switch (StringShape(this).representation_tag()) { |
| - case kConsStringTag: { |
| - String* second = ConsString::cast(this)->second(); |
| - // Only flattened strings have second part empty. |
| - return second->length() == 0; |
| - } |
| - default: |
| - return true; |
| - } |
| + if (!StringShape(this).IsCons()) return true; |
| + return ConsString::cast(this)->second()->length() == 0; |
| +} |
| + |
| + |
| +String* String::GetUnderlying() { |
| + // Giving direct access to underlying string only makes sense if the |
| + // wrapping string is already flattened. |
| + ASSERT(this->IsFlat()); |
| + ASSERT(StringShape(this).IsIndirect()); |
| + STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset); |
| + const int kUnderlyingOffset = SlicedString::kParentOffset; |
| + return String::cast(READ_FIELD(this, kUnderlyingOffset)); |
| } |
| @@ -2243,6 +2295,20 @@ int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { |
| } |
| +String* SlicedString::parent() { |
| + return String::cast(READ_FIELD(this, kParentOffset)); |
| +} |
| + |
| + |
| +void SlicedString::set_parent(String* parent) { |
| + ASSERT(parent->IsSeqString()); |
| + WRITE_FIELD(this, kParentOffset, parent); |
| +} |
| + |
| + |
| +SMI_ACCESSORS(SlicedString, offset, kOffsetOffset) |
| + |
| + |
| String* ConsString::first() { |
| return String::cast(READ_FIELD(this, kFirstOffset)); |
| } |