Revision: 6337
Author: [email protected]
Date: Sun Jan 16 13:29:32 2011
Log: Optimize JSON stringify by allowing QuoteJSONString to prefix with a
comma.
Review URL: http://codereview.chromium.org/6335004
http://code.google.com/p/v8/source/detail?r=6337
Modified:
/branches/bleeding_edge/src/json.js
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
=======================================
--- /branches/bleeding_edge/src/json.js Wed Jan 12 06:16:19 2011
+++ /branches/bleeding_edge/src/json.js Sun Jan 16 13:29:32 2011
@@ -193,14 +193,14 @@
// First entry is a string. Remaining entries are likely to be strings
too.
builder.push(%QuoteJSONString(val));
for (var i = 1; i < len; i++) {
- builder.push(",");
val = value[i];
if (IS_STRING(val)) {
- builder.push(%QuoteJSONString(val));
+ builder.push(%QuoteJSONStringComma(val));
} else {
+ builder.push(",");
var before = builder.length;
BasicJSONSerialize(i, value[i], stack, builder);
- if (before == builder.length) builder.push("null");
+ if (before == builder.length) builder[before - 1] = ",null";
}
}
} else if (IS_NUMBER(val)) {
@@ -216,7 +216,7 @@
} else {
var before = builder.length;
BasicJSONSerialize(i, value[i], stack, builder);
- if (before == builder.length) builder.push("null");
+ if (before == builder.length) builder[before - 1] = ",null";
}
}
} else {
@@ -228,7 +228,7 @@
before = builder.length;
val = value[i];
BasicJSONSerialize(i, val, stack, builder);
- if (before == builder.length) builder.push("null");
+ if (before == builder.length) builder[before - 1] = ",null";
}
}
stack.pop();
@@ -241,9 +241,14 @@
throw MakeTypeError('circular_structure', []);
}
builder.push("{");
+ var first = true;
for (var p in value) {
if (%HasLocalProperty(value, p)) {
- builder.push(%QuoteJSONString(p));
+ if (!first) {
+ builder.push(%QuoteJSONStringComma(p));
+ } else {
+ builder.push(%QuoteJSONString(p));
+ }
builder.push(":");
var before = builder.length;
BasicJSONSerialize(p, value[p], stack, builder);
@@ -251,16 +256,12 @@
builder.pop();
builder.pop();
} else {
- builder.push(",");
+ first = false;
}
}
}
stack.pop();
- if (builder.pop() != ",") {
- builder.push("{}"); // Object has no own properties. Push "{" back on.
- } else {
- builder.push("}");
- }
+ builder.push("}");
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Jan 11 06:55:47 2011
+++ /branches/bleeding_edge/src/runtime.cc Sun Jan 16 13:29:32 2011
@@ -4621,12 +4621,12 @@
}
-template <typename Char, typename StringType>
+template <typename Char, typename StringType, bool comma>
static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) {
int length = characters.length();
const Char* read_cursor = characters.start();
const Char* end = read_cursor + length;
- const int kSpaceForQuotes = 2;
+ const int kSpaceForQuotes = 2 + (comma ? 1 :0);
int quoted_length = kSpaceForQuotes;
while (read_cursor < end) {
Char c = *(read_cursor++);
@@ -4645,6 +4645,7 @@
Char* write_cursor = reinterpret_cast<Char*>(
new_string->address() + SeqAsciiString::kHeaderSize);
+ if (comma) *(write_cursor++) = ',';
*(write_cursor++) = '"';
read_cursor = characters.start();
@@ -4666,14 +4667,14 @@
}
-template <typename Char, typename StringType>
+template <typename Char, typename StringType, bool comma>
static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
int length = characters.length();
Counters::quote_json_char_count.Increment(length);
- const int kSpaceForQuotes = 2;
+ const int kSpaceForQuotes = 2 + (comma ? 1 :0);
int worst_case_length = length * kJsonQuoteWorstCaseBlowup +
kSpaceForQuotes;
if (worst_case_length > kMaxGuaranteedNewSpaceString) {
- return SlowQuoteJsonString<Char, StringType>(characters);
+ return SlowQuoteJsonString<Char, StringType, comma>(characters);
}
MaybeObject* new_alloc =
AllocateRawString<StringType>(worst_case_length);
@@ -4686,7 +4687,7 @@
// handle it being allocated in old space as may happen in the third
// attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
// CEntryStub::GenerateCore.
- return SlowQuoteJsonString<Char, StringType>(characters);
+ return SlowQuoteJsonString<Char, StringType, comma>(characters);
}
StringType* new_string = StringType::cast(new_object);
ASSERT(Heap::new_space()->Contains(new_string));
@@ -4694,6 +4695,7 @@
STATIC_ASSERT(SeqTwoByteString::kHeaderSize ==
SeqAsciiString::kHeaderSize);
Char* write_cursor = reinterpret_cast<Char*>(
new_string->address() + SeqAsciiString::kHeaderSize);
+ if (comma) *(write_cursor++) = ',';
*(write_cursor++) = '"';
const Char* read_cursor = characters.start();
@@ -4744,13 +4746,32 @@
ASSERT(str->IsFlat());
}
if (str->IsTwoByteRepresentation()) {
- return QuoteJsonString<uc16, SeqTwoByteString>(str->ToUC16Vector());
+ return QuoteJsonString<uc16, SeqTwoByteString,
false>(str->ToUC16Vector());
} else {
- return QuoteJsonString<char, SeqAsciiString>(str->ToAsciiVector());
+ return QuoteJsonString<char, SeqAsciiString,
false>(str->ToAsciiVector());
}
}
+static MaybeObject* Runtime_QuoteJSONStringComma(Arguments args) {
+ NoHandleAllocation ha;
+ CONVERT_CHECKED(String, str, args[0]);
+ if (!str->IsFlat()) {
+ MaybeObject* try_flatten = str->TryFlatten();
+ Object* flat;
+ if (!try_flatten->ToObject(&flat)) {
+ return try_flatten;
+ }
+ str = String::cast(flat);
+ ASSERT(str->IsFlat());
+ }
+ if (str->IsTwoByteRepresentation()) {
+ return QuoteJsonString<uc16, SeqTwoByteString,
true>(str->ToUC16Vector());
+ } else {
+ return QuoteJsonString<char, SeqAsciiString,
true>(str->ToAsciiVector());
+ }
+}
+
static MaybeObject* Runtime_StringParseInt(Arguments args) {
NoHandleAllocation ha;
=======================================
--- /branches/bleeding_edge/src/runtime.h Tue Jan 11 06:55:47 2011
+++ /branches/bleeding_edge/src/runtime.h Sun Jan 16 13:29:32 2011
@@ -106,6 +106,7 @@
F(URIEscape, 1, 1) \
F(URIUnescape, 1, 1) \
F(QuoteJSONString, 1, 1) \
+ F(QuoteJSONStringComma, 1, 1) \
\
F(NumberToString, 1, 1) \
F(NumberToStringSkipCache, 1, 1) \
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev