| Index: src/json-stringifier.h
|
| diff --git a/src/json-stringifier.h b/src/json-stringifier.h
|
| index cd3053ae12abecb6afad4cab1cc36b00aa215a06..930f526b765dc15f87b90ed498cc816b59119074 100644
|
| --- a/src/json-stringifier.h
|
| +++ b/src/json-stringifier.h
|
| @@ -59,14 +59,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
| INLINE(void Append_(Char c));
|
|
|
| template <bool is_ascii, typename Char>
|
| - INLINE(void AppendUnchecked_(Char c));
|
| -
|
| - template <bool is_ascii, typename Char>
|
| INLINE(void Append_(const Char* chars));
|
|
|
| - template <bool is_ascii, typename Char>
|
| - INLINE(void AppendUnchecked_(const Char* chars));
|
| -
|
| INLINE(void Append(char c)) {
|
| if (is_ascii_) {
|
| Append_<true>(c);
|
| @@ -123,11 +117,19 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
|
|
| void SerializeString(Handle<String> object);
|
|
|
| + template <typename SrcChar, typename DestChar>
|
| + INLINE(void SerializeStringUnchecked_(const SrcChar* src,
|
| + DestChar* dest,
|
| + int length));
|
| +
|
| template <bool is_ascii, typename Char>
|
| INLINE(void SerializeString_(Vector<const Char> vector,
|
| Handle<String> string));
|
|
|
| template <typename Char>
|
| + INLINE(bool DoNotEscape(Char c));
|
| +
|
| + template <typename Char>
|
| INLINE(Vector<const Char> GetCharVector(Handle<String> string));
|
|
|
| INLINE(Result StackPush(Handle<Object> object));
|
| @@ -152,12 +154,14 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
| int part_length_;
|
| bool is_ascii_;
|
|
|
| - static const int kJsonQuotesCharactersPerEntry = 8;
|
| - static const char* const JsonQuotes;
|
| + static const int kJsonEscapeTableEntrySize = 8;
|
| + static const char* const JsonEscapeTable;
|
| };
|
|
|
|
|
| -const char* const BasicJsonStringifier::JsonQuotes =
|
| +// Translation table to escape ASCII characters.
|
| +// Table entries start at a multiple of 8 and are null-terminated.
|
| +const char* const BasicJsonStringifier::JsonEscapeTable =
|
| "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 "
|
| "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 "
|
| "\\b\0 \\t\0 \\n\0 \\u000b\0 "
|
| @@ -236,30 +240,11 @@ void BasicJsonStringifier::Append_(Char c) {
|
|
|
|
|
| template <bool is_ascii, typename Char>
|
| -void BasicJsonStringifier::AppendUnchecked_(Char c) {
|
| - if (is_ascii) {
|
| - SeqAsciiString::cast(*current_part_)->SeqAsciiStringSet(
|
| - current_index_++, c);
|
| - } else {
|
| - SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet(
|
| - current_index_++, c);
|
| - }
|
| - ASSERT(current_index_ < part_length_);
|
| -}
|
| -
|
| -
|
| -template <bool is_ascii, typename Char>
|
| void BasicJsonStringifier::Append_(const Char* chars) {
|
| for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars);
|
| }
|
|
|
|
|
| -template <bool is_ascii, typename Char>
|
| -void BasicJsonStringifier::AppendUnchecked_(const Char* chars) {
|
| - for ( ; *chars != '\0'; chars++) AppendUnchecked_<is_ascii, Char>(*chars);
|
| -}
|
| -
|
| -
|
| Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object,
|
| Handle<String> key) {
|
| LookupResult lookup(isolate_);
|
| @@ -579,34 +564,60 @@ void BasicJsonStringifier::ChangeEncoding() {
|
| }
|
|
|
|
|
| +template <typename SrcChar, typename DestChar>
|
| +void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
|
| + DestChar* dest,
|
| + int length) {
|
| + dest += current_index_;
|
| + DestChar* dest_start = dest;
|
| +
|
| + *(dest++) = '"';
|
| + for (int i = 0; i < length; i++) {
|
| + SrcChar c = src[i];
|
| + if (DoNotEscape(c)) {
|
| + *(dest++) = c;
|
| + } else {
|
| + const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize];
|
| + while (*chars != '\0') *(dest++) = *(chars++);
|
| + }
|
| + }
|
| +
|
| + *(dest++) = '"';
|
| + current_index_ += dest - dest_start;
|
| +}
|
| +
|
| +
|
| template <bool is_ascii, typename Char>
|
| void BasicJsonStringifier::SerializeString_(Vector<const Char> vector,
|
| Handle<String> string) {
|
| int length = vector.length();
|
| - if (current_index_ + (length << 3) < (part_length_ - 2)) {
|
| - AssertNoAllocation no_allocation_scope;
|
| - AppendUnchecked_<is_ascii, char>('"');
|
| - for (int i = 0; i < length; i++) {
|
| - Char c = vector[i];
|
| - if ((c >= '#' && c <= '~' && c != '\\') ||
|
| - (!is_ascii && ((c & 0xFF80) != 0))) {
|
| - AppendUnchecked_<is_ascii, Char>(c);
|
| - } else {
|
| - AppendUnchecked_<is_ascii, char>(
|
| - &JsonQuotes[c * kJsonQuotesCharactersPerEntry]);
|
| - }
|
| + // We do a rough estimate to find out if the current string can be
|
| + // serialized without allocating a new string part. The worst case length of
|
| + // an escaped character is 6. Shifting left by 3 is a more pessimistic
|
| + // estimate than multiplying by 6, but faster to calculate.
|
| + static const int kEnclosingQuotesLength = 2;
|
| + if (current_index_ + (length << 3) + kEnclosingQuotesLength < part_length_) {
|
| + if (is_ascii) {
|
| + SerializeStringUnchecked_(
|
| + vector.start(),
|
| + SeqAsciiString::cast(*current_part_)->GetChars(),
|
| + length);
|
| + } else {
|
| + SerializeStringUnchecked_(
|
| + vector.start(),
|
| + SeqTwoByteString::cast(*current_part_)->GetChars(),
|
| + length);
|
| }
|
| - AppendUnchecked_<is_ascii, char>('"');
|
| } else {
|
| Append_<is_ascii, char>('"');
|
| String* string_location = *string;
|
| for (int i = 0; i < length; i++) {
|
| Char c = vector[i];
|
| - if ((c >= '#' && c <= '~' && c != '\\') ||
|
| - (!is_ascii && ((c & 0xFF80) != 0))) {
|
| + if (DoNotEscape(c)) {
|
| Append_<is_ascii, Char>(c);
|
| } else {
|
| - Append_<is_ascii, char>(&JsonQuotes[c * kJsonQuotesCharactersPerEntry]);
|
| + Append_<is_ascii, char>(
|
| + &JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
|
| }
|
| // If GC moved the string, we need to refresh the vector.
|
| if (*string != string_location) {
|
| @@ -620,6 +631,18 @@ void BasicJsonStringifier::SerializeString_(Vector<const Char> vector,
|
|
|
|
|
| template <>
|
| +bool BasicJsonStringifier::DoNotEscape(char c) {
|
| + return c >= '#' && c <= '~' && c != '\\';
|
| +}
|
| +
|
| +
|
| +template <>
|
| +bool BasicJsonStringifier::DoNotEscape(uc16 c) {
|
| + return (c >= 0x80) || (c >= '#' && c <= '~' && c != '\\');
|
| +}
|
| +
|
| +
|
| +template <>
|
| Vector<const char> BasicJsonStringifier::GetCharVector(Handle<String> string) {
|
| String::FlatContent flat = string->GetFlatContent();
|
| ASSERT(flat.IsAscii());
|
|
|