OLD | NEW |
---|---|
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/elements.h" | 5 #include "src/elements.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/factory.h" | 9 #include "src/factory.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1188 Handle<FixedArray> new_elements = | 1188 Handle<FixedArray> new_elements = |
1189 SeededNumberDictionary::Shrink(dict, index); | 1189 SeededNumberDictionary::Shrink(dict, index); |
1190 obj->set_elements(*new_elements); | 1190 obj->set_elements(*new_elements); |
1191 } | 1191 } |
1192 | 1192 |
1193 static bool HasAccessorsImpl(JSObject* holder, | 1193 static bool HasAccessorsImpl(JSObject* holder, |
1194 FixedArrayBase* backing_store) { | 1194 FixedArrayBase* backing_store) { |
1195 SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store); | 1195 SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store); |
1196 if (!dict->requires_slow_elements()) return false; | 1196 if (!dict->requires_slow_elements()) return false; |
1197 int capacity = dict->Capacity(); | 1197 int capacity = dict->Capacity(); |
1198 Heap* heap = holder->GetHeap(); | |
Yang
2016/04/01 13:29:53
Can we have a disallow allocation scope here?
| |
1199 Object* undefined = heap->undefined_value(); | |
1200 Object* the_hole = heap->the_hole_value(); | |
1198 for (int i = 0; i < capacity; i++) { | 1201 for (int i = 0; i < capacity; i++) { |
1199 Object* key = dict->KeyAt(i); | 1202 Object* key = dict->KeyAt(i); |
1200 if (!dict->IsKey(key)) continue; | 1203 if (key == the_hole || key == undefined) continue; |
1201 DCHECK(!dict->IsDeleted(i)); | 1204 DCHECK(!dict->IsDeleted(i)); |
1202 PropertyDetails details = dict->DetailsAt(i); | 1205 PropertyDetails details = dict->DetailsAt(i); |
1203 if (details.type() == ACCESSOR_CONSTANT) return true; | 1206 if (details.type() == ACCESSOR_CONSTANT) return true; |
1204 } | 1207 } |
1205 return false; | 1208 return false; |
1206 } | 1209 } |
1207 | 1210 |
1208 static Object* GetRaw(FixedArrayBase* store, uint32_t entry) { | 1211 static Object* GetRaw(FixedArrayBase* store, uint32_t entry) { |
1209 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); | 1212 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
1210 return backing_store->ValueAt(entry); | 1213 return backing_store->ValueAt(entry); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1289 | 1292 |
1290 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { | 1293 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { |
1291 return GetDetailsImpl(holder->elements(), entry); | 1294 return GetDetailsImpl(holder->elements(), entry); |
1292 } | 1295 } |
1293 | 1296 |
1294 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1297 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1295 uint32_t entry) { | 1298 uint32_t entry) { |
1296 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); | 1299 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
1297 } | 1300 } |
1298 | 1301 |
1299 static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary, | 1302 static uint32_t FilterKey(Handle<SeededNumberDictionary> dictionary, |
1300 int entry, PropertyFilter filter) { | 1303 int entry, Object* raw_key, PropertyFilter filter) { |
1301 DisallowHeapAllocation no_gc; | |
1302 Object* raw_key = dictionary->KeyAt(entry); | |
1303 if (!dictionary->IsKey(raw_key)) return kMaxUInt32; | |
1304 DCHECK(!dictionary->IsDeleted(entry)); | 1304 DCHECK(!dictionary->IsDeleted(entry)); |
1305 DCHECK(raw_key->IsNumber()); | 1305 DCHECK(raw_key->IsNumber()); |
1306 DCHECK_LE(raw_key->Number(), kMaxUInt32); | 1306 DCHECK_LE(raw_key->Number(), kMaxUInt32); |
1307 PropertyDetails details = dictionary->DetailsAt(entry); | 1307 PropertyDetails details = dictionary->DetailsAt(entry); |
1308 PropertyAttributes attr = details.attributes(); | 1308 PropertyAttributes attr = details.attributes(); |
1309 if ((attr & filter) != 0) return kMaxUInt32; | 1309 if ((attr & filter) != 0) return kMaxUInt32; |
1310 return static_cast<uint32_t>(raw_key->Number()); | 1310 return static_cast<uint32_t>(raw_key->Number()); |
1311 } | 1311 } |
1312 | 1312 |
1313 static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary, | |
1314 int entry, PropertyFilter filter) { | |
1315 DisallowHeapAllocation no_gc; | |
1316 Object* raw_key = dictionary->KeyAt(entry); | |
1317 if (!dictionary->IsKey(raw_key)) return kMaxUInt32; | |
1318 return FilterKey(dictionary, entry, raw_key, filter); | |
1319 } | |
1320 | |
1321 static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary, | |
1322 int entry, PropertyFilter filter, | |
1323 Object* undefined, Object* the_hole) { | |
1324 DisallowHeapAllocation no_gc; | |
1325 Object* raw_key = dictionary->KeyAt(entry); | |
1326 // Replace the IsKey check with a direct comparison which is much faster. | |
1327 if (raw_key == undefined || raw_key == the_hole) { | |
1328 return kMaxUInt32; | |
1329 } | |
1330 return FilterKey(dictionary, entry, raw_key, filter); | |
1331 } | |
1332 | |
1313 static void CollectElementIndicesImpl(Handle<JSObject> object, | 1333 static void CollectElementIndicesImpl(Handle<JSObject> object, |
1314 Handle<FixedArrayBase> backing_store, | 1334 Handle<FixedArrayBase> backing_store, |
1315 KeyAccumulator* keys, uint32_t range, | 1335 KeyAccumulator* keys, uint32_t range, |
1316 PropertyFilter filter, | 1336 PropertyFilter filter, |
1317 uint32_t offset) { | 1337 uint32_t offset) { |
1318 if (filter & SKIP_STRINGS) return; | 1338 if (filter & SKIP_STRINGS) return; |
1339 Isolate* isolate = keys->isolate(); | |
1340 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
1341 Handle<Object> the_hole = isolate->factory()->the_hole_value(); | |
1319 Handle<SeededNumberDictionary> dictionary = | 1342 Handle<SeededNumberDictionary> dictionary = |
1320 Handle<SeededNumberDictionary>::cast(backing_store); | 1343 Handle<SeededNumberDictionary>::cast(backing_store); |
1321 int capacity = dictionary->Capacity(); | 1344 int capacity = dictionary->Capacity(); |
1322 for (int i = 0; i < capacity; i++) { | 1345 for (int i = 0; i < capacity; i++) { |
1323 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); | 1346 uint32_t key = |
1347 GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole); | |
1324 if (key == kMaxUInt32) continue; | 1348 if (key == kMaxUInt32) continue; |
1325 keys->AddKey(key); | 1349 keys->AddKey(key); |
1326 } | 1350 } |
1327 | 1351 |
1328 keys->SortCurrentElementsList(); | 1352 keys->SortCurrentElementsList(); |
1329 } | 1353 } |
1330 | 1354 |
1331 static Handle<FixedArray> DirectCollectElementIndicesImpl( | 1355 static Handle<FixedArray> DirectCollectElementIndicesImpl( |
1332 Isolate* isolate, Handle<JSObject> object, | 1356 Isolate* isolate, Handle<JSObject> object, |
1333 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | 1357 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, |
1334 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, | 1358 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, |
1335 uint32_t insertion_index = 0) { | 1359 uint32_t insertion_index = 0) { |
1336 if (filter & SKIP_STRINGS) return list; | 1360 if (filter & SKIP_STRINGS) return list; |
1337 if (filter & ONLY_ALL_CAN_READ) return list; | 1361 if (filter & ONLY_ALL_CAN_READ) return list; |
1362 | |
1363 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
1364 Handle<Object> the_hole = isolate->factory()->the_hole_value(); | |
1338 Handle<SeededNumberDictionary> dictionary = | 1365 Handle<SeededNumberDictionary> dictionary = |
1339 Handle<SeededNumberDictionary>::cast(backing_store); | 1366 Handle<SeededNumberDictionary>::cast(backing_store); |
1340 uint32_t capacity = dictionary->Capacity(); | 1367 uint32_t capacity = dictionary->Capacity(); |
1341 for (uint32_t i = 0; i < capacity; i++) { | 1368 for (uint32_t i = 0; i < capacity; i++) { |
1342 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); | 1369 uint32_t key = |
1370 GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole); | |
1343 if (key == kMaxUInt32) continue; | 1371 if (key == kMaxUInt32) continue; |
1344 Handle<Object> index = isolate->factory()->NewNumberFromUint(key); | 1372 Handle<Object> index = isolate->factory()->NewNumberFromUint(key); |
1345 list->set(insertion_index, *index); | 1373 list->set(insertion_index, *index); |
1346 insertion_index++; | 1374 insertion_index++; |
1347 } | 1375 } |
1348 *nof_indices = insertion_index; | 1376 *nof_indices = insertion_index; |
1349 return list; | 1377 return list; |
1350 } | 1378 } |
1351 | 1379 |
1352 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 1380 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
1353 KeyAccumulator* accumulator, | 1381 KeyAccumulator* accumulator, |
1354 AddKeyConversion convert) { | 1382 AddKeyConversion convert) { |
1383 Isolate* isolate = accumulator->isolate(); | |
1384 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
1385 Handle<Object> the_hole = isolate->factory()->the_hole_value(); | |
1355 SeededNumberDictionary* dictionary = | 1386 SeededNumberDictionary* dictionary = |
1356 SeededNumberDictionary::cast(receiver->elements()); | 1387 SeededNumberDictionary::cast(receiver->elements()); |
1357 int capacity = dictionary->Capacity(); | 1388 int capacity = dictionary->Capacity(); |
1358 for (int i = 0; i < capacity; i++) { | 1389 for (int i = 0; i < capacity; i++) { |
1359 Object* k = dictionary->KeyAt(i); | 1390 Object* k = dictionary->KeyAt(i); |
1360 if (!dictionary->IsKey(k)) continue; | 1391 if (k == *undefined) continue; |
1392 if (k == *the_hole) continue; | |
1361 if (dictionary->IsDeleted(i)) continue; | 1393 if (dictionary->IsDeleted(i)) continue; |
1362 Object* value = dictionary->ValueAt(i); | 1394 Object* value = dictionary->ValueAt(i); |
1363 DCHECK(!value->IsTheHole()); | 1395 DCHECK(!value->IsTheHole()); |
1364 DCHECK(!value->IsAccessorPair()); | 1396 DCHECK(!value->IsAccessorPair()); |
1365 DCHECK(!value->IsAccessorInfo()); | 1397 DCHECK(!value->IsAccessorInfo()); |
1366 accumulator->AddKey(value, convert); | 1398 accumulator->AddKey(value, convert); |
1367 } | 1399 } |
1368 } | 1400 } |
1369 }; | 1401 }; |
1370 | 1402 |
(...skipping 1633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3004 insertion_index += len; | 3036 insertion_index += len; |
3005 } | 3037 } |
3006 | 3038 |
3007 DCHECK_EQ(insertion_index, result_len); | 3039 DCHECK_EQ(insertion_index, result_len); |
3008 return result_array; | 3040 return result_array; |
3009 } | 3041 } |
3010 | 3042 |
3011 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3043 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3012 } // namespace internal | 3044 } // namespace internal |
3013 } // namespace v8 | 3045 } // namespace v8 |
OLD | NEW |