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 int kJsonQuotesCharactersPerEntry = 8; | 4549 static const char* const JsonQuotes[kQuoteTableLength] = { |
4550 static const char* const JsonQuotes = | 4550 "\\u0000", "\\u0001", "\\u0002", "\\u0003", |
4551 "\\u0000 \\u0001 \\u0002 \\u0003 " | 4551 "\\u0004", "\\u0005", "\\u0006", "\\u0007", |
4552 "\\u0004 \\u0005 \\u0006 \\u0007 " | 4552 "\\b", "\\t", "\\n", "\\u000b", |
4553 "\\b \\t \\n \\u000b " | 4553 "\\f", "\\r", "\\u000e", "\\u000f", |
4554 "\\f \\r \\u000e \\u000f " | 4554 "\\u0010", "\\u0011", "\\u0012", "\\u0013", |
4555 "\\u0010 \\u0011 \\u0012 \\u0013 " | 4555 "\\u0014", "\\u0015", "\\u0016", "\\u0017", |
4556 "\\u0014 \\u0015 \\u0016 \\u0017 " | 4556 "\\u0018", "\\u0019", "\\u001a", "\\u001b", |
4557 "\\u0018 \\u0019 \\u001a \\u001b " | 4557 "\\u001c", "\\u001d", "\\u001e", "\\u001f", |
4558 "\\u001c \\u001d \\u001e \\u001f " | 4558 NULL, NULL, "\\\"", NULL, |
4559 " ! \\\" # " | 4559 NULL, NULL, NULL, NULL, |
4560 "$ % & ' " | 4560 NULL, NULL, NULL, NULL, |
4561 "( ) * + " | 4561 NULL, NULL, NULL, NULL, |
4562 ", - . / " | 4562 NULL, NULL, NULL, NULL, |
4563 "0 1 2 3 " | 4563 NULL, NULL, NULL, NULL, |
4564 "4 5 6 7 " | 4564 NULL, NULL, NULL, NULL, |
4565 "8 9 : ; " | 4565 NULL, NULL, NULL, NULL, |
4566 "< = > ? " | 4566 NULL, NULL, NULL, NULL, |
4567 "@ A B C " | 4567 NULL, NULL, NULL, NULL, |
4568 "D E F G " | 4568 NULL, NULL, NULL, NULL, |
4569 "H I J K " | 4569 NULL, NULL, NULL, NULL, |
4570 "L M N O " | 4570 NULL, NULL, NULL, NULL, |
4571 "P Q R S " | 4571 NULL, NULL, NULL, NULL, |
4572 "T U V W " | 4572 NULL, NULL, NULL, NULL, |
4573 "X Y Z [ " | 4573 "\\\\", NULL, NULL, NULL, |
4574 "\\\\ ] ^ _ " | 4574 NULL, NULL, NULL, NULL, |
4575 "` a b c " | 4575 NULL, NULL, NULL, NULL, |
4576 "d e f g " | 4576 NULL, NULL, NULL, NULL, |
4577 "h i j k " | 4577 NULL, NULL, NULL, NULL, |
4578 "l m n o " | 4578 NULL, NULL, NULL, NULL, |
4579 "p q r s " | 4579 NULL, NULL, NULL, NULL, |
4580 "t u v w " | 4580 NULL, NULL, NULL, NULL, |
4581 "x y z { " | 4581 NULL, NULL, NULL, NULL, |
4582 "| } ~ \177 "; | 4582 }; |
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). | |
4596 static const byte JsonQuoteLengths[kQuoteTableLength] = { | 4585 static const byte JsonQuoteLengths[kQuoteTableLength] = { |
4597 6, 6, 6, 6, 6, 6, 6, 6, | 4586 6, 6, 6, 6, 6, 6, 6, 6, |
4598 2, 2, 2, 6, 2, 2, 6, 6, | 4587 2, 2, 2, 6, 2, 2, 6, 6, |
4599 6, 6, 6, 6, 6, 6, 6, 6, | 4588 6, 6, 6, 6, 6, 6, 6, 6, |
4600 6, 6, 6, 6, 6, 6, 6, 6, | 4589 6, 6, 6, 6, 6, 6, 6, 6, |
4601 1, 1, 2, 1, 1, 1, 1, 1, | 4590 1, 1, 2, 1, 1, 1, 1, 1, |
4602 1, 1, 1, 1, 1, 1, 1, 1, | 4591 1, 1, 1, 1, 1, 1, 1, 1, |
4603 1, 1, 1, 1, 1, 1, 1, 1, | 4592 1, 1, 1, 1, 1, 1, 1, 1, |
4604 1, 1, 1, 1, 1, 1, 1, 1, | 4593 1, 1, 1, 1, 1, 1, 1, 1, |
4605 1, 1, 1, 1, 1, 1, 1, 1, | 4594 1, 1, 1, 1, 1, 1, 1, 1, |
4606 1, 1, 1, 1, 1, 1, 1, 1, | 4595 1, 1, 1, 1, 1, 1, 1, 1, |
4607 1, 1, 1, 1, 1, 1, 1, 1, | 4596 1, 1, 1, 1, 1, 1, 1, 1, |
4608 1, 1, 1, 1, 2, 1, 1, 1, | 4597 1, 1, 1, 1, 2, 1, 1, 1, |
4609 1, 1, 1, 1, 1, 1, 1, 1, | 4598 1, 1, 1, 1, 1, 1, 1, 1, |
4610 1, 1, 1, 1, 1, 1, 1, 1, | 4599 1, 1, 1, 1, 1, 1, 1, 1, |
4611 1, 1, 1, 1, 1, 1, 1, 1, | 4600 1, 1, 1, 1, 1, 1, 1, 1, |
4612 1, 1, 1, 1, 1, 1, 1, 1, | 4601 1, 1, 1, 1, 1, 1, 1, 1, |
4613 }; | 4602 }; |
4614 | 4603 |
4615 | 4604 |
| 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 |
4616 template <typename StringType> | 4617 template <typename StringType> |
4617 MaybeObject* AllocateRawString(int length); | 4618 MaybeObject* AllocateRawString(int length); |
4618 | 4619 |
4619 | 4620 |
4620 template <> | 4621 template <> |
4621 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { | 4622 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { |
4622 return Heap::AllocateRawTwoByteString(length); | 4623 return Heap::AllocateRawTwoByteString(length); |
4623 } | 4624 } |
4624 | 4625 |
4625 | 4626 |
4626 template <> | 4627 template <> |
4627 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { | 4628 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
4628 return Heap::AllocateRawAsciiString(length); | 4629 return Heap::AllocateRawAsciiString(length); |
4629 } | 4630 } |
4630 | 4631 |
4631 | 4632 |
4632 template <typename Char, typename StringType> | 4633 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> | |
4678 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { | 4634 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
4679 int length = characters.length(); | 4635 int length = characters.length(); |
| 4636 int quoted_length = 0; |
| 4637 for (int i = 0; i < length; i++) { |
| 4638 unsigned int c = characters[i]; |
| 4639 if (sizeof(Char) > 1u) { |
| 4640 quoted_length += (c >= kQuoteTableLength) ? 1 : JsonQuoteLengths[c]; |
| 4641 } else { |
| 4642 quoted_length += JsonQuoteLengths[c]; |
| 4643 } |
| 4644 } |
4680 Counters::quote_json_char_count.Increment(length); | 4645 Counters::quote_json_char_count.Increment(length); |
4681 const int kSpaceForQuotes = 2; | |
4682 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | |
4683 if (worst_case_length > kMaxGuaranteedNewSpaceString) { | |
4684 return SlowQuoteJsonString<Char, StringType>(characters); | |
4685 } | |
4686 | 4646 |
4687 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); | 4647 // Add space for quotes. |
| 4648 quoted_length += 2; |
| 4649 |
| 4650 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
4688 Object* new_object; | 4651 Object* new_object; |
4689 if (!new_alloc->ToObject(&new_object)) { | 4652 if (!new_alloc->ToObject(&new_object)) { |
| 4653 Counters::quote_json_char_recount.Increment(length); |
4690 return new_alloc; | 4654 return new_alloc; |
4691 } | 4655 } |
4692 if (!Heap::new_space()->Contains(new_object)) { | |
4693 // Even if our string is small enough to fit in new space we still have to | |
4694 // handle it being allocated in old space as may happen in the third | |
4695 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | |
4696 // CEntryStub::GenerateCore. | |
4697 return SlowQuoteJsonString<Char, StringType>(characters); | |
4698 } | |
4699 StringType* new_string = StringType::cast(new_object); | 4656 StringType* new_string = StringType::cast(new_object); |
4700 ASSERT(Heap::new_space()->Contains(new_string)); | 4657 |
4701 | 4658 |
4702 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4659 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
4703 Char* write_cursor = reinterpret_cast<Char*>( | 4660 Char* write_cursor = reinterpret_cast<Char*>( |
4704 new_string->address() + SeqAsciiString::kHeaderSize); | 4661 new_string->address() + SeqAsciiString::kHeaderSize); |
4705 *(write_cursor++) = '"'; | 4662 *(write_cursor++) = '"'; |
4706 | |
4707 const Char* read_cursor = characters.start(); | 4663 const Char* read_cursor = characters.start(); |
4708 const Char* end = read_cursor + length; | 4664 if (quoted_length == length + 2) { |
4709 while (read_cursor < end) { | 4665 CopyChars(write_cursor, read_cursor, length); |
4710 Char c = *(read_cursor++); | 4666 write_cursor += length; |
4711 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4667 } else { |
4712 *(write_cursor++) = c; | 4668 const Char* end = read_cursor + length; |
4713 } else { | 4669 while (read_cursor < end) { |
4714 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 4670 Char c = *(read_cursor++); |
4715 const char* replacement = JsonQuotes + | 4671 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
4716 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; | 4672 *(write_cursor++) = c; |
4717 write_cursor[0] = replacement[0]; | 4673 } else { |
4718 if (len > 1) { | 4674 const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; |
4719 write_cursor[1] = replacement[1]; | 4675 if (!replacement) { |
4720 if (len > 2) { | 4676 *(write_cursor++) = c; |
4721 ASSERT(len == 6); | 4677 } else { |
4722 write_cursor[2] = replacement[2]; | 4678 write_cursor = WriteString(write_cursor, replacement); |
4723 write_cursor[3] = replacement[3]; | |
4724 write_cursor[4] = replacement[4]; | |
4725 write_cursor[5] = replacement[5]; | |
4726 } | 4679 } |
4727 } | 4680 } |
4728 write_cursor += len; | |
4729 } | 4681 } |
4730 } | 4682 } |
4731 *(write_cursor++) = '"'; | 4683 *(write_cursor++) = '"'; |
4732 | 4684 ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char), |
4733 int final_length = static_cast<int>( | 4685 reinterpret_cast<Address>(write_cursor) - new_string->address()); |
4734 write_cursor - reinterpret_cast<Char*>( | |
4735 new_string->address() + SeqAsciiString::kHeaderSize)); | |
4736 Heap::new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string, | |
4737 final_length); | |
4738 return new_string; | 4686 return new_string; |
4739 } | 4687 } |
4740 | 4688 |
4741 | 4689 |
4742 static MaybeObject* Runtime_QuoteJSONString(Arguments args) { | 4690 static MaybeObject* Runtime_QuoteJSONString(Arguments args) { |
4743 NoHandleAllocation ha; | 4691 NoHandleAllocation ha; |
4744 CONVERT_CHECKED(String, str, args[0]); | 4692 CONVERT_CHECKED(String, str, args[0]); |
4745 if (!str->IsFlat()) { | 4693 if (!str->IsFlat()) { |
4746 MaybeObject* try_flatten = str->TryFlatten(); | 4694 MaybeObject* try_flatten = str->TryFlatten(); |
4747 Object* flat; | 4695 Object* flat; |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6022 static MaybeObject* Runtime_Math_log(Arguments args) { | 5970 static MaybeObject* Runtime_Math_log(Arguments args) { |
6023 NoHandleAllocation ha; | 5971 NoHandleAllocation ha; |
6024 ASSERT(args.length() == 1); | 5972 ASSERT(args.length() == 1); |
6025 Counters::math_log.Increment(); | 5973 Counters::math_log.Increment(); |
6026 | 5974 |
6027 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5975 CONVERT_DOUBLE_CHECKED(x, args[0]); |
6028 return TranscendentalCache::Get(TranscendentalCache::LOG, x); | 5976 return TranscendentalCache::Get(TranscendentalCache::LOG, x); |
6029 } | 5977 } |
6030 | 5978 |
6031 | 5979 |
| 5980 // Helper function to compute x^y, where y is known to be an |
| 5981 // integer. Uses binary decomposition to limit the number of |
| 5982 // multiplications; see the discussion in "Hacker's Delight" by Henry |
| 5983 // S. Warren, Jr., figure 11-6, page 213. |
| 5984 static double powi(double x, int y) { |
| 5985 ASSERT(y != kMinInt); |
| 5986 unsigned n = (y < 0) ? -y : y; |
| 5987 double m = x; |
| 5988 double p = 1; |
| 5989 while (true) { |
| 5990 if ((n & 1) != 0) p *= m; |
| 5991 n >>= 1; |
| 5992 if (n == 0) { |
| 5993 if (y < 0) { |
| 5994 // Unfortunately, we have to be careful when p has reached |
| 5995 // infinity in the computation, because sometimes the higher |
| 5996 // internal precision in the pow() implementation would have |
| 5997 // given us a finite p. This happens very rarely. |
| 5998 double result = 1.0 / p; |
| 5999 return (result == 0 && isinf(p)) |
| 6000 ? pow(x, static_cast<double>(y)) // Avoid pow(double, int). |
| 6001 : result; |
| 6002 } else { |
| 6003 return p; |
| 6004 } |
| 6005 } |
| 6006 m *= m; |
| 6007 } |
| 6008 } |
| 6009 |
| 6010 |
6032 static MaybeObject* Runtime_Math_pow(Arguments args) { | 6011 static MaybeObject* Runtime_Math_pow(Arguments args) { |
6033 NoHandleAllocation ha; | 6012 NoHandleAllocation ha; |
6034 ASSERT(args.length() == 2); | 6013 ASSERT(args.length() == 2); |
6035 Counters::math_pow.Increment(); | 6014 Counters::math_pow.Increment(); |
6036 | 6015 |
6037 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6016 CONVERT_DOUBLE_CHECKED(x, args[0]); |
6038 | 6017 |
6039 // If the second argument is a smi, it is much faster to call the | 6018 // If the second argument is a smi, it is much faster to call the |
6040 // custom powi() function than the generic pow(). | 6019 // custom powi() function than the generic pow(). |
6041 if (args[1]->IsSmi()) { | 6020 if (args[1]->IsSmi()) { |
6042 int y = Smi::cast(args[1])->value(); | 6021 int y = Smi::cast(args[1])->value(); |
6043 return Heap::NumberFromDouble(power_double_int(x, y)); | 6022 return Heap::NumberFromDouble(powi(x, y)); |
6044 } | 6023 } |
6045 | 6024 |
6046 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6025 CONVERT_DOUBLE_CHECKED(y, args[1]); |
6047 return Heap::AllocateHeapNumber(power_double_double(x, y)); | 6026 |
| 6027 if (!isinf(x)) { |
| 6028 if (y == 0.5) { |
| 6029 // It's not uncommon to use Math.pow(x, 0.5) to compute the |
| 6030 // square root of a number. To speed up such computations, we |
| 6031 // explictly check for this case and use the sqrt() function |
| 6032 // which is faster than pow(). |
| 6033 return Heap::AllocateHeapNumber(sqrt(x)); |
| 6034 } else if (y == -0.5) { |
| 6035 // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5). |
| 6036 return Heap::AllocateHeapNumber(1.0 / sqrt(x)); |
| 6037 } |
| 6038 } |
| 6039 |
| 6040 if (y == 0) { |
| 6041 return Smi::FromInt(1); |
| 6042 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { |
| 6043 return Heap::nan_value(); |
| 6044 } else { |
| 6045 return Heap::AllocateHeapNumber(pow(x, y)); |
| 6046 } |
6048 } | 6047 } |
6049 | 6048 |
6050 // Fast version of Math.pow if we know that y is not an integer and | 6049 // Fast version of Math.pow if we know that y is not an integer and |
6051 // y is not -0.5 or 0.5. Used as slowcase from codegen. | 6050 // y is not -0.5 or 0.5. Used as slowcase from codegen. |
6052 static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) { | 6051 static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) { |
6053 NoHandleAllocation ha; | 6052 NoHandleAllocation ha; |
6054 ASSERT(args.length() == 2); | 6053 ASSERT(args.length() == 2); |
6055 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6054 CONVERT_DOUBLE_CHECKED(x, args[0]); |
6056 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6055 CONVERT_DOUBLE_CHECKED(y, args[1]); |
6057 if (y == 0) { | 6056 if (y == 0) { |
6058 return Smi::FromInt(1); | 6057 return Smi::FromInt(1); |
6059 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { | 6058 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { |
6060 return Heap::nan_value(); | 6059 return Heap::nan_value(); |
6061 } else { | 6060 } else { |
6062 return Heap::AllocateHeapNumber(pow(x, y)); | 6061 return Heap::AllocateHeapNumber(pow(x, y)); |
6063 } | 6062 } |
6064 } | 6063 } |
6065 | 6064 |
6066 | 6065 |
6067 static MaybeObject* Runtime_RoundNumber(Arguments args) { | 6066 static MaybeObject* Runtime_RoundNumber(Arguments args) { |
6068 NoHandleAllocation ha; | 6067 NoHandleAllocation ha; |
6069 ASSERT(args.length() == 1); | 6068 ASSERT(args.length() == 1); |
6070 Counters::math_round.Increment(); | 6069 Counters::math_round.Increment(); |
6071 | 6070 |
6072 if (!args[0]->IsHeapNumber()) { | 6071 if (!args[0]->IsHeapNumber()) { |
(...skipping 1592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7665 Object* allocation; | 7664 Object* allocation; |
7666 { MaybeObject* maybe_allocation = Heap::new_space()->AllocateRaw(size); | 7665 { MaybeObject* maybe_allocation = Heap::new_space()->AllocateRaw(size); |
7667 if (maybe_allocation->ToObject(&allocation)) { | 7666 if (maybe_allocation->ToObject(&allocation)) { |
7668 Heap::CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); | 7667 Heap::CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); |
7669 } | 7668 } |
7670 return maybe_allocation; | 7669 return maybe_allocation; |
7671 } | 7670 } |
7672 } | 7671 } |
7673 | 7672 |
7674 | 7673 |
7675 // Push an object unto an array of objects if it is not already in the | 7674 // Push an array unto an array of arrays if it is not already in the |
7676 // array. Returns true if the element was pushed on the stack and | 7675 // array. Returns true if the element was pushed on the stack and |
7677 // false otherwise. | 7676 // false otherwise. |
7678 static MaybeObject* Runtime_PushIfAbsent(Arguments args) { | 7677 static MaybeObject* Runtime_PushIfAbsent(Arguments args) { |
7679 ASSERT(args.length() == 2); | 7678 ASSERT(args.length() == 2); |
7680 CONVERT_CHECKED(JSArray, array, args[0]); | 7679 CONVERT_CHECKED(JSArray, array, args[0]); |
7681 CONVERT_CHECKED(JSObject, element, args[1]); | 7680 CONVERT_CHECKED(JSArray, element, args[1]); |
7682 RUNTIME_ASSERT(array->HasFastElements()); | 7681 RUNTIME_ASSERT(array->HasFastElements()); |
7683 int length = Smi::cast(array->length())->value(); | 7682 int length = Smi::cast(array->length())->value(); |
7684 FixedArray* elements = FixedArray::cast(array->elements()); | 7683 FixedArray* elements = FixedArray::cast(array->elements()); |
7685 for (int i = 0; i < length; i++) { | 7684 for (int i = 0; i < length; i++) { |
7686 if (elements->get(i) == element) return Heap::false_value(); | 7685 if (elements->get(i) == element) return Heap::false_value(); |
7687 } | 7686 } |
7688 Object* obj; | 7687 Object* obj; |
7689 { MaybeObject* maybe_obj = array->SetFastElement(length, element); | 7688 { MaybeObject* maybe_obj = array->SetFastElement(length, element); |
7690 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7689 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
7691 } | 7690 } |
(...skipping 3093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10785 } else { | 10784 } else { |
10786 // Handle last resort GC and make sure to allow future allocations | 10785 // Handle last resort GC and make sure to allow future allocations |
10787 // to grow the heap without causing GCs (if possible). | 10786 // to grow the heap without causing GCs (if possible). |
10788 Counters::gc_last_resort_from_js.Increment(); | 10787 Counters::gc_last_resort_from_js.Increment(); |
10789 Heap::CollectAllGarbage(false); | 10788 Heap::CollectAllGarbage(false); |
10790 } | 10789 } |
10791 } | 10790 } |
10792 | 10791 |
10793 | 10792 |
10794 } } // namespace v8::internal | 10793 } } // namespace v8::internal |
OLD | NEW |