| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 934c82eb10566973cd6fead748b1144f10b20989..8e251575cbef13d73e96f278dec8a72ebff08364 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -5171,365 +5171,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
|
| }
|
|
|
|
|
| -static const unsigned int kQuoteTableLength = 128u;
|
| -
|
| -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;
|
| -
|
| -static const int kSpaceForQuotesAndComma = 3;
|
| -static const int kSpaceForBrackets = 2;
|
| -
|
| -// Covers the entire ASCII range (all other characters are unchanged by JSON
|
| -// quoting).
|
| -static const byte JsonQuoteLengths[kQuoteTableLength] = {
|
| - 6, 6, 6, 6, 6, 6, 6, 6,
|
| - 2, 2, 2, 6, 2, 2, 6, 6,
|
| - 6, 6, 6, 6, 6, 6, 6, 6,
|
| - 6, 6, 6, 6, 6, 6, 6, 6,
|
| - 1, 1, 2, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 2, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| - 1, 1, 1, 1, 1, 1, 1, 1,
|
| -};
|
| -
|
| -
|
| -template <typename StringType>
|
| -MaybeObject* AllocateRawString(Isolate* isolate, int length);
|
| -
|
| -
|
| -template <>
|
| -MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
|
| - return isolate->heap()->AllocateRawTwoByteString(length);
|
| -}
|
| -
|
| -
|
| -template <>
|
| -MaybeObject* AllocateRawString<SeqOneByteString>(Isolate* isolate, int length) {
|
| - return isolate->heap()->AllocateRawOneByteString(length);
|
| -}
|
| -
|
| -
|
| -template <typename Char, typename StringType, bool comma>
|
| -static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
|
| - Vector<const Char> characters) {
|
| - int length = characters.length();
|
| - const Char* read_cursor = characters.start();
|
| - const Char* end = read_cursor + length;
|
| - const int kSpaceForQuotes = 2 + (comma ? 1 :0);
|
| - int quoted_length = kSpaceForQuotes;
|
| - while (read_cursor < end) {
|
| - Char c = *(read_cursor++);
|
| - if (static_cast<unsigned>(c) >= kQuoteTableLength) {
|
| - quoted_length++;
|
| - } else {
|
| - quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
|
| - }
|
| - }
|
| - MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
|
| - 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() + SeqString::kHeaderSize);
|
| - if (comma) *(write_cursor++) = ',';
|
| - *(write_cursor++) = '"';
|
| -
|
| - read_cursor = characters.start();
|
| - while (read_cursor < end) {
|
| - Char c = *(read_cursor++);
|
| - if (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 SinkChar, typename SourceChar>
|
| -static inline SinkChar* WriteQuoteJsonString(
|
| - Isolate* isolate,
|
| - SinkChar* write_cursor,
|
| - Vector<const SourceChar> characters) {
|
| - // SinkChar is only char if SourceChar is guaranteed to be char.
|
| - ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
|
| - const SourceChar* read_cursor = characters.start();
|
| - const SourceChar* end = read_cursor + characters.length();
|
| - *(write_cursor++) = '"';
|
| - while (read_cursor < end) {
|
| - SourceChar c = *(read_cursor++);
|
| - if (static_cast<unsigned>(c) >= kQuoteTableLength) {
|
| - *(write_cursor++) = static_cast<SinkChar>(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);
|
| - int worst_case_length =
|
| - length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
|
| - if (worst_case_length > kMaxGuaranteedNewSpaceString) {
|
| - return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
|
| - }
|
| -
|
| - 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 SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
|
| - }
|
| - StringType* new_string = StringType::cast(new_object);
|
| - ASSERT(isolate->heap()->new_space()->Contains(new_string));
|
| -
|
| - Char* write_cursor = reinterpret_cast<Char*>(
|
| - new_string->address() + SeqString::kHeaderSize);
|
| - if (comma) *(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() + SeqString::kHeaderSize));
|
| - isolate->heap()->new_space()->
|
| - template ShrinkStringAtAllocationBoundary<StringType>(
|
| - new_string, final_length);
|
| - return new_string;
|
| -}
|
| -
|
| -
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
|
| - NoHandleAllocation ha(isolate);
|
| - CONVERT_ARG_CHECKED(String, str, 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());
|
| - }
|
| - String::FlatContent flat = str->GetFlatContent();
|
| - ASSERT(flat.IsFlat());
|
| - if (flat.IsTwoByte()) {
|
| - return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
|
| - flat.ToUC16Vector());
|
| - } else {
|
| - return QuoteJsonString<uint8_t, SeqOneByteString, false>(
|
| - isolate,
|
| - flat.ToOneByteVector());
|
| - }
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
|
| - NoHandleAllocation ha(isolate);
|
| - CONVERT_ARG_CHECKED(String, str, 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());
|
| - }
|
| - String::FlatContent flat = str->GetFlatContent();
|
| - if (flat.IsTwoByte()) {
|
| - return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
|
| - flat.ToUC16Vector());
|
| - } else {
|
| - return QuoteJsonString<uint8_t, SeqOneByteString, true>(
|
| - isolate,
|
| - flat.ToOneByteVector());
|
| - }
|
| -}
|
| -
|
| -
|
| -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));
|
| -
|
| - Char* write_cursor = reinterpret_cast<Char*>(
|
| - new_string->address() + SeqString::kHeaderSize);
|
| - *(write_cursor++) = '[';
|
| - for (int i = 0; i < length; i++) {
|
| - if (i != 0) *(write_cursor++) = ',';
|
| - String* str = String::cast(array->get(i));
|
| - String::FlatContent content = str->GetFlatContent();
|
| - ASSERT(content.IsFlat());
|
| - if (content.IsTwoByte()) {
|
| - write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
|
| - write_cursor,
|
| - content.ToUC16Vector());
|
| - } else {
|
| - write_cursor =
|
| - WriteQuoteJsonString<Char, uint8_t>(isolate,
|
| - write_cursor,
|
| - content.ToOneByteVector());
|
| - }
|
| - }
|
| - *(write_cursor++) = ']';
|
| -
|
| - int final_length = static_cast<int>(
|
| - write_cursor - reinterpret_cast<Char*>(
|
| - new_string->address() + SeqString::kHeaderSize));
|
| - isolate->heap()->new_space()->
|
| - template ShrinkStringAtAllocationBoundary<StringType>(
|
| - new_string, final_length);
|
| - return new_string;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
|
| - NoHandleAllocation ha(isolate);
|
| + HandleScope scope(isolate);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
|
| ASSERT(args.length() == 1);
|
| - CONVERT_ARG_CHECKED(JSArray, array, 0);
|
| -
|
| - if (!array->HasFastObjectElements()) {
|
| - 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, SeqOneByteString>(isolate,
|
| - elements,
|
| - worst_case_length);
|
| - } else {
|
| - return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
|
| - elements,
|
| - worst_case_length);
|
| - }
|
| + return BasicJsonStringifier::StringifyString(isolate, string);
|
| }
|
|
|
|
|
|
|