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

Side by Side Diff: src/code-stub-assembler.cc

Issue 1995453002: [stubs] Extend HasProperty stub with dictionary-mode and double-elements objects support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebasing and cleanup Created 4 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
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/code-stub-assembler.h" 5 #include "src/code-stub-assembler.h"
6 #include "src/code-factory.h" 6 #include "src/code-factory.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 10
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 } 51 }
52 52
53 Node* CodeStubAssembler::NullConstant() { 53 Node* CodeStubAssembler::NullConstant() {
54 return LoadRoot(Heap::kNullValueRootIndex); 54 return LoadRoot(Heap::kNullValueRootIndex);
55 } 55 }
56 56
57 Node* CodeStubAssembler::UndefinedConstant() { 57 Node* CodeStubAssembler::UndefinedConstant() {
58 return LoadRoot(Heap::kUndefinedValueRootIndex); 58 return LoadRoot(Heap::kUndefinedValueRootIndex);
59 } 59 }
60 60
61 Node* CodeStubAssembler::TheHoleConstant() {
62 return LoadRoot(Heap::kTheHoleValueRootIndex);
63 }
64
65 Node* CodeStubAssembler::HashSeed() {
66 return SmiToWord32(LoadRoot(Heap::kHashSeedRootIndex));
67 }
68
61 Node* CodeStubAssembler::StaleRegisterConstant() { 69 Node* CodeStubAssembler::StaleRegisterConstant() {
62 return LoadRoot(Heap::kStaleRegisterRootIndex); 70 return LoadRoot(Heap::kStaleRegisterRootIndex);
63 } 71 }
64 72
65 Node* CodeStubAssembler::Float64Round(Node* x) { 73 Node* CodeStubAssembler::Float64Round(Node* x) {
66 Node* one = Float64Constant(1.0); 74 Node* one = Float64Constant(1.0);
67 Node* one_half = Float64Constant(0.5); 75 Node* one_half = Float64Constant(0.5);
68 76
69 Variable var_x(this, MachineRepresentation::kFloat64); 77 Variable var_x(this, MachineRepresentation::kFloat64);
70 Label return_x(this); 78 Label return_x(this);
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 } 486 }
479 487
480 Node* CodeStubAssembler::LoadMap(Node* object) { 488 Node* CodeStubAssembler::LoadMap(Node* object) {
481 return LoadObjectField(object, HeapObject::kMapOffset); 489 return LoadObjectField(object, HeapObject::kMapOffset);
482 } 490 }
483 491
484 Node* CodeStubAssembler::LoadInstanceType(Node* object) { 492 Node* CodeStubAssembler::LoadInstanceType(Node* object) {
485 return LoadMapInstanceType(LoadMap(object)); 493 return LoadMapInstanceType(LoadMap(object));
486 } 494 }
487 495
496 Node* CodeStubAssembler::LoadProperties(Node* object) {
497 return LoadObjectField(object, JSObject::kPropertiesOffset);
498 }
499
488 Node* CodeStubAssembler::LoadElements(Node* object) { 500 Node* CodeStubAssembler::LoadElements(Node* object) {
489 return LoadObjectField(object, JSObject::kElementsOffset); 501 return LoadObjectField(object, JSObject::kElementsOffset);
490 } 502 }
491 503
492 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) { 504 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) {
493 return LoadObjectField(array, FixedArrayBase::kLengthOffset); 505 return LoadObjectField(array, FixedArrayBase::kLengthOffset);
494 } 506 }
495 507
496 Node* CodeStubAssembler::LoadMapBitField(Node* map) { 508 Node* CodeStubAssembler::LoadMapBitField(Node* map) {
497 return Load(MachineType::Uint8(), map, 509 return Load(MachineType::Uint8(), map,
(...skipping 16 matching lines...) Expand all
514 } 526 }
515 527
516 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { 528 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
517 return LoadObjectField(map, Map::kDescriptorsOffset); 529 return LoadObjectField(map, Map::kDescriptorsOffset);
518 } 530 }
519 531
520 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { 532 Node* CodeStubAssembler::LoadMapPrototype(Node* map) {
521 return LoadObjectField(map, Map::kPrototypeOffset); 533 return LoadObjectField(map, Map::kPrototypeOffset);
522 } 534 }
523 535
524 Node* CodeStubAssembler::LoadNameHash(Node* name) { 536 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
537 return Load(MachineType::Uint8(), map,
538 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag));
539 }
540
541 Node* CodeStubAssembler::LoadNameHashField(Node* name) {
525 return Load(MachineType::Uint32(), name, 542 return Load(MachineType::Uint32(), name,
526 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); 543 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag));
527 } 544 }
528 545
546 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) {
547 Node* hash_field = LoadNameHashField(name);
548 if (if_hash_not_computed != nullptr) {
549 GotoIf(WordEqual(
550 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
551 Int32Constant(0)),
552 if_hash_not_computed);
553 }
554 return Word32Shr(hash_field, Int32Constant(Name::kHashShift));
555 }
556
557 Node* CodeStubAssembler::LoadStringLength(Node* object) {
558 return LoadObjectField(object, String::kLengthOffset);
559 }
560
561 Node* CodeStubAssembler::LoadJSValueValue(Node* object) {
562 return LoadObjectField(object, JSValue::kValueOffset);
563 }
564
529 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) { 565 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) {
530 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize); 566 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize);
531 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2)); 567 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2));
532 Node* total_size = IntPtrAdd(data_size, header_size); 568 Node* total_size = IntPtrAdd(data_size, header_size);
533 569
534 Node* result = Allocate(total_size, kNone); 570 Node* result = Allocate(total_size, kNone);
535 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex)); 571 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex));
536 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset, 572 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
537 SmiTag(length)); 573 SmiTag(length));
538 574
539 return result; 575 return result;
540 } 576 }
541 577
542 Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node, 578 Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
543 int additional_offset, 579 int additional_offset,
544 ParameterMode parameter_mode) { 580 ParameterMode parameter_mode) {
545 int32_t header_size = 581 int32_t header_size =
546 FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; 582 FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
547 Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, 583 Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS,
548 parameter_mode, header_size); 584 parameter_mode, header_size);
549 return Load(MachineType::AnyTagged(), object, offset); 585 return Load(MachineType::AnyTagged(), object, offset);
550 } 586 }
551 587
552 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { 588 Node* CodeStubAssembler::LoadFixedDoubleArrayElement(
553 return Load(MachineType::Uint8(), map, 589 Node* object, Node* index_node, MachineType machine_type,
554 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag)); 590 int additional_offset, ParameterMode parameter_mode) {
591 int32_t header_size =
592 FixedDoubleArray::kHeaderSize + additional_offset - kHeapObjectTag;
593 Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_DOUBLE_ELEMENTS,
594 parameter_mode, header_size);
595 return Load(machine_type, object, offset);
555 } 596 }
556 597
557 Node* CodeStubAssembler::LoadNativeContext(Node* context) { 598 Node* CodeStubAssembler::LoadNativeContext(Node* context) {
558 return LoadFixedArrayElement(context, 599 return LoadFixedArrayElement(context,
559 Int32Constant(Context::NATIVE_CONTEXT_INDEX)); 600 Int32Constant(Context::NATIVE_CONTEXT_INDEX));
560 } 601 }
561 602
562 Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind, 603 Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
563 Node* native_context) { 604 Node* native_context) {
564 return LoadFixedArrayElement(native_context, 605 return LoadFixedArrayElement(native_context,
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 } 1345 }
1305 1346
1306 Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, 1347 Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
1307 uint32_t mask) { 1348 uint32_t mask) {
1308 return Word32Shr(Word32And(word32, Int32Constant(mask)), 1349 return Word32Shr(Word32And(word32, Int32Constant(mask)),
1309 Int32Constant(shift)); 1350 Int32Constant(shift));
1310 } 1351 }
1311 1352
1312 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, 1353 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
1313 Variable* var_index, Label* if_keyisunique, 1354 Variable* var_index, Label* if_keyisunique,
1314 Label* call_runtime) { 1355 Label* if_bailout) {
1315 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); 1356 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep());
1316 1357
1317 Label if_keyissmi(this), if_keyisnotsmi(this); 1358 Label if_keyissmi(this), if_keyisnotsmi(this);
1318 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); 1359 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
1319 Bind(&if_keyissmi); 1360 Bind(&if_keyissmi);
1320 { 1361 {
1321 // Negative smi keys are named properties. Handle in the runtime. 1362 // Negative smi keys are named properties. Handle in the runtime.
1322 Label if_keyispositive(this); 1363 GotoUnless(WordIsPositiveSmi(key), if_bailout);
1323 Branch(WordIsPositiveSmi(key), &if_keyispositive, call_runtime);
1324 Bind(&if_keyispositive);
1325 1364
1326 var_index->Bind(SmiToWord32(key)); 1365 var_index->Bind(SmiToWord32(key));
1327 Goto(if_keyisindex); 1366 Goto(if_keyisindex);
1328 } 1367 }
1329 1368
1330 Bind(&if_keyisnotsmi); 1369 Bind(&if_keyisnotsmi);
1331 1370
1332 Node* key_instance_type = LoadInstanceType(key); 1371 Node* key_instance_type = LoadInstanceType(key);
1333 Label if_keyisnotsymbol(this); 1372 // Symbols are unique.
1334 Branch(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), 1373 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)),
1335 if_keyisunique, &if_keyisnotsymbol); 1374 if_keyisunique);
1336 Bind(&if_keyisnotsymbol); 1375
1337 { 1376 Label if_keyisinternalized(this);
1338 Label if_keyisinternalized(this); 1377 Node* bits =
1339 Node* bits = 1378 WordAnd(key_instance_type,
1340 WordAnd(key_instance_type, 1379 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
1341 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)); 1380 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)),
1342 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)), 1381 &if_keyisinternalized, if_bailout);
1343 &if_keyisinternalized, call_runtime); 1382 Bind(&if_keyisinternalized);
1344 Bind(&if_keyisinternalized); 1383
1345 1384 // Check whether the key is an array index passed in as string. Handle
1346 // Check whether the key is an array index passed in as string. Handle 1385 // uniform with smi keys if so.
1347 // uniform with smi keys if so. 1386 // TODO(verwaest): Also support non-internalized strings.
1348 // TODO(verwaest): Also support non-internalized strings. 1387 Node* hash = LoadNameHashField(key);
1349 Node* hash = LoadNameHash(key); 1388 Node* bit = Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
1350 Node* bit = 1389 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique);
1351 Word32And(hash, Int32Constant(internal::Name::kIsNotArrayIndexMask)); 1390 // Key is an index. Check if it is small enough to be encoded in the
1352 Label if_isarrayindex(this); 1391 // hash_field. Handle too big array index in runtime.
1353 Branch(Word32Equal(bit, Int32Constant(0)), &if_isarrayindex, 1392 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
1354 if_keyisunique); 1393 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout);
1355 Bind(&if_isarrayindex); 1394 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash));
1356 var_index->Bind(BitFieldDecode<internal::Name::ArrayIndexValueBits>(hash)); 1395 Goto(if_keyisindex);
1357 Goto(if_keyisindex); 1396 }
1397
1398 template <typename Dictionary>
1399 void CodeStubAssembler::NameDictionaryLookup(
1400 Node* dictionary, Node* unique_name, Label* if_found_, Variable* var_entry,
1401 Label* if_not_found, int inlined_probes) {
1402 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep());
1403
1404 // TODO(ishell): Remove this trampoline block once crbug/615621 is fixed.
1405 // This trampoline block is currently necessary here to generate a correct
1406 // phi for |var_entry|.
1407 Label if_found(this, var_entry);
1408
1409 const int kElementsStartOffset =
1410 Dictionary::kElementsStartIndex * kPointerSize;
1411
1412 Node* capacity = SmiToWord32(LoadFixedArrayElement(
1413 dictionary, Int32Constant(Dictionary::kCapacityIndex)));
1414 Node* mask = Int32Sub(capacity, Int32Constant(1));
1415 Node* hash = LoadNameHash(unique_name);
1416
1417 // See Dictionary::FirstProbe().
1418 Node* count = Int32Constant(0);
1419 Node* entry = Word32And(hash, mask);
1420
1421 for (int i = 0; i < inlined_probes; i++) {
1422 // See Dictionary::EntryToIndex()
1423 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1424 Node* current =
1425 LoadFixedArrayElement(dictionary, index, kElementsStartOffset);
1426 var_entry->Bind(entry);
1427 GotoIf(WordEqual(current, unique_name), &if_found);
1428
1429 // See Dictionary::NextProbe().
1430 count = Int32Constant(i + 1);
1431 entry = Word32And(Int32Add(entry, count), mask);
1432 }
1433
1434 Node* undefined = UndefinedConstant();
1435
1436 Variable var_count(this, MachineRepresentation::kWord32);
1437 Variable* loop_vars[] = {&var_count, var_entry};
1438 Label loop(this, 2, loop_vars);
1439 var_count.Bind(count);
1440 var_entry->Bind(entry);
1441 Goto(&loop);
1442 Bind(&loop);
1443 {
1444 Node* count = var_count.value();
1445 Node* entry = var_entry->value();
1446
1447 // See Dictionary::EntryToIndex()
1448 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1449 Node* current =
1450 LoadFixedArrayElement(dictionary, index, kElementsStartOffset);
1451 GotoIf(WordEqual(current, undefined), if_not_found);
1452 GotoIf(WordEqual(current, unique_name), &if_found);
1453
1454 // See Dictionary::NextProbe().
1455 count = Int32Add(count, Int32Constant(1));
1456 entry = Word32And(Int32Add(entry, count), mask);
1457
1458 var_count.Bind(count);
1459 var_entry->Bind(entry);
1460 Goto(&loop);
1461 }
1462 Bind(&if_found);
1463 Goto(if_found_);
1464 }
1465
1466 Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
1467 // See v8::internal::ComputeIntegerHash()
1468 Node* hash = key;
1469 hash = Word32Xor(hash, seed);
1470 hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)),
1471 Word32Shl(hash, Int32Constant(15)));
1472 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
1473 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2)));
1474 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4)));
1475 hash = Int32Mul(hash, Int32Constant(2057));
1476 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16)));
1477 return Word32And(hash, Int32Constant(0x3fffffff));
1478 }
1479
1480 template <typename Dictionary>
1481 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key,
1482 Label* if_found,
1483 Variable* var_entry,
1484 Label* if_not_found) {
1485 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep());
1486
1487 const int kElementsStartOffset =
1488 Dictionary::kElementsStartIndex * kPointerSize;
1489
1490 Node* capacity = SmiToWord32(LoadFixedArrayElement(
1491 dictionary, Int32Constant(Dictionary::kCapacityIndex)));
1492 Node* mask = Int32Sub(capacity, Int32Constant(1));
1493
1494 Node* seed;
1495 if (Dictionary::ShapeT::UsesSeed) {
1496 seed = HashSeed();
1497 } else {
1498 seed = Int32Constant(kZeroHashSeed);
1499 }
1500 Node* hash = ComputeIntegerHash(key, seed);
1501 Node* key_as_float64 = ChangeUint32ToFloat64(key);
1502
1503 // See Dictionary::FirstProbe().
1504 Node* count = Int32Constant(0);
1505 Node* entry = Word32And(hash, mask);
1506
1507 Node* undefined = UndefinedConstant();
1508 Node* the_hole = TheHoleConstant();
1509
1510 Variable var_count(this, MachineRepresentation::kWord32);
1511 Variable* loop_vars[] = {&var_count, var_entry};
1512 Label loop(this, 2, loop_vars);
1513 var_count.Bind(count);
1514 var_entry->Bind(entry);
1515 Goto(&loop);
1516 Bind(&loop);
1517 {
1518 Node* count = var_count.value();
1519 Node* entry = var_entry->value();
1520
1521 // See Dictionary::EntryToIndex()
1522 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1523 Node* current =
1524 LoadFixedArrayElement(dictionary, index, kElementsStartOffset);
1525 GotoIf(WordEqual(current, undefined), if_not_found);
1526 Label next_probe(this);
1527 {
1528 Label if_currentissmi(this), if_currentisnotsmi(this);
1529 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi);
1530 Bind(&if_currentissmi);
1531 {
1532 Node* current_value = SmiToWord32(current);
1533 Branch(Word32Equal(current_value, key), if_found, &next_probe);
1534 }
1535 Bind(&if_currentisnotsmi);
1536 {
1537 GotoIf(WordEqual(current, the_hole), &next_probe);
1538 // Current must be the Number.
1539 Node* current_value = LoadHeapNumberValue(current);
1540 Branch(Float64Equal(current_value, key_as_float64), if_found,
1541 &next_probe);
1542 }
1543 }
1544
1545 Bind(&next_probe);
1546 // See Dictionary::NextProbe().
1547 count = Int32Add(count, Int32Constant(1));
1548 entry = Word32And(Int32Add(entry, count), mask);
1549
1550 var_count.Bind(count);
1551 var_entry->Bind(entry);
1552 Goto(&loop);
1358 } 1553 }
1359 } 1554 }
1360 1555
1361 void CodeStubAssembler::TryLookupProperty(Node* object, Node* map, 1556 void CodeStubAssembler::TryLookupProperty(Node* object, Node* map,
1362 Node* instance_type, Node* name, 1557 Node* instance_type,
1363 Label* if_found, Label* if_not_found, 1558 Node* unique_name, Label* if_found,
1364 Label* call_runtime) { 1559 Label* if_not_found,
1365 { 1560 Label* if_bailout) {
1366 Label if_objectissimple(this); 1561 Label if_objectisspecial(this);
1367 Branch(Int32LessThanOrEqual(instance_type, 1562 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
1368 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), 1563 GotoIf(Int32LessThanOrEqual(instance_type,
1369 call_runtime, &if_objectissimple); 1564 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
1370 Bind(&if_objectissimple); 1565 &if_objectisspecial);
1371 } 1566
1372
1373 // TODO(verwaest): Perform a dictonary lookup on slow-mode receivers.
1374 Node* bit_field3 = LoadMapBitField3(map); 1567 Node* bit_field3 = LoadMapBitField3(map);
1375 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); 1568 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3);
1376 Label if_isfastmap(this); 1569 Label if_isfastmap(this), if_isslowmap(this);
1377 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, call_runtime); 1570 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap);
1378 Bind(&if_isfastmap); 1571 Bind(&if_isfastmap);
1379 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); 1572 {
1380 // Bail out to the runtime for large numbers of own descriptors. The stub only 1573 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
1381 // does linear search, which becomes too expensive in that case. 1574 // Bail out to the runtime for large numbers of own descriptors. The stub
1382 { 1575 // only does linear search, which becomes too expensive in that case.
1383 static const int32_t kMaxLinear = 210;
1384 Label above_max(this), below_max(this);
1385 Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxLinear)), &below_max,
1386 call_runtime);
1387 Bind(&below_max);
1388 }
1389 Node* descriptors = LoadMapDescriptors(map);
1390
1391 Variable var_descriptor(this, MachineRepresentation::kWord32);
1392 Label loop(this, &var_descriptor);
1393 var_descriptor.Bind(Int32Constant(0));
1394 Goto(&loop);
1395 Bind(&loop);
1396 {
1397 Node* index = var_descriptor.value();
1398 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0));
1399 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize);
1400 Label if_notdone(this);
1401 Branch(Word32Equal(index, nof), if_not_found, &if_notdone);
1402 Bind(&if_notdone);
1403 { 1576 {
1577 static const int32_t kMaxLinear = 210;
1578 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout);
1579 }
1580 Node* descriptors = LoadMapDescriptors(map);
1581
1582 Variable var_descriptor(this, MachineRepresentation::kWord32);
1583 Label loop(this, &var_descriptor);
1584 var_descriptor.Bind(Int32Constant(0));
1585 Goto(&loop);
1586 Bind(&loop);
1587 {
1588 Node* index = var_descriptor.value();
1589 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0));
1590 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize);
1591 GotoIf(Word32Equal(index, nof), if_not_found);
1592
1404 Node* array_index = Int32Add(offset, Int32Mul(index, factor)); 1593 Node* array_index = Int32Add(offset, Int32Mul(index, factor));
1405 Node* current = LoadFixedArrayElement(descriptors, array_index); 1594 Node* current = LoadFixedArrayElement(descriptors, array_index);
1406 Label if_unequal(this); 1595 GotoIf(WordEqual(current, unique_name), if_found);
1407 Branch(WordEqual(current, name), if_found, &if_unequal);
1408 Bind(&if_unequal);
1409 1596
1410 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); 1597 var_descriptor.Bind(Int32Add(index, Int32Constant(1)));
1411 Goto(&loop); 1598 Goto(&loop);
1412 } 1599 }
1413 } 1600 }
1601 Bind(&if_isslowmap);
1602 {
1603 Variable var_entry(this, MachineRepresentation::kWord32);
1604 Node* dictionary = LoadProperties(object);
1605
1606 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found,
1607 &var_entry, if_not_found);
1608 }
1609 Bind(&if_objectisspecial);
1610 {
1611 // Handle global object here and other special objects in runtime.
1612 GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)),
1613 if_bailout);
1614 Variable var_entry(this, MachineRepresentation::kWord32);
1615 Node* dictionary = LoadProperties(object);
1616
1617 NameDictionaryLookup<GlobalDictionary>(dictionary, unique_name, if_found,
1618 &var_entry, if_not_found);
1619 }
1414 } 1620 }
1415 1621
1416 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, 1622 void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
1417 Node* instance_type, Node* index, 1623 Node* instance_type, Node* index,
1418 Label* if_found, Label* if_not_found, 1624 Label* if_found, Label* if_not_found,
1419 Label* call_runtime) { 1625 Label* if_bailout) {
1420 { 1626 // Handle special objects in runtime.
1421 Label if_objectissimple(this); 1627 GotoIf(Int32LessThanOrEqual(instance_type,
1422 Branch(Int32LessThanOrEqual(instance_type, 1628 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
1423 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), 1629 if_bailout);
1424 call_runtime, &if_objectissimple);
1425 Bind(&if_objectissimple);
1426 }
1427 1630
1428 Node* bit_field2 = LoadMapBitField2(map); 1631 Node* bit_field2 = LoadMapBitField2(map);
1429 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); 1632 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
1430 1633
1431 // TODO(verwaest): Support other elements kinds as well. 1634 // TODO(verwaest): Support other elements kinds as well.
1432 Label if_isobjectorsmi(this); 1635 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this),
1433 Branch( 1636 if_isfaststringwrapper(this), if_isslowstringwrapper(this);
1434 Int32LessThanOrEqual(elements_kind, Int32Constant(FAST_HOLEY_ELEMENTS)), 1637 // clang-format off
1435 &if_isobjectorsmi, call_runtime); 1638 int32_t values[] = {
1639 // Handled by {if_isobjectorsmi}.
1640 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
1641 FAST_HOLEY_ELEMENTS,
1642 // Handled by {if_isdouble}.
1643 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
1644 // Handled by {if_isdictionary}.
1645 DICTIONARY_ELEMENTS,
1646 // Handled by {if_isfaststringwrapper}.
1647 FAST_STRING_WRAPPER_ELEMENTS,
1648 // Handled by {if_isslowstringwrapper}.
1649 SLOW_STRING_WRAPPER_ELEMENTS,
1650 // Handled by {if_not_found}.
1651 NO_ELEMENTS,
1652 };
1653 Label* labels[] = {
1654 &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi,
1655 &if_isobjectorsmi,
1656 &if_isdouble, &if_isdouble,
1657 &if_isdictionary,
1658 &if_isfaststringwrapper,
1659 &if_isslowstringwrapper,
1660 if_not_found,
1661 };
1662 // clang-format on
1663 STATIC_ASSERT(arraysize(values) == arraysize(labels));
1664 Switch(elements_kind, if_bailout, values, labels, arraysize(values));
1665
1436 Bind(&if_isobjectorsmi); 1666 Bind(&if_isobjectorsmi);
1437 { 1667 {
1438 Node* elements = LoadElements(object); 1668 Node* elements = LoadElements(object);
1439 Node* length = LoadFixedArrayBaseLength(elements); 1669 Node* length = LoadFixedArrayBaseLength(elements);
1440 1670
1441 Label if_iskeyinrange(this); 1671 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
1442 Branch(Int32LessThan(index, SmiToWord32(length)), &if_iskeyinrange, 1672
1443 if_not_found);
1444
1445 Bind(&if_iskeyinrange);
1446 Node* element = LoadFixedArrayElement(elements, index); 1673 Node* element = LoadFixedArrayElement(elements, index);
1447 Node* the_hole = LoadRoot(Heap::kTheHoleValueRootIndex); 1674 Node* the_hole = TheHoleConstant();
1448 Branch(WordEqual(element, the_hole), if_not_found, if_found); 1675 Branch(WordEqual(element, the_hole), if_not_found, if_found);
1449 } 1676 }
1450 } 1677 Bind(&if_isdouble);
1678 {
1679 Node* elements = LoadElements(object);
1680 Node* length = LoadFixedArrayBaseLength(elements);
1681
1682 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
1683
1684 if (kPointerSize == kDoubleSize) {
1685 Node* element =
1686 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64());
1687 Node* the_hole = Int64Constant(kHoleNanInt64);
1688 Branch(Word64Equal(element, the_hole), if_not_found, if_found);
1689 } else {
1690 Node* element_upper =
1691 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(),
1692 IeeeDoubleArchType::kExponentWordOffset);
1693 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
1694 if_not_found, if_found);
1695 }
1696 }
1697 Bind(&if_isdictionary);
1698 {
1699 Variable var_entry(this, MachineRepresentation::kWord32);
1700 Node* elements = LoadElements(object);
1701 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found,
1702 &var_entry, if_not_found);
1703 }
1704 Bind(&if_isfaststringwrapper);
1705 {
1706 Assert(Word32Equal(LoadInstanceType(object), Int32Constant(JS_VALUE_TYPE)));
1707 Node* string = LoadJSValueValue(object);
1708 Assert(Int32LessThan(LoadInstanceType(string),
1709 Int32Constant(FIRST_NONSTRING_TYPE)));
1710 Node* length = LoadStringLength(string);
1711 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
1712 Goto(&if_isobjectorsmi);
1713 }
1714 Bind(&if_isslowstringwrapper);
1715 {
1716 Assert(Word32Equal(LoadInstanceType(object), Int32Constant(JS_VALUE_TYPE)));
1717 Node* string = LoadJSValueValue(object);
1718 Assert(Int32LessThan(LoadInstanceType(string),
1719 Int32Constant(FIRST_NONSTRING_TYPE)));
1720 Node* length = LoadStringLength(string);
1721 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
1722 Goto(&if_isdictionary);
1723 }
1724 }
1725
1726 // Instantiate this for the purpose of testing.
1727 template void CodeStubAssembler::NumberDictionaryLookup<
1728 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*);
1451 1729
1452 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, 1730 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
1453 Node* object) { 1731 Node* object) {
1454 Variable var_result(this, MachineRepresentation::kTagged); 1732 Variable var_result(this, MachineRepresentation::kTagged);
1455 Label return_false(this), return_true(this), 1733 Label return_false(this), return_true(this),
1456 return_runtime(this, Label::kDeferred), return_result(this); 1734 return_runtime(this, Label::kDeferred), return_result(this);
1457 1735
1458 // Goto runtime if {object} is a Smi. 1736 // Goto runtime if {object} is a Smi.
1459 GotoIf(WordIsSmi(object), &return_runtime); 1737 GotoIf(WordIsSmi(object), &return_runtime);
1460 1738
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 } 1894 }
1617 return IntPtrAdd( 1895 return IntPtrAdd(
1618 IntPtrConstant(base_size), 1896 IntPtrConstant(base_size),
1619 (element_size_shift >= 0) 1897 (element_size_shift >= 0)
1620 ? WordShl(index_node, IntPtrConstant(element_size_shift)) 1898 ? WordShl(index_node, IntPtrConstant(element_size_shift))
1621 : WordShr(index_node, IntPtrConstant(-element_size_shift))); 1899 : WordShr(index_node, IntPtrConstant(-element_size_shift)));
1622 } 1900 }
1623 1901
1624 } // namespace internal 1902 } // namespace internal
1625 } // namespace v8 1903 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698