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 10924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |