Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2096)

Unified Diff: src/json-stringifier.h

Issue 11234031: Optimize inner-loop in JSON.stringify. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comments Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698