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

Unified Diff: src/runtime.cc

Issue 7077004: JSON.stringify improvement. Fast case in C++ for string arrays. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 7 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 | « src/runtime.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
===================================================================
--- src/runtime.cc (revision 8080)
+++ src/runtime.cc (working copy)
@@ -3534,13 +3534,13 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
+ CONVERT_SMI_CHECKED(radix, args[1]);
+ RUNTIME_ASSERT(2 <= radix && radix <= 36);
// Fast case where the result is a one character string.
- if (args[0]->IsSmi() && args[1]->IsSmi()) {
+ if (args[0]->IsSmi()) {
int value = Smi::cast(args[0])->value();
- int radix = Smi::cast(args[1])->value();
if (value >= 0 && value < radix) {
- RUNTIME_ASSERT(radix <= 36);
// Character array used for conversion.
static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
return isolate->heap()->
@@ -3559,9 +3559,6 @@
}
return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity"));
}
- CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
- int radix = FastD2I(radix_number);
- RUNTIME_ASSERT(2 <= radix && radix <= 36);
char* str = DoubleToRadixCString(value, radix);
MaybeObject* result =
isolate->heap()->AllocateStringFromAscii(CStrVector(str));
@@ -5011,6 +5008,8 @@
// Doing JSON quoting cannot make the string more than this many times larger.
static const int kJsonQuoteWorstCaseBlowup = 6;
+static const int kSpaceForQuotesAndComma = 3;
+static const int kSpaceForBrackets = 2;
// Covers the entire ASCII range (all other characters are unchanged by JSON
// quoting).
@@ -5098,13 +5097,49 @@
}
+template <typename SinkChar, typename SourceChar>
+static inline SinkChar* WriteQuoteJsonString(
+ Isolate* isolate,
+ SinkChar* write_cursor,
+ Vector<const SourceChar> characters) {
+ const SourceChar* read_cursor = characters.start();
+ const SourceChar* end = read_cursor + characters.length();
+ *(write_cursor++) = '"';
+ while (read_cursor < end) {
+ SourceChar c = *(read_cursor++);
+ if (sizeof(SourceChar) > 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];
+ if (len > 1) {
+ 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++) = '"';
+ return write_cursor;
+}
+
+
template <typename Char, typename StringType, bool comma>
static MaybeObject* QuoteJsonString(Isolate* isolate,
Vector<const Char> characters) {
int length = characters.length();
isolate->counters()->quote_json_char_count()->Increment(length);
- const int kSpaceForQuotes = 2 + (comma ? 1 :0);
- int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
+ int worst_case_length =
+ length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
if (worst_case_length > kMaxGuaranteedNewSpaceString) {
return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
}
@@ -5129,34 +5164,9 @@
Char* write_cursor = reinterpret_cast<Char*>(
new_string->address() + SeqAsciiString::kHeaderSize);
if (comma) *(write_cursor++) = ',';
- *(write_cursor++) = '"';
-
- const Char* read_cursor = characters.start();
- 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];
- if (len > 1) {
- 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++) = '"';
-
+ write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
+ write_cursor,
+ characters);
int final_length = static_cast<int>(
write_cursor - reinterpret_cast<Char*>(
new_string->address() + SeqAsciiString::kHeaderSize));
@@ -5210,6 +5220,101 @@
}
}
+
+template <typename Char, typename StringType>
+static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
+ FixedArray* array,
+ int worst_case_length) {
+ int length = array->length();
+
+ MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
+ worst_case_length);
+ Object* new_object;
+ if (!new_alloc->ToObject(&new_object)) {
+ return new_alloc;
+ }
+ if (!isolate->heap()->new_space()->Contains(new_object)) {
+ // Even if our string is small enough to fit in new space we still have to
+ // 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 isolate->heap()->undefined_value();
+ }
+ AssertNoAllocation no_gc;
+ StringType* new_string = StringType::cast(new_object);
+ ASSERT(isolate->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++) = '[';
+ for (int i = 0; i < length; i++) {
+ if (i != 0) *(write_cursor++) = ',';
+ String* str = String::cast(array->get(i));
+ if (str->IsTwoByteRepresentation()) {
+ write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
+ write_cursor,
+ str->ToUC16Vector());
+ } else {
+ write_cursor = WriteQuoteJsonString<Char, char>(isolate,
+ write_cursor,
+ str->ToAsciiVector());
+ }
+ }
+ *(write_cursor++) = ']';
+
+ int final_length = static_cast<int>(
+ write_cursor - reinterpret_cast<Char*>(
+ new_string->address() + SeqAsciiString::kHeaderSize));
+ isolate->heap()->new_space()->
+ template ShrinkStringAtAllocationBoundary<StringType>(
+ new_string, final_length);
+ return new_string;
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 1);
+ CONVERT_CHECKED(JSArray, array, args[0]);
+
+ if (!array->HasFastElements()) return isolate->heap()->undefined_value();
+ FixedArray* elements = FixedArray::cast(array->elements());
+ int n = elements->length();
+ bool ascii = true;
+ int total_length = 0;
+
+ for (int i = 0; i < n; i++) {
+ Object* elt = elements->get(i);
+ if (!elt->IsString()) return isolate->heap()->undefined_value();
+ String* element = String::cast(elt);
+ if (!element->IsFlat()) return isolate->heap()->undefined_value();
+ total_length += element->length();
+ if (ascii && element->IsTwoByteRepresentation()) {
+ ascii = false;
+ }
+ }
+
+ int worst_case_length =
+ kSpaceForBrackets + n * kSpaceForQuotesAndComma
+ + total_length * kJsonQuoteWorstCaseBlowup;
+
+ if (worst_case_length > kMaxGuaranteedNewSpaceString) {
+ return isolate->heap()->undefined_value();
+ }
+
+ if (ascii) {
+ return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
+ elements,
+ worst_case_length);
+ } else {
+ return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
+ elements,
+ worst_case_length);
+ }
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
NoHandleAllocation ha;
« no previous file with comments | « src/runtime.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698