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;
// 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 =
// 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);
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();
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) {
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();
}
// 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;
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;
}
} else {
map = long_ascii_symbol_map();
}
- size = AsciiString::SizeFor(chars);
+ size = SeqAsciiString::SizeFor(chars);
} else {
if (chars <= String::kMaxShortStringSize) {
map = short_symbol_map();
} else {
map = long_symbol_map();
}
- size = TwoByteString::SizeFor(chars);
+ size = SeqTwoByteString::SizeFor(chars);
}
// Allocate string.
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;
}
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;
}
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;
}
}
-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());
}
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());
}
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)
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:
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();
}
}
-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;
}
}
-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
}
-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
// an old space GC.
PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
int len = length();
- Object* object = IsAscii() ?
+ Object* object = IsAsciiRepresentation() ?
Heap::AllocateRawAsciiString(len, tenure) :
Heap::AllocateRawTwoByteString(len, tenure);
if (object->IsFailure()) return object;
if (instance_type < FIRST_NONSTRING_TYPE
&& (reinterpret_cast<String*>(this)->map_representation_tag(map)
== kSeqStringTag)) {
- if (reinterpret_cast<String*>(this)->is_ascii_map(map)) {
- return reinterpret_cast<AsciiString*>(this)->AsciiStringSize(map);
+ if (reinterpret_cast<String*>(this)->is_ascii_representation_map(map)) {
+ return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(map);
} else {
- return reinterpret_cast<TwoByteString*>(this)->TwoByteStringSize(map);
+ SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
+ return self->SeqTwoByteStringSize(map);
}
}
int String::Utf8Length() {
- if (is_ascii()) return length();
+ if (is_ascii_representation()) return length();
// Attempt to flatten before accessing the string. It probably
// doesn't make Utf8Length faster, but it is very likely that
// the string will be accessed later (for example by WriteUtf8)
}
+Vector<const char> String::ToAsciiVector() {
+ ASSERT(IsAsciiRepresentation());
+ ASSERT(IsFlat());
+
+ int offset = 0;
+ int length = this->length();
+ StringRepresentationTag string_tag = representation_tag();
+ String* string = this;
+ 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) {
+ SeqAsciiString* seq = SeqAsciiString::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);
+}
+
+
+Vector<const uc16> String::ToUC16Vector() {
+ ASSERT(IsTwoByteStringRepresentation());
+ ASSERT(IsFlat());
+
+ int offset = 0;
+ int length = this->length();
+ StringRepresentationTag string_tag = representation_tag();
+ String* string = this;
+ 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) {
+ SeqTwoByteString* seq = SeqTwoByteString::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);
+}
+
+
SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
RobustnessFlag robust_flag,
int offset,
const uc16* String::GetTwoByteData(unsigned start) {
- ASSERT(!IsAscii());
+ ASSERT(!IsAsciiRepresentation());
switch (representation_tag()) {
case kSeqStringTag:
- return TwoByteString::cast(this)->TwoByteStringGetData(start);
+ return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
case kExternalStringTag:
return ExternalTwoByteString::cast(this)->
ExternalTwoByteStringGetData(start);
}
-const uc16* TwoByteString::TwoByteStringGetData(unsigned start) {
+const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
return reinterpret_cast<uc16*>(
reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
}
-void TwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
unsigned chars_read = 0;
}
-const unibrow::byte* AsciiString::AsciiStringReadBlock(unsigned* remaining,
- unsigned* offset_ptr,
- unsigned max_chars) {
+const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
+ unsigned* remaining,
+ unsigned* offset_ptr,
+ unsigned max_chars) {
// Cast const char* to unibrow::byte* (signedness difference).
const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
}
-void AsciiString::AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
unsigned capacity = rbb->capacity - rbb->cursor;
}
switch (input->representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii()) {
- return AsciiString::cast(input)->AsciiStringReadBlock(&rbb->remaining,
- offset_ptr,
- max_chars);
+ if (input->is_ascii_representation()) {
+ SeqAsciiString* str = SeqAsciiString::cast(input);
+ return str->SeqAsciiStringReadBlock(&rbb->remaining,
+ offset_ptr,
+ max_chars);
} else {
- TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
- offset_ptr,
- max_chars);
+ SeqTwoByteString* str = SeqTwoByteString::cast(input);
+ str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
+ offset_ptr,
+ max_chars);
return rbb->util_buffer;
}
case kConsStringTag:
offset_ptr,
max_chars);
case kExternalStringTag:
- if (input->is_ascii()) {
+ if (input->is_ascii_representation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
switch (input->representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii()) {
- AsciiString::cast(input)->AsciiStringReadBlockIntoBuffer(rbb,
+ if (input->is_ascii_representation()) {
+ SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
return;
} else {
- TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
+ SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
return;
max_chars);
return;
case kExternalStringTag:
- if (input->is_ascii()) {
+ if (input->is_ascii_representation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
}
+template <typename IteratorA, typename IteratorB>
+static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
+ // General slow case check. We know that the ia and ib iterators
+ // have the same length.
+ while (ia->has_more()) {
+ uc32 ca = ia->GetNext();
+ uc32 cb = ib->GetNext();
+ if (ca != cb)
+ return false;
+ }
+ return true;
+}
+
+
+static StringInputBuffer string_compare_buffer_b;
+
+
+template <typename IteratorA>
+static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
+ if (b->IsFlat()) {
+ if (b->IsAsciiRepresentation()) {
+ VectorIterator<const char> ib(b->ToAsciiVector());
+ return CompareStringContents(ia, &ib);
+ } else {
+ VectorIterator<const uc16> ib(b->ToUC16Vector());
+ return CompareStringContents(ia, &ib);
+ }
+ } else {
+ string_compare_buffer_b.Reset(0, b);
+ return CompareStringContents(ia, &string_compare_buffer_b);
+ }
+}
+
+
+static StringInputBuffer string_compare_buffer_a;
+
+
bool String::SlowEquals(String* other) {
// Fast check: negative check with lengths.
int len = length();
if (Hash() != other->Hash()) return false;
}
- // Fast case: avoid input buffers for small strings.
- const int kMaxLenthForFastCaseCheck = 5;
- for (int i = 0; i < kMaxLenthForFastCaseCheck; i++) {
- if (Get(i) != other->Get(i)) return false;
- if (i + 1 == len) return true;
- }
-
- // General slow case check.
- static StringInputBuffer buf1;
- static StringInputBuffer buf2;
- buf1.Reset(kMaxLenthForFastCaseCheck, this);
- buf2.Reset(kMaxLenthForFastCaseCheck, other);
- while (buf1.has_more()) {
- if (buf1.GetNext() != buf2.GetNext()) {
- return false;
+ if (this->IsFlat()) {
+ if (this->IsAsciiRepresentation()) {
+ VectorIterator<const char> buf1(this->ToAsciiVector());
+ return CompareStringContentsPartial(&buf1, other);
+ } else {
+ VectorIterator<const uc16> buf1(this->ToUC16Vector());
+ return CompareStringContentsPartial(&buf1, other);
}
+ } else {
+ string_compare_buffer_a.Reset(0, this);
+ return CompareStringContentsPartial(&string_compare_buffer_a, other);
}
- return true;
}
// - GlobalContext
// - String
// - SeqString
-// - AsciiString
-// - TwoByteString
+// - SeqAsciiString
+// - SeqTwoByteString
// - ConsString
// - SlicedString
// - ExternalString
// 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) \
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) \
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();
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();
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();
// 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) {
static const int kHeaderSize = String::kSize;
// Support for StringInputBuffer.
- inline void AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
- unsigned* offset,
- unsigned chars);
- inline const unibrow::byte* AsciiStringReadBlock(unsigned* remaining,
- unsigned* offset,
- unsigned chars);
+ inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+ unsigned* offset,
+ unsigned chars);
+ 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) {
static const int kHeaderSize = String::kSize;
// Support for StringInputBuffer.
- inline void TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
- unsigned* offset_ptr,
- unsigned chars);
+ inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+ unsigned* offset_ptr,
+ unsigned chars);
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(TwoByteString);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
};
};
+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:
}
-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,
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);
}
// 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;
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);
return Failure::OutOfMemoryException();
}
position += element_length;
- if (ascii && !element->IsAscii()) {
+ if (ascii && !element->IsAsciiRepresentation()) {
ascii = false;
}
} else {
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);
}