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 |