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

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: cr comments 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
« no previous file with comments | « src/contexts.h ('k') | src/v8natives.js » ('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 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/contexts.h ('k') | src/v8natives.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698