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

Side by Side Diff: src/elements.cc

Issue 1218813012: Cleanup Delete backend implementation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years, 5 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
« no previous file with comments | « src/elements.h ('k') | src/lookup.h » ('j') | src/lookup.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions.h" 8 #include "src/conversions.h"
9 #include "src/elements.h" 9 #include "src/elements.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements, 724 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements,
725 to_kind, elements); 725 to_kind, elements);
726 } 726 }
727 } 727 }
728 728
729 virtual void GrowCapacityAndConvert(Handle<JSObject> object, 729 virtual void GrowCapacityAndConvert(Handle<JSObject> object,
730 uint32_t capacity) final { 730 uint32_t capacity) final {
731 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity); 731 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity);
732 } 732 }
733 733
734 virtual void Delete(Handle<JSObject> obj, uint32_t key, 734 virtual void Delete(Handle<JSObject> obj, uint32_t index) override = 0;
735 LanguageMode language_mode) override = 0;
736 735
737 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 736 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
738 FixedArrayBase* to, ElementsKind from_kind, 737 FixedArrayBase* to, ElementsKind from_kind,
739 uint32_t to_start, int packed_size, 738 uint32_t to_start, int packed_size,
740 int copy_size) { 739 int copy_size) {
741 UNREACHABLE(); 740 UNREACHABLE();
742 } 741 }
743 742
744 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start, 743 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start,
745 ElementsKind from_kind, Handle<FixedArrayBase> to, 744 ElementsKind from_kind, Handle<FixedArrayBase> to,
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 981 }
983 982
984 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 983 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
985 FixedArrayBase* to, ElementsKind from_kind, 984 FixedArrayBase* to, ElementsKind from_kind,
986 uint32_t to_start, int packed_size, 985 uint32_t to_start, int packed_size,
987 int copy_size) { 986 int copy_size) {
988 UNREACHABLE(); 987 UNREACHABLE();
989 } 988 }
990 989
991 990
992 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, 991 static void DeleteImpl(Handle<JSObject> obj, uint32_t index,
993 LanguageMode language_mode) { 992 Handle<FixedArrayBase> store) {
994 Isolate* isolate = obj->GetIsolate(); 993 Handle<SeededNumberDictionary> dict =
995 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), 994 Handle<SeededNumberDictionary>::cast(store);
996 isolate); 995 // TODO(verwaest): Remove reliance on key in Shrink.
997 bool is_arguments = obj->HasSloppyArgumentsElements(); 996 uint32_t key = GetKeyForIndexImpl(*dict, index);
998 if (is_arguments) { 997 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, index);
999 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); 998 USE(result);
1000 } 999 DCHECK(result->IsTrue());
1001 Handle<SeededNumberDictionary> dictionary = 1000 Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict, key);
1002 Handle<SeededNumberDictionary>::cast(backing_store);
1003 int entry = dictionary->FindEntry(key);
1004 if (entry != SeededNumberDictionary::kNotFound) {
1005 Handle<Object> result =
1006 SeededNumberDictionary::DeleteProperty(dictionary, entry);
1007 USE(result);
1008 DCHECK(result->IsTrue());
1009 Handle<FixedArray> new_elements =
1010 SeededNumberDictionary::Shrink(dictionary, key);
1011 1001
1012 if (is_arguments) { 1002 if (obj->elements() != *store) {
Igor Sheludko 2015/07/03 15:09:01 It looks like you can do the same trick to unify A
1013 FixedArray::cast(obj->elements())->set(1, *new_elements); 1003 DCHECK(obj->HasSlowArgumentsElements());
1014 } else { 1004 FixedArray::cast(obj->elements())->set(1, *new_elements);
1015 obj->set_elements(*new_elements); 1005 } else {
1016 } 1006 obj->set_elements(*new_elements);
1017 } 1007 }
1018 } 1008 }
1019 1009
1020 virtual void Delete(Handle<JSObject> obj, uint32_t key, 1010 virtual void Delete(Handle<JSObject> obj, uint32_t index) final {
Igor Sheludko 2015/07/03 15:09:01 Could you please move this virtual Delete() implem
1021 LanguageMode language_mode) final { 1011 DeleteImpl(obj, index, handle(obj->elements()));
1022 DeleteCommon(obj, key, language_mode);
1023 } 1012 }
1024 1013
1025 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, 1014 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
1026 Handle<FixedArrayBase> store) { 1015 Handle<FixedArrayBase> store) {
1027 Handle<SeededNumberDictionary> backing_store = 1016 Handle<SeededNumberDictionary> backing_store =
1028 Handle<SeededNumberDictionary>::cast(store); 1017 Handle<SeededNumberDictionary>::cast(store);
1029 Isolate* isolate = backing_store->GetIsolate(); 1018 Isolate* isolate = backing_store->GetIsolate();
1030 int entry = backing_store->FindEntry(key); 1019 int entry = backing_store->FindEntry(key);
1031 if (entry != SeededNumberDictionary::kNotFound) { 1020 if (entry != SeededNumberDictionary::kNotFound) {
1032 return handle(backing_store->ValueAt(entry), isolate); 1021 return handle(backing_store->ValueAt(entry), isolate);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 typename KindTraits> 1109 typename KindTraits>
1121 class FastElementsAccessor 1110 class FastElementsAccessor
1122 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { 1111 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
1123 public: 1112 public:
1124 explicit FastElementsAccessor(const char* name) 1113 explicit FastElementsAccessor(const char* name)
1125 : ElementsAccessorBase<FastElementsAccessorSubclass, 1114 : ElementsAccessorBase<FastElementsAccessorSubclass,
1126 KindTraits>(name) {} 1115 KindTraits>(name) {}
1127 1116
1128 typedef typename KindTraits::BackingStore BackingStore; 1117 typedef typename KindTraits::BackingStore BackingStore;
1129 1118
1130 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, 1119 static void DeleteImpl(Handle<JSObject> obj, uint32_t index,
1131 LanguageMode language_mode) { 1120 Handle<FixedArrayBase> store) {
1132 DCHECK(obj->HasFastSmiOrObjectElements() || 1121 DCHECK(obj->HasFastSmiOrObjectElements() ||
1133 obj->HasFastDoubleElements() || 1122 obj->HasFastDoubleElements() ||
1134 obj->HasFastArgumentsElements()); 1123 obj->HasFastArgumentsElements());
1135 Isolate* isolate = obj->GetIsolate(); 1124 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store);
1136 Heap* heap = obj->GetHeap(); 1125 backing_store->set_the_hole(index);
1137 Handle<FixedArrayBase> elements(obj->elements());
1138 if (*elements == heap->empty_fixed_array()) return;
1139 1126
1140 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements); 1127 // TODO(verwaest): Move this out of elements.cc.
1141 bool is_sloppy_arguments_elements_map = 1128 // If an old space backing store is larger than a certain size and
1142 backing_store->map() == heap->sloppy_arguments_elements_map(); 1129 // has too few used values, normalize it.
1143 if (is_sloppy_arguments_elements_map) { 1130 // To avoid doing the check on every delete we require at least
1144 backing_store = handle( 1131 // one adjacent hole to the value being deleted.
1145 BackingStore::cast(Handle<FixedArray>::cast(backing_store)->get(1)), 1132 const int kMinLengthForSparsenessCheck = 64;
1146 isolate); 1133 if (backing_store->length() < kMinLengthForSparsenessCheck) return;
1134 if (backing_store->GetHeap()->InNewSpace(*backing_store)) return;
1135 uint32_t length = 0;
1136 if (obj->IsJSArray()) {
1137 JSArray::cast(*obj)->length()->ToArrayLength(&length);
1138 } else {
1139 length = static_cast<uint32_t>(store->length());
1147 } 1140 }
1148 uint32_t length = static_cast<uint32_t>( 1141 if ((index > 0 && backing_store->is_the_hole(index - 1)) ||
1149 obj->IsJSArray() 1142 (index + 1 < length && backing_store->is_the_hole(index + 1))) {
1150 ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value() 1143 int num_used = 0;
1151 : backing_store->length()); 1144 for (int i = 0; i < backing_store->length(); ++i) {
1152 if (key < length) { 1145 if (!backing_store->is_the_hole(i)) ++num_used;
1153 if (!is_sloppy_arguments_elements_map) { 1146 // Bail out early if more than 1/4 is used.
1154 ElementsKind kind = KindTraits::Kind; 1147 if (4 * num_used > backing_store->length()) break;
1155 if (IsFastPackedElementsKind(kind)) {
1156 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
1157 }
1158 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
1159 Handle<Object> writable = JSObject::EnsureWritableFastElements(obj);
1160 backing_store = Handle<BackingStore>::cast(writable);
1161 }
1162 } 1148 }
1163 backing_store->set_the_hole(key); 1149 if (4 * num_used <= backing_store->length()) {
1164 // If an old space backing store is larger than a certain size and 1150 JSObject::NormalizeElements(obj);
1165 // has too few used values, normalize it.
1166 // To avoid doing the check on every delete we require at least
1167 // one adjacent hole to the value being deleted.
1168 const int kMinLengthForSparsenessCheck = 64;
1169 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
1170 !heap->InNewSpace(*backing_store) &&
1171 ((key > 0 && backing_store->is_the_hole(key - 1)) ||
1172 (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
1173 int num_used = 0;
1174 for (int i = 0; i < backing_store->length(); ++i) {
1175 if (!backing_store->is_the_hole(i)) ++num_used;
1176 // Bail out early if more than 1/4 is used.
1177 if (4 * num_used > backing_store->length()) break;
1178 }
1179 if (4 * num_used <= backing_store->length()) {
1180 JSObject::NormalizeElements(obj);
1181 }
1182 } 1151 }
1183 } 1152 }
1184 } 1153 }
1185 1154
1186 static void ReconfigureImpl(Handle<JSObject> object, 1155 static void ReconfigureImpl(Handle<JSObject> object,
1187 Handle<FixedArrayBase> store, uint32_t index, 1156 Handle<FixedArrayBase> store, uint32_t index,
1188 Handle<Object> value, 1157 Handle<Object> value,
1189 PropertyAttributes attributes) { 1158 PropertyAttributes attributes) {
1190 Handle<SeededNumberDictionary> dictionary = 1159 Handle<SeededNumberDictionary> dictionary =
1191 JSObject::NormalizeElements(object); 1160 JSObject::NormalizeElements(object);
(...skipping 20 matching lines...) Expand all
1212 JSObject::TransitionElementsKind(object, to_kind); 1181 JSObject::TransitionElementsKind(object, to_kind);
1213 } 1182 }
1214 if (IsFastSmiOrObjectElementsKind(from_kind)) { 1183 if (IsFastSmiOrObjectElementsKind(from_kind)) {
1215 DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); 1184 DCHECK(IsFastSmiOrObjectElementsKind(to_kind));
1216 JSObject::EnsureWritableFastElements(object); 1185 JSObject::EnsureWritableFastElements(object);
1217 } 1186 }
1218 } 1187 }
1219 FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value); 1188 FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value);
1220 } 1189 }
1221 1190
1222 virtual void Delete(Handle<JSObject> obj, uint32_t key, 1191 virtual void Delete(Handle<JSObject> obj, uint32_t index) final {
1223 LanguageMode language_mode) final { 1192 ElementsKind kind = KindTraits::Kind;
1224 DeleteCommon(obj, key, language_mode); 1193 if (IsFastPackedElementsKind(kind)) {
1194 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
1195 }
1196 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
1197 JSObject::EnsureWritableFastElements(obj);
1198 }
1199 DeleteImpl(obj, index, handle(obj->elements()));
1225 } 1200 }
1226 1201
1227 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) { 1202 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) {
1228 return !BackingStore::cast(backing_store)->is_the_hole(index); 1203 return !BackingStore::cast(backing_store)->is_the_hole(index);
1229 } 1204 }
1230 1205
1231 static void ValidateContents(Handle<JSObject> holder, int length) { 1206 static void ValidateContents(Handle<JSObject> holder, int length) {
1232 #if DEBUG 1207 #if DEBUG
1233 Isolate* isolate = holder->GetIsolate(); 1208 Isolate* isolate = holder->GetIsolate();
1234 HandleScope scope(isolate); 1209 HandleScope scope(isolate);
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 uint32_t index) { 1430 uint32_t index) {
1456 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); 1431 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell);
1457 } 1432 }
1458 1433
1459 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, 1434 static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
1460 Handle<FixedArrayBase> backing_store) { 1435 Handle<FixedArrayBase> backing_store) {
1461 // External arrays do not support changing their length. 1436 // External arrays do not support changing their length.
1462 UNREACHABLE(); 1437 UNREACHABLE();
1463 } 1438 }
1464 1439
1465 virtual void Delete(Handle<JSObject> obj, uint32_t key, 1440 virtual void Delete(Handle<JSObject> obj, uint32_t index) final {
1466 LanguageMode language_mode) final { 1441 UNREACHABLE();
1467 // External arrays always ignore deletes.
1468 } 1442 }
1469 1443
1470 static uint32_t GetIndexForKeyImpl(JSObject* holder, 1444 static uint32_t GetIndexForKeyImpl(JSObject* holder,
1471 FixedArrayBase* backing_store, 1445 FixedArrayBase* backing_store,
1472 uint32_t key) { 1446 uint32_t key) {
1473 return key < AccessorClass::GetCapacityImpl(holder, backing_store) 1447 return key < AccessorClass::GetCapacityImpl(holder, backing_store)
1474 ? key 1448 ? key
1475 : kMaxUInt32; 1449 : kMaxUInt32;
1476 } 1450 }
1477 1451
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 Context* context = Context::cast(parameter_map->get(0)); 1507 Context* context = Context::cast(parameter_map->get(0));
1534 int context_index = entry->aliased_context_slot(); 1508 int context_index = entry->aliased_context_slot();
1535 DCHECK(!context->get(context_index)->IsTheHole()); 1509 DCHECK(!context->get(context_index)->IsTheHole());
1536 return handle(context->get(context_index), isolate); 1510 return handle(context->get(context_index), isolate);
1537 } else { 1511 } else {
1538 return result; 1512 return result;
1539 } 1513 }
1540 } 1514 }
1541 } 1515 }
1542 1516
1543 virtual void Delete(Handle<JSObject> obj, uint32_t key, 1517 virtual void Delete(Handle<JSObject> obj, uint32_t index) final {
1544 LanguageMode language_mode) final {
1545 FixedArray* parameter_map = FixedArray::cast(obj->elements()); 1518 FixedArray* parameter_map = FixedArray::cast(obj->elements());
1546 if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) { 1519 uint32_t length = static_cast<uint32_t>(parameter_map->length()) - 2;
1520 if (index < length) {
1547 // TODO(kmillikin): We could check if this was the last aliased 1521 // TODO(kmillikin): We could check if this was the last aliased
1548 // parameter, and revert to normal elements in that case. That 1522 // parameter, and revert to normal elements in that case. That
1549 // would enable GC of the context. 1523 // would enable GC of the context.
1550 parameter_map->set_the_hole(key + 2); 1524 parameter_map->set_the_hole(index + 2);
1551 } else { 1525 } else {
1552 ArgumentsAccessor::DeleteCommon(obj, key, language_mode); 1526 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
1527 ArgumentsAccessor::DeleteImpl(obj, index - length, arguments);
1553 } 1528 }
1554 } 1529 }
1555 1530
1556 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, 1531 static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
1557 uint32_t capacity) { 1532 uint32_t capacity) {
1558 UNREACHABLE(); 1533 UNREACHABLE();
1559 } 1534 }
1560 1535
1561 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { 1536 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
1562 FixedArray* parameter_map = FixedArray::cast(store); 1537 FixedArray* parameter_map = FixedArray::cast(store);
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 break; 1926 break;
1952 } 1927 }
1953 1928
1954 array->set_elements(*elms); 1929 array->set_elements(*elms);
1955 array->set_length(Smi::FromInt(number_of_elements)); 1930 array->set_length(Smi::FromInt(number_of_elements));
1956 return array; 1931 return array;
1957 } 1932 }
1958 1933
1959 } // namespace internal 1934 } // namespace internal
1960 } // namespace v8 1935 } // namespace v8
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/lookup.h » ('j') | src/lookup.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698