int first_length = first->length();
int second_length = second->length();
int length = first_length + second_length;
- bool is_ascii = StringShape(first).IsAsciiRepresentation()
- && StringShape(second).IsAsciiRepresentation();
+ bool is_ascii = first->IsAsciiRepresentation()
+ && second->IsAsciiRepresentation();
// If the resulting string is small make a flat string.
if (length < String::kMinNonFlatLength) {
Map* map;
if (length <= String::kMaxShortStringSize) {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
short_sliced_ascii_string_map() :
short_sliced_string_map();
} else if (length <= String::kMaxMediumStringSize) {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
medium_sliced_ascii_string_map() :
medium_sliced_string_map();
} else {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
long_sliced_ascii_string_map() :
long_sliced_string_map();
}
buffer->TryFlatten();
}
- Object* result = StringShape(buffer).IsAsciiRepresentation()
+ Object* result = buffer->IsAsciiRepresentation()
? AllocateRawAsciiString(length)
: AllocateRawTwoByteString(length);
if (result->IsFailure()) return result;
int start_offset = previous_index;
int end_offset = subject_ptr->length();
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (StringShape(subject_ptr).IsCons()) {
subject_ptr = ConsString::cast(subject_ptr)->first();
subject_ptr = slice->buffer();
}
// 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());
// String is now either Sequential or External
int char_size_shift = is_ascii ? 0 : 1;
ASSERT(subject->IsExternalString() || subject->IsSeqString());
ASSERT(start_index >= 0);
ASSERT(start_index <= subject->length());
- if (StringShape(subject).IsAsciiRepresentation()) {
+ if (subject->IsAsciiRepresentation()) {
const byte* address;
if (StringShape(subject).IsExternal()) {
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
// Current string.
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
ASSERT(re_code->instruction_start() <= *return_address);
ASSERT(*return_address <=
}
// 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
// code cannot be used, and we need to restart regexp matching from
// scratch (including, potentially, compiling a new version of the code).
AssertNoAllocation a;
const byte* code_base = code_array->GetDataStartAddress();
uc16 previous_char = '\n';
- if (StringShape(*subject).IsAsciiRepresentation()) {
+ if (subject->IsAsciiRepresentation()) {
Vector<const char> subject_vector = subject->ToAsciiVector();
if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(code_base,
#ifdef V8_ARCH_IA32
RegExpMacroAssemblerIA32::Result res;
do {
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
}
rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
#endif
} else {
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
}
if (len > 0x1000)
len = 0x1000;
if (show_impl_info) {
- Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
+ Append(str->IsAsciiRepresentation() ? 'a' : '2');
if (StringShape(str).IsExternal())
Append('e');
if (StringShape(str).IsSymbol())
bool Object::IsSeqAsciiString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
- StringShape(String::cast(this)).IsAsciiRepresentation();
+ String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsSeqTwoByteString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
- StringShape(String::cast(this)).IsTwoByteRepresentation();
+ String::cast(this)->IsTwoByteRepresentation();
}
bool Object::IsExternalAsciiString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
- StringShape(String::cast(this)).IsAsciiRepresentation();
+ String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsExternalTwoByteString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
- StringShape(String::cast(this)).IsTwoByteRepresentation();
+ String::cast(this)->IsTwoByteRepresentation();
}
}
-bool StringShape::IsAsciiRepresentation() {
- return (type_ & kStringEncodingMask) == kAsciiStringTag;
+bool String::IsAsciiRepresentation() {
+ 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() {
- return (type_ & kStringEncodingMask) == kTwoByteStringTag;
+bool String::IsTwoByteRepresentation() {
+ 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;
}
ASSERT(index >= 0 && index < length());
ASSERT(StringShape(this).IsSequential());
- return StringShape(this).IsAsciiRepresentation()
+ return this->IsAsciiRepresentation()
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
}
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));
}
String* SlicedString::buffer() {
- ASSERT(
- StringShape(
- String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
- == StringShape(this).IsAsciiRepresentation());
return String::cast(READ_FIELD(this, kBufferOffset));
}
if (StringShape(String::cast(ok)).IsCons()) {
ss->set_buffer(ConsString::cast(ok)->first());
}
- ASSERT(StringShape(this).IsAsciiRepresentation() ==
- StringShape(ss->buffer()).IsAsciiRepresentation());
return this;
}
case kConsStringTag: {
int len = length();
Object* object;
String* result;
- if (StringShape(this).IsAsciiRepresentation()) {
+ if (IsAsciiRepresentation()) {
object = Heap::AllocateRawAsciiString(len, tenure);
if (object->IsFailure()) return object;
result = String::cast(object);
// Avoid calling functions such as FixedArray::cast during GC, which
// read map pointer of this object again.
InstanceType instance_type = map->instance_type();
+ uint32_t type = static_cast<uint32_t>(instance_type);
if (instance_type < FIRST_NONSTRING_TYPE
&& (StringShape(instance_type).IsSequential())) {
- if (StringShape(instance_type).IsAsciiRepresentation()) {
+ if ((type & kStringEncodingMask) == kAsciiStringTag) {
SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
return seq_ascii_this->SeqAsciiStringSize(instance_type);
} else {
int String::Utf8Length() {
- if (StringShape(this).IsAsciiRepresentation()) return length();
+ if (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)
Vector<const char> String::ToAsciiVector() {
- ASSERT(StringShape(this).IsAsciiRepresentation());
+ ASSERT(IsAsciiRepresentation());
ASSERT(IsFlat());
int offset = 0;
Vector<const uc16> String::ToUC16Vector() {
- ASSERT(StringShape(this).IsTwoByteRepresentation());
+ ASSERT(IsTwoByteRepresentation());
ASSERT(IsFlat());
int offset = 0;
const uc16* String::GetTwoByteData(unsigned start) {
- ASSERT(!StringShape(this).IsAsciiRepresentation());
+ ASSERT(!IsAsciiRepresentation());
switch (StringShape(this).representation_tag()) {
case kSeqStringTag:
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
}
switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
SeqAsciiString* str = SeqAsciiString::cast(input);
return str->SeqAsciiStringReadBlock(&rbb->remaining,
offset_ptr,
offset_ptr,
max_chars);
case kExternalStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
if (str_ == NULL) return;
Handle<String> str(str_);
ASSERT(str->IsFlat());
- is_ascii_ = StringShape(*str).IsAsciiRepresentation();
+ is_ascii_ = str->IsAsciiRepresentation();
if (is_ascii_) {
start_ = str->ToAsciiVector().start();
} else {
switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
max_chars);
return;
case kExternalStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
template <typename IteratorA>
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
if (b->IsFlat()) {
- if (StringShape(b).IsAsciiRepresentation()) {
+ if (b->IsAsciiRepresentation()) {
VectorIterator<char> ib(b->ToAsciiVector());
return CompareStringContents(ia, &ib);
} else {
}
if (this->IsFlat()) {
- if (StringShape(this).IsAsciiRepresentation()) {
+ if (IsAsciiRepresentation()) {
Vector<const char> vec1 = this->ToAsciiVector();
if (other->IsFlat()) {
- if (StringShape(other).IsAsciiRepresentation()) {
+ if (other->IsAsciiRepresentation()) {
Vector<const char> vec2 = other->ToAsciiVector();
return CompareRawStringContents(vec1, vec2);
} else {
Vector<const uc16> vec1 = this->ToUC16Vector();
if (CheckVectorForBug9746(vec1)) return false;
if (other->IsFlat()) {
- if (StringShape(other).IsAsciiRepresentation()) {
+ if (other->IsAsciiRepresentation()) {
VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(other->ToAsciiVector());
return CompareStringContents(&buf1, &ib);
inline explicit StringShape(String* s);
inline explicit StringShape(Map* s);
inline explicit StringShape(InstanceType t);
- inline bool IsAsciiRepresentation();
- inline bool IsTwoByteRepresentation();
inline bool IsSequential();
inline bool IsExternal();
inline bool IsCons();
inline uint32_t length_field();
inline void set_length_field(uint32_t value);
+ inline bool IsAsciiRepresentation();
+ inline bool IsTwoByteRepresentation();
+
// Get and set individual two byte chars in the string.
inline void Set(int index, uint16_t value);
// Get individual two byte char in the string. Repeated calls
parts_(Factory::NewFixedArray(estimated_part_count)),
part_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
// extend the array will work.
ASSERT(estimated_part_count > 0);
int length = string->length();
ASSERT(length > 0);
AddElement(*string);
- if (!StringShape(*string).IsAsciiRepresentation()) {
+ if (!string->IsAsciiRepresentation()) {
is_ascii_ = false;
}
IncrementCharacterCount(length);
int capture_count,
int subject_length) {
ASSERT(replacement->IsFlat());
- if (StringShape(*replacement).IsAsciiRepresentation()) {
+ if (replacement->IsAsciiRepresentation()) {
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
replacement->ToAsciiVector(),
capture_count,
subject_length);
} else {
- ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
+ ASSERT(replacement->IsTwoByteRepresentation());
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
// algorithm is unnecessary overhead.
if (pattern_length == 1) {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- if (StringShape(*sub).IsAsciiRepresentation()) {
+ if (sub->IsAsciiRepresentation()) {
uc16 pchar = pat->Get(0);
if (pchar > String::kMaxAsciiCharCode) {
return -1;
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// dispatch on type of strings
- if (StringShape(*pat).IsAsciiRepresentation()) {
+ if (pat->IsAsciiRepresentation()) {
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->ToUC16Vector(), pat_vector, start_index);
}
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->ToUC16Vector(), pat_vector, start_index);
// character is also ascii. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
- Object* o = StringShape(s).IsAsciiRepresentation()
+ Object* o = s->IsAsciiRepresentation()
? Heap::AllocateRawAsciiString(length)
: Heap::AllocateRawTwoByteString(length);
if (o->IsFailure()) return o;
if (first->IsString()) return first;
}
- bool ascii = StringShape(special).IsAsciiRepresentation();
+ bool ascii = special->IsAsciiRepresentation();
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
return Failure::OutOfMemoryException();
}
position += element_length;
- if (ascii && !StringShape(element).IsAsciiRepresentation()) {
+ if (ascii && !element->IsAsciiRepresentation()) {
ascii = false;
}
} else {
FixedArray* output_array = output->elements();
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
bool result;
- if (StringShape(*str).IsAsciiRepresentation()) {
+ if (str->IsAsciiRepresentation()) {
result = DateParser::Parse(str->ToAsciiVector(), output_array);
} else {
- ASSERT(StringShape(*str).IsTwoByteRepresentation());
+ ASSERT(str->IsTwoByteRepresentation());
result = DateParser::Parse(str->ToUC16Vector(), output_array);
}
if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
return true;
}
- if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
+ if (String::cast(str)->IsAsciiRepresentation()) {
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;
} else {
return true;
public:
static int dispose_count;
- explicit TestAsciiResource(char* data)
+ explicit TestAsciiResource(const char* data)
: data_(data),
length_(strlen(data)) { }
return length_;
}
private:
- char* data_;
+ const char* data_;
size_t length_;
};
}
+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 {
public:
RegExpStringModificationTest()
}
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.
static const int kRequiredModifications = 5;
static const int kMaxModifications = 100;
v8::Locker lock;
// Swap string between ascii and two-byte representation.
i::String* string = *input_;
- CHECK(i::StringShape(string).IsExternal());
- 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_);
- }
+ MorphAString(string, &ascii_resource_, &uc16_resource_);
morphs_++;
}
i::OS::Sleep(1);