| 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 if (value->IsFixedArray()) { | 323 if (value->IsFixedArray()) { |
| 324 // The value contains the constant_properties of a | 324 // The value contains the constant_properties of a |
| 325 // simple object literal. | 325 // simple object literal. |
| 326 Handle<FixedArray> array = Handle<FixedArray>::cast(value); | 326 Handle<FixedArray> array = Handle<FixedArray>::cast(value); |
| 327 value = CreateLiteralBoilerplate(literals, array); | 327 value = CreateLiteralBoilerplate(literals, array); |
| 328 if (value.is_null()) return value; | 328 if (value.is_null()) return value; |
| 329 } | 329 } |
| 330 Handle<Object> result; | 330 Handle<Object> result; |
| 331 uint32_t element_index = 0; | 331 uint32_t element_index = 0; |
| 332 if (key->IsSymbol()) { | 332 if (key->IsSymbol()) { |
| 333 // If key is a symbol it is not an array element. | 333 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { |
| 334 Handle<String> name(String::cast(*key)); | 334 // Array index as string (uint32). |
| 335 ASSERT(!name->AsArrayIndex(&element_index)); | 335 result = SetOwnElement(boilerplate, element_index, value); |
| 336 result = SetProperty(boilerplate, name, value, NONE); | 336 } else { |
| 337 Handle<String> name(String::cast(*key)); |
| 338 ASSERT(!name->AsArrayIndex(&element_index)); |
| 339 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, |
| 340 value, NONE); |
| 341 } |
| 337 } else if (key->ToArrayIndex(&element_index)) { | 342 } else if (key->ToArrayIndex(&element_index)) { |
| 338 // Array index (uint32). | 343 // Array index (uint32). |
| 339 result = SetElement(boilerplate, element_index, value); | 344 result = SetOwnElement(boilerplate, element_index, value); |
| 340 } else { | 345 } else { |
| 341 // Non-uint32 number. | 346 // Non-uint32 number. |
| 342 ASSERT(key->IsNumber()); | 347 ASSERT(key->IsNumber()); |
| 343 double num = key->Number(); | 348 double num = key->Number(); |
| 344 char arr[100]; | 349 char arr[100]; |
| 345 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | 350 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 346 const char* str = DoubleToCString(num, buffer); | 351 const char* str = DoubleToCString(num, buffer); |
| 347 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | 352 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); |
| 348 result = SetProperty(boilerplate, name, value, NONE); | 353 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, |
| 354 value, NONE); |
| 349 } | 355 } |
| 350 // If setting the property on the boilerplate throws an | 356 // If setting the property on the boilerplate throws an |
| 351 // exception, the exception is converted to an empty handle in | 357 // exception, the exception is converted to an empty handle in |
| 352 // the handle based operations. In that case, we need to | 358 // the handle based operations. In that case, we need to |
| 353 // convert back to an exception. | 359 // convert back to an exception. |
| 354 if (result.is_null()) return result; | 360 if (result.is_null()) return result; |
| 355 } | 361 } |
| 356 } | 362 } |
| 357 | 363 |
| 358 return boilerplate; | 364 return boilerplate; |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 if (!result->IsProperty()) { | 637 if (!result->IsProperty()) { |
| 632 Object* proto = obj->GetPrototype(); | 638 Object* proto = obj->GetPrototype(); |
| 633 if (proto->IsJSObject() && | 639 if (proto->IsJSObject() && |
| 634 JSObject::cast(proto)->map()->is_hidden_prototype()) | 640 JSObject::cast(proto)->map()->is_hidden_prototype()) |
| 635 GetOwnPropertyImplementation(JSObject::cast(proto), | 641 GetOwnPropertyImplementation(JSObject::cast(proto), |
| 636 name, result); | 642 name, result); |
| 637 } | 643 } |
| 638 } | 644 } |
| 639 | 645 |
| 640 | 646 |
| 647 static bool CheckAccessException(LookupResult* result, |
| 648 v8::AccessType access_type) { |
| 649 if (result->type() == CALLBACKS) { |
| 650 Object* callback = result->GetCallbackObject(); |
| 651 if (callback->IsAccessorInfo()) { |
| 652 AccessorInfo* info = AccessorInfo::cast(callback); |
| 653 bool can_access = |
| 654 (access_type == v8::ACCESS_HAS && |
| 655 (info->all_can_read() || info->all_can_write())) || |
| 656 (access_type == v8::ACCESS_GET && info->all_can_read()) || |
| 657 (access_type == v8::ACCESS_SET && info->all_can_write()); |
| 658 return can_access; |
| 659 } |
| 660 } |
| 661 |
| 662 return false; |
| 663 } |
| 664 |
| 665 |
| 666 static bool CheckAccess(JSObject* obj, |
| 667 String* name, |
| 668 LookupResult* result, |
| 669 v8::AccessType access_type) { |
| 670 ASSERT(result->IsProperty()); |
| 671 |
| 672 JSObject* holder = result->holder(); |
| 673 JSObject* current = obj; |
| 674 while (true) { |
| 675 if (current->IsAccessCheckNeeded() && |
| 676 !Top::MayNamedAccess(current, name, access_type)) { |
| 677 // Access check callback denied the access, but some properties |
| 678 // can have a special permissions which override callbacks descision |
| 679 // (currently see v8::AccessControl). |
| 680 break; |
| 681 } |
| 682 |
| 683 if (current == holder) { |
| 684 return true; |
| 685 } |
| 686 |
| 687 current = JSObject::cast(current->GetPrototype()); |
| 688 } |
| 689 |
| 690 // API callbacks can have per callback access exceptions. |
| 691 switch (result->type()) { |
| 692 case CALLBACKS: { |
| 693 if (CheckAccessException(result, access_type)) { |
| 694 return true; |
| 695 } |
| 696 break; |
| 697 } |
| 698 case INTERCEPTOR: { |
| 699 // If the object has an interceptor, try real named properties. |
| 700 // Overwrite the result to fetch the correct property later. |
| 701 holder->LookupRealNamedProperty(name, result); |
| 702 if (result->IsProperty()) { |
| 703 if (CheckAccessException(result, access_type)) { |
| 704 return true; |
| 705 } |
| 706 } |
| 707 break; |
| 708 } |
| 709 default: |
| 710 break; |
| 711 } |
| 712 |
| 713 Top::ReportFailedAccessCheck(current, access_type); |
| 714 return false; |
| 715 } |
| 716 |
| 717 |
| 718 // TODO(1095): we should traverse hidden prototype hierachy as well. |
| 719 static bool CheckElementAccess(JSObject* obj, |
| 720 uint32_t index, |
| 721 v8::AccessType access_type) { |
| 722 if (obj->IsAccessCheckNeeded() && |
| 723 !Top::MayIndexedAccess(obj, index, access_type)) { |
| 724 return false; |
| 725 } |
| 726 |
| 727 return true; |
| 728 } |
| 729 |
| 730 |
| 641 // Enumerator used as indices into the array returned from GetOwnProperty | 731 // Enumerator used as indices into the array returned from GetOwnProperty |
| 642 enum PropertyDescriptorIndices { | 732 enum PropertyDescriptorIndices { |
| 643 IS_ACCESSOR_INDEX, | 733 IS_ACCESSOR_INDEX, |
| 644 VALUE_INDEX, | 734 VALUE_INDEX, |
| 645 GETTER_INDEX, | 735 GETTER_INDEX, |
| 646 SETTER_INDEX, | 736 SETTER_INDEX, |
| 647 WRITABLE_INDEX, | 737 WRITABLE_INDEX, |
| 648 ENUMERABLE_INDEX, | 738 ENUMERABLE_INDEX, |
| 649 CONFIGURABLE_INDEX, | 739 CONFIGURABLE_INDEX, |
| 650 DESCRIPTOR_SIZE | 740 DESCRIPTOR_SIZE |
| (...skipping 22 matching lines...) Expand all Loading... |
| 673 case JSObject::UNDEFINED_ELEMENT: | 763 case JSObject::UNDEFINED_ELEMENT: |
| 674 return Heap::undefined_value(); | 764 return Heap::undefined_value(); |
| 675 | 765 |
| 676 case JSObject::STRING_CHARACTER_ELEMENT: { | 766 case JSObject::STRING_CHARACTER_ELEMENT: { |
| 677 // Special handling of string objects according to ECMAScript 5 | 767 // Special handling of string objects according to ECMAScript 5 |
| 678 // 15.5.5.2. Note that this might be a string object with elements | 768 // 15.5.5.2. Note that this might be a string object with elements |
| 679 // other than the actual string value. This is covered by the | 769 // other than the actual string value. This is covered by the |
| 680 // subsequent cases. | 770 // subsequent cases. |
| 681 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); | 771 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); |
| 682 Handle<String> str(String::cast(js_value->value())); | 772 Handle<String> str(String::cast(js_value->value())); |
| 683 Handle<String> substr = SubString(str, index, index+1, NOT_TENURED); | 773 Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); |
| 684 | 774 |
| 685 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 775 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 686 elms->set(VALUE_INDEX, *substr); | 776 elms->set(VALUE_INDEX, *substr); |
| 687 elms->set(WRITABLE_INDEX, Heap::false_value()); | 777 elms->set(WRITABLE_INDEX, Heap::false_value()); |
| 688 elms->set(ENUMERABLE_INDEX, Heap::false_value()); | 778 elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
| 689 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); | 779 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
| 690 return *desc; | 780 return *desc; |
| 691 } | 781 } |
| 692 | 782 |
| 693 case JSObject::INTERCEPTED_ELEMENT: | 783 case JSObject::INTERCEPTED_ELEMENT: |
| 694 case JSObject::FAST_ELEMENT: { | 784 case JSObject::FAST_ELEMENT: { |
| 695 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 785 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 696 Handle<Object> element = GetElement(Handle<Object>(obj), index); | 786 elms->set(VALUE_INDEX, *GetElement(obj, index)); |
| 697 elms->set(VALUE_INDEX, *element); | |
| 698 elms->set(WRITABLE_INDEX, Heap::true_value()); | 787 elms->set(WRITABLE_INDEX, Heap::true_value()); |
| 699 elms->set(ENUMERABLE_INDEX, Heap::true_value()); | 788 elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
| 700 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); | 789 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
| 701 return *desc; | 790 return *desc; |
| 702 } | 791 } |
| 703 | 792 |
| 704 case JSObject::DICTIONARY_ELEMENT: { | 793 case JSObject::DICTIONARY_ELEMENT: { |
| 705 NumberDictionary* dictionary = obj->element_dictionary(); | 794 Handle<JSObject> holder = obj; |
| 795 if (obj->IsJSGlobalProxy()) { |
| 796 Object* proto = obj->GetPrototype(); |
| 797 if (proto->IsNull()) return Heap::undefined_value(); |
| 798 ASSERT(proto->IsJSGlobalObject()); |
| 799 holder = Handle<JSObject>(JSObject::cast(proto)); |
| 800 } |
| 801 NumberDictionary* dictionary = holder->element_dictionary(); |
| 706 int entry = dictionary->FindEntry(index); | 802 int entry = dictionary->FindEntry(index); |
| 707 ASSERT(entry != NumberDictionary::kNotFound); | 803 ASSERT(entry != NumberDictionary::kNotFound); |
| 708 PropertyDetails details = dictionary->DetailsAt(entry); | 804 PropertyDetails details = dictionary->DetailsAt(entry); |
| 709 switch (details.type()) { | 805 switch (details.type()) { |
| 710 case CALLBACKS: { | 806 case CALLBACKS: { |
| 711 // This is an accessor property with getter and/or setter. | 807 // This is an accessor property with getter and/or setter. |
| 712 FixedArray* callbacks = | 808 FixedArray* callbacks = |
| 713 FixedArray::cast(dictionary->ValueAt(entry)); | 809 FixedArray::cast(dictionary->ValueAt(entry)); |
| 714 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | 810 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 715 elms->set(GETTER_INDEX, callbacks->get(0)); | 811 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { |
| 716 elms->set(SETTER_INDEX, callbacks->get(1)); | 812 elms->set(GETTER_INDEX, callbacks->get(0)); |
| 813 } |
| 814 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { |
| 815 elms->set(SETTER_INDEX, callbacks->get(1)); |
| 816 } |
| 717 break; | 817 break; |
| 718 } | 818 } |
| 719 case NORMAL: | 819 case NORMAL: |
| 720 // This is a data property. | 820 // This is a data property. |
| 721 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 821 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 722 elms->set(VALUE_INDEX, dictionary->ValueAt(entry)); | 822 elms->set(VALUE_INDEX, *GetElement(obj, index)); |
| 723 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); | 823 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); |
| 724 break; | 824 break; |
| 725 default: | 825 default: |
| 726 UNREACHABLE(); | 826 UNREACHABLE(); |
| 727 break; | 827 break; |
| 728 } | 828 } |
| 729 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); | 829 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
| 730 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); | 830 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
| 731 return *desc; | 831 return *desc; |
| 732 } | 832 } |
| 733 } | 833 } |
| 734 } | 834 } |
| 735 | 835 |
| 736 // Use recursive implementation to also traverse hidden prototypes | 836 // Use recursive implementation to also traverse hidden prototypes |
| 737 GetOwnPropertyImplementation(*obj, *name, &result); | 837 GetOwnPropertyImplementation(*obj, *name, &result); |
| 738 | 838 |
| 739 if (!result.IsProperty()) { | 839 if (!result.IsProperty()) { |
| 740 return Heap::undefined_value(); | 840 return Heap::undefined_value(); |
| 741 } | 841 } |
| 742 if (result.type() == CALLBACKS) { | 842 |
| 743 Object* structure = result.GetCallbackObject(); | 843 if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) { |
| 744 if (structure->IsProxy() || structure->IsAccessorInfo()) { | 844 return Heap::false_value(); |
| 745 // Property that is internally implemented as a callback or | |
| 746 // an API defined callback. | |
| 747 Object* value; | |
| 748 { MaybeObject* maybe_value = obj->GetPropertyWithCallback( | |
| 749 *obj, structure, *name, result.holder()); | |
| 750 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 751 } | |
| 752 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | |
| 753 elms->set(VALUE_INDEX, value); | |
| 754 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); | |
| 755 } else if (structure->IsFixedArray()) { | |
| 756 // __defineGetter__/__defineSetter__ callback. | |
| 757 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | |
| 758 elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); | |
| 759 elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); | |
| 760 } else { | |
| 761 return Heap::undefined_value(); | |
| 762 } | |
| 763 } else { | |
| 764 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | |
| 765 elms->set(VALUE_INDEX, result.GetLazyValue()); | |
| 766 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); | |
| 767 } | 845 } |
| 768 | 846 |
| 769 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); | 847 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); |
| 770 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); | 848 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); |
| 849 |
| 850 bool is_js_accessor = (result.type() == CALLBACKS) && |
| 851 (result.GetCallbackObject()->IsFixedArray()); |
| 852 |
| 853 if (is_js_accessor) { |
| 854 // __defineGetter__/__defineSetter__ callback. |
| 855 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 856 |
| 857 FixedArray* structure = FixedArray::cast(result.GetCallbackObject()); |
| 858 if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { |
| 859 elms->set(GETTER_INDEX, structure->get(0)); |
| 860 } |
| 861 if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { |
| 862 elms->set(SETTER_INDEX, structure->get(1)); |
| 863 } |
| 864 } else { |
| 865 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 866 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
| 867 |
| 868 PropertyAttributes attrs; |
| 869 Object* value; |
| 870 // GetProperty will check access and report any violations. |
| 871 { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs); |
| 872 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 873 } |
| 874 elms->set(VALUE_INDEX, value); |
| 875 } |
| 876 |
| 771 return *desc; | 877 return *desc; |
| 772 } | 878 } |
| 773 | 879 |
| 774 | 880 |
| 775 static MaybeObject* Runtime_PreventExtensions(Arguments args) { | 881 static MaybeObject* Runtime_PreventExtensions(Arguments args) { |
| 776 ASSERT(args.length() == 1); | 882 ASSERT(args.length() == 1); |
| 777 CONVERT_CHECKED(JSObject, obj, args[0]); | 883 CONVERT_CHECKED(JSObject, obj, args[0]); |
| 778 return obj->PreventExtensions(); | 884 return obj->PreventExtensions(); |
| 779 } | 885 } |
| 780 | 886 |
| 887 |
| 781 static MaybeObject* Runtime_IsExtensible(Arguments args) { | 888 static MaybeObject* Runtime_IsExtensible(Arguments args) { |
| 782 ASSERT(args.length() == 1); | 889 ASSERT(args.length() == 1); |
| 783 CONVERT_CHECKED(JSObject, obj, args[0]); | 890 CONVERT_CHECKED(JSObject, obj, args[0]); |
| 784 return obj->map()->is_extensible() ? Heap::true_value() | 891 if (obj->IsJSGlobalProxy()) { |
| 892 Object* proto = obj->GetPrototype(); |
| 893 if (proto->IsNull()) return Heap::false_value(); |
| 894 ASSERT(proto->IsJSGlobalObject()); |
| 895 obj = JSObject::cast(proto); |
| 896 } |
| 897 return obj->map()->is_extensible() ? Heap::true_value() |
| 785 : Heap::false_value(); | 898 : Heap::false_value(); |
| 786 } | 899 } |
| 787 | 900 |
| 788 | 901 |
| 789 static MaybeObject* Runtime_RegExpCompile(Arguments args) { | 902 static MaybeObject* Runtime_RegExpCompile(Arguments args) { |
| 790 HandleScope scope; | 903 HandleScope scope; |
| 791 ASSERT(args.length() == 3); | 904 ASSERT(args.length() == 3); |
| 792 CONVERT_ARG_CHECKED(JSRegExp, re, 0); | 905 CONVERT_ARG_CHECKED(JSRegExp, re, 0); |
| 793 CONVERT_ARG_CHECKED(String, pattern, 1); | 906 CONVERT_ARG_CHECKED(String, pattern, 1); |
| 794 CONVERT_ARG_CHECKED(String, flags, 2); | 907 CONVERT_ARG_CHECKED(String, flags, 2); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 // that claims the property is absent. | 1082 // that claims the property is absent. |
| 970 | 1083 |
| 971 // Check for conflicting re-declarations. We cannot have | 1084 // Check for conflicting re-declarations. We cannot have |
| 972 // conflicting types in case of intercepted properties because | 1085 // conflicting types in case of intercepted properties because |
| 973 // they are absent. | 1086 // they are absent. |
| 974 if (lookup.type() != INTERCEPTOR && | 1087 if (lookup.type() != INTERCEPTOR && |
| 975 (lookup.IsReadOnly() || is_const_property)) { | 1088 (lookup.IsReadOnly() || is_const_property)) { |
| 976 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; | 1089 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; |
| 977 return ThrowRedeclarationError(type, name); | 1090 return ThrowRedeclarationError(type, name); |
| 978 } | 1091 } |
| 979 SetProperty(global, name, value, attributes); | 1092 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); |
| 980 } else { | 1093 } else { |
| 981 // If a property with this name does not already exist on the | 1094 // If a property with this name does not already exist on the |
| 982 // global object add the property locally. We take special | 1095 // global object add the property locally. We take special |
| 983 // precautions to always add it as a local property even in case | 1096 // precautions to always add it as a local property even in case |
| 984 // of callbacks in the prototype chain (this rules out using | 1097 // of callbacks in the prototype chain (this rules out using |
| 985 // SetProperty). Also, we must use the handle-based version to | 1098 // SetProperty). Also, we must use the handle-based version to |
| 986 // avoid GC issues. | 1099 // avoid GC issues. |
| 987 IgnoreAttributesAndSetLocalProperty(global, name, value, attributes); | 1100 RETURN_IF_EMPTY_HANDLE( |
| 1101 SetLocalPropertyIgnoreAttributes(global, name, value, attributes)); |
| 988 } | 1102 } |
| 989 } | 1103 } |
| 990 | 1104 |
| 1105 ASSERT(!Top::has_pending_exception()); |
| 991 return Heap::undefined_value(); | 1106 return Heap::undefined_value(); |
| 992 } | 1107 } |
| 993 | 1108 |
| 994 | 1109 |
| 995 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { | 1110 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
| 996 HandleScope scope; | 1111 HandleScope scope; |
| 997 ASSERT(args.length() == 4); | 1112 ASSERT(args.length() == 4); |
| 998 | 1113 |
| 999 CONVERT_ARG_CHECKED(Context, context, 0); | 1114 CONVERT_ARG_CHECKED(Context, context, 0); |
| 1000 Handle<String> name(String::cast(args[1])); | 1115 Handle<String> name(String::cast(args[1])); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1030 // the function context or the arguments object. | 1145 // the function context or the arguments object. |
| 1031 if (holder->IsContext()) { | 1146 if (holder->IsContext()) { |
| 1032 ASSERT(holder.is_identical_to(context)); | 1147 ASSERT(holder.is_identical_to(context)); |
| 1033 if (((attributes & READ_ONLY) == 0) || | 1148 if (((attributes & READ_ONLY) == 0) || |
| 1034 context->get(index)->IsTheHole()) { | 1149 context->get(index)->IsTheHole()) { |
| 1035 context->set(index, *initial_value); | 1150 context->set(index, *initial_value); |
| 1036 } | 1151 } |
| 1037 } else { | 1152 } else { |
| 1038 // The holder is an arguments object. | 1153 // The holder is an arguments object. |
| 1039 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1154 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
| 1040 SetElement(arguments, index, initial_value); | 1155 Handle<Object> result = SetElement(arguments, index, initial_value); |
| 1156 if (result.is_null()) return Failure::Exception(); |
| 1041 } | 1157 } |
| 1042 } else { | 1158 } else { |
| 1043 // Slow case: The property is not in the FixedArray part of the context. | 1159 // Slow case: The property is not in the FixedArray part of the context. |
| 1044 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1160 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
| 1045 SetProperty(context_ext, name, initial_value, mode); | 1161 RETURN_IF_EMPTY_HANDLE( |
| 1162 SetProperty(context_ext, name, initial_value, mode)); |
| 1046 } | 1163 } |
| 1047 } | 1164 } |
| 1048 | 1165 |
| 1049 } else { | 1166 } else { |
| 1050 // The property is not in the function context. It needs to be | 1167 // The property is not in the function context. It needs to be |
| 1051 // "declared" in the function context's extension context, or in the | 1168 // "declared" in the function context's extension context, or in the |
| 1052 // global context. | 1169 // global context. |
| 1053 Handle<JSObject> context_ext; | 1170 Handle<JSObject> context_ext; |
| 1054 if (context->has_extension()) { | 1171 if (context->has_extension()) { |
| 1055 // The function context's extension context exists - use it. | 1172 // The function context's extension context exists - use it. |
| 1056 context_ext = Handle<JSObject>(context->extension()); | 1173 context_ext = Handle<JSObject>(context->extension()); |
| 1057 } else { | 1174 } else { |
| 1058 // The function context's extension context does not exists - allocate | 1175 // The function context's extension context does not exists - allocate |
| 1059 // it. | 1176 // it. |
| 1060 context_ext = Factory::NewJSObject(Top::context_extension_function()); | 1177 context_ext = Factory::NewJSObject(Top::context_extension_function()); |
| 1061 // And store it in the extension slot. | 1178 // And store it in the extension slot. |
| 1062 context->set_extension(*context_ext); | 1179 context->set_extension(*context_ext); |
| 1063 } | 1180 } |
| 1064 ASSERT(*context_ext != NULL); | 1181 ASSERT(*context_ext != NULL); |
| 1065 | 1182 |
| 1066 // Declare the property by setting it to the initial value if provided, | 1183 // Declare the property by setting it to the initial value if provided, |
| 1067 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1184 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
| 1068 // constant declarations). | 1185 // constant declarations). |
| 1069 ASSERT(!context_ext->HasLocalProperty(*name)); | 1186 ASSERT(!context_ext->HasLocalProperty(*name)); |
| 1070 Handle<Object> value(Heap::undefined_value()); | 1187 Handle<Object> value(Heap::undefined_value()); |
| 1071 if (*initial_value != NULL) value = initial_value; | 1188 if (*initial_value != NULL) value = initial_value; |
| 1072 SetProperty(context_ext, name, value, mode); | 1189 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode)); |
| 1073 ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode); | |
| 1074 } | 1190 } |
| 1075 | 1191 |
| 1076 return Heap::undefined_value(); | 1192 return Heap::undefined_value(); |
| 1077 } | 1193 } |
| 1078 | 1194 |
| 1079 | 1195 |
| 1080 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { | 1196 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
| 1081 NoHandleAllocation nha; | 1197 NoHandleAllocation nha; |
| 1082 | 1198 |
| 1083 // Determine if we need to assign to the variable if it already | 1199 // Determine if we need to assign to the variable if it already |
| 1084 // exists (based on the number of arguments). | 1200 // exists (based on the number of arguments). |
| 1085 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); | 1201 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); |
| 1086 bool assign = args.length() == 2; | 1202 bool assign = args.length() == 2; |
| 1087 | 1203 |
| 1088 CONVERT_ARG_CHECKED(String, name, 0); | 1204 CONVERT_ARG_CHECKED(String, name, 0); |
| 1089 GlobalObject* global = Top::context()->global(); | 1205 GlobalObject* global = Top::context()->global(); |
| 1090 | 1206 |
| 1091 // According to ECMA-262, section 12.2, page 62, the property must | 1207 // According to ECMA-262, section 12.2, page 62, the property must |
| 1092 // not be deletable. | 1208 // not be deletable. |
| 1093 PropertyAttributes attributes = DONT_DELETE; | 1209 PropertyAttributes attributes = DONT_DELETE; |
| 1094 | 1210 |
| 1095 // Lookup the property locally in the global object. If it isn't | 1211 // Lookup the property locally in the global object. If it isn't |
| 1096 // there, there is a property with this name in the prototype chain. | 1212 // there, there is a property with this name in the prototype chain. |
| 1097 // We follow Safari and Firefox behavior and only set the property | 1213 // We follow Safari and Firefox behavior and only set the property |
| 1098 // locally if there is an explicit initialization value that we have | 1214 // locally if there is an explicit initialization value that we have |
| 1099 // to assign to the property. When adding the property we take | 1215 // to assign to the property. When adding the property we take |
| 1100 // special precautions to always add it as a local property even in | 1216 // special precautions to always add it as a local property even in |
| 1101 // case of callbacks in the prototype chain (this rules out using | 1217 // case of callbacks in the prototype chain (this rules out using |
| 1102 // SetProperty). We have IgnoreAttributesAndSetLocalProperty for | 1218 // SetProperty). We have SetLocalPropertyIgnoreAttributes for |
| 1103 // this. | 1219 // this. |
| 1104 // Note that objects can have hidden prototypes, so we need to traverse | 1220 // Note that objects can have hidden prototypes, so we need to traverse |
| 1105 // the whole chain of hidden prototypes to do a 'local' lookup. | 1221 // the whole chain of hidden prototypes to do a 'local' lookup. |
| 1106 JSObject* real_holder = global; | 1222 JSObject* real_holder = global; |
| 1107 LookupResult lookup; | 1223 LookupResult lookup; |
| 1108 while (true) { | 1224 while (true) { |
| 1109 real_holder->LocalLookup(*name, &lookup); | 1225 real_holder->LocalLookup(*name, &lookup); |
| 1110 if (lookup.IsProperty()) { | 1226 if (lookup.IsProperty()) { |
| 1111 // Determine if this is a redeclaration of something read-only. | 1227 // Determine if this is a redeclaration of something read-only. |
| 1112 if (lookup.IsReadOnly()) { | 1228 if (lookup.IsReadOnly()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 break; | 1271 break; |
| 1156 | 1272 |
| 1157 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) | 1273 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) |
| 1158 break; | 1274 break; |
| 1159 | 1275 |
| 1160 real_holder = JSObject::cast(proto); | 1276 real_holder = JSObject::cast(proto); |
| 1161 } | 1277 } |
| 1162 | 1278 |
| 1163 global = Top::context()->global(); | 1279 global = Top::context()->global(); |
| 1164 if (assign) { | 1280 if (assign) { |
| 1165 return global->IgnoreAttributesAndSetLocalProperty(*name, | 1281 return global->SetLocalPropertyIgnoreAttributes(*name, |
| 1166 args[1], | 1282 args[1], |
| 1167 attributes); | 1283 attributes); |
| 1168 } | 1284 } |
| 1169 return Heap::undefined_value(); | 1285 return Heap::undefined_value(); |
| 1170 } | 1286 } |
| 1171 | 1287 |
| 1172 | 1288 |
| 1173 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { | 1289 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { |
| 1174 // All constants are declared with an initial value. The name | 1290 // All constants are declared with an initial value. The name |
| 1175 // of the constant is the first argument and the initial value | 1291 // of the constant is the first argument and the initial value |
| 1176 // is the second. | 1292 // is the second. |
| 1177 RUNTIME_ASSERT(args.length() == 2); | 1293 RUNTIME_ASSERT(args.length() == 2); |
| 1178 CONVERT_ARG_CHECKED(String, name, 0); | 1294 CONVERT_ARG_CHECKED(String, name, 0); |
| 1179 Handle<Object> value = args.at<Object>(1); | 1295 Handle<Object> value = args.at<Object>(1); |
| 1180 | 1296 |
| 1181 // Get the current global object from top. | 1297 // Get the current global object from top. |
| 1182 GlobalObject* global = Top::context()->global(); | 1298 GlobalObject* global = Top::context()->global(); |
| 1183 | 1299 |
| 1184 // According to ECMA-262, section 12.2, page 62, the property must | 1300 // According to ECMA-262, section 12.2, page 62, the property must |
| 1185 // not be deletable. Since it's a const, it must be READ_ONLY too. | 1301 // not be deletable. Since it's a const, it must be READ_ONLY too. |
| 1186 PropertyAttributes attributes = | 1302 PropertyAttributes attributes = |
| 1187 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 1303 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
| 1188 | 1304 |
| 1189 // Lookup the property locally in the global object. If it isn't | 1305 // Lookup the property locally in the global object. If it isn't |
| 1190 // there, we add the property and take special precautions to always | 1306 // there, we add the property and take special precautions to always |
| 1191 // add it as a local property even in case of callbacks in the | 1307 // add it as a local property even in case of callbacks in the |
| 1192 // prototype chain (this rules out using SetProperty). | 1308 // prototype chain (this rules out using SetProperty). |
| 1193 // We use IgnoreAttributesAndSetLocalProperty instead | 1309 // We use SetLocalPropertyIgnoreAttributes instead |
| 1194 LookupResult lookup; | 1310 LookupResult lookup; |
| 1195 global->LocalLookup(*name, &lookup); | 1311 global->LocalLookup(*name, &lookup); |
| 1196 if (!lookup.IsProperty()) { | 1312 if (!lookup.IsProperty()) { |
| 1197 return global->IgnoreAttributesAndSetLocalProperty(*name, | 1313 return global->SetLocalPropertyIgnoreAttributes(*name, |
| 1198 *value, | 1314 *value, |
| 1199 attributes); | 1315 attributes); |
| 1200 } | 1316 } |
| 1201 | 1317 |
| 1202 // Determine if this is a redeclaration of something not | 1318 // Determine if this is a redeclaration of something not |
| 1203 // read-only. In case the result is hidden behind an interceptor we | 1319 // read-only. In case the result is hidden behind an interceptor we |
| 1204 // need to ask it for the property attributes. | 1320 // need to ask it for the property attributes. |
| 1205 if (!lookup.IsReadOnly()) { | 1321 if (!lookup.IsReadOnly()) { |
| 1206 if (lookup.type() != INTERCEPTOR) { | 1322 if (lookup.type() != INTERCEPTOR) { |
| 1207 return ThrowRedeclarationError("var", name); | 1323 return ThrowRedeclarationError("var", name); |
| 1208 } | 1324 } |
| 1209 | 1325 |
| 1210 PropertyAttributes intercepted = global->GetPropertyAttribute(*name); | 1326 PropertyAttributes intercepted = global->GetPropertyAttribute(*name); |
| 1211 | 1327 |
| 1212 // Throw re-declaration error if the intercepted property is present | 1328 // Throw re-declaration error if the intercepted property is present |
| 1213 // but not read-only. | 1329 // but not read-only. |
| 1214 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { | 1330 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { |
| 1215 return ThrowRedeclarationError("var", name); | 1331 return ThrowRedeclarationError("var", name); |
| 1216 } | 1332 } |
| 1217 | 1333 |
| 1218 // Restore global object from context (in case of GC) and continue | 1334 // Restore global object from context (in case of GC) and continue |
| 1219 // with setting the value because the property is either absent or | 1335 // with setting the value because the property is either absent or |
| 1220 // read-only. We also have to do redo the lookup. | 1336 // read-only. We also have to do redo the lookup. |
| 1221 HandleScope handle_scope; | 1337 HandleScope handle_scope; |
| 1222 Handle<GlobalObject>global(Top::context()->global()); | 1338 Handle<GlobalObject> global(Top::context()->global()); |
| 1223 | 1339 |
| 1224 // BUG 1213579: Handle the case where we have to set a read-only | 1340 // BUG 1213575: Handle the case where we have to set a read-only |
| 1225 // property through an interceptor and only do it if it's | 1341 // property through an interceptor and only do it if it's |
| 1226 // uninitialized, e.g. the hole. Nirk... | 1342 // uninitialized, e.g. the hole. Nirk... |
| 1227 SetProperty(global, name, value, attributes); | 1343 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); |
| 1228 return *value; | 1344 return *value; |
| 1229 } | 1345 } |
| 1230 | 1346 |
| 1231 // Set the value, but only we're assigning the initial value to a | 1347 // Set the value, but only we're assigning the initial value to a |
| 1232 // constant. For now, we determine this by checking if the | 1348 // constant. For now, we determine this by checking if the |
| 1233 // current value is the hole. | 1349 // current value is the hole. |
| 1234 PropertyType type = lookup.type(); | 1350 PropertyType type = lookup.type(); |
| 1235 if (type == FIELD) { | 1351 if (type == FIELD) { |
| 1236 FixedArray* properties = global->properties(); | 1352 FixedArray* properties = global->properties(); |
| 1237 int index = lookup.GetFieldIndex(); | 1353 int index = lookup.GetFieldIndex(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1415 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
| 1300 SetElement(arguments, index, value); | 1416 SetElement(arguments, index, value); |
| 1301 } | 1417 } |
| 1302 return *value; | 1418 return *value; |
| 1303 } | 1419 } |
| 1304 | 1420 |
| 1305 // The property could not be found, we introduce it in the global | 1421 // The property could not be found, we introduce it in the global |
| 1306 // context. | 1422 // context. |
| 1307 if (attributes == ABSENT) { | 1423 if (attributes == ABSENT) { |
| 1308 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); | 1424 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); |
| 1309 SetProperty(global, name, value, NONE); | 1425 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE)); |
| 1310 return *value; | 1426 return *value; |
| 1311 } | 1427 } |
| 1312 | 1428 |
| 1313 // The property was present in a context extension object. | 1429 // The property was present in a context extension object. |
| 1314 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1430 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
| 1315 | 1431 |
| 1316 if (*context_ext == context->extension()) { | 1432 if (*context_ext == context->extension()) { |
| 1317 // This is the property that was introduced by the const | 1433 // This is the property that was introduced by the const |
| 1318 // declaration. Set it if it hasn't been set before. NOTE: We | 1434 // declaration. Set it if it hasn't been set before. NOTE: We |
| 1319 // cannot use GetProperty() to get the current value as it | 1435 // cannot use GetProperty() to get the current value as it |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1336 } | 1452 } |
| 1337 } else { | 1453 } else { |
| 1338 // We should not reach here. Any real, named property should be | 1454 // We should not reach here. Any real, named property should be |
| 1339 // either a field or a dictionary slot. | 1455 // either a field or a dictionary slot. |
| 1340 UNREACHABLE(); | 1456 UNREACHABLE(); |
| 1341 } | 1457 } |
| 1342 } else { | 1458 } else { |
| 1343 // The property was found in a different context extension object. | 1459 // The property was found in a different context extension object. |
| 1344 // Set it if it is not a read-only property. | 1460 // Set it if it is not a read-only property. |
| 1345 if ((attributes & READ_ONLY) == 0) { | 1461 if ((attributes & READ_ONLY) == 0) { |
| 1346 Handle<Object> set = SetProperty(context_ext, name, value, attributes); | 1462 RETURN_IF_EMPTY_HANDLE( |
| 1347 // Setting a property might throw an exception. Exceptions | 1463 SetProperty(context_ext, name, value, attributes)); |
| 1348 // are converted to empty handles in handle operations. We | |
| 1349 // need to convert back to exceptions here. | |
| 1350 if (set.is_null()) { | |
| 1351 ASSERT(Top::has_pending_exception()); | |
| 1352 return Failure::Exception(); | |
| 1353 } | |
| 1354 } | 1464 } |
| 1355 } | 1465 } |
| 1356 | 1466 |
| 1357 return *value; | 1467 return *value; |
| 1358 } | 1468 } |
| 1359 | 1469 |
| 1360 | 1470 |
| 1361 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( | 1471 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( |
| 1362 Arguments args) { | 1472 Arguments args) { |
| 1363 HandleScope scope; | 1473 HandleScope scope; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 } | 1570 } |
| 1461 | 1571 |
| 1462 // Map has changed, so use generic, but slower, method. Since these | 1572 // Map has changed, so use generic, but slower, method. Since these |
| 1463 // properties were all added as DONT_DELETE they must be present and | 1573 // properties were all added as DONT_DELETE they must be present and |
| 1464 // normal so no failures can be expected. | 1574 // normal so no failures can be expected. |
| 1465 PropertyAttributes final = | 1575 PropertyAttributes final = |
| 1466 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); | 1576 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); |
| 1467 PropertyAttributes writable = | 1577 PropertyAttributes writable = |
| 1468 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); | 1578 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
| 1469 MaybeObject* result; | 1579 MaybeObject* result; |
| 1470 result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(), | 1580 result = regexp->SetLocalPropertyIgnoreAttributes(Heap::source_symbol(), |
| 1471 source, | 1581 source, |
| 1472 final); | 1582 final); |
| 1473 ASSERT(!result->IsFailure()); | 1583 ASSERT(!result->IsFailure()); |
| 1474 result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(), | 1584 result = regexp->SetLocalPropertyIgnoreAttributes(Heap::global_symbol(), |
| 1475 global, | 1585 global, |
| 1476 final); | 1586 final); |
| 1477 ASSERT(!result->IsFailure()); | 1587 ASSERT(!result->IsFailure()); |
| 1478 result = | 1588 result = |
| 1479 regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(), | 1589 regexp->SetLocalPropertyIgnoreAttributes(Heap::ignore_case_symbol(), |
| 1480 ignoreCase, | 1590 ignoreCase, |
| 1481 final); | 1591 final); |
| 1482 ASSERT(!result->IsFailure()); | 1592 ASSERT(!result->IsFailure()); |
| 1483 result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(), | 1593 result = regexp->SetLocalPropertyIgnoreAttributes(Heap::multiline_symbol(), |
| 1484 multiline, | 1594 multiline, |
| 1485 final); | 1595 final); |
| 1486 ASSERT(!result->IsFailure()); | 1596 ASSERT(!result->IsFailure()); |
| 1487 result = | 1597 result = |
| 1488 regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(), | 1598 regexp->SetLocalPropertyIgnoreAttributes(Heap::last_index_symbol(), |
| 1489 Smi::FromInt(0), | 1599 Smi::FromInt(0), |
| 1490 writable); | 1600 writable); |
| 1491 ASSERT(!result->IsFailure()); | 1601 ASSERT(!result->IsFailure()); |
| 1492 USE(result); | 1602 USE(result); |
| 1493 return regexp; | 1603 return regexp; |
| 1494 } | 1604 } |
| 1495 | 1605 |
| 1496 | 1606 |
| 1497 static MaybeObject* Runtime_FinishArrayPrototypeSetup(Arguments args) { | 1607 static MaybeObject* Runtime_FinishArrayPrototypeSetup(Arguments args) { |
| 1498 HandleScope scope; | 1608 HandleScope scope; |
| 1499 ASSERT(args.length() == 1); | 1609 ASSERT(args.length() == 1); |
| 1500 CONVERT_ARG_CHECKED(JSArray, prototype, 0); | 1610 CONVERT_ARG_CHECKED(JSArray, prototype, 0); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1736 target->ReplaceCode(shared->code()); | 1846 target->ReplaceCode(shared->code()); |
| 1737 target->shared()->set_scope_info(shared->scope_info()); | 1847 target->shared()->set_scope_info(shared->scope_info()); |
| 1738 target->shared()->set_length(shared->length()); | 1848 target->shared()->set_length(shared->length()); |
| 1739 target->shared()->set_formal_parameter_count( | 1849 target->shared()->set_formal_parameter_count( |
| 1740 shared->formal_parameter_count()); | 1850 shared->formal_parameter_count()); |
| 1741 // Set the source code of the target function to undefined. | 1851 // Set the source code of the target function to undefined. |
| 1742 // SetCode is only used for built-in constructors like String, | 1852 // SetCode is only used for built-in constructors like String, |
| 1743 // Array, and Object, and some web code | 1853 // Array, and Object, and some web code |
| 1744 // doesn't like seeing source code for constructors. | 1854 // doesn't like seeing source code for constructors. |
| 1745 target->shared()->set_script(Heap::undefined_value()); | 1855 target->shared()->set_script(Heap::undefined_value()); |
| 1856 target->shared()->code()->set_optimizable(false); |
| 1746 // Clear the optimization hints related to the compiled code as these are no | 1857 // Clear the optimization hints related to the compiled code as these are no |
| 1747 // longer valid when the code is overwritten. | 1858 // longer valid when the code is overwritten. |
| 1748 target->shared()->ClearThisPropertyAssignmentsInfo(); | 1859 target->shared()->ClearThisPropertyAssignmentsInfo(); |
| 1749 context = Handle<Context>(fun->context()); | 1860 context = Handle<Context>(fun->context()); |
| 1750 | 1861 |
| 1751 // Make sure we get a fresh copy of the literal vector to avoid | 1862 // Make sure we get a fresh copy of the literal vector to avoid |
| 1752 // cross context contamination. | 1863 // cross context contamination. |
| 1753 int number_of_literals = fun->NumberOfLiterals(); | 1864 int number_of_literals = fun->NumberOfLiterals(); |
| 1754 Handle<FixedArray> literals = | 1865 Handle<FixedArray> literals = |
| 1755 Factory::NewFixedArray(number_of_literals, TENURED); | 1866 Factory::NewFixedArray(number_of_literals, TENURED); |
| (...skipping 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3477 value = JSGlobalPropertyCell::cast(value)->value(); | 3588 value = JSGlobalPropertyCell::cast(value)->value(); |
| 3478 if (!value->IsTheHole()) return value; | 3589 if (!value->IsTheHole()) return value; |
| 3479 // If value is the hole do the general lookup. | 3590 // If value is the hole do the general lookup. |
| 3480 } | 3591 } |
| 3481 } | 3592 } |
| 3482 } else if (args[0]->IsString() && args[1]->IsSmi()) { | 3593 } else if (args[0]->IsString() && args[1]->IsSmi()) { |
| 3483 // Fast case for string indexing using [] with a smi index. | 3594 // Fast case for string indexing using [] with a smi index. |
| 3484 HandleScope scope; | 3595 HandleScope scope; |
| 3485 Handle<String> str = args.at<String>(0); | 3596 Handle<String> str = args.at<String>(0); |
| 3486 int index = Smi::cast(args[1])->value(); | 3597 int index = Smi::cast(args[1])->value(); |
| 3487 Handle<Object> result = GetCharAt(str, index); | 3598 if (index >= 0 && index < str->length()) { |
| 3488 return *result; | 3599 Handle<Object> result = GetCharAt(str, index); |
| 3600 return *result; |
| 3601 } |
| 3489 } | 3602 } |
| 3490 | 3603 |
| 3491 // Fall back to GetObjectProperty. | 3604 // Fall back to GetObjectProperty. |
| 3492 return Runtime::GetObjectProperty(args.at<Object>(0), | 3605 return Runtime::GetObjectProperty(args.at<Object>(0), |
| 3493 args.at<Object>(1)); | 3606 args.at<Object>(1)); |
| 3494 } | 3607 } |
| 3495 | 3608 |
| 3496 | 3609 // Implements part of 8.12.9 DefineOwnProperty. |
| 3610 // There are 3 cases that lead here: |
| 3611 // Step 4b - define a new accessor property. |
| 3612 // Steps 9c & 12 - replace an existing data property with an accessor property. |
| 3613 // Step 12 - update an existing accessor property with an accessor or generic |
| 3614 // descriptor. |
| 3497 static MaybeObject* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { | 3615 static MaybeObject* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { |
| 3498 ASSERT(args.length() == 5); | 3616 ASSERT(args.length() == 5); |
| 3499 HandleScope scope; | 3617 HandleScope scope; |
| 3500 CONVERT_ARG_CHECKED(JSObject, obj, 0); | 3618 CONVERT_ARG_CHECKED(JSObject, obj, 0); |
| 3501 CONVERT_CHECKED(String, name, args[1]); | 3619 CONVERT_CHECKED(String, name, args[1]); |
| 3502 CONVERT_CHECKED(Smi, flag_setter, args[2]); | 3620 CONVERT_CHECKED(Smi, flag_setter, args[2]); |
| 3503 Object* fun = args[3]; | 3621 Object* fun = args[3]; |
| 3504 RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined()); | 3622 RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined()); |
| 3505 CONVERT_CHECKED(Smi, flag_attr, args[4]); | 3623 CONVERT_CHECKED(Smi, flag_attr, args[4]); |
| 3506 int unchecked = flag_attr->value(); | 3624 int unchecked = flag_attr->value(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3518 || result.type() == CONSTANT_FUNCTION)) { | 3636 || result.type() == CONSTANT_FUNCTION)) { |
| 3519 Object* ok; | 3637 Object* ok; |
| 3520 { MaybeObject* maybe_ok = | 3638 { MaybeObject* maybe_ok = |
| 3521 obj->DeleteProperty(name, JSObject::NORMAL_DELETION); | 3639 obj->DeleteProperty(name, JSObject::NORMAL_DELETION); |
| 3522 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 3640 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 3523 } | 3641 } |
| 3524 } | 3642 } |
| 3525 return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); | 3643 return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); |
| 3526 } | 3644 } |
| 3527 | 3645 |
| 3646 // Implements part of 8.12.9 DefineOwnProperty. |
| 3647 // There are 3 cases that lead here: |
| 3648 // Step 4a - define a new data property. |
| 3649 // Steps 9b & 12 - replace an existing accessor property with a data property. |
| 3650 // Step 12 - update an existing data property with a data or generic |
| 3651 // descriptor. |
| 3528 static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) { | 3652 static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) { |
| 3529 ASSERT(args.length() == 4); | 3653 ASSERT(args.length() == 4); |
| 3530 HandleScope scope; | 3654 HandleScope scope; |
| 3531 CONVERT_ARG_CHECKED(JSObject, js_object, 0); | 3655 CONVERT_ARG_CHECKED(JSObject, js_object, 0); |
| 3532 CONVERT_ARG_CHECKED(String, name, 1); | 3656 CONVERT_ARG_CHECKED(String, name, 1); |
| 3533 Handle<Object> obj_value = args.at<Object>(2); | 3657 Handle<Object> obj_value = args.at<Object>(2); |
| 3534 | 3658 |
| 3535 CONVERT_CHECKED(Smi, flag, args[3]); | 3659 CONVERT_CHECKED(Smi, flag, args[3]); |
| 3536 int unchecked = flag->value(); | 3660 int unchecked = flag->value(); |
| 3537 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 3661 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 3538 | 3662 |
| 3539 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 3663 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
| 3540 | 3664 |
| 3541 // Check if this is an element. | 3665 // Check if this is an element. |
| 3542 uint32_t index; | 3666 uint32_t index; |
| 3543 bool is_element = name->AsArrayIndex(&index); | 3667 bool is_element = name->AsArrayIndex(&index); |
| 3544 | 3668 |
| 3545 // Special case for elements if any of the flags are true. | 3669 // Special case for elements if any of the flags are true. |
| 3546 // If elements are in fast case we always implicitly assume that: | 3670 // If elements are in fast case we always implicitly assume that: |
| 3547 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. | 3671 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. |
| 3548 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && | 3672 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && |
| 3549 is_element) { | 3673 is_element) { |
| 3550 // Normalize the elements to enable attributes on the property. | 3674 // Normalize the elements to enable attributes on the property. |
| 3675 if (js_object->IsJSGlobalProxy()) { |
| 3676 Handle<Object> proto(js_object->GetPrototype()); |
| 3677 // If proxy is detached, ignore the assignment. Alternatively, |
| 3678 // we could throw an exception. |
| 3679 if (proto->IsNull()) return *obj_value; |
| 3680 js_object = Handle<JSObject>::cast(proto); |
| 3681 } |
| 3551 NormalizeElements(js_object); | 3682 NormalizeElements(js_object); |
| 3552 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); | 3683 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); |
| 3553 // Make sure that we never go back to fast case. | 3684 // Make sure that we never go back to fast case. |
| 3554 dictionary->set_requires_slow_elements(); | 3685 dictionary->set_requires_slow_elements(); |
| 3555 PropertyDetails details = PropertyDetails(attr, NORMAL); | 3686 PropertyDetails details = PropertyDetails(attr, NORMAL); |
| 3556 NumberDictionarySet(dictionary, index, obj_value, details); | 3687 NumberDictionarySet(dictionary, index, obj_value, details); |
| 3688 return *obj_value; |
| 3557 } | 3689 } |
| 3558 | 3690 |
| 3559 LookupResult result; | 3691 LookupResult result; |
| 3560 js_object->LookupRealNamedProperty(*name, &result); | 3692 js_object->LookupRealNamedProperty(*name, &result); |
| 3561 | 3693 |
| 3562 // Take special care when attributes are different and there is already | 3694 // Take special care when attributes are different and there is already |
| 3563 // a property. For simplicity we normalize the property which enables us | 3695 // a property. For simplicity we normalize the property which enables us |
| 3564 // to not worry about changing the instance_descriptor and creating a new | 3696 // to not worry about changing the instance_descriptor and creating a new |
| 3565 // map. The current version of SetObjectProperty does not handle attributes | 3697 // map. The current version of SetObjectProperty does not handle attributes |
| 3566 // correctly in the case where a property is a field and is reset with | 3698 // correctly in the case where a property is a field and is reset with |
| 3567 // new attributes. | 3699 // new attributes. |
| 3568 if (result.IsProperty() && | 3700 if (result.IsProperty() && |
| 3569 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { | 3701 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { |
| 3570 // New attributes - normalize to avoid writing to instance descriptor | 3702 // New attributes - normalize to avoid writing to instance descriptor |
| 3703 if (js_object->IsJSGlobalProxy()) { |
| 3704 // Since the result is a property, the prototype will exist so |
| 3705 // we don't have to check for null. |
| 3706 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); |
| 3707 } |
| 3571 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 3708 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 3572 // Use IgnoreAttributes version since a readonly property may be | 3709 // Use IgnoreAttributes version since a readonly property may be |
| 3573 // overridden and SetProperty does not allow this. | 3710 // overridden and SetProperty does not allow this. |
| 3574 return js_object->IgnoreAttributesAndSetLocalProperty(*name, | 3711 return js_object->SetLocalPropertyIgnoreAttributes(*name, |
| 3575 *obj_value, | 3712 *obj_value, |
| 3576 attr); | 3713 attr); |
| 3577 } | 3714 } |
| 3578 | 3715 |
| 3579 return Runtime::SetObjectProperty(js_object, name, obj_value, attr); | 3716 return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr); |
| 3580 } | 3717 } |
| 3581 | 3718 |
| 3582 | 3719 |
| 3583 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, | 3720 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
| 3584 Handle<Object> key, | 3721 Handle<Object> key, |
| 3585 Handle<Object> value, | 3722 Handle<Object> value, |
| 3586 PropertyAttributes attr) { | 3723 PropertyAttributes attr) { |
| 3587 HandleScope scope; | 3724 HandleScope scope; |
| 3588 | 3725 |
| 3589 if (object->IsUndefined() || object->IsNull()) { | 3726 if (object->IsUndefined() || object->IsNull()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3667 | 3804 |
| 3668 return js_object->SetElement(index, *value); | 3805 return js_object->SetElement(index, *value); |
| 3669 } | 3806 } |
| 3670 | 3807 |
| 3671 if (key->IsString()) { | 3808 if (key->IsString()) { |
| 3672 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 3809 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 3673 return js_object->SetElement(index, *value); | 3810 return js_object->SetElement(index, *value); |
| 3674 } else { | 3811 } else { |
| 3675 Handle<String> key_string = Handle<String>::cast(key); | 3812 Handle<String> key_string = Handle<String>::cast(key); |
| 3676 key_string->TryFlatten(); | 3813 key_string->TryFlatten(); |
| 3677 return js_object->IgnoreAttributesAndSetLocalProperty(*key_string, | 3814 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, |
| 3678 *value, | 3815 *value, |
| 3679 attr); | 3816 attr); |
| 3680 } | 3817 } |
| 3681 } | 3818 } |
| 3682 | 3819 |
| 3683 // Call-back into JavaScript to convert the key to a string. | 3820 // Call-back into JavaScript to convert the key to a string. |
| 3684 bool has_pending_exception = false; | 3821 bool has_pending_exception = false; |
| 3685 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 3822 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3686 if (has_pending_exception) return Failure::Exception(); | 3823 if (has_pending_exception) return Failure::Exception(); |
| 3687 Handle<String> name = Handle<String>::cast(converted); | 3824 Handle<String> name = Handle<String>::cast(converted); |
| 3688 | 3825 |
| 3689 if (name->AsArrayIndex(&index)) { | 3826 if (name->AsArrayIndex(&index)) { |
| 3690 return js_object->SetElement(index, *value); | 3827 return js_object->SetElement(index, *value); |
| 3691 } else { | 3828 } else { |
| 3692 return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr); | 3829 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); |
| 3693 } | 3830 } |
| 3694 } | 3831 } |
| 3695 | 3832 |
| 3696 | 3833 |
| 3697 MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, | 3834 MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, |
| 3698 Handle<Object> key) { | 3835 Handle<Object> key) { |
| 3699 HandleScope scope; | 3836 HandleScope scope; |
| 3700 | 3837 |
| 3701 // Check if the given key is an array index. | 3838 // Check if the given key is an array index. |
| 3702 uint32_t index; | 3839 uint32_t index; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3764 if (args.length() == 4) { | 3901 if (args.length() == 4) { |
| 3765 CONVERT_CHECKED(Smi, value_obj, args[3]); | 3902 CONVERT_CHECKED(Smi, value_obj, args[3]); |
| 3766 int unchecked_value = value_obj->value(); | 3903 int unchecked_value = value_obj->value(); |
| 3767 // Only attribute bits should be set. | 3904 // Only attribute bits should be set. |
| 3768 RUNTIME_ASSERT( | 3905 RUNTIME_ASSERT( |
| 3769 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 3906 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 3770 attributes = static_cast<PropertyAttributes>(unchecked_value); | 3907 attributes = static_cast<PropertyAttributes>(unchecked_value); |
| 3771 } | 3908 } |
| 3772 | 3909 |
| 3773 return object-> | 3910 return object-> |
| 3774 IgnoreAttributesAndSetLocalProperty(name, args[2], attributes); | 3911 SetLocalPropertyIgnoreAttributes(name, args[2], attributes); |
| 3775 } | 3912 } |
| 3776 | 3913 |
| 3777 | 3914 |
| 3778 static MaybeObject* Runtime_DeleteProperty(Arguments args) { | 3915 static MaybeObject* Runtime_DeleteProperty(Arguments args) { |
| 3779 NoHandleAllocation ha; | 3916 NoHandleAllocation ha; |
| 3780 ASSERT(args.length() == 2); | 3917 ASSERT(args.length() == 3); |
| 3781 | 3918 |
| 3782 CONVERT_CHECKED(JSObject, object, args[0]); | 3919 CONVERT_CHECKED(JSObject, object, args[0]); |
| 3783 CONVERT_CHECKED(String, key, args[1]); | 3920 CONVERT_CHECKED(String, key, args[1]); |
| 3784 return object->DeleteProperty(key, JSObject::NORMAL_DELETION); | 3921 CONVERT_SMI_CHECKED(strict, args[2]); |
| 3922 return object->DeleteProperty(key, strict == kStrictMode |
| 3923 ? JSObject::STRICT_DELETION |
| 3924 : JSObject::NORMAL_DELETION); |
| 3785 } | 3925 } |
| 3786 | 3926 |
| 3787 | 3927 |
| 3788 static Object* HasLocalPropertyImplementation(Handle<JSObject> object, | 3928 static Object* HasLocalPropertyImplementation(Handle<JSObject> object, |
| 3789 Handle<String> key) { | 3929 Handle<String> key) { |
| 3790 if (object->HasLocalProperty(*key)) return Heap::true_value(); | 3930 if (object->HasLocalProperty(*key)) return Heap::true_value(); |
| 3791 // Handle hidden prototypes. If there's a hidden prototype above this thing | 3931 // Handle hidden prototypes. If there's a hidden prototype above this thing |
| 3792 // then we have to check it for properties, because they are supposed to | 3932 // then we have to check it for properties, because they are supposed to |
| 3793 // look like they are on this object. | 3933 // look like they are on this object. |
| 3794 Handle<Object> proto(object->GetPrototype()); | 3934 Handle<Object> proto(object->GetPrototype()); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4068 } | 4208 } |
| 4069 return Heap::undefined_value(); | 4209 return Heap::undefined_value(); |
| 4070 } | 4210 } |
| 4071 | 4211 |
| 4072 | 4212 |
| 4073 static MaybeObject* Runtime_LocalKeys(Arguments args) { | 4213 static MaybeObject* Runtime_LocalKeys(Arguments args) { |
| 4074 ASSERT_EQ(args.length(), 1); | 4214 ASSERT_EQ(args.length(), 1); |
| 4075 CONVERT_CHECKED(JSObject, raw_object, args[0]); | 4215 CONVERT_CHECKED(JSObject, raw_object, args[0]); |
| 4076 HandleScope scope; | 4216 HandleScope scope; |
| 4077 Handle<JSObject> object(raw_object); | 4217 Handle<JSObject> object(raw_object); |
| 4218 |
| 4219 if (object->IsJSGlobalProxy()) { |
| 4220 // Do access checks before going to the global object. |
| 4221 if (object->IsAccessCheckNeeded() && |
| 4222 !Top::MayNamedAccess(*object, Heap::undefined_value(), |
| 4223 v8::ACCESS_KEYS)) { |
| 4224 Top::ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
| 4225 return *Factory::NewJSArray(0); |
| 4226 } |
| 4227 |
| 4228 Handle<Object> proto(object->GetPrototype()); |
| 4229 // If proxy is detached we simply return an empty array. |
| 4230 if (proto->IsNull()) return *Factory::NewJSArray(0); |
| 4231 object = Handle<JSObject>::cast(proto); |
| 4232 } |
| 4233 |
| 4078 Handle<FixedArray> contents = GetKeysInFixedArrayFor(object, | 4234 Handle<FixedArray> contents = GetKeysInFixedArrayFor(object, |
| 4079 LOCAL_ONLY); | 4235 LOCAL_ONLY); |
| 4080 // Some fast paths through GetKeysInFixedArrayFor reuse a cached | 4236 // Some fast paths through GetKeysInFixedArrayFor reuse a cached |
| 4081 // property array and since the result is mutable we have to create | 4237 // property array and since the result is mutable we have to create |
| 4082 // a fresh clone on each invocation. | 4238 // a fresh clone on each invocation. |
| 4083 int length = contents->length(); | 4239 int length = contents->length(); |
| 4084 Handle<FixedArray> copy = Factory::NewFixedArray(length); | 4240 Handle<FixedArray> copy = Factory::NewFixedArray(length); |
| 4085 for (int i = 0; i < length; i++) { | 4241 for (int i = 0; i < length; i++) { |
| 4086 Object* entry = contents->get(i); | 4242 Object* entry = contents->get(i); |
| 4087 if (entry->IsString()) { | 4243 if (entry->IsString()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4157 } | 4313 } |
| 4158 return *object; | 4314 return *object; |
| 4159 } | 4315 } |
| 4160 | 4316 |
| 4161 | 4317 |
| 4162 static MaybeObject* Runtime_ToSlowProperties(Arguments args) { | 4318 static MaybeObject* Runtime_ToSlowProperties(Arguments args) { |
| 4163 HandleScope scope; | 4319 HandleScope scope; |
| 4164 | 4320 |
| 4165 ASSERT(args.length() == 1); | 4321 ASSERT(args.length() == 1); |
| 4166 Handle<Object> object = args.at<Object>(0); | 4322 Handle<Object> object = args.at<Object>(0); |
| 4167 if (object->IsJSObject()) { | 4323 if (object->IsJSObject() && !object->IsJSGlobalProxy()) { |
| 4168 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 4324 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 4169 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 4325 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 4170 } | 4326 } |
| 4171 return *object; | 4327 return *object; |
| 4172 } | 4328 } |
| 4173 | 4329 |
| 4174 | 4330 |
| 4175 static MaybeObject* Runtime_ToBool(Arguments args) { | 4331 static MaybeObject* Runtime_ToBool(Arguments args) { |
| 4176 NoHandleAllocation ha; | 4332 NoHandleAllocation ha; |
| 4177 ASSERT(args.length() == 1); | 4333 ASSERT(args.length() == 1); |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4608 return Heap::AllocateRawTwoByteString(length); | 4764 return Heap::AllocateRawTwoByteString(length); |
| 4609 } | 4765 } |
| 4610 | 4766 |
| 4611 | 4767 |
| 4612 template <> | 4768 template <> |
| 4613 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { | 4769 MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
| 4614 return Heap::AllocateRawAsciiString(length); | 4770 return Heap::AllocateRawAsciiString(length); |
| 4615 } | 4771 } |
| 4616 | 4772 |
| 4617 | 4773 |
| 4618 template <typename Char, typename StringType> | 4774 template <typename Char, typename StringType, bool comma> |
| 4619 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { | 4775 static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) { |
| 4620 int length = characters.length(); | 4776 int length = characters.length(); |
| 4621 const Char* read_cursor = characters.start(); | 4777 const Char* read_cursor = characters.start(); |
| 4622 const Char* end = read_cursor + length; | 4778 const Char* end = read_cursor + length; |
| 4623 const int kSpaceForQuotes = 2; | 4779 const int kSpaceForQuotes = 2 + (comma ? 1 :0); |
| 4624 int quoted_length = kSpaceForQuotes; | 4780 int quoted_length = kSpaceForQuotes; |
| 4625 while (read_cursor < end) { | 4781 while (read_cursor < end) { |
| 4626 Char c = *(read_cursor++); | 4782 Char c = *(read_cursor++); |
| 4627 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4783 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4628 quoted_length++; | 4784 quoted_length++; |
| 4629 } else { | 4785 } else { |
| 4630 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; | 4786 quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4631 } | 4787 } |
| 4632 } | 4788 } |
| 4633 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); | 4789 MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
| 4634 Object* new_object; | 4790 Object* new_object; |
| 4635 if (!new_alloc->ToObject(&new_object)) { | 4791 if (!new_alloc->ToObject(&new_object)) { |
| 4636 return new_alloc; | 4792 return new_alloc; |
| 4637 } | 4793 } |
| 4638 StringType* new_string = StringType::cast(new_object); | 4794 StringType* new_string = StringType::cast(new_object); |
| 4639 | 4795 |
| 4640 Char* write_cursor = reinterpret_cast<Char*>( | 4796 Char* write_cursor = reinterpret_cast<Char*>( |
| 4641 new_string->address() + SeqAsciiString::kHeaderSize); | 4797 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4798 if (comma) *(write_cursor++) = ','; |
| 4642 *(write_cursor++) = '"'; | 4799 *(write_cursor++) = '"'; |
| 4643 | 4800 |
| 4644 read_cursor = characters.start(); | 4801 read_cursor = characters.start(); |
| 4645 while (read_cursor < end) { | 4802 while (read_cursor < end) { |
| 4646 Char c = *(read_cursor++); | 4803 Char c = *(read_cursor++); |
| 4647 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4804 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4648 *(write_cursor++) = c; | 4805 *(write_cursor++) = c; |
| 4649 } else { | 4806 } else { |
| 4650 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 4807 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 4651 const char* replacement = JsonQuotes + | 4808 const char* replacement = JsonQuotes + |
| 4652 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; | 4809 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
| 4653 for (int i = 0; i < len; i++) { | 4810 for (int i = 0; i < len; i++) { |
| 4654 *write_cursor++ = *replacement++; | 4811 *write_cursor++ = *replacement++; |
| 4655 } | 4812 } |
| 4656 } | 4813 } |
| 4657 } | 4814 } |
| 4658 *(write_cursor++) = '"'; | 4815 *(write_cursor++) = '"'; |
| 4659 return new_string; | 4816 return new_string; |
| 4660 } | 4817 } |
| 4661 | 4818 |
| 4662 | 4819 |
| 4663 template <typename Char, typename StringType> | 4820 template <typename Char, typename StringType, bool comma> |
| 4664 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { | 4821 static MaybeObject* QuoteJsonString(Vector<const Char> characters) { |
| 4665 int length = characters.length(); | 4822 int length = characters.length(); |
| 4666 Counters::quote_json_char_count.Increment(length); | 4823 Counters::quote_json_char_count.Increment(length); |
| 4667 const int kSpaceForQuotes = 2; | 4824 const int kSpaceForQuotes = 2 + (comma ? 1 :0); |
| 4668 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 4825 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 4669 if (worst_case_length > kMaxGuaranteedNewSpaceString) { | 4826 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
| 4670 return SlowQuoteJsonString<Char, StringType>(characters); | 4827 return SlowQuoteJsonString<Char, StringType, comma>(characters); |
| 4671 } | 4828 } |
| 4672 | 4829 |
| 4673 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); | 4830 MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length); |
| 4674 Object* new_object; | 4831 Object* new_object; |
| 4675 if (!new_alloc->ToObject(&new_object)) { | 4832 if (!new_alloc->ToObject(&new_object)) { |
| 4676 return new_alloc; | 4833 return new_alloc; |
| 4677 } | 4834 } |
| 4678 if (!Heap::new_space()->Contains(new_object)) { | 4835 if (!Heap::new_space()->Contains(new_object)) { |
| 4679 // Even if our string is small enough to fit in new space we still have to | 4836 // Even if our string is small enough to fit in new space we still have to |
| 4680 // handle it being allocated in old space as may happen in the third | 4837 // handle it being allocated in old space as may happen in the third |
| 4681 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | 4838 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
| 4682 // CEntryStub::GenerateCore. | 4839 // CEntryStub::GenerateCore. |
| 4683 return SlowQuoteJsonString<Char, StringType>(characters); | 4840 return SlowQuoteJsonString<Char, StringType, comma>(characters); |
| 4684 } | 4841 } |
| 4685 StringType* new_string = StringType::cast(new_object); | 4842 StringType* new_string = StringType::cast(new_object); |
| 4686 ASSERT(Heap::new_space()->Contains(new_string)); | 4843 ASSERT(Heap::new_space()->Contains(new_string)); |
| 4687 | 4844 |
| 4688 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 4845 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 4689 Char* write_cursor = reinterpret_cast<Char*>( | 4846 Char* write_cursor = reinterpret_cast<Char*>( |
| 4690 new_string->address() + SeqAsciiString::kHeaderSize); | 4847 new_string->address() + SeqAsciiString::kHeaderSize); |
| 4848 if (comma) *(write_cursor++) = ','; |
| 4691 *(write_cursor++) = '"'; | 4849 *(write_cursor++) = '"'; |
| 4692 | 4850 |
| 4693 const Char* read_cursor = characters.start(); | 4851 const Char* read_cursor = characters.start(); |
| 4694 const Char* end = read_cursor + length; | 4852 const Char* end = read_cursor + length; |
| 4695 while (read_cursor < end) { | 4853 while (read_cursor < end) { |
| 4696 Char c = *(read_cursor++); | 4854 Char c = *(read_cursor++); |
| 4697 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 4855 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 4698 *(write_cursor++) = c; | 4856 *(write_cursor++) = c; |
| 4699 } else { | 4857 } else { |
| 4700 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 4858 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4731 if (!str->IsFlat()) { | 4889 if (!str->IsFlat()) { |
| 4732 MaybeObject* try_flatten = str->TryFlatten(); | 4890 MaybeObject* try_flatten = str->TryFlatten(); |
| 4733 Object* flat; | 4891 Object* flat; |
| 4734 if (!try_flatten->ToObject(&flat)) { | 4892 if (!try_flatten->ToObject(&flat)) { |
| 4735 return try_flatten; | 4893 return try_flatten; |
| 4736 } | 4894 } |
| 4737 str = String::cast(flat); | 4895 str = String::cast(flat); |
| 4738 ASSERT(str->IsFlat()); | 4896 ASSERT(str->IsFlat()); |
| 4739 } | 4897 } |
| 4740 if (str->IsTwoByteRepresentation()) { | 4898 if (str->IsTwoByteRepresentation()) { |
| 4741 return QuoteJsonString<uc16, SeqTwoByteString>(str->ToUC16Vector()); | 4899 return QuoteJsonString<uc16, SeqTwoByteString, false>(str->ToUC16Vector()); |
| 4742 } else { | 4900 } else { |
| 4743 return QuoteJsonString<char, SeqAsciiString>(str->ToAsciiVector()); | 4901 return QuoteJsonString<char, SeqAsciiString, false>(str->ToAsciiVector()); |
| 4744 } | 4902 } |
| 4745 } | 4903 } |
| 4746 | 4904 |
| 4747 | 4905 |
| 4906 static MaybeObject* Runtime_QuoteJSONStringComma(Arguments args) { |
| 4907 NoHandleAllocation ha; |
| 4908 CONVERT_CHECKED(String, str, args[0]); |
| 4909 if (!str->IsFlat()) { |
| 4910 MaybeObject* try_flatten = str->TryFlatten(); |
| 4911 Object* flat; |
| 4912 if (!try_flatten->ToObject(&flat)) { |
| 4913 return try_flatten; |
| 4914 } |
| 4915 str = String::cast(flat); |
| 4916 ASSERT(str->IsFlat()); |
| 4917 } |
| 4918 if (str->IsTwoByteRepresentation()) { |
| 4919 return QuoteJsonString<uc16, SeqTwoByteString, true>(str->ToUC16Vector()); |
| 4920 } else { |
| 4921 return QuoteJsonString<char, SeqAsciiString, true>(str->ToAsciiVector()); |
| 4922 } |
| 4923 } |
| 4924 |
| 4748 | 4925 |
| 4749 static MaybeObject* Runtime_StringParseInt(Arguments args) { | 4926 static MaybeObject* Runtime_StringParseInt(Arguments args) { |
| 4750 NoHandleAllocation ha; | 4927 NoHandleAllocation ha; |
| 4751 | 4928 |
| 4752 CONVERT_CHECKED(String, s, args[0]); | 4929 CONVERT_CHECKED(String, s, args[0]); |
| 4753 CONVERT_SMI_CHECKED(radix, args[1]); | 4930 CONVERT_SMI_CHECKED(radix, args[1]); |
| 4754 | 4931 |
| 4755 s->TryFlatten(); | 4932 s->TryFlatten(); |
| 4756 | 4933 |
| 4757 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); | 4934 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); |
| (...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5636 SeqTwoByteString* answer = SeqTwoByteString::cast(object); | 5813 SeqTwoByteString* answer = SeqTwoByteString::cast(object); |
| 5637 StringBuilderConcatHelper(special, | 5814 StringBuilderConcatHelper(special, |
| 5638 answer->GetChars(), | 5815 answer->GetChars(), |
| 5639 fixed_array, | 5816 fixed_array, |
| 5640 array_length); | 5817 array_length); |
| 5641 return answer; | 5818 return answer; |
| 5642 } | 5819 } |
| 5643 } | 5820 } |
| 5644 | 5821 |
| 5645 | 5822 |
| 5823 static MaybeObject* Runtime_StringBuilderJoin(Arguments args) { |
| 5824 NoHandleAllocation ha; |
| 5825 ASSERT(args.length() == 3); |
| 5826 CONVERT_CHECKED(JSArray, array, args[0]); |
| 5827 if (!args[1]->IsSmi()) { |
| 5828 Top::context()->mark_out_of_memory(); |
| 5829 return Failure::OutOfMemoryException(); |
| 5830 } |
| 5831 int array_length = Smi::cast(args[1])->value(); |
| 5832 CONVERT_CHECKED(String, separator, args[2]); |
| 5833 |
| 5834 if (!array->HasFastElements()) { |
| 5835 return Top::Throw(Heap::illegal_argument_symbol()); |
| 5836 } |
| 5837 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| 5838 if (fixed_array->length() < array_length) { |
| 5839 array_length = fixed_array->length(); |
| 5840 } |
| 5841 |
| 5842 if (array_length == 0) { |
| 5843 return Heap::empty_string(); |
| 5844 } else if (array_length == 1) { |
| 5845 Object* first = fixed_array->get(0); |
| 5846 if (first->IsString()) return first; |
| 5847 } |
| 5848 |
| 5849 int separator_length = separator->length(); |
| 5850 int max_nof_separators = |
| 5851 (String::kMaxLength + separator_length - 1) / separator_length; |
| 5852 if (max_nof_separators < (array_length - 1)) { |
| 5853 Top::context()->mark_out_of_memory(); |
| 5854 return Failure::OutOfMemoryException(); |
| 5855 } |
| 5856 int length = (array_length - 1) * separator_length; |
| 5857 for (int i = 0; i < array_length; i++) { |
| 5858 Object* element_obj = fixed_array->get(i); |
| 5859 if (!element_obj->IsString()) { |
| 5860 // TODO(1161): handle this case. |
| 5861 return Top::Throw(Heap::illegal_argument_symbol()); |
| 5862 } |
| 5863 String* element = String::cast(element_obj); |
| 5864 int increment = element->length(); |
| 5865 if (increment > String::kMaxLength - length) { |
| 5866 Top::context()->mark_out_of_memory(); |
| 5867 return Failure::OutOfMemoryException(); |
| 5868 } |
| 5869 length += increment; |
| 5870 } |
| 5871 |
| 5872 Object* object; |
| 5873 { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length); |
| 5874 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 5875 } |
| 5876 SeqTwoByteString* answer = SeqTwoByteString::cast(object); |
| 5877 |
| 5878 uc16* sink = answer->GetChars(); |
| 5879 #ifdef DEBUG |
| 5880 uc16* end = sink + length; |
| 5881 #endif |
| 5882 |
| 5883 String* first = String::cast(fixed_array->get(0)); |
| 5884 int first_length = first->length(); |
| 5885 String::WriteToFlat(first, sink, 0, first_length); |
| 5886 sink += first_length; |
| 5887 |
| 5888 for (int i = 1; i < array_length; i++) { |
| 5889 ASSERT(sink + separator_length <= end); |
| 5890 String::WriteToFlat(separator, sink, 0, separator_length); |
| 5891 sink += separator_length; |
| 5892 |
| 5893 String* element = String::cast(fixed_array->get(i)); |
| 5894 int element_length = element->length(); |
| 5895 ASSERT(sink + element_length <= end); |
| 5896 String::WriteToFlat(element, sink, 0, element_length); |
| 5897 sink += element_length; |
| 5898 } |
| 5899 ASSERT(sink == end); |
| 5900 |
| 5901 ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead. |
| 5902 return answer; |
| 5903 } |
| 5904 |
| 5905 |
| 5646 static MaybeObject* Runtime_NumberOr(Arguments args) { | 5906 static MaybeObject* Runtime_NumberOr(Arguments args) { |
| 5647 NoHandleAllocation ha; | 5907 NoHandleAllocation ha; |
| 5648 ASSERT(args.length() == 2); | 5908 ASSERT(args.length() == 2); |
| 5649 | 5909 |
| 5650 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | 5910 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); |
| 5651 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | 5911 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); |
| 5652 return Heap::NumberFromInt32(x | y); | 5912 return Heap::NumberFromInt32(x | y); |
| 5653 } | 5913 } |
| 5654 | 5914 |
| 5655 | 5915 |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6535 // directly to properties. | 6795 // directly to properties. |
| 6536 pretenure = pretenure || (context->global_context() == *context); | 6796 pretenure = pretenure || (context->global_context() == *context); |
| 6537 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; | 6797 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; |
| 6538 Handle<JSFunction> result = | 6798 Handle<JSFunction> result = |
| 6539 Factory::NewFunctionFromSharedFunctionInfo(shared, | 6799 Factory::NewFunctionFromSharedFunctionInfo(shared, |
| 6540 context, | 6800 context, |
| 6541 pretenure_flag); | 6801 pretenure_flag); |
| 6542 return *result; | 6802 return *result; |
| 6543 } | 6803 } |
| 6544 | 6804 |
| 6805 |
| 6545 static MaybeObject* Runtime_NewObjectFromBound(Arguments args) { | 6806 static MaybeObject* Runtime_NewObjectFromBound(Arguments args) { |
| 6546 HandleScope scope; | 6807 HandleScope scope; |
| 6547 ASSERT(args.length() == 2); | 6808 ASSERT(args.length() == 2); |
| 6809 // First argument is a function to use as a constructor. |
| 6548 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 6810 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 6549 CONVERT_ARG_CHECKED(JSArray, params, 1); | |
| 6550 | 6811 |
| 6551 RUNTIME_ASSERT(params->HasFastElements()); | 6812 // Second argument is either null or an array of bound arguments. |
| 6552 FixedArray* fixed = FixedArray::cast(params->elements()); | 6813 FixedArray* bound_args = NULL; |
| 6814 int bound_argc = 0; |
| 6815 if (!args[1]->IsNull()) { |
| 6816 CONVERT_ARG_CHECKED(JSArray, params, 1); |
| 6817 RUNTIME_ASSERT(params->HasFastElements()); |
| 6818 bound_args = FixedArray::cast(params->elements()); |
| 6819 bound_argc = Smi::cast(params->length())->value(); |
| 6820 } |
| 6553 | 6821 |
| 6554 int fixed_length = Smi::cast(params->length())->value(); | 6822 // Find frame containing arguments passed to the caller. |
| 6555 SmartPointer<Object**> param_data(NewArray<Object**>(fixed_length)); | 6823 JavaScriptFrameIterator it; |
| 6556 for (int i = 0; i < fixed_length; i++) { | 6824 JavaScriptFrame* frame = it.frame(); |
| 6557 Handle<Object> val = Handle<Object>(fixed->get(i)); | 6825 ASSERT(!frame->is_optimized()); |
| 6826 it.AdvanceToArgumentsFrame(); |
| 6827 frame = it.frame(); |
| 6828 int argc = frame->GetProvidedParametersCount(); |
| 6829 |
| 6830 // Prepend bound arguments to caller's arguments. |
| 6831 int total_argc = bound_argc + argc; |
| 6832 SmartPointer<Object**> param_data(NewArray<Object**>(total_argc)); |
| 6833 for (int i = 0; i < bound_argc; i++) { |
| 6834 Handle<Object> val = Handle<Object>(bound_args->get(i)); |
| 6558 param_data[i] = val.location(); | 6835 param_data[i] = val.location(); |
| 6559 } | 6836 } |
| 6837 for (int i = 0; i < argc; i++) { |
| 6838 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); |
| 6839 param_data[bound_argc + i] = val.location(); |
| 6840 } |
| 6560 | 6841 |
| 6561 bool exception = false; | 6842 bool exception = false; |
| 6562 Handle<Object> result = Execution::New( | 6843 Handle<Object> result = |
| 6563 function, fixed_length, *param_data, &exception); | 6844 Execution::New(function, total_argc, *param_data, &exception); |
| 6564 if (exception) { | 6845 if (exception) { |
| 6565 return Failure::Exception(); | 6846 return Failure::Exception(); |
| 6566 } | 6847 } |
| 6848 |
| 6567 ASSERT(!result.is_null()); | 6849 ASSERT(!result.is_null()); |
| 6568 return *result; | 6850 return *result; |
| 6569 } | 6851 } |
| 6570 | 6852 |
| 6571 | 6853 |
| 6572 static void TrySettingInlineConstructStub(Handle<JSFunction> function) { | 6854 static void TrySettingInlineConstructStub(Handle<JSFunction> function) { |
| 6573 Handle<Object> prototype = Factory::null_value(); | 6855 Handle<Object> prototype = Factory::null_value(); |
| 6574 if (function->has_instance_prototype()) { | 6856 if (function->has_instance_prototype()) { |
| 6575 prototype = Handle<Object>(function->instance_prototype()); | 6857 prototype = Handle<Object>(function->instance_prototype()); |
| 6576 } | 6858 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6707 | 6989 |
| 6708 | 6990 |
| 6709 static MaybeObject* Runtime_LazyRecompile(Arguments args) { | 6991 static MaybeObject* Runtime_LazyRecompile(Arguments args) { |
| 6710 HandleScope scope; | 6992 HandleScope scope; |
| 6711 ASSERT(args.length() == 1); | 6993 ASSERT(args.length() == 1); |
| 6712 Handle<JSFunction> function = args.at<JSFunction>(0); | 6994 Handle<JSFunction> function = args.at<JSFunction>(0); |
| 6713 // If the function is not optimizable or debugger is active continue using the | 6995 // If the function is not optimizable or debugger is active continue using the |
| 6714 // code from the full compiler. | 6996 // code from the full compiler. |
| 6715 if (!function->shared()->code()->optimizable() || | 6997 if (!function->shared()->code()->optimizable() || |
| 6716 Debug::has_break_points()) { | 6998 Debug::has_break_points()) { |
| 6999 if (FLAG_trace_opt) { |
| 7000 PrintF("[failed to optimize "); |
| 7001 function->PrintName(); |
| 7002 PrintF(": is code optimizable: %s, is debugger enabled: %s]\n", |
| 7003 function->shared()->code()->optimizable() ? "T" : "F", |
| 7004 Debug::has_break_points() ? "T" : "F"); |
| 7005 } |
| 6717 function->ReplaceCode(function->shared()->code()); | 7006 function->ReplaceCode(function->shared()->code()); |
| 6718 return function->code(); | 7007 return function->code(); |
| 6719 } | 7008 } |
| 6720 if (CompileOptimized(function, AstNode::kNoNumber)) { | 7009 if (CompileOptimized(function, AstNode::kNoNumber)) { |
| 6721 return function->code(); | 7010 return function->code(); |
| 6722 } | 7011 } |
| 7012 if (FLAG_trace_opt) { |
| 7013 PrintF("[failed to optimize "); |
| 7014 function->PrintName(); |
| 7015 PrintF(": optimized compilation failed]\n"); |
| 7016 } |
| 6723 function->ReplaceCode(function->shared()->code()); | 7017 function->ReplaceCode(function->shared()->code()); |
| 6724 return Failure::Exception(); | 7018 return Failure::Exception(); |
| 6725 } | 7019 } |
| 6726 | 7020 |
| 6727 | 7021 |
| 6728 static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) { | 7022 static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) { |
| 6729 HandleScope scope; | 7023 HandleScope scope; |
| 6730 ASSERT(args.length() == 1); | 7024 ASSERT(args.length() == 1); |
| 6731 RUNTIME_ASSERT(args[0]->IsSmi()); | 7025 RUNTIME_ASSERT(args[0]->IsSmi()); |
| 6732 Deoptimizer::BailoutType type = | 7026 Deoptimizer::BailoutType type = |
| 6733 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); | 7027 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); |
| 6734 Deoptimizer* deoptimizer = Deoptimizer::Grab(); | 7028 Deoptimizer* deoptimizer = Deoptimizer::Grab(); |
| 6735 ASSERT(Heap::IsAllocationAllowed()); | 7029 ASSERT(Heap::IsAllocationAllowed()); |
| 6736 int frames = deoptimizer->output_count(); | 7030 int frames = deoptimizer->output_count(); |
| 6737 | 7031 |
| 6738 JavaScriptFrameIterator it; | 7032 JavaScriptFrameIterator it; |
| 6739 JavaScriptFrame* frame = NULL; | 7033 JavaScriptFrame* frame = NULL; |
| 6740 for (int i = 0; i < frames; i++) { | 7034 for (int i = 0; i < frames; i++) { |
| 6741 if (i != 0) it.Advance(); | 7035 if (i != 0) it.Advance(); |
| 6742 frame = it.frame(); | 7036 frame = it.frame(); |
| 6743 deoptimizer->InsertHeapNumberValues(frames - i - 1, frame); | 7037 deoptimizer->InsertHeapNumberValues(frames - i - 1, frame); |
| 6744 } | 7038 } |
| 6745 delete deoptimizer; | 7039 delete deoptimizer; |
| 6746 | 7040 |
| 6747 RUNTIME_ASSERT(frame->function()->IsJSFunction()); | 7041 RUNTIME_ASSERT(frame->function()->IsJSFunction()); |
| 6748 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 7042 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| 6749 Handle<Object> arguments; | 7043 Handle<Object> arguments; |
| 6750 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { | 7044 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { |
| 6751 if (frame->GetExpression(i) == Heap::the_hole_value()) { | 7045 if (frame->GetExpression(i) == Heap::arguments_marker()) { |
| 6752 if (arguments.is_null()) { | 7046 if (arguments.is_null()) { |
| 6753 // FunctionGetArguments can't throw an exception, so cast away the | 7047 // FunctionGetArguments can't throw an exception, so cast away the |
| 6754 // doubt with an assert. | 7048 // doubt with an assert. |
| 6755 arguments = Handle<Object>( | 7049 arguments = Handle<Object>( |
| 6756 Accessors::FunctionGetArguments(*function, | 7050 Accessors::FunctionGetArguments(*function, |
| 6757 NULL)->ToObjectUnchecked()); | 7051 NULL)->ToObjectUnchecked()); |
| 6758 ASSERT(*arguments != Heap::null_value()); | 7052 ASSERT(*arguments != Heap::null_value()); |
| 6759 ASSERT(*arguments != Heap::undefined_value()); | 7053 ASSERT(*arguments != Heap::undefined_value()); |
| 6760 } | 7054 } |
| 6761 frame->SetExpression(i, *arguments); | 7055 frame->SetExpression(i, *arguments); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6852 JavaScriptFrameIterator it; | 7146 JavaScriptFrameIterator it; |
| 6853 JavaScriptFrame* frame = it.frame(); | 7147 JavaScriptFrame* frame = it.frame(); |
| 6854 ASSERT(frame->function() == *function); | 7148 ASSERT(frame->function() == *function); |
| 6855 ASSERT(frame->code() == *unoptimized); | 7149 ASSERT(frame->code() == *unoptimized); |
| 6856 ASSERT(unoptimized->contains(frame->pc())); | 7150 ASSERT(unoptimized->contains(frame->pc())); |
| 6857 | 7151 |
| 6858 // Use linear search of the unoptimized code's stack check table to find | 7152 // Use linear search of the unoptimized code's stack check table to find |
| 6859 // the AST id matching the PC. | 7153 // the AST id matching the PC. |
| 6860 Address start = unoptimized->instruction_start(); | 7154 Address start = unoptimized->instruction_start(); |
| 6861 unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start); | 7155 unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start); |
| 6862 Address table_cursor = start + unoptimized->stack_check_table_start(); | 7156 Address table_cursor = start + unoptimized->stack_check_table_offset(); |
| 6863 uint32_t table_length = Memory::uint32_at(table_cursor); | 7157 uint32_t table_length = Memory::uint32_at(table_cursor); |
| 6864 table_cursor += kIntSize; | 7158 table_cursor += kIntSize; |
| 6865 for (unsigned i = 0; i < table_length; ++i) { | 7159 for (unsigned i = 0; i < table_length; ++i) { |
| 6866 // Table entries are (AST id, pc offset) pairs. | 7160 // Table entries are (AST id, pc offset) pairs. |
| 6867 uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize); | 7161 uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize); |
| 6868 if (pc_offset == target_pc_offset) { | 7162 if (pc_offset == target_pc_offset) { |
| 6869 ast_id = static_cast<int>(Memory::uint32_at(table_cursor)); | 7163 ast_id = static_cast<int>(Memory::uint32_at(table_cursor)); |
| 6870 break; | 7164 break; |
| 6871 } | 7165 } |
| 6872 table_cursor += 2 * kIntSize; | 7166 table_cursor += 2 * kIntSize; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 6903 // Revert to the original stack checks in the original unoptimized code. | 7197 // Revert to the original stack checks in the original unoptimized code. |
| 6904 if (FLAG_trace_osr) { | 7198 if (FLAG_trace_osr) { |
| 6905 PrintF("[restoring original stack checks in "); | 7199 PrintF("[restoring original stack checks in "); |
| 6906 function->PrintName(); | 7200 function->PrintName(); |
| 6907 PrintF("]\n"); | 7201 PrintF("]\n"); |
| 6908 } | 7202 } |
| 6909 StackCheckStub check_stub; | 7203 StackCheckStub check_stub; |
| 6910 Handle<Code> check_code = check_stub.GetCode(); | 7204 Handle<Code> check_code = check_stub.GetCode(); |
| 6911 Handle<Code> replacement_code( | 7205 Handle<Code> replacement_code( |
| 6912 Builtins::builtin(Builtins::OnStackReplacement)); | 7206 Builtins::builtin(Builtins::OnStackReplacement)); |
| 6913 // Iterate the unoptimized code and revert all the patched stack checks. | 7207 Deoptimizer::RevertStackCheckCode(*unoptimized, |
| 6914 for (RelocIterator it(*unoptimized, RelocInfo::kCodeTargetMask); | 7208 *check_code, |
| 6915 !it.done(); | 7209 *replacement_code); |
| 6916 it.next()) { | |
| 6917 RelocInfo* rinfo = it.rinfo(); | |
| 6918 if (rinfo->target_address() == replacement_code->entry()) { | |
| 6919 Deoptimizer::RevertStackCheckCode(rinfo, *check_code); | |
| 6920 } | |
| 6921 } | |
| 6922 | 7210 |
| 6923 // Allow OSR only at nesting level zero again. | 7211 // Allow OSR only at nesting level zero again. |
| 6924 unoptimized->set_allow_osr_at_loop_nesting_level(0); | 7212 unoptimized->set_allow_osr_at_loop_nesting_level(0); |
| 6925 | 7213 |
| 6926 // If the optimization attempt succeeded, return the AST id tagged as a | 7214 // If the optimization attempt succeeded, return the AST id tagged as a |
| 6927 // smi. This tells the builtin that we need to translate the unoptimized | 7215 // smi. This tells the builtin that we need to translate the unoptimized |
| 6928 // frame to an optimized one. | 7216 // frame to an optimized one. |
| 6929 if (succeeded) { | 7217 if (succeeded) { |
| 6930 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | 7218 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
| 6931 return Smi::FromInt(ast_id); | 7219 return Smi::FromInt(ast_id); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7008 } | 7296 } |
| 7009 | 7297 |
| 7010 | 7298 |
| 7011 static MaybeObject* Runtime_PushCatchContext(Arguments args) { | 7299 static MaybeObject* Runtime_PushCatchContext(Arguments args) { |
| 7012 NoHandleAllocation ha; | 7300 NoHandleAllocation ha; |
| 7013 ASSERT(args.length() == 1); | 7301 ASSERT(args.length() == 1); |
| 7014 return PushContextHelper(args[0], true); | 7302 return PushContextHelper(args[0], true); |
| 7015 } | 7303 } |
| 7016 | 7304 |
| 7017 | 7305 |
| 7018 static MaybeObject* Runtime_LookupContext(Arguments args) { | 7306 static MaybeObject* Runtime_DeleteContextSlot(Arguments args) { |
| 7019 HandleScope scope; | 7307 HandleScope scope; |
| 7020 ASSERT(args.length() == 2); | 7308 ASSERT(args.length() == 2); |
| 7021 | 7309 |
| 7022 CONVERT_ARG_CHECKED(Context, context, 0); | 7310 CONVERT_ARG_CHECKED(Context, context, 0); |
| 7023 CONVERT_ARG_CHECKED(String, name, 1); | 7311 CONVERT_ARG_CHECKED(String, name, 1); |
| 7024 | 7312 |
| 7025 int index; | 7313 int index; |
| 7026 PropertyAttributes attributes; | 7314 PropertyAttributes attributes; |
| 7027 ContextLookupFlags flags = FOLLOW_CHAINS; | 7315 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7028 Handle<Object> holder = | 7316 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7029 context->Lookup(name, flags, &index, &attributes); | |
| 7030 | 7317 |
| 7031 if (index < 0 && !holder.is_null()) { | 7318 // If the slot was not found the result is true. |
| 7032 ASSERT(holder->IsJSObject()); | 7319 if (holder.is_null()) { |
| 7033 return *holder; | 7320 return Heap::true_value(); |
| 7034 } | 7321 } |
| 7035 | 7322 |
| 7036 // No intermediate context found. Use global object by default. | 7323 // If the slot was found in a context, it should be DONT_DELETE. |
| 7037 return Top::context()->global(); | 7324 if (holder->IsContext()) { |
| 7325 return Heap::false_value(); |
| 7326 } |
| 7327 |
| 7328 // The slot was found in a JSObject, either a context extension object, |
| 7329 // the global object, or an arguments object. Try to delete it |
| 7330 // (respecting DONT_DELETE). For consistency with V8's usual behavior, |
| 7331 // which allows deleting all parameters in functions that mention |
| 7332 // 'arguments', we do this even for the case of slots found on an |
| 7333 // arguments object. The slot was found on an arguments object if the |
| 7334 // index is non-negative. |
| 7335 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 7336 if (index >= 0) { |
| 7337 return object->DeleteElement(index, JSObject::NORMAL_DELETION); |
| 7338 } else { |
| 7339 return object->DeleteProperty(*name, JSObject::NORMAL_DELETION); |
| 7340 } |
| 7038 } | 7341 } |
| 7039 | 7342 |
| 7040 | 7343 |
| 7041 // A mechanism to return a pair of Object pointers in registers (if possible). | 7344 // A mechanism to return a pair of Object pointers in registers (if possible). |
| 7042 // How this is achieved is calling convention-dependent. | 7345 // How this is achieved is calling convention-dependent. |
| 7043 // All currently supported x86 compiles uses calling conventions that are cdecl | 7346 // All currently supported x86 compiles uses calling conventions that are cdecl |
| 7044 // variants where a 64-bit value is returned in two 32-bit registers | 7347 // variants where a 64-bit value is returned in two 32-bit registers |
| 7045 // (edx:eax on ia32, r1:r0 on ARM). | 7348 // (edx:eax on ia32, r1:r0 on ARM). |
| 7046 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. | 7349 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. |
| 7047 // In Win64 calling convention, a struct of two pointers is returned in memory, | 7350 // In Win64 calling convention, a struct of two pointers is returned in memory, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7100 | 7403 |
| 7101 if (!args[0]->IsContext() || !args[1]->IsString()) { | 7404 if (!args[0]->IsContext() || !args[1]->IsString()) { |
| 7102 return MakePair(Top::ThrowIllegalOperation(), NULL); | 7405 return MakePair(Top::ThrowIllegalOperation(), NULL); |
| 7103 } | 7406 } |
| 7104 Handle<Context> context = args.at<Context>(0); | 7407 Handle<Context> context = args.at<Context>(0); |
| 7105 Handle<String> name = args.at<String>(1); | 7408 Handle<String> name = args.at<String>(1); |
| 7106 | 7409 |
| 7107 int index; | 7410 int index; |
| 7108 PropertyAttributes attributes; | 7411 PropertyAttributes attributes; |
| 7109 ContextLookupFlags flags = FOLLOW_CHAINS; | 7412 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7110 Handle<Object> holder = | 7413 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7111 context->Lookup(name, flags, &index, &attributes); | |
| 7112 | 7414 |
| 7113 // If the index is non-negative, the slot has been found in a local | 7415 // If the index is non-negative, the slot has been found in a local |
| 7114 // variable or a parameter. Read it from the context object or the | 7416 // variable or a parameter. Read it from the context object or the |
| 7115 // arguments object. | 7417 // arguments object. |
| 7116 if (index >= 0) { | 7418 if (index >= 0) { |
| 7117 // If the "property" we were looking for is a local variable or an | 7419 // If the "property" we were looking for is a local variable or an |
| 7118 // argument in a context, the receiver is the global object; see | 7420 // argument in a context, the receiver is the global object; see |
| 7119 // ECMA-262, 3rd., 10.1.6 and 10.2.3. | 7421 // ECMA-262, 3rd., 10.1.6 and 10.2.3. |
| 7120 JSObject* receiver = Top::context()->global()->global_receiver(); | 7422 JSObject* receiver = Top::context()->global()->global_receiver(); |
| 7121 MaybeObject* value = (holder->IsContext()) | 7423 MaybeObject* value = (holder->IsContext()) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7168 HandleScope scope; | 7470 HandleScope scope; |
| 7169 ASSERT(args.length() == 3); | 7471 ASSERT(args.length() == 3); |
| 7170 | 7472 |
| 7171 Handle<Object> value(args[0]); | 7473 Handle<Object> value(args[0]); |
| 7172 CONVERT_ARG_CHECKED(Context, context, 1); | 7474 CONVERT_ARG_CHECKED(Context, context, 1); |
| 7173 CONVERT_ARG_CHECKED(String, name, 2); | 7475 CONVERT_ARG_CHECKED(String, name, 2); |
| 7174 | 7476 |
| 7175 int index; | 7477 int index; |
| 7176 PropertyAttributes attributes; | 7478 PropertyAttributes attributes; |
| 7177 ContextLookupFlags flags = FOLLOW_CHAINS; | 7479 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7178 Handle<Object> holder = | 7480 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7179 context->Lookup(name, flags, &index, &attributes); | |
| 7180 | 7481 |
| 7181 if (index >= 0) { | 7482 if (index >= 0) { |
| 7182 if (holder->IsContext()) { | 7483 if (holder->IsContext()) { |
| 7183 // Ignore if read_only variable. | 7484 // Ignore if read_only variable. |
| 7184 if ((attributes & READ_ONLY) == 0) { | 7485 if ((attributes & READ_ONLY) == 0) { |
| 7185 Handle<Context>::cast(holder)->set(index, *value); | 7486 // Context is a fixed array and set cannot fail. |
| 7487 Context::cast(*holder)->set(index, *value); |
| 7186 } | 7488 } |
| 7187 } else { | 7489 } else { |
| 7188 ASSERT((attributes & READ_ONLY) == 0); | 7490 ASSERT((attributes & READ_ONLY) == 0); |
| 7189 Handle<JSObject>::cast(holder)->SetElement(index, *value)-> | 7491 Handle<Object> result = |
| 7190 ToObjectUnchecked(); | 7492 SetElement(Handle<JSObject>::cast(holder), index, value); |
| 7493 if (result.is_null()) { |
| 7494 ASSERT(Top::has_pending_exception()); |
| 7495 return Failure::Exception(); |
| 7496 } |
| 7191 } | 7497 } |
| 7192 return *value; | 7498 return *value; |
| 7193 } | 7499 } |
| 7194 | 7500 |
| 7195 // Slow case: The property is not in a FixedArray context. | 7501 // Slow case: The property is not in a FixedArray context. |
| 7196 // It is either in an JSObject extension context or it was not found. | 7502 // It is either in an JSObject extension context or it was not found. |
| 7197 Handle<JSObject> context_ext; | 7503 Handle<JSObject> context_ext; |
| 7198 | 7504 |
| 7199 if (!holder.is_null()) { | 7505 if (!holder.is_null()) { |
| 7200 // The property exists in the extension context. | 7506 // The property exists in the extension context. |
| 7201 context_ext = Handle<JSObject>::cast(holder); | 7507 context_ext = Handle<JSObject>::cast(holder); |
| 7202 } else { | 7508 } else { |
| 7203 // The property was not found. It needs to be stored in the global context. | 7509 // The property was not found. It needs to be stored in the global context. |
| 7204 ASSERT(attributes == ABSENT); | 7510 ASSERT(attributes == ABSENT); |
| 7205 attributes = NONE; | 7511 attributes = NONE; |
| 7206 context_ext = Handle<JSObject>(Top::context()->global()); | 7512 context_ext = Handle<JSObject>(Top::context()->global()); |
| 7207 } | 7513 } |
| 7208 | 7514 |
| 7209 // Set the property, but ignore if read_only variable on the context | 7515 // Set the property, but ignore if read_only variable on the context |
| 7210 // extension object itself. | 7516 // extension object itself. |
| 7211 if ((attributes & READ_ONLY) == 0 || | 7517 if ((attributes & READ_ONLY) == 0 || |
| 7212 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 7518 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
| 7213 Handle<Object> set = SetProperty(context_ext, name, value, NONE); | 7519 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE)); |
| 7214 if (set.is_null()) { | |
| 7215 // Failure::Exception is converted to a null handle in the | |
| 7216 // handle-based methods such as SetProperty. We therefore need | |
| 7217 // to convert null handles back to exceptions. | |
| 7218 ASSERT(Top::has_pending_exception()); | |
| 7219 return Failure::Exception(); | |
| 7220 } | |
| 7221 } | 7520 } |
| 7222 return *value; | 7521 return *value; |
| 7223 } | 7522 } |
| 7224 | 7523 |
| 7225 | 7524 |
| 7226 static MaybeObject* Runtime_Throw(Arguments args) { | 7525 static MaybeObject* Runtime_Throw(Arguments args) { |
| 7227 HandleScope scope; | 7526 HandleScope scope; |
| 7228 ASSERT(args.length() == 1); | 7527 ASSERT(args.length() == 1); |
| 7229 | 7528 |
| 7230 return Top::Throw(args[0]); | 7529 return Top::Throw(args[0]); |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7509 | 7808 |
| 7510 static MaybeObject* Runtime_CompileString(Arguments args) { | 7809 static MaybeObject* Runtime_CompileString(Arguments args) { |
| 7511 HandleScope scope; | 7810 HandleScope scope; |
| 7512 ASSERT_EQ(1, args.length()); | 7811 ASSERT_EQ(1, args.length()); |
| 7513 CONVERT_ARG_CHECKED(String, source, 0); | 7812 CONVERT_ARG_CHECKED(String, source, 0); |
| 7514 | 7813 |
| 7515 // Compile source string in the global context. | 7814 // Compile source string in the global context. |
| 7516 Handle<Context> context(Top::context()->global_context()); | 7815 Handle<Context> context(Top::context()->global_context()); |
| 7517 Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, | 7816 Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, |
| 7518 context, | 7817 context, |
| 7519 true); | 7818 true, |
| 7819 kNonStrictMode); |
| 7520 if (shared.is_null()) return Failure::Exception(); | 7820 if (shared.is_null()) return Failure::Exception(); |
| 7521 Handle<JSFunction> fun = | 7821 Handle<JSFunction> fun = |
| 7522 Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED); | 7822 Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED); |
| 7523 return *fun; | 7823 return *fun; |
| 7524 } | 7824 } |
| 7525 | 7825 |
| 7526 | 7826 |
| 7527 static ObjectPair CompileGlobalEval(Handle<String> source, | 7827 static ObjectPair CompileGlobalEval(Handle<String> source, |
| 7528 Handle<Object> receiver) { | 7828 Handle<Object> receiver, |
| 7829 StrictModeFlag mode) { |
| 7529 // Deal with a normal eval call with a string argument. Compile it | 7830 // Deal with a normal eval call with a string argument. Compile it |
| 7530 // and return the compiled function bound in the local context. | 7831 // and return the compiled function bound in the local context. |
| 7531 Handle<SharedFunctionInfo> shared = Compiler::CompileEval( | 7832 Handle<SharedFunctionInfo> shared = Compiler::CompileEval( |
| 7532 source, | 7833 source, |
| 7533 Handle<Context>(Top::context()), | 7834 Handle<Context>(Top::context()), |
| 7534 Top::context()->IsGlobalContext()); | 7835 Top::context()->IsGlobalContext(), |
| 7836 mode); |
| 7535 if (shared.is_null()) return MakePair(Failure::Exception(), NULL); | 7837 if (shared.is_null()) return MakePair(Failure::Exception(), NULL); |
| 7536 Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo( | 7838 Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo( |
| 7537 shared, | 7839 shared, |
| 7538 Handle<Context>(Top::context()), | 7840 Handle<Context>(Top::context()), |
| 7539 NOT_TENURED); | 7841 NOT_TENURED); |
| 7540 return MakePair(*compiled, *receiver); | 7842 return MakePair(*compiled, *receiver); |
| 7541 } | 7843 } |
| 7542 | 7844 |
| 7543 | 7845 |
| 7544 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { | 7846 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { |
| 7545 ASSERT(args.length() == 3); | 7847 ASSERT(args.length() == 4); |
| 7546 if (!args[0]->IsJSFunction()) { | 7848 if (!args[0]->IsJSFunction()) { |
| 7547 return MakePair(Top::ThrowIllegalOperation(), NULL); | 7849 return MakePair(Top::ThrowIllegalOperation(), NULL); |
| 7548 } | 7850 } |
| 7549 | 7851 |
| 7550 HandleScope scope; | 7852 HandleScope scope; |
| 7551 Handle<JSFunction> callee = args.at<JSFunction>(0); | 7853 Handle<JSFunction> callee = args.at<JSFunction>(0); |
| 7552 Handle<Object> receiver; // Will be overwritten. | 7854 Handle<Object> receiver; // Will be overwritten. |
| 7553 | 7855 |
| 7554 // Compute the calling context. | 7856 // Compute the calling context. |
| 7555 Handle<Context> context = Handle<Context>(Top::context()); | 7857 Handle<Context> context = Handle<Context>(Top::context()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7599 return MakePair(*callee, *receiver); | 7901 return MakePair(*callee, *receiver); |
| 7600 } | 7902 } |
| 7601 | 7903 |
| 7602 // 'eval' is bound in the global context, but it may have been overwritten. | 7904 // 'eval' is bound in the global context, but it may have been overwritten. |
| 7603 // Compare it to the builtin 'GlobalEval' function to make sure. | 7905 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 7604 if (*callee != Top::global_context()->global_eval_fun() || | 7906 if (*callee != Top::global_context()->global_eval_fun() || |
| 7605 !args[1]->IsString()) { | 7907 !args[1]->IsString()) { |
| 7606 return MakePair(*callee, Top::context()->global()->global_receiver()); | 7908 return MakePair(*callee, Top::context()->global()->global_receiver()); |
| 7607 } | 7909 } |
| 7608 | 7910 |
| 7609 return CompileGlobalEval(args.at<String>(1), args.at<Object>(2)); | 7911 ASSERT(args[3]->IsSmi()); |
| 7912 return CompileGlobalEval(args.at<String>(1), |
| 7913 args.at<Object>(2), |
| 7914 static_cast<StrictModeFlag>( |
| 7915 Smi::cast(args[3])->value())); |
| 7610 } | 7916 } |
| 7611 | 7917 |
| 7612 | 7918 |
| 7613 static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) { | 7919 static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) { |
| 7614 ASSERT(args.length() == 3); | 7920 ASSERT(args.length() == 4); |
| 7615 if (!args[0]->IsJSFunction()) { | 7921 if (!args[0]->IsJSFunction()) { |
| 7616 return MakePair(Top::ThrowIllegalOperation(), NULL); | 7922 return MakePair(Top::ThrowIllegalOperation(), NULL); |
| 7617 } | 7923 } |
| 7618 | 7924 |
| 7619 HandleScope scope; | 7925 HandleScope scope; |
| 7620 Handle<JSFunction> callee = args.at<JSFunction>(0); | 7926 Handle<JSFunction> callee = args.at<JSFunction>(0); |
| 7621 | 7927 |
| 7622 // 'eval' is bound in the global context, but it may have been overwritten. | 7928 // 'eval' is bound in the global context, but it may have been overwritten. |
| 7623 // Compare it to the builtin 'GlobalEval' function to make sure. | 7929 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 7624 if (*callee != Top::global_context()->global_eval_fun() || | 7930 if (*callee != Top::global_context()->global_eval_fun() || |
| 7625 !args[1]->IsString()) { | 7931 !args[1]->IsString()) { |
| 7626 return MakePair(*callee, Top::context()->global()->global_receiver()); | 7932 return MakePair(*callee, Top::context()->global()->global_receiver()); |
| 7627 } | 7933 } |
| 7628 | 7934 |
| 7629 return CompileGlobalEval(args.at<String>(1), args.at<Object>(2)); | 7935 ASSERT(args[3]->IsSmi()); |
| 7936 return CompileGlobalEval(args.at<String>(1), |
| 7937 args.at<Object>(2), |
| 7938 static_cast<StrictModeFlag>( |
| 7939 Smi::cast(args[3])->value())); |
| 7630 } | 7940 } |
| 7631 | 7941 |
| 7632 | 7942 |
| 7633 static MaybeObject* Runtime_SetNewFunctionAttributes(Arguments args) { | 7943 static MaybeObject* Runtime_SetNewFunctionAttributes(Arguments args) { |
| 7634 // This utility adjusts the property attributes for newly created Function | 7944 // This utility adjusts the property attributes for newly created Function |
| 7635 // object ("new Function(...)") by changing the map. | 7945 // object ("new Function(...)") by changing the map. |
| 7636 // All it does is changing the prototype property to enumerable | 7946 // All it does is changing the prototype property to enumerable |
| 7637 // as specified in ECMA262, 15.3.5.2. | 7947 // as specified in ECMA262, 15.3.5.2. |
| 7638 HandleScope scope; | 7948 HandleScope scope; |
| 7639 ASSERT(args.length() == 1); | 7949 ASSERT(args.length() == 1); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8050 } | 8360 } |
| 8051 if (JSObject::kMaxElementCount - result_length < length_estimate) { | 8361 if (JSObject::kMaxElementCount - result_length < length_estimate) { |
| 8052 result_length = JSObject::kMaxElementCount; | 8362 result_length = JSObject::kMaxElementCount; |
| 8053 break; | 8363 break; |
| 8054 } | 8364 } |
| 8055 result_length += length_estimate; | 8365 result_length += length_estimate; |
| 8056 } | 8366 } |
| 8057 } | 8367 } |
| 8058 } | 8368 } |
| 8059 | 8369 |
| 8060 // Allocate an empty array, will set length and content later. | 8370 // Allocate an empty array, will set map, length, and content later. |
| 8061 Handle<JSArray> result = Factory::NewJSArray(0); | 8371 Handle<JSArray> result = Factory::NewJSArray(0); |
| 8062 | 8372 |
| 8063 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); | 8373 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); |
| 8064 // If estimated number of elements is more than half of length, a | 8374 // If estimated number of elements is more than half of length, a |
| 8065 // fixed array (fast case) is more time and space-efficient than a | 8375 // fixed array (fast case) is more time and space-efficient than a |
| 8066 // dictionary. | 8376 // dictionary. |
| 8067 bool fast_case = (estimate_nof_elements * 2) >= result_length; | 8377 bool fast_case = (estimate_nof_elements * 2) >= result_length; |
| 8068 | 8378 |
| 8379 Handle<Map> map; |
| 8069 Handle<FixedArray> storage; | 8380 Handle<FixedArray> storage; |
| 8070 if (fast_case) { | 8381 if (fast_case) { |
| 8071 // The backing storage array must have non-existing elements to | 8382 // The backing storage array must have non-existing elements to |
| 8072 // preserve holes across concat operations. | 8383 // preserve holes across concat operations. |
| 8384 map = Factory::GetFastElementsMap(Handle<Map>(result->map())); |
| 8073 storage = Factory::NewFixedArrayWithHoles(result_length); | 8385 storage = Factory::NewFixedArrayWithHoles(result_length); |
| 8074 Handle<Map> fast_map = | |
| 8075 Factory::GetFastElementsMap(Handle<Map>(result->map())); | |
| 8076 result->set_map(*fast_map); | |
| 8077 } else { | 8386 } else { |
| 8387 map = Factory::GetSlowElementsMap(Handle<Map>(result->map())); |
| 8078 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 8388 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
| 8079 uint32_t at_least_space_for = estimate_nof_elements + | 8389 uint32_t at_least_space_for = estimate_nof_elements + |
| 8080 (estimate_nof_elements >> 2); | 8390 (estimate_nof_elements >> 2); |
| 8081 storage = Handle<FixedArray>::cast( | 8391 storage = Handle<FixedArray>::cast( |
| 8082 Factory::NewNumberDictionary(at_least_space_for)); | 8392 Factory::NewNumberDictionary(at_least_space_for)); |
| 8083 Handle<Map> slow_map = | |
| 8084 Factory::GetSlowElementsMap(Handle<Map>(result->map())); | |
| 8085 result->set_map(*slow_map); | |
| 8086 } | 8393 } |
| 8087 | 8394 |
| 8088 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); | 8395 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); |
| 8089 | 8396 |
| 8090 ArrayConcatVisitor visitor(storage, result_length, fast_case); | 8397 ArrayConcatVisitor visitor(storage, result_length, fast_case); |
| 8091 | 8398 |
| 8092 IterateArguments(arguments, &visitor); | 8399 IterateArguments(arguments, &visitor); |
| 8093 | 8400 |
| 8401 // Please note: |
| 8402 // - the storage might have been changed in the visitor; |
| 8403 // - the map and the storage must be set together to avoid breaking |
| 8404 // the invariant that the map describes the array's elements. |
| 8405 result->set_map(*map); |
| 8094 result->set_length(*len); | 8406 result->set_length(*len); |
| 8095 // Please note the storage might have changed in the visitor. | |
| 8096 result->set_elements(*visitor.storage()); | 8407 result->set_elements(*visitor.storage()); |
| 8097 | 8408 |
| 8098 return *result; | 8409 return *result; |
| 8099 } | 8410 } |
| 8100 | 8411 |
| 8101 | 8412 |
| 8102 // This will not allocate (flatten the string), but it may run | 8413 // This will not allocate (flatten the string), but it may run |
| 8103 // very slowly for very deeply nested ConsStrings. For debugging use only. | 8414 // very slowly for very deeply nested ConsStrings. For debugging use only. |
| 8104 static MaybeObject* Runtime_GlobalPrint(Arguments args) { | 8415 static MaybeObject* Runtime_GlobalPrint(Arguments args) { |
| 8105 NoHandleAllocation ha; | 8416 NoHandleAllocation ha; |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8679 for (int i = 0; i < info.NumberOfLocals(); i++) { | 8990 for (int i = 0; i < info.NumberOfLocals(); i++) { |
| 8680 locals->set(i * 2, *info.LocalName(i)); | 8991 locals->set(i * 2, *info.LocalName(i)); |
| 8681 } | 8992 } |
| 8682 | 8993 |
| 8683 // Fill in the values of the locals. | 8994 // Fill in the values of the locals. |
| 8684 for (int i = 0; i < info.NumberOfLocals(); i++) { | 8995 for (int i = 0; i < info.NumberOfLocals(); i++) { |
| 8685 if (is_optimized_frame) { | 8996 if (is_optimized_frame) { |
| 8686 // If we are inspecting an optimized frame use undefined as the | 8997 // If we are inspecting an optimized frame use undefined as the |
| 8687 // value for all locals. | 8998 // value for all locals. |
| 8688 // | 8999 // |
| 8689 // TODO(3141533): We should be able to get the correct values | 9000 // TODO(1140): We should be able to get the correct values |
| 8690 // for locals in optimized frames. | 9001 // for locals in optimized frames. |
| 8691 locals->set(i * 2 + 1, Heap::undefined_value()); | 9002 locals->set(i * 2 + 1, Heap::undefined_value()); |
| 8692 } else if (i < info.number_of_stack_slots()) { | 9003 } else if (i < info.number_of_stack_slots()) { |
| 8693 // Get the value from the stack. | 9004 // Get the value from the stack. |
| 8694 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 9005 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); |
| 8695 } else { | 9006 } else { |
| 8696 // Traverse the context chain to the function context as all local | 9007 // Traverse the context chain to the function context as all local |
| 8697 // variables stored in the context will be on the function context. | 9008 // variables stored in the context will be on the function context. |
| 8698 Handle<String> name = info.LocalName(i); | 9009 Handle<String> name = info.LocalName(i); |
| 8699 while (!context->is_function_context()) { | 9010 while (!context->is_function_context()) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8843 receiver = Factory::ToObject(receiver, calling_frames_global_context); | 9154 receiver = Factory::ToObject(receiver, calling_frames_global_context); |
| 8844 } | 9155 } |
| 8845 details->set(kFrameDetailsReceiverIndex, *receiver); | 9156 details->set(kFrameDetailsReceiverIndex, *receiver); |
| 8846 | 9157 |
| 8847 ASSERT_EQ(details_size, details_index); | 9158 ASSERT_EQ(details_size, details_index); |
| 8848 return *Factory::NewJSArrayWithElements(details); | 9159 return *Factory::NewJSArrayWithElements(details); |
| 8849 } | 9160 } |
| 8850 | 9161 |
| 8851 | 9162 |
| 8852 // Copy all the context locals into an object used to materialize a scope. | 9163 // Copy all the context locals into an object used to materialize a scope. |
| 8853 static void CopyContextLocalsToScopeObject( | 9164 static bool CopyContextLocalsToScopeObject( |
| 8854 Handle<SerializedScopeInfo> serialized_scope_info, | 9165 Handle<SerializedScopeInfo> serialized_scope_info, |
| 8855 ScopeInfo<>& scope_info, | 9166 ScopeInfo<>& scope_info, |
| 8856 Handle<Context> context, | 9167 Handle<Context> context, |
| 8857 Handle<JSObject> scope_object) { | 9168 Handle<JSObject> scope_object) { |
| 8858 // Fill all context locals to the context extension. | 9169 // Fill all context locals to the context extension. |
| 8859 for (int i = Context::MIN_CONTEXT_SLOTS; | 9170 for (int i = Context::MIN_CONTEXT_SLOTS; |
| 8860 i < scope_info.number_of_context_slots(); | 9171 i < scope_info.number_of_context_slots(); |
| 8861 i++) { | 9172 i++) { |
| 8862 int context_index = serialized_scope_info->ContextSlotIndex( | 9173 int context_index = serialized_scope_info->ContextSlotIndex( |
| 8863 *scope_info.context_slot_name(i), NULL); | 9174 *scope_info.context_slot_name(i), NULL); |
| 8864 | 9175 |
| 8865 // Don't include the arguments shadow (.arguments) context variable. | 9176 // Don't include the arguments shadow (.arguments) context variable. |
| 8866 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) { | 9177 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) { |
| 8867 SetProperty(scope_object, | 9178 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 8868 scope_info.context_slot_name(i), | 9179 SetProperty(scope_object, |
| 8869 Handle<Object>(context->get(context_index)), NONE); | 9180 scope_info.context_slot_name(i), |
| 9181 Handle<Object>(context->get(context_index)), NONE), |
| 9182 false); |
| 8870 } | 9183 } |
| 8871 } | 9184 } |
| 9185 |
| 9186 return true; |
| 8872 } | 9187 } |
| 8873 | 9188 |
| 8874 | 9189 |
| 8875 // Create a plain JSObject which materializes the local scope for the specified | 9190 // Create a plain JSObject which materializes the local scope for the specified |
| 8876 // frame. | 9191 // frame. |
| 8877 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { | 9192 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { |
| 8878 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 9193 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| 8879 Handle<SharedFunctionInfo> shared(function->shared()); | 9194 Handle<SharedFunctionInfo> shared(function->shared()); |
| 8880 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); | 9195 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); |
| 8881 ScopeInfo<> scope_info(*serialized_scope_info); | 9196 ScopeInfo<> scope_info(*serialized_scope_info); |
| 8882 | 9197 |
| 8883 // Allocate and initialize a JSObject with all the arguments, stack locals | 9198 // Allocate and initialize a JSObject with all the arguments, stack locals |
| 8884 // heap locals and extension properties of the debugged function. | 9199 // heap locals and extension properties of the debugged function. |
| 8885 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function()); | 9200 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function()); |
| 8886 | 9201 |
| 8887 // First fill all parameters. | 9202 // First fill all parameters. |
| 8888 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { | 9203 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { |
| 8889 SetProperty(local_scope, | 9204 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 8890 scope_info.parameter_name(i), | 9205 SetProperty(local_scope, |
| 8891 Handle<Object>(frame->GetParameter(i)), NONE); | 9206 scope_info.parameter_name(i), |
| 9207 Handle<Object>(frame->GetParameter(i)), NONE), |
| 9208 Handle<JSObject>()); |
| 8892 } | 9209 } |
| 8893 | 9210 |
| 8894 // Second fill all stack locals. | 9211 // Second fill all stack locals. |
| 8895 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { | 9212 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { |
| 8896 SetProperty(local_scope, | 9213 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 8897 scope_info.stack_slot_name(i), | 9214 SetProperty(local_scope, |
| 8898 Handle<Object>(frame->GetExpression(i)), NONE); | 9215 scope_info.stack_slot_name(i), |
| 9216 Handle<Object>(frame->GetExpression(i)), NONE), |
| 9217 Handle<JSObject>()); |
| 8899 } | 9218 } |
| 8900 | 9219 |
| 8901 // Third fill all context locals. | 9220 // Third fill all context locals. |
| 8902 Handle<Context> frame_context(Context::cast(frame->context())); | 9221 Handle<Context> frame_context(Context::cast(frame->context())); |
| 8903 Handle<Context> function_context(frame_context->fcontext()); | 9222 Handle<Context> function_context(frame_context->fcontext()); |
| 8904 CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, | 9223 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, |
| 8905 function_context, local_scope); | 9224 function_context, local_scope)) { |
| 9225 return Handle<JSObject>(); |
| 9226 } |
| 8906 | 9227 |
| 8907 // Finally copy any properties from the function context extension. This will | 9228 // Finally copy any properties from the function context extension. This will |
| 8908 // be variables introduced by eval. | 9229 // be variables introduced by eval. |
| 8909 if (function_context->closure() == *function) { | 9230 if (function_context->closure() == *function) { |
| 8910 if (function_context->has_extension() && | 9231 if (function_context->has_extension() && |
| 8911 !function_context->IsGlobalContext()) { | 9232 !function_context->IsGlobalContext()) { |
| 8912 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | 9233 Handle<JSObject> ext(JSObject::cast(function_context->extension())); |
| 8913 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); | 9234 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); |
| 8914 for (int i = 0; i < keys->length(); i++) { | 9235 for (int i = 0; i < keys->length(); i++) { |
| 8915 // Names of variables introduced by eval are strings. | 9236 // Names of variables introduced by eval are strings. |
| 8916 ASSERT(keys->get(i)->IsString()); | 9237 ASSERT(keys->get(i)->IsString()); |
| 8917 Handle<String> key(String::cast(keys->get(i))); | 9238 Handle<String> key(String::cast(keys->get(i))); |
| 8918 SetProperty(local_scope, key, GetProperty(ext, key), NONE); | 9239 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9240 SetProperty(local_scope, key, GetProperty(ext, key), NONE), |
| 9241 Handle<JSObject>()); |
| 8919 } | 9242 } |
| 8920 } | 9243 } |
| 8921 } | 9244 } |
| 8922 return local_scope; | 9245 return local_scope; |
| 8923 } | 9246 } |
| 8924 | 9247 |
| 8925 | 9248 |
| 8926 // Create a plain JSObject which materializes the closure content for the | 9249 // Create a plain JSObject which materializes the closure content for the |
| 8927 // context. | 9250 // context. |
| 8928 static Handle<JSObject> MaterializeClosure(Handle<Context> context) { | 9251 static Handle<JSObject> MaterializeClosure(Handle<Context> context) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 8941 shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(), | 9264 shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(), |
| 8942 NULL); | 9265 NULL); |
| 8943 if (arguments_shadow_index >= 0) { | 9266 if (arguments_shadow_index >= 0) { |
| 8944 // In this case all the arguments are available in the arguments shadow | 9267 // In this case all the arguments are available in the arguments shadow |
| 8945 // object. | 9268 // object. |
| 8946 Handle<JSObject> arguments_shadow( | 9269 Handle<JSObject> arguments_shadow( |
| 8947 JSObject::cast(context->get(arguments_shadow_index))); | 9270 JSObject::cast(context->get(arguments_shadow_index))); |
| 8948 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { | 9271 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { |
| 8949 // We don't expect exception-throwing getters on the arguments shadow. | 9272 // We don't expect exception-throwing getters on the arguments shadow. |
| 8950 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); | 9273 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); |
| 8951 SetProperty(closure_scope, | 9274 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 8952 scope_info.parameter_name(i), | 9275 SetProperty(closure_scope, |
| 8953 Handle<Object>(element), | 9276 scope_info.parameter_name(i), |
| 8954 NONE); | 9277 Handle<Object>(element), |
| 9278 NONE), |
| 9279 Handle<JSObject>()); |
| 8955 } | 9280 } |
| 8956 } | 9281 } |
| 8957 | 9282 |
| 8958 // Fill all context locals to the context extension. | 9283 // Fill all context locals to the context extension. |
| 8959 CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, | 9284 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, |
| 8960 context, closure_scope); | 9285 context, closure_scope)) { |
| 9286 return Handle<JSObject>(); |
| 9287 } |
| 8961 | 9288 |
| 8962 // Finally copy any properties from the function context extension. This will | 9289 // Finally copy any properties from the function context extension. This will |
| 8963 // be variables introduced by eval. | 9290 // be variables introduced by eval. |
| 8964 if (context->has_extension()) { | 9291 if (context->has_extension()) { |
| 8965 Handle<JSObject> ext(JSObject::cast(context->extension())); | 9292 Handle<JSObject> ext(JSObject::cast(context->extension())); |
| 8966 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); | 9293 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); |
| 8967 for (int i = 0; i < keys->length(); i++) { | 9294 for (int i = 0; i < keys->length(); i++) { |
| 8968 // Names of variables introduced by eval are strings. | 9295 // Names of variables introduced by eval are strings. |
| 8969 ASSERT(keys->get(i)->IsString()); | 9296 ASSERT(keys->get(i)->IsString()); |
| 8970 Handle<String> key(String::cast(keys->get(i))); | 9297 Handle<String> key(String::cast(keys->get(i))); |
| 8971 SetProperty(closure_scope, key, GetProperty(ext, key), NONE); | 9298 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9299 SetProperty(closure_scope, key, GetProperty(ext, key), NONE), |
| 9300 Handle<JSObject>()); |
| 8972 } | 9301 } |
| 8973 } | 9302 } |
| 8974 | 9303 |
| 8975 return closure_scope; | 9304 return closure_scope; |
| 8976 } | 9305 } |
| 8977 | 9306 |
| 8978 | 9307 |
| 8979 // Iterate over the actual scopes visible from a stack frame. All scopes are | 9308 // Iterate over the actual scopes visible from a stack frame. All scopes are |
| 8980 // backed by an actual context except the local scope, which is inserted | 9309 // backed by an actual context except the local scope, which is inserted |
| 8981 // "artifically" in the context chain. | 9310 // "artifically" in the context chain. |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9248 return Heap::undefined_value(); | 9577 return Heap::undefined_value(); |
| 9249 } | 9578 } |
| 9250 | 9579 |
| 9251 // Calculate the size of the result. | 9580 // Calculate the size of the result. |
| 9252 int details_size = kScopeDetailsSize; | 9581 int details_size = kScopeDetailsSize; |
| 9253 Handle<FixedArray> details = Factory::NewFixedArray(details_size); | 9582 Handle<FixedArray> details = Factory::NewFixedArray(details_size); |
| 9254 | 9583 |
| 9255 // Fill in scope details. | 9584 // Fill in scope details. |
| 9256 details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type())); | 9585 details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type())); |
| 9257 Handle<JSObject> scope_object = it.ScopeObject(); | 9586 Handle<JSObject> scope_object = it.ScopeObject(); |
| 9587 RETURN_IF_EMPTY_HANDLE(scope_object); |
| 9258 details->set(kScopeDetailsObjectIndex, *scope_object); | 9588 details->set(kScopeDetailsObjectIndex, *scope_object); |
| 9259 | 9589 |
| 9260 return *Factory::NewJSArrayWithElements(details); | 9590 return *Factory::NewJSArrayWithElements(details); |
| 9261 } | 9591 } |
| 9262 | 9592 |
| 9263 | 9593 |
| 9264 static MaybeObject* Runtime_DebugPrintScopes(Arguments args) { | 9594 static MaybeObject* Runtime_DebugPrintScopes(Arguments args) { |
| 9265 HandleScope scope; | 9595 HandleScope scope; |
| 9266 ASSERT(args.length() == 0); | 9596 ASSERT(args.length() == 0); |
| 9267 | 9597 |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9729 Factory::NewFunction(Factory::empty_string(), Factory::undefined_value()); | 10059 Factory::NewFunction(Factory::empty_string(), Factory::undefined_value()); |
| 9730 go_between->set_context(function->context()); | 10060 go_between->set_context(function->context()); |
| 9731 #ifdef DEBUG | 10061 #ifdef DEBUG |
| 9732 ScopeInfo<> go_between_sinfo(go_between->shared()->scope_info()); | 10062 ScopeInfo<> go_between_sinfo(go_between->shared()->scope_info()); |
| 9733 ASSERT(go_between_sinfo.number_of_parameters() == 0); | 10063 ASSERT(go_between_sinfo.number_of_parameters() == 0); |
| 9734 ASSERT(go_between_sinfo.number_of_context_slots() == 0); | 10064 ASSERT(go_between_sinfo.number_of_context_slots() == 0); |
| 9735 #endif | 10065 #endif |
| 9736 | 10066 |
| 9737 // Materialize the content of the local scope into a JSObject. | 10067 // Materialize the content of the local scope into a JSObject. |
| 9738 Handle<JSObject> local_scope = MaterializeLocalScope(frame); | 10068 Handle<JSObject> local_scope = MaterializeLocalScope(frame); |
| 10069 RETURN_IF_EMPTY_HANDLE(local_scope); |
| 9739 | 10070 |
| 9740 // Allocate a new context for the debug evaluation and set the extension | 10071 // Allocate a new context for the debug evaluation and set the extension |
| 9741 // object build. | 10072 // object build. |
| 9742 Handle<Context> context = | 10073 Handle<Context> context = |
| 9743 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between); | 10074 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between); |
| 9744 context->set_extension(*local_scope); | 10075 context->set_extension(*local_scope); |
| 9745 // Copy any with contexts present and chain them in front of this context. | 10076 // Copy any with contexts present and chain them in front of this context. |
| 9746 Handle<Context> frame_context(Context::cast(frame->context())); | 10077 Handle<Context> frame_context(Context::cast(frame->context())); |
| 9747 Handle<Context> function_context(frame_context->fcontext()); | 10078 Handle<Context> function_context(frame_context->fcontext()); |
| 9748 context = CopyWithContextChain(frame_context, context); | 10079 context = CopyWithContextChain(frame_context, context); |
| 9749 | 10080 |
| 9750 if (additional_context->IsJSObject()) { | 10081 if (additional_context->IsJSObject()) { |
| 9751 context = Factory::NewWithContext(context, | 10082 context = Factory::NewWithContext(context, |
| 9752 Handle<JSObject>::cast(additional_context), false); | 10083 Handle<JSObject>::cast(additional_context), false); |
| 9753 } | 10084 } |
| 9754 | 10085 |
| 9755 // Wrap the evaluation statement in a new function compiled in the newly | 10086 // Wrap the evaluation statement in a new function compiled in the newly |
| 9756 // created context. The function has one parameter which has to be called | 10087 // created context. The function has one parameter which has to be called |
| 9757 // 'arguments'. This it to have access to what would have been 'arguments' in | 10088 // 'arguments'. This it to have access to what would have been 'arguments' in |
| 9758 // the function being debugged. | 10089 // the function being debugged. |
| 9759 // function(arguments,__source__) {return eval(__source__);} | 10090 // function(arguments,__source__) {return eval(__source__);} |
| 9760 static const char* source_str = | 10091 static const char* source_str = |
| 9761 "(function(arguments,__source__){return eval(__source__);})"; | 10092 "(function(arguments,__source__){return eval(__source__);})"; |
| 9762 static const int source_str_length = StrLength(source_str); | 10093 static const int source_str_length = StrLength(source_str); |
| 9763 Handle<String> function_source = | 10094 Handle<String> function_source = |
| 9764 Factory::NewStringFromAscii(Vector<const char>(source_str, | 10095 Factory::NewStringFromAscii(Vector<const char>(source_str, |
| 9765 source_str_length)); | 10096 source_str_length)); |
| 10097 |
| 10098 // Currently, the eval code will be executed in non-strict mode, |
| 10099 // even in the strict code context. |
| 9766 Handle<SharedFunctionInfo> shared = | 10100 Handle<SharedFunctionInfo> shared = |
| 9767 Compiler::CompileEval(function_source, | 10101 Compiler::CompileEval(function_source, |
| 9768 context, | 10102 context, |
| 9769 context->IsGlobalContext()); | 10103 context->IsGlobalContext(), |
| 10104 kNonStrictMode); |
| 9770 if (shared.is_null()) return Failure::Exception(); | 10105 if (shared.is_null()) return Failure::Exception(); |
| 9771 Handle<JSFunction> compiled_function = | 10106 Handle<JSFunction> compiled_function = |
| 9772 Factory::NewFunctionFromSharedFunctionInfo(shared, context); | 10107 Factory::NewFunctionFromSharedFunctionInfo(shared, context); |
| 9773 | 10108 |
| 9774 // Invoke the result of the compilation to get the evaluation function. | 10109 // Invoke the result of the compilation to get the evaluation function. |
| 9775 bool has_pending_exception; | 10110 bool has_pending_exception; |
| 9776 Handle<Object> receiver(frame->receiver()); | 10111 Handle<Object> receiver(frame->receiver()); |
| 9777 Handle<Object> evaluation_function = | 10112 Handle<Object> evaluation_function = |
| 9778 Execution::Call(compiled_function, receiver, 0, NULL, | 10113 Execution::Call(compiled_function, receiver, 0, NULL, |
| 9779 &has_pending_exception); | 10114 &has_pending_exception); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9841 Handle<JSFunction> go_between = Factory::NewFunction( | 10176 Handle<JSFunction> go_between = Factory::NewFunction( |
| 9842 Factory::empty_string(), Factory::undefined_value()); | 10177 Factory::empty_string(), Factory::undefined_value()); |
| 9843 go_between->set_context(*context); | 10178 go_between->set_context(*context); |
| 9844 context = | 10179 context = |
| 9845 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between); | 10180 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between); |
| 9846 context->set_extension(JSObject::cast(*additional_context)); | 10181 context->set_extension(JSObject::cast(*additional_context)); |
| 9847 is_global = false; | 10182 is_global = false; |
| 9848 } | 10183 } |
| 9849 | 10184 |
| 9850 // Compile the source to be evaluated. | 10185 // Compile the source to be evaluated. |
| 10186 // Currently, the eval code will be executed in non-strict mode, |
| 10187 // even in the strict code context. |
| 9851 Handle<SharedFunctionInfo> shared = | 10188 Handle<SharedFunctionInfo> shared = |
| 9852 Compiler::CompileEval(source, | 10189 Compiler::CompileEval(source, context, is_global, kNonStrictMode); |
| 9853 context, | |
| 9854 is_global); | |
| 9855 if (shared.is_null()) return Failure::Exception(); | 10190 if (shared.is_null()) return Failure::Exception(); |
| 9856 Handle<JSFunction> compiled_function = | 10191 Handle<JSFunction> compiled_function = |
| 9857 Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared, | 10192 Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared, |
| 9858 context)); | 10193 context)); |
| 9859 | 10194 |
| 9860 // Invoke the result of the compilation to get the evaluation function. | 10195 // Invoke the result of the compilation to get the evaluation function. |
| 9861 bool has_pending_exception; | 10196 bool has_pending_exception; |
| 9862 Handle<Object> receiver = Top::global(); | 10197 Handle<Object> receiver = Top::global(); |
| 9863 Handle<Object> result = | 10198 Handle<Object> result = |
| 9864 Execution::Call(compiled_function, receiver, 0, NULL, | 10199 Execution::Call(compiled_function, receiver, 0, NULL, |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10327 // LiveEdit::FunctionPatchabilityStatus type. | 10662 // LiveEdit::FunctionPatchabilityStatus type. |
| 10328 static MaybeObject* Runtime_LiveEditCheckAndDropActivations(Arguments args) { | 10663 static MaybeObject* Runtime_LiveEditCheckAndDropActivations(Arguments args) { |
| 10329 ASSERT(args.length() == 2); | 10664 ASSERT(args.length() == 2); |
| 10330 HandleScope scope; | 10665 HandleScope scope; |
| 10331 CONVERT_ARG_CHECKED(JSArray, shared_array, 0); | 10666 CONVERT_ARG_CHECKED(JSArray, shared_array, 0); |
| 10332 CONVERT_BOOLEAN_CHECKED(do_drop, args[1]); | 10667 CONVERT_BOOLEAN_CHECKED(do_drop, args[1]); |
| 10333 | 10668 |
| 10334 return *LiveEdit::CheckAndDropActivations(shared_array, do_drop); | 10669 return *LiveEdit::CheckAndDropActivations(shared_array, do_drop); |
| 10335 } | 10670 } |
| 10336 | 10671 |
| 10337 // Compares 2 strings line-by-line and returns diff in form of JSArray of | 10672 // Compares 2 strings line-by-line, then token-wise and returns diff in form |
| 10338 // triplets (pos1, pos1_end, pos2_end) describing list of diff chunks. | 10673 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list |
| 10339 static MaybeObject* Runtime_LiveEditCompareStringsLinewise(Arguments args) { | 10674 // of diff chunks. |
| 10675 static MaybeObject* Runtime_LiveEditCompareStrings(Arguments args) { |
| 10340 ASSERT(args.length() == 2); | 10676 ASSERT(args.length() == 2); |
| 10341 HandleScope scope; | 10677 HandleScope scope; |
| 10342 CONVERT_ARG_CHECKED(String, s1, 0); | 10678 CONVERT_ARG_CHECKED(String, s1, 0); |
| 10343 CONVERT_ARG_CHECKED(String, s2, 1); | 10679 CONVERT_ARG_CHECKED(String, s2, 1); |
| 10344 | 10680 |
| 10345 return *LiveEdit::CompareStringsLinewise(s1, s2); | 10681 return *LiveEdit::CompareStrings(s1, s2); |
| 10346 } | 10682 } |
| 10347 | 10683 |
| 10348 | 10684 |
| 10349 | 10685 |
| 10350 // A testing entry. Returns statement position which is the closest to | 10686 // A testing entry. Returns statement position which is the closest to |
| 10351 // source_position. | 10687 // source_position. |
| 10352 static MaybeObject* Runtime_GetFunctionCodePositionFromSource(Arguments args) { | 10688 static MaybeObject* Runtime_GetFunctionCodePositionFromSource(Arguments args) { |
| 10353 ASSERT(args.length() == 2); | 10689 ASSERT(args.length() == 2); |
| 10354 HandleScope scope; | 10690 HandleScope scope; |
| 10355 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 10691 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10405 } | 10741 } |
| 10406 } | 10742 } |
| 10407 if (!pending_exception) { | 10743 if (!pending_exception) { |
| 10408 return *result; | 10744 return *result; |
| 10409 } else { | 10745 } else { |
| 10410 return Failure::Exception(); | 10746 return Failure::Exception(); |
| 10411 } | 10747 } |
| 10412 } | 10748 } |
| 10413 | 10749 |
| 10414 | 10750 |
| 10751 // Sets a v8 flag. |
| 10752 static MaybeObject* Runtime_SetFlags(Arguments args) { |
| 10753 CONVERT_CHECKED(String, arg, args[0]); |
| 10754 SmartPointer<char> flags = |
| 10755 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
| 10756 FlagList::SetFlagsFromString(*flags, StrLength(*flags)); |
| 10757 return Heap::undefined_value(); |
| 10758 } |
| 10759 |
| 10760 |
| 10761 // Performs a GC. |
| 10762 // Presently, it only does a full GC. |
| 10763 static MaybeObject* Runtime_CollectGarbage(Arguments args) { |
| 10764 Heap::CollectAllGarbage(true); |
| 10765 return Heap::undefined_value(); |
| 10766 } |
| 10767 |
| 10768 |
| 10769 // Gets the current heap usage. |
| 10770 static MaybeObject* Runtime_GetHeapUsage(Arguments args) { |
| 10771 int usage = static_cast<int>(Heap::SizeOfObjects()); |
| 10772 if (!Smi::IsValid(usage)) { |
| 10773 return *Factory::NewNumberFromInt(usage); |
| 10774 } |
| 10775 return Smi::FromInt(usage); |
| 10776 } |
| 10415 #endif // ENABLE_DEBUGGER_SUPPORT | 10777 #endif // ENABLE_DEBUGGER_SUPPORT |
| 10416 | 10778 |
| 10779 |
| 10417 #ifdef ENABLE_LOGGING_AND_PROFILING | 10780 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 10418 | |
| 10419 static MaybeObject* Runtime_ProfilerResume(Arguments args) { | 10781 static MaybeObject* Runtime_ProfilerResume(Arguments args) { |
| 10420 NoHandleAllocation ha; | 10782 NoHandleAllocation ha; |
| 10421 ASSERT(args.length() == 2); | 10783 ASSERT(args.length() == 2); |
| 10422 | 10784 |
| 10423 CONVERT_CHECKED(Smi, smi_modules, args[0]); | 10785 CONVERT_CHECKED(Smi, smi_modules, args[0]); |
| 10424 CONVERT_CHECKED(Smi, smi_tag, args[1]); | 10786 CONVERT_CHECKED(Smi, smi_tag, args[1]); |
| 10425 v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value()); | 10787 v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value()); |
| 10426 return Heap::undefined_value(); | 10788 return Heap::undefined_value(); |
| 10427 } | 10789 } |
| 10428 | 10790 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10586 ASSERT(args.length() == 2); | 10948 ASSERT(args.length() == 2); |
| 10587 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + | 10949 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + |
| 10588 Smi::cast(args[1])->value()); | 10950 Smi::cast(args[1])->value()); |
| 10589 Top::PrintStack(); | 10951 Top::PrintStack(); |
| 10590 OS::Abort(); | 10952 OS::Abort(); |
| 10591 UNREACHABLE(); | 10953 UNREACHABLE(); |
| 10592 return NULL; | 10954 return NULL; |
| 10593 } | 10955 } |
| 10594 | 10956 |
| 10595 | 10957 |
| 10596 MUST_USE_RESULT static MaybeObject* CacheMiss(FixedArray* cache_obj, | |
| 10597 int index, | |
| 10598 Object* key_obj) { | |
| 10599 ASSERT(index % 2 == 0); // index of the key | |
| 10600 ASSERT(index >= JSFunctionResultCache::kEntriesIndex); | |
| 10601 ASSERT(index < cache_obj->length()); | |
| 10602 | |
| 10603 HandleScope scope; | |
| 10604 | |
| 10605 Handle<FixedArray> cache(cache_obj); | |
| 10606 Handle<Object> key(key_obj); | |
| 10607 Handle<JSFunction> factory(JSFunction::cast( | |
| 10608 cache->get(JSFunctionResultCache::kFactoryIndex))); | |
| 10609 // TODO(antonm): consider passing a receiver when constructing a cache. | |
| 10610 Handle<Object> receiver(Top::global_context()->global()); | |
| 10611 | |
| 10612 Handle<Object> value; | |
| 10613 { | |
| 10614 // This handle is nor shared, nor used later, so it's safe. | |
| 10615 Object** argv[] = { key.location() }; | |
| 10616 bool pending_exception = false; | |
| 10617 value = Execution::Call(factory, | |
| 10618 receiver, | |
| 10619 1, | |
| 10620 argv, | |
| 10621 &pending_exception); | |
| 10622 if (pending_exception) return Failure::Exception(); | |
| 10623 } | |
| 10624 | |
| 10625 cache->set(index, *key); | |
| 10626 cache->set(index + 1, *value); | |
| 10627 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(index)); | |
| 10628 | |
| 10629 return *value; | |
| 10630 } | |
| 10631 | |
| 10632 | |
| 10633 static MaybeObject* Runtime_GetFromCache(Arguments args) { | 10958 static MaybeObject* Runtime_GetFromCache(Arguments args) { |
| 10634 // This is only called from codegen, so checks might be more lax. | 10959 // This is only called from codegen, so checks might be more lax. |
| 10635 CONVERT_CHECKED(FixedArray, cache, args[0]); | 10960 CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]); |
| 10636 Object* key = args[1]; | 10961 Object* key = args[1]; |
| 10637 | 10962 |
| 10638 const int finger_index = | 10963 int finger_index = cache->finger_index(); |
| 10639 Smi::cast(cache->get(JSFunctionResultCache::kFingerIndex))->value(); | |
| 10640 | |
| 10641 Object* o = cache->get(finger_index); | 10964 Object* o = cache->get(finger_index); |
| 10642 if (o == key) { | 10965 if (o == key) { |
| 10643 // The fastest case: hit the same place again. | 10966 // The fastest case: hit the same place again. |
| 10644 return cache->get(finger_index + 1); | 10967 return cache->get(finger_index + 1); |
| 10645 } | 10968 } |
| 10646 | 10969 |
| 10647 for (int i = finger_index - 2; | 10970 for (int i = finger_index - 2; |
| 10648 i >= JSFunctionResultCache::kEntriesIndex; | 10971 i >= JSFunctionResultCache::kEntriesIndex; |
| 10649 i -= 2) { | 10972 i -= 2) { |
| 10650 o = cache->get(i); | 10973 o = cache->get(i); |
| 10651 if (o == key) { | 10974 if (o == key) { |
| 10652 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i)); | 10975 cache->set_finger_index(i); |
| 10653 return cache->get(i + 1); | 10976 return cache->get(i + 1); |
| 10654 } | 10977 } |
| 10655 } | 10978 } |
| 10656 | 10979 |
| 10657 const int size = | 10980 int size = cache->size(); |
| 10658 Smi::cast(cache->get(JSFunctionResultCache::kCacheSizeIndex))->value(); | |
| 10659 ASSERT(size <= cache->length()); | 10981 ASSERT(size <= cache->length()); |
| 10660 | 10982 |
| 10661 for (int i = size - 2; i > finger_index; i -= 2) { | 10983 for (int i = size - 2; i > finger_index; i -= 2) { |
| 10662 o = cache->get(i); | 10984 o = cache->get(i); |
| 10663 if (o == key) { | 10985 if (o == key) { |
| 10664 cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i)); | 10986 cache->set_finger_index(i); |
| 10665 return cache->get(i + 1); | 10987 return cache->get(i + 1); |
| 10666 } | 10988 } |
| 10667 } | 10989 } |
| 10668 | 10990 |
| 10669 // Cache miss. If we have spare room, put new data into it, otherwise | 10991 // There is no value in the cache. Invoke the function and cache result. |
| 10670 // evict post finger entry which must be least recently used. | 10992 HandleScope scope; |
| 10671 if (size < cache->length()) { | 10993 |
| 10672 cache->set(JSFunctionResultCache::kCacheSizeIndex, Smi::FromInt(size + 2)); | 10994 Handle<JSFunctionResultCache> cache_handle(cache); |
| 10673 return CacheMiss(cache, size, key); | 10995 Handle<Object> key_handle(key); |
| 10996 Handle<Object> value; |
| 10997 { |
| 10998 Handle<JSFunction> factory(JSFunction::cast( |
| 10999 cache_handle->get(JSFunctionResultCache::kFactoryIndex))); |
| 11000 // TODO(antonm): consider passing a receiver when constructing a cache. |
| 11001 Handle<Object> receiver(Top::global_context()->global()); |
| 11002 // This handle is nor shared, nor used later, so it's safe. |
| 11003 Object** argv[] = { key_handle.location() }; |
| 11004 bool pending_exception = false; |
| 11005 value = Execution::Call(factory, |
| 11006 receiver, |
| 11007 1, |
| 11008 argv, |
| 11009 &pending_exception); |
| 11010 if (pending_exception) return Failure::Exception(); |
| 11011 } |
| 11012 |
| 11013 #ifdef DEBUG |
| 11014 cache_handle->JSFunctionResultCacheVerify(); |
| 11015 #endif |
| 11016 |
| 11017 // Function invocation may have cleared the cache. Reread all the data. |
| 11018 finger_index = cache_handle->finger_index(); |
| 11019 size = cache_handle->size(); |
| 11020 |
| 11021 // If we have spare room, put new data into it, otherwise evict post finger |
| 11022 // entry which is likely to be the least recently used. |
| 11023 int index = -1; |
| 11024 if (size < cache_handle->length()) { |
| 11025 cache_handle->set_size(size + JSFunctionResultCache::kEntrySize); |
| 11026 index = size; |
| 10674 } else { | 11027 } else { |
| 10675 int target_index = finger_index + JSFunctionResultCache::kEntrySize; | 11028 index = finger_index + JSFunctionResultCache::kEntrySize; |
| 10676 if (target_index == cache->length()) { | 11029 if (index == cache_handle->length()) { |
| 10677 target_index = JSFunctionResultCache::kEntriesIndex; | 11030 index = JSFunctionResultCache::kEntriesIndex; |
| 10678 } | 11031 } |
| 10679 return CacheMiss(cache, target_index, key); | |
| 10680 } | 11032 } |
| 11033 |
| 11034 ASSERT(index % 2 == 0); |
| 11035 ASSERT(index >= JSFunctionResultCache::kEntriesIndex); |
| 11036 ASSERT(index < cache_handle->length()); |
| 11037 |
| 11038 cache_handle->set(index, *key_handle); |
| 11039 cache_handle->set(index + 1, *value); |
| 11040 cache_handle->set_finger_index(index); |
| 11041 |
| 11042 #ifdef DEBUG |
| 11043 cache_handle->JSFunctionResultCacheVerify(); |
| 11044 #endif |
| 11045 |
| 11046 return *value; |
| 10681 } | 11047 } |
| 10682 | 11048 |
| 11049 |
| 11050 static MaybeObject* Runtime_NewMessageObject(Arguments args) { |
| 11051 HandleScope scope; |
| 11052 CONVERT_ARG_CHECKED(String, type, 0); |
| 11053 CONVERT_ARG_CHECKED(JSArray, arguments, 1); |
| 11054 return *Factory::NewJSMessageObject(type, |
| 11055 arguments, |
| 11056 0, |
| 11057 0, |
| 11058 Factory::undefined_value(), |
| 11059 Factory::undefined_value(), |
| 11060 Factory::undefined_value()); |
| 11061 } |
| 11062 |
| 11063 |
| 11064 static MaybeObject* Runtime_MessageGetType(Arguments args) { |
| 11065 CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| 11066 return message->type(); |
| 11067 } |
| 11068 |
| 11069 |
| 11070 static MaybeObject* Runtime_MessageGetArguments(Arguments args) { |
| 11071 CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| 11072 return message->arguments(); |
| 11073 } |
| 11074 |
| 11075 |
| 11076 static MaybeObject* Runtime_MessageGetStartPosition(Arguments args) { |
| 11077 CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| 11078 return Smi::FromInt(message->start_position()); |
| 11079 } |
| 11080 |
| 11081 |
| 11082 static MaybeObject* Runtime_MessageGetScript(Arguments args) { |
| 11083 CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| 11084 return message->script(); |
| 11085 } |
| 11086 |
| 11087 |
| 10683 #ifdef DEBUG | 11088 #ifdef DEBUG |
| 10684 // ListNatives is ONLY used by the fuzz-natives.js in debug mode | 11089 // ListNatives is ONLY used by the fuzz-natives.js in debug mode |
| 10685 // Exclude the code in release mode. | 11090 // Exclude the code in release mode. |
| 10686 static MaybeObject* Runtime_ListNatives(Arguments args) { | 11091 static MaybeObject* Runtime_ListNatives(Arguments args) { |
| 10687 ASSERT(args.length() == 0); | 11092 ASSERT(args.length() == 0); |
| 10688 HandleScope scope; | 11093 HandleScope scope; |
| 10689 Handle<JSArray> result = Factory::NewJSArray(0); | 11094 Handle<JSArray> result = Factory::NewJSArray(0); |
| 10690 int index = 0; | 11095 int index = 0; |
| 10691 bool inline_runtime_functions = false; | 11096 bool inline_runtime_functions = false; |
| 10692 #define ADD_ENTRY(Name, argc, ressize) \ | 11097 #define ADD_ENTRY(Name, argc, ressize) \ |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10802 } else { | 11207 } else { |
| 10803 // Handle last resort GC and make sure to allow future allocations | 11208 // Handle last resort GC and make sure to allow future allocations |
| 10804 // to grow the heap without causing GCs (if possible). | 11209 // to grow the heap without causing GCs (if possible). |
| 10805 Counters::gc_last_resort_from_js.Increment(); | 11210 Counters::gc_last_resort_from_js.Increment(); |
| 10806 Heap::CollectAllGarbage(false); | 11211 Heap::CollectAllGarbage(false); |
| 10807 } | 11212 } |
| 10808 } | 11213 } |
| 10809 | 11214 |
| 10810 | 11215 |
| 10811 } } // namespace v8::internal | 11216 } } // namespace v8::internal |
| OLD | NEW |