Chromium Code Reviews| 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 |