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 | |
10952 | |
10953 static void EndPerformSplice(Handle<JSArray> object) { | |
10954 Isolate* isolate = object->GetIsolate(); | |
10955 HandleScope scope(isolate); | |
10956 Handle<Object> args[] = { object }; | |
10957 | |
10958 bool threw; | |
10959 Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()), | |
10960 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | |
10961 &threw); | |
10962 ASSERT(!threw); | |
10963 } | |
10964 | |
10965 | |
10914 MaybeObject* JSArray::SetElementsLength(Object* len) { | 10966 MaybeObject* JSArray::SetElementsLength(Object* len) { |
10915 // We should never end in here with a pixel or external array. | 10967 // We should never end in here with a pixel or external array. |
10916 ASSERT(AllowsSetElementsLength()); | 10968 ASSERT(AllowsSetElementsLength()); |
10917 if (!(FLAG_harmony_observation && map()->is_observed())) | 10969 if (!(FLAG_harmony_observation && map()->is_observed())) |
10918 return GetElementsAccessor()->SetLength(this, len); | 10970 return GetElementsAccessor()->SetLength(this, len); |
10919 | 10971 |
10920 Isolate* isolate = GetIsolate(); | 10972 Isolate* isolate = GetIsolate(); |
10921 HandleScope scope(isolate); | 10973 HandleScope scope(isolate); |
10922 Handle<JSArray> self(this); | 10974 Handle<JSArray> self(this); |
10923 List<Handle<String> > indices; | 10975 List<uint32_t> indices; |
10924 List<Handle<Object> > old_values; | 10976 List<Handle<Object> > old_values; |
10925 Handle<Object> old_length_handle(self->length(), isolate); | 10977 Handle<Object> old_length_handle(self->length(), isolate); |
10926 Handle<Object> new_length_handle(len, isolate); | 10978 Handle<Object> new_length_handle(len, isolate); |
10927 uint32_t old_length = 0; | 10979 uint32_t old_length = 0; |
10928 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 10980 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
10929 uint32_t new_length = 0; | 10981 uint32_t new_length = 0; |
10930 if (!new_length_handle->ToArrayIndex(&new_length)) | 10982 if (!new_length_handle->ToArrayIndex(&new_length)) |
10931 return Failure::InternalError(); | 10983 return Failure::InternalError(); |
10932 | 10984 |
10933 // Observed arrays should always be in dictionary mode; | 10985 // Observed arrays should always be in dictionary mode; |
(...skipping 19 matching lines...) Expand all Loading... | |
10953 } | 11005 } |
10954 } | 11006 } |
10955 } | 11007 } |
10956 | 11008 |
10957 MaybeObject* result = | 11009 MaybeObject* result = |
10958 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); | 11010 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); |
10959 Handle<Object> hresult; | 11011 Handle<Object> hresult; |
10960 if (!result->ToHandle(&hresult, isolate)) return result; | 11012 if (!result->ToHandle(&hresult, isolate)) return result; |
10961 | 11013 |
10962 CHECK(self->length()->ToArrayIndex(&new_length)); | 11014 CHECK(self->length()->ToArrayIndex(&new_length)); |
10963 if (old_length != new_length) { | 11015 if (old_length == new_length) return *hresult; |
10964 for (int i = 0; i < indices.length(); ++i) { | 11016 |
10965 JSObject::EnqueueChangeRecord( | 11017 BeginPerformSplice(self); |
10966 self, "deleted", indices[i], old_values[i]); | 11018 |
11019 for (int i = 0; i < indices.length(); ++i) { | |
11020 JSObject::EnqueueChangeRecord( | |
11021 self, "deleted", isolate->factory()->Uint32ToString(indices[i]), | |
11022 old_values[i]); | |
11023 } | |
11024 JSObject::EnqueueChangeRecord( | |
11025 self, "updated", isolate->factory()->length_string(), | |
11026 old_length_handle); | |
11027 | |
11028 EndPerformSplice(self); | |
11029 | |
11030 uint32_t index = Min(old_length, new_length); | |
11031 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; | |
rossberg
2013/05/27 14:48:41
Max(new_length - old_length, 0)
rafaelw
2013/05/28 11:38:53
new_length and old_length are both uint so, withou
rossberg
2013/06/04 10:56:58
OK, I see.
| |
11032 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; | |
rossberg
2013/05/27 14:48:41
Max(old_length - new_length, 0)
rafaelw
2013/05/28 11:38:53
Same here.
On 2013/05/27 14:48:41, rossberg wrote
| |
11033 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
11034 if (delete_count) { | |
rossberg
2013/05/27 14:48:41
Nit: delete_count > 0
rafaelw
2013/05/28 11:38:53
Done.
| |
11035 int i = indices.length(); | |
11036 while (i--) { | |
rossberg
2013/05/27 14:48:41
Can we make this a for loop?
rafaelw
2013/05/28 11:38:53
I'm curious why you prefer the for loop, but I've
rossberg
2013/06/04 10:56:58
I'm curious why you're curious. ;) It is just an i
| |
11037 JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE, | |
11038 kNonStrictMode); | |
10967 } | 11039 } |
10968 JSObject::EnqueueChangeRecord( | |
10969 self, "updated", isolate->factory()->length_string(), | |
10970 old_length_handle); | |
10971 } | 11040 } |
11041 | |
11042 EnqueueSpliceRecord(self, index, deleted, delete_count, add_count); | |
11043 | |
10972 return *hresult; | 11044 return *hresult; |
10973 } | 11045 } |
10974 | 11046 |
10975 | 11047 |
10976 Map* Map::GetPrototypeTransition(Object* prototype) { | 11048 Map* Map::GetPrototypeTransition(Object* prototype) { |
10977 FixedArray* cache = GetPrototypeTransitions(); | 11049 FixedArray* cache = GetPrototypeTransitions(); |
10978 int number_of_transitions = NumberOfProtoTransitions(); | 11050 int number_of_transitions = NumberOfProtoTransitions(); |
10979 const int proto_offset = | 11051 const int proto_offset = |
10980 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 11052 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
10981 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 11053 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) | 12058 index, value_raw, attributes, strict_mode, check_prototype, set_mode) |
11987 : SetElementWithoutInterceptor( | 12059 : SetElementWithoutInterceptor( |
11988 index, value_raw, attributes, strict_mode, check_prototype, set_mode); | 12060 index, value_raw, attributes, strict_mode, check_prototype, set_mode); |
11989 } | 12061 } |
11990 | 12062 |
11991 // From here on, everything has to be handlified. | 12063 // From here on, everything has to be handlified. |
11992 Handle<JSObject> self(this); | 12064 Handle<JSObject> self(this); |
11993 Handle<Object> value(value_raw, isolate); | 12065 Handle<Object> value(value_raw, isolate); |
11994 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); | 12066 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); |
11995 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 12067 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
11996 Handle<Object> old_length; | 12068 Handle<Object> old_length_handle; |
12069 Handle<Object> new_length_handle; | |
rossberg
2013/05/27 14:48:41
Move this and new_length into conditional below, t
rafaelw
2013/05/28 11:38:53
Done.
| |
12070 uint32_t old_length = 0; | |
12071 uint32_t new_length = 0; | |
11997 | 12072 |
11998 if (old_attributes != ABSENT) { | 12073 if (old_attributes != ABSENT) { |
11999 if (self->GetLocalElementAccessorPair(index) == NULL) | 12074 if (self->GetLocalElementAccessorPair(index) == NULL) |
12000 old_value = Object::GetElement(self, index); | 12075 old_value = Object::GetElement(self, index); |
12001 } else if (self->IsJSArray()) { | 12076 } else if (self->IsJSArray()) { |
12002 // Store old array length in case adding an element grows the array. | 12077 // Store old array length in case adding an element grows the array. |
12003 old_length = handle(Handle<JSArray>::cast(self)->length(), isolate); | 12078 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate); |
12079 CHECK(old_length_handle->ToArrayIndex(&old_length)); | |
12004 } | 12080 } |
12005 | 12081 |
12006 // Check for lookup interceptor | 12082 // Check for lookup interceptor |
12007 MaybeObject* result = self->HasIndexedInterceptor() | 12083 MaybeObject* result = self->HasIndexedInterceptor() |
12008 ? self->SetElementWithInterceptor( | 12084 ? self->SetElementWithInterceptor( |
12009 index, *value, attributes, strict_mode, check_prototype, set_mode) | 12085 index, *value, attributes, strict_mode, check_prototype, set_mode) |
12010 : self->SetElementWithoutInterceptor( | 12086 : self->SetElementWithoutInterceptor( |
12011 index, *value, attributes, strict_mode, check_prototype, set_mode); | 12087 index, *value, attributes, strict_mode, check_prototype, set_mode); |
12012 | 12088 |
12013 Handle<Object> hresult; | 12089 Handle<Object> hresult; |
12014 if (!result->ToHandle(&hresult, isolate)) return result; | 12090 if (!result->ToHandle(&hresult, isolate)) return result; |
12015 | 12091 |
12016 Handle<String> name = isolate->factory()->Uint32ToString(index); | 12092 Handle<String> name = isolate->factory()->Uint32ToString(index); |
12017 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); | 12093 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); |
12018 if (old_attributes == ABSENT) { | 12094 if (old_attributes == ABSENT) { |
12095 bool array_extended = false; | |
rossberg
2013/05/27 14:48:41
Can we initialize this properly instead of mutatin
rafaelw
2013/05/28 11:38:53
Done.
| |
12096 if (self->IsJSArray() && | |
12097 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { | |
12098 array_extended = true; | |
12099 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), | |
12100 isolate); | |
12101 CHECK(new_length_handle->ToArrayIndex(&new_length)); | |
12102 BeginPerformSplice(Handle<JSArray>::cast(self)); | |
12103 } | |
12104 | |
12019 EnqueueChangeRecord(self, "new", name, old_value); | 12105 EnqueueChangeRecord(self, "new", name, old_value); |
12020 if (self->IsJSArray() && | 12106 if (array_extended) { |
12021 !old_length->SameValue(Handle<JSArray>::cast(self)->length())) { | 12107 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(), |
12022 EnqueueChangeRecord( | 12108 old_length_handle); |
12023 self, "updated", isolate->factory()->length_string(), old_length); | 12109 |
12110 EndPerformSplice(Handle<JSArray>::cast(self)); | |
12111 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
12112 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, 0, | |
12113 new_length - old_length); | |
12024 } | 12114 } |
12025 } else if (old_value->IsTheHole()) { | 12115 } else if (old_value->IsTheHole()) { |
12026 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12116 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
12027 } else { | 12117 } else { |
12028 Handle<Object> new_value = Object::GetElement(self, index); | 12118 Handle<Object> new_value = Object::GetElement(self, index); |
12029 bool value_changed = !old_value->SameValue(*new_value); | 12119 bool value_changed = !old_value->SameValue(*new_value); |
12030 if (old_attributes != new_attributes) { | 12120 if (old_attributes != new_attributes) { |
12031 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 12121 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
12032 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12122 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
12033 } else if (value_changed) { | 12123 } 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); | 15723 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
15634 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15724 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
15635 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15725 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
15636 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15726 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
15637 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15727 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
15638 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15728 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
15639 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15729 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
15640 } | 15730 } |
15641 | 15731 |
15642 } } // namespace v8::internal | 15732 } } // namespace v8::internal |
OLD | NEW |