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

Unified Diff: src/objects-inl.h

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-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);
}

Powered by Google App Engine
This is Rietveld 408576698