i::Handle<i::String> str = Utils::OpenHandle(this);
// Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters.
- str->TryFlattenIfNotFlat(i::StringShape(*str));
+ str->TryFlattenIfNotFlat();
int end = length;
if ( (length == -1) || (length > str->length() - start) )
end = str->length() - start;
i::Handle<i::String> str = Utils::OpenHandle(this);
// Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters.
- str->TryFlattenIfNotFlat(i::StringShape(*str));
+ str->TryFlattenIfNotFlat();
int end = length;
if ( (length == -1) || (length > str->length() - start) )
end = str->length() - start;
bool v8::String::IsExternal() const {
EnsureInitialized("v8::String::IsExternal()");
i::Handle<i::String> str = Utils::OpenHandle(this);
- i::StringShape shape(*str);
- return shape.IsExternalTwoByte();
+ return i::StringShape(*str).IsExternalTwoByte();
}
bool v8::String::IsExternalAscii() const {
EnsureInitialized("v8::String::IsExternalAscii()");
i::Handle<i::String> str = Utils::OpenHandle(this);
- i::StringShape shape(*str);
- return shape.IsExternalAscii();
+ return i::StringShape(*str).IsExternalAscii();
}
"_Log"}
};
Handle<String> name = node->name();
- StringShape shape(*name);
- if (name->length(shape) > 0 && name->Get(shape, 0) == '_') {
+ if (name->length() > 0 && name->Get(0) == '_') {
for (unsigned i = 0;
i < sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
i++) {
static inline int GetChar(String* str, int index) {
- StringShape shape(str);
- return str->Get(shape, index);
+ return str->Get(index);
}
static inline const char* GetCString(String* str, int index) {
- StringShape shape(str);
- int length = str->length(shape);
+ int length = str->length();
char* result = NewArray<char>(length + 1);
for (int i = index; i < length; i++) {
- uc16 c = str->Get(shape, i);
+ uc16 c = str->Get(i);
if (c <= 127) {
result[i - index] = static_cast<char>(c);
} else {
static inline bool IsSpace(String* str, int index) {
- StringShape shape(str);
- return Scanner::kIsWhiteSpace.get(str->Get(shape, index));
+ return Scanner::kIsWhiteSpace.get(str->Get(index));
}
Handle<String> Factory::NewConsString(Handle<String> first,
- StringShape first_shape,
- Handle<String> second,
- StringShape second_shape) {
- if (first->length(first_shape) == 0) return second;
- if (second->length(second_shape) == 0) return first;
+ Handle<String> second) {
+ if (first->length() == 0) return second;
+ if (second->length() == 0) return first;
CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
}
// Create a new cons string object which consists of a pair of strings.
static Handle<String> NewConsString(Handle<String> first,
- StringShape first_shape,
- Handle<String> second,
- StringShape second_shape);
+ Handle<String> second);
// Create a new sliced string object which represents a substring of a
// backing string.
void FlattenString(Handle<String> string) {
- CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat(StringShape(*string)));
- ASSERT(string->IsFlat(StringShape(*string)));
+ CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat());
+ ASSERT(string->IsFlat());
}
void Heap::GarbageCollectionPrologue() {
- RegExpImpl::NewSpaceCollectionPrologue();
gc_count_++;
#ifdef DEBUG
ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
ClearKeyedLookupCache();
CompilationCache::MarkCompactPrologue();
- RegExpImpl::OldSpaceCollectionPrologue();
Top::MarkCompactPrologue(is_compacting);
ThreadManager::MarkCompactPrologue(is_compacting);
Object* Heap::AllocateConsString(String* first,
String* second) {
- StringShape first_shape(first);
- StringShape second_shape(second);
- int first_length = first->length(first_shape);
- int second_length = second->length(second_shape);
+ int first_length = first->length();
+ int second_length = second->length();
int length = first_length + second_length;
- bool is_ascii = first_shape.IsAsciiRepresentation()
- && second_shape.IsAsciiRepresentation();
+ bool is_ascii = StringShape(first).IsAsciiRepresentation()
+ && StringShape(second).IsAsciiRepresentation();
// If the resulting string is small make a flat string.
if (length < String::kMinNonFlatLength) {
- ASSERT(first->IsFlat(first_shape));
- ASSERT(second->IsFlat(second_shape));
+ ASSERT(first->IsFlat());
+ ASSERT(second->IsFlat());
if (is_ascii) {
Object* result = AllocateRawAsciiString(length);
if (result->IsFailure()) return result;
// Copy the characters into the new object.
char* dest = SeqAsciiString::cast(result)->GetChars();
- String::WriteToFlat(first, first_shape, dest, 0, first_length);
- String::WriteToFlat(second,
- second_shape,
- dest + first_length,
- 0,
- second_length);
+ String::WriteToFlat(first, dest, 0, first_length);
+ String::WriteToFlat(second, dest + first_length, 0, second_length);
return result;
} else {
Object* result = AllocateRawTwoByteString(length);
if (result->IsFailure()) return result;
// Copy the characters into the new object.
uc16* dest = SeqTwoByteString::cast(result)->GetChars();
- String::WriteToFlat(first, first_shape, dest, 0, first_length);
- String::WriteToFlat(second,
- second_shape,
- dest + first_length,
- 0,
- second_length);
+ String::WriteToFlat(first, dest, 0, first_length);
+ String::WriteToFlat(second, dest + first_length, 0, second_length);
return result;
}
}
Object* Heap::AllocateSlicedString(String* buffer,
int start,
int end) {
- StringShape buffer_shape(buffer);
int length = end - start;
// If the resulting string is small make a sub string.
if (end - start <= String::kMinNonFlatLength) {
- return Heap::AllocateSubString(buffer, buffer_shape, start, end);
+ return Heap::AllocateSubString(buffer, start, end);
}
Map* map;
if (length <= String::kMaxShortStringSize) {
- map = buffer_shape.IsAsciiRepresentation() ?
+ map = StringShape(buffer).IsAsciiRepresentation() ?
short_sliced_ascii_string_map() :
short_sliced_string_map();
} else if (length <= String::kMaxMediumStringSize) {
- map = buffer_shape.IsAsciiRepresentation() ?
+ map = StringShape(buffer).IsAsciiRepresentation() ?
medium_sliced_ascii_string_map() :
medium_sliced_string_map();
} else {
- map = buffer_shape.IsAsciiRepresentation() ?
+ map = StringShape(buffer).IsAsciiRepresentation() ?
long_sliced_ascii_string_map() :
long_sliced_string_map();
}
Object* Heap::AllocateSubString(String* buffer,
- StringShape buffer_shape,
int start,
int end) {
int length = end - start;
if (length == 1) {
return Heap::LookupSingleCharacterStringFromCode(
- buffer->Get(buffer_shape, start));
+ buffer->Get(start));
}
// Make an attempt to flatten the buffer to reduce access time.
- if (!buffer->IsFlat(buffer_shape)) {
- buffer->TryFlatten(buffer_shape);
- buffer_shape = StringShape(buffer);
+ if (!buffer->IsFlat()) {
+ buffer->TryFlatten();
}
- Object* result = buffer_shape.IsAsciiRepresentation()
+ Object* result = StringShape(buffer).IsAsciiRepresentation()
? AllocateRawAsciiString(length)
: AllocateRawTwoByteString(length);
if (result->IsFailure()) return result;
// Copy the characters into the new object.
String* string_result = String::cast(result);
- StringShape result_shape(string_result);
StringHasher hasher(length);
int i = 0;
for (; i < length && hasher.is_array_index(); i++) {
- uc32 c = buffer->Get(buffer_shape, start + i);
+ uc32 c = buffer->Get(start + i);
hasher.AddCharacter(c);
- string_result->Set(result_shape, i, c);
+ string_result->Set(i, c);
}
for (; i < length; i++) {
- uc32 c = buffer->Get(buffer_shape, start + i);
+ uc32 c = buffer->Get(start + i);
hasher.AddCharacterNoIndex(c);
- string_result->Set(result_shape, i, c);
+ string_result->Set(i, c);
}
string_result->set_length_field(hasher.GetHashField());
return result;
Object* result = Heap::AllocateRawTwoByteString(1);
if (result->IsFailure()) return result;
String* answer = String::cast(result);
- answer->Set(StringShape(answer), 0, code);
+ answer->Set(0, code);
return answer;
}
// Convert and copy the characters into the new object.
String* string_result = String::cast(result);
decoder->Reset(string.start(), string.length());
- StringShape result_shape(string_result);
for (int i = 0; i < chars; i++) {
uc32 r = decoder->GetNext();
- string_result->Set(result_shape, i, r);
+ string_result->Set(i, r);
}
return result;
}
// Copy the characters into the new object, which may be either ASCII or
// UTF-16.
String* string_result = String::cast(result);
- StringShape result_shape(string_result);
for (int i = 0; i < string.length(); i++) {
- string_result->Set(result_shape, i, string[i]);
+ string_result->Set(i, string[i]);
}
return result;
}
reinterpret_cast<HeapObject*>(result)->set_map(map);
// The hash value contains the length of the string.
String* answer = String::cast(result);
- StringShape answer_shape(answer);
answer->set_length_field(length_field);
ASSERT_EQ(size, answer->Size());
// Fill in the characters.
for (int i = 0; i < chars; i++) {
- answer->Set(answer_shape, i, buffer->GetNext());
+ answer->Set(i, buffer->GetNext());
}
return answer;
}
// failed.
// Please note this does not perform a garbage collection.
static Object* AllocateSubString(String* buffer,
- StringShape buffer_shape,
int start,
int end);
Handle<String> subject,
int* registers,
int start_position) {
- ASSERT(subject->IsFlat(StringShape(*subject)));
+ ASSERT(subject->IsFlat());
AssertNoAllocation a;
const byte* code_base = code_array->GetDataStartAddress();
- StringShape subject_shape(*subject);
uc16 previous_char = '\n';
- if (subject_shape.IsAsciiRepresentation()) {
+ if (StringShape(*subject).IsAsciiRepresentation()) {
Vector<const char> subject_vector = subject->ToAsciiVector();
if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(code_base,
namespace v8 { namespace internal {
-String* RegExpImpl::last_ascii_string_ = NULL;
-String* RegExpImpl::two_byte_cached_string_ = NULL;
-
-
-void RegExpImpl::NewSpaceCollectionPrologue() {
- // The two byte string is always in the old space. The Ascii string may be
- // in either place. If it is in the old space we don't need to do anything.
- if (Heap::InNewSpace(last_ascii_string_)) {
- // Invalidate the cache.
- last_ascii_string_ = NULL;
- two_byte_cached_string_ = NULL;
- }
-}
-
-
-void RegExpImpl::OldSpaceCollectionPrologue() {
- last_ascii_string_ = NULL;
- two_byte_cached_string_ = NULL;
-}
-
-
Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
Handle<String> pattern,
Handle<String> flags,
}
-// Converts a source string to a 16 bit flat string or a SlicedString containing
-// a 16 bit flat string).
-Handle<String> RegExpImpl::CachedStringToTwoByte(Handle<String> subject) {
- if (*subject == last_ascii_string_) {
- ASSERT(two_byte_cached_string_ != NULL);
- return Handle<String>(String::cast(two_byte_cached_string_));
- }
- Handle<String> two_byte_string = StringToTwoByte(subject);
- last_ascii_string_ = *subject;
- two_byte_cached_string_ = *two_byte_string;
- return two_byte_string;
-}
-
-
-// Converts a source string to a 16 bit flat string or a SlicedString containing
-// a 16 bit flat string).
-Handle<String> RegExpImpl::StringToTwoByte(Handle<String> pattern) {
- StringShape shape(*pattern);
- if (!pattern->IsFlat(shape)) {
- FlattenString(pattern);
- shape = StringShape(*pattern);
- }
- Handle<String> flat_string(shape.IsCons() ?
- String::cast(ConsString::cast(*pattern)->first()) :
- *pattern);
- ASSERT(flat_string->IsString());
- StringShape flat_shape(*flat_string);
- ASSERT(!flat_shape.IsCons());
- ASSERT(flat_shape.IsSequential() ||
- flat_shape.IsSliced() ||
- flat_shape.IsExternal());
- if (!flat_shape.IsAsciiRepresentation()) {
- return flat_string;
- }
-
- int len = flat_string->length(flat_shape);
- Handle<String> two_byte_string =
- Factory::NewRawTwoByteString(len, TENURED);
- uc16* dest = SeqTwoByteString::cast(*two_byte_string)->GetChars();
- String::WriteToFlat(*flat_string, flat_shape, dest, 0, len);
- return two_byte_string;
-}
-
-
static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) {
int flags = JSRegExp::NONE;
- StringShape shape(*str);
- for (int i = 0; i < str->length(shape); i++) {
- switch (str->Get(shape, i)) {
+ for (int i = 0; i < str->length(); i++) {
+ switch (str->Get(i)) {
case 'i':
flags |= JSRegExp::IGNORE_CASE;
break;
JSRegExp::Flags flags = re->GetFlags();
Handle<String> pattern(re->Pattern());
- if (!pattern->IsFlat(StringShape(*pattern))) {
+ if (!pattern->IsFlat()) {
FlattenString(pattern);
}
}
#endif
- if (!subject->IsFlat(StringShape(*subject))) {
+ if (!subject->IsFlat()) {
FlattenString(subject);
}
int result_length = 0;
Handle<Object> matches;
- if (!subject->IsFlat(StringShape(*subject))) {
+ if (!subject->IsFlat()) {
FlattenString(subject);
}
int previous_index,
int* offsets_vector,
int offsets_vector_length) {
- StringShape shape(*subject);
- ASSERT(subject->IsFlat(shape));
- bool is_ascii = shape.IsAsciiRepresentation();
+ ASSERT(subject->IsFlat());
+ bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
bool rc;
Handle<String> original_subject = subject;
Handle<String> subject,
Handle<JSArray> lastMatchInfo);
- static void NewSpaceCollectionPrologue();
- static void OldSpaceCollectionPrologue();
-
- // Converts a source string to a 16 bit flat string. The string
- // will be either sequential or it will be a SlicedString backed
- // by a flat string.
- static Handle<String> StringToTwoByte(Handle<String> pattern);
- static Handle<String> CachedStringToTwoByte(Handle<String> pattern);
-
// Offsets in the lastMatchInfo array.
static const int kLastCaptureCount = 0;
static const int kLastSubject = 1;
// Append a heap string.
void LogMessageBuilder::Append(String* str) {
AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
- StringShape shape(str);
- int length = str->length(shape);
+ int length = str->length();
for (int i = 0; i < length; i++) {
- Append(static_cast<char>(str->Get(shape, i)));
+ Append(static_cast<char>(str->Get(i)));
}
}
void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
- StringShape shape(str);
- int len = str->length(shape);
+ int len = str->length();
if (len > 0x1000)
len = 0x1000;
if (show_impl_info) {
- Append(shape.IsAsciiRepresentation() ? 'a' : '2');
- if (shape.IsExternal())
+ Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
+ if (StringShape(str).IsExternal())
Append('e');
- if (shape.IsSymbol())
+ if (StringShape(str).IsSymbol())
Append('#');
Append(":%i:", str->length());
}
for (int i = 0; i < len; i++) {
- uc32 c = str->Get(shape, i);
+ uc32 c = str->Get(i);
if (c > 0xff) {
Append("\\u%04x", c);
} else if (c < 32 || c > 126) {
void String::StringPrint() {
- StringShape shape(this);
- if (shape.IsSymbol()) {
+ if (StringShape(this).IsSymbol()) {
PrintF("#");
- } else if (shape.IsCons()) {
+ } else if (StringShape(this).IsCons()) {
PrintF("c\"");
} else {
PrintF("\"");
}
for (int i = 0; i < length(); i++) {
- PrintF("%c", Get(shape, i));
+ PrintF("%c", Get(i));
}
- if (!shape.IsSymbol()) PrintF("\"");
+ if (!StringShape(this).IsSymbol()) PrintF("\"");
}
bool Object::IsSeqAsciiString() {
if (!IsString()) return false;
- StringShape shape(String::cast(this));
- return shape.IsSequential() && shape.IsAsciiRepresentation();
+ return StringShape(String::cast(this)).IsSequential() &&
+ StringShape(String::cast(this)).IsAsciiRepresentation();
}
bool Object::IsSeqTwoByteString() {
if (!IsString()) return false;
- StringShape shape(String::cast(this));
- return shape.IsSequential() && shape.IsTwoByteRepresentation();
+ return StringShape(String::cast(this)).IsSequential() &&
+ StringShape(String::cast(this)).IsTwoByteRepresentation();
}
bool Object::IsExternalAsciiString() {
if (!IsString()) return false;
- StringShape shape(String::cast(this));
- return shape.IsExternal() && shape.IsAsciiRepresentation();
+ return StringShape(String::cast(this)).IsExternal() &&
+ StringShape(String::cast(this)).IsAsciiRepresentation();
}
bool Object::IsExternalTwoByteString() {
if (!IsString()) return false;
- StringShape shape(String::cast(this));
- return shape.IsExternal() && shape.IsTwoByteRepresentation();
+ return StringShape(String::cast(this)).IsExternal() &&
+ StringShape(String::cast(this)).IsTwoByteRepresentation();
}
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 (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) {
+ if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
return LinearSearch(name, nof);
}
bool String::Equals(String* other) {
if (other == this) return true;
- StringShape this_shape(this);
- StringShape other_shape(other);
- if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false;
- return SlowEquals(this_shape, other, other_shape);
+ if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
+ return false;
+ }
+ return SlowEquals(other);
}
-int String::length(StringShape shape) {
- ASSERT(shape.type() == StringShape(this).type());
+int String::length() {
uint32_t len = READ_INT_FIELD(this, kLengthOffset);
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
ASSERT(kLongStringTag == 0);
- return len >> (shape.size_tag() + kLongLengthShift);
-}
-
-
-int String::length() {
- return length(StringShape(this));
+ return len >> (StringShape(this).size_tag() + kLongLengthShift);
}
ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
ASSERT(kLongStringTag == 0);
- StringShape shape(this);
WRITE_INT_FIELD(this,
kLengthOffset,
- value << (shape.size_tag() + kLongLengthShift));
+ value << (StringShape(this).size_tag() + kLongLengthShift));
}
}
-Object* String::TryFlattenIfNotFlat(StringShape shape) {
- ASSERT(shape.type() == StringShape(this).type());
+Object* String::TryFlattenIfNotFlat() {
// 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.
- if (!IsFlat(shape)) {
- return TryFlatten(shape);
+ if (!IsFlat()) {
+ return TryFlatten();
}
return this;
}
-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()) {
+uint16_t String::Get(int index) {
+ ASSERT(index >= 0 && index < length());
+ switch (StringShape(this).full_representation_tag()) {
case kSeqStringTag | kAsciiStringTag:
return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
case kSeqStringTag | kTwoByteStringTag:
}
-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());
+void String::Set(int index, uint16_t value) {
+ ASSERT(index >= 0 && index < length());
+ ASSERT(StringShape(this).IsSequential());
- return shape.IsAsciiRepresentation()
+ return StringShape(this).IsAsciiRepresentation()
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
}
-bool String::IsFlat(StringShape shape) {
- ASSERT(shape.type() == StringShape(this).type());
- switch (shape.representation_tag()) {
+bool String::IsFlat() {
+ switch (StringShape(this).representation_tag()) {
case kConsStringTag: {
String* second = ConsString::cast(this)->second();
// Only flattened strings have second part empty.
return second->length() == 0;
}
case kSlicedStringTag: {
- StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
- StringRepresentationTag tag = slice_shape.representation_tag();
+ StringRepresentationTag tag =
+ StringShape(SlicedString::cast(this)->buffer()).representation_tag();
return tag == kSeqStringTag || tag == kExternalStringTag;
}
default:
}
-int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
+int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
// Use the map (and not 'this') to compute the size tag, since
// TwoByteStringSize is called during GC when maps are encoded.
- length >>= shape.size_tag() + kLongLengthShift;
+ length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
return SizeFor(length);
}
-int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
+int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
// Use the map (and not 'this') to compute the size tag, since
// AsciiStringSize is called during GC when maps are encoded.
- length >>= shape.size_tag() + kLongLengthShift;
+ length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
return SizeFor(length);
}
// We don't use the BBC's overcorrect "an historic occasion" though if
// you speak a dialect you may well say "an 'istoric occasion".
static bool AnWord(String* str) {
- StringShape shape(str);
- if (str->length(shape) == 0) return false; // A nothing.
- int c0 = str->Get(shape, 0);
- int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0;
+ if (str->length() == 0) return false; // A nothing.
+ int c0 = str->Get(0);
+ int c1 = str->length() > 1 ? str->Get(1) : 0;
if (c0 == 'U') {
if (c1 > 'Z') {
return true; // An Umpire, but a UTF8String, a U.
}
-Object* String::TryFlatten(StringShape shape) {
+Object* String::TryFlatten() {
#ifdef DEBUG
// Do not attempt to flatten in debug mode when allocation is not
// allowed. This is to avoid an assertion failure when allocating.
if (!Heap::IsAllocationAllowed()) return this;
#endif
- switch (shape.representation_tag()) {
+ switch (StringShape(this).representation_tag()) {
case kSlicedStringTag: {
SlicedString* ss = SlicedString::cast(this);
// The SlicedString constructor should ensure that there are no
// SlicedStrings.
String* buf = ss->buffer();
ASSERT(!buf->IsSlicedString());
- Object* ok = buf->TryFlatten(StringShape(buf));
+ Object* ok = buf->TryFlatten();
if (ok->IsFailure()) return ok;
// Under certain circumstances (TryFlattenIfNotFlat fails in
// String::Slice) we can have a cons string under a slice.
// cons string is in old space. It can never get GCed until there is
// an old space GC.
PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
- int len = length(shape);
+ int len = length();
Object* object;
String* result;
- if (shape.IsAsciiRepresentation()) {
+ if (StringShape(this).IsAsciiRepresentation()) {
object = Heap::AllocateRawAsciiString(len, tenure);
if (object->IsFailure()) return object;
result = String::cast(object);
String* first = cs->first();
- StringShape first_shape(first);
- int first_length = first->length(first_shape);
+ int first_length = first->length();
char* dest = SeqAsciiString::cast(result)->GetChars();
- WriteToFlat(first, first_shape, dest, 0, first_length);
+ WriteToFlat(first, dest, 0, first_length);
String* second = cs->second();
WriteToFlat(second,
- StringShape(second),
dest + first_length,
0,
len - first_length);
result = String::cast(object);
uc16* dest = SeqTwoByteString::cast(result)->GetChars();
String* first = cs->first();
- StringShape first_shape(first);
- int first_length = first->length(first_shape);
- WriteToFlat(first, first_shape, dest, 0, first_length);
+ int first_length = first->length();
+ WriteToFlat(first, dest, 0, first_length);
String* second = cs->second();
WriteToFlat(second,
- StringShape(second),
dest + first_length,
0,
len - first_length);
void String::StringShortPrint(StringStream* accumulator) {
- StringShape shape(this);
- int len = length(shape);
+ int len = length();
if (len > kMaxMediumStringSize) {
accumulator->Add("<Very long string[%u]>", len);
return;
}
buf.Reset(this);
if (ascii) {
- accumulator->Add("<String[%u]: ", length(shape));
+ accumulator->Add("<String[%u]: ", length());
for (int i = 0; i < len; i++) {
accumulator->Put(buf.GetNext());
}
} else {
// Backslash indicates that the string contains control
// characters and that backslashes are therefore escaped.
- accumulator->Add("<String[%u]\\: ", length(shape));
+ accumulator->Add("<String[%u]\\: ", length());
for (int i = 0; i < len; i++) {
int c = buf.GetNext();
if (c == '\n') {
if (instance_type < FIRST_NONSTRING_TYPE
&& (StringShape(instance_type).IsSequential())) {
- StringShape shape(instance_type);
- if (shape.IsAsciiRepresentation()) {
- return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(shape);
+ if (StringShape(instance_type).IsAsciiRepresentation()) {
+ SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
+ return seq_ascii_this->SeqAsciiStringSize(instance_type);
} else {
SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
- return self->SeqTwoByteStringSize(shape);
+ return self->SeqTwoByteStringSize(instance_type);
}
}
}
// Try to flatten before operating on the string.
- name->TryFlattenIfNotFlat(StringShape(name));
+ name->TryFlattenIfNotFlat();
// Check if there is an API defined callback object which prohibits
// callback overwriting in this object or it's prototype chain.
int String::Utf8Length() {
- StringShape shape(this);
- if (shape.IsAsciiRepresentation()) return length(shape);
+ if (StringShape(this).IsAsciiRepresentation()) 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)
// so it's still a good idea.
- TryFlattenIfNotFlat(shape); // shape is now no longer valid.
+ TryFlattenIfNotFlat();
Access<StringInputBuffer> buffer(&string_input_buffer);
buffer->Reset(0, this);
int result = 0;
Vector<const char> String::ToAsciiVector() {
- StringShape shape(this);
- ASSERT(shape.IsAsciiRepresentation());
- ASSERT(IsFlat(shape));
+ ASSERT(StringShape(this).IsAsciiRepresentation());
+ ASSERT(IsFlat());
int offset = 0;
- int length = this->length(shape);
- StringRepresentationTag string_tag = shape.representation_tag();
+ int length = this->length();
+ StringRepresentationTag string_tag = StringShape(this).representation_tag();
String* string = this;
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
string = sliced->buffer();
- shape = StringShape(string);
- string_tag = shape.representation_tag();
+ string_tag = StringShape(string).representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
- ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+ ASSERT(cons->second()->length() == 0);
string = cons->first();
- shape = StringShape(string);
- string_tag = shape.representation_tag();
+ string_tag = StringShape(string).representation_tag();
}
if (string_tag == kSeqStringTag) {
SeqAsciiString* seq = SeqAsciiString::cast(string);
Vector<const uc16> String::ToUC16Vector() {
- StringShape shape(this);
- ASSERT(shape.IsTwoByteRepresentation());
- ASSERT(IsFlat(shape));
+ ASSERT(StringShape(this).IsTwoByteRepresentation());
+ ASSERT(IsFlat());
int offset = 0;
- int length = this->length(shape);
- StringRepresentationTag string_tag = shape.representation_tag();
+ int length = this->length();
+ StringRepresentationTag string_tag = StringShape(this).representation_tag();
String* string = this;
if (string_tag == kSlicedStringTag) {
SlicedString* sliced = SlicedString::cast(string);
offset += sliced->start();
string = String::cast(sliced->buffer());
- shape = StringShape(string);
- string_tag = shape.representation_tag();
+ string_tag = StringShape(string).representation_tag();
} else if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
- ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+ ASSERT(cons->second()->length() == 0);
string = cons->first();
- shape = StringShape(string);
- string_tag = shape.representation_tag();
+ string_tag = StringShape(string).representation_tag();
}
if (string_tag == kSeqStringTag) {
SeqTwoByteString* seq = SeqTwoByteString::cast(string);
const uc16* String::GetTwoByteData(unsigned start) {
- StringShape shape(this);
- ASSERT(!shape.IsAsciiRepresentation());
- switch (shape.representation_tag()) {
+ ASSERT(!StringShape(this).IsAsciiRepresentation());
+ switch (StringShape(this).representation_tag()) {
case kSeqStringTag:
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
case kExternalStringTag:
if (StringShape(buffer).IsCons()) {
ConsString* cs = ConsString::cast(buffer);
// Flattened string.
- ASSERT(cs->second()->length(StringShape(cs->second())) == 0);
+ ASSERT(cs->second()->length() == 0);
buffer = cs->first();
}
return buffer->GetTwoByteData(start + sliced_string->start());
while (true) {
String* left = current->first();
- StringShape left_shape(left);
- unsigned left_length = (unsigned)left->length(left_shape);
+ unsigned left_length = (unsigned)left->length();
if (left_length > offset &&
(max_chars <= left_length - offset ||
(rbb->capacity <= left_length - offset &&
// the point where we switch to the -IntoBuffer routines (below) in order
// to maximize the chances of delegating a big chunk of work to the
// efficient *AsciiStringReadBlock routines.
- if (left_shape.IsCons()) {
+ if (StringShape(left).IsCons()) {
current = ConsString::cast(left);
continue;
} else {
rbb->remaining = 0;
return NULL;
}
- StringShape shape(input);
- switch (shape.representation_tag()) {
+ switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (shape.IsAsciiRepresentation()) {
+ if (StringShape(input).IsAsciiRepresentation()) {
SeqAsciiString* str = SeqAsciiString::cast(input);
return str->SeqAsciiStringReadBlock(&rbb->remaining,
offset_ptr,
offset_ptr,
max_chars);
case kExternalStringTag:
- if (shape.IsAsciiRepresentation()) {
+ if (StringShape(input).IsAsciiRepresentation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
void FlatStringReader::RefreshState() {
if (str_ == NULL) return;
Handle<String> str(str_);
- StringShape shape(*str);
- ASSERT(str->IsFlat(shape));
- is_ascii_ = shape.IsAsciiRepresentation();
+ ASSERT(str->IsFlat());
+ is_ascii_ = StringShape(*str).IsAsciiRepresentation();
if (is_ascii_) {
start_ = str->ToAsciiVector().start();
} else {
ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
- StringShape shape(input);
- ASSERT(*offset_ptr <= (unsigned)input->length(shape));
+ ASSERT(*offset_ptr <= (unsigned)input->length());
if (max_chars == 0) return;
- switch (shape.representation_tag()) {
+ switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (shape.IsAsciiRepresentation()) {
+ if (StringShape(input).IsAsciiRepresentation()) {
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
max_chars);
return;
case kExternalStringTag:
- if (shape.IsAsciiRepresentation()) {
+ if (StringShape(input).IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
unsigned capacity,
unsigned* remaining,
unsigned* offset_ptr) {
- StringShape shape(input);
- ASSERT(*offset_ptr <= (unsigned)input->length(shape));
- unsigned chars = input->length(shape) - *offset_ptr;
+ ASSERT(*offset_ptr <= (unsigned)input->length());
+ unsigned chars = input->length() - *offset_ptr;
ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
- ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
+ ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
*remaining = rbb.remaining;
return answer;
}
unsigned capacity,
unsigned* remaining,
unsigned* offset_ptr) {
- StringShape shape(*raw_input);
Handle<String> input(raw_input);
- ASSERT(*offset_ptr <= (unsigned)input->length(shape));
- unsigned chars = input->length(shape) - *offset_ptr;
+ ASSERT(*offset_ptr <= (unsigned)input->length());
+ unsigned chars = input->length() - *offset_ptr;
if (chars > capacity) chars = capacity;
ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
- ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
+ ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
*remaining = rbb.remaining;
return rbb.util_buffer;
}
while (true) {
String* left = current->first();
- StringShape left_shape(left);
- unsigned left_length = (unsigned)left->length(left_shape);
+ unsigned left_length = (unsigned)left->length();
if (left_length > offset &&
max_chars <= left_length - offset) {
// Left hand side only - iterate unless we have reached the bottom of
// the cons tree.
- if (left_shape.IsCons()) {
+ if (StringShape(left).IsCons()) {
current = ConsString::cast(left);
continue;
} else {
// Check for a flattened cons string
if (second()->length() == 0) {
String* left = first();
- return left->Get(StringShape(left), index);
+ return left->Get(index);
}
String* string = String::cast(this);
- StringShape shape(string);
while (true) {
- if (shape.IsCons()) {
+ if (StringShape(string).IsCons()) {
ConsString* cons_string = ConsString::cast(string);
String* left = cons_string->first();
- StringShape left_shape(left);
- if (left->length(left_shape) > index) {
+ if (left->length() > index) {
string = left;
- shape = left_shape;
} else {
- index -= left->length(left_shape);
+ index -= left->length();
string = cons_string->second();
- shape = StringShape(string);
}
} else {
- return string->Get(shape, index);
+ return string->Get(index);
}
}
template <typename sinkchar>
void String::WriteToFlat(String* src,
- StringShape src_shape,
sinkchar* sink,
int f,
int t) {
String* source = src;
- StringShape shape = src_shape;
int from = f;
int to = t;
while (true) {
- ASSERT(0 <= from && from <= to && to <= source->length(shape));
- switch (shape.full_representation_tag()) {
+ ASSERT(0 <= from && from <= to && to <= source->length());
+ switch (StringShape(source).full_representation_tag()) {
case kAsciiStringTag | kExternalStringTag: {
CopyChars(sink,
ExternalAsciiString::cast(source)->resource()->data() + from,
from += start;
to += start;
source = String::cast(sliced_string->buffer());
- shape = StringShape(source);
break;
}
case kAsciiStringTag | kConsStringTag:
case kTwoByteStringTag | kConsStringTag: {
ConsString* cons_string = ConsString::cast(source);
String* first = cons_string->first();
- StringShape first_shape(first);
- int boundary = first->length(first_shape);
+ int boundary = first->length();
if (to - boundary >= boundary - from) {
// Right hand side is longer. Recurse over left.
if (from < boundary) {
- WriteToFlat(first, first_shape, sink, from, boundary);
+ WriteToFlat(first, sink, from, boundary);
sink += boundary - from;
from = 0;
} else {
}
to -= boundary;
source = cons_string->second();
- shape = StringShape(source);
} else {
// Left hand side is longer. Recurse over right.
if (to > boundary) {
String* second = cons_string->second();
WriteToFlat(second,
- StringShape(second),
sink + boundary - from,
0,
to - boundary);
to = boundary;
}
source = first;
- shape = first_shape;
}
break;
}
ASSERT(index >= 0 && index < this->length());
// Delegate to the buffer string.
String* underlying = buffer();
- return underlying->Get(StringShape(underlying), start() + index);
+ return underlying->Get(start() + index);
}
template <typename IteratorA>
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
- StringShape b_shape(b);
- if (b->IsFlat(b_shape)) {
- if (b_shape.IsAsciiRepresentation()) {
+ if (b->IsFlat()) {
+ if (StringShape(b).IsAsciiRepresentation()) {
VectorIterator<char> ib(b->ToAsciiVector());
return CompareStringContents(ia, &ib);
} else {
static StringInputBuffer string_compare_buffer_a;
-bool String::SlowEquals(StringShape this_shape,
- String* other,
- StringShape other_shape) {
+bool String::SlowEquals(String* other) {
// Fast check: negative check with lengths.
- int len = length(this_shape);
- if (len != other->length(other_shape)) return false;
+ int len = length();
+ if (len != other->length()) return false;
if (len == 0) return true;
// Fast check: if hash code is computed for both strings
if (Hash() != other->Hash()) return false;
}
- if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) {
+ if (StringShape(this).IsSequentialAscii() && StringShape(other).IsSequentialAscii()) {
const char* str1 = SeqAsciiString::cast(this)->GetChars();
const char* str2 = SeqAsciiString::cast(other)->GetChars();
return CompareRawStringContents(Vector<const char>(str1, len),
Vector<const char>(str2, len));
}
- if (this->IsFlat(this_shape)) {
- if (this_shape.IsAsciiRepresentation()) {
+ if (this->IsFlat()) {
+ if (StringShape(this).IsAsciiRepresentation()) {
Vector<const char> vec1 = this->ToAsciiVector();
- if (other->IsFlat(other_shape)) {
- if (other_shape.IsAsciiRepresentation()) {
+ if (other->IsFlat()) {
+ if (StringShape(other).IsAsciiRepresentation()) {
Vector<const char> vec2 = other->ToAsciiVector();
return CompareRawStringContents(vec1, vec2);
} else {
}
} else {
Vector<const uc16> vec1 = this->ToUC16Vector();
- if (other->IsFlat(other_shape)) {
- if (other_shape.IsAsciiRepresentation()) {
+ if (other->IsFlat()) {
+ if (StringShape(other).IsAsciiRepresentation()) {
VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(other->ToAsciiVector());
return CompareStringContents(&buf1, &ib);
bool String::IsEqualTo(Vector<const char> str) {
- StringShape this_shape(this);
- int slen = length(this_shape);
+ int slen = length();
Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
decoder->Reset(str.start(), str.length());
int i;
for (i = 0; i < slen && decoder->has_more(); i++) {
uc32 r = decoder->GetNext();
- if (Get(this_shape, i) != r) return false;
+ if (Get(i) != r) return false;
}
return i == slen && !decoder->has_more();
}
bool String::SlowAsArrayIndex(uint32_t* index) {
- StringShape shape(this);
- if (length(shape) <= kMaxCachedArrayIndexLength) {
+ if (length() <= kMaxCachedArrayIndexLength) {
Hash(); // force computation of hash code
uint32_t field = length_field();
if ((field & kIsArrayIndexMask) == 0) return false;
return true;
} else {
StringInputBuffer buffer(this);
- return ComputeArrayIndex(&buffer, index, length(shape));
+ return ComputeArrayIndex(&buffer, index, length());
}
}
Object* String::Slice(int start, int end) {
- StringShape shape(this);
- if (start == 0 && end == length(shape)) return this;
- if (shape.representation_tag() == kSlicedStringTag) {
+ if (start == 0 && end == length()) return this;
+ if (StringShape(this).representation_tag() == kSlicedStringTag) {
// Translate slices of a SlicedString into slices of the
// underlying string buffer.
SlicedString* str = SlicedString::cast(this);
// if Heap::AllocateSlicedString actually returned a SlicedString. It will
// return flat strings for small slices for efficiency reasons.
String* answer = String::cast(result);
- StringShape answer_shape(answer);
- if (answer_shape.IsSliced() &&
- shape.representation_tag() == kConsStringTag) {
- TryFlatten(shape);
+ if (StringShape(answer).IsSliced() &&
+ StringShape(this).representation_tag() == kConsStringTag) {
+ TryFlatten();
// If the flatten succeeded we might as well make the sliced string point
// to the flat string rather than the cons string.
String* second = ConsString::cast(this)->second();
- if (second->length(StringShape(second)) == 0) {
+ if (second->length() == 0) {
SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
}
}
void String::PrintOn(FILE* file) {
- StringShape shape(this);
- int length = this->length(shape);
+ int length = this->length();
for (int i = 0; i < length; i++) {
- fprintf(file, "%c", Get(shape, i));
+ fprintf(file, "%c", Get(i));
}
}
Object* val = JSValue::cast(this)->value();
if (val->IsString()) {
String* str = String::cast(val);
- StringShape shape(str);
if (storage) {
- for (int i = 0; i < str->length(shape); i++) {
+ for (int i = 0; i < str->length(); i++) {
storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
}
}
- counter += str->length(shape);
+ counter += str->length();
}
}
ASSERT(!storage || storage->length() == counter);
Object* GetObject() {
// If the string is a cons string, attempt to flatten it so that
// symbols will most often be flat strings.
- StringShape shape(string_);
- if (shape.IsCons()) {
+ if (StringShape(string_).IsCons()) {
ConsString* cons_string = ConsString::cast(string_);
- cons_string->TryFlatten(shape);
+ cons_string->TryFlatten();
if (cons_string->second() == Heap::empty_string()) {
string_ = cons_string->first();
}
// to be passed by value and is immutable, but be aware that flattening a
// string can potentially alter its shape. Also be aware that a GC caused by
// something else can alter the shape of a string due to ConsString
-// shortcutting.
-//
-// Most of the methods designed to interrogate a string as to its exact nature
-// have been made into methods on StringShape in order to encourage the use of
-// StringShape. The String class has both a length() and a length(StringShape)
-// operation. The former is simpler to type, but the latter is faster if you
-// need the StringShape for some other operation immediately before or after.
+// shortcutting. Keeping these restrictions in mind has proven to be error-
+// prone and so we no longer put StringShapes in variables unless there is a
+// concrete performance benefit at that particular point in the code.
class StringShape BASE_EMBEDDED {
public:
inline explicit StringShape(String* s);
class String: public HeapObject {
public:
// Get and set the length of the string.
- // Fast version.
- inline int length(StringShape shape);
- // Easy version.
inline int length();
inline void set_length(int value);
inline void set_length_field(uint32_t value);
// Get and set individual two byte chars in the string.
- inline void Set(StringShape shape, int index, uint16_t value);
+ inline void Set(int index, uint16_t value);
// Get individual two byte char in the string. Repeated calls
// to this method are not efficient unless the string is flat.
- inline uint16_t Get(StringShape shape, int index);
+ inline uint16_t Get(int index);
// Try to flatten the top level ConsString that is hiding behind this
// string. This is a no-op unless the string is a ConsString or a
// SlicedString. Flatten mutates the ConsString and might return a
// failure.
- Object* TryFlatten(StringShape shape);
+ Object* TryFlatten();
// Try to flatten the string. Checks first inline to see if it is necessary.
// Do not handle allocation failures. After calling TryFlattenIfNotFlat, the
// string could still be a ConsString, in which case a failure is returned.
// Use FlattenString from Handles.cc to be sure to flatten.
- inline Object* TryFlattenIfNotFlat(StringShape shape);
+ inline Object* TryFlattenIfNotFlat();
Vector<const char> ToAsciiVector();
Vector<const uc16> ToUC16Vector();
void StringPrint();
void StringVerify();
#endif
- inline bool IsFlat(StringShape shape);
+ inline bool IsFlat();
// Layout description.
static const int kLengthOffset = HeapObject::kHeaderSize;
// Helper function for flattening strings.
template <typename sinkchar>
static void WriteToFlat(String* source,
- StringShape shape,
sinkchar* sink,
int from,
int to);
private:
// Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat.
- bool SlowEquals(StringShape this_shape,
- String* other,
- StringShape other_shape);
+ bool SlowEquals(String* other);
// Slow case of AsArrayIndex.
bool SlowAsArrayIndex(uint32_t* index);
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of an AsciiString
// instance.
- inline int SeqAsciiStringSize(StringShape shape);
+ inline int SeqAsciiStringSize(InstanceType instance_type);
// Computes the size for an AsciiString instance of a given length.
static int SizeFor(int length) {
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of a TwoByteString
// instance.
- inline int SeqTwoByteStringSize(StringShape shape);
+ inline int SeqTwoByteStringSize(InstanceType instance_type);
// Computes the size for a TwoByteString instance of a given length.
static int SizeFor(int length) {
ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::parse);
- StringShape shape(*source);
- Counters::total_parse_size.Increment(source->length(shape));
+ Counters::total_parse_size.Increment(source->length());
// Initialize parser state.
- source->TryFlattenIfNotFlat(shape);
+ source->TryFlattenIfNotFlat();
scanner_.Init(source, stream, 0);
ASSERT(target_stack_ == NULL);
bool is_expression) {
ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::parse_lazy);
- source->TryFlattenIfNotFlat(StringShape(*source));
- StringShape shape(*source);
- Counters::total_parse_size.Increment(source->length(shape));
+ source->TryFlattenIfNotFlat();
+ Counters::total_parse_size.Increment(source->length());
SafeStringInputBuffer buffer(source.location());
// Initialize parser state.
Object* object = *value;
if (object->IsString()) {
String* string = String::cast(object);
- StringShape shape(string);
if (quote) Print("\"");
- for (int i = 0; i < string->length(shape); i++) {
- Print("%c", string->Get(shape, i));
+ for (int i = 0; i < string->length(); i++) {
+ Print("%c", string->Get(i));
}
if (quote) Print("\"");
} else if (object == Heap::null_value()) {
int* offsets_vector,
int offsets_vector_length,
int previous_index) {
- StringShape shape(*subject);
-
// Character offsets into string.
int start_offset = previous_index;
- int end_offset = subject->length(shape);
+ int end_offset = subject->length();
- if (shape.IsCons()) {
+ if (StringShape(*subject).IsCons()) {
subject =
Handle<String>(String::cast(ConsString::cast(*subject)->first()));
- } else if (shape.IsSliced()) {
+ } else if (StringShape(*subject).IsSliced()) {
SlicedString* slice = SlicedString::cast(*subject);
start_offset += slice->start();
end_offset += slice->start();
}
// String is now either Sequential or External
- StringShape flatshape(*subject);
- bool is_ascii = flatshape.IsAsciiRepresentation();
+ bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
int char_size_shift = is_ascii ? 0 : 1;
RegExpMacroAssemblerIA32::Result res;
- if (flatshape.IsExternal()) {
+ if (StringShape(*subject).IsExternal()) {
const byte* address;
if (is_ascii) {
ExternalAsciiString* ext = ExternalAsciiString::cast(*subject);
// Flatten the string. If someone wants to get a char at an index
// in a cons string, it is likely that more indices will be
// accessed.
- subject->TryFlattenIfNotFlat(StringShape(subject));
- StringShape shape(subject);
- if (i >= static_cast<uint32_t>(subject->length(shape))) {
+ subject->TryFlattenIfNotFlat();
+ if (i >= static_cast<uint32_t>(subject->length())) {
return Heap::nan_value();
}
- return Smi::FromInt(subject->Get(shape, i));
+ return Smi::FromInt(subject->Get(i));
}
template <typename schar>
static inline void StringBuilderConcatHelper(String*,
- StringShape,
schar*,
FixedArray*,
int);
void AddString(Handle<String> string) {
- StringShape shape(*string);
- int length = string->length(shape);
+ int length = string->length();
ASSERT(length > 0);
AddElement(*string);
- if (!shape.IsAsciiRepresentation()) {
+ if (!StringShape(*string).IsAsciiRepresentation()) {
is_ascii_ = false;
}
IncrementCharacterCount(length);
SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
char* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
- StringShape(*subject_),
char_buffer,
*parts_,
part_count_);
SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
uc16* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
- StringShape(*subject_),
char_buffer,
*parts_,
part_count_);
void CompiledReplacement::Compile(Handle<String> replacement,
int capture_count,
int subject_length) {
- StringShape shape(*replacement);
- ASSERT(replacement->IsFlat(shape));
- if (shape.IsAsciiRepresentation()) {
+ ASSERT(replacement->IsFlat());
+ if (StringShape(*replacement).IsAsciiRepresentation()) {
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
replacement->ToAsciiVector(),
capture_count,
subject_length);
} else {
- ASSERT(shape.IsTwoByteRepresentation());
+ ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
JSRegExp* regexp,
String* replacement,
JSArray* last_match_info) {
- ASSERT(subject->IsFlat(StringShape(subject)));
- ASSERT(replacement->IsFlat(StringShape(replacement)));
+ ASSERT(subject->IsFlat());
+ ASSERT(replacement->IsFlat());
HandleScope handles;
ASSERT(args.length() == 4);
CONVERT_CHECKED(String, subject, args[0]);
- StringShape subject_shape(subject);
- if (!subject->IsFlat(subject_shape)) {
- Object* flat_subject = subject->TryFlatten(subject_shape);
+ if (!subject->IsFlat()) {
+ Object* flat_subject = subject->TryFlatten();
if (flat_subject->IsFailure()) {
return flat_subject;
}
}
CONVERT_CHECKED(String, replacement, args[2]);
- StringShape replacement_shape(replacement);
- if (!replacement->IsFlat(replacement_shape)) {
- Object* flat_replacement = replacement->TryFlatten(replacement_shape);
+ if (!replacement->IsFlat()) {
+ Object* flat_replacement = replacement->TryFlatten();
if (flat_replacement->IsFailure()) {
return flat_replacement;
}
Handle<String> pat,
int start_index) {
ASSERT(0 <= start_index);
- StringShape sub_shape(*sub);
- ASSERT(start_index <= sub->length(sub_shape));
+ ASSERT(start_index <= sub->length());
int pattern_length = pat->length();
if (pattern_length == 0) return start_index;
- int subject_length = sub->length(sub_shape);
+ int subject_length = sub->length();
if (start_index + pattern_length > subject_length) return -1;
- if (!sub->IsFlat(sub_shape)) {
+ if (!sub->IsFlat()) {
FlattenString(sub);
- sub_shape = StringShape(*sub);
}
- StringShape pat_shape(*pat);
// Searching for one specific character is common. For one
// character patterns linear search is necessary, so any smart
// algorithm is unnecessary overhead.
if (pattern_length == 1) {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- if (sub_shape.IsAsciiRepresentation()) {
- uc16 pchar = pat->Get(pat_shape, 0);
+ if (StringShape(*sub).IsAsciiRepresentation()) {
+ uc16 pchar = pat->Get(0);
if (pchar > String::kMaxAsciiCharCode) {
return -1;
}
return reinterpret_cast<const char*>(pos) - ascii_vector.start()
+ start_index;
}
- return SingleCharIndexOf(sub->ToUC16Vector(),
- pat->Get(pat_shape, 0),
- start_index);
+ return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
}
- if (!pat->IsFlat(pat_shape)) {
+ if (!pat->IsFlat()) {
FlattenString(pat);
- pat_shape = StringShape(*pat);
- sub_shape = StringShape(*sub);
}
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// dispatch on type of strings
- if (pat_shape.IsAsciiRepresentation()) {
+ if (StringShape(*pat).IsAsciiRepresentation()) {
Vector<const char> pat_vector = pat->ToAsciiVector();
- if (sub_shape.IsAsciiRepresentation()) {
+ if (StringShape(*sub).IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
}
Vector<const uc16> pat_vector = pat->ToUC16Vector();
- if (sub_shape.IsAsciiRepresentation()) {
+ if (StringShape(*sub).IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
CONVERT_CHECKED(String, pat, args[1]);
Object* index = args[2];
- sub->TryFlattenIfNotFlat(StringShape(sub));
- pat->TryFlattenIfNotFlat(StringShape(pat));
-
- StringShape sub_shape(sub);
- StringShape pat_shape(pat);
+ sub->TryFlattenIfNotFlat();
+ pat->TryFlattenIfNotFlat();
uint32_t start_index;
if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
- uint32_t pattern_length = pat->length(pat_shape);
- uint32_t sub_length = sub->length(sub_shape);
+ uint32_t pattern_length = pat->length();
+ uint32_t sub_length = sub->length();
if (start_index + pattern_length > sub_length) {
start_index = sub_length - pattern_length;
for (int i = start_index; i >= 0; i--) {
bool found = true;
for (uint32_t j = 0; j < pattern_length; j++) {
- if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) {
+ if (sub->Get(i + j) != pat->Get(j)) {
found = false;
break;
}
CONVERT_CHECKED(String, str2, args[1]);
if (str1 == str2) return Smi::FromInt(0); // Equal.
- StringShape shape1(str1);
- StringShape shape2(str2);
- int str1_length = str1->length(shape1);
- int str2_length = str2->length(shape2);
+ int str1_length = str1->length();
+ int str2_length = str2->length();
// Decide trivial cases without flattening.
if (str1_length == 0) {
// No need to flatten if we are going to find the answer on the first
// character. At this point we know there is at least one character
// in each string, due to the trivial case handling above.
- int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
+ int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
- str1->TryFlattenIfNotFlat(shape1); // Shapes are no longer valid now!
- str2->TryFlattenIfNotFlat(shape2);
+ str1->TryFlattenIfNotFlat();
+ str2->TryFlattenIfNotFlat();
static StringInputBuffer buf1;
static StringInputBuffer buf2;
// Returns a single character string where first character equals
// string->Get(index).
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
- StringShape shape(*string);
- if (index < static_cast<uint32_t>(string->length(shape))) {
- string->TryFlattenIfNotFlat(shape); // Invalidates shape!
+ if (index < static_cast<uint32_t>(string->length())) {
+ string->TryFlattenIfNotFlat();
return LookupSingleCharacterStringFromCode(
- string->Get(StringShape(*string), index));
+ string->Get(index));
}
return Execution::CharAt(string, index);
}
result = SetElement(js_object, index, value);
} else {
Handle<String> key_string = Handle<String>::cast(key);
- key_string->TryFlattenIfNotFlat(StringShape(*key_string));
+ key_string->TryFlattenIfNotFlat();
result = SetProperty(js_object, key_string, value, attr);
}
if (result.is_null()) return Failure::Exception();
NoHandleAllocation ha;
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, subject, args[0]);
- subject->TryFlattenIfNotFlat(StringShape(subject));
+ subject->TryFlattenIfNotFlat();
return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
}
if (object->IsFailure()) return object;
String* result = String::cast(object);
- StringShape result_shape(result);
for (int i = 0; i < length; i++) {
Object* element = codes->GetElement(i);
CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
- result->Set(result_shape, i, chr & 0xffff);
+ result->Set(i, chr & 0xffff);
}
return result;
}
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]);
- source->TryFlattenIfNotFlat(StringShape(source));
+ source->TryFlattenIfNotFlat();
int escaped_length = 0;
int length = source->length();
Object* o = Heap::AllocateRawAsciiString(escaped_length);
if (o->IsFailure()) return o;
String* destination = String::cast(o);
- StringShape dshape(destination);
int dest_position = 0;
Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
while (buffer->has_more()) {
uint16_t chr = buffer->GetNext();
if (chr >= 256) {
- destination->Set(dshape, dest_position, '%');
- destination->Set(dshape, dest_position+1, 'u');
- destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]);
- destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]);
- destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]);
- destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]);
+ destination->Set(dest_position, '%');
+ destination->Set(dest_position+1, 'u');
+ destination->Set(dest_position+2, hex_chars[chr >> 12]);
+ destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
+ destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
+ destination->Set(dest_position+5, hex_chars[chr & 0xf]);
dest_position += 6;
} else if (IsNotEscaped(chr)) {
- destination->Set(dshape, dest_position, chr);
+ destination->Set(dest_position, chr);
dest_position++;
} else {
- destination->Set(dshape, dest_position, '%');
- destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]);
- destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]);
+ destination->Set(dest_position, '%');
+ destination->Set(dest_position+1, hex_chars[chr >> 4]);
+ destination->Set(dest_position+2, hex_chars[chr & 0xf]);
dest_position += 3;
}
}
static inline int Unescape(String* source,
- StringShape shape,
int i,
int length,
int* step) {
- uint16_t character = source->Get(shape, i);
+ uint16_t character = source->Get(i);
int32_t hi = 0;
int32_t lo = 0;
if (character == '%' &&
i <= length - 6 &&
- source->Get(shape, i + 1) == 'u' &&
- (hi = TwoDigitHex(source->Get(shape, i + 2),
- source->Get(shape, i + 3))) != -1 &&
- (lo = TwoDigitHex(source->Get(shape, i + 4),
- source->Get(shape, i + 5))) != -1) {
+ source->Get(i + 1) == 'u' &&
+ (hi = TwoDigitHex(source->Get(i + 2),
+ source->Get(i + 3))) != -1 &&
+ (lo = TwoDigitHex(source->Get(i + 4),
+ source->Get(i + 5))) != -1) {
*step = 6;
return (hi << 8) + lo;
} else if (character == '%' &&
i <= length - 3 &&
- (lo = TwoDigitHex(source->Get(shape, i + 1),
- source->Get(shape, i + 2))) != -1) {
+ (lo = TwoDigitHex(source->Get(i + 1),
+ source->Get(i + 2))) != -1) {
*step = 3;
return lo;
} else {
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]);
- source->TryFlattenIfNotFlat(StringShape(source));
- StringShape source_shape(source);
+ source->TryFlattenIfNotFlat();
bool ascii = true;
- int length = source->length(source_shape);
+ int length = source->length();
int unescaped_length = 0;
for (int i = 0; i < length; unescaped_length++) {
int step;
- if (Unescape(source,
- source_shape,
- i,
- length,
- &step) >
- String::kMaxAsciiCharCode)
+ if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
ascii = false;
+ }
i += step;
}
Heap::AllocateRawTwoByteString(unescaped_length);
if (o->IsFailure()) return o;
String* destination = String::cast(o);
- StringShape destination_shape(destination);
int dest_position = 0;
for (int i = 0; i < length; dest_position++) {
int step;
- destination->Set(destination_shape,
- dest_position,
- Unescape(source, source_shape, i, length, &step));
+ destination->Set(dest_position, Unescape(source, i, length, &step));
i += step;
}
return destination;
CONVERT_DOUBLE_CHECKED(n, args[1]);
int radix = FastD2I(n);
- s->TryFlattenIfNotFlat(StringShape(s));
-
- StringShape shape(s);
+ s->TryFlattenIfNotFlat();
- int len = s->length(shape);
+ int len = s->length();
int i;
// Skip leading white space.
- for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ;
+ for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
if (i == len) return Heap::nan_value();
// Compute the sign (default to +).
int sign = 1;
- if (s->Get(shape, i) == '-') {
+ if (s->Get(i) == '-') {
sign = -1;
i++;
- } else if (s->Get(shape, i) == '+') {
+ } else if (s->Get(i) == '+') {
i++;
}
// Compute the radix if 0.
if (radix == 0) {
radix = 10;
- if (i < len && s->Get(shape, i) == '0') {
+ if (i < len && s->Get(i) == '0') {
radix = 8;
if (i + 1 < len) {
- int c = s->Get(shape, i + 1);
+ int c = s->Get(i + 1);
if (c == 'x' || c == 'X') {
radix = 16;
i += 2;
}
} else if (radix == 16) {
// Allow 0x or 0X prefix if radix is 16.
- if (i + 1 < len && s->Get(shape, i) == '0') {
- int c = s->Get(shape, i + 1);
+ if (i + 1 < len && s->Get(i) == '0') {
+ int c = s->Get(i + 1);
if (c == 'x' || c == 'X') i += 2;
}
}
template <class Converter>
-static Object* ConvertCase(Arguments args,
- unibrow::Mapping<Converter, 128>* mapping) {
- NoHandleAllocation ha;
-
- CONVERT_CHECKED(String, s, args[0]);
- s->TryFlattenIfNotFlat(StringShape(s));
- StringShape shape(s);
-
- int raw_string_length = s->length(shape);
- // Assume that the string is not empty; we need this assumption later
- if (raw_string_length == 0) return s;
- int length = raw_string_length;
-
-
- // We try this twice, once with the assumption that the result is
- // no longer than the input and, if that assumption breaks, again
- // with the exact length. This is implemented using a goto back
- // to this label if we discover that the assumption doesn't hold.
- // I apologize sincerely for this and will give a vaffel-is to
- // the first person who can implement it in a nicer way.
- try_convert:
-
+static Object* ConvertCaseHelper(String* s,
+ int length,
+ int input_string_length,
+ unibrow::Mapping<Converter, 128>* mapping) {
+ // We try this twice, once with the assumption that the result is no longer
+ // than the input and, if that assumption breaks, again with the exact
+ // length. This may not be pretty, but it is nicer than what was here before
+ // and I hereby claim my vaffel-is.
+ //
// Allocate the resulting string.
//
// NOTE: This assumes that the upper/lower case of an ascii
// 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 = shape.IsAsciiRepresentation()
+ Object* o = StringShape(s).IsAsciiRepresentation()
? Heap::AllocateRawAsciiString(length)
: Heap::AllocateRawTwoByteString(length);
if (o->IsFailure()) return o;
String* result = String::cast(o);
- StringShape result_shape(result);
bool has_changed_character = false;
// Convert all characters to upper case, assuming that they will fit
Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
buffer->Reset(s);
unibrow::uchar chars[Converter::kMaxWidth];
- int i = 0;
// We can assume that the string is not empty
uc32 current = buffer->GetNext();
- while (i < length) {
+ for (int i = 0; i < length; ) {
bool has_next = buffer->has_more();
uc32 next = has_next ? buffer->GetNext() : 0;
int char_length = mapping->get(current, next, chars);
if (char_length == 0) {
// The case conversion of this character is the character itself.
- result->Set(result_shape, i, current);
+ result->Set(i, current);
i++;
} else if (char_length == 1) {
// Common case: converting the letter resulted in one character.
ASSERT(static_cast<uc32>(chars[0]) != current);
- result->Set(result_shape, i, chars[0]);
+ result->Set(i, chars[0]);
has_changed_character = true;
i++;
- } else if (length == raw_string_length) {
+ } else if (length == input_string_length) {
// We've assumed that the result would be as long as the
// input but here is a character that converts to several
// characters. No matter, we calculate the exact length
int char_length = mapping->get(current, 0, chars);
if (char_length == 0) char_length = 1;
current_length += char_length;
+ if (current_length > Smi::kMaxValue) {
+ Top::context()->mark_out_of_memory();
+ return Failure::OutOfMemoryException();
+ }
}
- length = current_length;
- goto try_convert;
+ // Try again with the real length.
+ return Smi::FromInt(current_length);
} else {
for (int j = 0; j < char_length; j++) {
- result->Set(result_shape, i, chars[j]);
+ result->Set(i, chars[j]);
i++;
}
has_changed_character = true;
}
+template <class Converter>
+static Object* ConvertCase(Arguments args,
+ unibrow::Mapping<Converter, 128>* mapping) {
+ NoHandleAllocation ha;
+
+ CONVERT_CHECKED(String, s, args[0]);
+ s->TryFlattenIfNotFlat();
+
+ int input_string_length = s->length();
+ // Assume that the string is not empty; we need this assumption later
+ if (input_string_length == 0) return s;
+ int length = input_string_length;
+
+ Object* answer = ConvertCaseHelper(s, length, length, mapping);
+ if (answer->IsSmi()) {
+ // Retry with correct length.
+ answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
+ }
+ return answer; // This may be a failure.
+}
+
+
static Object* Runtime_StringToLowerCase(Arguments args) {
return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
}
template<typename sinkchar>
static inline void StringBuilderConcatHelper(String* special,
- StringShape special_shape,
sinkchar* sink,
FixedArray* fixed_array,
int array_length) {
int pos = StringBuilderSubstringPosition::decode(encoded_slice);
int len = StringBuilderSubstringLength::decode(encoded_slice);
String::WriteToFlat(special,
- special_shape,
sink + position,
pos,
pos + len);
position += len;
} else {
String* string = String::cast(element);
- StringShape shape(string);
- int element_length = string->length(shape);
- String::WriteToFlat(string, shape, sink + position, 0, element_length);
+ int element_length = string->length();
+ String::WriteToFlat(string, sink + position, 0, element_length);
position += element_length;
}
}
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSArray, array, args[0]);
CONVERT_CHECKED(String, special, args[1]);
- StringShape special_shape(special);
- int special_length = special->length(special_shape);
+ int special_length = special->length();
Object* smi_array_length = array->length();
if (!smi_array_length->IsSmi()) {
Top::context()->mark_out_of_memory();
if (first->IsString()) return first;
}
- bool ascii = special_shape.IsAsciiRepresentation();
+ bool ascii = StringShape(special).IsAsciiRepresentation();
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
position += len;
} else if (elt->IsString()) {
String* element = String::cast(elt);
- StringShape element_shape(element);
- int element_length = element->length(element_shape);
+ int element_length = element->length();
if (!Smi::IsValid(element_length + position)) {
Top::context()->mark_out_of_memory();
return Failure::OutOfMemoryException();
}
position += element_length;
- if (ascii && !element_shape.IsAsciiRepresentation()) {
+ if (ascii && !StringShape(element).IsAsciiRepresentation()) {
ascii = false;
}
} else {
if (object->IsFailure()) return object;
SeqAsciiString* answer = SeqAsciiString::cast(object);
StringBuilderConcatHelper(special,
- special_shape,
answer->GetChars(),
fixed_array,
array_length);
if (object->IsFailure()) return object;
SeqTwoByteString* answer = SeqTwoByteString::cast(object);
StringBuilderConcatHelper(special,
- special_shape,
answer->GetChars(),
fixed_array,
array_length);
CONVERT_CHECKED(String, x, args[0]);
CONVERT_CHECKED(String, y, args[1]);
- StringShape x_shape(x);
- StringShape y_shape(y);
-
// A few fast case tests before we flatten.
if (x == y) return Smi::FromInt(EQUAL);
- if (y->length(y_shape) == 0) {
- if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL);
+ if (y->length() == 0) {
+ if (x->length() == 0) return Smi::FromInt(EQUAL);
return Smi::FromInt(GREATER);
- } else if (x->length(x_shape) == 0) {
+ } else if (x->length() == 0) {
return Smi::FromInt(LESS);
}
- int d = x->Get(x_shape, 0) - y->Get(y_shape, 0);
+ int d = x->Get(0) - y->Get(0);
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
- x->TryFlattenIfNotFlat(x_shape); // Shapes are no longer valid!
- y->TryFlattenIfNotFlat(y_shape);
+ x->TryFlattenIfNotFlat();
+ y->TryFlattenIfNotFlat();
static StringInputBuffer bufx;
static StringInputBuffer bufy;
static void VerifyStringAllocation(const char* string) {
String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
- StringShape shape(s);
- CHECK_EQ(static_cast<int>(strlen(string)), s->length(shape));
- for (int index = 0; index < s->length(shape); index++) {
- CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(shape, index)); }
+ CHECK_EQ(static_cast<int>(strlen(string)), s->length());
+ for (int index = 0; index < s->length(); index++) {
+ CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index)); }
}
Handle<String> f1 =
Factory::NewStringFromAscii(CStrVector("foobar"));
- Handle<String> f1_16 = RegExpImpl::StringToTwoByte(f1);
- CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
+ CHECK(IrregexpInterpreter::Match(array, f1, captures, 0));
CHECK_EQ(0, captures[0]);
CHECK_EQ(3, captures[1]);
CHECK_EQ(1, captures[2]);
Handle<String> f2 =
Factory::NewStringFromAscii(CStrVector("barfoo"));
- Handle<String> f2_16 = RegExpImpl::StringToTwoByte(f2);
- CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
+ CHECK(!IrregexpInterpreter::Match(array, f2, captures, 0));
CHECK_EQ(42, captures[0]);
}
building_blocks[i] =
Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len));
for (int j = 0; j < len; j++) {
- StringShape shape(*building_blocks[i]);
- CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+ CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
break;
}
building_blocks[i] =
Factory::NewStringFromAscii(Vector<const char>(buf, len));
for (int j = 0; j < len; j++) {
- StringShape shape(*building_blocks[i]);
- CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+ CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
break;
}
Resource* resource = new Resource(Vector<const uc16>(buf, len));
building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource);
for (int j = 0; j < len; j++) {
- StringShape shape(*building_blocks[i]);
- CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+ CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
break;
}
building_blocks[i] =
Factory::NewStringFromAscii(Vector<const char>(buf, len));
for (int j = 0; j < len; j++) {
- StringShape shape(*building_blocks[i]);
- CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+ CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
DeleteArray<char>(buf);
break;
for (int i = 0; i < depth; i++) {
answer = Factory::NewConsString(
answer,
- StringShape(*answer),
- building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
- StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]));
+ building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
}
return answer;
}
for (int i = depth - 1; i >= 0; i--) {
answer = Factory::NewConsString(
building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
- StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]),
- answer,
- StringShape(*answer));
+ answer);
}
return answer;
}
if (to - from == 2) {
return Factory::NewConsString(
building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
- StringShape(*building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]),
- building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS],
- StringShape(*building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]));
+ building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
}
Handle<String> part1 =
ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
Handle<String> part2 =
ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
- return Factory::NewConsString(
- part1,
- StringShape(*part1),
- part2,
- StringShape(*part2));
+ return Factory::NewConsString(part1, part2);
}
CHECK_EQ(c, buffer2.GetNext());
i++;
}
- s1->Get(StringShape(*s1), s1->length() - 1);
- s2->Get(StringShape(*s2), s2->length() - 1);
+ s1->Get(s1->length() - 1);
+ s2->Get(s2->length() - 1);
}
Handle<String> rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS];
if (gen() % 2 == 0)
rhs = SliceOf(rhs);
- return Factory::NewConsString(lhs,
- StringShape(*lhs),
- rhs,
- StringShape(*rhs));
+ return Factory::NewConsString(lhs, rhs);
}
Handle<String> part1 =
ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
Handle<String> part2 =
ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
- Handle<String> branch = Factory::NewConsString(part1,
- StringShape(*part1),
- part2,
- StringShape(*part2));
+ Handle<String> branch = Factory::NewConsString(part1, part2);
if (gen() % 2 == 0)
return branch;
return(SliceOf(branch));
Factory::NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
Handle<String> foo_string = Factory::NewStringFromAscii(CStrVector("foo"));
for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
- string = Factory::NewConsString(string,
- StringShape(*string),
- foo_string,
- StringShape(*foo_string));
+ string = Factory::NewConsString(string, foo_string);
}
- Handle<String> flat_string = Factory::NewConsString(string,
- StringShape(*string),
- foo_string,
- StringShape(*foo_string));
+ Handle<String> flat_string = Factory::NewConsString(string, foo_string);
FlattenString(flat_string);
for (int i = 0; i < 500; i++) {