Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 5937) |
+++ src/runtime.cc (working copy) |
@@ -4546,42 +4546,53 @@ |
static const unsigned int kQuoteTableLength = 128u; |
-static const char* const JsonQuotes[kQuoteTableLength] = { |
- "\\u0000", "\\u0001", "\\u0002", "\\u0003", |
- "\\u0004", "\\u0005", "\\u0006", "\\u0007", |
- "\\b", "\\t", "\\n", "\\u000b", |
- "\\f", "\\r", "\\u000e", "\\u000f", |
- "\\u0010", "\\u0011", "\\u0012", "\\u0013", |
- "\\u0014", "\\u0015", "\\u0016", "\\u0017", |
- "\\u0018", "\\u0019", "\\u001a", "\\u001b", |
- "\\u001c", "\\u001d", "\\u001e", "\\u001f", |
- NULL, NULL, "\\\"", NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- "\\\\", NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
- NULL, NULL, NULL, NULL, |
-}; |
+static const int kJsonQuotesCharactersPerEntry = 8; |
+static const char* const JsonQuotes = |
+ "\\u0000 \\u0001 \\u0002 \\u0003 " |
+ "\\u0004 \\u0005 \\u0006 \\u0007 " |
+ "\\b \\t \\n \\u000b " |
+ "\\f \\r \\u000e \\u000f " |
+ "\\u0010 \\u0011 \\u0012 \\u0013 " |
+ "\\u0014 \\u0015 \\u0016 \\u0017 " |
+ "\\u0018 \\u0019 \\u001a \\u001b " |
+ "\\u001c \\u001d \\u001e \\u001f " |
+ " ! \\\" # " |
+ "$ % & ' " |
+ "( ) * + " |
+ ", - . / " |
+ "0 1 2 3 " |
+ "4 5 6 7 " |
+ "8 9 : ; " |
+ "< = > ? " |
+ "@ A B C " |
+ "D E F G " |
+ "H I J K " |
+ "L M N O " |
+ "P Q R S " |
+ "T U V W " |
+ "X Y Z [ " |
+ "\\\\ ] ^ _ " |
+ "` a b c " |
+ "d e f g " |
+ "h i j k " |
+ "l m n o " |
+ "p q r s " |
+ "t u v w " |
+ "x y z { " |
+ "| } ~ \177 "; |
+// For a string that is less than 32k characters it should always be |
+// possible to allocate it in new space. |
+static const int kMaxGuaranteedNewSpaceString = 32 * 1024; |
+ |
+ |
+// Doing JSON quoting cannot make the string more than this many times larger. |
+static const int kJsonQuoteWorstCaseBlowup = 6; |
+ |
+ |
+// Covers the entire ASCII range (all other characters are unchanged by JSON |
+// quoting). |
static const byte JsonQuoteLengths[kQuoteTableLength] = { |
Vyacheslav Egorov (Chromium)
2010/12/08 10:51:31
I do not like subtle connection between string abo
Erik Corry
2010/12/08 16:35:56
Changed the string above so it is also 8 per line,
|
6, 6, 6, 6, 6, 6, 6, 6, |
2, 2, 2, 6, 2, 2, 6, 6, |
@@ -4602,18 +4613,6 @@ |
}; |
-template <typename Char> |
-Char* WriteString(Char* dst, const char* src_string) { |
- char c; |
- for (c = *src_string; c; c = *src_string) { |
- *dst = c; |
- dst++; |
- src_string++; |
- } |
- return dst; |
-} |
- |
- |
template <typename StringType> |
MaybeObject* AllocateRawString(int length); |
@@ -4631,58 +4630,102 @@ |
template <typename Char, typename StringType> |
-static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
+static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { |
int length = characters.length(); |
- int quoted_length = 0; |
- for (int i = 0; i < length; i++) { |
- unsigned int c = characters[i]; |
- if (sizeof(Char) > 1u) { |
- quoted_length += (c >= kQuoteTableLength) ? 1 : JsonQuoteLengths[c]; |
+ const Char* read_cursor = characters.start(); |
+ const Char* end = read_cursor + length; |
+ const int kSpaceForQuotes = 2; |
+ int quoted_length = kSpaceForQuotes; |
+ while (read_cursor < end) { |
+ Char c = *(read_cursor++); |
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
+ quoted_length++; |
} else { |
- quoted_length += JsonQuoteLengths[c]; |
+ quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; |
} |
} |
+ MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
+ Object* new_object; |
+ if (!new_alloc->ToObject(&new_object)) { |
+ return new_alloc; |
+ } |
+ StringType* new_string = StringType::cast(new_object); |
+ |
+ Char* write_cursor = reinterpret_cast<Char*>( |
+ new_string->address() + SeqAsciiString::kHeaderSize); |
+ *(write_cursor++) = '"'; |
+ |
+ read_cursor = characters.start(); |
+ while (read_cursor < end) { |
+ Char c = *(read_cursor++); |
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
+ *(write_cursor++) = c; |
+ } else { |
+ int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
+ const char* replacement = JsonQuotes + |
+ static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
+ for (int i = 0; i < len; i++) { |
+ *write_cursor++ = *replacement++; |
+ } |
+ } |
+ } |
+ *(write_cursor++) = '"'; |
+ return new_string; |
+} |
+ |
+ |
+template <typename Char, typename StringType> |
+static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
+ int length = characters.length(); |
Counters::quote_json_char_count.Increment(length); |
+ const int kSpaceForQuotes = 2; |
+ int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
+ if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
+ return SlowQuoteJsonString<Char, StringType>(characters); |
+ } |
- // Add space for quotes. |
- quoted_length += 2; |
- |
- MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
+ MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); |
Object* new_object; |
if (!new_alloc->ToObject(&new_object)) { |
- Counters::quote_json_char_recount.Increment(length); |
return new_alloc; |
} |
StringType* new_string = StringType::cast(new_object); |
+ ASSERT(Heap::new_space()->Contains(new_string)); |
- |
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
Char* write_cursor = reinterpret_cast<Char*>( |
new_string->address() + SeqAsciiString::kHeaderSize); |
*(write_cursor++) = '"'; |
+ |
const Char* read_cursor = characters.start(); |
- if (quoted_length == length + 2) { |
- CopyChars(write_cursor, read_cursor, length); |
- write_cursor += length; |
- } else { |
- const Char* end = read_cursor + length; |
- while (read_cursor < end) { |
- Char c = *(read_cursor++); |
- if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
- *(write_cursor++) = c; |
- } else { |
- const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; |
- if (!replacement) { |
- *(write_cursor++) = c; |
- } else { |
- write_cursor = WriteString(write_cursor, replacement); |
- } |
+ const Char* end = read_cursor + length; |
+ while (read_cursor < end) { |
+ Char c = *(read_cursor++); |
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
+ *(write_cursor++) = c; |
+ } else { |
+ int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
+ const char* replacement = JsonQuotes + |
+ static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
+ write_cursor[0] = replacement[0]; |
Vyacheslav Egorov (Chromium)
2010/12/08 10:51:31
Some replacements have len == 1.
Why we optimisti
Erik Corry
2010/12/08 16:35:56
It is in order to remove mispredicted branches in
|
+ write_cursor[1] = replacement[1]; |
+ if (len > 2) { |
+ ASSERT(len == 6); |
+ write_cursor[2] = replacement[2]; |
+ write_cursor[3] = replacement[3]; |
+ write_cursor[4] = replacement[4]; |
+ write_cursor[5] = replacement[5]; |
} |
+ write_cursor += len; |
} |
} |
*(write_cursor++) = '"'; |
- ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char), |
- reinterpret_cast<Address>(write_cursor) - new_string->address()); |
+ |
+ int final_length = |
+ write_cursor - reinterpret_cast<Char*>( |
+ new_string->address() + SeqAsciiString::kHeaderSize); |
+ Heap::new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string, |
+ final_length); |
return new_string; |
} |