Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 6c9fe1badf5036771710e12038b8823e9ffe0b1f..f9420470e2552e9b7af614f46b5ec66ebe12afae 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2663,21 +2663,22 @@ class CompiledReplacement { |
void CompiledReplacement::Compile(Handle<String> replacement, |
int capture_count, |
int subject_length) { |
- ASSERT(replacement->IsFlat()); |
- if (replacement->IsAsciiRepresentation()) { |
- AssertNoAllocation no_alloc; |
- ParseReplacementPattern(&parts_, |
- replacement->ToAsciiVector(), |
- capture_count, |
- subject_length); |
- } else { |
- ASSERT(replacement->IsTwoByteRepresentation()); |
+ { |
AssertNoAllocation no_alloc; |
- |
- ParseReplacementPattern(&parts_, |
- replacement->ToUC16Vector(), |
- capture_count, |
- subject_length); |
+ String::FlatContent content = replacement->GetFlatContent(no_alloc); |
+ ASSERT(content.IsFlat()); |
+ if (content.IsAscii()) { |
+ ParseReplacementPattern(&parts_, |
+ content.ToAsciiVector(), |
+ capture_count, |
+ subject_length); |
+ } else { |
+ ASSERT(content.IsTwoByte()); |
+ ParseReplacementPattern(&parts_, |
+ content.ToUC16Vector(), |
+ capture_count, |
+ subject_length); |
+ } |
} |
Isolate* isolate = replacement->GetIsolate(); |
// Find substrings of replacement string and create them as String objects. |
@@ -3049,34 +3050,32 @@ int Runtime::StringMatch(Isolate* isolate, |
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
// Extract flattened substrings of cons strings before determining asciiness. |
- String* seq_sub = *sub; |
- if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first(); |
- String* seq_pat = *pat; |
- if (seq_pat->IsConsString()) seq_pat = ConsString::cast(seq_pat)->first(); |
+ String::FlatContent seq_sub = sub->GetFlatContent(no_heap_allocation); |
+ String::FlatContent seq_pat = pat->GetFlatContent(no_heap_allocation); |
// dispatch on type of strings |
- if (seq_pat->IsAsciiRepresentation()) { |
- Vector<const char> pat_vector = seq_pat->ToAsciiVector(); |
- if (seq_sub->IsAsciiRepresentation()) { |
+ if (seq_pat.IsAscii()) { |
+ Vector<const char> pat_vector = seq_pat.ToAsciiVector(); |
+ if (seq_sub.IsAscii()) { |
return SearchString(isolate, |
- seq_sub->ToAsciiVector(), |
+ seq_sub.ToAsciiVector(), |
pat_vector, |
start_index); |
} |
return SearchString(isolate, |
- seq_sub->ToUC16Vector(), |
+ seq_sub.ToUC16Vector(), |
pat_vector, |
start_index); |
} |
- Vector<const uc16> pat_vector = seq_pat->ToUC16Vector(); |
- if (seq_sub->IsAsciiRepresentation()) { |
+ Vector<const uc16> pat_vector = seq_pat.ToUC16Vector(); |
+ if (seq_sub.IsAscii()) { |
return SearchString(isolate, |
- seq_sub->ToAsciiVector(), |
+ seq_sub.ToAsciiVector(), |
pat_vector, |
start_index); |
} |
return SearchString(isolate, |
- seq_sub->ToUC16Vector(), |
+ seq_sub.ToUC16Vector(), |
pat_vector, |
start_index); |
} |
@@ -3161,31 +3160,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) { |
int position = -1; |
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
- // Extract flattened substrings of cons strings before determining asciiness. |
- String* seq_sub = *sub; |
- if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first(); |
- String* seq_pat = *pat; |
- if (seq_pat->IsConsString()) seq_pat = ConsString::cast(seq_pat)->first(); |
- |
- if (seq_pat->IsAsciiRepresentation()) { |
- Vector<const char> pat_vector = seq_pat->ToAsciiVector(); |
- if (seq_sub->IsAsciiRepresentation()) { |
- position = StringMatchBackwards(seq_sub->ToAsciiVector(), |
+ |
+ String::FlatContent sub_content = sub->GetFlatContent(no_heap_allocation); |
+ String::FlatContent pat_content = pat->GetFlatContent(no_heap_allocation); |
+ |
+ if (pat_content.IsAscii()) { |
+ Vector<const char> pat_vector = pat_content.ToAsciiVector(); |
+ if (sub_content.IsAscii()) { |
+ position = StringMatchBackwards(sub_content.ToAsciiVector(), |
pat_vector, |
start_index); |
} else { |
- position = StringMatchBackwards(seq_sub->ToUC16Vector(), |
+ position = StringMatchBackwards(sub_content.ToUC16Vector(), |
pat_vector, |
start_index); |
} |
} else { |
- Vector<const uc16> pat_vector = seq_pat->ToUC16Vector(); |
- if (seq_sub->IsAsciiRepresentation()) { |
- position = StringMatchBackwards(seq_sub->ToAsciiVector(), |
+ Vector<const uc16> pat_vector = pat_content.ToUC16Vector(); |
+ if (sub_content.IsAscii()) { |
+ position = StringMatchBackwards(sub_content.ToAsciiVector(), |
pat_vector, |
start_index); |
} else { |
- position = StringMatchBackwards(seq_sub->ToUC16Vector(), |
+ position = StringMatchBackwards(sub_content.ToUC16Vector(), |
pat_vector, |
start_index); |
} |
@@ -3403,36 +3400,38 @@ static bool SearchStringMultiple(Isolate* isolate, |
for (;;) { // Break when search complete. |
builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
AssertNoAllocation no_gc; |
- if (subject->IsAsciiRepresentation()) { |
- Vector<const char> subject_vector = subject->ToAsciiVector(); |
- if (pattern->IsAsciiRepresentation()) { |
+ String::FlatContent subject_content = subject->GetFlatContent(no_gc); |
+ String::FlatContent pattern_content = pattern->GetFlatContent(no_gc); |
+ if (subject_content.IsAscii()) { |
+ Vector<const char> subject_vector = subject_content.ToAsciiVector(); |
+ if (pattern_content.IsAscii()) { |
if (SearchStringMultiple(isolate, |
subject_vector, |
- pattern->ToAsciiVector(), |
+ pattern_content.ToAsciiVector(), |
*pattern, |
builder, |
&match_pos)) break; |
} else { |
if (SearchStringMultiple(isolate, |
subject_vector, |
- pattern->ToUC16Vector(), |
+ pattern_content.ToUC16Vector(), |
*pattern, |
builder, |
&match_pos)) break; |
} |
} else { |
- Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
- if (pattern->IsAsciiRepresentation()) { |
+ Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); |
+ if (pattern_content.IsAscii()) { |
if (SearchStringMultiple(isolate, |
subject_vector, |
- pattern->ToAsciiVector(), |
+ pattern_content.ToAsciiVector(), |
*pattern, |
builder, |
&match_pos)) break; |
} else { |
if (SearchStringMultiple(isolate, |
subject_vector, |
- pattern->ToUC16Vector(), |
+ pattern_content.ToUC16Vector(), |
*pattern, |
builder, |
&match_pos)) break; |
@@ -5420,12 +5419,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) { |
str = String::cast(flat); |
ASSERT(str->IsFlat()); |
} |
- if (str->IsTwoByteRepresentation()) { |
+ AssertNoAllocation no_alloc; |
+ String::FlatContent flat = str->GetFlatContent(no_alloc); |
+ ASSERT(flat.IsFlat()); |
+ if (flat.IsTwoByte()) { |
return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate, |
- str->ToUC16Vector()); |
+ flat.ToUC16Vector()); |
} else { |
return QuoteJsonString<char, SeqAsciiString, false>(isolate, |
- str->ToAsciiVector()); |
+ flat.ToAsciiVector()); |
} |
} |
@@ -5442,12 +5444,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) { |
str = String::cast(flat); |
ASSERT(str->IsFlat()); |
} |
- if (str->IsTwoByteRepresentation()) { |
+ AssertNoAllocation no_alloc; |
+ String::FlatContent flat = str->GetFlatContent(no_alloc); |
+ if (flat.IsTwoByte()) { |
return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate, |
- str->ToUC16Vector()); |
+ flat.ToUC16Vector()); |
} else { |
return QuoteJsonString<char, SeqAsciiString, true>(isolate, |
- str->ToAsciiVector()); |
+ flat.ToAsciiVector()); |
} |
} |
@@ -5482,14 +5486,16 @@ static MaybeObject* QuoteJsonStringArray(Isolate* isolate, |
for (int i = 0; i < length; i++) { |
if (i != 0) *(write_cursor++) = ','; |
String* str = String::cast(array->get(i)); |
- if (str->IsTwoByteRepresentation()) { |
+ String::FlatContent content = str->GetFlatContent(no_gc); |
+ ASSERT(content.IsFlat()); |
+ if (content.IsTwoByte()) { |
write_cursor = WriteQuoteJsonString<Char, uc16>(isolate, |
write_cursor, |
- str->ToUC16Vector()); |
+ content.ToUC16Vector()); |
} else { |
write_cursor = WriteQuoteJsonString<Char, char>(isolate, |
write_cursor, |
- str->ToAsciiVector()); |
+ content.ToAsciiVector()); |
} |
} |
*(write_cursor++) = ']'; |
@@ -5968,11 +5974,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
// No allocation block. |
{ |
- AssertNoAllocation nogc; |
- if (subject->IsAsciiRepresentation()) { |
- Vector<const char> subject_vector = subject->ToAsciiVector(); |
- if (pattern->IsAsciiRepresentation()) { |
- Vector<const char> pattern_vector = pattern->ToAsciiVector(); |
+ AssertNoAllocation no_gc; |
+ String::FlatContent subject_content = subject->GetFlatContent(no_gc); |
+ String::FlatContent pattern_content = pattern->GetFlatContent(no_gc); |
+ ASSERT(subject_content.IsFlat()); |
+ ASSERT(pattern_content.IsFlat()); |
+ if (subject_content.IsAscii()) { |
+ Vector<const char> subject_vector = subject_content.ToAsciiVector(); |
+ if (pattern_content.IsAscii()) { |
+ Vector<const char> pattern_vector = pattern_content.ToAsciiVector(); |
if (pattern_vector.length() == 1) { |
FindAsciiStringIndices(subject_vector, |
pattern_vector[0], |
@@ -5988,22 +5998,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
} else { |
FindStringIndices(isolate, |
subject_vector, |
- pattern->ToUC16Vector(), |
+ pattern_content.ToUC16Vector(), |
&indices, |
limit); |
} |
} else { |
- Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
+ Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); |
if (pattern->IsAsciiRepresentation()) { |
FindStringIndices(isolate, |
subject_vector, |
- pattern->ToAsciiVector(), |
+ pattern_content.ToAsciiVector(), |
&indices, |
limit); |
} else { |
FindStringIndices(isolate, |
subject_vector, |
- pattern->ToUC16Vector(), |
+ pattern_content.ToUC16Vector(), |
&indices, |
limit); |
} |
@@ -6085,36 +6095,40 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) { |
CONVERT_ARG_CHECKED(String, s, 0); |
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); |
- s->TryFlatten(); |
+ s = FlattenGetString(s); |
const int length = static_cast<int>(Min<uint32_t>(s->length(), limit)); |
Handle<FixedArray> elements; |
+ int position = 0; |
if (s->IsFlat() && s->IsAsciiRepresentation()) { |
+ // Try using cached chars where possible. |
Object* obj; |
{ MaybeObject* maybe_obj = |
isolate->heap()->AllocateUninitializedFixedArray(length); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
+ AssertNoAllocation no_alloc; |
elements = Handle<FixedArray>(FixedArray::cast(obj), isolate); |
- |
- Vector<const char> chars = s->ToAsciiVector(); |
- // Note, this will initialize all elements (not only the prefix) |
- // to prevent GC from seeing partially initialized array. |
- int num_copied_from_cache = CopyCachedAsciiCharsToArray(isolate->heap(), |
- chars.start(), |
- *elements, |
- length); |
- |
- for (int i = num_copied_from_cache; i < length; ++i) { |
- Handle<Object> str = LookupSingleCharacterStringFromCode(chars[i]); |
- elements->set(i, *str); |
+ String::FlatContent content = s->GetFlatContent(no_alloc); |
+ if (content.IsAscii()) { |
+ Vector<const char> chars = content.ToAsciiVector(); |
+ // Note, this will initialize all elements (not only the prefix) |
+ // to prevent GC from seeing partially initialized array. |
+ position = CopyCachedAsciiCharsToArray(isolate->heap(), |
+ chars.start(), |
+ *elements, |
+ length); |
+ } else { |
+ MemsetPointer(elements->data_start(), |
+ isolate->heap()->undefined_value(), |
+ length); |
} |
} else { |
elements = isolate->factory()->NewFixedArray(length); |
- for (int i = 0; i < length; ++i) { |
- Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i)); |
- elements->set(i, *str); |
- } |
+ } |
+ for (int i = position; i < length; ++i) { |
+ Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i)); |
+ elements->set(i, *str); |
} |
#ifdef DEBUG |
@@ -6916,6 +6930,7 @@ static Object* StringInputBufferCompare(RuntimeState* state, |
static Object* FlatStringCompare(String* x, String* y) { |
ASSERT(x->IsFlat()); |
ASSERT(y->IsFlat()); |
+ AssertNoAllocation no_alloc; |
Object* equal_prefix_result = Smi::FromInt(EQUAL); |
int prefix_length = x->length(); |
if (y->length() < prefix_length) { |
@@ -6925,22 +6940,24 @@ static Object* FlatStringCompare(String* x, String* y) { |
equal_prefix_result = Smi::FromInt(LESS); |
} |
int r; |
- if (x->IsAsciiRepresentation()) { |
- Vector<const char> x_chars = x->ToAsciiVector(); |
- if (y->IsAsciiRepresentation()) { |
- Vector<const char> y_chars = y->ToAsciiVector(); |
+ String::FlatContent x_content = x->GetFlatContent(no_alloc); |
+ String::FlatContent y_content = y->GetFlatContent(no_alloc); |
+ if (x_content.IsAscii()) { |
+ Vector<const char> x_chars = x_content.ToAsciiVector(); |
+ if (y_content.IsAscii()) { |
+ Vector<const char> y_chars = y_content.ToAsciiVector(); |
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
} else { |
- Vector<const uc16> y_chars = y->ToUC16Vector(); |
+ Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
} |
} else { |
- Vector<const uc16> x_chars = x->ToUC16Vector(); |
- if (y->IsAsciiRepresentation()) { |
- Vector<const char> y_chars = y->ToAsciiVector(); |
+ Vector<const uc16> x_chars = x_content.ToUC16Vector(); |
+ if (y_content.IsAscii()) { |
+ Vector<const char> y_chars = y_content.ToAsciiVector(); |
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
} else { |
- Vector<const uc16> y_chars = y->ToUC16Vector(); |
+ Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
} |
} |
@@ -8821,13 +8838,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) { |
FixedArray* output_array = FixedArray::cast(output->elements()); |
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); |
bool result; |
- if (str->IsAsciiRepresentation()) { |
- result = DateParser::Parse(str->ToAsciiVector(), |
+ String::FlatContent str_content = str->GetFlatContent(no_allocation); |
+ if (str_content.IsAscii()) { |
+ result = DateParser::Parse(str_content.ToAsciiVector(), |
output_array, |
isolate->unicode_cache()); |
} else { |
- ASSERT(str->IsTwoByteRepresentation()); |
- result = DateParser::Parse(str->ToUC16Vector(), |
+ ASSERT(str_content.IsTwoByte()); |
+ result = DateParser::Parse(str_content.ToUC16Vector(), |
output_array, |
isolate->unicode_cache()); |
} |
@@ -12805,9 +12823,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) { |
RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) { |
ASSERT(args.length() == 2); |
+ AssertNoAllocation no_alloc; |
CONVERT_CHECKED(String, format, args[0]); |
CONVERT_CHECKED(JSArray, elms, args[1]); |
- Vector<const char> chars = format->ToAsciiVector(); |
+ String::FlatContent format_content = format->GetFlatContent(no_alloc); |
+ RUNTIME_ASSERT(format_content.IsAscii()); |
+ Vector<const char> chars = format_content.ToAsciiVector(); |
LOGGER->LogRuntime(chars, elms); |
return isolate->heap()->undefined_value(); |
} |