OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 10881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10892 } | 10892 } |
10893 | 10893 |
10894 | 10894 |
10895 // Returns false if the passed-in index is marked non-configurable, | 10895 // Returns false if the passed-in index is marked non-configurable, |
10896 // which will cause the ES5 truncation operation to halt, and thus | 10896 // which will cause the ES5 truncation operation to halt, and thus |
10897 // no further old values need be collected. | 10897 // no further old values need be collected. |
10898 static bool GetOldValue(Isolate* isolate, | 10898 static bool GetOldValue(Isolate* isolate, |
10899 Handle<JSObject> object, | 10899 Handle<JSObject> object, |
10900 uint32_t index, | 10900 uint32_t index, |
10901 List<Handle<Object> >* old_values, | 10901 List<Handle<Object> >* old_values, |
10902 List<Handle<String> >* indices) { | 10902 List<uint32_t>* indices) { |
10903 PropertyAttributes attributes = object->GetLocalElementAttribute(index); | 10903 PropertyAttributes attributes = object->GetLocalElementAttribute(index); |
10904 ASSERT(attributes != ABSENT); | 10904 ASSERT(attributes != ABSENT); |
10905 if (attributes == DONT_DELETE) return false; | 10905 if (attributes == DONT_DELETE) return false; |
10906 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL | 10906 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL |
10907 ? Object::GetElement(object, index) | 10907 ? Object::GetElement(object, index) |
10908 : Handle<Object>::cast(isolate->factory()->the_hole_value())); | 10908 : Handle<Object>::cast(isolate->factory()->the_hole_value())); |
10909 indices->Add(isolate->factory()->Uint32ToString(index)); | 10909 indices->Add(index); |
10910 return true; | 10910 return true; |
10911 } | 10911 } |
10912 | 10912 |
10913 | 10913 |
10914 // TODO(rafaelw): Remove |delete_count| argument and rely on the length of | |
10915 // of |deleted|. | |
10916 static void EnqueueSpliceRecord(Handle<JSArray> object, | |
10917 uint32_t index, | |
10918 Handle<JSArray> deleted, | |
10919 uint32_t delete_count, | |
10920 uint32_t add_count) { | |
10921 Isolate* isolate = object->GetIsolate(); | |
10922 HandleScope scope(isolate); | |
10923 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index); | |
10924 Handle<Object> delete_count_object = | |
10925 isolate->factory()->NewNumberFromUint(delete_count); | |
10926 Handle<Object> add_count_object = | |
10927 isolate->factory()->NewNumberFromUint(add_count); | |
10928 | |
10929 Handle<Object> args[] = | |
10930 { object, index_object, deleted, delete_count_object, add_count_object }; | |
10931 | |
10932 bool threw; | |
10933 Execution::Call(Handle<JSFunction>(isolate->observers_enqueue_splice()), | |
10934 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | |
10935 &threw); | |
10936 ASSERT(!threw); | |
10937 } | |
10938 | |
10939 | |
10940 static void BeginPerformSplice(Handle<JSArray> object) { | |
10941 Isolate* isolate = object->GetIsolate(); | |
10942 HandleScope scope(isolate); | |
10943 Handle<Object> args[] = { object }; | |
10944 | |
10945 bool threw; | |
10946 Execution::Call(Handle<JSFunction>(isolate->observers_begin_perform_splice()), | |
10947 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | |
10948 &threw); | |
10949 ASSERT(!threw); | |
10950 } | |
10951 | |
adamk
2013/05/24 21:39:35
needs moar whitespace
rafaelw
2013/05/24 21:54:52
Done.
| |
10952 static void EndPerformSplice(Handle<JSArray> object) { | |
10953 Isolate* isolate = object->GetIsolate(); | |
10954 HandleScope scope(isolate); | |
10955 Handle<Object> args[] = { object }; | |
10956 | |
10957 bool threw; | |
10958 Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()), | |
10959 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | |
10960 &threw); | |
10961 ASSERT(!threw); | |
10962 } | |
10963 | |
10964 | |
10914 MaybeObject* JSArray::SetElementsLength(Object* len) { | 10965 MaybeObject* JSArray::SetElementsLength(Object* len) { |
10915 // We should never end in here with a pixel or external array. | 10966 // We should never end in here with a pixel or external array. |
10916 ASSERT(AllowsSetElementsLength()); | 10967 ASSERT(AllowsSetElementsLength()); |
10917 if (!(FLAG_harmony_observation && map()->is_observed())) | 10968 if (!(FLAG_harmony_observation && map()->is_observed())) |
10918 return GetElementsAccessor()->SetLength(this, len); | 10969 return GetElementsAccessor()->SetLength(this, len); |
10919 | 10970 |
10920 Isolate* isolate = GetIsolate(); | 10971 Isolate* isolate = GetIsolate(); |
10921 HandleScope scope(isolate); | 10972 HandleScope scope(isolate); |
10922 Handle<JSArray> self(this); | 10973 Handle<JSArray> self(this); |
10923 List<Handle<String> > indices; | 10974 List<uint32_t> indices; |
10924 List<Handle<Object> > old_values; | 10975 List<Handle<Object> > old_values; |
10925 Handle<Object> old_length_handle(self->length(), isolate); | 10976 Handle<Object> old_length_handle(self->length(), isolate); |
10926 Handle<Object> new_length_handle(len, isolate); | 10977 Handle<Object> new_length_handle(len, isolate); |
10927 uint32_t old_length = 0; | 10978 uint32_t old_length = 0; |
10928 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 10979 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
10929 uint32_t new_length = 0; | 10980 uint32_t new_length = 0; |
10930 if (!new_length_handle->ToArrayIndex(&new_length)) | 10981 if (!new_length_handle->ToArrayIndex(&new_length)) |
10931 return Failure::InternalError(); | 10982 return Failure::InternalError(); |
10932 | 10983 |
10933 // Observed arrays should always be in dictionary mode; | 10984 // Observed arrays should always be in dictionary mode; |
(...skipping 19 matching lines...) Expand all Loading... | |
10953 } | 11004 } |
10954 } | 11005 } |
10955 } | 11006 } |
10956 | 11007 |
10957 MaybeObject* result = | 11008 MaybeObject* result = |
10958 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); | 11009 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); |
10959 Handle<Object> hresult; | 11010 Handle<Object> hresult; |
10960 if (!result->ToHandle(&hresult, isolate)) return result; | 11011 if (!result->ToHandle(&hresult, isolate)) return result; |
10961 | 11012 |
10962 CHECK(self->length()->ToArrayIndex(&new_length)); | 11013 CHECK(self->length()->ToArrayIndex(&new_length)); |
10963 if (old_length != new_length) { | 11014 if (old_length == new_length) return *hresult; |
10964 for (int i = 0; i < indices.length(); ++i) { | 11015 |
10965 JSObject::EnqueueChangeRecord( | 11016 BeginPerformSplice(self); |
10966 self, "deleted", indices[i], old_values[i]); | 11017 |
11018 for (int i = 0; i < indices.length(); ++i) { | |
11019 JSObject::EnqueueChangeRecord( | |
11020 self, "deleted", isolate->factory()->Uint32ToString(indices[i]), | |
11021 old_values[i]); | |
11022 } | |
11023 JSObject::EnqueueChangeRecord( | |
11024 self, "updated", isolate->factory()->length_string(), | |
11025 old_length_handle); | |
11026 | |
11027 EndPerformSplice(self); | |
11028 | |
11029 uint32_t index = Min(old_length, new_length); | |
11030 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; | |
11031 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; | |
11032 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
11033 if (delete_count) { | |
11034 int i = indices.length(); | |
11035 while (i--) { | |
11036 JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE, | |
11037 kNonStrictMode); | |
10967 } | 11038 } |
10968 JSObject::EnqueueChangeRecord( | |
10969 self, "updated", isolate->factory()->length_string(), | |
10970 old_length_handle); | |
10971 } | 11039 } |
11040 | |
11041 EnqueueSpliceRecord(self, index, deleted, delete_count, add_count); | |
11042 | |
10972 return *hresult; | 11043 return *hresult; |
10973 } | 11044 } |
10974 | 11045 |
10975 | 11046 |
10976 Map* Map::GetPrototypeTransition(Object* prototype) { | 11047 Map* Map::GetPrototypeTransition(Object* prototype) { |
10977 FixedArray* cache = GetPrototypeTransitions(); | 11048 FixedArray* cache = GetPrototypeTransitions(); |
10978 int number_of_transitions = NumberOfProtoTransitions(); | 11049 int number_of_transitions = NumberOfProtoTransitions(); |
10979 const int proto_offset = | 11050 const int proto_offset = |
10980 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 11051 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
10981 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 11052 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11986 index, value_raw, attributes, strict_mode, check_prototype, set_mode) | 12057 index, value_raw, attributes, strict_mode, check_prototype, set_mode) |
11987 : SetElementWithoutInterceptor( | 12058 : SetElementWithoutInterceptor( |
11988 index, value_raw, attributes, strict_mode, check_prototype, set_mode); | 12059 index, value_raw, attributes, strict_mode, check_prototype, set_mode); |
11989 } | 12060 } |
11990 | 12061 |
11991 // From here on, everything has to be handlified. | 12062 // From here on, everything has to be handlified. |
11992 Handle<JSObject> self(this); | 12063 Handle<JSObject> self(this); |
11993 Handle<Object> value(value_raw, isolate); | 12064 Handle<Object> value(value_raw, isolate); |
11994 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); | 12065 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); |
11995 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 12066 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
11996 Handle<Object> old_length; | 12067 Handle<Object> old_length_handle; |
12068 Handle<Object> new_length_handle; | |
12069 uint32_t old_length = 0; | |
12070 uint32_t new_length = 0; | |
11997 | 12071 |
11998 if (old_attributes != ABSENT) { | 12072 if (old_attributes != ABSENT) { |
11999 if (self->GetLocalElementAccessorPair(index) == NULL) | 12073 if (self->GetLocalElementAccessorPair(index) == NULL) |
12000 old_value = Object::GetElement(self, index); | 12074 old_value = Object::GetElement(self, index); |
12001 } else if (self->IsJSArray()) { | 12075 } else if (self->IsJSArray()) { |
12002 // Store old array length in case adding an element grows the array. | 12076 // Store old array length in case adding an element grows the array. |
12003 old_length = handle(Handle<JSArray>::cast(self)->length(), isolate); | 12077 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate); |
12078 CHECK(old_length_handle->ToArrayIndex(&old_length)); | |
12004 } | 12079 } |
12005 | 12080 |
12006 // Check for lookup interceptor | 12081 // Check for lookup interceptor |
12007 MaybeObject* result = self->HasIndexedInterceptor() | 12082 MaybeObject* result = self->HasIndexedInterceptor() |
12008 ? self->SetElementWithInterceptor( | 12083 ? self->SetElementWithInterceptor( |
12009 index, *value, attributes, strict_mode, check_prototype, set_mode) | 12084 index, *value, attributes, strict_mode, check_prototype, set_mode) |
12010 : self->SetElementWithoutInterceptor( | 12085 : self->SetElementWithoutInterceptor( |
12011 index, *value, attributes, strict_mode, check_prototype, set_mode); | 12086 index, *value, attributes, strict_mode, check_prototype, set_mode); |
12012 | 12087 |
12013 Handle<Object> hresult; | 12088 Handle<Object> hresult; |
12014 if (!result->ToHandle(&hresult, isolate)) return result; | 12089 if (!result->ToHandle(&hresult, isolate)) return result; |
12015 | 12090 |
12016 Handle<String> name = isolate->factory()->Uint32ToString(index); | 12091 Handle<String> name = isolate->factory()->Uint32ToString(index); |
12017 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); | 12092 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); |
12018 if (old_attributes == ABSENT) { | 12093 if (old_attributes == ABSENT) { |
12094 bool array_extended = false; | |
12095 if (self->IsJSArray() && | |
12096 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { | |
12097 array_extended = true; | |
12098 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), | |
12099 isolate); | |
12100 CHECK(new_length_handle->ToArrayIndex(&new_length)); | |
12101 BeginPerformSplice(Handle<JSArray>::cast(self)); | |
12102 } | |
12103 | |
12019 EnqueueChangeRecord(self, "new", name, old_value); | 12104 EnqueueChangeRecord(self, "new", name, old_value); |
12020 if (self->IsJSArray() && | 12105 if (array_extended) { |
12021 !old_length->SameValue(Handle<JSArray>::cast(self)->length())) { | 12106 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(), |
12022 EnqueueChangeRecord( | 12107 old_length_handle); |
12023 self, "updated", isolate->factory()->length_string(), old_length); | 12108 |
12109 EndPerformSplice(Handle<JSArray>::cast(self)); | |
12110 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
12111 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, 0, | |
12112 new_length - old_length); | |
12024 } | 12113 } |
12025 } else if (old_value->IsTheHole()) { | 12114 } else if (old_value->IsTheHole()) { |
12026 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12115 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
12027 } else { | 12116 } else { |
12028 Handle<Object> new_value = Object::GetElement(self, index); | 12117 Handle<Object> new_value = Object::GetElement(self, index); |
12029 bool value_changed = !old_value->SameValue(*new_value); | 12118 bool value_changed = !old_value->SameValue(*new_value); |
12030 if (old_attributes != new_attributes) { | 12119 if (old_attributes != new_attributes) { |
12031 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 12120 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
12032 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12121 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
12033 } else if (value_changed) { | 12122 } else if (value_changed) { |
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15633 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15722 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
15634 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15723 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
15635 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15724 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
15636 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15725 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
15637 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15726 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
15638 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15727 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
15639 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15728 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
15640 } | 15729 } |
15641 | 15730 |
15642 } } // namespace v8::internal | 15731 } } // namespace v8::internal |
OLD | NEW |