| 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 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 new_proto_map->set_is_hidden_prototype(); | 637 new_proto_map->set_is_hidden_prototype(); |
| 638 | 638 |
| 639 // Set the object's prototype to proto. | 639 // Set the object's prototype to proto. |
| 640 new_map->set_prototype(proto); | 640 new_map->set_prototype(proto); |
| 641 jsobject->set_map(new_map); | 641 jsobject->set_map(new_map); |
| 642 | 642 |
| 643 return isolate->heap()->undefined_value(); | 643 return isolate->heap()->undefined_value(); |
| 644 } | 644 } |
| 645 | 645 |
| 646 | 646 |
| 647 // Sets the magic number that identifies a function as one of the special | |
| 648 // math functions that can be inlined. | |
| 649 static MaybeObject* Runtime_SetMathFunctionId(RUNTIME_CALLING_CONVENTION) { | |
| 650 RUNTIME_GET_ISOLATE; | |
| 651 NoHandleAllocation ha; | |
| 652 ASSERT(args.length() == 2); | |
| 653 CONVERT_CHECKED(JSFunction, function, args[0]); | |
| 654 CONVERT_CHECKED(Smi, id, args[1]); | |
| 655 RUNTIME_ASSERT(id->value() >= 0); | |
| 656 RUNTIME_ASSERT(id->value() < SharedFunctionInfo::max_math_id_number()); | |
| 657 | |
| 658 function->shared()->set_math_function_id(id->value()); | |
| 659 | |
| 660 return isolate->heap()->undefined_value(); | |
| 661 } | |
| 662 | |
| 663 | |
| 664 static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) { | 647 static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) { |
| 665 RUNTIME_GET_ISOLATE; | 648 RUNTIME_GET_ISOLATE; |
| 666 NoHandleAllocation ha; | 649 NoHandleAllocation ha; |
| 667 ASSERT(args.length() == 0); | 650 ASSERT(args.length() == 0); |
| 668 JavaScriptFrameIterator it; | 651 JavaScriptFrameIterator it; |
| 669 return isolate->heap()->ToBoolean(it.frame()->IsConstructor()); | 652 return isolate->heap()->ToBoolean(it.frame()->IsConstructor()); |
| 670 } | 653 } |
| 671 | 654 |
| 672 | 655 |
| 673 // Recursively traverses hidden prototypes if property is not found | 656 // Recursively traverses hidden prototypes if property is not found |
| (...skipping 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3668 | 3651 |
| 3669 | 3652 |
| 3670 static MaybeObject* Runtime_DefineOrRedefineAccessorProperty( | 3653 static MaybeObject* Runtime_DefineOrRedefineAccessorProperty( |
| 3671 RUNTIME_CALLING_CONVENTION) { | 3654 RUNTIME_CALLING_CONVENTION) { |
| 3672 RUNTIME_GET_ISOLATE; | 3655 RUNTIME_GET_ISOLATE; |
| 3673 ASSERT(args.length() == 5); | 3656 ASSERT(args.length() == 5); |
| 3674 HandleScope scope(isolate); | 3657 HandleScope scope(isolate); |
| 3675 CONVERT_ARG_CHECKED(JSObject, obj, 0); | 3658 CONVERT_ARG_CHECKED(JSObject, obj, 0); |
| 3676 CONVERT_CHECKED(String, name, args[1]); | 3659 CONVERT_CHECKED(String, name, args[1]); |
| 3677 CONVERT_CHECKED(Smi, flag_setter, args[2]); | 3660 CONVERT_CHECKED(Smi, flag_setter, args[2]); |
| 3678 CONVERT_CHECKED(JSFunction, fun, args[3]); | 3661 Object* fun = args[3]; |
| 3662 RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined()); |
| 3679 CONVERT_CHECKED(Smi, flag_attr, args[4]); | 3663 CONVERT_CHECKED(Smi, flag_attr, args[4]); |
| 3680 int unchecked = flag_attr->value(); | 3664 int unchecked = flag_attr->value(); |
| 3681 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 3665 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 3682 RUNTIME_ASSERT(!obj->IsNull()); | 3666 RUNTIME_ASSERT(!obj->IsNull()); |
| 3683 LookupResult result; | 3667 LookupResult result; |
| 3684 obj->LocalLookupRealNamedProperty(name, &result); | 3668 obj->LocalLookupRealNamedProperty(name, &result); |
| 3685 | 3669 |
| 3686 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 3670 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
| 3687 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION | 3671 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION |
| 3688 // delete it to avoid running into trouble in DefineAccessor, which | 3672 // delete it to avoid running into trouble in DefineAccessor, which |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3726 // Normalize the elements to enable attributes on the property. | 3710 // Normalize the elements to enable attributes on the property. |
| 3727 NormalizeElements(js_object); | 3711 NormalizeElements(js_object); |
| 3728 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); | 3712 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); |
| 3729 // Make sure that we never go back to fast case. | 3713 // Make sure that we never go back to fast case. |
| 3730 dictionary->set_requires_slow_elements(); | 3714 dictionary->set_requires_slow_elements(); |
| 3731 PropertyDetails details = PropertyDetails(attr, NORMAL); | 3715 PropertyDetails details = PropertyDetails(attr, NORMAL); |
| 3732 NumberDictionarySet(dictionary, index, obj_value, details); | 3716 NumberDictionarySet(dictionary, index, obj_value, details); |
| 3733 } | 3717 } |
| 3734 | 3718 |
| 3735 LookupResult result; | 3719 LookupResult result; |
| 3736 js_object->LocalLookupRealNamedProperty(*name, &result); | 3720 js_object->LookupRealNamedProperty(*name, &result); |
| 3737 | 3721 |
| 3738 // Take special care when attributes are different and there is already | 3722 // Take special care when attributes are different and there is already |
| 3739 // a property. For simplicity we normalize the property which enables us | 3723 // a property. For simplicity we normalize the property which enables us |
| 3740 // to not worry about changing the instance_descriptor and creating a new | 3724 // to not worry about changing the instance_descriptor and creating a new |
| 3741 // map. The current version of SetObjectProperty does not handle attributes | 3725 // map. The current version of SetObjectProperty does not handle attributes |
| 3742 // correctly in the case where a property is a field and is reset with | 3726 // correctly in the case where a property is a field and is reset with |
| 3743 // new attributes. | 3727 // new attributes. |
| 3744 if (result.IsProperty() && attr != result.GetAttributes()) { | 3728 if (result.IsProperty() && |
| 3729 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { |
| 3745 // New attributes - normalize to avoid writing to instance descriptor | 3730 // New attributes - normalize to avoid writing to instance descriptor |
| 3746 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 3731 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 3747 // Use IgnoreAttributes version since a readonly property may be | 3732 // Use IgnoreAttributes version since a readonly property may be |
| 3748 // overridden and SetProperty does not allow this. | 3733 // overridden and SetProperty does not allow this. |
| 3749 return js_object->IgnoreAttributesAndSetLocalProperty(*name, | 3734 return js_object->IgnoreAttributesAndSetLocalProperty(*name, |
| 3750 *obj_value, | 3735 *obj_value, |
| 3751 attr); | 3736 attr); |
| 3752 } | 3737 } |
| 3753 | 3738 |
| 3754 return Runtime::SetObjectProperty(isolate, js_object, name, obj_value, attr); | 3739 return Runtime::SetObjectProperty(isolate, js_object, name, obj_value, attr); |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4745 int step; | 4730 int step; |
| 4746 destination->Set(dest_position, Unescape(source, i, length, &step)); | 4731 destination->Set(dest_position, Unescape(source, i, length, &step)); |
| 4747 i += step; | 4732 i += step; |
| 4748 } | 4733 } |
| 4749 return destination; | 4734 return destination; |
| 4750 } | 4735 } |
| 4751 | 4736 |
| 4752 | 4737 |
| 4753 static const unsigned int kQuoteTableLength = 128u; | 4738 static const unsigned int kQuoteTableLength = 128u; |
| 4754 | 4739 |
| 4755 static const char* const JsonQuotes[kQuoteTableLength] = { | 4740 static const int kJsonQuotesCharactersPerEntry = 8; |
| 4756 "\\u0000", "\\u0001", "\\u0002", "\\u0003", | 4741 static const char* const JsonQuotes = |
| 4757 "\\u0004", "\\u0005", "\\u0006", "\\u0007", | 4742 "\\u0000 \\u0001 \\u0002 \\u0003 " |
| 4758 "\\b", "\\t", "\\n", "\\u000b", | 4743 "\\u0004 \\u0005 \\u0006 \\u0007 " |
| 4759 "\\f", "\\r", "\\u000e", "\\u000f", | 4744 "\\b \\t \\n \\u000b " |
| 4760 "\\u0010", "\\u0011", "\\u0012", "\\u0013", | 4745 "\\f \\r \\u000e \\u000f " |
| 4761 "\\u0014", "\\u0015", "\\u0016", "\\u0017", | 4746 "\\u0010 \\u0011 \\u0012 \\u0013 " |
| 4762 "\\u0018", "\\u0019", "\\u001a", "\\u001b", | 4747 "\\u0014 \\u0015 \\u0016 \\u0017 " |
| 4763 "\\u001c", "\\u001d", "\\u001e", "\\u001f", | 4748 "\\u0018 \\u0019 \\u001a \\u001b " |
| 4764 NULL, NULL, "\\\"", NULL, | 4749 "\\u001c \\u001d \\u001e \\u001f " |
| 4765 NULL, NULL, NULL, NULL, | 4750 " ! \\\" # " |
| 4766 NULL, NULL, NULL, NULL, | 4751 "$ % & ' " |
| 4767 NULL, NULL, NULL, NULL, | 4752 "( ) * + " |
| 4768 NULL, NULL, NULL, NULL, | 4753 ", - . / " |
| 4769 NULL, NULL, NULL, NULL, | 4754 "0 1 2 3 " |
| 4770 NULL, NULL, NULL, NULL, | 4755 "4 5 6 7 " |
| 4771 NULL, NULL, NULL, NULL, | 4756 "8 9 : ; " |
| 4772 NULL, NULL, NULL, NULL, | 4757 "< = > ? " |
| 4773 NULL, NULL, NULL, NULL, | 4758 "@ A B C " |
| 4774 NULL, NULL, NULL, NULL, | 4759 "D E F G " |
| 4775 NULL, NULL, NULL, NULL, | 4760 "H I J K " |
| 4776 NULL, NULL, NULL, NULL, | 4761 "L M N O " |
| 4777 NULL, NULL, NULL, NULL, | 4762 "P Q R S " |
| 4778 NULL, NULL, NULL, NULL, | 4763 "T U V W " |
| 4779 "\\\\", NULL, NULL, NULL, | 4764 "X Y Z [ " |
| 4780 NULL, NULL, NULL, NULL, | 4765 "\\\\ ] ^ _ " |
| 4781 NULL, NULL, NULL, NULL, | 4766 "` a b c " |
| 4782 NULL, NULL, NULL, NULL, | 4767 "d e f g " |
| 4783 NULL, NULL, NULL, NULL, | 4768 "h i j k " |
| 4784 NULL, NULL, NULL, NULL, | 4769 "l m n o " |
| 4785 NULL, NULL, NULL, NULL, | 4770 "p q r s " |
| 4786 NULL, NULL, NULL, NULL, | 4771 "t u v w " |
| 4787 NULL, NULL, NULL, NULL, | 4772 "x y z { " |
| 4788 }; | 4773 "| } ~ \177 "; |
| 4789 | 4774 |
| 4790 | 4775 |
| 4776 // For a string that is less than 32k characters it should always be |
| 4777 // possible to allocate it in new space. |
| 4778 static const int kMaxGuaranteedNewSpaceString = 32 * 1024; |
| 4779 |
| 4780 |
| 4781 // Doing JSON quoting cannot make the string more than this many times larger. |
| 4782 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 4783 |
| 4784 |
| 4785 // Covers the entire ASCII range (all other characters are unchanged by JSON |
| 4786 // quoting). |
| 4791 static const byte JsonQuoteLengths[kQuoteTableLength] = { | 4787 static const byte JsonQuoteLengths[kQuoteTableLength] = { |
| 4792 6, 6, 6, 6, 6, 6, 6, 6, | 4788 6, 6, 6, 6, 6, 6, 6, 6, |
| 4793 2, 2, 2, 6, 2, 2, 6, 6, | 4789 2, 2, 2, 6, 2, 2, 6, 6, |
| 4794 6, 6, 6, 6, 6, 6, 6, 6, | 4790 6, 6, 6, 6, 6, 6, 6, 6, |
| 4795 6, 6, 6, 6, 6, 6, 6, 6, | 4791 6, 6, 6, 6, 6, 6, 6, 6, |
| 4796 1, 1, 2, 1, 1, 1, 1, 1, | 4792 1, 1, 2, 1, 1, 1, 1, 1, |
| 4797 1, 1, 1, 1, 1, 1, 1, 1, | 4793 1, 1, 1, 1, 1, 1, 1, 1, |
| 4798 1, 1, 1, 1, 1, 1, 1, 1, | 4794 1, 1, 1, 1, 1, 1, 1, 1, |
| 4799 1, 1, 1, 1, 1, 1, 1, 1, | 4795 1, 1, 1, 1, 1, 1, 1, 1, |
| 4800 1, 1, 1, 1, 1, 1, 1, 1, | 4796 1, 1, 1, 1, 1, 1, 1, 1, |
| 4801 1, 1, 1, 1, 1, 1, 1, 1, | 4797 1, 1, 1, 1, 1, 1, 1, 1, |
| 4802 1, 1, 1, 1, 1, 1, 1, 1, | 4798 1, 1, 1, 1, 1, 1, 1, 1, |
| 4803 1, 1, 1, 1, 2, 1, 1, 1, | 4799 1, 1, 1, 1, 2, 1, 1, 1, |
| 4804 1, 1, 1, 1, 1, 1, 1, 1, | 4800 1, 1, 1, 1, 1, 1, 1, 1, |
| 4805 1, 1, 1, 1, 1, 1, 1, 1, | 4801 1, 1, 1, 1, 1, 1, 1, 1, |
| 4806 1, 1, 1, 1, 1, 1, 1, 1, | 4802 1, 1, 1, 1, 1, 1, 1, 1, |
| 4807 1, 1, 1, 1, 1, 1, 1, 1, | 4803 1, 1, 1, 1, 1, 1, 1, 1, |
| 4808 }; | 4804 }; |
| 4809 | 4805 |
| 4810 | 4806 |
| 4811 template <typename Char> | |
| 4812 Char* WriteString(Char* dst, const char* src_string) { | |
| 4813 char c; | |
| 4814 for (c = *src_string; c; c = *src_string) { | |
| 4815 *dst = c; | |
| 4816 dst++; | |
| 4817 src_string++; | |
| 4818 } | |
| 4819 return dst; | |
| 4820 } | |
| 4821 | |
| 4822 | |
| 4823 template <typename StringType> | 4807 template <typename StringType> |
| 4824 MaybeObject* AllocateRawString(int length); | 4808 MaybeObject* AllocateRawString(int length); |
| 4825 | 4809 |
| 4826 | 4810 |
| 4827 template <> | 4811 template <> |
| 4828 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { | 4812 MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { |
| 4829 return HEAP->AllocateRawTwoByteString(length); | 4813 return HEAP->AllocateRawTwoByteString(length); |
| 4830 } | 4814 } |
| 4831 | 4815 |
| 4832 | 4816 |
| 4833 template <> | 4817 template <> |
| 4834 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { | 4818 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
| 4835 return HEAP->AllocateRawAsciiString(length); | 4819 return HEAP->AllocateRawAsciiString(length); |
| 4836 } | 4820 } |
| 4837 | 4821 |
| 4838 | 4822 |
| 4839 template <typename Char, typename StringType> | 4823 template <typename Char, typename StringType> |
| 4824 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { |
| 4825 int length = characters.length(); |
| 4826 const Char* read_cursor = characters.start(); |
| 4827 const Char* end = read_cursor + length; |
| 4828 const int kSpaceForQuotes = 2; |
| 4829 int quoted_length = kSpaceForQuotes; |
| 4830 while (read_cursor < end) { |
| 4831 Char c = *(read_cursor++); |
| 4832 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4833 quoted_length++; |
| 4834 } else { |
| 4835 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4836 } |
| 4837 } |
| 4838 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
| 4839 Object* new_object; |
| 4840 if (!new_alloc->ToObject(&new_object)) { |
| 4841 return new_alloc; |
| 4842 } |
| 4843 StringType* new_string = StringType::cast(new_object); |
| 4844 |
| 4845 Char* write_cursor = reinterpret_cast<Char*>( |
| 4846 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4847 *(write_cursor++) = '"'; |
| 4848 |
| 4849 read_cursor = characters.start(); |
| 4850 while (read_cursor < end) { |
| 4851 Char c = *(read_cursor++); |
| 4852 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4853 *(write_cursor++) = c; |
| 4854 } else { |
| 4855 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4856 const char* replacement = JsonQuotes + |
| 4857 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
| 4858 for (int i = 0; i < len; i++) { |
| 4859 *write_cursor++ = *replacement++; |
| 4860 } |
| 4861 } |
| 4862 } |
| 4863 *(write_cursor++) = '"'; |
| 4864 return new_string; |
| 4865 } |
| 4866 |
| 4867 |
| 4868 template <typename Char, typename StringType> |
| 4840 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { | 4869 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
| 4841 int length = characters.length(); | 4870 int length = characters.length(); |
| 4842 int quoted_length = 0; | 4871 COUNTERS->quote_json_char_count()->Increment(length); |
| 4843 for (int i = 0; i < length; i++) { | 4872 const int kSpaceForQuotes = 2; |
| 4844 unsigned int c = characters[i]; | 4873 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 4845 if (sizeof(Char) > 1u) { | 4874 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
| 4846 quoted_length += (c >= kQuoteTableLength) ? 1 : JsonQuoteLengths[c]; | 4875 return SlowQuoteJsonString<Char, StringType>(characters); |
| 4847 } else { | |
| 4848 quoted_length += JsonQuoteLengths[c]; | |
| 4849 } | |
| 4850 } | 4876 } |
| 4851 COUNTERS->quote_json_char_count()->Increment(length); | |
| 4852 | 4877 |
| 4853 // Add space for quotes. | 4878 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); |
| 4854 quoted_length += 2; | |
| 4855 | |
| 4856 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); | |
| 4857 Object* new_object; | 4879 Object* new_object; |
| 4858 if (!new_alloc->ToObject(&new_object)) { | 4880 if (!new_alloc->ToObject(&new_object)) { |
| 4859 COUNTERS->quote_json_char_recount()->Increment(length); | |
| 4860 return new_alloc; | 4881 return new_alloc; |
| 4861 } | 4882 } |
| 4883 if (!HEAP->new_space()->Contains(new_object)) { |
| 4884 // Even if our string is small enough to fit in new space we still have to |
| 4885 // handle it being allocated in old space as may happen in the third |
| 4886 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
| 4887 // CEntryStub::GenerateCore. |
| 4888 return SlowQuoteJsonString<Char, StringType>(characters); |
| 4889 } |
| 4862 StringType* new_string = StringType::cast(new_object); | 4890 StringType* new_string = StringType::cast(new_object); |
| 4863 | 4891 ASSERT(HEAP->new_space()->Contains(new_string)); |
| 4864 | 4892 |
| 4865 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4893 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 4866 Char* write_cursor = reinterpret_cast<Char*>( | 4894 Char* write_cursor = reinterpret_cast<Char*>( |
| 4867 new_string->address() + SeqAsciiString::kHeaderSize); | 4895 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4868 *(write_cursor++) = '"'; | 4896 *(write_cursor++) = '"'; |
| 4897 |
| 4869 const Char* read_cursor = characters.start(); | 4898 const Char* read_cursor = characters.start(); |
| 4870 if (quoted_length == length + 2) { | 4899 const Char* end = read_cursor + length; |
| 4871 CopyChars(write_cursor, read_cursor, length); | 4900 while (read_cursor < end) { |
| 4872 write_cursor += length; | 4901 Char c = *(read_cursor++); |
| 4873 } else { | 4902 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4874 const Char* end = read_cursor + length; | 4903 *(write_cursor++) = c; |
| 4875 while (read_cursor < end) { | 4904 } else { |
| 4876 Char c = *(read_cursor++); | 4905 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4877 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4906 const char* replacement = JsonQuotes + |
| 4878 *(write_cursor++) = c; | 4907 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
| 4879 } else { | 4908 write_cursor[0] = replacement[0]; |
| 4880 const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; | 4909 if (len > 1) { |
| 4881 if (!replacement) { | 4910 write_cursor[1] = replacement[1]; |
| 4882 *(write_cursor++) = c; | 4911 if (len > 2) { |
| 4883 } else { | 4912 ASSERT(len == 6); |
| 4884 write_cursor = WriteString(write_cursor, replacement); | 4913 write_cursor[2] = replacement[2]; |
| 4914 write_cursor[3] = replacement[3]; |
| 4915 write_cursor[4] = replacement[4]; |
| 4916 write_cursor[5] = replacement[5]; |
| 4885 } | 4917 } |
| 4886 } | 4918 } |
| 4919 write_cursor += len; |
| 4887 } | 4920 } |
| 4888 } | 4921 } |
| 4889 *(write_cursor++) = '"'; | 4922 *(write_cursor++) = '"'; |
| 4890 ASSERT_EQ( | 4923 |
| 4891 static_cast<int64_t>( | 4924 int final_length = static_cast<int>( |
| 4892 SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char)), | 4925 write_cursor - reinterpret_cast<Char*>( |
| 4893 static_cast<int64_t>( | 4926 new_string->address() + SeqAsciiString::kHeaderSize)); |
| 4894 reinterpret_cast<Address>(write_cursor) - new_string->address())); | 4927 HEAP->new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string, |
| 4928 final_length); |
| 4895 return new_string; | 4929 return new_string; |
| 4896 } | 4930 } |
| 4897 | 4931 |
| 4898 | 4932 |
| 4899 static MaybeObject* Runtime_QuoteJSONString(RUNTIME_CALLING_CONVENTION) { | 4933 static MaybeObject* Runtime_QuoteJSONString(RUNTIME_CALLING_CONVENTION) { |
| 4900 RUNTIME_GET_ISOLATE; | 4934 RUNTIME_GET_ISOLATE; |
| 4901 NoHandleAllocation ha; | 4935 NoHandleAllocation ha; |
| 4902 CONVERT_CHECKED(String, str, args[0]); | 4936 CONVERT_CHECKED(String, str, args[0]); |
| 4903 if (!str->IsFlat()) { | 4937 if (!str->IsFlat()) { |
| 4904 MaybeObject* try_flatten = str->TryFlatten(); | 4938 MaybeObject* try_flatten = str->TryFlatten(); |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6249 RUNTIME_GET_ISOLATE; | 6283 RUNTIME_GET_ISOLATE; |
| 6250 NoHandleAllocation ha; | 6284 NoHandleAllocation ha; |
| 6251 ASSERT(args.length() == 1); | 6285 ASSERT(args.length() == 1); |
| 6252 isolate->counters()->math_log()->Increment(); | 6286 isolate->counters()->math_log()->Increment(); |
| 6253 | 6287 |
| 6254 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6288 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 6255 return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x); | 6289 return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x); |
| 6256 } | 6290 } |
| 6257 | 6291 |
| 6258 | 6292 |
| 6259 // Helper function to compute x^y, where y is known to be an | |
| 6260 // integer. Uses binary decomposition to limit the number of | |
| 6261 // multiplications; see the discussion in "Hacker's Delight" by Henry | |
| 6262 // S. Warren, Jr., figure 11-6, page 213. | |
| 6263 static double powi(double x, int y) { | |
| 6264 ASSERT(y != kMinInt); | |
| 6265 unsigned n = (y < 0) ? -y : y; | |
| 6266 double m = x; | |
| 6267 double p = 1; | |
| 6268 while (true) { | |
| 6269 if ((n & 1) != 0) p *= m; | |
| 6270 n >>= 1; | |
| 6271 if (n == 0) { | |
| 6272 if (y < 0) { | |
| 6273 // Unfortunately, we have to be careful when p has reached | |
| 6274 // infinity in the computation, because sometimes the higher | |
| 6275 // internal precision in the pow() implementation would have | |
| 6276 // given us a finite p. This happens very rarely. | |
| 6277 double result = 1.0 / p; | |
| 6278 return (result == 0 && isinf(p)) | |
| 6279 ? pow(x, static_cast<double>(y)) // Avoid pow(double, int). | |
| 6280 : result; | |
| 6281 } else { | |
| 6282 return p; | |
| 6283 } | |
| 6284 } | |
| 6285 m *= m; | |
| 6286 } | |
| 6287 } | |
| 6288 | |
| 6289 | |
| 6290 static MaybeObject* Runtime_Math_pow(RUNTIME_CALLING_CONVENTION) { | 6293 static MaybeObject* Runtime_Math_pow(RUNTIME_CALLING_CONVENTION) { |
| 6291 RUNTIME_GET_ISOLATE; | 6294 RUNTIME_GET_ISOLATE; |
| 6292 NoHandleAllocation ha; | 6295 NoHandleAllocation ha; |
| 6293 ASSERT(args.length() == 2); | 6296 ASSERT(args.length() == 2); |
| 6294 isolate->counters()->math_pow()->Increment(); | 6297 isolate->counters()->math_pow()->Increment(); |
| 6295 | 6298 |
| 6296 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6299 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 6297 | 6300 |
| 6298 // If the second argument is a smi, it is much faster to call the | 6301 // If the second argument is a smi, it is much faster to call the |
| 6299 // custom powi() function than the generic pow(). | 6302 // custom powi() function than the generic pow(). |
| 6300 if (args[1]->IsSmi()) { | 6303 if (args[1]->IsSmi()) { |
| 6301 int y = Smi::cast(args[1])->value(); | 6304 int y = Smi::cast(args[1])->value(); |
| 6302 return isolate->heap()->NumberFromDouble(powi(x, y)); | 6305 return isolate->heap()->NumberFromDouble(power_double_int(x, y)); |
| 6303 } | 6306 } |
| 6304 | 6307 |
| 6305 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6308 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 6306 | 6309 return isolate->heap()->AllocateHeapNumber(power_double_double(x, y)); |
| 6307 if (!isinf(x)) { | |
| 6308 if (y == 0.5) { | |
| 6309 // It's not uncommon to use Math.pow(x, 0.5) to compute the | |
| 6310 // square root of a number. To speed up such computations, we | |
| 6311 // explictly check for this case and use the sqrt() function | |
| 6312 // which is faster than pow(). | |
| 6313 return isolate->heap()->AllocateHeapNumber(sqrt(x)); | |
| 6314 } else if (y == -0.5) { | |
| 6315 // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5). | |
| 6316 return isolate->heap()->AllocateHeapNumber(1.0 / sqrt(x)); | |
| 6317 } | |
| 6318 } | |
| 6319 | |
| 6320 if (y == 0) { | |
| 6321 return Smi::FromInt(1); | |
| 6322 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { | |
| 6323 return isolate->heap()->nan_value(); | |
| 6324 } else { | |
| 6325 return isolate->heap()->AllocateHeapNumber(pow(x, y)); | |
| 6326 } | |
| 6327 } | 6310 } |
| 6328 | 6311 |
| 6329 // Fast version of Math.pow if we know that y is not an integer and | 6312 // Fast version of Math.pow if we know that y is not an integer and |
| 6330 // y is not -0.5 or 0.5. Used as slowcase from codegen. | 6313 // y is not -0.5 or 0.5. Used as slowcase from codegen. |
| 6331 static MaybeObject* Runtime_Math_pow_cfunction(RUNTIME_CALLING_CONVENTION) { | 6314 static MaybeObject* Runtime_Math_pow_cfunction(RUNTIME_CALLING_CONVENTION) { |
| 6332 RUNTIME_GET_ISOLATE; | 6315 RUNTIME_GET_ISOLATE; |
| 6333 NoHandleAllocation ha; | 6316 NoHandleAllocation ha; |
| 6334 ASSERT(args.length() == 2); | 6317 ASSERT(args.length() == 2); |
| 6335 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6318 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 6336 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6319 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 6337 if (y == 0) { | 6320 if (y == 0) { |
| 6338 return Smi::FromInt(1); | 6321 return Smi::FromInt(1); |
| 6339 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { | 6322 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { |
| 6340 return isolate->heap()->nan_value(); | 6323 return isolate->heap()->nan_value(); |
| 6341 } else { | 6324 } else { |
| 6342 return isolate->heap()->AllocateHeapNumber(pow(x, y)); | 6325 return isolate->heap()->AllocateHeapNumber(pow(x, y)); |
| 6343 } | 6326 } |
| 6344 } | 6327 } |
| 6345 | 6328 |
| 6346 | 6329 |
| 6347 static MaybeObject* Runtime_RoundNumber(RUNTIME_CALLING_CONVENTION) { | 6330 static MaybeObject* Runtime_RoundNumber(RUNTIME_CALLING_CONVENTION) { |
| 6348 RUNTIME_GET_ISOLATE; | 6331 RUNTIME_GET_ISOLATE; |
| 6349 NoHandleAllocation ha; | 6332 NoHandleAllocation ha; |
| 6350 ASSERT(args.length() == 1); | 6333 ASSERT(args.length() == 1); |
| 6351 isolate->counters()->math_round()->Increment(); | 6334 isolate->counters()->math_round()->Increment(); |
| 6352 | 6335 |
| (...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7187 function->PrintName(); | 7170 function->PrintName(); |
| 7188 PrintF("]\n"); | 7171 PrintF("]\n"); |
| 7189 } | 7172 } |
| 7190 | 7173 |
| 7191 // Try to compile the optimized code. A true return value from | 7174 // Try to compile the optimized code. A true return value from |
| 7192 // CompileOptimized means that compilation succeeded, not necessarily | 7175 // CompileOptimized means that compilation succeeded, not necessarily |
| 7193 // that optimization succeeded. | 7176 // that optimization succeeded. |
| 7194 if (CompileOptimized(function, ast_id) && function->IsOptimized()) { | 7177 if (CompileOptimized(function, ast_id) && function->IsOptimized()) { |
| 7195 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 7178 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 7196 function->code()->deoptimization_data()); | 7179 function->code()->deoptimization_data()); |
| 7197 if (FLAG_trace_osr) { | 7180 if (data->OsrPcOffset()->value() >= 0) { |
| 7198 PrintF("[on-stack replacement offset %d in optimized code]\n", | 7181 if (FLAG_trace_osr) { |
| 7182 PrintF("[on-stack replacement offset %d in optimized code]\n", |
| 7199 data->OsrPcOffset()->value()); | 7183 data->OsrPcOffset()->value()); |
| 7184 } |
| 7185 ASSERT(data->OsrAstId()->value() == ast_id); |
| 7186 } else { |
| 7187 // We may never generate the desired OSR entry if we emit an |
| 7188 // early deoptimize. |
| 7189 succeeded = false; |
| 7200 } | 7190 } |
| 7201 ASSERT(data->OsrAstId()->value() == ast_id); | |
| 7202 ASSERT(data->OsrPcOffset()->value() >= 0); | |
| 7203 } else { | 7191 } else { |
| 7204 succeeded = false; | 7192 succeeded = false; |
| 7205 } | 7193 } |
| 7206 } | 7194 } |
| 7207 | 7195 |
| 7208 // Revert to the original stack checks in the original unoptimized code. | 7196 // Revert to the original stack checks in the original unoptimized code. |
| 7209 if (FLAG_trace_osr) { | 7197 if (FLAG_trace_osr) { |
| 7210 PrintF("[restoring original stack checks in "); | 7198 PrintF("[restoring original stack checks in "); |
| 7211 function->PrintName(); | 7199 function->PrintName(); |
| 7212 PrintF("]\n"); | 7200 PrintF("]\n"); |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7526 // The property was not found. It needs to be stored in the global context. | 7514 // The property was not found. It needs to be stored in the global context. |
| 7527 ASSERT(attributes == ABSENT); | 7515 ASSERT(attributes == ABSENT); |
| 7528 attributes = NONE; | 7516 attributes = NONE; |
| 7529 context_ext = Handle<JSObject>(isolate->context()->global()); | 7517 context_ext = Handle<JSObject>(isolate->context()->global()); |
| 7530 } | 7518 } |
| 7531 | 7519 |
| 7532 // Set the property, but ignore if read_only variable on the context | 7520 // Set the property, but ignore if read_only variable on the context |
| 7533 // extension object itself. | 7521 // extension object itself. |
| 7534 if ((attributes & READ_ONLY) == 0 || | 7522 if ((attributes & READ_ONLY) == 0 || |
| 7535 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 7523 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
| 7536 Handle<Object> set = SetProperty(context_ext, name, value, attributes); | 7524 Handle<Object> set = SetProperty(context_ext, name, value, NONE); |
| 7537 if (set.is_null()) { | 7525 if (set.is_null()) { |
| 7538 // Failure::Exception is converted to a null handle in the | 7526 // Failure::Exception is converted to a null handle in the |
| 7539 // handle-based methods such as SetProperty. We therefore need | 7527 // handle-based methods such as SetProperty. We therefore need |
| 7540 // to convert null handles back to exceptions. | 7528 // to convert null handles back to exceptions. |
| 7541 ASSERT(isolate->has_pending_exception()); | 7529 ASSERT(isolate->has_pending_exception()); |
| 7542 return Failure::Exception(); | 7530 return Failure::Exception(); |
| 7543 } | 7531 } |
| 7544 } | 7532 } |
| 7545 return *value; | 7533 return *value; |
| 7546 } | 7534 } |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8014 Object* allocation; | 8002 Object* allocation; |
| 8015 { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size); | 8003 { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size); |
| 8016 if (maybe_allocation->ToObject(&allocation)) { | 8004 if (maybe_allocation->ToObject(&allocation)) { |
| 8017 heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); | 8005 heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); |
| 8018 } | 8006 } |
| 8019 return maybe_allocation; | 8007 return maybe_allocation; |
| 8020 } | 8008 } |
| 8021 } | 8009 } |
| 8022 | 8010 |
| 8023 | 8011 |
| 8024 // Push an array unto an array of arrays if it is not already in the | 8012 // Push an object unto an array of objects if it is not already in the |
| 8025 // array. Returns true if the element was pushed on the stack and | 8013 // array. Returns true if the element was pushed on the stack and |
| 8026 // false otherwise. | 8014 // false otherwise. |
| 8027 static MaybeObject* Runtime_PushIfAbsent(RUNTIME_CALLING_CONVENTION) { | 8015 static MaybeObject* Runtime_PushIfAbsent(RUNTIME_CALLING_CONVENTION) { |
| 8028 RUNTIME_GET_ISOLATE; | 8016 RUNTIME_GET_ISOLATE; |
| 8029 ASSERT(args.length() == 2); | 8017 ASSERT(args.length() == 2); |
| 8030 CONVERT_CHECKED(JSArray, array, args[0]); | 8018 CONVERT_CHECKED(JSArray, array, args[0]); |
| 8031 CONVERT_CHECKED(JSArray, element, args[1]); | 8019 CONVERT_CHECKED(JSObject, element, args[1]); |
| 8032 RUNTIME_ASSERT(array->HasFastElements()); | 8020 RUNTIME_ASSERT(array->HasFastElements()); |
| 8033 int length = Smi::cast(array->length())->value(); | 8021 int length = Smi::cast(array->length())->value(); |
| 8034 FixedArray* elements = FixedArray::cast(array->elements()); | 8022 FixedArray* elements = FixedArray::cast(array->elements()); |
| 8035 for (int i = 0; i < length; i++) { | 8023 for (int i = 0; i < length; i++) { |
| 8036 if (elements->get(i) == element) return isolate->heap()->false_value(); | 8024 if (elements->get(i) == element) return isolate->heap()->false_value(); |
| 8037 } | 8025 } |
| 8038 Object* obj; | 8026 Object* obj; |
| 8039 { MaybeObject* maybe_obj = array->SetFastElement(length, element); | 8027 { MaybeObject* maybe_obj = array->SetFastElement(length, element); |
| 8040 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8028 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8041 } | 8029 } |
| (...skipping 2075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10117 // This function and the context acts as replacements for the function on the | 10105 // This function and the context acts as replacements for the function on the |
| 10118 // stack frame presenting the same view of the values of parameters and | 10106 // stack frame presenting the same view of the values of parameters and |
| 10119 // local variables as if the piece of JavaScript was evaluated at the point | 10107 // local variables as if the piece of JavaScript was evaluated at the point |
| 10120 // where the function on the stack frame is currently stopped. | 10108 // where the function on the stack frame is currently stopped. |
| 10121 static MaybeObject* Runtime_DebugEvaluate(RUNTIME_CALLING_CONVENTION) { | 10109 static MaybeObject* Runtime_DebugEvaluate(RUNTIME_CALLING_CONVENTION) { |
| 10122 RUNTIME_GET_ISOLATE; | 10110 RUNTIME_GET_ISOLATE; |
| 10123 HandleScope scope(isolate); | 10111 HandleScope scope(isolate); |
| 10124 | 10112 |
| 10125 // Check the execution state and decode arguments frame and source to be | 10113 // Check the execution state and decode arguments frame and source to be |
| 10126 // evaluated. | 10114 // evaluated. |
| 10127 ASSERT(args.length() == 4); | 10115 ASSERT(args.length() == 5); |
| 10128 Object* check_result; | 10116 Object* check_result; |
| 10129 { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args, | 10117 { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args, |
| 10130 isolate); | 10118 isolate); |
| 10131 if (!maybe_check_result->ToObject(&check_result)) { | 10119 if (!maybe_check_result->ToObject(&check_result)) { |
| 10132 return maybe_check_result; | 10120 return maybe_check_result; |
| 10133 } | 10121 } |
| 10134 } | 10122 } |
| 10135 CONVERT_CHECKED(Smi, wrapped_id, args[1]); | 10123 CONVERT_CHECKED(Smi, wrapped_id, args[1]); |
| 10136 CONVERT_ARG_CHECKED(String, source, 2); | 10124 CONVERT_ARG_CHECKED(String, source, 2); |
| 10137 CONVERT_BOOLEAN_CHECKED(disable_break, args[3]); | 10125 CONVERT_BOOLEAN_CHECKED(disable_break, args[3]); |
| 10126 Handle<Object> additional_context(args[4]); |
| 10138 | 10127 |
| 10139 // Handle the processing of break. | 10128 // Handle the processing of break. |
| 10140 DisableBreak disable_break_save(disable_break); | 10129 DisableBreak disable_break_save(disable_break); |
| 10141 | 10130 |
| 10142 // Get the frame where the debugging is performed. | 10131 // Get the frame where the debugging is performed. |
| 10143 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 10132 StackFrame::Id id = UnwrapFrameId(wrapped_id); |
| 10144 JavaScriptFrameIterator it(id); | 10133 JavaScriptFrameIterator it(id); |
| 10145 JavaScriptFrame* frame = it.frame(); | 10134 JavaScriptFrame* frame = it.frame(); |
| 10146 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 10135 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| 10147 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); | 10136 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10180 // object build. | 10169 // object build. |
| 10181 Handle<Context> context = | 10170 Handle<Context> context = |
| 10182 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, | 10171 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, |
| 10183 go_between); | 10172 go_between); |
| 10184 context->set_extension(*local_scope); | 10173 context->set_extension(*local_scope); |
| 10185 // Copy any with contexts present and chain them in front of this context. | 10174 // Copy any with contexts present and chain them in front of this context. |
| 10186 Handle<Context> frame_context(Context::cast(frame->context())); | 10175 Handle<Context> frame_context(Context::cast(frame->context())); |
| 10187 Handle<Context> function_context(frame_context->fcontext()); | 10176 Handle<Context> function_context(frame_context->fcontext()); |
| 10188 context = CopyWithContextChain(frame_context, context); | 10177 context = CopyWithContextChain(frame_context, context); |
| 10189 | 10178 |
| 10179 if (additional_context->IsJSObject()) { |
| 10180 context = isolate->factory()->NewWithContext(context, |
| 10181 Handle<JSObject>::cast(additional_context), false); |
| 10182 } |
| 10183 |
| 10190 // Wrap the evaluation statement in a new function compiled in the newly | 10184 // Wrap the evaluation statement in a new function compiled in the newly |
| 10191 // created context. The function has one parameter which has to be called | 10185 // created context. The function has one parameter which has to be called |
| 10192 // 'arguments'. This it to have access to what would have been 'arguments' in | 10186 // 'arguments'. This it to have access to what would have been 'arguments' in |
| 10193 // the function being debugged. | 10187 // the function being debugged. |
| 10194 // function(arguments,__source__) {return eval(__source__);} | 10188 // function(arguments,__source__) {return eval(__source__);} |
| 10195 | 10189 |
| 10196 Handle<String> function_source = | 10190 Handle<String> function_source = |
| 10197 isolate->factory()->NewStringFromAscii( | 10191 isolate->factory()->NewStringFromAscii( |
| 10198 Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1)); | 10192 Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1)); |
| 10199 Handle<SharedFunctionInfo> shared = | 10193 Handle<SharedFunctionInfo> shared = |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10234 return *result; | 10228 return *result; |
| 10235 } | 10229 } |
| 10236 | 10230 |
| 10237 | 10231 |
| 10238 static MaybeObject* Runtime_DebugEvaluateGlobal(RUNTIME_CALLING_CONVENTION) { | 10232 static MaybeObject* Runtime_DebugEvaluateGlobal(RUNTIME_CALLING_CONVENTION) { |
| 10239 RUNTIME_GET_ISOLATE; | 10233 RUNTIME_GET_ISOLATE; |
| 10240 HandleScope scope(isolate); | 10234 HandleScope scope(isolate); |
| 10241 | 10235 |
| 10242 // Check the execution state and decode arguments frame and source to be | 10236 // Check the execution state and decode arguments frame and source to be |
| 10243 // evaluated. | 10237 // evaluated. |
| 10244 ASSERT(args.length() == 3); | 10238 ASSERT(args.length() == 4); |
| 10245 Object* check_result; | 10239 Object* check_result; |
| 10246 { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args, | 10240 { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args, |
| 10247 isolate); | 10241 isolate); |
| 10248 if (!maybe_check_result->ToObject(&check_result)) { | 10242 if (!maybe_check_result->ToObject(&check_result)) { |
| 10249 return maybe_check_result; | 10243 return maybe_check_result; |
| 10250 } | 10244 } |
| 10251 } | 10245 } |
| 10252 CONVERT_ARG_CHECKED(String, source, 1); | 10246 CONVERT_ARG_CHECKED(String, source, 1); |
| 10253 CONVERT_BOOLEAN_CHECKED(disable_break, args[2]); | 10247 CONVERT_BOOLEAN_CHECKED(disable_break, args[2]); |
| 10248 Handle<Object> additional_context(args[3]); |
| 10254 | 10249 |
| 10255 // Handle the processing of break. | 10250 // Handle the processing of break. |
| 10256 DisableBreak disable_break_save(disable_break); | 10251 DisableBreak disable_break_save(disable_break); |
| 10257 | 10252 |
| 10258 // Enter the top context from before the debugger was invoked. | 10253 // Enter the top context from before the debugger was invoked. |
| 10259 SaveContext save(isolate); | 10254 SaveContext save(isolate); |
| 10260 SaveContext* top = &save; | 10255 SaveContext* top = &save; |
| 10261 while (top != NULL && *top->context() == *isolate->debug()->debug_context()) { | 10256 while (top != NULL && *top->context() == *isolate->debug()->debug_context()) { |
| 10262 top = top->prev(); | 10257 top = top->prev(); |
| 10263 } | 10258 } |
| 10264 if (top != NULL) { | 10259 if (top != NULL) { |
| 10265 isolate->set_context(*top->context()); | 10260 isolate->set_context(*top->context()); |
| 10266 } | 10261 } |
| 10267 | 10262 |
| 10268 // Get the global context now set to the top context from before the | 10263 // Get the global context now set to the top context from before the |
| 10269 // debugger was invoked. | 10264 // debugger was invoked. |
| 10270 Handle<Context> context = isolate->global_context(); | 10265 Handle<Context> context = isolate->global_context(); |
| 10271 | 10266 |
| 10267 bool is_global = true; |
| 10268 |
| 10269 if (additional_context->IsJSObject()) { |
| 10270 // Create a function context first, than put 'with' context on top of it. |
| 10271 Handle<JSFunction> go_between = isolate->factory()->NewFunction( |
| 10272 isolate->factory()->empty_string(), |
| 10273 isolate->factory()->undefined_value()); |
| 10274 go_between->set_context(*context); |
| 10275 context = |
| 10276 isolate->factory()->NewFunctionContext( |
| 10277 Context::MIN_CONTEXT_SLOTS, go_between); |
| 10278 context->set_extension(JSObject::cast(*additional_context)); |
| 10279 is_global = false; |
| 10280 } |
| 10281 |
| 10272 // Compile the source to be evaluated. | 10282 // Compile the source to be evaluated. |
| 10273 Handle<SharedFunctionInfo> shared = | 10283 Handle<SharedFunctionInfo> shared = |
| 10274 Compiler::CompileEval(source, | 10284 Compiler::CompileEval(source, |
| 10275 context, | 10285 context, |
| 10276 true); | 10286 is_global); |
| 10277 if (shared.is_null()) return Failure::Exception(); | 10287 if (shared.is_null()) return Failure::Exception(); |
| 10278 Handle<JSFunction> compiled_function = | 10288 Handle<JSFunction> compiled_function = |
| 10279 Handle<JSFunction>( | 10289 Handle<JSFunction>( |
| 10280 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 10290 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
| 10281 context)); | 10291 context)); |
| 10282 | 10292 |
| 10283 // Invoke the result of the compilation to get the evaluation function. | 10293 // Invoke the result of the compilation to get the evaluation function. |
| 10284 bool has_pending_exception; | 10294 bool has_pending_exception; |
| 10285 Handle<Object> receiver = isolate->global(); | 10295 Handle<Object> receiver = isolate->global(); |
| 10286 Handle<Object> result = | 10296 Handle<Object> result = |
| (...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11271 } else { | 11281 } else { |
| 11272 // Handle last resort GC and make sure to allow future allocations | 11282 // Handle last resort GC and make sure to allow future allocations |
| 11273 // to grow the heap without causing GCs (if possible). | 11283 // to grow the heap without causing GCs (if possible). |
| 11274 COUNTERS->gc_last_resort_from_js()->Increment(); | 11284 COUNTERS->gc_last_resort_from_js()->Increment(); |
| 11275 HEAP->CollectAllGarbage(false); | 11285 HEAP->CollectAllGarbage(false); |
| 11276 } | 11286 } |
| 11277 } | 11287 } |
| 11278 | 11288 |
| 11279 | 11289 |
| 11280 } } // namespace v8::internal | 11290 } } // namespace v8::internal |
| OLD | NEW |