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 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1982 } | 1982 } |
1983 Handle<Object> args[] = { type, object, name, old_value }; | 1983 Handle<Object> args[] = { type, object, name, old_value }; |
1984 bool threw; | 1984 bool threw; |
1985 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()), | 1985 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()), |
1986 isolate->factory()->undefined_value(), | 1986 isolate->factory()->undefined_value(), |
1987 old_value->IsTheHole() ? 3 : 4, args, | 1987 old_value->IsTheHole() ? 3 : 4, args, |
1988 &threw); | 1988 &threw); |
1989 ASSERT(!threw); | 1989 ASSERT(!threw); |
1990 } | 1990 } |
1991 | 1991 |
1992 void JSObject::EnqueueSpliceRecord(Handle<JSObject> object, | |
1993 uint32_t index, | |
adamk
2013/05/20 23:13:13
Nit: indentation seems off here.
rafaelw
2013/05/20 23:52:06
Done.
| |
1994 Handle<JSArray> deleted, | |
1995 uint32_t delete_count, | |
1996 uint32_t add_count) { | |
1997 Isolate* isolate = object->GetIsolate(); | |
1998 HandleScope scope(isolate); | |
1999 if (object->IsJSGlobalObject()) { | |
adamk
2013/05/20 23:13:13
Can this even happen? Do we ever emit splices for
rafaelw
2013/05/20 23:52:06
Replaced with assert.
On 2013/05/20 23:13:13, ada
adamk
2013/05/21 19:11:11
Now that you've added the assert I'm wondering wha
rafaelw
2013/05/23 18:19:58
These only get called from within objects.cc, but
| |
2000 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | |
2001 } | |
2002 | |
2003 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index); | |
2004 Handle<Object> delete_count_object = | |
adamk
2013/05/20 23:13:13
It's not obvious why we need the delete_count here
rafaelw
2013/05/20 23:52:06
You are correct. This is an artifact of having spl
| |
2005 isolate->factory()->NewNumberFromUint(delete_count); | |
2006 Handle<Object> add_count_object = | |
2007 isolate->factory()->NewNumberFromUint(add_count); | |
2008 | |
2009 Handle<Object> args[] = | |
2010 { object, index_object, deleted, delete_count_object, add_count_object }; | |
2011 | |
2012 bool threw; | |
2013 Execution::Call(Handle<JSFunction>(isolate->observers_enqueue_splice()), | |
2014 isolate->factory()->undefined_value(), 5, args, | |
2015 &threw); | |
2016 ASSERT(!threw); | |
2017 } | |
2018 | |
2019 void JSObject::BeginPerformSplice(Handle<JSObject> object) { | |
2020 Isolate* isolate = object->GetIsolate(); | |
2021 HandleScope scope(isolate); | |
2022 if (object->IsJSGlobalObject()) { | |
adamk
2013/05/20 23:13:13
Same question as above, can this happen?
rafaelw
2013/05/20 23:52:06
Done.
| |
2023 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | |
2024 } | |
2025 | |
2026 Handle<Object> args[] = { object }; | |
2027 | |
2028 bool threw; | |
2029 Execution::Call(Handle<JSFunction>(isolate->observers_begin_perform_splice()), | |
2030 isolate->factory()->undefined_value(), 1, args, | |
2031 &threw); | |
2032 ASSERT(!threw); | |
2033 } | |
2034 | |
2035 void JSObject::EndPerformSplice(Handle<JSObject> object) { | |
2036 Isolate* isolate = object->GetIsolate(); | |
2037 HandleScope scope(isolate); | |
2038 if (object->IsJSGlobalObject()) { | |
adamk
2013/05/20 23:13:13
ditto
rafaelw
2013/05/20 23:52:06
Done.
| |
2039 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | |
2040 } | |
2041 | |
2042 Handle<Object> args[] = { object }; | |
2043 | |
2044 bool threw; | |
2045 Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()), | |
2046 isolate->factory()->undefined_value(), 1, args, | |
2047 &threw); | |
2048 ASSERT(!threw); | |
2049 } | |
1992 | 2050 |
1993 void JSObject::DeliverChangeRecords(Isolate* isolate) { | 2051 void JSObject::DeliverChangeRecords(Isolate* isolate) { |
1994 ASSERT(isolate->observer_delivery_pending()); | 2052 ASSERT(isolate->observer_delivery_pending()); |
1995 bool threw = false; | 2053 bool threw = false; |
1996 Execution::Call( | 2054 Execution::Call( |
1997 isolate->observers_deliver_changes(), | 2055 isolate->observers_deliver_changes(), |
1998 isolate->factory()->undefined_value(), | 2056 isolate->factory()->undefined_value(), |
1999 0, | 2057 0, |
2000 NULL, | 2058 NULL, |
2001 &threw); | 2059 &threw); |
(...skipping 8720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10722 MaybeObject* JSArray::SetElementsLength(Object* len) { | 10780 MaybeObject* JSArray::SetElementsLength(Object* len) { |
10723 // We should never end in here with a pixel or external array. | 10781 // We should never end in here with a pixel or external array. |
10724 ASSERT(AllowsSetElementsLength()); | 10782 ASSERT(AllowsSetElementsLength()); |
10725 if (!(FLAG_harmony_observation && map()->is_observed())) | 10783 if (!(FLAG_harmony_observation && map()->is_observed())) |
10726 return GetElementsAccessor()->SetLength(this, len); | 10784 return GetElementsAccessor()->SetLength(this, len); |
10727 | 10785 |
10728 Isolate* isolate = GetIsolate(); | 10786 Isolate* isolate = GetIsolate(); |
10729 HandleScope scope(isolate); | 10787 HandleScope scope(isolate); |
10730 Handle<JSArray> self(this); | 10788 Handle<JSArray> self(this); |
10731 List<Handle<String> > indices; | 10789 List<Handle<String> > indices; |
10790 List<uint32_t> int_indices; | |
10732 List<Handle<Object> > old_values; | 10791 List<Handle<Object> > old_values; |
10733 Handle<Object> old_length_handle(self->length(), isolate); | 10792 Handle<Object> old_length_handle(self->length(), isolate); |
10734 Handle<Object> new_length_handle(len, isolate); | 10793 Handle<Object> new_length_handle(len, isolate); |
10735 uint32_t old_length = 0; | 10794 uint32_t old_length = 0; |
10736 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 10795 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
10737 uint32_t new_length = 0; | 10796 uint32_t new_length = 0; |
10738 if (!new_length_handle->ToArrayIndex(&new_length)) | 10797 if (!new_length_handle->ToArrayIndex(&new_length)) |
10739 return Failure::InternalError(); | 10798 return Failure::InternalError(); |
10740 | 10799 |
10741 // Observed arrays should always be in dictionary mode; | 10800 // Observed arrays should always be in dictionary mode; |
10742 // if they were in fast mode, the below is slower than necessary | 10801 // if they were in fast mode, the below is slower than necessary |
10743 // as it iterates over the array backing store multiple times. | 10802 // as it iterates over the array backing store multiple times. |
10744 ASSERT(self->HasDictionaryElements()); | 10803 ASSERT(self->HasDictionaryElements()); |
10745 static const PropertyAttributes kNoAttrFilter = NONE; | 10804 static const PropertyAttributes kNoAttrFilter = NONE; |
10746 int num_elements = self->NumberOfLocalElements(kNoAttrFilter); | 10805 int num_elements = self->NumberOfLocalElements(kNoAttrFilter); |
10747 if (num_elements > 0) { | 10806 if (num_elements > 0) { |
10748 if (old_length == static_cast<uint32_t>(num_elements)) { | 10807 if (old_length == static_cast<uint32_t>(num_elements)) { |
10749 // Simple case for arrays without holes. | 10808 // Simple case for arrays without holes. |
10750 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { | 10809 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
10751 if (!GetOldValue(isolate, self, i, &old_values, &indices)) break; | 10810 if (!GetOldValue(isolate, self, i, &old_values, &indices)) break; |
10811 int_indices.Add(i); | |
adamk
2013/05/20 23:13:13
It seems odd to keep track of the indices twice. A
rafaelw
2013/05/20 23:52:06
Done.
| |
10752 } | 10812 } |
10753 } else { | 10813 } else { |
10754 // For sparse arrays, only iterate over existing elements. | 10814 // For sparse arrays, only iterate over existing elements. |
10755 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | 10815 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); |
10756 self->GetLocalElementKeys(*keys, kNoAttrFilter); | 10816 self->GetLocalElementKeys(*keys, kNoAttrFilter); |
10757 while (num_elements-- > 0) { | 10817 while (num_elements-- > 0) { |
10758 uint32_t index = NumberToUint32(keys->get(num_elements)); | 10818 uint32_t index = NumberToUint32(keys->get(num_elements)); |
10759 if (index < new_length) break; | 10819 if (index < new_length) break; |
10760 if (!GetOldValue(isolate, self, index, &old_values, &indices)) break; | 10820 if (!GetOldValue(isolate, self, index, &old_values, &indices)) break; |
10821 int_indices.Add(index); | |
10761 } | 10822 } |
10762 } | 10823 } |
10763 } | 10824 } |
10764 | 10825 |
10765 MaybeObject* result = | 10826 MaybeObject* result = |
10766 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); | 10827 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); |
10767 Handle<Object> hresult; | 10828 Handle<Object> hresult; |
10768 if (!result->ToHandle(&hresult, isolate)) return result; | 10829 if (!result->ToHandle(&hresult, isolate)) return result; |
10769 | 10830 |
10770 CHECK(self->length()->ToArrayIndex(&new_length)); | 10831 CHECK(self->length()->ToArrayIndex(&new_length)); |
10771 if (old_length != new_length) { | 10832 if (old_length == new_length) |
10772 for (int i = 0; i < indices.length(); ++i) { | 10833 return *hresult; |
10773 JSObject::EnqueueChangeRecord( | 10834 |
10774 self, "deleted", indices[i], old_values[i]); | 10835 JSObject::BeginPerformSplice(self); |
10775 } | 10836 |
10837 for (int i = 0; i < indices.length(); ++i) { | |
10776 JSObject::EnqueueChangeRecord( | 10838 JSObject::EnqueueChangeRecord( |
10777 self, "updated", isolate->factory()->length_string(), | 10839 self, "deleted", indices[i], old_values[i]); |
10778 old_length_handle); | |
10779 } | 10840 } |
10841 JSObject::EnqueueChangeRecord( | |
10842 self, "updated", isolate->factory()->length_string(), | |
10843 old_length_handle); | |
10844 | |
10845 JSObject::EndPerformSplice(self); | |
10846 | |
10847 uint32_t index = new_length > old_length ? old_length : new_length; | |
10848 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; | |
10849 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; | |
10850 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
10851 if (delete_count) { | |
10852 for (int i = 0; i < int_indices.length(); ++i) | |
10853 JSObject::SetElement(deleted, int_indices[i] - index, old_values[i], | |
10854 NONE, kNonStrictMode); | |
10855 } | |
10856 | |
10857 JSObject::EnqueueSpliceRecord(self, index, deleted, delete_count, add_count); | |
10858 | |
10780 return *hresult; | 10859 return *hresult; |
10781 } | 10860 } |
10782 | 10861 |
10783 | 10862 |
10784 Map* Map::GetPrototypeTransition(Object* prototype) { | 10863 Map* Map::GetPrototypeTransition(Object* prototype) { |
10785 FixedArray* cache = GetPrototypeTransitions(); | 10864 FixedArray* cache = GetPrototypeTransitions(); |
10786 int number_of_transitions = NumberOfProtoTransitions(); | 10865 int number_of_transitions = NumberOfProtoTransitions(); |
10787 const int proto_offset = | 10866 const int proto_offset = |
10788 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 10867 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
10789 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 10868 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11795 index, value_raw, attributes, strict_mode, check_prototype, set_mode) | 11874 index, value_raw, attributes, strict_mode, check_prototype, set_mode) |
11796 : SetElementWithoutInterceptor( | 11875 : SetElementWithoutInterceptor( |
11797 index, value_raw, attributes, strict_mode, check_prototype, set_mode); | 11876 index, value_raw, attributes, strict_mode, check_prototype, set_mode); |
11798 } | 11877 } |
11799 | 11878 |
11800 // From here on, everything has to be handlified. | 11879 // From here on, everything has to be handlified. |
11801 Handle<JSObject> self(this); | 11880 Handle<JSObject> self(this); |
11802 Handle<Object> value(value_raw, isolate); | 11881 Handle<Object> value(value_raw, isolate); |
11803 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); | 11882 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); |
11804 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 11883 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
11805 Handle<Object> old_length; | 11884 Handle<Object> old_length_handle; |
11885 Handle<Object> new_length_handle; | |
11886 uint32_t old_length = 0; | |
11887 uint32_t new_length = 0; | |
11806 | 11888 |
11807 if (old_attributes != ABSENT) { | 11889 if (old_attributes != ABSENT) { |
11808 if (self->GetLocalElementAccessorPair(index) == NULL) | 11890 if (self->GetLocalElementAccessorPair(index) == NULL) |
11809 old_value = Object::GetElement(self, index); | 11891 old_value = Object::GetElement(self, index); |
11810 } else if (self->IsJSArray()) { | 11892 } else if (self->IsJSArray()) { |
11811 // Store old array length in case adding an element grows the array. | 11893 // Store old array length in case adding an element grows the array. |
11812 old_length = handle(Handle<JSArray>::cast(self)->length(), isolate); | 11894 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate); |
11895 CHECK(old_length_handle->ToArrayIndex(&old_length)); | |
11813 } | 11896 } |
11814 | 11897 |
11815 // Check for lookup interceptor | 11898 // Check for lookup interceptor |
11816 MaybeObject* result = self->HasIndexedInterceptor() | 11899 MaybeObject* result = self->HasIndexedInterceptor() |
11817 ? self->SetElementWithInterceptor( | 11900 ? self->SetElementWithInterceptor( |
11818 index, *value, attributes, strict_mode, check_prototype, set_mode) | 11901 index, *value, attributes, strict_mode, check_prototype, set_mode) |
11819 : self->SetElementWithoutInterceptor( | 11902 : self->SetElementWithoutInterceptor( |
11820 index, *value, attributes, strict_mode, check_prototype, set_mode); | 11903 index, *value, attributes, strict_mode, check_prototype, set_mode); |
11821 | 11904 |
11822 Handle<Object> hresult; | 11905 Handle<Object> hresult; |
11823 if (!result->ToHandle(&hresult, isolate)) return result; | 11906 if (!result->ToHandle(&hresult, isolate)) return result; |
11824 | 11907 |
11825 Handle<String> name = isolate->factory()->Uint32ToString(index); | 11908 Handle<String> name = isolate->factory()->Uint32ToString(index); |
11826 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); | 11909 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); |
11827 if (old_attributes == ABSENT) { | 11910 if (old_attributes == ABSENT) { |
11911 bool array_extended = false; | |
11912 if (self->IsJSArray() && | |
11913 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { | |
11914 array_extended = true; | |
11915 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), | |
11916 isolate); | |
11917 CHECK(new_length_handle->ToArrayIndex(&new_length)); | |
11918 JSObject::BeginPerformSplice(self); | |
11919 } | |
11920 | |
11828 EnqueueChangeRecord(self, "new", name, old_value); | 11921 EnqueueChangeRecord(self, "new", name, old_value); |
11829 if (self->IsJSArray() && | 11922 if (array_extended) { |
11830 !old_length->SameValue(Handle<JSArray>::cast(self)->length())) { | 11923 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(), |
11831 EnqueueChangeRecord( | 11924 old_length_handle); |
11832 self, "updated", isolate->factory()->length_string(), old_length); | 11925 |
11926 JSObject::EndPerformSplice(self); | |
11927 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | |
11928 JSObject::EnqueueSpliceRecord(self, old_length, deleted, 0, | |
11929 new_length - old_length); | |
11833 } | 11930 } |
11834 } else if (old_value->IsTheHole()) { | 11931 } else if (old_value->IsTheHole()) { |
11835 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 11932 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
11836 } else { | 11933 } else { |
11837 Handle<Object> new_value = Object::GetElement(self, index); | 11934 Handle<Object> new_value = Object::GetElement(self, index); |
11838 bool value_changed = !old_value->SameValue(*new_value); | 11935 bool value_changed = !old_value->SameValue(*new_value); |
11839 if (old_attributes != new_attributes) { | 11936 if (old_attributes != new_attributes) { |
11840 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 11937 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
11841 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 11938 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
11842 } else if (value_changed) { | 11939 } else if (value_changed) { |
(...skipping 3594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15437 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15534 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
15438 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15535 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
15439 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15536 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
15440 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15537 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
15441 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15538 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
15442 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15539 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
15443 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15540 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
15444 } | 15541 } |
15445 | 15542 |
15446 } } // namespace v8::internal | 15543 } } // namespace v8::internal |
OLD | NEW |