| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index c43a1ab327c5e4952f454b2bb5d20f070e1fcb30..5f79570a240a2707ad8aeee209c0ac1fcbb5a518 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -4524,6 +4524,167 @@ static MaybeObject* Runtime_URIUnescape(Arguments args) {
|
| }
|
|
|
|
|
| +static const char* const JsonQuotes[128] = {
|
| + "\\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",
|
| + NULL, NULL, "\\\"", NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + "\\\\", NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| + NULL, NULL, NULL, NULL,
|
| +};
|
| +
|
| +
|
| +static const byte JsonQuoteLengths[128] = {
|
| + 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 Char>
|
| +Char* WriteString(Char* dst, const char* src_string) {
|
| + char c;
|
| + for (c = *src_string; c; c = *src_string) {
|
| + *dst = c;
|
| + dst++;
|
| + src_string++;
|
| + }
|
| + return dst;
|
| +}
|
| +
|
| +
|
| +template <typename StringType>
|
| +MaybeObject* AllocateRawString(int length);
|
| +
|
| +
|
| +template <>
|
| +MaybeObject* AllocateRawString<SeqTwoByteString>(int length) {
|
| + return Heap::AllocateRawTwoByteString(length);
|
| +}
|
| +
|
| +
|
| +template <>
|
| +MaybeObject* AllocateRawString<SeqAsciiString>(int length) {
|
| + return Heap::AllocateRawAsciiString(length);
|
| +}
|
| +
|
| +
|
| +template <typename Char, typename StringType>
|
| +static MaybeObject* QuoteJsonString(String* original,
|
| + Vector<const Char> characters) {
|
| + int length = characters.length();
|
| + int quoted_length = 0;
|
| + for (int i = 0; i < length; i++) {
|
| + unsigned int c = characters[i];
|
| + if (sizeof(Char) > 1u) {
|
| + quoted_length +=
|
| + (c >= sizeof(JsonQuoteLengths)) ? 1 : JsonQuoteLengths[c];
|
| + } else {
|
| + quoted_length += JsonQuoteLengths[c];
|
| + }
|
| + }
|
| + if (quoted_length == length) {
|
| + return Heap::undefined_value();
|
| + }
|
| + Counters::quote_json_char_count.Increment(length);
|
| +
|
| + // Add space for quotes.
|
| + quoted_length += 2;
|
| +
|
| + MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length);
|
| + Object* new_object;
|
| + if (!new_alloc->ToObject(&new_object)) {
|
| + Counters::quote_json_char_recount.Increment(length);
|
| + return new_alloc;
|
| + }
|
| + StringType* new_string = StringType::cast(new_object);
|
| +
|
| +
|
| + STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
|
| + Char* write_cursor = reinterpret_cast<Char*>(
|
| + new_string->address() + SeqAsciiString::kHeaderSize);
|
| + *(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) >= sizeof(JsonQuotes)) {
|
| + *(write_cursor++) = c;
|
| + } else {
|
| + const char* replacement = JsonQuotes[static_cast<unsigned>(c)];
|
| + if (!replacement) {
|
| + *(write_cursor++) = c;
|
| + } else {
|
| + write_cursor = WriteString(write_cursor, replacement);
|
| + }
|
| + }
|
| + }
|
| + *(write_cursor++) = '"';
|
| + ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char),
|
| + reinterpret_cast<Address>(write_cursor) - new_string->address());
|
| + return new_string;
|
| +}
|
| +
|
| +
|
| +static MaybeObject* Runtime_QuoteJSONString(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>(str, str->ToUC16Vector());
|
| + } else {
|
| + return QuoteJsonString<char, SeqAsciiString>(str, str->ToAsciiVector());
|
| + }
|
| +}
|
| +
|
| +
|
| static MaybeObject* Runtime_StringParseInt(Arguments args) {
|
| NoHandleAllocation ha;
|
|
|
|
|