Index: src/objects-inl.h |
diff --git a/src/objects-inl.h b/src/objects-inl.h |
index 65f12cadfb318271696cc9c192ecfee5a0a0e7db..6a787fa42fe3eb61c6379c7bac9e780359d1121d 100644 |
--- a/src/objects-inl.h |
+++ b/src/objects-inl.h |
@@ -275,6 +275,11 @@ bool HeapObject::IsConsString() const { |
return StringShape(String::cast(this)).IsCons(); |
} |
+bool HeapObject::IsThinString() const { |
+ if (!IsString()) return false; |
+ return StringShape(String::cast(this)).IsThin(); |
+} |
+ |
bool HeapObject::IsSlicedString() const { |
if (!IsString()) return false; |
return StringShape(String::cast(this)).IsSliced(); |
@@ -698,6 +703,7 @@ CAST_ACCESSOR(StringTable) |
CAST_ACCESSOR(Struct) |
CAST_ACCESSOR(Symbol) |
CAST_ACCESSOR(TemplateInfo) |
+CAST_ACCESSOR(ThinString) |
CAST_ACCESSOR(Uint16x8) |
CAST_ACCESSOR(Uint32x4) |
CAST_ACCESSOR(Uint8x16) |
@@ -841,6 +847,10 @@ bool StringShape::IsCons() { |
return (type_ & kStringRepresentationMask) == kConsStringTag; |
} |
+bool StringShape::IsThin() { |
+ return (type_ & kStringRepresentationMask) == kThinStringTag; |
+} |
+ |
bool StringShape::IsSliced() { |
return (type_ & kStringRepresentationMask) == kSlicedStringTag; |
} |
@@ -3662,10 +3672,19 @@ bool String::Equals(Handle<String> one, Handle<String> two) { |
Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) { |
- if (!string->IsConsString()) return string; |
- Handle<ConsString> cons = Handle<ConsString>::cast(string); |
- if (cons->IsFlat()) return handle(cons->first()); |
- return SlowFlatten(cons, pretenure); |
+ if (string->IsConsString()) { |
+ Handle<ConsString> cons = Handle<ConsString>::cast(string); |
+ if (cons->IsFlat()) { |
+ string = handle(cons->first()); |
+ } else { |
+ return SlowFlatten(cons, pretenure); |
+ } |
+ } |
+ if (string->IsThinString()) { |
+ string = handle(Handle<ThinString>::cast(string)->actual()); |
+ DCHECK(!string->IsConsString()); |
+ } |
+ return string; |
} |
@@ -3686,6 +3705,9 @@ uint16_t String::Get(int index) { |
case kSlicedStringTag | kOneByteStringTag: |
case kSlicedStringTag | kTwoByteStringTag: |
return SlicedString::cast(this)->SlicedStringGet(index); |
+ case kThinStringTag | kOneByteStringTag: |
+ case kThinStringTag | kTwoByteStringTag: |
+ return ThinString::cast(this)->ThinStringGet(index); |
default: |
break; |
} |
@@ -3717,6 +3739,7 @@ String* String::GetUnderlying() { |
DCHECK(this->IsFlat()); |
DCHECK(StringShape(this).IsIndirect()); |
STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset); |
+ STATIC_ASSERT(ConsString::kFirstOffset == ThinString::kActualOffset); |
const int kUnderlyingOffset = SlicedString::kParentOffset; |
return String::cast(READ_FIELD(this, kUnderlyingOffset)); |
} |
@@ -3768,6 +3791,11 @@ ConsString* String::VisitFlat(Visitor* visitor, |
case kConsStringTag | kTwoByteStringTag: |
return ConsString::cast(string); |
+ case kThinStringTag | kOneByteStringTag: |
+ case kThinStringTag | kTwoByteStringTag: |
+ string = ThinString::cast(string)->actual(); |
+ continue; |
+ |
default: |
UNREACHABLE(); |
return NULL; |
@@ -3899,6 +3927,7 @@ void ConsString::set_second(String* value, WriteBarrierMode mode) { |
CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode); |
} |
+ACCESSORS(ThinString, actual, String, kActualOffset); |
bool ExternalString::is_short() { |
InstanceType type = map()->instance_type(); |