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

Side by Side Diff: src/objects.cc

Issue 15504002: Array.observe emit splices for array length change and update index >= length (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: missed header files (JSArray) Created 7 years, 7 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
OLDNEW
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
1982 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); 1982 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate);
1983 } 1983 }
1984 Handle<Object> args[] = { type, object, name, old_value }; 1984 Handle<Object> args[] = { type, object, name, old_value };
1985 bool threw; 1985 bool threw;
1986 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()), 1986 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()),
1987 isolate->factory()->undefined_value(), 1987 isolate->factory()->undefined_value(),
1988 old_value->IsTheHole() ? 3 : 4, args, 1988 old_value->IsTheHole() ? 3 : 4, args,
1989 &threw); 1989 &threw);
1990 ASSERT(!threw); 1990 ASSERT(!threw);
1991 } 1991 }
1992 1992
adamk 2013/05/24 00:15:30 v8 style nit: need two blank lines between functio
rafaelw 2013/05/24 19:11:43 Done.
1993 void JSObject::EnqueueSpliceRecord(Handle<JSArray> object,
1994 uint32_t index,
1995 Handle<JSArray> deleted,
1996 uint32_t delete_count,
adamk 2013/05/24 00:15:30 I know we discussed this before, but can you avoid
rafaelw 2013/05/24 19:11:43 I've put a todo to go back and remove it. There ar
1997 uint32_t add_count) {
1998 Isolate* isolate = object->GetIsolate();
1999 HandleScope scope(isolate);
2000 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
2001 Handle<Object> delete_count_object =
2002 isolate->factory()->NewNumberFromUint(delete_count);
2003 Handle<Object> add_count_object =
2004 isolate->factory()->NewNumberFromUint(add_count);
2005
2006 Handle<Object> args[] =
2007 { object, index_object, deleted, delete_count_object, add_count_object };
2008
2009 bool threw;
2010 Execution::Call(Handle<JSFunction>(isolate->observers_enqueue_splice()),
2011 isolate->factory()->undefined_value(), 5, args,
adamk 2013/05/24 00:15:30 I'd use ARRAY_SIZE(args) here, and below.
rafaelw 2013/05/24 19:11:43 Done.
2012 &threw);
2013 ASSERT(!threw);
2014 }
2015
adamk 2013/05/24 00:15:30 same whitespace nit, and so on below
rafaelw 2013/05/24 19:11:43 Done.
2016 void JSObject::BeginPerformSplice(Handle<JSArray> object) {
2017 Isolate* isolate = object->GetIsolate();
2018 HandleScope scope(isolate);
2019 Handle<Object> args[] = { object };
2020
2021 bool threw;
2022 Execution::Call(Handle<JSFunction>(isolate->observers_begin_perform_splice()),
2023 isolate->factory()->undefined_value(), 1, args,
2024 &threw);
2025 ASSERT(!threw);
2026 }
2027
2028 void JSObject::EndPerformSplice(Handle<JSArray> object) {
2029 Isolate* isolate = object->GetIsolate();
2030 HandleScope scope(isolate);
2031 Handle<Object> args[] = { object };
2032
2033 bool threw;
2034 Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()),
2035 isolate->factory()->undefined_value(), 1, args,
2036 &threw);
2037 ASSERT(!threw);
2038 }
1993 2039
1994 void JSObject::DeliverChangeRecords(Isolate* isolate) { 2040 void JSObject::DeliverChangeRecords(Isolate* isolate) {
1995 ASSERT(isolate->observer_delivery_pending()); 2041 ASSERT(isolate->observer_delivery_pending());
1996 bool threw = false; 2042 bool threw = false;
1997 Execution::Call( 2043 Execution::Call(
1998 isolate->observers_deliver_changes(), 2044 isolate->observers_deliver_changes(),
1999 isolate->factory()->undefined_value(), 2045 isolate->factory()->undefined_value(),
2000 0, 2046 0,
2001 NULL, 2047 NULL,
2002 &threw); 2048 &threw);
(...skipping 8889 matching lines...) Expand 10 before | Expand all | Expand 10 after
10892 } 10938 }
10893 10939
10894 10940
10895 // Returns false if the passed-in index is marked non-configurable, 10941 // Returns false if the passed-in index is marked non-configurable,
10896 // which will cause the ES5 truncation operation to halt, and thus 10942 // which will cause the ES5 truncation operation to halt, and thus
10897 // no further old values need be collected. 10943 // no further old values need be collected.
10898 static bool GetOldValue(Isolate* isolate, 10944 static bool GetOldValue(Isolate* isolate,
10899 Handle<JSObject> object, 10945 Handle<JSObject> object,
10900 uint32_t index, 10946 uint32_t index,
10901 List<Handle<Object> >* old_values, 10947 List<Handle<Object> >* old_values,
10902 List<Handle<String> >* indices) { 10948 List<uint32_t>* indices) {
10903 PropertyAttributes attributes = object->GetLocalElementAttribute(index); 10949 PropertyAttributes attributes = object->GetLocalElementAttribute(index);
10904 ASSERT(attributes != ABSENT); 10950 ASSERT(attributes != ABSENT);
10905 if (attributes == DONT_DELETE) return false; 10951 if (attributes == DONT_DELETE) return false;
10906 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL 10952 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
10907 ? Object::GetElement(object, index) 10953 ? Object::GetElement(object, index)
10908 : Handle<Object>::cast(isolate->factory()->the_hole_value())); 10954 : Handle<Object>::cast(isolate->factory()->the_hole_value()));
10909 indices->Add(isolate->factory()->Uint32ToString(index)); 10955 indices->Add(index);
10910 return true; 10956 return true;
10911 } 10957 }
10912 10958
10913 10959
10914 MaybeObject* JSArray::SetElementsLength(Object* len) { 10960 MaybeObject* JSArray::SetElementsLength(Object* len) {
10915 // We should never end in here with a pixel or external array. 10961 // We should never end in here with a pixel or external array.
10916 ASSERT(AllowsSetElementsLength()); 10962 ASSERT(AllowsSetElementsLength());
10917 if (!(FLAG_harmony_observation && map()->is_observed())) 10963 if (!(FLAG_harmony_observation && map()->is_observed()))
10918 return GetElementsAccessor()->SetLength(this, len); 10964 return GetElementsAccessor()->SetLength(this, len);
10919 10965
10920 Isolate* isolate = GetIsolate(); 10966 Isolate* isolate = GetIsolate();
10921 HandleScope scope(isolate); 10967 HandleScope scope(isolate);
10922 Handle<JSArray> self(this); 10968 Handle<JSArray> self(this);
10923 List<Handle<String> > indices; 10969 List<uint32_t> indices;
10924 List<Handle<Object> > old_values; 10970 List<Handle<Object> > old_values;
10925 Handle<Object> old_length_handle(self->length(), isolate); 10971 Handle<Object> old_length_handle(self->length(), isolate);
10926 Handle<Object> new_length_handle(len, isolate); 10972 Handle<Object> new_length_handle(len, isolate);
10927 uint32_t old_length = 0; 10973 uint32_t old_length = 0;
10928 CHECK(old_length_handle->ToArrayIndex(&old_length)); 10974 CHECK(old_length_handle->ToArrayIndex(&old_length));
10929 uint32_t new_length = 0; 10975 uint32_t new_length = 0;
10930 if (!new_length_handle->ToArrayIndex(&new_length)) 10976 if (!new_length_handle->ToArrayIndex(&new_length))
10931 return Failure::InternalError(); 10977 return Failure::InternalError();
10932 10978
10933 // Observed arrays should always be in dictionary mode; 10979 // Observed arrays should always be in dictionary mode;
(...skipping 19 matching lines...) Expand all
10953 } 10999 }
10954 } 11000 }
10955 } 11001 }
10956 11002
10957 MaybeObject* result = 11003 MaybeObject* result =
10958 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); 11004 self->GetElementsAccessor()->SetLength(*self, *new_length_handle);
10959 Handle<Object> hresult; 11005 Handle<Object> hresult;
10960 if (!result->ToHandle(&hresult, isolate)) return result; 11006 if (!result->ToHandle(&hresult, isolate)) return result;
10961 11007
10962 CHECK(self->length()->ToArrayIndex(&new_length)); 11008 CHECK(self->length()->ToArrayIndex(&new_length));
10963 if (old_length != new_length) { 11009 if (old_length == new_length)
10964 for (int i = 0; i < indices.length(); ++i) { 11010 return *hresult;
adamk 2013/05/24 00:15:30 v8 style puts this on the previous line
rafaelw 2013/05/24 19:11:43 Done.
10965 JSObject::EnqueueChangeRecord( 11011
10966 self, "deleted", indices[i], old_values[i]); 11012 JSObject::BeginPerformSplice(self);
10967 } 11013
11014 for (int i = 0; i < indices.length(); ++i) {
10968 JSObject::EnqueueChangeRecord( 11015 JSObject::EnqueueChangeRecord(
10969 self, "updated", isolate->factory()->length_string(), 11016 self, "deleted", isolate->factory()->Uint32ToString(indices[i]),
10970 old_length_handle); 11017 old_values[i]);
10971 } 11018 }
11019 JSObject::EnqueueChangeRecord(
11020 self, "updated", isolate->factory()->length_string(),
11021 old_length_handle);
11022
11023 JSObject::EndPerformSplice(self);
11024
11025 uint32_t index = new_length > old_length ? old_length : new_length;
adamk 2013/05/24 00:15:30 this would be slightly more readable as min(old_le
rafaelw 2013/05/24 19:11:43 Done.
11026 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11027 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11028 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11029 if (delete_count) {
11030 for (int i = 0; i < indices.length(); ++i)
adamk 2013/05/24 00:15:30 Note that these indices are in descending order du
rafaelw 2013/05/24 19:11:43 Done.
11031 JSObject::SetElement(deleted, indices[i] - index, old_values[i],
11032 NONE, kNonStrictMode);
11033 }
11034
11035 JSObject::EnqueueSpliceRecord(self, index, deleted, delete_count, add_count);
11036
10972 return *hresult; 11037 return *hresult;
10973 } 11038 }
10974 11039
10975 11040
10976 Map* Map::GetPrototypeTransition(Object* prototype) { 11041 Map* Map::GetPrototypeTransition(Object* prototype) {
10977 FixedArray* cache = GetPrototypeTransitions(); 11042 FixedArray* cache = GetPrototypeTransitions();
10978 int number_of_transitions = NumberOfProtoTransitions(); 11043 int number_of_transitions = NumberOfProtoTransitions();
10979 const int proto_offset = 11044 const int proto_offset =
10980 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; 11045 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
10981 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; 11046 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after
11986 index, value_raw, attributes, strict_mode, check_prototype, set_mode) 12051 index, value_raw, attributes, strict_mode, check_prototype, set_mode)
11987 : SetElementWithoutInterceptor( 12052 : SetElementWithoutInterceptor(
11988 index, value_raw, attributes, strict_mode, check_prototype, set_mode); 12053 index, value_raw, attributes, strict_mode, check_prototype, set_mode);
11989 } 12054 }
11990 12055
11991 // From here on, everything has to be handlified. 12056 // From here on, everything has to be handlified.
11992 Handle<JSObject> self(this); 12057 Handle<JSObject> self(this);
11993 Handle<Object> value(value_raw, isolate); 12058 Handle<Object> value(value_raw, isolate);
11994 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); 12059 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index);
11995 Handle<Object> old_value = isolate->factory()->the_hole_value(); 12060 Handle<Object> old_value = isolate->factory()->the_hole_value();
11996 Handle<Object> old_length; 12061 Handle<Object> old_length_handle;
12062 Handle<Object> new_length_handle;
12063 uint32_t old_length = 0;
12064 uint32_t new_length = 0;
11997 12065
11998 if (old_attributes != ABSENT) { 12066 if (old_attributes != ABSENT) {
11999 if (self->GetLocalElementAccessorPair(index) == NULL) 12067 if (self->GetLocalElementAccessorPair(index) == NULL)
12000 old_value = Object::GetElement(self, index); 12068 old_value = Object::GetElement(self, index);
12001 } else if (self->IsJSArray()) { 12069 } else if (self->IsJSArray()) {
12002 // Store old array length in case adding an element grows the array. 12070 // Store old array length in case adding an element grows the array.
12003 old_length = handle(Handle<JSArray>::cast(self)->length(), isolate); 12071 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate);
12072 CHECK(old_length_handle->ToArrayIndex(&old_length));
12004 } 12073 }
12005 12074
12006 // Check for lookup interceptor 12075 // Check for lookup interceptor
12007 MaybeObject* result = self->HasIndexedInterceptor() 12076 MaybeObject* result = self->HasIndexedInterceptor()
12008 ? self->SetElementWithInterceptor( 12077 ? self->SetElementWithInterceptor(
12009 index, *value, attributes, strict_mode, check_prototype, set_mode) 12078 index, *value, attributes, strict_mode, check_prototype, set_mode)
12010 : self->SetElementWithoutInterceptor( 12079 : self->SetElementWithoutInterceptor(
12011 index, *value, attributes, strict_mode, check_prototype, set_mode); 12080 index, *value, attributes, strict_mode, check_prototype, set_mode);
12012 12081
12013 Handle<Object> hresult; 12082 Handle<Object> hresult;
12014 if (!result->ToHandle(&hresult, isolate)) return result; 12083 if (!result->ToHandle(&hresult, isolate)) return result;
12015 12084
12016 Handle<String> name = isolate->factory()->Uint32ToString(index); 12085 Handle<String> name = isolate->factory()->Uint32ToString(index);
12017 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); 12086 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index);
12018 if (old_attributes == ABSENT) { 12087 if (old_attributes == ABSENT) {
12088 bool array_extended = false;
12089 if (self->IsJSArray() &&
12090 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) {
12091 array_extended = true;
12092 new_length_handle = handle(Handle<JSArray>::cast(self)->length(),
12093 isolate);
12094 CHECK(new_length_handle->ToArrayIndex(&new_length));
adamk 2013/05/24 00:15:30 We should really find a better way to avoid droppi
12095 JSObject::BeginPerformSplice(Handle<JSArray>::cast(self));
12096 }
12097
12019 EnqueueChangeRecord(self, "new", name, old_value); 12098 EnqueueChangeRecord(self, "new", name, old_value);
12020 if (self->IsJSArray() && 12099 if (array_extended) {
12021 !old_length->SameValue(Handle<JSArray>::cast(self)->length())) { 12100 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(),
12022 EnqueueChangeRecord( 12101 old_length_handle);
12023 self, "updated", isolate->factory()->length_string(), old_length); 12102
12103 JSObject::EndPerformSplice(Handle<JSArray>::cast(self));
12104 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12105 JSObject::EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length,
12106 deleted,
12107 0,
12108 new_length - old_length);
12024 } 12109 }
12025 } else if (old_value->IsTheHole()) { 12110 } else if (old_value->IsTheHole()) {
12026 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12111 EnqueueChangeRecord(self, "reconfigured", name, old_value);
12027 } else { 12112 } else {
12028 Handle<Object> new_value = Object::GetElement(self, index); 12113 Handle<Object> new_value = Object::GetElement(self, index);
12029 bool value_changed = !old_value->SameValue(*new_value); 12114 bool value_changed = !old_value->SameValue(*new_value);
12030 if (old_attributes != new_attributes) { 12115 if (old_attributes != new_attributes) {
12031 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 12116 if (!value_changed) old_value = isolate->factory()->the_hole_value();
12032 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12117 EnqueueChangeRecord(self, "reconfigured", name, old_value);
12033 } else if (value_changed) { 12118 } else if (value_changed) {
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after
15633 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 15718 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15634 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 15719 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15635 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 15720 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15636 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 15721 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15637 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 15722 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15638 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 15723 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15639 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 15724 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15640 } 15725 }
15641 15726
15642 } } // namespace v8::internal 15727 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/v8natives.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698