| Index: src/objects-inl.h
|
| diff --git a/src/objects-inl.h b/src/objects-inl.h
|
| index 53a3183694cbfdfc87f16524888036e27d434d14..a9caf4ebac1819a0e75abde2ee6c79811737e3fb 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();
|
| }
|
|
|
|
|
| @@ -280,6 +284,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 +2055,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 +2142,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 +2150,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 +2169,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 +2192,18 @@ 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() == GetHeap()->empty_string();
|
| +}
|
| +
|
| +
|
| +String* String::GetIndirect() {
|
| + STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
|
| + // Giving direct access to underlying string only makes sense if the
|
| + // wrapping string is already flattened.
|
| + ASSERT(this->IsFlat());
|
| + ASSERT(StringShape(this).IsIndirect());
|
| + return String::cast(reinterpret_cast<ConsString*>(this)->first());
|
| }
|
|
|
|
|
| @@ -2243,6 +2262,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));
|
| }
|
|
|