- Specialized slow-case string equality nine ways based on the

  underlying string representation of the two strings involved.
- Renamed ascii and two byte string classes to sequential ascii and
  sequential two byte, and renamed IsAscii and friends to
  IsAsciiRepresentation.  This is to make a clear distinction between
  strings with an ascii/two-byte representation, of which there is
  four, and flat sequential ascii/two-byte string.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@474 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f6a26964
......@@ -63,7 +63,7 @@ class SourceCodeCache BASE_EMBEDDED {
bool Lookup(Vector<const char> name, Handle<JSFunction>* handle) {
for (int i = 0; i < cache_->length(); i+=2) {
AsciiString* str = AsciiString::cast(cache_->get(i));
SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
if (str->IsEqualTo(name)) {
*handle = Handle<JSFunction>(JSFunction::cast(cache_->get(i + 1)));
return true;
......@@ -751,7 +751,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
// function and insert it into the cache.
if (!cache->Lookup(name, &boilerplate)) {
#ifdef DEBUG
ASSERT(source->IsAscii());
ASSERT(source->IsAsciiRepresentation());
#endif
Handle<String> script_name = Factory::NewStringFromUtf8(name);
boilerplate =
......
......@@ -3156,13 +3156,14 @@ void Ia32CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
// 2-byte string.
// Load the 2-byte character code.
__ movzx_w(eax, FieldOperand(eax, ebx, times_2, TwoByteString::kHeaderSize));
__ movzx_w(eax,
FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
__ jmp(&got_char_code);
// ASCII string.
__ bind(&ascii_string);
// Load the byte.
__ movzx_b(eax, FieldOperand(eax, ebx, times_1, AsciiString::kHeaderSize));
__ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
__ bind(&got_char_code);
ASSERT(kSmiTag == 0);
......
......@@ -931,32 +931,32 @@ bool Heap::CreateInitialMaps() {
STRING_TYPE_LIST(ALLOCATE_STRING_MAP);
#undef ALLOCATE_STRING_MAP
obj = AllocateMap(SHORT_STRING_TYPE, TwoByteString::kHeaderSize);
obj = AllocateMap(SHORT_STRING_TYPE, SeqTwoByteString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_short_string_map_ = Map::cast(obj);
undetectable_short_string_map_->set_is_undetectable();
obj = AllocateMap(MEDIUM_STRING_TYPE, TwoByteString::kHeaderSize);
obj = AllocateMap(MEDIUM_STRING_TYPE, SeqTwoByteString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_medium_string_map_ = Map::cast(obj);
undetectable_medium_string_map_->set_is_undetectable();
obj = AllocateMap(LONG_STRING_TYPE, TwoByteString::kHeaderSize);
obj = AllocateMap(LONG_STRING_TYPE, SeqTwoByteString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_long_string_map_ = Map::cast(obj);
undetectable_long_string_map_->set_is_undetectable();
obj = AllocateMap(SHORT_ASCII_STRING_TYPE, AsciiString::kHeaderSize);
obj = AllocateMap(SHORT_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_short_ascii_string_map_ = Map::cast(obj);
undetectable_short_ascii_string_map_->set_is_undetectable();
obj = AllocateMap(MEDIUM_ASCII_STRING_TYPE, AsciiString::kHeaderSize);
obj = AllocateMap(MEDIUM_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_medium_ascii_string_map_ = Map::cast(obj);
undetectable_medium_ascii_string_map_->set_is_undetectable();
obj = AllocateMap(LONG_ASCII_STRING_TYPE, AsciiString::kHeaderSize);
obj = AllocateMap(LONG_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
if (obj->IsFailure()) return false;
undetectable_long_ascii_string_map_ = Map::cast(obj);
undetectable_long_ascii_string_map_->set_is_undetectable();
......@@ -1328,7 +1328,8 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
Object* Heap::AllocateConsString(String* first, String* second) {
int length = first->length() + second->length();
bool is_ascii = first->is_ascii() && second->is_ascii();
bool is_ascii = first->is_ascii_representation()
&& second->is_ascii_representation();
// If the resulting string is small make a flat string.
if (length < ConsString::kMinLength) {
......@@ -1385,13 +1386,13 @@ Object* Heap::AllocateSlicedString(String* buffer, int start, int end) {
Map* map;
if (length <= String::kMaxShortStringSize) {
map = buffer->is_ascii() ? short_sliced_ascii_string_map()
map = buffer->is_ascii_representation() ? short_sliced_ascii_string_map()
: short_sliced_string_map();
} else if (length <= String::kMaxMediumStringSize) {
map = buffer->is_ascii() ? medium_sliced_ascii_string_map()
map = buffer->is_ascii_representation() ? medium_sliced_ascii_string_map()
: medium_sliced_string_map();
} else {
map = buffer->is_ascii() ? long_sliced_ascii_string_map()
map = buffer->is_ascii_representation() ? long_sliced_ascii_string_map()
: long_sliced_string_map();
}
......@@ -1417,7 +1418,7 @@ Object* Heap::AllocateSubString(String* buffer, int start, int end) {
// Make an attempt to flatten the buffer to reduce access time.
buffer->TryFlatten();
Object* result = buffer->is_ascii()
Object* result = buffer->is_ascii_representation()
? AllocateRawAsciiString(length)
: AllocateRawTwoByteString(length);
if (result->IsFailure()) return result;
......@@ -1768,9 +1769,9 @@ Object* Heap::AllocateStringFromAscii(Vector<const char> string,
if (result->IsFailure()) return result;
// Copy the characters into the new object.
AsciiString* string_result = AsciiString::cast(result);
SeqAsciiString* string_result = SeqAsciiString::cast(result);
for (int i = 0; i < string.length(); i++) {
string_result->AsciiStringSet(i, string[i]);
string_result->SeqAsciiStringSet(i, string[i]);
}
return result;
}
......@@ -1918,7 +1919,7 @@ Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer,
} else {
map = long_ascii_symbol_map();
}
size = AsciiString::SizeFor(chars);
size = SeqAsciiString::SizeFor(chars);
} else {
if (chars <= String::kMaxShortStringSize) {
map = short_symbol_map();
......@@ -1927,7 +1928,7 @@ Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer,
} else {
map = long_symbol_map();
}
size = TwoByteString::SizeFor(chars);
size = SeqTwoByteString::SizeFor(chars);
}
// Allocate string.
......@@ -1952,7 +1953,7 @@ Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer,
Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
int size = AsciiString::SizeFor(length);
int size = SeqAsciiString::SizeFor(length);
if (size > MaxHeapObjectSize()) {
space = LO_SPACE;
}
......@@ -1982,7 +1983,7 @@ Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) {
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
int size = TwoByteString::SizeFor(length);
int size = SeqTwoByteString::SizeFor(length);
if (size > MaxHeapObjectSize()) {
space = LO_SPACE;
}
......
......@@ -128,7 +128,7 @@ Handle<String> RegExpImpl::StringToTwoByte(Handle<String> pattern) {
ASSERT(!flat_string->IsConsString());
ASSERT(flat_string->IsSeqString() || flat_string->IsSlicedString() ||
flat_string->IsExternalString());
if (!flat_string->IsAscii()) {
if (!flat_string->IsAsciiRepresentation()) {
return flat_string;
}
......
......@@ -119,13 +119,25 @@ bool Object::IsSeqString() {
}
bool Object::IsAsciiString() {
return IsString() && (String::cast(this)->is_ascii());
bool Object::IsSeqAsciiString() {
return IsSeqString()
&& String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsTwoByteString() {
return IsString() && (!String::cast(this)->is_ascii());
bool Object::IsSeqTwoByteString() {
return IsSeqString()
&& !String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsAsciiStringRepresentation() {
return IsString() && (String::cast(this)->is_ascii_representation());
}
bool Object::IsTwoByteStringRepresentation() {
return IsString() && (!String::cast(this)->is_ascii_representation());
}
......@@ -148,12 +160,12 @@ bool Object::IsExternalString() {
bool Object::IsExternalAsciiString() {
return IsExternalString() && (String::cast(this)->is_ascii());
return IsExternalString() && (String::cast(this)->is_ascii_representation());
}
bool Object::IsExternalTwoByteString() {
return IsExternalString() && (!String::cast(this)->is_ascii());
return IsExternalString() && (!String::cast(this)->is_ascii_representation());
}
......@@ -1126,8 +1138,8 @@ CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(MapCache)
CAST_ACCESSOR(String)
CAST_ACCESSOR(SeqString)
CAST_ACCESSOR(AsciiString)
CAST_ACCESSOR(TwoByteString)
CAST_ACCESSOR(SeqAsciiString)
CAST_ACCESSOR(SeqTwoByteString)
CAST_ACCESSOR(ConsString)
CAST_ACCESSOR(SlicedString)
CAST_ACCESSOR(ExternalString)
......@@ -1234,15 +1246,15 @@ uint16_t String::Get(int index) {
ASSERT(index >= 0 && index < length());
switch (representation_tag()) {
case kSeqStringTag:
return is_ascii()
? AsciiString::cast(this)->AsciiStringGet(index)
: TwoByteString::cast(this)->TwoByteStringGet(index);
return is_ascii_representation()
? SeqAsciiString::cast(this)->SeqAsciiStringGet(index)
: SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
case kConsStringTag:
return ConsString::cast(this)->ConsStringGet(index);
case kSlicedStringTag:
return SlicedString::cast(this)->SlicedStringGet(index);
case kExternalStringTag:
return is_ascii()
return is_ascii_representation()
? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
: ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
default:
......@@ -1258,14 +1270,14 @@ void String::Set(int index, uint16_t value) {
ASSERT(index >= 0 && index < length());
ASSERT(IsSeqString());
return is_ascii()
? AsciiString::cast(this)->AsciiStringSet(index, value)
: TwoByteString::cast(this)->TwoByteStringSet(index, value);
return is_ascii_representation()
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
}
bool String::IsAscii() {
return is_ascii();
bool String::IsAsciiRepresentation() {
return is_ascii_representation();
}
......@@ -1299,12 +1311,12 @@ bool String::is_symbol_map(Map* map) {
}
bool String::is_ascii() {
return is_ascii_map(map());
bool String::is_ascii_representation() {
return is_ascii_representation_map(map());
}
bool String::is_ascii_map(Map* map) {
bool String::is_ascii_representation_map(Map* map) {
return (map->instance_type() & kStringEncodingMask) != 0;
}
......@@ -1336,42 +1348,42 @@ bool String::IsFlat() {
}
uint16_t AsciiString::AsciiStringGet(int index) {
uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
ASSERT(index >= 0 && index < length());
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}
void AsciiString::AsciiStringSet(int index, uint16_t value) {
void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
static_cast<byte>(value));
}
Address AsciiString::GetCharsAddress() {
Address SeqAsciiString::GetCharsAddress() {
return FIELD_ADDR(this, kHeaderSize);
}
Address TwoByteString::GetCharsAddress() {
Address SeqTwoByteString::GetCharsAddress() {
return FIELD_ADDR(this, kHeaderSize);
}
uint16_t TwoByteString::TwoByteStringGet(int index) {
uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
ASSERT(index >= 0 && index < length());
return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
}
void TwoByteString::TwoByteStringSet(int index, uint16_t value) {
void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
ASSERT(index >= 0 && index < length());
WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
}
int TwoByteString::TwoByteStringSize(Map* map) {
int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
// Use the map (and not 'this') to compute the size tag, since
......@@ -1393,7 +1405,7 @@ int TwoByteString::TwoByteStringSize(Map* map) {
}
int AsciiString::AsciiStringSize(Map* map) {
int SeqAsciiString::SeqAsciiStringSize(Map* map) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
// Use the map (and not 'this') to compute the size tag, since
......
This diff is collapsed.
......@@ -61,8 +61,8 @@
// - GlobalContext
// - String
// - SeqString
// - AsciiString
// - TwoByteString
// - SeqAsciiString
// - SeqTwoByteString
// - ConsString
// - SlicedString
// - ExternalString
......@@ -272,12 +272,12 @@ class PropertyDetails BASE_EMBEDDED {
// Since string types are not consecutive, this macro is used to
// iterate over them.
#define STRING_TYPE_LIST(V) \
V(SHORT_SYMBOL_TYPE, TwoByteString::kHeaderSize, short_symbol) \
V(MEDIUM_SYMBOL_TYPE, TwoByteString::kHeaderSize, medium_symbol) \
V(LONG_SYMBOL_TYPE, TwoByteString::kHeaderSize, long_symbol) \
V(SHORT_ASCII_SYMBOL_TYPE, AsciiString::kHeaderSize, short_ascii_symbol) \
V(MEDIUM_ASCII_SYMBOL_TYPE, AsciiString::kHeaderSize, medium_ascii_symbol) \
V(LONG_ASCII_SYMBOL_TYPE, AsciiString::kHeaderSize, long_ascii_symbol) \
V(SHORT_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, short_symbol) \
V(MEDIUM_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, medium_symbol) \
V(LONG_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, long_symbol) \
V(SHORT_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, short_ascii_symbol) \
V(MEDIUM_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, medium_ascii_symbol)\
V(LONG_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, long_ascii_symbol) \
V(SHORT_CONS_SYMBOL_TYPE, ConsString::kSize, short_cons_symbol) \
V(MEDIUM_CONS_SYMBOL_TYPE, ConsString::kSize, medium_cons_symbol) \
V(LONG_CONS_SYMBOL_TYPE, ConsString::kSize, long_cons_symbol) \
......@@ -314,12 +314,12 @@ class PropertyDetails BASE_EMBEDDED {
V(LONG_EXTERNAL_ASCII_SYMBOL_TYPE, \
ExternalAsciiString::kSize, \
long_external_ascii_symbol) \
V(SHORT_STRING_TYPE, TwoByteString::kHeaderSize, short_string) \
V(MEDIUM_STRING_TYPE, TwoByteString::kHeaderSize, medium_string) \
V(LONG_STRING_TYPE, TwoByteString::kHeaderSize, long_string) \
V(SHORT_ASCII_STRING_TYPE, AsciiString::kHeaderSize, short_ascii_string) \
V(MEDIUM_ASCII_STRING_TYPE, AsciiString::kHeaderSize, medium_ascii_string) \
V(LONG_ASCII_STRING_TYPE, AsciiString::kHeaderSize, long_ascii_string) \
V(SHORT_STRING_TYPE, SeqTwoByteString::kHeaderSize, short_string) \
V(MEDIUM_STRING_TYPE, SeqTwoByteString::kHeaderSize, medium_string) \
V(LONG_STRING_TYPE, SeqTwoByteString::kHeaderSize, long_string) \
V(SHORT_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, short_ascii_string) \
V(MEDIUM_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, medium_ascii_string)\
V(LONG_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, long_ascii_string) \
V(SHORT_CONS_STRING_TYPE, ConsString::kSize, short_cons_string) \
V(MEDIUM_CONS_STRING_TYPE, ConsString::kSize, medium_cons_string) \
V(LONG_CONS_STRING_TYPE, ConsString::kSize, long_cons_string) \
......@@ -584,8 +584,10 @@ class Object BASE_EMBEDDED {
inline bool IsHeapNumber();
inline bool IsString();
inline bool IsSeqString();
inline bool IsAsciiString();
inline bool IsTwoByteString();
inline bool IsAsciiStringRepresentation();
inline bool IsTwoByteStringRepresentation();
inline bool IsSeqAsciiString();
inline bool IsSeqTwoByteString();
inline bool IsConsString();
inline bool IsSlicedString();
inline bool IsExternalString();
......@@ -2928,13 +2930,16 @@ class String: public HeapObject {
inline void TryFlatten();
// Is this string an ascii string.
inline bool IsAscii();
inline bool IsAsciiRepresentation();
// Fast testing routines that assume the receiver is a string and
// just check whether it is a certain kind of string.
inline bool StringIsSlicedString();
inline bool StringIsConsString();
Vector<const char> ToAsciiVector();
Vector<const uc16> ToUC16Vector();
// Mark the string as an undetectable object. It only applies to
// ascii and two byte string types.
bool MarkAsUndetectable();
......@@ -3005,8 +3010,8 @@ class String: public HeapObject {
static inline bool is_symbol_map(Map* map);
// True if the string is ASCII.
inline bool is_ascii();
static inline bool is_ascii_map(Map* map);
inline bool is_ascii_representation();
static inline bool is_ascii_representation_map(Map* map);
// Get the representation tag.
inline StringRepresentationTag representation_tag();
......@@ -3145,22 +3150,22 @@ class SeqString: public String {
// The AsciiString class captures sequential ascii string objects.
// Each character in the AsciiString is an ascii character.
class AsciiString: public SeqString {
class SeqAsciiString: public SeqString {
public:
// Dispatched behavior.
inline uint16_t AsciiStringGet(int index);
inline void AsciiStringSet(int index, uint16_t value);
inline uint16_t SeqAsciiStringGet(int index);
inline void SeqAsciiStringSet(int index, uint16_t value);
// Get the address of the characters in this string.
inline Address GetCharsAddress();
// Casting
static inline AsciiString* cast(Object* obj);
static inline SeqAsciiString* cast(Object* obj);
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of an AsciiString
// instance.
inline int AsciiStringSize(Map* map);
inline int SeqAsciiStringSize(Map* map);
// Computes the size for an AsciiString instance of a given length.
static int SizeFor(int length) {
......@@ -3171,39 +3176,39 @@ class AsciiString: public SeqString {
static const int kHeaderSize = String::kSize;
// Support for StringInputBuffer.
inline void AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset,
unsigned chars);
inline const unibrow::byte* AsciiStringReadBlock(unsigned* remaining,
inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
unsigned* offset,
unsigned chars);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AsciiString);
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
};
// The TwoByteString class captures sequential unicode string objects.
// Each character in the TwoByteString is a two-byte uint16_t.
class TwoByteString: public SeqString {
class SeqTwoByteString: public SeqString {
public:
// Dispatched behavior.
inline uint16_t TwoByteStringGet(int index);
inline void TwoByteStringSet(int index, uint16_t value);
inline uint16_t SeqTwoByteStringGet(int index);
inline void SeqTwoByteStringSet(int index, uint16_t value);
// Get the address of the characters in this string.
inline Address GetCharsAddress();
// For regexp code.
const uint16_t* TwoByteStringGetData(unsigned start);
const uint16_t* SeqTwoByteStringGetData(unsigned start);
// Casting
static inline TwoByteString* cast(Object* obj);
static inline SeqTwoByteString* cast(Object* obj);
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of a TwoByteString
// instance.
inline int TwoByteStringSize(Map* map);
inline int SeqTwoByteStringSize(Map* map);
// Computes the size for a TwoByteString instance of a given length.
static int SizeFor(int length) {
......@@ -3214,12 +3219,12 @@ class TwoByteString: public SeqString {
static const int kHeaderSize = String::kSize;
// Support for StringInputBuffer.
inline void TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TwoByteString);
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
};
......@@ -3431,6 +3436,19 @@ class SafeStringInputBuffer
};
template <typename T>
class VectorIterator {
public:
VectorIterator(T* d, int l) : data_(Vector<T>(d, l)), index_(0) { }
explicit VectorIterator(Vector<T> data) : data_(data), index_(0) { }
T GetNext() { return data_[index_++]; }
bool has_more() { return index_ < data_.length(); }
private:
Vector<T> data_;
int index_;
};
// The Oddball describes objects null, undefined, true, and false.
class Oddball: public HeapObject {
public:
......
......@@ -952,68 +952,6 @@ static Object* Runtime_CharFromCode(Arguments args) {
}
static Vector<const char> ToAsciiVector(String *string) {
ASSERT(string->IsAscii());
ASSERT(string->IsFlat());
int offset = 0;
int length = string->length();
StringRepresentationTag string_tag = string->representation_tag();
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
string = String::cast(sliced->buffer());
string_tag = string->representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
ASSERT(String::cast(cons->second())->length() == 0);
string = String::cast(cons->first());
string_tag = string->representation_tag();
}
if (string_tag == kSeqStringTag) {
AsciiString* seq = AsciiString::cast(string);
char* start = reinterpret_cast<char*>(seq->GetCharsAddress());
return Vector<const char>(start + offset, length);
}
ASSERT(string_tag == kExternalStringTag);
ExternalAsciiString* ext = ExternalAsciiString::cast(string);
const char* start = ext->resource()->data();
return Vector<const char>(start + offset, length);
}
static Vector<const uc16> ToUC16Vector(String *string) {
ASSERT(string->IsTwoByteString());
ASSERT(string->IsFlat());
int offset = 0;
int length = string->length();
StringRepresentationTag string_tag = string->representation_tag();
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
string = String::cast(sliced->buffer());
string_tag = string->representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
ASSERT(String::cast(cons->second())->length() == 0);
string = String::cast(cons->first());
string_tag = string->representation_tag();
}
if (string_tag == kSeqStringTag) {
TwoByteString* seq = TwoByteString::cast(string);
uc16* start = reinterpret_cast<uc16*>(seq->GetCharsAddress());
return Vector<const uc16>(start + offset, length);
}
ASSERT(string_tag == kExternalStringTag);
ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
const uc16* start =
reinterpret_cast<const uc16*>(ext->resource()->data());
return Vector<const uc16>(start + offset, length);
}
template <typename schar, typename pchar>
static int SingleCharIndexOf(Vector<const schar> string,
pchar pattern_char,
......@@ -1202,18 +1140,18 @@ int Runtime::StringMatch(Handle<String> sub,
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// dispatch on type of strings
if (pat->is_ascii()) {
Vector<const char> pat_vector = ToAsciiVector(*pat);
if (sub->is_ascii()) {
return StringMatchStrategy(ToAsciiVector(*sub), pat_vector, start_index);
if (pat->is_ascii_representation()) {
Vector<const char> pat_vector = pat->ToAsciiVector();
if (sub->is_ascii_representation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(ToUC16Vector(*sub), pat_vector, start_index);
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
}
Vector<const uc16> pat_vector = ToUC16Vector(*pat);
if (sub->is_ascii()) {
return StringMatchStrategy(ToAsciiVector(*sub), pat_vector, start_index);
Vector<const uc16> pat_vector = pat->ToUC16Vector();
if (sub->is_ascii_representation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(ToUC16Vector(*sub), pat_vector, start_index);
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
}
......@@ -2155,7 +2093,7 @@ static Object* ConvertCase(Arguments args,
// character is also ascii. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
Object* o = s->IsAscii()
Object* o = s->IsAsciiRepresentation()
? Heap::AllocateRawAsciiString(length)
: Heap::AllocateRawTwoByteString(length);
if (o->IsFailure()) return o;
......@@ -2432,7 +2370,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
if (first->IsString()) return first;
}
bool ascii = special->IsAscii();
bool ascii = special->IsAsciiRepresentation();
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
......@@ -2452,7 +2390,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
return Failure::OutOfMemoryException();
}
position += element_length;
if (ascii && !element->IsAscii()) {
if (ascii && !element->IsAsciiRepresentation()) {
ascii = false;
}
} else {
......
......@@ -38,7 +38,7 @@ TEST(HeapMaps) {
CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, Array::kHeaderSize);
CheckMap(Heap::long_string_map(), LONG_STRING_TYPE,
TwoByteString::kHeaderSize);
SeqTwoByteString::kHeaderSize);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment