| 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;
|
|
|
|
|