OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4539 int step; | 4539 int step; |
4540 destination->Set(dest_position, Unescape(source, i, length, &step)); | 4540 destination->Set(dest_position, Unescape(source, i, length, &step)); |
4541 i += step; | 4541 i += step; |
4542 } | 4542 } |
4543 return destination; | 4543 return destination; |
4544 } | 4544 } |
4545 | 4545 |
4546 | 4546 |
4547 static const unsigned int kQuoteTableLength = 128u; | 4547 static const unsigned int kQuoteTableLength = 128u; |
4548 | 4548 |
4549 static const char* const JsonQuotes[kQuoteTableLength] = { | 4549 static const int kJsonQuotesCharactersPerEntry = 8; |
4550 "\\u0000", "\\u0001", "\\u0002", "\\u0003", | 4550 static const char* const JsonQuotes = |
4551 "\\u0004", "\\u0005", "\\u0006", "\\u0007", | 4551 "\\u0000 \\u0001 \\u0002 \\u0003 " |
4552 "\\b", "\\t", "\\n", "\\u000b", | 4552 "\\u0004 \\u0005 \\u0006 \\u0007 " |
4553 "\\f", "\\r", "\\u000e", "\\u000f", | 4553 "\\b \\t \\n \\u000b " |
4554 "\\u0010", "\\u0011", "\\u0012", "\\u0013", | 4554 "\\f \\r \\u000e \\u000f " |
4555 "\\u0014", "\\u0015", "\\u0016", "\\u0017", | 4555 "\\u0010 \\u0011 \\u0012 \\u0013 " |
4556 "\\u0018", "\\u0019", "\\u001a", "\\u001b", | 4556 "\\u0014 \\u0015 \\u0016 \\u0017 " |
4557 "\\u001c", "\\u001d", "\\u001e", "\\u001f", | 4557 "\\u0018 \\u0019 \\u001a \\u001b " |
4558 NULL, NULL, "\\\"", NULL, | 4558 "\\u001c \\u001d \\u001e \\u001f " |
4559 NULL, NULL, NULL, NULL, | 4559 " ! \\\" # " |
4560 NULL, NULL, NULL, NULL, | 4560 "$ % & ' " |
4561 NULL, NULL, NULL, NULL, | 4561 "( ) * + " |
4562 NULL, NULL, NULL, NULL, | 4562 ", - . / " |
4563 NULL, NULL, NULL, NULL, | 4563 "0 1 2 3 " |
4564 NULL, NULL, NULL, NULL, | 4564 "4 5 6 7 " |
4565 NULL, NULL, NULL, NULL, | 4565 "8 9 : ; " |
4566 NULL, NULL, NULL, NULL, | 4566 "< = > ? " |
4567 NULL, NULL, NULL, NULL, | 4567 "@ A B C " |
4568 NULL, NULL, NULL, NULL, | 4568 "D E F G " |
4569 NULL, NULL, NULL, NULL, | 4569 "H I J K " |
4570 NULL, NULL, NULL, NULL, | 4570 "L M N O " |
4571 NULL, NULL, NULL, NULL, | 4571 "P Q R S " |
4572 NULL, NULL, NULL, NULL, | 4572 "T U V W " |
4573 "\\\\", NULL, NULL, NULL, | 4573 "X Y Z [ " |
4574 NULL, NULL, NULL, NULL, | 4574 "\\\\ ] ^ _ " |
4575 NULL, NULL, NULL, NULL, | 4575 "` a b c " |
4576 NULL, NULL, NULL, NULL, | 4576 "d e f g " |
4577 NULL, NULL, NULL, NULL, | 4577 "h i j k " |
4578 NULL, NULL, NULL, NULL, | 4578 "l m n o " |
4579 NULL, NULL, NULL, NULL, | 4579 "p q r s " |
4580 NULL, NULL, NULL, NULL, | 4580 "t u v w " |
4581 NULL, NULL, NULL, NULL, | 4581 "x y z { " |
4582 }; | 4582 "| } ~ \177 "; |
4583 | 4583 |
4584 | 4584 |
4585 // For a string that is less than 32k characters it should always be | |
4586 // possible to allocate it in new space. | |
4587 static const int kMaxGuaranteedNewSpaceString = 32 * 1024; | |
4588 | |
4589 | |
4590 // Doing JSON quoting cannot make the string more than this many times larger. | |
4591 static const int kJsonQuoteWorstCaseBlowup = 6; | |
4592 | |
4593 | |
4594 // Covers the entire ASCII range (all other characters are unchanged by JSON | |
4595 // quoting). | |
4585 static const byte JsonQuoteLengths[kQuoteTableLength] = { | 4596 static const byte JsonQuoteLengths[kQuoteTableLength] = { |
Vyacheslav Egorov (Chromium)
2010/12/08 10:51:31
I do not like subtle connection between string abo
Erik Corry
2010/12/08 16:35:56
Changed the string above so it is also 8 per line,
| |
4586 6, 6, 6, 6, 6, 6, 6, 6, | 4597 6, 6, 6, 6, 6, 6, 6, 6, |
4587 2, 2, 2, 6, 2, 2, 6, 6, | 4598 2, 2, 2, 6, 2, 2, 6, 6, |
4588 6, 6, 6, 6, 6, 6, 6, 6, | 4599 6, 6, 6, 6, 6, 6, 6, 6, |
4589 6, 6, 6, 6, 6, 6, 6, 6, | 4600 6, 6, 6, 6, 6, 6, 6, 6, |
4590 1, 1, 2, 1, 1, 1, 1, 1, | 4601 1, 1, 2, 1, 1, 1, 1, 1, |
4591 1, 1, 1, 1, 1, 1, 1, 1, | 4602 1, 1, 1, 1, 1, 1, 1, 1, |
4592 1, 1, 1, 1, 1, 1, 1, 1, | 4603 1, 1, 1, 1, 1, 1, 1, 1, |
4593 1, 1, 1, 1, 1, 1, 1, 1, | 4604 1, 1, 1, 1, 1, 1, 1, 1, |
4594 1, 1, 1, 1, 1, 1, 1, 1, | 4605 1, 1, 1, 1, 1, 1, 1, 1, |
4595 1, 1, 1, 1, 1, 1, 1, 1, | 4606 1, 1, 1, 1, 1, 1, 1, 1, |
4596 1, 1, 1, 1, 1, 1, 1, 1, | 4607 1, 1, 1, 1, 1, 1, 1, 1, |
4597 1, 1, 1, 1, 2, 1, 1, 1, | 4608 1, 1, 1, 1, 2, 1, 1, 1, |
4598 1, 1, 1, 1, 1, 1, 1, 1, | 4609 1, 1, 1, 1, 1, 1, 1, 1, |
4599 1, 1, 1, 1, 1, 1, 1, 1, | 4610 1, 1, 1, 1, 1, 1, 1, 1, |
4600 1, 1, 1, 1, 1, 1, 1, 1, | 4611 1, 1, 1, 1, 1, 1, 1, 1, |
4601 1, 1, 1, 1, 1, 1, 1, 1, | 4612 1, 1, 1, 1, 1, 1, 1, 1, |
4602 }; | 4613 }; |
4603 | 4614 |
4604 | 4615 |
4605 template <typename Char> | |
4606 Char* WriteString(Char* dst, const char* src_string) { | |
4607 char c; | |
4608 for (c = *src_string; c; c = *src_string) { | |
4609 *dst = c; | |
4610 dst++; | |
4611 src_string++; | |
4612 } | |
4613 return dst; | |
4614 } | |
4615 | |
4616 | |
4617 template <typename StringType> | 4616 template <typename StringType> |
4618 MaybeObject* AllocateRawString(int length); | 4617 MaybeObject* AllocateRawString(int length); |
4619 | 4618 |
4620 | 4619 |
4621 template <> | 4620 template <> |
4622 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { | 4621 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { |
4623 return Heap::AllocateRawTwoByteString(length); | 4622 return Heap::AllocateRawTwoByteString(length); |
4624 } | 4623 } |
4625 | 4624 |
4626 | 4625 |
4627 template <> | 4626 template <> |
4628 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { | 4627 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
4629 return Heap::AllocateRawAsciiString(length); | 4628 return Heap::AllocateRawAsciiString(length); |
4630 } | 4629 } |
4631 | 4630 |
4632 | 4631 |
4633 template <typename Char, typename StringType> | 4632 template <typename Char, typename StringType> |
4633 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { | |
4634 int length = characters.length(); | |
4635 const Char* read_cursor = characters.start(); | |
4636 const Char* end = read_cursor + length; | |
4637 const int kSpaceForQuotes = 2; | |
4638 int quoted_length = kSpaceForQuotes; | |
4639 while (read_cursor < end) { | |
4640 Char c = *(read_cursor++); | |
4641 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | |
4642 quoted_length++; | |
4643 } else { | |
4644 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; | |
4645 } | |
4646 } | |
4647 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); | |
4648 Object* new_object; | |
4649 if (!new_alloc->ToObject(&new_object)) { | |
4650 return new_alloc; | |
4651 } | |
4652 StringType* new_string = StringType::cast(new_object); | |
4653 | |
4654 Char* write_cursor = reinterpret_cast<Char*>( | |
4655 new_string->address() + SeqAsciiString::kHeaderSize); | |
4656 *(write_cursor++) = '"'; | |
4657 | |
4658 read_cursor = characters.start(); | |
4659 while (read_cursor < end) { | |
4660 Char c = *(read_cursor++); | |
4661 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | |
4662 *(write_cursor++) = c; | |
4663 } else { | |
4664 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | |
4665 const char* replacement = JsonQuotes + | |
4666 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; | |
4667 for (int i = 0; i < len; i++) { | |
4668 *write_cursor++ = *replacement++; | |
4669 } | |
4670 } | |
4671 } | |
4672 *(write_cursor++) = '"'; | |
4673 return new_string; | |
4674 } | |
4675 | |
4676 | |
4677 template <typename Char, typename StringType> | |
4634 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { | 4678 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
4635 int length = characters.length(); | 4679 int length = characters.length(); |
4636 int quoted_length = 0; | 4680 Counters::quote_json_char_count.Increment(length); |
4637 for (int i = 0; i < length; i++) { | 4681 const int kSpaceForQuotes = 2; |
4638 unsigned int c = characters[i]; | 4682 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
4639 if (sizeof(Char) > 1u) { | 4683 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
4640 quoted_length += (c >= kQuoteTableLength) ? 1 : JsonQuoteLengths[c]; | 4684 return SlowQuoteJsonString<Char, StringType>(characters); |
4641 } else { | |
4642 quoted_length += JsonQuoteLengths[c]; | |
4643 } | |
4644 } | 4685 } |
4645 Counters::quote_json_char_count.Increment(length); | |
4646 | 4686 |
4647 // Add space for quotes. | 4687 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); |
4648 quoted_length += 2; | |
4649 | |
4650 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); | |
4651 Object* new_object; | 4688 Object* new_object; |
4652 if (!new_alloc->ToObject(&new_object)) { | 4689 if (!new_alloc->ToObject(&new_object)) { |
4653 Counters::quote_json_char_recount.Increment(length); | |
4654 return new_alloc; | 4690 return new_alloc; |
4655 } | 4691 } |
4656 StringType* new_string = StringType::cast(new_object); | 4692 StringType* new_string = StringType::cast(new_object); |
4657 | 4693 ASSERT(Heap::new_space()->Contains(new_string)); |
4658 | 4694 |
4659 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4695 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
4660 Char* write_cursor = reinterpret_cast<Char*>( | 4696 Char* write_cursor = reinterpret_cast<Char*>( |
4661 new_string->address() + SeqAsciiString::kHeaderSize); | 4697 new_string->address() + SeqAsciiString::kHeaderSize); |
4662 *(write_cursor++) = '"'; | 4698 *(write_cursor++) = '"'; |
4699 | |
4663 const Char* read_cursor = characters.start(); | 4700 const Char* read_cursor = characters.start(); |
4664 if (quoted_length == length + 2) { | 4701 const Char* end = read_cursor + length; |
4665 CopyChars(write_cursor, read_cursor, length); | 4702 while (read_cursor < end) { |
4666 write_cursor += length; | 4703 Char c = *(read_cursor++); |
4667 } else { | 4704 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
4668 const Char* end = read_cursor + length; | 4705 *(write_cursor++) = c; |
4669 while (read_cursor < end) { | 4706 } else { |
4670 Char c = *(read_cursor++); | 4707 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
4671 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4708 const char* replacement = JsonQuotes + |
4672 *(write_cursor++) = c; | 4709 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
4673 } else { | 4710 write_cursor[0] = replacement[0]; |
Vyacheslav Egorov (Chromium)
2010/12/08 10:51:31
Some replacements have len == 1.
Why we optimisti
Erik Corry
2010/12/08 16:35:56
It is in order to remove mispredicted branches in
| |
4674 const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; | 4711 write_cursor[1] = replacement[1]; |
4675 if (!replacement) { | 4712 if (len > 2) { |
4676 *(write_cursor++) = c; | 4713 ASSERT(len == 6); |
4677 } else { | 4714 write_cursor[2] = replacement[2]; |
4678 write_cursor = WriteString(write_cursor, replacement); | 4715 write_cursor[3] = replacement[3]; |
4679 } | 4716 write_cursor[4] = replacement[4]; |
4717 write_cursor[5] = replacement[5]; | |
4680 } | 4718 } |
4719 write_cursor += len; | |
4681 } | 4720 } |
4682 } | 4721 } |
4683 *(write_cursor++) = '"'; | 4722 *(write_cursor++) = '"'; |
4684 ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char), | 4723 |
4685 reinterpret_cast<Address>(write_cursor) - new_string->address()); | 4724 int final_length = |
4725 write_cursor - reinterpret_cast<Char*>( | |
4726 new_string->address() + SeqAsciiString::kHeaderSize); | |
4727 Heap::new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string, | |
4728 final_length); | |
4686 return new_string; | 4729 return new_string; |
4687 } | 4730 } |
4688 | 4731 |
4689 | 4732 |
4690 static MaybeObject* Runtime_QuoteJSONString(Arguments args) { | 4733 static MaybeObject* Runtime_QuoteJSONString(Arguments args) { |
4691 NoHandleAllocation ha; | 4734 NoHandleAllocation ha; |
4692 CONVERT_CHECKED(String, str, args[0]); | 4735 CONVERT_CHECKED(String, str, args[0]); |
4693 if (!str->IsFlat()) { | 4736 if (!str->IsFlat()) { |
4694 MaybeObject* try_flatten = str->TryFlatten(); | 4737 MaybeObject* try_flatten = str->TryFlatten(); |
4695 Object* flat; | 4738 Object* flat; |
(...skipping 6088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10784 } else { | 10827 } else { |
10785 // Handle last resort GC and make sure to allow future allocations | 10828 // Handle last resort GC and make sure to allow future allocations |
10786 // to grow the heap without causing GCs (if possible). | 10829 // to grow the heap without causing GCs (if possible). |
10787 Counters::gc_last_resort_from_js.Increment(); | 10830 Counters::gc_last_resort_from_js.Increment(); |
10788 Heap::CollectAllGarbage(false); | 10831 Heap::CollectAllGarbage(false); |
10789 } | 10832 } |
10790 } | 10833 } |
10791 | 10834 |
10792 | 10835 |
10793 } } // namespace v8::internal | 10836 } } // namespace v8::internal |
OLD | NEW |