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

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, 6 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 10924 matching lines...) Expand 10 before | Expand all | Expand 10 after
10935 } 10935 }
10936 10936
10937 10937
10938 // Returns false if the passed-in index is marked non-configurable, 10938 // Returns false if the passed-in index is marked non-configurable,
10939 // which will cause the ES5 truncation operation to halt, and thus 10939 // which will cause the ES5 truncation operation to halt, and thus
10940 // no further old values need be collected. 10940 // no further old values need be collected.
10941 static bool GetOldValue(Isolate* isolate, 10941 static bool GetOldValue(Isolate* isolate,
10942 Handle<JSObject> object, 10942 Handle<JSObject> object,
10943 uint32_t index, 10943 uint32_t index,
10944 List<Handle<Object> >* old_values, 10944 List<Handle<Object> >* old_values,
10945 List<Handle<String> >* indices) { 10945 List<uint32_t>* indices) {
10946 PropertyAttributes attributes = object->GetLocalElementAttribute(index); 10946 PropertyAttributes attributes = object->GetLocalElementAttribute(index);
10947 ASSERT(attributes != ABSENT); 10947 ASSERT(attributes != ABSENT);
10948 if (attributes == DONT_DELETE) return false; 10948 if (attributes == DONT_DELETE) return false;
10949 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL 10949 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
10950 ? Object::GetElement(object, index) 10950 ? Object::GetElement(object, index)
10951 : Handle<Object>::cast(isolate->factory()->the_hole_value())); 10951 : Handle<Object>::cast(isolate->factory()->the_hole_value()));
10952 indices->Add(isolate->factory()->Uint32ToString(index)); 10952 indices->Add(index);
10953 return true; 10953 return true;
10954 } 10954 }
10955 10955
10956 10956
10957 // TODO(rafaelw): Remove |delete_count| argument and rely on the length of
10958 // of |deleted|.
10959 static void EnqueueSpliceRecord(Handle<JSArray> object,
10960 uint32_t index,
10961 Handle<JSArray> deleted,
10962 uint32_t delete_count,
10963 uint32_t add_count) {
10964 Isolate* isolate = object->GetIsolate();
10965 HandleScope scope(isolate);
10966 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
10967 Handle<Object> delete_count_object =
10968 isolate->factory()->NewNumberFromUint(delete_count);
10969 Handle<Object> add_count_object =
10970 isolate->factory()->NewNumberFromUint(add_count);
10971
10972 Handle<Object> args[] =
10973 { object, index_object, deleted, delete_count_object, add_count_object };
10974
10975 bool threw;
10976 Execution::Call(Handle<JSFunction>(isolate->observers_enqueue_splice()),
10977 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
10978 &threw);
10979 ASSERT(!threw);
10980 }
10981
10982
10983 static void BeginPerformSplice(Handle<JSArray> object) {
10984 Isolate* isolate = object->GetIsolate();
10985 HandleScope scope(isolate);
10986 Handle<Object> args[] = { object };
10987
10988 bool threw;
10989 Execution::Call(Handle<JSFunction>(isolate->observers_begin_perform_splice()),
10990 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
10991 &threw);
10992 ASSERT(!threw);
10993 }
10994
10995
10996 static void EndPerformSplice(Handle<JSArray> object) {
10997 Isolate* isolate = object->GetIsolate();
10998 HandleScope scope(isolate);
10999 Handle<Object> args[] = { object };
11000
11001 bool threw;
11002 Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()),
11003 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
11004 &threw);
11005 ASSERT(!threw);
11006 }
11007
11008
10957 MaybeObject* JSArray::SetElementsLength(Object* len) { 11009 MaybeObject* JSArray::SetElementsLength(Object* len) {
10958 // We should never end in here with a pixel or external array. 11010 // We should never end in here with a pixel or external array.
10959 ASSERT(AllowsSetElementsLength()); 11011 ASSERT(AllowsSetElementsLength());
10960 if (!(FLAG_harmony_observation && map()->is_observed())) 11012 if (!(FLAG_harmony_observation && map()->is_observed()))
10961 return GetElementsAccessor()->SetLength(this, len); 11013 return GetElementsAccessor()->SetLength(this, len);
10962 11014
10963 Isolate* isolate = GetIsolate(); 11015 Isolate* isolate = GetIsolate();
10964 HandleScope scope(isolate); 11016 HandleScope scope(isolate);
10965 Handle<JSArray> self(this); 11017 Handle<JSArray> self(this);
10966 List<Handle<String> > indices; 11018 List<uint32_t> indices;
10967 List<Handle<Object> > old_values; 11019 List<Handle<Object> > old_values;
10968 Handle<Object> old_length_handle(self->length(), isolate); 11020 Handle<Object> old_length_handle(self->length(), isolate);
10969 Handle<Object> new_length_handle(len, isolate); 11021 Handle<Object> new_length_handle(len, isolate);
10970 uint32_t old_length = 0; 11022 uint32_t old_length = 0;
10971 CHECK(old_length_handle->ToArrayIndex(&old_length)); 11023 CHECK(old_length_handle->ToArrayIndex(&old_length));
10972 uint32_t new_length = 0; 11024 uint32_t new_length = 0;
10973 if (!new_length_handle->ToArrayIndex(&new_length)) 11025 if (!new_length_handle->ToArrayIndex(&new_length))
10974 return Failure::InternalError(); 11026 return Failure::InternalError();
10975 11027
10976 // Observed arrays should always be in dictionary mode; 11028 // Observed arrays should always be in dictionary mode;
(...skipping 19 matching lines...) Expand all
10996 } 11048 }
10997 } 11049 }
10998 } 11050 }
10999 11051
11000 MaybeObject* result = 11052 MaybeObject* result =
11001 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); 11053 self->GetElementsAccessor()->SetLength(*self, *new_length_handle);
11002 Handle<Object> hresult; 11054 Handle<Object> hresult;
11003 if (!result->ToHandle(&hresult, isolate)) return result; 11055 if (!result->ToHandle(&hresult, isolate)) return result;
11004 11056
11005 CHECK(self->length()->ToArrayIndex(&new_length)); 11057 CHECK(self->length()->ToArrayIndex(&new_length));
11006 if (old_length != new_length) { 11058 if (old_length == new_length) return *hresult;
11007 for (int i = 0; i < indices.length(); ++i) { 11059
11008 JSObject::EnqueueChangeRecord( 11060 BeginPerformSplice(self);
11009 self, "deleted", indices[i], old_values[i]); 11061
11062 for (int i = 0; i < indices.length(); ++i) {
11063 JSObject::EnqueueChangeRecord(
11064 self, "deleted", isolate->factory()->Uint32ToString(indices[i]),
11065 old_values[i]);
11066 }
11067 JSObject::EnqueueChangeRecord(
11068 self, "updated", isolate->factory()->length_string(),
11069 old_length_handle);
11070
11071 EndPerformSplice(self);
11072
11073 uint32_t index = Min(old_length, new_length);
11074 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11075 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11076 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11077 if (delete_count) {
11078 for (int i = indices.length() - 1; i >= 0; i--) {
11079 JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE,
11080 kNonStrictMode);
11010 } 11081 }
11011 JSObject::EnqueueChangeRecord(
11012 self, "updated", isolate->factory()->length_string(),
11013 old_length_handle);
11014 } 11082 }
11083
11084 EnqueueSpliceRecord(self, index, deleted, delete_count, add_count);
11085
11015 return *hresult; 11086 return *hresult;
11016 } 11087 }
11017 11088
11018 11089
11019 Map* Map::GetPrototypeTransition(Object* prototype) { 11090 Map* Map::GetPrototypeTransition(Object* prototype) {
11020 FixedArray* cache = GetPrototypeTransitions(); 11091 FixedArray* cache = GetPrototypeTransitions();
11021 int number_of_transitions = NumberOfProtoTransitions(); 11092 int number_of_transitions = NumberOfProtoTransitions();
11022 const int proto_offset = 11093 const int proto_offset =
11023 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; 11094 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
11024 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; 11095 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after
12030 index, value_raw, attributes, strict_mode, check_prototype, set_mode) 12101 index, value_raw, attributes, strict_mode, check_prototype, set_mode)
12031 : SetElementWithoutInterceptor( 12102 : SetElementWithoutInterceptor(
12032 index, value_raw, attributes, strict_mode, check_prototype, set_mode); 12103 index, value_raw, attributes, strict_mode, check_prototype, set_mode);
12033 } 12104 }
12034 12105
12035 // From here on, everything has to be handlified. 12106 // From here on, everything has to be handlified.
12036 Handle<JSObject> self(this); 12107 Handle<JSObject> self(this);
12037 Handle<Object> value(value_raw, isolate); 12108 Handle<Object> value(value_raw, isolate);
12038 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); 12109 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index);
12039 Handle<Object> old_value = isolate->factory()->the_hole_value(); 12110 Handle<Object> old_value = isolate->factory()->the_hole_value();
12040 Handle<Object> old_length; 12111 Handle<Object> old_length_handle;
12112 Handle<Object> new_length_handle;
12041 12113
12042 if (old_attributes != ABSENT) { 12114 if (old_attributes != ABSENT) {
12043 if (self->GetLocalElementAccessorPair(index) == NULL) 12115 if (self->GetLocalElementAccessorPair(index) == NULL)
12044 old_value = Object::GetElement(self, index); 12116 old_value = Object::GetElement(self, index);
12045 } else if (self->IsJSArray()) { 12117 } else if (self->IsJSArray()) {
12046 // Store old array length in case adding an element grows the array. 12118 // Store old array length in case adding an element grows the array.
12047 old_length = handle(Handle<JSArray>::cast(self)->length(), isolate); 12119 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate);
12048 } 12120 }
12049 12121
12050 // Check for lookup interceptor 12122 // Check for lookup interceptor
12051 MaybeObject* result = self->HasIndexedInterceptor() 12123 MaybeObject* result = self->HasIndexedInterceptor()
12052 ? self->SetElementWithInterceptor( 12124 ? self->SetElementWithInterceptor(
12053 index, *value, attributes, strict_mode, check_prototype, set_mode) 12125 index, *value, attributes, strict_mode, check_prototype, set_mode)
12054 : self->SetElementWithoutInterceptor( 12126 : self->SetElementWithoutInterceptor(
12055 index, *value, attributes, strict_mode, check_prototype, set_mode); 12127 index, *value, attributes, strict_mode, check_prototype, set_mode);
12056 12128
12057 Handle<Object> hresult; 12129 Handle<Object> hresult;
12058 if (!result->ToHandle(&hresult, isolate)) return result; 12130 if (!result->ToHandle(&hresult, isolate)) return result;
12059 12131
12060 Handle<String> name = isolate->factory()->Uint32ToString(index); 12132 Handle<String> name = isolate->factory()->Uint32ToString(index);
12061 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); 12133 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index);
12062 if (old_attributes == ABSENT) { 12134 if (old_attributes == ABSENT) {
12063 EnqueueChangeRecord(self, "new", name, old_value);
12064 if (self->IsJSArray() && 12135 if (self->IsJSArray() &&
12065 !old_length->SameValue(Handle<JSArray>::cast(self)->length())) { 12136 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) {
12066 EnqueueChangeRecord( 12137 new_length_handle = handle(Handle<JSArray>::cast(self)->length(),
12067 self, "updated", isolate->factory()->length_string(), old_length); 12138 isolate);
12139 uint32_t old_length = 0;
12140 uint32_t new_length = 0;
12141 CHECK(old_length_handle->ToArrayIndex(&old_length));
12142 CHECK(new_length_handle->ToArrayIndex(&new_length));
12143
12144 BeginPerformSplice(Handle<JSArray>::cast(self));
12145 EnqueueChangeRecord(self, "new", name, old_value);
12146 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(),
12147 old_length_handle);
12148 EndPerformSplice(Handle<JSArray>::cast(self));
12149 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12150 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, 0,
12151 new_length - old_length);
12152 } else {
12153 EnqueueChangeRecord(self, "new", name, old_value);
12068 } 12154 }
12069 } else if (old_value->IsTheHole()) { 12155 } else if (old_value->IsTheHole()) {
12070 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12156 EnqueueChangeRecord(self, "reconfigured", name, old_value);
12071 } else { 12157 } else {
12072 Handle<Object> new_value = Object::GetElement(self, index); 12158 Handle<Object> new_value = Object::GetElement(self, index);
12073 bool value_changed = !old_value->SameValue(*new_value); 12159 bool value_changed = !old_value->SameValue(*new_value);
12074 if (old_attributes != new_attributes) { 12160 if (old_attributes != new_attributes) {
12075 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 12161 if (!value_changed) old_value = isolate->factory()->the_hole_value();
12076 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12162 EnqueueChangeRecord(self, "reconfigured", name, old_value);
12077 } else if (value_changed) { 12163 } else if (value_changed) {
(...skipping 3602 matching lines...) Expand 10 before | Expand all | Expand 10 after
15680 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 15766 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15681 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 15767 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15682 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 15768 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15683 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 15769 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15684 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 15770 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15685 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 15771 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15686 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 15772 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15687 } 15773 }
15688 15774
15689 } } // namespace v8::internal 15775 } } // 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