When strings can change from an ASCII representation to a
UC16 representation we need to be careful about flat strings. Flat strings can be sliced or cons strings that have a flat string under them, so when we ask a flat cons or a slice whether it is ASCII or not we should ask the underlying string about its representation. This should fix http://code.google.com/p/chromium/issues/detail?id=10971 Review URL: http://codereview.chromium.org/100249 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1830 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
83d1d02df7
commit
ad23017469
12
src/heap.cc
12
src/heap.cc
@ -1423,8 +1423,8 @@ Object* Heap::AllocateConsString(String* first,
|
|||||||
int first_length = first->length();
|
int first_length = first->length();
|
||||||
int second_length = second->length();
|
int second_length = second->length();
|
||||||
int length = first_length + second_length;
|
int length = first_length + second_length;
|
||||||
bool is_ascii = StringShape(first).IsAsciiRepresentation()
|
bool is_ascii = first->IsAsciiRepresentation()
|
||||||
&& StringShape(second).IsAsciiRepresentation();
|
&& second->IsAsciiRepresentation();
|
||||||
|
|
||||||
// If the resulting string is small make a flat string.
|
// If the resulting string is small make a flat string.
|
||||||
if (length < String::kMinNonFlatLength) {
|
if (length < String::kMinNonFlatLength) {
|
||||||
@ -1484,15 +1484,15 @@ Object* Heap::AllocateSlicedString(String* buffer,
|
|||||||
|
|
||||||
Map* map;
|
Map* map;
|
||||||
if (length <= String::kMaxShortStringSize) {
|
if (length <= String::kMaxShortStringSize) {
|
||||||
map = StringShape(buffer).IsAsciiRepresentation() ?
|
map = buffer->IsAsciiRepresentation() ?
|
||||||
short_sliced_ascii_string_map() :
|
short_sliced_ascii_string_map() :
|
||||||
short_sliced_string_map();
|
short_sliced_string_map();
|
||||||
} else if (length <= String::kMaxMediumStringSize) {
|
} else if (length <= String::kMaxMediumStringSize) {
|
||||||
map = StringShape(buffer).IsAsciiRepresentation() ?
|
map = buffer->IsAsciiRepresentation() ?
|
||||||
medium_sliced_ascii_string_map() :
|
medium_sliced_ascii_string_map() :
|
||||||
medium_sliced_string_map();
|
medium_sliced_string_map();
|
||||||
} else {
|
} else {
|
||||||
map = StringShape(buffer).IsAsciiRepresentation() ?
|
map = buffer->IsAsciiRepresentation() ?
|
||||||
long_sliced_ascii_string_map() :
|
long_sliced_ascii_string_map() :
|
||||||
long_sliced_string_map();
|
long_sliced_string_map();
|
||||||
}
|
}
|
||||||
@ -1524,7 +1524,7 @@ Object* Heap::AllocateSubString(String* buffer,
|
|||||||
buffer->TryFlatten();
|
buffer->TryFlatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object* result = StringShape(buffer).IsAsciiRepresentation()
|
Object* result = buffer->IsAsciiRepresentation()
|
||||||
? AllocateRawAsciiString(length)
|
? AllocateRawAsciiString(length)
|
||||||
: AllocateRawTwoByteString(length);
|
: AllocateRawTwoByteString(length);
|
||||||
if (result->IsFailure()) return result;
|
if (result->IsFailure()) return result;
|
||||||
|
@ -974,7 +974,7 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
|
|||||||
int start_offset = previous_index;
|
int start_offset = previous_index;
|
||||||
int end_offset = subject_ptr->length();
|
int end_offset = subject_ptr->length();
|
||||||
|
|
||||||
bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
|
bool is_ascii = subject->IsAsciiRepresentation();
|
||||||
|
|
||||||
if (StringShape(subject_ptr).IsCons()) {
|
if (StringShape(subject_ptr).IsCons()) {
|
||||||
subject_ptr = ConsString::cast(subject_ptr)->first();
|
subject_ptr = ConsString::cast(subject_ptr)->first();
|
||||||
@ -985,7 +985,7 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
|
|||||||
subject_ptr = slice->buffer();
|
subject_ptr = slice->buffer();
|
||||||
}
|
}
|
||||||
// Ensure that an underlying string has the same ascii-ness.
|
// Ensure that an underlying string has the same ascii-ness.
|
||||||
ASSERT(StringShape(subject_ptr).IsAsciiRepresentation() == is_ascii);
|
ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii);
|
||||||
ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
|
ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
|
||||||
// String is now either Sequential or External
|
// String is now either Sequential or External
|
||||||
int char_size_shift = is_ascii ? 0 : 1;
|
int char_size_shift = is_ascii ? 0 : 1;
|
||||||
@ -1112,7 +1112,7 @@ const byte* RegExpMacroAssemblerIA32::StringCharacterPosition(String* subject,
|
|||||||
ASSERT(subject->IsExternalString() || subject->IsSeqString());
|
ASSERT(subject->IsExternalString() || subject->IsSeqString());
|
||||||
ASSERT(start_index >= 0);
|
ASSERT(start_index >= 0);
|
||||||
ASSERT(start_index <= subject->length());
|
ASSERT(start_index <= subject->length());
|
||||||
if (StringShape(subject).IsAsciiRepresentation()) {
|
if (subject->IsAsciiRepresentation()) {
|
||||||
const byte* address;
|
const byte* address;
|
||||||
if (StringShape(subject).IsExternal()) {
|
if (StringShape(subject).IsExternal()) {
|
||||||
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
|
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
|
||||||
@ -1152,7 +1152,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
|
|||||||
|
|
||||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||||
// Current string.
|
// Current string.
|
||||||
bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
|
bool is_ascii = subject->IsAsciiRepresentation();
|
||||||
|
|
||||||
ASSERT(re_code->instruction_start() <= *return_address);
|
ASSERT(re_code->instruction_start() <= *return_address);
|
||||||
ASSERT(*return_address <=
|
ASSERT(*return_address <=
|
||||||
@ -1171,7 +1171,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// String might have changed.
|
// String might have changed.
|
||||||
if (StringShape(*subject).IsAsciiRepresentation() != is_ascii) {
|
if (subject->IsAsciiRepresentation() != is_ascii) {
|
||||||
// If we changed between an ASCII and an UC16 string, the specialized
|
// If we changed between an ASCII and an UC16 string, the specialized
|
||||||
// code cannot be used, and we need to restart regexp matching from
|
// code cannot be used, and we need to restart regexp matching from
|
||||||
// scratch (including, potentially, compiling a new version of the code).
|
// scratch (including, potentially, compiling a new version of the code).
|
||||||
|
@ -574,7 +574,7 @@ bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
|
|||||||
AssertNoAllocation a;
|
AssertNoAllocation a;
|
||||||
const byte* code_base = code_array->GetDataStartAddress();
|
const byte* code_base = code_array->GetDataStartAddress();
|
||||||
uc16 previous_char = '\n';
|
uc16 previous_char = '\n';
|
||||||
if (StringShape(*subject).IsAsciiRepresentation()) {
|
if (subject->IsAsciiRepresentation()) {
|
||||||
Vector<const char> subject_vector = subject->ToAsciiVector();
|
Vector<const char> subject_vector = subject->ToAsciiVector();
|
||||||
if (start_position != 0) previous_char = subject_vector[start_position - 1];
|
if (start_position != 0) previous_char = subject_vector[start_position - 1];
|
||||||
return RawMatch(code_base,
|
return RawMatch(code_base,
|
||||||
|
@ -440,7 +440,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|
|||||||
#ifdef V8_ARCH_IA32
|
#ifdef V8_ARCH_IA32
|
||||||
RegExpMacroAssemblerIA32::Result res;
|
RegExpMacroAssemblerIA32::Result res;
|
||||||
do {
|
do {
|
||||||
bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
|
bool is_ascii = subject->IsAsciiRepresentation();
|
||||||
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
||||||
return Handle<Object>::null();
|
return Handle<Object>::null();
|
||||||
}
|
}
|
||||||
@ -463,7 +463,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|
|||||||
rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
|
rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
|
bool is_ascii = subject->IsAsciiRepresentation();
|
||||||
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
||||||
return Handle<Object>::null();
|
return Handle<Object>::null();
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
|
|||||||
if (len > 0x1000)
|
if (len > 0x1000)
|
||||||
len = 0x1000;
|
len = 0x1000;
|
||||||
if (show_impl_info) {
|
if (show_impl_info) {
|
||||||
Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
|
Append(str->IsAsciiRepresentation() ? 'a' : '2');
|
||||||
if (StringShape(str).IsExternal())
|
if (StringShape(str).IsExternal())
|
||||||
Append('e');
|
Append('e');
|
||||||
if (StringShape(str).IsSymbol())
|
if (StringShape(str).IsSymbol())
|
||||||
|
@ -144,14 +144,14 @@ bool Object::IsSeqString() {
|
|||||||
bool Object::IsSeqAsciiString() {
|
bool Object::IsSeqAsciiString() {
|
||||||
if (!IsString()) return false;
|
if (!IsString()) return false;
|
||||||
return StringShape(String::cast(this)).IsSequential() &&
|
return StringShape(String::cast(this)).IsSequential() &&
|
||||||
StringShape(String::cast(this)).IsAsciiRepresentation();
|
String::cast(this)->IsAsciiRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Object::IsSeqTwoByteString() {
|
bool Object::IsSeqTwoByteString() {
|
||||||
if (!IsString()) return false;
|
if (!IsString()) return false;
|
||||||
return StringShape(String::cast(this)).IsSequential() &&
|
return StringShape(String::cast(this)).IsSequential() &&
|
||||||
StringShape(String::cast(this)).IsTwoByteRepresentation();
|
String::cast(this)->IsTwoByteRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -164,14 +164,14 @@ bool Object::IsExternalString() {
|
|||||||
bool Object::IsExternalAsciiString() {
|
bool Object::IsExternalAsciiString() {
|
||||||
if (!IsString()) return false;
|
if (!IsString()) return false;
|
||||||
return StringShape(String::cast(this)).IsExternal() &&
|
return StringShape(String::cast(this)).IsExternal() &&
|
||||||
StringShape(String::cast(this)).IsAsciiRepresentation();
|
String::cast(this)->IsAsciiRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Object::IsExternalTwoByteString() {
|
bool Object::IsExternalTwoByteString() {
|
||||||
if (!IsString()) return false;
|
if (!IsString()) return false;
|
||||||
return StringShape(String::cast(this)).IsExternal() &&
|
return StringShape(String::cast(this)).IsExternal() &&
|
||||||
StringShape(String::cast(this)).IsTwoByteRepresentation();
|
String::cast(this)->IsTwoByteRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -211,13 +211,28 @@ bool StringShape::IsSymbol() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool StringShape::IsAsciiRepresentation() {
|
bool String::IsAsciiRepresentation() {
|
||||||
return (type_ & kStringEncodingMask) == kAsciiStringTag;
|
uint32_t type = map()->instance_type();
|
||||||
|
if ((type & kStringRepresentationMask) == kSlicedStringTag) {
|
||||||
|
return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
|
||||||
|
}
|
||||||
|
if ((type & kStringRepresentationMask) == kConsStringTag &&
|
||||||
|
ConsString::cast(this)->second()->length() == 0) {
|
||||||
|
return ConsString::cast(this)->first()->IsAsciiRepresentation();
|
||||||
|
}
|
||||||
|
return (type & kStringEncodingMask) == kAsciiStringTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool StringShape::IsTwoByteRepresentation() {
|
bool String::IsTwoByteRepresentation() {
|
||||||
return (type_ & kStringEncodingMask) == kTwoByteStringTag;
|
uint32_t type = map()->instance_type();
|
||||||
|
if ((type & kStringRepresentationMask) == kSlicedStringTag) {
|
||||||
|
return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
|
||||||
|
} else if ((type & kStringRepresentationMask) == kConsStringTag &&
|
||||||
|
ConsString::cast(this)->second()->length() == 0) {
|
||||||
|
return ConsString::cast(this)->first()->IsTwoByteRepresentation();
|
||||||
|
}
|
||||||
|
return (type & kStringEncodingMask) == kTwoByteStringTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1476,7 +1491,7 @@ void String::Set(int index, uint16_t value) {
|
|||||||
ASSERT(index >= 0 && index < length());
|
ASSERT(index >= 0 && index < length());
|
||||||
ASSERT(StringShape(this).IsSequential());
|
ASSERT(StringShape(this).IsSequential());
|
||||||
|
|
||||||
return StringShape(this).IsAsciiRepresentation()
|
return this->IsAsciiRepresentation()
|
||||||
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
|
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
|
||||||
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
|
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
|
||||||
}
|
}
|
||||||
@ -1576,11 +1591,6 @@ int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
|
|||||||
|
|
||||||
|
|
||||||
String* ConsString::first() {
|
String* ConsString::first() {
|
||||||
ASSERT(String::cast(READ_FIELD(this, kSecondOffset))->length() != 0 ||
|
|
||||||
StringShape(
|
|
||||||
String::cast(
|
|
||||||
READ_FIELD(this, kFirstOffset))).IsAsciiRepresentation()
|
|
||||||
== StringShape(this).IsAsciiRepresentation());
|
|
||||||
return String::cast(READ_FIELD(this, kFirstOffset));
|
return String::cast(READ_FIELD(this, kFirstOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1613,10 +1623,6 @@ void ConsString::set_second(String* value, WriteBarrierMode mode) {
|
|||||||
|
|
||||||
|
|
||||||
String* SlicedString::buffer() {
|
String* SlicedString::buffer() {
|
||||||
ASSERT(
|
|
||||||
StringShape(
|
|
||||||
String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
|
|
||||||
== StringShape(this).IsAsciiRepresentation());
|
|
||||||
return String::cast(READ_FIELD(this, kBufferOffset));
|
return String::cast(READ_FIELD(this, kBufferOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,8 +602,6 @@ Object* String::TryFlatten() {
|
|||||||
if (StringShape(String::cast(ok)).IsCons()) {
|
if (StringShape(String::cast(ok)).IsCons()) {
|
||||||
ss->set_buffer(ConsString::cast(ok)->first());
|
ss->set_buffer(ConsString::cast(ok)->first());
|
||||||
}
|
}
|
||||||
ASSERT(StringShape(this).IsAsciiRepresentation() ==
|
|
||||||
StringShape(ss->buffer()).IsAsciiRepresentation());
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
case kConsStringTag: {
|
case kConsStringTag: {
|
||||||
@ -618,7 +616,7 @@ Object* String::TryFlatten() {
|
|||||||
int len = length();
|
int len = length();
|
||||||
Object* object;
|
Object* object;
|
||||||
String* result;
|
String* result;
|
||||||
if (StringShape(this).IsAsciiRepresentation()) {
|
if (IsAsciiRepresentation()) {
|
||||||
object = Heap::AllocateRawAsciiString(len, tenure);
|
object = Heap::AllocateRawAsciiString(len, tenure);
|
||||||
if (object->IsFailure()) return object;
|
if (object->IsFailure()) return object;
|
||||||
result = String::cast(object);
|
result = String::cast(object);
|
||||||
@ -956,10 +954,11 @@ int HeapObject::SlowSizeFromMap(Map* map) {
|
|||||||
// Avoid calling functions such as FixedArray::cast during GC, which
|
// Avoid calling functions such as FixedArray::cast during GC, which
|
||||||
// read map pointer of this object again.
|
// read map pointer of this object again.
|
||||||
InstanceType instance_type = map->instance_type();
|
InstanceType instance_type = map->instance_type();
|
||||||
|
uint32_t type = static_cast<uint32_t>(instance_type);
|
||||||
|
|
||||||
if (instance_type < FIRST_NONSTRING_TYPE
|
if (instance_type < FIRST_NONSTRING_TYPE
|
||||||
&& (StringShape(instance_type).IsSequential())) {
|
&& (StringShape(instance_type).IsSequential())) {
|
||||||
if (StringShape(instance_type).IsAsciiRepresentation()) {
|
if ((type & kStringEncodingMask) == kAsciiStringTag) {
|
||||||
SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
|
SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
|
||||||
return seq_ascii_this->SeqAsciiStringSize(instance_type);
|
return seq_ascii_this->SeqAsciiStringSize(instance_type);
|
||||||
} else {
|
} else {
|
||||||
@ -3235,7 +3234,7 @@ bool String::LooksValid() {
|
|||||||
|
|
||||||
|
|
||||||
int String::Utf8Length() {
|
int String::Utf8Length() {
|
||||||
if (StringShape(this).IsAsciiRepresentation()) return length();
|
if (IsAsciiRepresentation()) return length();
|
||||||
// Attempt to flatten before accessing the string. It probably
|
// Attempt to flatten before accessing the string. It probably
|
||||||
// doesn't make Utf8Length faster, but it is very likely that
|
// doesn't make Utf8Length faster, but it is very likely that
|
||||||
// the string will be accessed later (for example by WriteUtf8)
|
// the string will be accessed later (for example by WriteUtf8)
|
||||||
@ -3251,7 +3250,7 @@ int String::Utf8Length() {
|
|||||||
|
|
||||||
|
|
||||||
Vector<const char> String::ToAsciiVector() {
|
Vector<const char> String::ToAsciiVector() {
|
||||||
ASSERT(StringShape(this).IsAsciiRepresentation());
|
ASSERT(IsAsciiRepresentation());
|
||||||
ASSERT(IsFlat());
|
ASSERT(IsFlat());
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@ -3282,7 +3281,7 @@ Vector<const char> String::ToAsciiVector() {
|
|||||||
|
|
||||||
|
|
||||||
Vector<const uc16> String::ToUC16Vector() {
|
Vector<const uc16> String::ToUC16Vector() {
|
||||||
ASSERT(StringShape(this).IsTwoByteRepresentation());
|
ASSERT(IsTwoByteRepresentation());
|
||||||
ASSERT(IsFlat());
|
ASSERT(IsFlat());
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@ -3385,7 +3384,7 @@ const uc16* String::GetTwoByteData() {
|
|||||||
|
|
||||||
|
|
||||||
const uc16* String::GetTwoByteData(unsigned start) {
|
const uc16* String::GetTwoByteData(unsigned start) {
|
||||||
ASSERT(!StringShape(this).IsAsciiRepresentation());
|
ASSERT(!IsAsciiRepresentation());
|
||||||
switch (StringShape(this).representation_tag()) {
|
switch (StringShape(this).representation_tag()) {
|
||||||
case kSeqStringTag:
|
case kSeqStringTag:
|
||||||
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
|
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
|
||||||
@ -3680,7 +3679,7 @@ const unibrow::byte* String::ReadBlock(String* input,
|
|||||||
}
|
}
|
||||||
switch (StringShape(input).representation_tag()) {
|
switch (StringShape(input).representation_tag()) {
|
||||||
case kSeqStringTag:
|
case kSeqStringTag:
|
||||||
if (StringShape(input).IsAsciiRepresentation()) {
|
if (input->IsAsciiRepresentation()) {
|
||||||
SeqAsciiString* str = SeqAsciiString::cast(input);
|
SeqAsciiString* str = SeqAsciiString::cast(input);
|
||||||
return str->SeqAsciiStringReadBlock(&rbb->remaining,
|
return str->SeqAsciiStringReadBlock(&rbb->remaining,
|
||||||
offset_ptr,
|
offset_ptr,
|
||||||
@ -3701,7 +3700,7 @@ const unibrow::byte* String::ReadBlock(String* input,
|
|||||||
offset_ptr,
|
offset_ptr,
|
||||||
max_chars);
|
max_chars);
|
||||||
case kExternalStringTag:
|
case kExternalStringTag:
|
||||||
if (StringShape(input).IsAsciiRepresentation()) {
|
if (input->IsAsciiRepresentation()) {
|
||||||
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
|
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
|
||||||
&rbb->remaining,
|
&rbb->remaining,
|
||||||
offset_ptr,
|
offset_ptr,
|
||||||
@ -3754,7 +3753,7 @@ void FlatStringReader::RefreshState() {
|
|||||||
if (str_ == NULL) return;
|
if (str_ == NULL) return;
|
||||||
Handle<String> str(str_);
|
Handle<String> str(str_);
|
||||||
ASSERT(str->IsFlat());
|
ASSERT(str->IsFlat());
|
||||||
is_ascii_ = StringShape(*str).IsAsciiRepresentation();
|
is_ascii_ = str->IsAsciiRepresentation();
|
||||||
if (is_ascii_) {
|
if (is_ascii_) {
|
||||||
start_ = str->ToAsciiVector().start();
|
start_ = str->ToAsciiVector().start();
|
||||||
} else {
|
} else {
|
||||||
@ -3795,7 +3794,7 @@ void String::ReadBlockIntoBuffer(String* input,
|
|||||||
|
|
||||||
switch (StringShape(input).representation_tag()) {
|
switch (StringShape(input).representation_tag()) {
|
||||||
case kSeqStringTag:
|
case kSeqStringTag:
|
||||||
if (StringShape(input).IsAsciiRepresentation()) {
|
if (input->IsAsciiRepresentation()) {
|
||||||
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
|
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
|
||||||
offset_ptr,
|
offset_ptr,
|
||||||
max_chars);
|
max_chars);
|
||||||
@ -3817,7 +3816,7 @@ void String::ReadBlockIntoBuffer(String* input,
|
|||||||
max_chars);
|
max_chars);
|
||||||
return;
|
return;
|
||||||
case kExternalStringTag:
|
case kExternalStringTag:
|
||||||
if (StringShape(input).IsAsciiRepresentation()) {
|
if (input->IsAsciiRepresentation()) {
|
||||||
ExternalAsciiString::cast(input)->
|
ExternalAsciiString::cast(input)->
|
||||||
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
|
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
|
||||||
} else {
|
} else {
|
||||||
@ -4147,7 +4146,7 @@ static StringInputBuffer string_compare_buffer_b;
|
|||||||
template <typename IteratorA>
|
template <typename IteratorA>
|
||||||
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
|
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
|
||||||
if (b->IsFlat()) {
|
if (b->IsFlat()) {
|
||||||
if (StringShape(b).IsAsciiRepresentation()) {
|
if (b->IsAsciiRepresentation()) {
|
||||||
VectorIterator<char> ib(b->ToAsciiVector());
|
VectorIterator<char> ib(b->ToAsciiVector());
|
||||||
return CompareStringContents(ia, &ib);
|
return CompareStringContents(ia, &ib);
|
||||||
} else {
|
} else {
|
||||||
@ -4187,10 +4186,10 @@ bool String::SlowEquals(String* other) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->IsFlat()) {
|
if (this->IsFlat()) {
|
||||||
if (StringShape(this).IsAsciiRepresentation()) {
|
if (IsAsciiRepresentation()) {
|
||||||
Vector<const char> vec1 = this->ToAsciiVector();
|
Vector<const char> vec1 = this->ToAsciiVector();
|
||||||
if (other->IsFlat()) {
|
if (other->IsFlat()) {
|
||||||
if (StringShape(other).IsAsciiRepresentation()) {
|
if (other->IsAsciiRepresentation()) {
|
||||||
Vector<const char> vec2 = other->ToAsciiVector();
|
Vector<const char> vec2 = other->ToAsciiVector();
|
||||||
return CompareRawStringContents(vec1, vec2);
|
return CompareRawStringContents(vec1, vec2);
|
||||||
} else {
|
} else {
|
||||||
@ -4209,7 +4208,7 @@ bool String::SlowEquals(String* other) {
|
|||||||
Vector<const uc16> vec1 = this->ToUC16Vector();
|
Vector<const uc16> vec1 = this->ToUC16Vector();
|
||||||
if (CheckVectorForBug9746(vec1)) return false;
|
if (CheckVectorForBug9746(vec1)) return false;
|
||||||
if (other->IsFlat()) {
|
if (other->IsFlat()) {
|
||||||
if (StringShape(other).IsAsciiRepresentation()) {
|
if (other->IsAsciiRepresentation()) {
|
||||||
VectorIterator<uc16> buf1(vec1);
|
VectorIterator<uc16> buf1(vec1);
|
||||||
VectorIterator<char> ib(other->ToAsciiVector());
|
VectorIterator<char> ib(other->ToAsciiVector());
|
||||||
return CompareStringContents(&buf1, &ib);
|
return CompareStringContents(&buf1, &ib);
|
||||||
|
@ -3207,8 +3207,6 @@ class StringShape BASE_EMBEDDED {
|
|||||||
inline explicit StringShape(String* s);
|
inline explicit StringShape(String* s);
|
||||||
inline explicit StringShape(Map* s);
|
inline explicit StringShape(Map* s);
|
||||||
inline explicit StringShape(InstanceType t);
|
inline explicit StringShape(InstanceType t);
|
||||||
inline bool IsAsciiRepresentation();
|
|
||||||
inline bool IsTwoByteRepresentation();
|
|
||||||
inline bool IsSequential();
|
inline bool IsSequential();
|
||||||
inline bool IsExternal();
|
inline bool IsExternal();
|
||||||
inline bool IsCons();
|
inline bool IsCons();
|
||||||
@ -3260,6 +3258,9 @@ class String: public HeapObject {
|
|||||||
inline uint32_t length_field();
|
inline uint32_t length_field();
|
||||||
inline void set_length_field(uint32_t value);
|
inline void set_length_field(uint32_t value);
|
||||||
|
|
||||||
|
inline bool IsAsciiRepresentation();
|
||||||
|
inline bool IsTwoByteRepresentation();
|
||||||
|
|
||||||
// Get and set individual two byte chars in the string.
|
// Get and set individual two byte chars in the string.
|
||||||
inline void Set(int index, uint16_t value);
|
inline void Set(int index, uint16_t value);
|
||||||
// Get individual two byte char in the string. Repeated calls
|
// Get individual two byte char in the string. Repeated calls
|
||||||
|
@ -1282,7 +1282,7 @@ class ReplacementStringBuilder {
|
|||||||
parts_(Factory::NewFixedArray(estimated_part_count)),
|
parts_(Factory::NewFixedArray(estimated_part_count)),
|
||||||
part_count_(0),
|
part_count_(0),
|
||||||
character_count_(0),
|
character_count_(0),
|
||||||
is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
|
is_ascii_(subject->IsAsciiRepresentation()) {
|
||||||
// Require a non-zero initial size. Ensures that doubling the size to
|
// Require a non-zero initial size. Ensures that doubling the size to
|
||||||
// extend the array will work.
|
// extend the array will work.
|
||||||
ASSERT(estimated_part_count > 0);
|
ASSERT(estimated_part_count > 0);
|
||||||
@ -1326,7 +1326,7 @@ class ReplacementStringBuilder {
|
|||||||
int length = string->length();
|
int length = string->length();
|
||||||
ASSERT(length > 0);
|
ASSERT(length > 0);
|
||||||
AddElement(*string);
|
AddElement(*string);
|
||||||
if (!StringShape(*string).IsAsciiRepresentation()) {
|
if (!string->IsAsciiRepresentation()) {
|
||||||
is_ascii_ = false;
|
is_ascii_ = false;
|
||||||
}
|
}
|
||||||
IncrementCharacterCount(length);
|
IncrementCharacterCount(length);
|
||||||
@ -1583,14 +1583,14 @@ void CompiledReplacement::Compile(Handle<String> replacement,
|
|||||||
int capture_count,
|
int capture_count,
|
||||||
int subject_length) {
|
int subject_length) {
|
||||||
ASSERT(replacement->IsFlat());
|
ASSERT(replacement->IsFlat());
|
||||||
if (StringShape(*replacement).IsAsciiRepresentation()) {
|
if (replacement->IsAsciiRepresentation()) {
|
||||||
AssertNoAllocation no_alloc;
|
AssertNoAllocation no_alloc;
|
||||||
ParseReplacementPattern(&parts_,
|
ParseReplacementPattern(&parts_,
|
||||||
replacement->ToAsciiVector(),
|
replacement->ToAsciiVector(),
|
||||||
capture_count,
|
capture_count,
|
||||||
subject_length);
|
subject_length);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
|
ASSERT(replacement->IsTwoByteRepresentation());
|
||||||
AssertNoAllocation no_alloc;
|
AssertNoAllocation no_alloc;
|
||||||
|
|
||||||
ParseReplacementPattern(&parts_,
|
ParseReplacementPattern(&parts_,
|
||||||
@ -2165,7 +2165,7 @@ int Runtime::StringMatch(Handle<String> sub,
|
|||||||
// algorithm is unnecessary overhead.
|
// algorithm is unnecessary overhead.
|
||||||
if (pattern_length == 1) {
|
if (pattern_length == 1) {
|
||||||
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
||||||
if (StringShape(*sub).IsAsciiRepresentation()) {
|
if (sub->IsAsciiRepresentation()) {
|
||||||
uc16 pchar = pat->Get(0);
|
uc16 pchar = pat->Get(0);
|
||||||
if (pchar > String::kMaxAsciiCharCode) {
|
if (pchar > String::kMaxAsciiCharCode) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -2190,15 +2190,15 @@ int Runtime::StringMatch(Handle<String> sub,
|
|||||||
|
|
||||||
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
||||||
// dispatch on type of strings
|
// dispatch on type of strings
|
||||||
if (StringShape(*pat).IsAsciiRepresentation()) {
|
if (pat->IsAsciiRepresentation()) {
|
||||||
Vector<const char> pat_vector = pat->ToAsciiVector();
|
Vector<const char> pat_vector = pat->ToAsciiVector();
|
||||||
if (StringShape(*sub).IsAsciiRepresentation()) {
|
if (sub->IsAsciiRepresentation()) {
|
||||||
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
|
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
|
||||||
}
|
}
|
||||||
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
|
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
|
||||||
}
|
}
|
||||||
Vector<const uc16> pat_vector = pat->ToUC16Vector();
|
Vector<const uc16> pat_vector = pat->ToUC16Vector();
|
||||||
if (StringShape(*sub).IsAsciiRepresentation()) {
|
if (sub->IsAsciiRepresentation()) {
|
||||||
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
|
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
|
||||||
}
|
}
|
||||||
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
|
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
|
||||||
@ -3329,7 +3329,7 @@ static Object* ConvertCaseHelper(String* s,
|
|||||||
// character is also ascii. This is currently the case, but it
|
// character is also ascii. This is currently the case, but it
|
||||||
// might break in the future if we implement more context and locale
|
// might break in the future if we implement more context and locale
|
||||||
// dependent upper/lower conversions.
|
// dependent upper/lower conversions.
|
||||||
Object* o = StringShape(s).IsAsciiRepresentation()
|
Object* o = s->IsAsciiRepresentation()
|
||||||
? Heap::AllocateRawAsciiString(length)
|
? Heap::AllocateRawAsciiString(length)
|
||||||
: Heap::AllocateRawTwoByteString(length);
|
: Heap::AllocateRawTwoByteString(length);
|
||||||
if (o->IsFailure()) return o;
|
if (o->IsFailure()) return o;
|
||||||
@ -3680,7 +3680,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
|
|||||||
if (first->IsString()) return first;
|
if (first->IsString()) return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ascii = StringShape(special).IsAsciiRepresentation();
|
bool ascii = special->IsAsciiRepresentation();
|
||||||
int position = 0;
|
int position = 0;
|
||||||
for (int i = 0; i < array_length; i++) {
|
for (int i = 0; i < array_length; i++) {
|
||||||
Object* elt = fixed_array->get(i);
|
Object* elt = fixed_array->get(i);
|
||||||
@ -3700,7 +3700,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
|
|||||||
return Failure::OutOfMemoryException();
|
return Failure::OutOfMemoryException();
|
||||||
}
|
}
|
||||||
position += element_length;
|
position += element_length;
|
||||||
if (ascii && !StringShape(element).IsAsciiRepresentation()) {
|
if (ascii && !element->IsAsciiRepresentation()) {
|
||||||
ascii = false;
|
ascii = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -4757,10 +4757,10 @@ static Object* Runtime_DateParseString(Arguments args) {
|
|||||||
FixedArray* output_array = output->elements();
|
FixedArray* output_array = output->elements();
|
||||||
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
|
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
|
||||||
bool result;
|
bool result;
|
||||||
if (StringShape(*str).IsAsciiRepresentation()) {
|
if (str->IsAsciiRepresentation()) {
|
||||||
result = DateParser::Parse(str->ToAsciiVector(), output_array);
|
result = DateParser::Parse(str->ToAsciiVector(), output_array);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(StringShape(*str).IsTwoByteRepresentation());
|
ASSERT(str->IsTwoByteRepresentation());
|
||||||
result = DateParser::Parse(str->ToUC16Vector(), output_array);
|
result = DateParser::Parse(str->ToUC16Vector(), output_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6574,9 +6574,9 @@ static bool IsExternalStringValid(Object* str) {
|
|||||||
if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
|
if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
|
if (String::cast(str)->IsAsciiRepresentation()) {
|
||||||
return ExternalAsciiString::cast(str)->resource() != NULL;
|
return ExternalAsciiString::cast(str)->resource() != NULL;
|
||||||
} else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
|
} else if (String::cast(str)->IsTwoByteRepresentation()) {
|
||||||
return ExternalTwoByteString::cast(str)->resource() != NULL;
|
return ExternalTwoByteString::cast(str)->resource() != NULL;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -420,7 +420,7 @@ class TestAsciiResource: public String::ExternalAsciiStringResource {
|
|||||||
public:
|
public:
|
||||||
static int dispose_count;
|
static int dispose_count;
|
||||||
|
|
||||||
explicit TestAsciiResource(char* data)
|
explicit TestAsciiResource(const char* data)
|
||||||
: data_(data),
|
: data_(data),
|
||||||
length_(strlen(data)) { }
|
length_(strlen(data)) { }
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ class TestAsciiResource: public String::ExternalAsciiStringResource {
|
|||||||
return length_;
|
return length_;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
char* data_;
|
const char* data_;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -6153,6 +6153,117 @@ TEST(ObjectClone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
|
||||||
|
public:
|
||||||
|
explicit AsciiVectorResource(i::Vector<const char> vector)
|
||||||
|
: data_(vector) {}
|
||||||
|
virtual ~AsciiVectorResource() {}
|
||||||
|
virtual size_t length() const { return data_.length(); }
|
||||||
|
virtual const char* data() const { return data_.start(); }
|
||||||
|
private:
|
||||||
|
i::Vector<const char> data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class UC16VectorResource : public v8::String::ExternalStringResource {
|
||||||
|
public:
|
||||||
|
explicit UC16VectorResource(i::Vector<const i::uc16> vector)
|
||||||
|
: data_(vector) {}
|
||||||
|
virtual ~UC16VectorResource() {}
|
||||||
|
virtual size_t length() const { return data_.length(); }
|
||||||
|
virtual const i::uc16* data() const { return data_.start(); }
|
||||||
|
private:
|
||||||
|
i::Vector<const i::uc16> data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void MorphAString(i::String* string,
|
||||||
|
AsciiVectorResource* ascii_resource,
|
||||||
|
UC16VectorResource* uc16_resource) {
|
||||||
|
CHECK(i::StringShape(string).IsExternal());
|
||||||
|
if (string->IsAsciiRepresentation()) {
|
||||||
|
// Check old map is not symbol or long.
|
||||||
|
CHECK(string->map() == i::Heap::short_external_ascii_string_map() ||
|
||||||
|
string->map() == i::Heap::medium_external_ascii_string_map());
|
||||||
|
// Morph external string to be TwoByte string.
|
||||||
|
if (string->length() <= i::String::kMaxShortStringSize) {
|
||||||
|
string->set_map(i::Heap::short_external_string_map());
|
||||||
|
} else {
|
||||||
|
string->set_map(i::Heap::medium_external_string_map());
|
||||||
|
}
|
||||||
|
i::ExternalTwoByteString* morphed =
|
||||||
|
i::ExternalTwoByteString::cast(string);
|
||||||
|
morphed->set_resource(uc16_resource);
|
||||||
|
} else {
|
||||||
|
// Check old map is not symbol or long.
|
||||||
|
CHECK(string->map() == i::Heap::short_external_string_map() ||
|
||||||
|
string->map() == i::Heap::medium_external_string_map());
|
||||||
|
// Morph external string to be ASCII string.
|
||||||
|
if (string->length() <= i::String::kMaxShortStringSize) {
|
||||||
|
string->set_map(i::Heap::short_external_ascii_string_map());
|
||||||
|
} else {
|
||||||
|
string->set_map(i::Heap::medium_external_ascii_string_map());
|
||||||
|
}
|
||||||
|
i::ExternalAsciiString* morphed =
|
||||||
|
i::ExternalAsciiString::cast(string);
|
||||||
|
morphed->set_resource(ascii_resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test that we can still flatten a string if the components it is built up
|
||||||
|
// from have been turned into 16 bit strings in the mean time.
|
||||||
|
THREADED_TEST(MorphCompositeStringTest) {
|
||||||
|
const char* c_string = "Now is the time for all good men"
|
||||||
|
" to come to the aid of the party";
|
||||||
|
uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
|
||||||
|
{
|
||||||
|
v8::HandleScope scope;
|
||||||
|
LocalContext env;
|
||||||
|
AsciiVectorResource ascii_resource(
|
||||||
|
i::Vector<const char>(c_string, strlen(c_string)));
|
||||||
|
UC16VectorResource uc16_resource(
|
||||||
|
i::Vector<const uint16_t>(two_byte_string, strlen(c_string)));
|
||||||
|
|
||||||
|
Local<String> lhs(v8::Utils::ToLocal(
|
||||||
|
i::Factory::NewExternalStringFromAscii(&ascii_resource)));
|
||||||
|
Local<String> rhs(v8::Utils::ToLocal(
|
||||||
|
i::Factory::NewExternalStringFromAscii(&ascii_resource)));
|
||||||
|
|
||||||
|
env->Global()->Set(v8_str("lhs"), lhs);
|
||||||
|
env->Global()->Set(v8_str("rhs"), rhs);
|
||||||
|
|
||||||
|
CompileRun(
|
||||||
|
"var cons = lhs + rhs;"
|
||||||
|
"var slice = lhs.substring(1, lhs.length - 1);"
|
||||||
|
"var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
|
||||||
|
|
||||||
|
MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
|
||||||
|
MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
|
||||||
|
|
||||||
|
// Now do some stuff to make sure the strings are flattened, etc.
|
||||||
|
CompileRun(
|
||||||
|
"/[^a-z]/.test(cons);"
|
||||||
|
"/[^a-z]/.test(slice);"
|
||||||
|
"/[^a-z]/.test(slice_on_cons);");
|
||||||
|
const char* expected_cons =
|
||||||
|
"Now is the time for all good men to come to the aid of the party"
|
||||||
|
"Now is the time for all good men to come to the aid of the party";
|
||||||
|
const char* expected_slice =
|
||||||
|
"ow is the time for all good men to come to the aid of the part";
|
||||||
|
const char* expected_slice_on_cons =
|
||||||
|
"ow is the time for all good men to come to the aid of the party"
|
||||||
|
"Now is the time for all good men to come to the aid of the part";
|
||||||
|
CHECK_EQ(String::New(expected_cons),
|
||||||
|
env->Global()->Get(v8_str("cons")));
|
||||||
|
CHECK_EQ(String::New(expected_slice),
|
||||||
|
env->Global()->Get(v8_str("slice")));
|
||||||
|
CHECK_EQ(String::New(expected_slice_on_cons),
|
||||||
|
env->Global()->Get(v8_str("slice_on_cons")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RegExpStringModificationTest {
|
class RegExpStringModificationTest {
|
||||||
public:
|
public:
|
||||||
RegExpStringModificationTest()
|
RegExpStringModificationTest()
|
||||||
@ -6197,26 +6308,6 @@ class RegExpStringModificationTest {
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
|
|
||||||
public:
|
|
||||||
explicit AsciiVectorResource(i::Vector<const char> vector)
|
|
||||||
: data_(vector) {}
|
|
||||||
virtual ~AsciiVectorResource() {}
|
|
||||||
virtual size_t length() const { return data_.length(); }
|
|
||||||
virtual const char* data() const { return data_.start(); }
|
|
||||||
private:
|
|
||||||
i::Vector<const char> data_;
|
|
||||||
};
|
|
||||||
class UC16VectorResource : public v8::String::ExternalStringResource {
|
|
||||||
public:
|
|
||||||
explicit UC16VectorResource(i::Vector<const i::uc16> vector)
|
|
||||||
: data_(vector) {}
|
|
||||||
virtual ~UC16VectorResource() {}
|
|
||||||
virtual size_t length() const { return data_.length(); }
|
|
||||||
virtual const i::uc16* data() const { return data_.start(); }
|
|
||||||
private:
|
|
||||||
i::Vector<const i::uc16> data_;
|
|
||||||
};
|
|
||||||
// Number of string modifications required.
|
// Number of string modifications required.
|
||||||
static const int kRequiredModifications = 5;
|
static const int kRequiredModifications = 5;
|
||||||
static const int kMaxModifications = 100;
|
static const int kMaxModifications = 100;
|
||||||
@ -6240,25 +6331,7 @@ class RegExpStringModificationTest {
|
|||||||
v8::Locker lock;
|
v8::Locker lock;
|
||||||
// Swap string between ascii and two-byte representation.
|
// Swap string between ascii and two-byte representation.
|
||||||
i::String* string = *input_;
|
i::String* string = *input_;
|
||||||
CHECK(i::StringShape(string).IsExternal());
|
MorphAString(string, &ascii_resource_, &uc16_resource_);
|
||||||
if (i::StringShape(string).IsAsciiRepresentation()) {
|
|
||||||
// Morph external string to be TwoByte string.
|
|
||||||
i::ExternalAsciiString* ext_string =
|
|
||||||
i::ExternalAsciiString::cast(string);
|
|
||||||
i::ExternalTwoByteString* morphed =
|
|
||||||
reinterpret_cast<i::ExternalTwoByteString*>(ext_string);
|
|
||||||
morphed->map()->set_instance_type(i::SHORT_EXTERNAL_STRING_TYPE);
|
|
||||||
morphed->set_resource(&uc16_resource_);
|
|
||||||
} else {
|
|
||||||
// Morph external string to be ASCII string.
|
|
||||||
i::ExternalTwoByteString* ext_string =
|
|
||||||
i::ExternalTwoByteString::cast(string);
|
|
||||||
i::ExternalAsciiString* morphed =
|
|
||||||
reinterpret_cast<i::ExternalAsciiString*>(ext_string);
|
|
||||||
morphed->map()->set_instance_type(
|
|
||||||
i::SHORT_EXTERNAL_ASCII_STRING_TYPE);
|
|
||||||
morphed->set_resource(&ascii_resource_);
|
|
||||||
}
|
|
||||||
morphs_++;
|
morphs_++;
|
||||||
}
|
}
|
||||||
i::OS::Sleep(1);
|
i::OS::Sleep(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user