Chromium Code Reviews| 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 |