| 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 2660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); | 2671 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); |
| 2672 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2672 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2673 return raw_result; | 2673 return raw_result; |
| 2674 } | 2674 } |
| 2675 | 2675 |
| 2676 | 2676 |
| 2677 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, | 2677 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, |
| 2678 DeleteMode mode) { | 2678 DeleteMode mode) { |
| 2679 Heap* heap = GetHeap(); | 2679 Heap* heap = GetHeap(); |
| 2680 ASSERT(!HasExternalArrayElements()); | 2680 ASSERT(!HasExternalArrayElements()); |
| 2681 // We don't have to handle strict mode deletion of non-configurable |
| 2682 // properties. |
| 2683 ASSERT(mode != STRICT_DELETION); |
| 2681 switch (GetElementsKind()) { | 2684 switch (GetElementsKind()) { |
| 2682 case FAST_ELEMENTS: { | 2685 case FAST_ELEMENTS: { |
| 2683 Object* obj; | 2686 FixedArray* elements = FixedArray::cast(this->elements()); |
| 2684 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 2687 return DeleteFromElements(elements, FAST_ELEMENTS, index, mode); |
| 2685 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 2686 } | |
| 2687 uint32_t length = IsJSArray() ? | |
| 2688 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | |
| 2689 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | |
| 2690 if (index < length) { | |
| 2691 FixedArray::cast(elements())->set_the_hole(index); | |
| 2692 } | |
| 2693 break; | |
| 2694 } | 2688 } |
| 2695 case DICTIONARY_ELEMENTS: { | 2689 case DICTIONARY_ELEMENTS: { |
| 2696 NumberDictionary* dictionary = element_dictionary(); | 2690 NumberDictionary* dictionary = element_dictionary(); |
| 2697 int entry = dictionary->FindEntry(index); | 2691 int entry = dictionary->FindEntry(index); |
| 2698 if (entry != NumberDictionary::kNotFound) { | 2692 if (entry != NumberDictionary::kNotFound) { |
| 2699 return dictionary->DeleteProperty(entry, mode); | 2693 return dictionary->DeleteProperty(entry, mode); |
| 2700 } | 2694 } |
| 2701 break; | 2695 break; |
| 2702 } | 2696 } |
| 2703 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2697 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2745 ASSERT(result->IsBoolean()); | 2739 ASSERT(result->IsBoolean()); |
| 2746 return *v8::Utils::OpenHandle(*result); | 2740 return *v8::Utils::OpenHandle(*result); |
| 2747 } | 2741 } |
| 2748 MaybeObject* raw_result = | 2742 MaybeObject* raw_result = |
| 2749 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); | 2743 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); |
| 2750 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2744 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2751 return raw_result; | 2745 return raw_result; |
| 2752 } | 2746 } |
| 2753 | 2747 |
| 2754 | 2748 |
| 2755 void JSObject::DeleteFromFastElements(FixedArray* elements, uint32_t index) { | 2749 MaybeObject* JSObject::DeleteFromElements(FixedArray* elements, |
| 2756 ASSERT(elements->map() != elements->GetHeap()->fixed_cow_array_map()); | 2750 ElementsKind kind, |
| 2757 int length = IsJSArray() | 2751 uint32_t index, |
| 2758 ? Smi::cast(JSArray::cast(this)->length())->value() | 2752 DeleteMode mode) { |
| 2759 : elements->length(); | 2753 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); |
| 2760 if (index < static_cast<uint32_t>(length)) { | |
| 2761 elements->set_the_hole(index); | |
| 2762 } | |
| 2763 } | |
| 2764 | |
| 2765 | |
| 2766 MaybeObject* JSObject::DeleteFromDictionaryElements(NumberDictionary* elements, | |
| 2767 uint32_t index, | |
| 2768 DeleteMode mode) { | |
| 2769 Isolate* isolate = GetIsolate(); | 2754 Isolate* isolate = GetIsolate(); |
| 2770 int entry = elements->FindEntry(index); | 2755 if (kind == FAST_ELEMENTS) { |
| 2771 if (entry != NumberDictionary::kNotFound) { | 2756 Object* object; |
| 2772 Object* result = elements->DeleteProperty(entry, mode); | 2757 MaybeObject* maybe_object = EnsureWritableFastElements(); |
| 2773 if (mode == STRICT_DELETION && result == isolate->heap()->false_value()) { | 2758 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 2774 // In strict mode, attempting to delete a non-configurable property | 2759 int length = IsJSArray() |
| 2775 // throws an exception. | 2760 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2776 HandleScope scope(isolate); | 2761 : elements->length(); |
| 2777 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); | 2762 if (index < static_cast<uint32_t>(length)) { |
| 2778 Handle<Object> args[2] = { name, Handle<Object>(this) }; | 2763 elements->set_the_hole(index); |
| 2779 Handle<Object> error = | 2764 } |
| 2780 isolate->factory()->NewTypeError("strict_delete_property", | 2765 } else { |
| 2781 HandleVector(args, 2)); | 2766 NumberDictionary* dictionary = NumberDictionary::cast(elements); |
| 2782 return isolate->Throw(*error); | 2767 int entry = dictionary->FindEntry(index); |
| 2768 if (entry != NumberDictionary::kNotFound) { |
| 2769 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2770 if (mode == STRICT_DELETION && result == isolate->heap()->false_value()) { |
| 2771 // In strict mode, attempting to delete a non-configurable property |
| 2772 // throws an exception. |
| 2773 HandleScope scope(isolate); |
| 2774 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); |
| 2775 Handle<Object> args[2] = { name, Handle<Object>(this) }; |
| 2776 Handle<Object> error = |
| 2777 isolate->factory()->NewTypeError("strict_delete_property", |
| 2778 HandleVector(args, 2)); |
| 2779 return isolate->Throw(*error); |
| 2780 } |
| 2783 } | 2781 } |
| 2784 } | 2782 } |
| 2785 return isolate->heap()->true_value(); | 2783 return isolate->heap()->true_value(); |
| 2786 } | 2784 } |
| 2787 | 2785 |
| 2788 | 2786 |
| 2789 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { | 2787 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
| 2790 Isolate* isolate = GetIsolate(); | 2788 Isolate* isolate = GetIsolate(); |
| 2791 // Check access rights if needed. | 2789 // Check access rights if needed. |
| 2792 if (IsAccessCheckNeeded() && | 2790 if (IsAccessCheckNeeded() && |
| 2793 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { | 2791 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { |
| 2794 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 2792 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 2795 return isolate->heap()->false_value(); | 2793 return isolate->heap()->false_value(); |
| 2796 } | 2794 } |
| 2797 | 2795 |
| 2798 if (IsJSGlobalProxy()) { | 2796 if (IsJSGlobalProxy()) { |
| 2799 Object* proto = GetPrototype(); | 2797 Object* proto = GetPrototype(); |
| 2800 if (proto->IsNull()) return isolate->heap()->false_value(); | 2798 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 2801 ASSERT(proto->IsJSGlobalObject()); | 2799 ASSERT(proto->IsJSGlobalObject()); |
| 2802 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); | 2800 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); |
| 2803 } | 2801 } |
| 2804 | 2802 |
| 2805 if (HasIndexedInterceptor()) { | 2803 if (HasIndexedInterceptor()) { |
| 2806 // Skip interceptor if forcing deletion. | 2804 // Skip interceptor if forcing deletion. |
| 2807 if (mode == FORCE_DELETION) { | 2805 return (mode == FORCE_DELETION) |
| 2808 return DeleteElementPostInterceptor(index, mode); | 2806 ? DeleteElementPostInterceptor(index, FORCE_DELETION) |
| 2809 } | 2807 : DeleteElementWithInterceptor(index); |
| 2810 return DeleteElementWithInterceptor(index); | |
| 2811 } | 2808 } |
| 2812 | 2809 |
| 2813 switch (GetElementsKind()) { | 2810 ElementsKind kind = GetElementsKind(); |
| 2814 case FAST_ELEMENTS: { | 2811 switch (kind) { |
| 2815 Object* obj; | 2812 case FAST_ELEMENTS: |
| 2816 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 2813 case DICTIONARY_ELEMENTS: { |
| 2817 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2814 FixedArray* elements = FixedArray::cast(this->elements()); |
| 2818 } | 2815 return DeleteFromElements(elements, kind, index, mode); |
| 2819 DeleteFromFastElements(FixedArray::cast(elements()), index); | |
| 2820 break; | |
| 2821 } | 2816 } |
| 2822 | 2817 |
| 2823 case EXTERNAL_PIXEL_ELEMENTS: | 2818 case EXTERNAL_PIXEL_ELEMENTS: |
| 2824 case EXTERNAL_BYTE_ELEMENTS: | 2819 case EXTERNAL_BYTE_ELEMENTS: |
| 2825 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2820 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 2826 case EXTERNAL_SHORT_ELEMENTS: | 2821 case EXTERNAL_SHORT_ELEMENTS: |
| 2827 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2822 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 2828 case EXTERNAL_INT_ELEMENTS: | 2823 case EXTERNAL_INT_ELEMENTS: |
| 2829 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2824 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2830 case EXTERNAL_FLOAT_ELEMENTS: | 2825 case EXTERNAL_FLOAT_ELEMENTS: |
| 2831 // Pixel and external array elements cannot be deleted. Just | 2826 // Pixel and external array elements cannot be deleted. Just |
| 2832 // silently ignore here. | 2827 // silently ignore here. |
| 2833 break; | 2828 break; |
| 2834 | 2829 |
| 2835 case DICTIONARY_ELEMENTS: | |
| 2836 return DeleteFromDictionaryElements(element_dictionary(), index, mode); | |
| 2837 | |
| 2838 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 2830 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 2839 FixedArray* parameter_map = FixedArray::cast(elements()); | 2831 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 2840 uint32_t length = parameter_map->length(); | 2832 uint32_t length = parameter_map->length(); |
| 2841 Object* probe = | 2833 Object* probe = |
| 2842 (index + 2) < length ? parameter_map->get(index + 2) : NULL; | 2834 (index + 2) < length ? parameter_map->get(index + 2) : NULL; |
| 2843 if (probe != NULL && !probe->IsTheHole()) { | 2835 if (probe == NULL || probe->IsTheHole()) { |
| 2844 // TODO(kmillikin): We could check if this was the last aliased | |
| 2845 // parameter, and revert to normal elements in that case. That | |
| 2846 // would enable GC of the context. | |
| 2847 parameter_map->set_the_hole(index + 2); | |
| 2848 } else { | |
| 2849 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 2836 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 2850 if (arguments->IsDictionary()) { | 2837 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
| 2851 NumberDictionary* dictionary = NumberDictionary::cast(arguments); | 2838 return DeleteFromElements(arguments, kind, index, mode); |
| 2852 return DeleteFromDictionaryElements(dictionary, index, mode); | |
| 2853 } else { | |
| 2854 DeleteFromFastElements(arguments, index); | |
| 2855 } | |
| 2856 } | 2839 } |
| 2840 // TODO(kmillikin): We could check if this was the last aliased |
| 2841 // parameter, and revert to normal elements in that case. That |
| 2842 // would enable GC of the context. |
| 2843 parameter_map->set_the_hole(index + 2); |
| 2857 break; | 2844 break; |
| 2858 } | 2845 } |
| 2859 } | 2846 } |
| 2860 return isolate->heap()->true_value(); | 2847 return isolate->heap()->true_value(); |
| 2861 } | 2848 } |
| 2862 | 2849 |
| 2863 | 2850 |
| 2864 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 2851 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 2865 Isolate* isolate = GetIsolate(); | 2852 Isolate* isolate = GetIsolate(); |
| 2866 // ECMA-262, 3rd, 8.6.2.5 | 2853 // ECMA-262, 3rd, 8.6.2.5 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2911 { MaybeObject* maybe_obj = | 2898 { MaybeObject* maybe_obj = |
| 2912 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2899 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2913 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2900 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2914 } | 2901 } |
| 2915 // Make sure the properties are normalized before removing the entry. | 2902 // Make sure the properties are normalized before removing the entry. |
| 2916 return DeleteNormalizedProperty(name, mode); | 2903 return DeleteNormalizedProperty(name, mode); |
| 2917 } | 2904 } |
| 2918 } | 2905 } |
| 2919 | 2906 |
| 2920 | 2907 |
| 2908 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 2909 ElementsKind kind, |
| 2910 Object* object) { |
| 2911 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); |
| 2912 if (kind == FAST_ELEMENTS) { |
| 2913 int length = IsJSArray() |
| 2914 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2915 : elements->length(); |
| 2916 for (int i = 0; i < length; ++i) { |
| 2917 Object* element = elements->get(i); |
| 2918 if (!element->IsTheHole() && element == object) return true; |
| 2919 } |
| 2920 } else { |
| 2921 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
| 2922 if (!key->IsUndefined()) return true; |
| 2923 } |
| 2924 return false; |
| 2925 } |
| 2926 |
| 2927 |
| 2921 // Check whether this object references another object. | 2928 // Check whether this object references another object. |
| 2922 bool JSObject::ReferencesObject(Object* obj) { | 2929 bool JSObject::ReferencesObject(Object* obj) { |
| 2923 Heap* heap = GetHeap(); | 2930 Heap* heap = GetHeap(); |
| 2924 AssertNoAllocation no_alloc; | 2931 AssertNoAllocation no_alloc; |
| 2925 | 2932 |
| 2926 // Is the object the constructor for this object? | 2933 // Is the object the constructor for this object? |
| 2927 if (map()->constructor() == obj) { | 2934 if (map()->constructor() == obj) { |
| 2928 return true; | 2935 return true; |
| 2929 } | 2936 } |
| 2930 | 2937 |
| 2931 // Is the object the prototype for this object? | 2938 // Is the object the prototype for this object? |
| 2932 if (map()->prototype() == obj) { | 2939 if (map()->prototype() == obj) { |
| 2933 return true; | 2940 return true; |
| 2934 } | 2941 } |
| 2935 | 2942 |
| 2936 // Check if the object is among the named properties. | 2943 // Check if the object is among the named properties. |
| 2937 Object* key = SlowReverseLookup(obj); | 2944 Object* key = SlowReverseLookup(obj); |
| 2938 if (!key->IsUndefined()) { | 2945 if (!key->IsUndefined()) { |
| 2939 return true; | 2946 return true; |
| 2940 } | 2947 } |
| 2941 | 2948 |
| 2942 // Check if the object is among the indexed properties. | 2949 // Check if the object is among the indexed properties. |
| 2943 switch (GetElementsKind()) { | 2950 ElementsKind kind = GetElementsKind(); |
| 2951 switch (kind) { |
| 2944 case EXTERNAL_PIXEL_ELEMENTS: | 2952 case EXTERNAL_PIXEL_ELEMENTS: |
| 2945 case EXTERNAL_BYTE_ELEMENTS: | 2953 case EXTERNAL_BYTE_ELEMENTS: |
| 2946 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2954 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 2947 case EXTERNAL_SHORT_ELEMENTS: | 2955 case EXTERNAL_SHORT_ELEMENTS: |
| 2948 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2956 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 2949 case EXTERNAL_INT_ELEMENTS: | 2957 case EXTERNAL_INT_ELEMENTS: |
| 2950 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2958 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2951 case EXTERNAL_FLOAT_ELEMENTS: | 2959 case EXTERNAL_FLOAT_ELEMENTS: |
| 2952 // Raw pixels and external arrays do not reference other | 2960 // Raw pixels and external arrays do not reference other |
| 2953 // objects. | 2961 // objects. |
| 2954 break; | 2962 break; |
| 2955 case FAST_ELEMENTS: { | 2963 case FAST_ELEMENTS: |
| 2956 int length = IsJSArray() ? | |
| 2957 Smi::cast(JSArray::cast(this)->length())->value() : | |
| 2958 FixedArray::cast(elements())->length(); | |
| 2959 for (int i = 0; i < length; i++) { | |
| 2960 Object* element = FixedArray::cast(elements())->get(i); | |
| 2961 if (!element->IsTheHole() && element == obj) { | |
| 2962 return true; | |
| 2963 } | |
| 2964 } | |
| 2965 break; | |
| 2966 } | |
| 2967 case DICTIONARY_ELEMENTS: { | 2964 case DICTIONARY_ELEMENTS: { |
| 2968 key = element_dictionary()->SlowReverseLookup(obj); | 2965 FixedArray* elements = FixedArray::cast(this->elements()); |
| 2969 if (!key->IsUndefined()) { | 2966 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 2970 return true; | |
| 2971 } | |
| 2972 break; | 2967 break; |
| 2973 } | 2968 } |
| 2974 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 2969 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 2975 FixedArray* parameter_map = FixedArray::cast(elements()); | 2970 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 2976 // Check the mapped parameters. | 2971 // Check the mapped parameters. |
| 2977 int length = parameter_map->length(); | 2972 int length = parameter_map->length(); |
| 2978 for (int i = 2; i < length; ++i) { | 2973 for (int i = 2; i < length; ++i) { |
| 2979 Object* value = parameter_map->get(i); | 2974 Object* value = parameter_map->get(i); |
| 2980 if (!value->IsTheHole() && value == obj) return true; | 2975 if (!value->IsTheHole() && value == obj) return true; |
| 2981 } | 2976 } |
| 2982 // Check the arguments. | 2977 // Check the arguments. |
| 2983 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 2978 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 2984 if (arguments->IsDictionary()) { | 2979 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
| 2985 NumberDictionary* dictionary = NumberDictionary::cast(arguments); | 2980 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
| 2986 key = dictionary->SlowReverseLookup(obj); | |
| 2987 if (key != heap->undefined_value()) return true; | |
| 2988 } else { | |
| 2989 int count = arguments->length(); | |
| 2990 for (int i = 0; i < count; ++i) { | |
| 2991 Object* value = arguments->get(i); | |
| 2992 if (!value->IsTheHole() && value == obj) return true; | |
| 2993 } | |
| 2994 } | |
| 2995 break; | 2981 break; |
| 2996 } | 2982 } |
| 2997 } | 2983 } |
| 2998 | 2984 |
| 2999 // For functions check the context. | 2985 // For functions check the context. |
| 3000 if (IsJSFunction()) { | 2986 if (IsJSFunction()) { |
| 3001 // Get the constructor function for arguments array. | 2987 // Get the constructor function for arguments array. |
| 3002 JSObject* arguments_boilerplate = | 2988 JSObject* arguments_boilerplate = |
| 3003 heap->isolate()->context()->global_context()-> | 2989 heap->isolate()->context()->global_context()-> |
| 3004 arguments_boilerplate(); | 2990 arguments_boilerplate(); |
| (...skipping 4127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7132 } | 7118 } |
| 7133 case NON_STRICT_ARGUMENTS_ELEMENTS: | 7119 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 7134 UNIMPLEMENTED(); | 7120 UNIMPLEMENTED(); |
| 7135 break; | 7121 break; |
| 7136 } | 7122 } |
| 7137 | 7123 |
| 7138 return UNDEFINED_ELEMENT; | 7124 return UNDEFINED_ELEMENT; |
| 7139 } | 7125 } |
| 7140 | 7126 |
| 7141 | 7127 |
| 7128 bool JSObject::HasElementInElements(FixedArray* elements, |
| 7129 ElementsKind kind, |
| 7130 uint32_t index) { |
| 7131 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); |
| 7132 if (kind == FAST_ELEMENTS) { |
| 7133 int length = IsJSArray() |
| 7134 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 7135 : elements->length(); |
| 7136 if (index < static_cast<uint32_t>(length) && |
| 7137 !elements->get(index)->IsTheHole()) { |
| 7138 return true; |
| 7139 } |
| 7140 } else { |
| 7141 if (NumberDictionary::cast(elements)->FindEntry(index) != |
| 7142 NumberDictionary::kNotFound) { |
| 7143 return true; |
| 7144 } |
| 7145 } |
| 7146 return false; |
| 7147 } |
| 7148 |
| 7149 |
| 7142 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 7150 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| 7143 Heap* heap = GetHeap(); | 7151 Heap* heap = GetHeap(); |
| 7144 | 7152 |
| 7145 // Check access rights if needed. | 7153 // Check access rights if needed. |
| 7146 if (IsAccessCheckNeeded() && | 7154 if (IsAccessCheckNeeded() && |
| 7147 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 7155 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 7148 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7156 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7149 return false; | 7157 return false; |
| 7150 } | 7158 } |
| 7151 | 7159 |
| 7152 // Check for lookup interceptor | 7160 // Check for lookup interceptor |
| 7153 if (HasIndexedInterceptor()) { | 7161 if (HasIndexedInterceptor()) { |
| 7154 return HasElementWithInterceptor(receiver, index); | 7162 return HasElementWithInterceptor(receiver, index); |
| 7155 } | 7163 } |
| 7156 | 7164 |
| 7157 switch (GetElementsKind()) { | 7165 ElementsKind kind = GetElementsKind(); |
| 7158 case FAST_ELEMENTS: { | 7166 switch (kind) { |
| 7159 uint32_t length = IsJSArray() ? | 7167 case FAST_ELEMENTS: |
| 7160 static_cast<uint32_t> | 7168 case DICTIONARY_ELEMENTS: { |
| 7161 (Smi::cast(JSArray::cast(this)->length())->value()) : | 7169 FixedArray* elements = FixedArray::cast(this->elements()); |
| 7162 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 7170 if (HasElementInElements(elements, kind, index)) return true; |
| 7163 if ((index < length) && | |
| 7164 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | |
| 7165 break; | 7171 break; |
| 7166 } | 7172 } |
| 7167 case EXTERNAL_PIXEL_ELEMENTS: { | 7173 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7168 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 7174 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7169 if (index < static_cast<uint32_t>(pixels->length())) { | 7175 if (index < static_cast<uint32_t>(pixels->length())) { |
| 7170 return true; | 7176 return true; |
| 7171 } | 7177 } |
| 7172 break; | 7178 break; |
| 7173 } | 7179 } |
| 7174 case EXTERNAL_BYTE_ELEMENTS: | 7180 case EXTERNAL_BYTE_ELEMENTS: |
| 7175 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7181 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7176 case EXTERNAL_SHORT_ELEMENTS: | 7182 case EXTERNAL_SHORT_ELEMENTS: |
| 7177 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7183 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7178 case EXTERNAL_INT_ELEMENTS: | 7184 case EXTERNAL_INT_ELEMENTS: |
| 7179 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7185 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7180 case EXTERNAL_FLOAT_ELEMENTS: { | 7186 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7181 ExternalArray* array = ExternalArray::cast(elements()); | 7187 ExternalArray* array = ExternalArray::cast(elements()); |
| 7182 if (index < static_cast<uint32_t>(array->length())) { | 7188 if (index < static_cast<uint32_t>(array->length())) { |
| 7183 return true; | 7189 return true; |
| 7184 } | 7190 } |
| 7185 break; | 7191 break; |
| 7186 } | 7192 } |
| 7187 case DICTIONARY_ELEMENTS: { | |
| 7188 if (element_dictionary()->FindEntry(index) | |
| 7189 != NumberDictionary::kNotFound) { | |
| 7190 return true; | |
| 7191 } | |
| 7192 break; | |
| 7193 } | |
| 7194 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 7193 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 7195 FixedArray* parameter_map = FixedArray::cast(elements()); | 7194 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 7196 uint32_t length = parameter_map->length(); | 7195 uint32_t length = parameter_map->length(); |
| 7197 Object* probe = | 7196 Object* probe = |
| 7198 (index + 2 < length) ? parameter_map->get(index + 2) : NULL; | 7197 (index + 2 < length) ? parameter_map->get(index + 2) : NULL; |
| 7199 if (probe != NULL && !probe->IsTheHole()) return true; | 7198 if (probe != NULL && !probe->IsTheHole()) return true; |
| 7200 | 7199 |
| 7201 // Not a mapped parameter, check the arguments. | 7200 // Not a mapped parameter, check the arguments. |
| 7202 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 7201 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 7203 if (arguments->IsDictionary()) { | 7202 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
| 7204 if (NumberDictionary::cast(arguments)->FindEntry(index) != | 7203 if (HasElementInElements(arguments, kind, index)) return true; |
| 7205 NumberDictionary::kNotFound) { | |
| 7206 return true; | |
| 7207 } | |
| 7208 } else if (index < static_cast<uint32_t>(arguments->length()) && | |
| 7209 !arguments->get(index)->IsTheHole()) { | |
| 7210 return true; | |
| 7211 } | |
| 7212 break; | 7204 break; |
| 7213 } | 7205 } |
| 7214 } | 7206 } |
| 7215 | 7207 |
| 7216 // Handle [] on String objects. | 7208 // Handle [] on String objects. |
| 7217 if (this->IsStringObjectWithCharacterAt(index)) return true; | 7209 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 7218 | 7210 |
| 7219 Object* pt = GetPrototype(); | 7211 Object* pt = GetPrototype(); |
| 7220 if (pt->IsNull()) return false; | 7212 if (pt->IsNull()) return false; |
| 7221 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 7213 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| (...skipping 3211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10433 if (break_point_objects()->IsUndefined()) return 0; | 10425 if (break_point_objects()->IsUndefined()) return 0; |
| 10434 // Single beak point. | 10426 // Single beak point. |
| 10435 if (!break_point_objects()->IsFixedArray()) return 1; | 10427 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10436 // Multiple break points. | 10428 // Multiple break points. |
| 10437 return FixedArray::cast(break_point_objects())->length(); | 10429 return FixedArray::cast(break_point_objects())->length(); |
| 10438 } | 10430 } |
| 10439 #endif | 10431 #endif |
| 10440 | 10432 |
| 10441 | 10433 |
| 10442 } } // namespace v8::internal | 10434 } } // namespace v8::internal |
| OLD | NEW |