Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/objects.cc

Issue 7187007: Merge arguments branch to bleeding edge (second try). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Undelete external-array test. Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 1879 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 1890 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
1891 uint32_t index, 1891 uint32_t index,
1892 Object* value, 1892 Object* value,
1893 bool* found, 1893 bool* found,
1894 StrictModeFlag strict_mode) { 1894 StrictModeFlag strict_mode) {
1895 Heap* heap = GetHeap(); 1895 Heap* heap = GetHeap();
1896 for (Object* pt = GetPrototype(); 1896 for (Object* pt = GetPrototype();
1897 pt != heap->null_value(); 1897 pt != heap->null_value();
1898 pt = pt->GetPrototype()) { 1898 pt = pt->GetPrototype()) {
1899 if (!JSObject::cast(pt)->HasDictionaryElements()) { 1899 if (!JSObject::cast(pt)->HasDictionaryElements()) {
1900 continue; 1900 continue;
1901 } 1901 }
1902 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); 1902 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1903 int entry = dictionary->FindEntry(index); 1903 int entry = dictionary->FindEntry(index);
1904 if (entry != NumberDictionary::kNotFound) { 1904 if (entry != NumberDictionary::kNotFound) {
1905 PropertyDetails details = dictionary->DetailsAt(entry); 1905 PropertyDetails details = dictionary->DetailsAt(entry);
1906 if (details.type() == CALLBACKS) { 1906 if (details.type() == CALLBACKS) {
1907 *found = true; 1907 *found = true;
1908 return SetElementWithCallback(dictionary->ValueAt(entry), 1908 return SetElementWithCallback(dictionary->ValueAt(entry),
1909 index, 1909 index,
1910 value, 1910 value,
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { 2797 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
2798 if (HasFastProperties()) return this; 2798 if (HasFastProperties()) return this;
2799 ASSERT(!IsGlobalObject()); 2799 ASSERT(!IsGlobalObject());
2800 return property_dictionary()-> 2800 return property_dictionary()->
2801 TransformPropertiesToFastFor(this, unused_property_fields); 2801 TransformPropertiesToFastFor(this, unused_property_fields);
2802 } 2802 }
2803 2803
2804 2804
2805 MaybeObject* JSObject::NormalizeElements() { 2805 MaybeObject* JSObject::NormalizeElements() {
2806 ASSERT(!HasExternalArrayElements()); 2806 ASSERT(!HasExternalArrayElements());
2807 if (HasDictionaryElements()) return this;
2808 Map* old_map = map();
2809 ASSERT(old_map->has_fast_elements() || old_map->has_fast_double_elements());
2810 2807
2811 Object* obj; 2808 // Find the backing store.
2812 { MaybeObject* maybe_obj = old_map->GetSlowElementsMap(); 2809 FixedArray* array = FixedArray::cast(elements());
2813 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2810 Map* old_map = array->map();
2811 bool is_arguments =
2812 (old_map == old_map->heap()->non_strict_arguments_elements_map());
2813 if (is_arguments) {
2814 array = FixedArray::cast(array->get(1));
2814 } 2815 }
2815 Map* new_map = Map::cast(obj); 2816 if (array->IsDictionary()) return array;
2816 2817
2817 // Get number of entries. 2818 ASSERT(HasFastElements() || HasFastArgumentsElements());
2818 FixedArrayBase* array = FixedArrayBase::cast(elements()); 2819 // Compute the effective length and allocate a new backing store.
2820 int length = IsJSArray()
2821 ? Smi::cast(JSArray::cast(this)->length())->value()
2822 : array->length();
2823 NumberDictionary* dictionary = NULL;
2824 { Object* object;
2825 MaybeObject* maybe = NumberDictionary::Allocate(length);
2826 if (!maybe->ToObject(&object)) return maybe;
2827 dictionary = NumberDictionary::cast(object);
2828 }
2819 2829
2820 // Compute the effective length. 2830 // Copy the elements to the new backing store.
2821 int length = IsJSArray() ?
2822 Smi::cast(JSArray::cast(this)->length())->value() :
2823 array->length();
2824 { MaybeObject* maybe_obj = NumberDictionary::Allocate(length);
2825 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2826 }
2827 bool has_double_elements = old_map->has_fast_double_elements(); 2831 bool has_double_elements = old_map->has_fast_double_elements();
2828 NumberDictionary* dictionary = NumberDictionary::cast(obj);
2829 // Copy entries.
2830 for (int i = 0; i < length; i++) { 2832 for (int i = 0; i < length; i++) {
2831 Object* value = NULL; 2833 Object* value = NULL;
2832 if (has_double_elements) { 2834 if (has_double_elements) {
2833 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); 2835 FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
2834 if (double_array->is_the_hole(i)) { 2836 if (double_array->is_the_hole(i)) {
2835 value = GetIsolate()->heap()->the_hole_value(); 2837 value = GetIsolate()->heap()->the_hole_value();
2836 } else { 2838 } else {
2837 // Objects must be allocated in the old object space, since the 2839 // Objects must be allocated in the old object space, since the
2838 // overall number of HeapNumbers needed for the conversion might 2840 // overall number of HeapNumbers needed for the conversion might
2839 // exceed the capacity of new space, and we would fail repeatedly 2841 // exceed the capacity of new space, and we would fail repeatedly
2840 // trying to convert the FixedDoubleArray. 2842 // trying to convert the FixedDoubleArray.
2841 MaybeObject* maybe_value_object = 2843 MaybeObject* maybe_value_object =
2842 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); 2844 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED);
2843 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 2845 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
2844 } 2846 }
2845 } else { 2847 } else {
2846 ASSERT(old_map->has_fast_elements()); 2848 ASSERT(old_map->has_fast_elements());
2847 FixedArray* fixed_array = FixedArray::cast(array); 2849 value = array->get(i);
2848 value = fixed_array->get(i);
2849 } 2850 }
2850 PropertyDetails details = PropertyDetails(NONE, NORMAL); 2851 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2851 if (!value->IsTheHole()) { 2852 if (!value->IsTheHole()) {
2852 Object* result; 2853 Object* result;
2853 MaybeObject* maybe_result = 2854 MaybeObject* maybe_result =
2854 dictionary->AddNumberEntry(i, value, details); 2855 dictionary->AddNumberEntry(i, value, details);
2855 if (!maybe_result->ToObject(&result)) return maybe_result; 2856 if (!maybe_result->ToObject(&result)) return maybe_result;
2856 dictionary = NumberDictionary::cast(result); 2857 dictionary = NumberDictionary::cast(result);
2857 } 2858 }
2858 } 2859 }
2859 // Switch to using the dictionary as the backing storage for
2860 // elements. Set the new map first to satify the elements type
2861 // assert in set_elements().
2862 set_map(new_map);
2863 set_elements(dictionary);
2864 2860
2865 new_map->heap()->isolate()->counters()->elements_to_dictionary()-> 2861 // Switch to using the dictionary as the backing storage for elements.
2866 Increment(); 2862 if (is_arguments) {
2863 FixedArray::cast(elements())->set(1, dictionary);
2864 } else {
2865 // Set the new map first to satify the elements type assert in
2866 // set_elements().
2867 Object* new_map;
2868 MaybeObject* maybe = map()->GetSlowElementsMap();
2869 if (!maybe->ToObject(&new_map)) return maybe;
2870 set_map(Map::cast(new_map));
2871 set_elements(dictionary);
2872 }
2873
2874 old_map->isolate()->counters()->elements_to_dictionary()->Increment();
2867 2875
2868 #ifdef DEBUG 2876 #ifdef DEBUG
2869 if (FLAG_trace_normalization) { 2877 if (FLAG_trace_normalization) {
2870 PrintF("Object elements have been normalized:\n"); 2878 PrintF("Object elements have been normalized:\n");
2871 Print(); 2879 Print();
2872 } 2880 }
2873 #endif 2881 #endif
2874 2882
2875 return this; 2883 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
2884 return dictionary;
2876 } 2885 }
2877 2886
2878 2887
2879 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, 2888 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
2880 DeleteMode mode) { 2889 DeleteMode mode) {
2881 // Check local property, ignore interceptor. 2890 // Check local property, ignore interceptor.
2882 LookupResult result; 2891 LookupResult result;
2883 LocalLookupRealNamedProperty(name, &result); 2892 LocalLookupRealNamedProperty(name, &result);
2884 if (!result.IsProperty()) return GetHeap()->true_value(); 2893 if (!result.IsProperty()) return GetHeap()->true_value();
2885 2894
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2985 ASSERT(result->IsBoolean()); 2994 ASSERT(result->IsBoolean());
2986 return *v8::Utils::OpenHandle(*result); 2995 return *v8::Utils::OpenHandle(*result);
2987 } 2996 }
2988 MaybeObject* raw_result = 2997 MaybeObject* raw_result =
2989 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); 2998 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
2990 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 2999 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2991 return raw_result; 3000 return raw_result;
2992 } 3001 }
2993 3002
2994 3003
3004 MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
3005 ASSERT(HasFastElements() || HasFastArgumentsElements());
3006 Heap* heap = GetHeap();
3007 FixedArray* backing_store = FixedArray::cast(elements());
3008 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
3009 backing_store = FixedArray::cast(backing_store->get(1));
3010 } else {
3011 Object* writable;
3012 MaybeObject* maybe = EnsureWritableFastElements();
3013 if (!maybe->ToObject(&writable)) return maybe;
3014 backing_store = FixedArray::cast(writable);
3015 }
3016 int length = IsJSArray()
3017 ? Smi::cast(JSArray::cast(this)->length())->value()
3018 : backing_store->length();
3019 if (index < static_cast<uint32_t>(length)) {
3020 backing_store->set_the_hole(index);
3021 }
3022 return heap->true_value();
3023 }
3024
3025
3026 MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
3027 DeleteMode mode) {
3028 Isolate* isolate = GetIsolate();
3029 Heap* heap = isolate->heap();
3030 FixedArray* backing_store = FixedArray::cast(elements());
3031 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
3032 backing_store = FixedArray::cast(backing_store->get(1));
3033 }
3034 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
3035 int entry = dictionary->FindEntry(index);
3036 if (entry != NumberDictionary::kNotFound) {
3037 Object* result = dictionary->DeleteProperty(entry, mode);
3038 if (mode == STRICT_DELETION && result == heap->false_value()) {
3039 // In strict mode, attempting to delete a non-configurable property
3040 // throws an exception.
3041 HandleScope scope(isolate);
3042 Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
3043 Handle<Object> args[2] = { name, Handle<Object>(this) };
3044 Handle<Object> error =
3045 isolate->factory()->NewTypeError("strict_delete_property",
3046 HandleVector(args, 2));
3047 return isolate->Throw(*error);
3048 }
3049 }
3050 return heap->true_value();
3051 }
3052
3053
2995 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { 3054 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
2996 Isolate* isolate = GetIsolate(); 3055 Isolate* isolate = GetIsolate();
2997 // Check access rights if needed. 3056 // Check access rights if needed.
2998 if (IsAccessCheckNeeded() && 3057 if (IsAccessCheckNeeded() &&
2999 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { 3058 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3000 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); 3059 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3001 return isolate->heap()->false_value(); 3060 return isolate->heap()->false_value();
3002 } 3061 }
3003 3062
3004 if (IsJSGlobalProxy()) { 3063 if (IsJSGlobalProxy()) {
3005 Object* proto = GetPrototype(); 3064 Object* proto = GetPrototype();
3006 if (proto->IsNull()) return isolate->heap()->false_value(); 3065 if (proto->IsNull()) return isolate->heap()->false_value();
3007 ASSERT(proto->IsJSGlobalObject()); 3066 ASSERT(proto->IsJSGlobalObject());
3008 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); 3067 return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3009 } 3068 }
3010 3069
3011 if (HasIndexedInterceptor()) { 3070 if (HasIndexedInterceptor()) {
3012 // Skip interceptor if forcing deletion. 3071 // Skip interceptor if forcing deletion.
3013 if (mode == FORCE_DELETION) { 3072 return (mode == FORCE_DELETION)
3014 return DeleteElementPostInterceptor(index, mode); 3073 ? DeleteElementPostInterceptor(index, FORCE_DELETION)
3015 } 3074 : DeleteElementWithInterceptor(index);
3016 return DeleteElementWithInterceptor(index);
3017 } 3075 }
3018 3076
3019 switch (GetElementsKind()) { 3077 switch (GetElementsKind()) {
3020 case FAST_ELEMENTS: { 3078 case FAST_ELEMENTS:
3021 Object* obj; 3079 return DeleteFastElement(index);
3022 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 3080
3023 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3081 case DICTIONARY_ELEMENTS:
3024 } 3082 return DeleteDictionaryElement(index, mode);
3025 int length = IsJSArray() 3083
3026 ? Smi::cast(JSArray::cast(this)->length())->value()
3027 : FixedArray::cast(elements())->length();
3028 if (index < static_cast<uint32_t>(length)) {
3029 FixedArray::cast(elements())->set_the_hole(index);
3030 }
3031 break;
3032 }
3033 case FAST_DOUBLE_ELEMENTS: { 3084 case FAST_DOUBLE_ELEMENTS: {
3034 int length = IsJSArray() 3085 int length = IsJSArray()
3035 ? Smi::cast(JSArray::cast(this)->length())->value() 3086 ? Smi::cast(JSArray::cast(this)->length())->value()
3036 : FixedArray::cast(elements())->length(); 3087 : FixedArray::cast(elements())->length();
3037 if (index < static_cast<uint32_t>(length)) { 3088 if (index < static_cast<uint32_t>(length)) {
3038 FixedDoubleArray::cast(elements())->set_the_hole(index); 3089 FixedDoubleArray::cast(elements())->set_the_hole(index);
3039 } 3090 }
3040 break; 3091 break;
3041 } 3092 }
3042 case EXTERNAL_PIXEL_ELEMENTS: 3093 case EXTERNAL_PIXEL_ELEMENTS:
3043 case EXTERNAL_BYTE_ELEMENTS: 3094 case EXTERNAL_BYTE_ELEMENTS:
3044 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3095 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3045 case EXTERNAL_SHORT_ELEMENTS: 3096 case EXTERNAL_SHORT_ELEMENTS:
3046 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3097 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3047 case EXTERNAL_INT_ELEMENTS: 3098 case EXTERNAL_INT_ELEMENTS:
3048 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3099 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3049 case EXTERNAL_FLOAT_ELEMENTS: 3100 case EXTERNAL_FLOAT_ELEMENTS:
3050 case EXTERNAL_DOUBLE_ELEMENTS: 3101 case EXTERNAL_DOUBLE_ELEMENTS:
3051 // Pixel and external array elements cannot be deleted. Just 3102 // Pixel and external array elements cannot be deleted. Just
3052 // silently ignore here. 3103 // silently ignore here.
3053 break; 3104 break;
3054 case DICTIONARY_ELEMENTS: { 3105
3055 NumberDictionary* dictionary = element_dictionary(); 3106 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3056 int entry = dictionary->FindEntry(index); 3107 FixedArray* parameter_map = FixedArray::cast(elements());
3057 if (entry != NumberDictionary::kNotFound) { 3108 uint32_t length = parameter_map->length();
3058 Object* result = dictionary->DeleteProperty(entry, mode); 3109 Object* probe =
3059 if (mode == STRICT_DELETION && result == 3110 (index + 2) < length ? parameter_map->get(index + 2) : NULL;
3060 isolate->heap()->false_value()) { 3111 if (probe != NULL && !probe->IsTheHole()) {
3061 // In strict mode, deleting a non-configurable property throws 3112 // TODO(kmillikin): We could check if this was the last aliased
3062 // exception. dictionary->DeleteProperty will return false_value() 3113 // parameter, and revert to normal elements in that case. That
3063 // if a non-configurable property is being deleted. 3114 // would enable GC of the context.
3064 HandleScope scope; 3115 parameter_map->set_the_hole(index + 2);
3065 Handle<Object> self(this); 3116 } else {
3066 Handle<Object> i = isolate->factory()->NewNumberFromUint(index); 3117 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3067 Handle<Object> args[2] = { i, self }; 3118 if (arguments->IsDictionary()) {
3068 return isolate->Throw(*isolate->factory()->NewTypeError( 3119 return DeleteDictionaryElement(index, mode);
3069 "strict_delete_property", HandleVector(args, 2))); 3120 } else {
3121 return DeleteFastElement(index);
3070 } 3122 }
3071 } 3123 }
3072 break; 3124 break;
3073 } 3125 }
3074 default:
3075 UNREACHABLE();
3076 break;
3077 } 3126 }
3078 return isolate->heap()->true_value(); 3127 return isolate->heap()->true_value();
3079 } 3128 }
3080 3129
3081 3130
3082 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { 3131 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3083 Isolate* isolate = GetIsolate(); 3132 Isolate* isolate = GetIsolate();
3084 // ECMA-262, 3rd, 8.6.2.5 3133 // ECMA-262, 3rd, 8.6.2.5
3085 ASSERT(name->IsString()); 3134 ASSERT(name->IsString());
3086 3135
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3129 { MaybeObject* maybe_obj = 3178 { MaybeObject* maybe_obj =
3130 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 3179 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3131 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3180 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3132 } 3181 }
3133 // Make sure the properties are normalized before removing the entry. 3182 // Make sure the properties are normalized before removing the entry.
3134 return DeleteNormalizedProperty(name, mode); 3183 return DeleteNormalizedProperty(name, mode);
3135 } 3184 }
3136 } 3185 }
3137 3186
3138 3187
3188 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3189 ElementsKind kind,
3190 Object* object) {
3191 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS);
3192 if (kind == FAST_ELEMENTS) {
3193 int length = IsJSArray()
3194 ? Smi::cast(JSArray::cast(this)->length())->value()
3195 : elements->length();
3196 for (int i = 0; i < length; ++i) {
3197 Object* element = elements->get(i);
3198 if (!element->IsTheHole() && element == object) return true;
3199 }
3200 } else {
3201 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object);
3202 if (!key->IsUndefined()) return true;
3203 }
3204 return false;
3205 }
3206
3207
3139 // Check whether this object references another object. 3208 // Check whether this object references another object.
3140 bool JSObject::ReferencesObject(Object* obj) { 3209 bool JSObject::ReferencesObject(Object* obj) {
3141 Map* map_of_this = map(); 3210 Map* map_of_this = map();
3142 Heap* heap = map_of_this->heap(); 3211 Heap* heap = map_of_this->heap();
3143 AssertNoAllocation no_alloc; 3212 AssertNoAllocation no_alloc;
3144 3213
3145 // Is the object the constructor for this object? 3214 // Is the object the constructor for this object?
3146 if (map_of_this->constructor() == obj) { 3215 if (map_of_this->constructor() == obj) {
3147 return true; 3216 return true;
3148 } 3217 }
3149 3218
3150 // Is the object the prototype for this object? 3219 // Is the object the prototype for this object?
3151 if (map_of_this->prototype() == obj) { 3220 if (map_of_this->prototype() == obj) {
3152 return true; 3221 return true;
3153 } 3222 }
3154 3223
3155 // Check if the object is among the named properties. 3224 // Check if the object is among the named properties.
3156 Object* key = SlowReverseLookup(obj); 3225 Object* key = SlowReverseLookup(obj);
3157 if (!key->IsUndefined()) { 3226 if (!key->IsUndefined()) {
3158 return true; 3227 return true;
3159 } 3228 }
3160 3229
3161 // Check if the object is among the indexed properties. 3230 // Check if the object is among the indexed properties.
3162 switch (GetElementsKind()) { 3231 ElementsKind kind = GetElementsKind();
3232 switch (kind) {
3163 case EXTERNAL_PIXEL_ELEMENTS: 3233 case EXTERNAL_PIXEL_ELEMENTS:
3164 case EXTERNAL_BYTE_ELEMENTS: 3234 case EXTERNAL_BYTE_ELEMENTS:
3165 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3235 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3166 case EXTERNAL_SHORT_ELEMENTS: 3236 case EXTERNAL_SHORT_ELEMENTS:
3167 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3237 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3168 case EXTERNAL_INT_ELEMENTS: 3238 case EXTERNAL_INT_ELEMENTS:
3169 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3239 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3170 case EXTERNAL_FLOAT_ELEMENTS: 3240 case EXTERNAL_FLOAT_ELEMENTS:
3171 case EXTERNAL_DOUBLE_ELEMENTS: 3241 case EXTERNAL_DOUBLE_ELEMENTS:
3242 case FAST_DOUBLE_ELEMENTS:
3172 // Raw pixels and external arrays do not reference other 3243 // Raw pixels and external arrays do not reference other
3173 // objects. 3244 // objects.
3174 break; 3245 break;
3175 case FAST_ELEMENTS: { 3246 case FAST_ELEMENTS:
3176 int length = IsJSArray() ? 3247 case DICTIONARY_ELEMENTS: {
3177 Smi::cast(JSArray::cast(this)->length())->value() : 3248 FixedArray* elements = FixedArray::cast(this->elements());
3178 FixedArray::cast(elements())->length(); 3249 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
3179 for (int i = 0; i < length; i++) {
3180 Object* element = FixedArray::cast(elements())->get(i);
3181 if (!element->IsTheHole() && element == obj) {
3182 return true;
3183 }
3184 }
3185 break; 3250 break;
3186 } 3251 }
3187 case DICTIONARY_ELEMENTS: { 3252 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3188 key = element_dictionary()->SlowReverseLookup(obj); 3253 FixedArray* parameter_map = FixedArray::cast(elements());
3189 if (!key->IsUndefined()) { 3254 // Check the mapped parameters.
3190 return true; 3255 int length = parameter_map->length();
3256 for (int i = 2; i < length; ++i) {
3257 Object* value = parameter_map->get(i);
3258 if (!value->IsTheHole() && value == obj) return true;
3191 } 3259 }
3260 // Check the arguments.
3261 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3262 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
3263 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
3192 break; 3264 break;
3193 } 3265 }
3194 default:
3195 UNREACHABLE();
3196 break;
3197 } 3266 }
3198 3267
3199 // For functions check the context. 3268 // For functions check the context.
3200 if (IsJSFunction()) { 3269 if (IsJSFunction()) {
3201 // Get the constructor function for arguments array. 3270 // Get the constructor function for arguments array.
3202 JSObject* arguments_boilerplate = 3271 JSObject* arguments_boilerplate =
3203 heap->isolate()->context()->global_context()-> 3272 heap->isolate()->context()->global_context()->
3204 arguments_boilerplate(); 3273 arguments_boilerplate();
3205 JSFunction* arguments_function = 3274 JSFunction* arguments_function =
3206 JSFunction::cast(arguments_boilerplate->map()->constructor()); 3275 JSFunction::cast(arguments_boilerplate->map()->constructor());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3251 3320
3252 if (IsJSGlobalProxy()) { 3321 if (IsJSGlobalProxy()) {
3253 Object* proto = GetPrototype(); 3322 Object* proto = GetPrototype();
3254 if (proto->IsNull()) return this; 3323 if (proto->IsNull()) return this;
3255 ASSERT(proto->IsJSGlobalObject()); 3324 ASSERT(proto->IsJSGlobalObject());
3256 return JSObject::cast(proto)->PreventExtensions(); 3325 return JSObject::cast(proto)->PreventExtensions();
3257 } 3326 }
3258 3327
3259 // If there are fast elements we normalize. 3328 // If there are fast elements we normalize.
3260 if (HasFastElements()) { 3329 if (HasFastElements()) {
3261 Object* ok; 3330 MaybeObject* result = NormalizeElements();
3262 { MaybeObject* maybe_ok = NormalizeElements(); 3331 if (result->IsFailure()) return result;
3263 if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3264 }
3265 } 3332 }
3333 // TODO(kmillikin): Handle arguments object with dictionary elements.
3334 ASSERT(HasDictionaryElements());
3266 // Make sure that we never go back to fast case. 3335 // Make sure that we never go back to fast case.
3267 element_dictionary()->set_requires_slow_elements(); 3336 element_dictionary()->set_requires_slow_elements();
3268 3337
3269 // Do a map transition, other objects with this map may still 3338 // Do a map transition, other objects with this map may still
3270 // be extensible. 3339 // be extensible.
3271 Object* new_map; 3340 Object* new_map;
3272 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); 3341 { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
3273 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 3342 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
3274 } 3343 }
3275 Map::cast(new_map)->set_is_extensible(false); 3344 Map::cast(new_map)->set_is_extensible(false);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
3412 for (Object* current = this; 3481 for (Object* current = this;
3413 current != heap->null_value(); 3482 current != heap->null_value();
3414 current = JSObject::cast(current)->GetPrototype()) { 3483 current = JSObject::cast(current)->GetPrototype()) {
3415 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 3484 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
3416 if (result->IsProperty() && result->type() == CALLBACKS) return; 3485 if (result->IsProperty() && result->type() == CALLBACKS) return;
3417 } 3486 }
3418 result->NotFound(); 3487 result->NotFound();
3419 } 3488 }
3420 3489
3421 3490
3491 // Search for a getter or setter in an elements dictionary. Returns either
3492 // undefined if the element is read-only, or the getter/setter pair (fixed
3493 // array) if there is an existing one, or the hole value if the element does
3494 // not exist or is a normal non-getter/setter data element.
3495 static Object* FindGetterSetterInDictionary(NumberDictionary* dictionary,
3496 uint32_t index,
3497 Heap* heap) {
3498 int entry = dictionary->FindEntry(index);
3499 if (entry != NumberDictionary::kNotFound) {
3500 Object* result = dictionary->ValueAt(entry);
3501 PropertyDetails details = dictionary->DetailsAt(entry);
3502 if (details.IsReadOnly()) return heap->undefined_value();
3503 if (details.type() == CALLBACKS && result->IsFixedArray()) return result;
3504 }
3505 return heap->the_hole_value();
3506 }
3507
3508
3422 MaybeObject* JSObject::DefineGetterSetter(String* name, 3509 MaybeObject* JSObject::DefineGetterSetter(String* name,
3423 PropertyAttributes attributes) { 3510 PropertyAttributes attributes) {
3424 Heap* heap = GetHeap(); 3511 Heap* heap = GetHeap();
3425 // Make sure that the top context does not change when doing callbacks or 3512 // Make sure that the top context does not change when doing callbacks or
3426 // interceptor calls. 3513 // interceptor calls.
3427 AssertNoContextChange ncc; 3514 AssertNoContextChange ncc;
3428 3515
3429 // Try to flatten before operating on the string. 3516 // Try to flatten before operating on the string.
3430 name->TryFlatten(); 3517 name->TryFlatten();
3431 3518
(...skipping 10 matching lines...) Expand all
3442 break; 3529 break;
3443 case EXTERNAL_PIXEL_ELEMENTS: 3530 case EXTERNAL_PIXEL_ELEMENTS:
3444 case EXTERNAL_BYTE_ELEMENTS: 3531 case EXTERNAL_BYTE_ELEMENTS:
3445 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3532 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3446 case EXTERNAL_SHORT_ELEMENTS: 3533 case EXTERNAL_SHORT_ELEMENTS:
3447 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3534 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3448 case EXTERNAL_INT_ELEMENTS: 3535 case EXTERNAL_INT_ELEMENTS:
3449 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3536 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3450 case EXTERNAL_FLOAT_ELEMENTS: 3537 case EXTERNAL_FLOAT_ELEMENTS:
3451 case EXTERNAL_DOUBLE_ELEMENTS: 3538 case EXTERNAL_DOUBLE_ELEMENTS:
3539 case FAST_DOUBLE_ELEMENTS:
3452 // Ignore getters and setters on pixel and external array 3540 // Ignore getters and setters on pixel and external array
3453 // elements. 3541 // elements.
3454 return heap->undefined_value(); 3542 return heap->undefined_value();
3455 case DICTIONARY_ELEMENTS: { 3543 case DICTIONARY_ELEMENTS: {
3456 // Lookup the index. 3544 Object* probe =
3457 NumberDictionary* dictionary = element_dictionary(); 3545 FindGetterSetterInDictionary(element_dictionary(), index, heap);
3458 int entry = dictionary->FindEntry(index); 3546 if (!probe->IsTheHole()) return probe;
3459 if (entry != NumberDictionary::kNotFound) { 3547 // Otherwise allow to override it.
3460 Object* result = dictionary->ValueAt(entry); 3548 break;
3461 PropertyDetails details = dictionary->DetailsAt(entry); 3549 }
3462 if (details.IsReadOnly()) return heap->undefined_value(); 3550 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3463 if (details.type() == CALLBACKS) { 3551 // Ascertain whether we have read-only properties or an existing
3464 if (result->IsFixedArray()) { 3552 // getter/setter pair in an arguments elements dictionary backing
3465 return result; 3553 // store.
3466 } 3554 FixedArray* parameter_map = FixedArray::cast(elements());
3467 // Otherwise allow to override it. 3555 uint32_t length = parameter_map->length();
3556 Object* probe =
3557 (index + 2) < length ? parameter_map->get(index + 2) : NULL;
3558 if (probe == NULL || probe->IsTheHole()) {
3559 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3560 if (arguments->IsDictionary()) {
3561 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
3562 probe = FindGetterSetterInDictionary(dictionary, index, heap);
3563 if (!probe->IsTheHole()) return probe;
3468 } 3564 }
3469 } 3565 }
3470 break; 3566 break;
3471 } 3567 }
3472 default:
3473 UNREACHABLE();
3474 break;
3475 } 3568 }
3476 } else { 3569 } else {
3477 // Lookup the name. 3570 // Lookup the name.
3478 LookupResult result; 3571 LookupResult result;
3479 LocalLookup(name, &result); 3572 LocalLookup(name, &result);
3480 if (result.IsProperty()) { 3573 if (result.IsProperty()) {
3481 if (result.IsReadOnly()) return heap->undefined_value(); 3574 if (result.IsReadOnly()) return heap->undefined_value();
3482 if (result.type() == CALLBACKS) { 3575 if (result.type() == CALLBACKS) {
3483 Object* obj = result.GetCallbackObject(); 3576 Object* obj = result.GetCallbackObject();
3484 // Need to preserve old getters/setters. 3577 // Need to preserve old getters/setters.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3527 return true; 3620 return true;
3528 } 3621 }
3529 3622
3530 3623
3531 MaybeObject* JSObject::SetElementCallback(uint32_t index, 3624 MaybeObject* JSObject::SetElementCallback(uint32_t index,
3532 Object* structure, 3625 Object* structure,
3533 PropertyAttributes attributes) { 3626 PropertyAttributes attributes) {
3534 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 3627 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
3535 3628
3536 // Normalize elements to make this operation simple. 3629 // Normalize elements to make this operation simple.
3537 Object* ok; 3630 NumberDictionary* dictionary = NULL;
3538 { MaybeObject* maybe_ok = NormalizeElements(); 3631 { Object* result;
3539 if (!maybe_ok->ToObject(&ok)) return maybe_ok; 3632 MaybeObject* maybe = NormalizeElements();
3633 if (!maybe->ToObject(&result)) return maybe;
3634 dictionary = NumberDictionary::cast(result);
3635 }
3636 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3637
3638 // Update the dictionary with the new CALLBACKS property.
3639 { Object* result;
3640 MaybeObject* maybe = dictionary->Set(index, structure, details);
3641 if (!maybe->ToObject(&result)) return maybe;
3642 dictionary = NumberDictionary::cast(result);
3540 } 3643 }
3541 3644
3542 // Update the dictionary with the new CALLBACKS property. 3645 dictionary->set_requires_slow_elements();
3543 Object* dict; 3646 // Update the dictionary backing store on the object.
3544 { MaybeObject* maybe_dict = 3647 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
3545 element_dictionary()->Set(index, structure, details); 3648 // Also delete any parameter alias.
3546 if (!maybe_dict->ToObject(&dict)) return maybe_dict; 3649 //
3650 // TODO(kmillikin): when deleting the last parameter alias we could
3651 // switch to a direct backing store without the parameter map. This
3652 // would allow GC of the context.
3653 FixedArray* parameter_map = FixedArray::cast(elements());
3654 uint32_t length = parameter_map->length();
3655 if (index + 2 < length) {
3656 parameter_map->set(index + 2, GetHeap()->the_hole_value());
3657 }
3658 parameter_map->set(1, dictionary);
3659 } else {
3660 set_elements(dictionary);
3547 } 3661 }
3548 3662
3549 NumberDictionary* elements = NumberDictionary::cast(dict);
3550 elements->set_requires_slow_elements();
3551 // Set the potential new dictionary on the object.
3552 set_elements(elements);
3553
3554 return structure; 3663 return structure;
3555 } 3664 }
3556 3665
3557 3666
3558 MaybeObject* JSObject::SetPropertyCallback(String* name, 3667 MaybeObject* JSObject::SetPropertyCallback(String* name,
3559 Object* structure, 3668 Object* structure,
3560 PropertyAttributes attributes) { 3669 PropertyAttributes attributes) {
3561 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 3670 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
3562 3671
3563 bool convert_back_to_fast = HasFastProperties() && 3672 bool convert_back_to_fast = HasFastProperties() &&
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 break; 3778 break;
3670 case EXTERNAL_PIXEL_ELEMENTS: 3779 case EXTERNAL_PIXEL_ELEMENTS:
3671 case EXTERNAL_BYTE_ELEMENTS: 3780 case EXTERNAL_BYTE_ELEMENTS:
3672 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3781 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3673 case EXTERNAL_SHORT_ELEMENTS: 3782 case EXTERNAL_SHORT_ELEMENTS:
3674 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3783 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3675 case EXTERNAL_INT_ELEMENTS: 3784 case EXTERNAL_INT_ELEMENTS:
3676 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3785 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3677 case EXTERNAL_FLOAT_ELEMENTS: 3786 case EXTERNAL_FLOAT_ELEMENTS:
3678 case EXTERNAL_DOUBLE_ELEMENTS: 3787 case EXTERNAL_DOUBLE_ELEMENTS:
3788 case FAST_DOUBLE_ELEMENTS:
3679 // Ignore getters and setters on pixel and external array 3789 // Ignore getters and setters on pixel and external array
3680 // elements. 3790 // elements.
3681 return isolate->heap()->undefined_value(); 3791 return isolate->heap()->undefined_value();
3682 case DICTIONARY_ELEMENTS: 3792 case DICTIONARY_ELEMENTS:
3683 break; 3793 break;
3684 default: 3794 case NON_STRICT_ARGUMENTS_ELEMENTS:
3685 UNREACHABLE(); 3795 UNIMPLEMENTED();
3686 break; 3796 break;
3687 } 3797 }
3688 3798
3689 Object* ok; 3799 Object* ok;
3690 { MaybeObject* maybe_ok = 3800 { MaybeObject* maybe_ok =
3691 SetElementCallback(index, info, info->property_attributes()); 3801 SetElementCallback(index, info, info->property_attributes());
3692 if (!maybe_ok->ToObject(&ok)) return maybe_ok; 3802 if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3693 } 3803 }
3694 } else { 3804 } else {
3695 // Lookup the name. 3805 // Lookup the name.
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after
4462 int pos = 0; 4572 int pos = 0;
4463 // Copy the elements from the JSArray to the temporary fixed array. 4573 // Copy the elements from the JSArray to the temporary fixed array.
4464 for (int i = 0; i < capacity; i++) { 4574 for (int i = 0; i < capacity; i++) {
4465 if (dict->IsKey(dict->KeyAt(i))) { 4575 if (dict->IsKey(dict->KeyAt(i))) {
4466 key_array->set(pos++, dict->ValueAt(i)); 4576 key_array->set(pos++, dict->ValueAt(i));
4467 } 4577 }
4468 } 4578 }
4469 // Compute the union of this and the temporary fixed array. 4579 // Compute the union of this and the temporary fixed array.
4470 return UnionOfKeys(key_array); 4580 return UnionOfKeys(key_array);
4471 } 4581 }
4472 default: 4582 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
4473 UNREACHABLE(); 4583 UNIMPLEMENTED();
4584 break;
4585 case JSObject::EXTERNAL_BYTE_ELEMENTS:
4586 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4587 case JSObject::EXTERNAL_SHORT_ELEMENTS:
4588 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4589 case JSObject::EXTERNAL_INT_ELEMENTS:
4590 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
4591 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
4592 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
4593 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
4594 case JSObject::FAST_DOUBLE_ELEMENTS:
4595 break;
4474 } 4596 }
4475 UNREACHABLE(); 4597 UNREACHABLE();
4476 return GetHeap()->null_value(); // Failure case needs to "return" a value. 4598 return GetHeap()->null_value(); // Failure case needs to "return" a value.
4477 } 4599 }
4478 4600
4479 4601
4480 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { 4602 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
4481 int len0 = length(); 4603 int len0 = length();
4482 #ifdef DEBUG 4604 #ifdef DEBUG
4483 if (FLAG_enable_slow_asserts) { 4605 if (FLAG_enable_slow_asserts) {
(...skipping 2621 matching lines...) Expand 10 before | Expand all | Expand 10 after
7105 } 7227 }
7106 } 7228 }
7107 7229
7108 PrintF("RelocInfo (size = %d)\n", relocation_size()); 7230 PrintF("RelocInfo (size = %d)\n", relocation_size());
7109 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 7231 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
7110 PrintF(out, "\n"); 7232 PrintF(out, "\n");
7111 } 7233 }
7112 #endif // ENABLE_DISASSEMBLER 7234 #endif // ENABLE_DISASSEMBLER
7113 7235
7114 7236
7237 static void CopyFastElementsToFast(FixedArray* source,
7238 FixedArray* destination,
7239 WriteBarrierMode mode) {
7240 uint32_t count = static_cast<uint32_t>(source->length());
7241 for (uint32_t i = 0; i < count; ++i) {
7242 destination->set(i, source->get(i), mode);
7243 }
7244 }
7245
7246
7247 static void CopySlowElementsToFast(NumberDictionary* source,
7248 FixedArray* destination,
7249 WriteBarrierMode mode) {
7250 for (int i = 0; i < source->Capacity(); ++i) {
7251 Object* key = source->KeyAt(i);
7252 if (key->IsNumber()) {
7253 uint32_t entry = static_cast<uint32_t>(key->Number());
7254 destination->set(entry, source->ValueAt(i), mode);
7255 }
7256 }
7257 }
7258
7259
7115 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, 7260 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
7116 int length) { 7261 int length) {
7117 Heap* heap = GetHeap(); 7262 Heap* heap = GetHeap();
7118 // We should never end in here with a pixel or external array. 7263 // We should never end in here with a pixel or external array.
7119 ASSERT(!HasExternalArrayElements()); 7264 ASSERT(!HasExternalArrayElements());
7120 7265
7121 Object* obj; 7266 // Allocate a new fast elements backing store.
7122 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); 7267 FixedArray* new_elements = NULL;
7123 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7268 { Object* object;
7269 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
7270 if (!maybe->ToObject(&object)) return maybe;
7271 new_elements = FixedArray::cast(object);
7124 } 7272 }
7125 FixedArray* elems = FixedArray::cast(obj);
7126 7273
7127 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); 7274 // Find the new map to use for this object if there is a map change.
7128 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7275 Map* new_map = NULL;
7276 if (elements()->map() != heap->non_strict_arguments_elements_map()) {
7277 Object* object;
7278 MaybeObject* maybe = map()->GetFastElementsMap();
7279 if (!maybe->ToObject(&object)) return maybe;
7280 new_map = Map::cast(object);
7129 } 7281 }
7130 Map* new_map = Map::cast(obj);
7131 7282
7283 AssertNoAllocation no_gc;
7284 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
7132 switch (GetElementsKind()) { 7285 switch (GetElementsKind()) {
7133 case FAST_ELEMENTS: { 7286 case FAST_ELEMENTS:
7134 AssertNoAllocation no_gc; 7287 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
7135 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); 7288 set_map(new_map);
7136 FixedArray* old_elements = FixedArray::cast(elements()); 7289 set_elements(new_elements);
7137 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 7290 break;
7138 // Fill out the new array with this content and array holes. 7291 case DICTIONARY_ELEMENTS:
7139 for (uint32_t i = 0; i < old_length; i++) { 7292 CopySlowElementsToFast(NumberDictionary::cast(elements()),
7140 elems->set(i, old_elements->get(i), mode); 7293 new_elements,
7294 mode);
7295 set_map(new_map);
7296 set_elements(new_elements);
7297 break;
7298 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7299 // The object's map and the parameter map are unchanged, the unaliased
7300 // arguments are copied to the new backing store.
7301 FixedArray* parameter_map = FixedArray::cast(elements());
7302 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7303 if (arguments->IsDictionary()) {
7304 CopySlowElementsToFast(NumberDictionary::cast(arguments),
7305 new_elements,
7306 mode);
7307 } else {
7308 CopyFastElementsToFast(arguments, new_elements, mode);
7141 } 7309 }
7310 parameter_map->set(1, new_elements);
7142 break; 7311 break;
7143 } 7312 }
7144 case FAST_DOUBLE_ELEMENTS: { 7313 case FAST_DOUBLE_ELEMENTS: {
7145 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements()); 7314 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements());
7146 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 7315 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
7147 // Fill out the new array with this content and array holes. 7316 // Fill out the new array with this content and array holes.
7148 for (uint32_t i = 0; i < old_length; i++) { 7317 for (uint32_t i = 0; i < old_length; i++) {
7149 if (!old_elements->is_the_hole(i)) { 7318 if (!old_elements->is_the_hole(i)) {
7150 Object* obj; 7319 Object* obj;
7151 // Objects must be allocated in the old object space, since the 7320 // Objects must be allocated in the old object space, since the
7152 // overall number of HeapNumbers needed for the conversion might 7321 // overall number of HeapNumbers needed for the conversion might
7153 // exceed the capacity of new space, and we would fail repeatedly 7322 // exceed the capacity of new space, and we would fail repeatedly
7154 // trying to convert the FixedDoubleArray. 7323 // trying to convert the FixedDoubleArray.
7155 MaybeObject* maybe_value_object = 7324 MaybeObject* maybe_value_object =
7156 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); 7325 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED);
7157 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; 7326 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object;
7158 // Force write barrier. It's not worth trying to exploit 7327 // Force write barrier. It's not worth trying to exploit
7159 // elems->GetWriteBarrierMode(), since it requires an 7328 // elems->GetWriteBarrierMode(), since it requires an
7160 // AssertNoAllocation stack object that would have to be positioned 7329 // AssertNoAllocation stack object that would have to be positioned
7161 // after the HeapNumber allocation anyway. 7330 // after the HeapNumber allocation anyway.
7162 elems->set(i, obj, UPDATE_WRITE_BARRIER); 7331 new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
7163 } 7332 }
7164 } 7333 }
7165 break; 7334 break;
7166 } 7335 }
7167 case DICTIONARY_ELEMENTS: { 7336 case EXTERNAL_BYTE_ELEMENTS:
7168 AssertNoAllocation no_gc; 7337 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7169 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); 7338 case EXTERNAL_SHORT_ELEMENTS:
7170 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 7339 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7171 for (int i = 0; i < dictionary->Capacity(); i++) { 7340 case EXTERNAL_INT_ELEMENTS:
7172 Object* key = dictionary->KeyAt(i); 7341 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7173 if (key->IsNumber()) { 7342 case EXTERNAL_FLOAT_ELEMENTS:
7174 uint32_t entry = static_cast<uint32_t>(key->Number()); 7343 case EXTERNAL_DOUBLE_ELEMENTS:
7175 elems->set(entry, dictionary->ValueAt(i), mode); 7344 case EXTERNAL_PIXEL_ELEMENTS:
7176 }
7177 }
7178 break;
7179 }
7180 default:
7181 UNREACHABLE(); 7345 UNREACHABLE();
7182 break; 7346 break;
7183 } 7347 }
7184 7348
7185 set_map(new_map); 7349 // Update the length if necessary.
7186 set_elements(elems);
7187
7188 if (IsJSArray()) { 7350 if (IsJSArray()) {
7189 JSArray::cast(this)->set_length(Smi::FromInt(length)); 7351 JSArray::cast(this)->set_length(Smi::FromInt(length));
7190 } 7352 }
7191 7353
7192 return this; 7354 return new_elements;
7193 } 7355 }
7194 7356
7195 7357
7196 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( 7358 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
7197 int capacity, 7359 int capacity,
7198 int length) { 7360 int length) {
7199 Heap* heap = GetHeap(); 7361 Heap* heap = GetHeap();
7200 // We should never end in here with a pixel or external array. 7362 // We should never end in here with a pixel or external array.
7201 ASSERT(!HasExternalArrayElements()); 7363 ASSERT(!HasExternalArrayElements());
7202 7364
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
7246 // We should never end in here with a pixel or external array. 7408 // We should never end in here with a pixel or external array.
7247 ASSERT(!HasExternalArrayElements()); 7409 ASSERT(!HasExternalArrayElements());
7248 7410
7249 uint32_t new_length = static_cast<uint32_t>(len->Number()); 7411 uint32_t new_length = static_cast<uint32_t>(len->Number());
7250 7412
7251 switch (GetElementsKind()) { 7413 switch (GetElementsKind()) {
7252 case FAST_ELEMENTS: { 7414 case FAST_ELEMENTS: {
7253 // Make sure we never try to shrink dense arrays into sparse arrays. 7415 // Make sure we never try to shrink dense arrays into sparse arrays.
7254 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= 7416 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
7255 new_length); 7417 new_length);
7256 Object* obj; 7418 MaybeObject* result = NormalizeElements();
7257 { MaybeObject* maybe_obj = NormalizeElements(); 7419 if (result->IsFailure()) return result;
7258 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7259 }
7260 7420
7261 // Update length for JSArrays. 7421 // Update length for JSArrays.
7262 if (IsJSArray()) JSArray::cast(this)->set_length(len); 7422 if (IsJSArray()) JSArray::cast(this)->set_length(len);
7263 break; 7423 break;
7264 } 7424 }
7265 case DICTIONARY_ELEMENTS: { 7425 case DICTIONARY_ELEMENTS: {
7266 if (IsJSArray()) { 7426 if (IsJSArray()) {
7267 uint32_t old_length = 7427 uint32_t old_length =
7268 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 7428 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
7269 element_dictionary()->RemoveNumberEntries(new_length, old_length), 7429 element_dictionary()->RemoveNumberEntries(new_length, old_length),
7270 JSArray::cast(this)->set_length(len); 7430 JSArray::cast(this)->set_length(len);
7271 } 7431 }
7272 break; 7432 break;
7273 } 7433 }
7274 default: 7434 case NON_STRICT_ARGUMENTS_ELEMENTS:
7435 UNIMPLEMENTED();
7436 break;
7437 case EXTERNAL_BYTE_ELEMENTS:
7438 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7439 case EXTERNAL_SHORT_ELEMENTS:
7440 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7441 case EXTERNAL_INT_ELEMENTS:
7442 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7443 case EXTERNAL_FLOAT_ELEMENTS:
7444 case EXTERNAL_DOUBLE_ELEMENTS:
7445 case EXTERNAL_PIXEL_ELEMENTS:
7446 case FAST_DOUBLE_ELEMENTS:
7275 UNREACHABLE(); 7447 UNREACHABLE();
7276 break; 7448 break;
7277 } 7449 }
7278 return this; 7450 return this;
7279 } 7451 }
7280 7452
7281 7453
7282 MaybeObject* JSArray::Initialize(int capacity) { 7454 MaybeObject* JSArray::Initialize(int capacity) {
7283 Heap* heap = GetHeap(); 7455 Heap* heap = GetHeap();
7284 ASSERT(capacity >= 0); 7456 ASSERT(capacity >= 0);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
7344 FixedArray::cast(elements())->set_the_hole(i); 7516 FixedArray::cast(elements())->set_the_hole(i);
7345 } 7517 }
7346 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 7518 JSArray::cast(this)->set_length(Smi::cast(smi_length));
7347 } 7519 }
7348 return this; 7520 return this;
7349 } 7521 }
7350 int min = NewElementsCapacity(old_capacity); 7522 int min = NewElementsCapacity(old_capacity);
7351 int new_capacity = value > min ? value : min; 7523 int new_capacity = value > min ? value : min;
7352 if (new_capacity <= kMaxFastElementsLength || 7524 if (new_capacity <= kMaxFastElementsLength ||
7353 !ShouldConvertToSlowElements(new_capacity)) { 7525 !ShouldConvertToSlowElements(new_capacity)) {
7354 Object* obj; 7526 MaybeObject* result =
7355 { MaybeObject* maybe_obj = 7527 SetFastElementsCapacityAndLength(new_capacity, value);
7356 SetFastElementsCapacityAndLength(new_capacity, value); 7528 if (result->IsFailure()) return result;
7357 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7358 }
7359 return this; 7529 return this;
7360 } 7530 }
7361 break; 7531 break;
7362 } 7532 }
7363 case DICTIONARY_ELEMENTS: { 7533 case DICTIONARY_ELEMENTS: {
7364 if (IsJSArray()) { 7534 if (IsJSArray()) {
7365 if (value == 0) { 7535 if (value == 0) {
7366 // If the length of a slow array is reset to zero, we clear 7536 // If the length of a slow array is reset to zero, we clear
7367 // the array and flush backing storage. This has the added 7537 // the array and flush backing storage. This has the added
7368 // benefit that the array returns to fast mode. 7538 // benefit that the array returns to fast mode.
7369 Object* obj; 7539 Object* obj;
7370 { MaybeObject* maybe_obj = ResetElements(); 7540 { MaybeObject* maybe_obj = ResetElements();
7371 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7541 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7372 } 7542 }
7373 } else { 7543 } else {
7374 // Remove deleted elements. 7544 // Remove deleted elements.
7375 uint32_t old_length = 7545 uint32_t old_length =
7376 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 7546 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
7377 element_dictionary()->RemoveNumberEntries(value, old_length); 7547 element_dictionary()->RemoveNumberEntries(value, old_length);
7378 } 7548 }
7379 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 7549 JSArray::cast(this)->set_length(Smi::cast(smi_length));
7380 } 7550 }
7381 return this; 7551 return this;
7382 } 7552 }
7383 default: 7553 case NON_STRICT_ARGUMENTS_ELEMENTS:
7554 case EXTERNAL_BYTE_ELEMENTS:
7555 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7556 case EXTERNAL_SHORT_ELEMENTS:
7557 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7558 case EXTERNAL_INT_ELEMENTS:
7559 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7560 case EXTERNAL_FLOAT_ELEMENTS:
7561 case EXTERNAL_DOUBLE_ELEMENTS:
7562 case EXTERNAL_PIXEL_ELEMENTS:
7563 case FAST_DOUBLE_ELEMENTS:
7384 UNREACHABLE(); 7564 UNREACHABLE();
7385 break; 7565 break;
7386 } 7566 }
7387 } 7567 }
7388 7568
7389 // General slow case. 7569 // General slow case.
7390 if (len->IsNumber()) { 7570 if (len->IsNumber()) {
7391 uint32_t length; 7571 uint32_t length;
7392 if (len->ToArrayIndex(&length)) { 7572 if (len->ToArrayIndex(&length)) {
7393 return SetSlowElements(len); 7573 return SetSlowElements(len);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
7570 } 7750 }
7571 break; 7751 break;
7572 } 7752 }
7573 case EXTERNAL_BYTE_ELEMENTS: 7753 case EXTERNAL_BYTE_ELEMENTS:
7574 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 7754 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7575 case EXTERNAL_SHORT_ELEMENTS: 7755 case EXTERNAL_SHORT_ELEMENTS:
7576 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 7756 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7577 case EXTERNAL_INT_ELEMENTS: 7757 case EXTERNAL_INT_ELEMENTS:
7578 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 7758 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7579 case EXTERNAL_FLOAT_ELEMENTS: 7759 case EXTERNAL_FLOAT_ELEMENTS:
7580 case EXTERNAL_DOUBLE_ELEMENTS: { 7760 case EXTERNAL_DOUBLE_ELEMENTS:
7761 case FAST_DOUBLE_ELEMENTS: {
7581 ExternalArray* array = ExternalArray::cast(elements()); 7762 ExternalArray* array = ExternalArray::cast(elements());
7582 if (index < static_cast<uint32_t>(array->length())) { 7763 if (index < static_cast<uint32_t>(array->length())) {
7583 return true; 7764 return true;
7584 } 7765 }
7585 break; 7766 break;
7586 } 7767 }
7587 case DICTIONARY_ELEMENTS: { 7768 case DICTIONARY_ELEMENTS: {
7588 if (element_dictionary()->FindEntry(index) 7769 if (element_dictionary()->FindEntry(index)
7589 != NumberDictionary::kNotFound) { 7770 != NumberDictionary::kNotFound) {
7590 return true; 7771 return true;
7591 } 7772 }
7592 break; 7773 break;
7593 } 7774 }
7594 default: 7775 case NON_STRICT_ARGUMENTS_ELEMENTS:
7595 UNREACHABLE(); 7776 UNREACHABLE();
7596 break; 7777 break;
7597 } 7778 }
7598 7779
7599 // Handle [] on String objects. 7780 // Handle [] on String objects.
7600 if (this->IsStringObjectWithCharacterAt(index)) return true; 7781 if (this->IsStringObjectWithCharacterAt(index)) return true;
7601 7782
7602 Object* pt = GetPrototype(); 7783 Object* pt = GetPrototype();
7603 if (pt->IsNull()) return false; 7784 if (pt->IsNull()) return false;
7604 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 7785 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
7698 case EXTERNAL_SHORT_ELEMENTS: 7879 case EXTERNAL_SHORT_ELEMENTS:
7699 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 7880 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7700 case EXTERNAL_INT_ELEMENTS: 7881 case EXTERNAL_INT_ELEMENTS:
7701 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 7882 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7702 case EXTERNAL_FLOAT_ELEMENTS: 7883 case EXTERNAL_FLOAT_ELEMENTS:
7703 case EXTERNAL_DOUBLE_ELEMENTS: { 7884 case EXTERNAL_DOUBLE_ELEMENTS: {
7704 ExternalArray* array = ExternalArray::cast(elements()); 7885 ExternalArray* array = ExternalArray::cast(elements());
7705 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT; 7886 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
7706 break; 7887 break;
7707 } 7888 }
7889 case FAST_DOUBLE_ELEMENTS:
7890 UNREACHABLE();
7891 break;
7708 case DICTIONARY_ELEMENTS: { 7892 case DICTIONARY_ELEMENTS: {
7709 if (element_dictionary()->FindEntry(index) != 7893 if (element_dictionary()->FindEntry(index) !=
7710 NumberDictionary::kNotFound) { 7894 NumberDictionary::kNotFound) {
7711 return DICTIONARY_ELEMENT; 7895 return DICTIONARY_ELEMENT;
7712 } 7896 }
7713 break; 7897 break;
7714 } 7898 }
7715 default: 7899 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7716 UNREACHABLE(); 7900 // Aliased parameters and non-aliased elements in a fast backing store
7901 // behave as FAST_ELEMENT. Non-aliased elements in a dictionary
7902 // backing store behave as DICTIONARY_ELEMENT.
7903 FixedArray* parameter_map = FixedArray::cast(elements());
7904 uint32_t length = parameter_map->length();
7905 Object* probe =
7906 (index + 2) < length ? parameter_map->get(index + 2) : NULL;
7907 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
7908 // If not aliased, check the arguments.
7909 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7910 if (arguments->IsDictionary()) {
7911 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
7912 if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) {
7913 return DICTIONARY_ELEMENT;
7914 }
7915 } else {
7916 length = arguments->length();
7917 probe = (index < length) ? arguments->get(index) : NULL;
7918 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
7919 }
7717 break; 7920 break;
7921 }
7718 } 7922 }
7719 7923
7720 return UNDEFINED_ELEMENT; 7924 return UNDEFINED_ELEMENT;
7721 } 7925 }
7722 7926
7723 7927
7928 bool JSObject::HasElementInElements(FixedArray* elements,
7929 ElementsKind kind,
7930 uint32_t index) {
7931 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS);
7932 if (kind == FAST_ELEMENTS) {
7933 int length = IsJSArray()
7934 ? Smi::cast(JSArray::cast(this)->length())->value()
7935 : elements->length();
7936 if (index < static_cast<uint32_t>(length) &&
7937 !elements->get(index)->IsTheHole()) {
7938 return true;
7939 }
7940 } else {
7941 if (NumberDictionary::cast(elements)->FindEntry(index) !=
7942 NumberDictionary::kNotFound) {
7943 return true;
7944 }
7945 }
7946 return false;
7947 }
7948
7949
7724 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { 7950 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
7725 // Check access rights if needed. 7951 // Check access rights if needed.
7726 if (IsAccessCheckNeeded()) { 7952 if (IsAccessCheckNeeded()) {
7727 Heap* heap = GetHeap(); 7953 Heap* heap = GetHeap();
7728 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 7954 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
7729 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 7955 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
7730 return false; 7956 return false;
7731 } 7957 }
7732 } 7958 }
7733 7959
7734 // Check for lookup interceptor 7960 // Check for lookup interceptor
7735 if (HasIndexedInterceptor()) { 7961 if (HasIndexedInterceptor()) {
7736 return HasElementWithInterceptor(receiver, index); 7962 return HasElementWithInterceptor(receiver, index);
7737 } 7963 }
7738 7964
7739 switch (GetElementsKind()) { 7965 ElementsKind kind = GetElementsKind();
7966 switch (kind) {
7740 case FAST_ELEMENTS: { 7967 case FAST_ELEMENTS: {
7741 uint32_t length = IsJSArray() ? 7968 uint32_t length = IsJSArray() ?
7742 static_cast<uint32_t> 7969 static_cast<uint32_t>
7743 (Smi::cast(JSArray::cast(this)->length())->value()) : 7970 (Smi::cast(JSArray::cast(this)->length())->value()) :
7744 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 7971 static_cast<uint32_t>(FixedArray::cast(elements())->length());
7745 if ((index < length) && 7972 if ((index < length) &&
7746 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; 7973 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
7747 break; 7974 break;
7748 } 7975 }
7749 case EXTERNAL_PIXEL_ELEMENTS: { 7976 case EXTERNAL_PIXEL_ELEMENTS: {
(...skipping 10 matching lines...) Expand all
7760 case EXTERNAL_INT_ELEMENTS: 7987 case EXTERNAL_INT_ELEMENTS:
7761 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 7988 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7762 case EXTERNAL_FLOAT_ELEMENTS: 7989 case EXTERNAL_FLOAT_ELEMENTS:
7763 case EXTERNAL_DOUBLE_ELEMENTS: { 7990 case EXTERNAL_DOUBLE_ELEMENTS: {
7764 ExternalArray* array = ExternalArray::cast(elements()); 7991 ExternalArray* array = ExternalArray::cast(elements());
7765 if (index < static_cast<uint32_t>(array->length())) { 7992 if (index < static_cast<uint32_t>(array->length())) {
7766 return true; 7993 return true;
7767 } 7994 }
7768 break; 7995 break;
7769 } 7996 }
7997 case FAST_DOUBLE_ELEMENTS:
7998 UNREACHABLE();
7999 break;
7770 case DICTIONARY_ELEMENTS: { 8000 case DICTIONARY_ELEMENTS: {
7771 if (element_dictionary()->FindEntry(index) 8001 if (element_dictionary()->FindEntry(index)
7772 != NumberDictionary::kNotFound) { 8002 != NumberDictionary::kNotFound) {
7773 return true; 8003 return true;
7774 } 8004 }
7775 break; 8005 break;
7776 } 8006 }
7777 default: 8007 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7778 UNREACHABLE(); 8008 FixedArray* parameter_map = FixedArray::cast(elements());
8009 uint32_t length = parameter_map->length();
8010 Object* probe =
8011 (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
8012 if (probe != NULL && !probe->IsTheHole()) return true;
8013
8014 // Not a mapped parameter, check the arguments.
8015 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8016 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
8017 if (HasElementInElements(arguments, kind, index)) return true;
7779 break; 8018 break;
8019 }
7780 } 8020 }
7781 8021
7782 // Handle [] on String objects. 8022 // Handle [] on String objects.
7783 if (this->IsStringObjectWithCharacterAt(index)) return true; 8023 if (this->IsStringObjectWithCharacterAt(index)) return true;
7784 8024
7785 Object* pt = GetPrototype(); 8025 Object* pt = GetPrototype();
7786 if (pt->IsNull()) return false; 8026 if (pt->IsNull()) return false;
7787 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 8027 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
7788 } 8028 }
7789 8029
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
7835 8075
7836 // api style callbacks. 8076 // api style callbacks.
7837 if (structure->IsAccessorInfo()) { 8077 if (structure->IsAccessorInfo()) {
7838 Handle<AccessorInfo> data(AccessorInfo::cast(structure)); 8078 Handle<AccessorInfo> data(AccessorInfo::cast(structure));
7839 Object* fun_obj = data->getter(); 8079 Object* fun_obj = data->getter();
7840 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); 8080 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
7841 HandleScope scope(isolate); 8081 HandleScope scope(isolate);
7842 Handle<JSObject> self(JSObject::cast(receiver)); 8082 Handle<JSObject> self(JSObject::cast(receiver));
7843 Handle<JSObject> holder_handle(JSObject::cast(holder)); 8083 Handle<JSObject> holder_handle(JSObject::cast(holder));
7844 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 8084 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
7845 Handle<String> key(isolate->factory()->NumberToString(number)); 8085 Handle<String> key = isolate->factory()->NumberToString(number);
7846 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); 8086 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
7847 CustomArguments args(isolate, data->data(), *self, *holder_handle); 8087 CustomArguments args(isolate, data->data(), *self, *holder_handle);
7848 v8::AccessorInfo info(args.end()); 8088 v8::AccessorInfo info(args.end());
7849 v8::Handle<v8::Value> result; 8089 v8::Handle<v8::Value> result;
7850 { 8090 {
7851 // Leaving JavaScript. 8091 // Leaving JavaScript.
7852 VMState state(isolate, EXTERNAL); 8092 VMState state(isolate, EXTERNAL);
7853 result = call_fun(v8::Utils::ToLocal(key), info); 8093 result = call_fun(v8::Utils::ToLocal(key), info);
7854 } 8094 }
7855 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 8095 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
7930 *isolate->factory()->NewTypeError("no_setter_in_callback", 8170 *isolate->factory()->NewTypeError("no_setter_in_callback",
7931 HandleVector(args, 2))); 8171 HandleVector(args, 2)));
7932 } 8172 }
7933 } 8173 }
7934 8174
7935 UNREACHABLE(); 8175 UNREACHABLE();
7936 return NULL; 8176 return NULL;
7937 } 8177 }
7938 8178
7939 8179
8180 bool JSObject::HasFastArgumentsElements() {
8181 Heap* heap = GetHeap();
8182 if (!elements()->IsFixedArray()) return false;
8183 FixedArray* elements = FixedArray::cast(this->elements());
8184 if (elements->map() != heap->non_strict_arguments_elements_map()) {
8185 return false;
8186 }
8187 FixedArray* arguments = FixedArray::cast(elements->get(1));
8188 return !arguments->IsDictionary();
8189 }
8190
8191
8192 bool JSObject::HasDictionaryArgumentsElements() {
8193 Heap* heap = GetHeap();
8194 if (!elements()->IsFixedArray()) return false;
8195 FixedArray* elements = FixedArray::cast(this->elements());
8196 if (elements->map() != heap->non_strict_arguments_elements_map()) {
8197 return false;
8198 }
8199 FixedArray* arguments = FixedArray::cast(elements->get(1));
8200 return arguments->IsDictionary();
8201 }
8202
8203
7940 // Adding n elements in fast case is O(n*n). 8204 // Adding n elements in fast case is O(n*n).
7941 // Note: revisit design to have dual undefined values to capture absent 8205 // Note: revisit design to have dual undefined values to capture absent
7942 // elements. 8206 // elements.
7943 MaybeObject* JSObject::SetFastElement(uint32_t index, 8207 MaybeObject* JSObject::SetFastElement(uint32_t index,
7944 Object* value, 8208 Object* value,
7945 StrictModeFlag strict_mode, 8209 StrictModeFlag strict_mode,
7946 bool check_prototype) { 8210 bool check_prototype) {
7947 ASSERT(HasFastElements()); 8211 ASSERT(HasFastElements() || HasFastArgumentsElements());
7948 8212
7949 Object* elms_obj; 8213 FixedArray* backing_store = FixedArray::cast(elements());
7950 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); 8214 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
7951 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 8215 backing_store = FixedArray::cast(backing_store->get(1));
8216 } else {
8217 Object* writable;
8218 MaybeObject* maybe = EnsureWritableFastElements();
8219 if (!maybe->ToObject(&writable)) return maybe;
8220 backing_store = FixedArray::cast(writable);
7952 } 8221 }
7953 FixedArray* elms = FixedArray::cast(elms_obj); 8222 uint32_t length = static_cast<uint32_t>(backing_store->length());
7954 uint32_t elms_length = static_cast<uint32_t>(elms->length());
7955 8223
7956 if (check_prototype && 8224 if (check_prototype &&
7957 (index >= elms_length || elms->get(index)->IsTheHole())) { 8225 (index >= length || backing_store->get(index)->IsTheHole())) {
7958 bool found; 8226 bool found;
7959 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 8227 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
7960 value, 8228 value,
7961 &found, 8229 &found,
7962 strict_mode); 8230 strict_mode);
7963 if (found) return result; 8231 if (found) return result;
7964 } 8232 }
7965 8233
7966 // Check whether there is extra space in fixed array.. 8234 // Check whether there is extra space in fixed array..
7967 if (index < elms_length) { 8235 if (index < length) {
7968 elms->set(index, value); 8236 backing_store->set(index, value);
7969 if (IsJSArray()) { 8237 if (IsJSArray()) {
7970 // Update the length of the array if needed. 8238 // Update the length of the array if needed.
7971 uint32_t array_length = 0; 8239 uint32_t array_length = 0;
7972 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 8240 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
7973 if (index >= array_length) { 8241 if (index >= array_length) {
7974 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 8242 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
7975 } 8243 }
7976 } 8244 }
7977 return value; 8245 return value;
7978 } 8246 }
7979 8247
7980 // Allow gap in fast case. 8248 // Allow gap in fast case.
7981 if ((index - elms_length) < kMaxGap) { 8249 if ((index - length) < kMaxGap) {
7982 // Try allocating extra space. 8250 // Try allocating extra space.
7983 int new_capacity = NewElementsCapacity(index+1); 8251 int new_capacity = NewElementsCapacity(index + 1);
7984 if (new_capacity <= kMaxFastElementsLength || 8252 if (new_capacity <= kMaxFastElementsLength ||
7985 !ShouldConvertToSlowElements(new_capacity)) { 8253 !ShouldConvertToSlowElements(new_capacity)) {
7986 ASSERT(static_cast<uint32_t>(new_capacity) > index); 8254 ASSERT(static_cast<uint32_t>(new_capacity) > index);
7987 Object* obj; 8255 Object* new_elements;
7988 { MaybeObject* maybe_obj = 8256 MaybeObject* maybe =
7989 SetFastElementsCapacityAndLength(new_capacity, index + 1); 8257 SetFastElementsCapacityAndLength(new_capacity, index + 1);
7990 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8258 if (!maybe->ToObject(&new_elements)) return maybe;
7991 } 8259 FixedArray::cast(new_elements)->set(index, value);
7992 FixedArray::cast(elements())->set(index, value);
7993 return value; 8260 return value;
7994 } 8261 }
7995 } 8262 }
7996 8263
7997 // Otherwise default to slow case. 8264 // Otherwise default to slow case.
7998 Object* obj; 8265 MaybeObject* result = NormalizeElements();
7999 { MaybeObject* maybe_obj = NormalizeElements(); 8266 if (result->IsFailure()) return result;
8000 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8267 return SetDictionaryElement(index, value, strict_mode, check_prototype);
8001 }
8002 ASSERT(HasDictionaryElements());
8003 return SetElement(index, value, strict_mode, check_prototype);
8004 } 8268 }
8005 8269
8006 8270
8271 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
8272 Object* value,
8273 StrictModeFlag strict_mode,
8274 bool check_prototype) {
8275 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
8276 Isolate* isolate = GetIsolate();
8277 Heap* heap = isolate->heap();
8278
8279 // Insert element in the dictionary.
8280 FixedArray* elements = FixedArray::cast(this->elements());
8281 bool is_arguments =
8282 (elements->map() == heap->non_strict_arguments_elements_map());
8283 NumberDictionary* dictionary = NULL;
8284 if (is_arguments) {
8285 dictionary = NumberDictionary::cast(elements->get(1));
8286 } else {
8287 dictionary = NumberDictionary::cast(elements);
8288 }
8289
8290 int entry = dictionary->FindEntry(index);
8291 if (entry != NumberDictionary::kNotFound) {
8292 Object* element = dictionary->ValueAt(entry);
8293 PropertyDetails details = dictionary->DetailsAt(entry);
8294 if (details.type() == CALLBACKS) {
8295 return SetElementWithCallback(element, index, value, this, strict_mode);
8296 } else {
8297 dictionary->UpdateMaxNumberKey(index);
8298 // If put fails in strict mode, throw an exception.
8299 if (!dictionary->ValueAtPut(entry, value) && strict_mode == kStrictMode) {
8300 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
8301 Handle<Object> holder(this);
8302 Handle<Object> args[2] = { number, holder };
8303 Handle<Object> error =
8304 isolate->factory()->NewTypeError("strict_read_only_property",
8305 HandleVector(args, 2));
8306 return isolate->Throw(*error);
8307 }
8308 }
8309 } else {
8310 // Index not already used. Look for an accessor in the prototype chain.
8311 if (check_prototype) {
8312 bool found;
8313 MaybeObject* result =
8314 SetElementWithCallbackSetterInPrototypes(
8315 index, value, &found, strict_mode);
8316 if (found) return result;
8317 }
8318 // When we set the is_extensible flag to false we always force the
8319 // element into dictionary mode (and force them to stay there).
8320 if (!map()->is_extensible()) {
8321 if (strict_mode == kNonStrictMode) {
8322 return isolate->heap()->undefined_value();
8323 } else {
8324 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
8325 Handle<String> name = isolate->factory()->NumberToString(number);
8326 Handle<Object> args[1] = { name };
8327 Handle<Object> error =
8328 isolate->factory()->NewTypeError("object_not_extensible",
8329 HandleVector(args, 1));
8330 return isolate->Throw(*error);
8331 }
8332 }
8333 Object* new_dictionary;
8334 MaybeObject* maybe = dictionary->AtNumberPut(index, value);
8335 if (!maybe->ToObject(&new_dictionary)) return maybe;
8336 if (dictionary != NumberDictionary::cast(new_dictionary)) {
8337 if (is_arguments) {
8338 elements->set(1, new_dictionary);
8339 } else {
8340 set_elements(HeapObject::cast(new_dictionary));
8341 }
8342 dictionary = NumberDictionary::cast(new_dictionary);
8343 }
8344 }
8345
8346 // Update the array length if this JSObject is an array.
8347 if (IsJSArray()) {
8348 MaybeObject* result =
8349 JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
8350 if (result->IsFailure()) return result;
8351 }
8352
8353 // Attempt to put this object back in fast case.
8354 if (ShouldConvertToFastElements()) {
8355 uint32_t new_length = 0;
8356 if (IsJSArray()) {
8357 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
8358 } else {
8359 new_length = dictionary->max_number_key() + 1;
8360 }
8361 MaybeObject* result =
8362 SetFastElementsCapacityAndLength(new_length, new_length);
8363 if (result->IsFailure()) return result;
8364 #ifdef DEBUG
8365 if (FLAG_trace_normalization) {
8366 PrintF("Object elements are fast case again:\n");
8367 Print();
8368 }
8369 #endif
8370 }
8371 return value;
8372 }
8373
8374
8007 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( 8375 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
8008 uint32_t index, 8376 uint32_t index,
8009 Object* value, 8377 Object* value,
8010 StrictModeFlag strict_mode, 8378 StrictModeFlag strict_mode,
8011 bool check_prototype) { 8379 bool check_prototype) {
8012 ASSERT(HasFastDoubleElements()); 8380 ASSERT(HasFastDoubleElements());
8013 8381
8014 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 8382 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8015 uint32_t elms_length = static_cast<uint32_t>(elms->length()); 8383 uint32_t elms_length = static_cast<uint32_t>(elms->length());
8016 8384
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
8127 } 8495 }
8128 8496
8129 8497
8130 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 8498 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
8131 Object* value, 8499 Object* value,
8132 StrictModeFlag strict_mode, 8500 StrictModeFlag strict_mode,
8133 bool check_prototype) { 8501 bool check_prototype) {
8134 Isolate* isolate = GetIsolate(); 8502 Isolate* isolate = GetIsolate();
8135 switch (GetElementsKind()) { 8503 switch (GetElementsKind()) {
8136 case FAST_ELEMENTS: 8504 case FAST_ELEMENTS:
8137 // Fast case.
8138 return SetFastElement(index, value, strict_mode, check_prototype); 8505 return SetFastElement(index, value, strict_mode, check_prototype);
8139 case FAST_DOUBLE_ELEMENTS: 8506 case FAST_DOUBLE_ELEMENTS:
8140 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 8507 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
8141 case EXTERNAL_PIXEL_ELEMENTS: { 8508 case EXTERNAL_PIXEL_ELEMENTS: {
8142 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 8509 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8143 return pixels->SetValue(index, value); 8510 return pixels->SetValue(index, value);
8144 } 8511 }
8145 case EXTERNAL_BYTE_ELEMENTS: { 8512 case EXTERNAL_BYTE_ELEMENTS: {
8146 ExternalByteArray* array = ExternalByteArray::cast(elements()); 8513 ExternalByteArray* array = ExternalByteArray::cast(elements());
8147 return array->SetValue(index, value); 8514 return array->SetValue(index, value);
(...skipping 22 matching lines...) Expand all
8170 return array->SetValue(index, value); 8537 return array->SetValue(index, value);
8171 } 8538 }
8172 case EXTERNAL_FLOAT_ELEMENTS: { 8539 case EXTERNAL_FLOAT_ELEMENTS: {
8173 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); 8540 ExternalFloatArray* array = ExternalFloatArray::cast(elements());
8174 return array->SetValue(index, value); 8541 return array->SetValue(index, value);
8175 } 8542 }
8176 case EXTERNAL_DOUBLE_ELEMENTS: { 8543 case EXTERNAL_DOUBLE_ELEMENTS: {
8177 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); 8544 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
8178 return array->SetValue(index, value); 8545 return array->SetValue(index, value);
8179 } 8546 }
8180 case DICTIONARY_ELEMENTS: { 8547 case DICTIONARY_ELEMENTS:
8181 // Insert element in the dictionary. 8548 return SetDictionaryElement(index, value, strict_mode, check_prototype);
8182 FixedArray* elms = FixedArray::cast(elements()); 8549 case NON_STRICT_ARGUMENTS_ELEMENTS: {
8183 NumberDictionary* dictionary = NumberDictionary::cast(elms); 8550 FixedArray* parameter_map = FixedArray::cast(elements());
8184 8551 uint32_t length = parameter_map->length();
8185 int entry = dictionary->FindEntry(index); 8552 Object* probe =
8186 if (entry != NumberDictionary::kNotFound) { 8553 (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
8187 Object* element = dictionary->ValueAt(entry); 8554 if (probe != NULL && !probe->IsTheHole()) {
8188 PropertyDetails details = dictionary->DetailsAt(entry); 8555 Context* context = Context::cast(parameter_map->get(0));
8189 if (details.type() == CALLBACKS) { 8556 int context_index = Smi::cast(probe)->value();
8190 return SetElementWithCallback(element, 8557 ASSERT(!context->get(context_index)->IsTheHole());
8191 index, 8558 context->set(context_index, value);
8192 value, 8559 return value;
8193 this, 8560 } else {
8194 strict_mode); 8561 // Object is not mapped, defer to the arguments.
8562 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8563 if (arguments->IsDictionary()) {
8564 return SetDictionaryElement(index, value, strict_mode,
8565 check_prototype);
8195 } else { 8566 } else {
8196 dictionary->UpdateMaxNumberKey(index); 8567 return SetFastElement(index, value, strict_mode, check_prototype);
8197 // If put fails instrict mode, throw exception.
8198 if (!dictionary->ValueAtPut(entry, value) &&
8199 strict_mode == kStrictMode) {
8200 Handle<Object> holder(this);
8201 Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
8202 Handle<Object> args[2] = { number, holder };
8203 return isolate->Throw(
8204 *isolate->factory()->NewTypeError("strict_read_only_property",
8205 HandleVector(args, 2)));
8206 }
8207 }
8208 } else {
8209 // Index not already used. Look for an accessor in the prototype chain.
8210 if (check_prototype) {
8211 bool found;
8212 MaybeObject* result =
8213 // Strict mode not needed. No-setter case already handled.
8214 SetElementWithCallbackSetterInPrototypes(index,
8215 value,
8216 &found,
8217 strict_mode);
8218 if (found) return result;
8219 }
8220 // When we set the is_extensible flag to false we always force
8221 // the element into dictionary mode (and force them to stay there).
8222 if (!map()->is_extensible()) {
8223 if (strict_mode == kNonStrictMode) {
8224 return isolate->heap()->undefined_value();
8225 } else {
8226 Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
8227 Handle<String> index_string(
8228 isolate->factory()->NumberToString(number));
8229 Handle<Object> args[1] = { index_string };
8230 return isolate->Throw(
8231 *isolate->factory()->NewTypeError("object_not_extensible",
8232 HandleVector(args, 1)));
8233 }
8234 }
8235 Object* result;
8236 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value);
8237 if (!maybe_result->ToObject(&result)) return maybe_result;
8238 }
8239 if (elms != FixedArray::cast(result)) {
8240 set_elements(FixedArray::cast(result));
8241 } 8568 }
8242 } 8569 }
8243
8244 // Update the array length if this JSObject is an array.
8245 if (IsJSArray()) {
8246 JSArray* array = JSArray::cast(this);
8247 Object* return_value;
8248 { MaybeObject* maybe_return_value =
8249 array->JSArrayUpdateLengthFromIndex(index, value);
8250 if (!maybe_return_value->ToObject(&return_value)) {
8251 return maybe_return_value;
8252 }
8253 }
8254 }
8255
8256 // Attempt to put this object back in fast case.
8257 if (ShouldConvertToFastElements()) {
8258 uint32_t new_length = 0;
8259 if (IsJSArray()) {
8260 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
8261 } else {
8262 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
8263 }
8264 if (ShouldConvertToFastDoubleElements()) {
8265 Object* obj;
8266 { MaybeObject* maybe_obj =
8267 SetFastDoubleElementsCapacityAndLength(new_length, new_length);
8268 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8269 }
8270 #ifdef DEBUG
8271 if (FLAG_trace_normalization) {
8272 PrintF("Object elements are fast double case again:\n");
8273 Print();
8274 }
8275 #endif
8276 } else {
8277 Object* obj;
8278 { MaybeObject* maybe_obj =
8279 SetFastElementsCapacityAndLength(new_length, new_length);
8280 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8281 }
8282 #ifdef DEBUG
8283 if (FLAG_trace_normalization) {
8284 PrintF("Object elements are fast case again:\n");
8285 Print();
8286 }
8287 #endif
8288 }
8289 }
8290
8291 return value;
8292 } 8570 }
8293 } 8571 }
8294 // All possible cases have been handled above. Add a return to avoid the 8572 // All possible cases have been handled above. Add a return to avoid the
8295 // complaints from the compiler. 8573 // complaints from the compiler.
8296 UNREACHABLE(); 8574 UNREACHABLE();
8297 return isolate->heap()->null_value(); 8575 return isolate->heap()->null_value();
8298 } 8576 }
8299 8577
8300 8578
8301 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 8579 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
8362 if (details.type() == CALLBACKS) { 8640 if (details.type() == CALLBACKS) {
8363 return GetElementWithCallback(receiver, 8641 return GetElementWithCallback(receiver,
8364 element, 8642 element,
8365 index, 8643 index,
8366 this); 8644 this);
8367 } 8645 }
8368 return element; 8646 return element;
8369 } 8647 }
8370 break; 8648 break;
8371 } 8649 }
8372 default: 8650 case NON_STRICT_ARGUMENTS_ELEMENTS:
8373 UNREACHABLE(); 8651 UNIMPLEMENTED();
8374 break; 8652 break;
8375 } 8653 }
8376 8654
8377 // Continue searching via the prototype chain. 8655 // Continue searching via the prototype chain.
8378 Object* pt = GetPrototype(); 8656 Object* pt = GetPrototype();
8379 if (pt->IsNull()) return GetHeap()->undefined_value(); 8657 if (pt->IsNull()) return GetHeap()->undefined_value();
8380 return pt->GetElementWithReceiver(receiver, index); 8658 return pt->GetElementWithReceiver(receiver, index);
8381 } 8659 }
8382 8660
8383 8661
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
8475 if (details.type() == CALLBACKS) { 8753 if (details.type() == CALLBACKS) {
8476 return GetElementWithCallback(receiver, 8754 return GetElementWithCallback(receiver,
8477 element, 8755 element,
8478 index, 8756 index,
8479 this); 8757 this);
8480 } 8758 }
8481 return element; 8759 return element;
8482 } 8760 }
8483 break; 8761 break;
8484 } 8762 }
8763 case NON_STRICT_ARGUMENTS_ELEMENTS: {
8764 FixedArray* parameter_map = FixedArray::cast(elements());
8765 uint32_t length = parameter_map->length();
8766 Object* probe =
8767 (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
8768 if (probe != NULL && !probe->IsTheHole()) {
8769 Context* context = Context::cast(parameter_map->get(0));
8770 int context_index = Smi::cast(probe)->value();
8771 ASSERT(!context->get(context_index)->IsTheHole());
8772 return context->get(context_index);
8773 } else {
8774 // Object is not mapped, defer to the arguments.
8775 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8776 if (arguments->IsDictionary()) {
8777 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
8778 int entry = dictionary->FindEntry(index);
8779 if (entry != NumberDictionary::kNotFound) {
8780 Object* element = dictionary->ValueAt(entry);
8781 PropertyDetails details = dictionary->DetailsAt(entry);
8782 if (details.type() == CALLBACKS) {
8783 return GetElementWithCallback(receiver,
8784 element,
8785 index,
8786 this);
8787 }
8788 return element;
8789 }
8790 } else if (index < static_cast<uint32_t>(arguments->length())) {
8791 Object* value = arguments->get(index);
8792 if (!value->IsTheHole()) return value;
8793 }
8794 }
8795 break;
8796 }
8485 } 8797 }
8486 8798
8487 Object* pt = GetPrototype(); 8799 Object* pt = GetPrototype();
8488 Heap* heap = GetHeap(); 8800 Heap* heap = GetHeap();
8489 if (pt == heap->null_value()) return heap->undefined_value(); 8801 if (pt == heap->null_value()) return heap->undefined_value();
8490 return pt->GetElementWithReceiver(receiver, index); 8802 return pt->GetElementWithReceiver(receiver, index);
8491 } 8803 }
8492 8804
8493 8805
8494 MaybeObject* JSObject::GetExternalElement(uint32_t index) { 8806 MaybeObject* JSObject::GetExternalElement(uint32_t index) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
8568 double value = array->get(index); 8880 double value = array->get(index);
8569 return GetHeap()->AllocateHeapNumber(value); 8881 return GetHeap()->AllocateHeapNumber(value);
8570 } 8882 }
8571 break; 8883 break;
8572 } 8884 }
8573 case FAST_DOUBLE_ELEMENTS: 8885 case FAST_DOUBLE_ELEMENTS:
8574 case FAST_ELEMENTS: 8886 case FAST_ELEMENTS:
8575 case DICTIONARY_ELEMENTS: 8887 case DICTIONARY_ELEMENTS:
8576 UNREACHABLE(); 8888 UNREACHABLE();
8577 break; 8889 break;
8890 case NON_STRICT_ARGUMENTS_ELEMENTS:
8891 UNIMPLEMENTED();
8892 break;
8578 } 8893 }
8579 return GetHeap()->undefined_value(); 8894 return GetHeap()->undefined_value();
8580 } 8895 }
8581 8896
8582 8897
8583 bool JSObject::HasDenseElements() { 8898 bool JSObject::HasDenseElements() {
8584 int capacity = 0; 8899 int capacity = 0;
8585 int number_of_elements = 0; 8900 int number_of_elements = 0;
8586 8901
8902 FixedArray* backing_store = FixedArray::cast(elements());
8587 switch (GetElementsKind()) { 8903 switch (GetElementsKind()) {
8588 case FAST_ELEMENTS: { 8904 case NON_STRICT_ARGUMENTS_ELEMENTS:
8589 FixedArray* elms = FixedArray::cast(elements()); 8905 backing_store = FixedArray::cast(backing_store->get(1));
8590 capacity = elms->length(); 8906 if (backing_store->IsDictionary()) {
8591 for (int i = 0; i < capacity; i++) { 8907 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
8592 if (!elms->get(i)->IsTheHole()) number_of_elements++; 8908 capacity = dictionary->Capacity();
8909 number_of_elements = dictionary->NumberOfElements();
8910 break;
8593 } 8911 }
8912 // Fall through.
8913 case FAST_ELEMENTS:
8914 capacity = backing_store->length();
8915 for (int i = 0; i < capacity; ++i) {
8916 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
8917 }
8918 break;
8919 case DICTIONARY_ELEMENTS: {
8920 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
8921 capacity = dictionary->Capacity();
8922 number_of_elements = dictionary->NumberOfElements();
8594 break; 8923 break;
8595 } 8924 }
8596 case FAST_DOUBLE_ELEMENTS: { 8925 case FAST_DOUBLE_ELEMENTS: {
8597 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 8926 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8598 capacity = elms->length(); 8927 capacity = elms->length();
8599 for (int i = 0; i < capacity; i++) { 8928 for (int i = 0; i < capacity; i++) {
8600 if (!elms->is_the_hole(i)) number_of_elements++; 8929 if (!elms->is_the_hole(i)) number_of_elements++;
8601 } 8930 }
8602 break; 8931 break;
8603 } 8932 }
8604 case EXTERNAL_PIXEL_ELEMENTS: 8933 case EXTERNAL_PIXEL_ELEMENTS:
8605 case EXTERNAL_BYTE_ELEMENTS: 8934 case EXTERNAL_BYTE_ELEMENTS:
8606 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 8935 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8607 case EXTERNAL_SHORT_ELEMENTS: 8936 case EXTERNAL_SHORT_ELEMENTS:
8608 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 8937 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8609 case EXTERNAL_INT_ELEMENTS: 8938 case EXTERNAL_INT_ELEMENTS:
8610 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8939 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8611 case EXTERNAL_FLOAT_ELEMENTS: 8940 case EXTERNAL_FLOAT_ELEMENTS:
8612 case EXTERNAL_DOUBLE_ELEMENTS: { 8941 case EXTERNAL_DOUBLE_ELEMENTS: {
8613 return true; 8942 return true;
8614 } 8943 }
8615 case DICTIONARY_ELEMENTS: {
8616 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8617 capacity = dictionary->Capacity();
8618 number_of_elements = dictionary->NumberOfElements();
8619 break;
8620 }
8621 default:
8622 UNREACHABLE();
8623 break;
8624 } 8944 }
8625 8945 return (capacity == 0) || (number_of_elements > (capacity / 2));
8626 if (capacity == 0) return true;
8627 return (number_of_elements > (capacity / 2));
8628 } 8946 }
8629 8947
8630 8948
8631 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { 8949 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
8632 // Keep the array in fast case if the current backing storage is 8950 // Keep the array in fast case if the current backing storage is
8633 // almost filled and if the new capacity is no more than twice the 8951 // almost filled and if the new capacity is no more than twice the
8634 // old capacity. 8952 // old capacity.
8635 int elements_length = 0; 8953 int elements_length = 0;
8636 if (HasFastElements()) { 8954 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
8955 FixedArray* backing_store = FixedArray::cast(elements());
8956 elements_length = FixedArray::cast(backing_store->get(1))->length();
8957 } else if (HasFastElements()) {
8637 elements_length = FixedArray::cast(elements())->length(); 8958 elements_length = FixedArray::cast(elements())->length();
8638 } else if (HasFastDoubleElements()) { 8959 } else if (HasFastDoubleElements()) {
8639 elements_length = FixedDoubleArray::cast(elements())->length(); 8960 elements_length = FixedDoubleArray::cast(elements())->length();
8640 } else { 8961 } else {
8641 UNREACHABLE(); 8962 UNREACHABLE();
8642 } 8963 }
8643 return !HasDenseElements() || ((new_capacity / 2) > elements_length); 8964 return !HasDenseElements() || ((new_capacity / 2) > elements_length);
8644 } 8965 }
8645 8966
8646 8967
8647 bool JSObject::ShouldConvertToFastElements() { 8968 bool JSObject::ShouldConvertToFastElements() {
8648 ASSERT(HasDictionaryElements()); 8969 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
8649 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8650 // If the elements are sparse, we should not go back to fast case. 8970 // If the elements are sparse, we should not go back to fast case.
8651 if (!HasDenseElements()) return false; 8971 if (!HasDenseElements()) return false;
8972 // An object requiring access checks is never allowed to have fast
8973 // elements. If it had fast elements we would skip security checks.
8974 if (IsAccessCheckNeeded()) return false;
8975
8976 FixedArray* elements = FixedArray::cast(this->elements());
8977 NumberDictionary* dictionary = NULL;
8978 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
8979 dictionary = NumberDictionary::cast(elements->get(1));
8980 } else {
8981 dictionary = NumberDictionary::cast(elements);
8982 }
8652 // If an element has been added at a very high index in the elements 8983 // If an element has been added at a very high index in the elements
8653 // dictionary, we cannot go back to fast case. 8984 // dictionary, we cannot go back to fast case.
8654 if (dictionary->requires_slow_elements()) return false; 8985 if (dictionary->requires_slow_elements()) return false;
8655 // An object requiring access checks is never allowed to have fast
8656 // elements. If it had fast elements we would skip security checks.
8657 if (IsAccessCheckNeeded()) return false;
8658 // If the dictionary backing storage takes up roughly half as much 8986 // If the dictionary backing storage takes up roughly half as much
8659 // space as a fast-case backing storage would the array should have 8987 // space as a fast-case backing storage would the array should have
8660 // fast elements. 8988 // fast elements.
8661 uint32_t length = 0; 8989 uint32_t length = 0;
8662 if (IsJSArray()) { 8990 if (IsJSArray()) {
8663 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 8991 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8664 } else { 8992 } else {
8665 length = dictionary->max_number_key(); 8993 length = dictionary->max_number_key();
8666 } 8994 }
8667 return static_cast<uint32_t>(dictionary->Capacity()) >= 8995 return static_cast<uint32_t>(dictionary->Capacity()) >=
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
8867 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9195 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8868 case EXTERNAL_SHORT_ELEMENTS: 9196 case EXTERNAL_SHORT_ELEMENTS:
8869 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 9197 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8870 case EXTERNAL_INT_ELEMENTS: 9198 case EXTERNAL_INT_ELEMENTS:
8871 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 9199 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8872 case EXTERNAL_FLOAT_ELEMENTS: 9200 case EXTERNAL_FLOAT_ELEMENTS:
8873 case EXTERNAL_DOUBLE_ELEMENTS: { 9201 case EXTERNAL_DOUBLE_ELEMENTS: {
8874 ExternalArray* array = ExternalArray::cast(elements()); 9202 ExternalArray* array = ExternalArray::cast(elements());
8875 return index < static_cast<uint32_t>(array->length()); 9203 return index < static_cast<uint32_t>(array->length());
8876 } 9204 }
9205 case FAST_DOUBLE_ELEMENTS:
9206 UNREACHABLE();
9207 break;
8877 case DICTIONARY_ELEMENTS: { 9208 case DICTIONARY_ELEMENTS: {
8878 return element_dictionary()->FindEntry(index) 9209 return element_dictionary()->FindEntry(index)
8879 != NumberDictionary::kNotFound; 9210 != NumberDictionary::kNotFound;
8880 } 9211 }
8881 default: 9212 case NON_STRICT_ARGUMENTS_ELEMENTS:
8882 UNREACHABLE(); 9213 UNIMPLEMENTED();
8883 break; 9214 break;
8884 } 9215 }
8885 // All possibilities have been handled above already. 9216 // All possibilities have been handled above already.
8886 UNREACHABLE(); 9217 UNREACHABLE();
8887 return GetHeap()->null_value(); 9218 return GetHeap()->null_value();
8888 } 9219 }
8889 9220
8890 9221
8891 bool JSObject::HasRealNamedCallbackProperty(String* key) { 9222 bool JSObject::HasRealNamedCallbackProperty(String* key) {
8892 // Check access rights if needed. 9223 // Check access rights if needed.
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
9116 int length = ExternalArray::cast(elements())->length(); 9447 int length = ExternalArray::cast(elements())->length();
9117 while (counter < length) { 9448 while (counter < length) {
9118 if (storage != NULL) { 9449 if (storage != NULL) {
9119 storage->set(counter, Smi::FromInt(counter)); 9450 storage->set(counter, Smi::FromInt(counter));
9120 } 9451 }
9121 counter++; 9452 counter++;
9122 } 9453 }
9123 ASSERT(!storage || storage->length() >= counter); 9454 ASSERT(!storage || storage->length() >= counter);
9124 break; 9455 break;
9125 } 9456 }
9457 case FAST_DOUBLE_ELEMENTS:
9458 UNREACHABLE();
9459 break;
9126 case DICTIONARY_ELEMENTS: { 9460 case DICTIONARY_ELEMENTS: {
9127 if (storage != NULL) { 9461 if (storage != NULL) {
9128 element_dictionary()->CopyKeysTo(storage, filter); 9462 element_dictionary()->CopyKeysTo(storage, filter);
9129 } 9463 }
9130 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 9464 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
9131 break; 9465 break;
9132 } 9466 }
9133 default: 9467 case NON_STRICT_ARGUMENTS_ELEMENTS: {
9134 UNREACHABLE(); 9468 FixedArray* parameter_map = FixedArray::cast(elements());
9469 int length = parameter_map->length();
9470 for (int i = 2; i < length; ++i) {
9471 if (!parameter_map->get(i)->IsTheHole()) {
9472 if (storage != NULL) storage->set(i - 2, Smi::FromInt(i - 2));
9473 ++counter;
9474 }
9475 }
9476 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9477 if (arguments->IsDictionary()) {
9478 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
9479 if (storage != NULL) dictionary->CopyKeysTo(storage, filter);
9480 counter += dictionary->NumberOfElementsFilterAttributes(filter);
9481 } else {
9482 int length = arguments->length();
9483 for (int i = 0; i < length; ++i) {
9484 if (!arguments->get(i)->IsTheHole()) {
9485 if (storage != NULL) storage->set(i, Smi::FromInt(i));
9486 ++counter;
9487 }
9488 }
9489 }
9135 break; 9490 break;
9491 }
9136 } 9492 }
9137 9493
9138 if (this->IsJSValue()) { 9494 if (this->IsJSValue()) {
9139 Object* val = JSValue::cast(this)->value(); 9495 Object* val = JSValue::cast(this)->value();
9140 if (val->IsString()) { 9496 if (val->IsString()) {
9141 String* str = String::cast(val); 9497 String* str = String::cast(val);
9142 if (storage) { 9498 if (storage) {
9143 for (int i = 0; i < str->length(); i++) { 9499 for (int i = 0; i < str->length(); i++) {
9144 storage->set(counter + i, Smi::FromInt(i)); 9500 storage->set(counter + i, Smi::FromInt(i));
9145 } 9501 }
(...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after
11206 if (break_point_objects()->IsUndefined()) return 0; 11562 if (break_point_objects()->IsUndefined()) return 0;
11207 // Single beak point. 11563 // Single beak point.
11208 if (!break_point_objects()->IsFixedArray()) return 1; 11564 if (!break_point_objects()->IsFixedArray()) return 1;
11209 // Multiple break points. 11565 // Multiple break points.
11210 return FixedArray::cast(break_point_objects())->length(); 11566 return FixedArray::cast(break_point_objects())->length();
11211 } 11567 }
11212 #endif 11568 #endif
11213 11569
11214 11570
11215 } } // namespace v8::internal 11571 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698