Index: src/objects-inl.h |
=================================================================== |
--- src/objects-inl.h (revision 654) |
+++ src/objects-inl.h (working copy) |
@@ -114,88 +114,169 @@ |
} |
-bool Object::IsSeqString() { |
- return IsString() |
- && (String::cast(this)->representation_tag() == kSeqStringTag); |
+bool Object::IsSymbol() { |
+ if (this->IsSmi()) return false; |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ return (type & (kIsNotStringMask | kIsSymbolMask)) == |
+ (kStringTag | kSymbolTag); |
} |
-bool Object::IsSeqAsciiString() { |
- return IsSeqString() |
- && String::cast(this)->IsAsciiRepresentation(); |
+bool Object::IsConsString() { |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ return (type & (kIsNotStringMask | kStringRepresentationMask)) == |
+ (kStringTag | kConsStringTag); |
} |
-bool String::IsSeqAsciiString() { |
- return (this->representation_tag() == kSeqStringTag) |
- && is_ascii_representation(); |
+#ifdef DEBUG |
+// These are for cast checks. If you need one of these in release |
+// mode you should consider using a StringShape before moving it out |
+// of the ifdef |
+ |
+bool Object::IsSeqString() { |
Mads Ager (chromium)
2008/11/03 08:45:49
Is it too expensive to use StringShapes for these?
|
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask; |
+ return type == (kStringTag | kSeqStringTag); |
} |
+bool Object::IsSeqAsciiString() { |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
+ return type == (kStringTag | kSeqStringTag | kAsciiStringTag); |
+} |
+ |
+ |
bool Object::IsSeqTwoByteString() { |
- return IsSeqString() |
- && !String::cast(this)->IsAsciiRepresentation(); |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
+ return type == (kStringTag | kSeqStringTag | kTwoByteStringTag); |
} |
-bool Object::IsAsciiStringRepresentation() { |
- return IsString() && (String::cast(this)->is_ascii_representation()); |
+bool Object::IsExternalString() { |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask; |
+ return type == (kStringTag | kExternalStringTag); |
} |
-bool Object::IsTwoByteStringRepresentation() { |
- return IsString() && (!String::cast(this)->is_ascii_representation()); |
+bool Object::IsExternalAsciiString() { |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
+ return type == (kStringTag | kExternalStringTag | kAsciiStringTag); |
} |
-bool Object::IsConsString() { |
- return IsString() |
- && (String::cast(this)->representation_tag() == kConsStringTag); |
+bool Object::IsExternalTwoByteString() { |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
+ return type == (kStringTag | kExternalStringTag | kTwoByteStringTag); |
} |
bool Object::IsSlicedString() { |
- return IsString() |
- && (String::cast(this)->representation_tag() == kSlicedStringTag); |
+ uint32_t type = HeapObject::cast(this)->map()->instance_type(); |
+ type &= kIsNotStringMask | kStringRepresentationMask; |
+ return type == (kStringTag | kSlicedStringTag); |
} |
-bool Object::IsExternalString() { |
- return IsString() |
- && (String::cast(this)->representation_tag() == kExternalStringTag); |
+#endif // DEBUG |
+ |
+ |
+StringShape::StringShape(String* str) : |
+ type_(str->map()->instance_type()) { |
+ ASSERT((type_ & kIsNotStringMask) == kStringTag); |
} |
-bool Object::IsExternalAsciiString() { |
- return IsExternalString() && (String::cast(this)->is_ascii_representation()); |
+StringShape::StringShape(Map* map) : |
+ type_(map->instance_type()) { |
+ ASSERT((type_ & kIsNotStringMask) == kStringTag); |
} |
-bool Object::IsExternalTwoByteString() { |
- return IsExternalString() && (!String::cast(this)->is_ascii_representation()); |
+StringShape::StringShape(InstanceType t) : |
+ type_(static_cast<uint32_t>(t)) { |
+ ASSERT((type_ & kIsNotStringMask) == kStringTag); |
} |
-bool Object::IsShortString() { |
- return IsString() && (String::cast(this)->size_tag() == kShortStringTag); |
+bool StringShape::IsSymbol() { |
+ return (type_ & kIsSymbolMask) == kSymbolTag; |
} |
-bool Object::IsMediumString() { |
- return IsString() && (String::cast(this)->size_tag() == kMediumStringTag); |
+bool StringShape::IsAsciiRepresentation() { |
+ return (type_ & kStringEncodingMask) == kAsciiStringTag; |
} |
-bool Object::IsLongString() { |
- return IsString() && (String::cast(this)->size_tag() == kLongStringTag); |
+bool StringShape::IsTwoByteRepresentation() { |
+ return (type_ & kStringEncodingMask) == kTwoByteStringTag; |
} |
-bool Object::IsSymbol() { |
- return IsString() && (String::cast(this)->is_symbol()); |
+bool StringShape::IsCons() { |
+ return (type_ & kStringRepresentationMask) == kConsStringTag; |
} |
+bool StringShape::IsSliced() { |
+ return (type_ & kStringRepresentationMask) == kSlicedStringTag; |
+} |
+ |
+ |
+bool StringShape::IsExternal() { |
+ return (type_ & kStringRepresentationMask) == kExternalStringTag; |
+} |
+ |
+ |
+bool StringShape::IsSequential() { |
+ return (type_ & kStringRepresentationMask) == kSeqStringTag; |
+} |
+ |
+ |
+StringRepresentationTag StringShape::representation_tag() { |
+ uint32_t tag = (type_ & kStringRepresentationMask); |
+ return static_cast<StringRepresentationTag>(tag); |
+} |
+ |
+ |
+uint32_t StringShape::full_representation_tag() { |
+ return (type_ & (kStringRepresentationMask | kStringEncodingMask)); |
+} |
+ |
+ |
+uint32_t StringShape::size_tag() { |
+ return (type_ & kStringSizeMask); |
+} |
+ |
+ |
+bool StringShape::IsSequentialAscii() { |
+ return full_representation_tag() == (kSeqStringTag | kAsciiStringTag); |
+} |
+ |
+ |
+bool StringShape::IsSequentialTwoByte() { |
+ return (type_ & (kStringRepresentationMask | kStringEncodingMask)) == |
+ (kSeqStringTag | kTwoByteStringTag); |
+} |
+ |
+ |
+bool StringShape::IsExternalAscii() { |
+ return full_representation_tag() == (kExternalStringTag | kAsciiStringTag); |
+} |
+ |
+ |
+bool StringShape::IsExternalTwoByte() { |
+ return (type_ & (kStringRepresentationMask | kStringEncodingMask)) == |
+ (kExternalStringTag | kTwoByteStringTag); |
+} |
+ |
+ |
bool Object::IsNumber() { |
return IsSmi() || IsHeapNumber(); |
} |
@@ -1128,13 +1209,15 @@ |
int DescriptorArray::Search(String* name) { |
SLOW_ASSERT(IsSortedNoDuplicates()); |
+ StringShape shape(name); |
+ |
// Check for empty descriptor array. |
int nof = number_of_descriptors(); |
if (nof == 0) return kNotFound; |
// Fast case: do linear search for small arrays. |
const int kMaxElementsForLinearSearch = 8; |
- if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) { |
+ if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) { |
return LinearSearch(name, nof); |
} |
@@ -1268,30 +1351,39 @@ |
bool String::Equals(String* other) { |
if (other == this) return true; |
- if (IsSymbol() && other->IsSymbol()) return false; |
- return SlowEquals(other); |
+ StringShape this_shape(this); |
+ StringShape other_shape(other); |
+ if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false; |
+ return SlowEquals(this_shape, other, other_shape); |
} |
-int String::length() { |
+int String::length(StringShape shape) { |
+ ASSERT(shape.type() == StringShape(this).type()); |
uint32_t len = READ_INT_FIELD(this, kLengthOffset); |
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
ASSERT(kLongStringTag == 0); |
- return len >> (size_tag() + kLongLengthShift); |
+ return len >> (shape.size_tag() + kLongLengthShift); |
} |
+int String::length() { |
+ return length(StringShape(this)); |
+} |
+ |
+ |
void String::set_length(int value) { |
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); |
ASSERT(kLongStringTag == 0); |
+ StringShape shape(this); |
WRITE_INT_FIELD(this, |
kLengthOffset, |
- value << (size_tag() + kLongLengthShift)); |
+ value << (shape.size_tag() + kLongLengthShift)); |
} |
@@ -1305,31 +1397,34 @@ |
} |
-void String::TryFlatten() { |
+void String::TryFlatten(StringShape shape) { |
+ ASSERT(shape.type() == StringShape(this).type()); |
// We don't need to flatten strings that are already flat. Since this code |
// is inlined, it can be helpful in the flat case to not call out to Flatten. |
- StringRepresentationTag str_type = representation_tag(); |
- if (str_type != kSeqStringTag && str_type != kExternalStringTag) { |
- Flatten(); |
+ if (!IsFlat(shape)) { |
+ Flatten(shape); |
} |
} |
-uint16_t String::Get(int index) { |
- ASSERT(index >= 0 && index < length()); |
- switch (representation_tag()) { |
- case kSeqStringTag: |
- return is_ascii_representation() |
- ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index) |
- : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); |
- case kConsStringTag: |
+uint16_t String::Get(StringShape shape, int index) { |
+ ASSERT(shape.type() == StringShape(this).type()); |
+ ASSERT(index >= 0 && index < length(shape)); |
+ switch (shape.full_representation_tag()) { |
+ case kSeqStringTag | kAsciiStringTag: |
+ return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); |
+ case kSeqStringTag | kTwoByteStringTag: |
+ return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); |
+ case kConsStringTag | kAsciiStringTag: |
+ case kConsStringTag | kTwoByteStringTag: |
return ConsString::cast(this)->ConsStringGet(index); |
- case kSlicedStringTag: |
+ case kSlicedStringTag | kAsciiStringTag: |
+ case kSlicedStringTag | kTwoByteStringTag: |
return SlicedString::cast(this)->SlicedStringGet(index); |
- case kExternalStringTag: |
- return is_ascii_representation() |
- ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index) |
- : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); |
+ case kExternalStringTag | kAsciiStringTag: |
+ return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); |
+ case kExternalStringTag | kTwoByteStringTag: |
+ return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); |
default: |
break; |
} |
@@ -1339,86 +1434,29 @@ |
} |
-void String::Set(int index, uint16_t value) { |
- ASSERT(index >= 0 && index < length()); |
- ASSERT(IsSeqString()); |
+void String::Set(StringShape shape, int index, uint16_t value) { |
+ ASSERT(shape.type() == StringShape(this).type()); |
+ ASSERT(shape.type() == StringShape(this).type()); |
+ ASSERT(index >= 0 && index < length(shape)); |
+ ASSERT(shape.IsSequential()); |
- return is_ascii_representation() |
+ return shape.IsAsciiRepresentation() |
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) |
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); |
} |
-bool String::IsAsciiRepresentation() { |
- return is_ascii_representation(); |
-} |
- |
- |
-bool String::StringIsConsString() { |
- return representation_tag() == kConsStringTag; |
-} |
- |
- |
-bool String::StringIsSlicedString() { |
- return representation_tag() == kSlicedStringTag; |
-} |
- |
- |
-uint32_t String::size_tag() { |
- return map_size_tag(map()); |
-} |
- |
- |
-uint32_t String::map_size_tag(Map* map) { |
- return map->instance_type() & kStringSizeMask; |
-} |
- |
- |
-bool String::is_symbol() { |
- return is_symbol_map(map()); |
-} |
- |
- |
-bool String::is_symbol_map(Map* map) { |
- return (map->instance_type() & kIsSymbolMask) != 0; |
-} |
- |
- |
-bool String::is_ascii_representation() { |
- return is_ascii_representation_map(map()); |
-} |
- |
- |
-bool String::is_ascii_representation_map(Map* map) { |
- return (map->instance_type() & kStringEncodingMask) != 0; |
-} |
- |
- |
-int String::full_representation_tag() { |
- return map()->instance_type() & |
- (kStringRepresentationMask | kStringEncodingMask); |
-} |
- |
- |
-StringRepresentationTag String::representation_tag() { |
- return map_representation_tag(map()); |
-} |
- |
- |
-StringRepresentationTag String::map_representation_tag(Map* map) { |
- uint32_t tag = map->instance_type() & kStringRepresentationMask; |
- return static_cast<StringRepresentationTag>(tag); |
-} |
- |
- |
-bool String::IsFlat() { |
- switch (this->representation_tag()) { |
- case kConsStringTag: |
+bool String::IsFlat(StringShape shape) { |
+ ASSERT(shape.type() == StringShape(this).type()); |
+ switch (shape.representation_tag()) { |
+ case kConsStringTag: { |
+ String* second = ConsString::cast(this)->second(); |
// Only flattened strings have second part empty. |
- return String::cast(ConsString::cast(this)->second())->length() == 0; |
+ return second->length() == 0; |
+ } |
case kSlicedStringTag: { |
- String* slice = String::cast(SlicedString::cast(this)->buffer()); |
- StringRepresentationTag tag = slice->representation_tag(); |
+ StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer()); |
+ StringRepresentationTag tag = slice_shape.representation_tag(); |
return tag == kSeqStringTag || tag == kExternalStringTag; |
} |
default: |
@@ -1472,7 +1510,7 @@ |
} |
-int SeqTwoByteString::SeqTwoByteStringSize(Map* map) { |
+int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) { |
uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
@@ -1481,13 +1519,13 @@ |
// Use the map (and not 'this') to compute the size tag, since |
// TwoByteStringSize is called during GC when maps are encoded. |
- length >>= map_size_tag(map) + kLongLengthShift; |
+ length >>= shape.size_tag() + kLongLengthShift; |
return SizeFor(length); |
} |
-int SeqAsciiString::SeqAsciiStringSize(Map* map) { |
+int SeqAsciiString::SeqAsciiStringSize(StringShape shape) { |
uint32_t length = READ_INT_FIELD(this, kLengthOffset); |
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); |
@@ -1496,40 +1534,50 @@ |
// Use the map (and not 'this') to compute the size tag, since |
// AsciiStringSize is called during GC when maps are encoded. |
- length >>= map_size_tag(map) + kLongLengthShift; |
+ length >>= shape.size_tag() + kLongLengthShift; |
return SizeFor(length); |
} |
-Object* ConsString::first() { |
+String* ConsString::first() { |
+ return String::cast(READ_FIELD(this, kFirstOffset)); |
+} |
+ |
+ |
+Object* ConsString::unchecked_first() { |
return READ_FIELD(this, kFirstOffset); |
} |
-void ConsString::set_first(Object* value, WriteBarrierMode mode) { |
+void ConsString::set_first(String* value, WriteBarrierMode mode) { |
WRITE_FIELD(this, kFirstOffset, value); |
CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode); |
} |
-Object* ConsString::second() { |
+String* ConsString::second() { |
+ return String::cast(READ_FIELD(this, kSecondOffset)); |
+} |
+ |
+ |
+Object* ConsString::unchecked_second() { |
return READ_FIELD(this, kSecondOffset); |
} |
-void ConsString::set_second(Object* value, WriteBarrierMode mode) { |
+void ConsString::set_second(String* value, WriteBarrierMode mode) { |
WRITE_FIELD(this, kSecondOffset, value); |
CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode); |
} |
-Object* SlicedString::buffer() { |
- return READ_FIELD(this, kBufferOffset); |
+String* SlicedString::buffer() { |
+ return String::cast(READ_FIELD(this, kBufferOffset)); |
} |
-void SlicedString::set_buffer(Object* buffer) { |
+void SlicedString::set_buffer(String* buffer) { |
WRITE_FIELD(this, kBufferOffset, buffer); |
WRITE_BARRIER(this, kBufferOffset); |
} |