OLD | NEW |
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 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 result_size) {} | 21 result_size) {} |
22 | 22 |
23 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone, | 23 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone, |
24 int parameter_count, Code::Flags flags, | 24 int parameter_count, Code::Flags flags, |
25 const char* name) | 25 const char* name) |
26 : compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {} | 26 : compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {} |
27 | 27 |
28 void CodeStubAssembler::Assert(Node* condition) { | 28 void CodeStubAssembler::Assert(Node* condition) { |
29 #if defined(DEBUG) | 29 #if defined(DEBUG) |
30 Label ok(this); | 30 Label ok(this); |
31 Label not_ok(this); | 31 Comment("[ Assert"); |
32 Branch(condition, &ok, ¬_ok); | 32 GotoIf(condition, &ok); |
33 Bind(¬_ok); | |
34 DebugBreak(); | 33 DebugBreak(); |
35 Goto(&ok); | 34 Goto(&ok); |
36 Bind(&ok); | 35 Bind(&ok); |
| 36 Comment("] Assert"); |
37 #endif | 37 #endif |
38 } | 38 } |
39 | 39 |
40 Node* CodeStubAssembler::BooleanMapConstant() { | 40 Node* CodeStubAssembler::BooleanMapConstant() { |
41 return HeapConstant(isolate()->factory()->boolean_map()); | 41 return HeapConstant(isolate()->factory()->boolean_map()); |
42 } | 42 } |
43 | 43 |
44 Node* CodeStubAssembler::EmptyStringConstant() { | 44 Node* CodeStubAssembler::EmptyStringConstant() { |
45 return LoadRoot(Heap::kempty_stringRootIndex); | 45 return LoadRoot(Heap::kempty_stringRootIndex); |
46 } | 46 } |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset, | 487 Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset, |
488 MachineType rep) { | 488 MachineType rep) { |
489 return Load(rep, buffer, IntPtrConstant(offset)); | 489 return Load(rep, buffer, IntPtrConstant(offset)); |
490 } | 490 } |
491 | 491 |
492 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset, | 492 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset, |
493 MachineType rep) { | 493 MachineType rep) { |
494 return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag)); | 494 return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag)); |
495 } | 495 } |
496 | 496 |
| 497 Node* CodeStubAssembler::LoadObjectField(Node* object, Node* offset, |
| 498 MachineType rep) { |
| 499 return Load(rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag))); |
| 500 } |
| 501 |
497 Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) { | 502 Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) { |
498 return LoadObjectField(object, HeapNumber::kValueOffset, | 503 return LoadObjectField(object, HeapNumber::kValueOffset, |
499 MachineType::Float64()); | 504 MachineType::Float64()); |
500 } | 505 } |
501 | 506 |
502 Node* CodeStubAssembler::LoadMap(Node* object) { | 507 Node* CodeStubAssembler::LoadMap(Node* object) { |
503 return LoadObjectField(object, HeapObject::kMapOffset); | 508 return LoadObjectField(object, HeapObject::kMapOffset); |
504 } | 509 } |
505 | 510 |
506 Node* CodeStubAssembler::LoadInstanceType(Node* object) { | 511 Node* CodeStubAssembler::LoadInstanceType(Node* object) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 } | 550 } |
546 | 551 |
547 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { | 552 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { |
548 return LoadObjectField(map, Map::kPrototypeOffset); | 553 return LoadObjectField(map, Map::kPrototypeOffset); |
549 } | 554 } |
550 | 555 |
551 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { | 556 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { |
552 return LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8()); | 557 return LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8()); |
553 } | 558 } |
554 | 559 |
| 560 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) { |
| 561 // See Map::GetInObjectProperties() for details. |
| 562 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
| 563 Assert(Int32GreaterThanOrEqual(LoadMapInstanceType(map), |
| 564 Int32Constant(FIRST_JS_OBJECT_TYPE))); |
| 565 return LoadObjectField( |
| 566 map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset, |
| 567 MachineType::Uint8()); |
| 568 } |
| 569 |
555 Node* CodeStubAssembler::LoadNameHashField(Node* name) { | 570 Node* CodeStubAssembler::LoadNameHashField(Node* name) { |
556 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); | 571 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); |
557 } | 572 } |
558 | 573 |
559 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { | 574 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { |
560 Node* hash_field = LoadNameHashField(name); | 575 Node* hash_field = LoadNameHashField(name); |
561 if (if_hash_not_computed != nullptr) { | 576 if (if_hash_not_computed != nullptr) { |
562 GotoIf(WordEqual( | 577 GotoIf(WordEqual( |
563 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), | 578 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), |
564 Int32Constant(0)), | 579 Int32Constant(0)), |
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 Node* value = Load(MachineType::Int32(), counter_address); | 1495 Node* value = Load(MachineType::Int32(), counter_address); |
1481 value = Int32Sub(value, Int32Constant(delta)); | 1496 value = Int32Sub(value, Int32Constant(delta)); |
1482 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value); | 1497 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value); |
1483 } | 1498 } |
1484 } | 1499 } |
1485 | 1500 |
1486 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, | 1501 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, |
1487 Variable* var_index, Label* if_keyisunique, | 1502 Variable* var_index, Label* if_keyisunique, |
1488 Label* if_bailout) { | 1503 Label* if_bailout) { |
1489 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); | 1504 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); |
| 1505 Comment("TryToName"); |
1490 | 1506 |
1491 Label if_keyissmi(this), if_keyisnotsmi(this); | 1507 Label if_keyissmi(this), if_keyisnotsmi(this); |
1492 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); | 1508 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); |
1493 Bind(&if_keyissmi); | 1509 Bind(&if_keyissmi); |
1494 { | 1510 { |
1495 // Negative smi keys are named properties. Handle in the runtime. | 1511 // Negative smi keys are named properties. Handle in the runtime. |
1496 GotoUnless(WordIsPositiveSmi(key), if_bailout); | 1512 GotoUnless(WordIsPositiveSmi(key), if_bailout); |
1497 | 1513 |
1498 var_index->Bind(SmiToWord32(key)); | 1514 var_index->Bind(SmiToWord32(key)); |
1499 Goto(if_keyisindex); | 1515 Goto(if_keyisindex); |
(...skipping 22 matching lines...) Expand all Loading... |
1522 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique); | 1538 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique); |
1523 // Key is an index. Check if it is small enough to be encoded in the | 1539 // Key is an index. Check if it is small enough to be encoded in the |
1524 // hash_field. Handle too big array index in runtime. | 1540 // hash_field. Handle too big array index in runtime. |
1525 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | 1541 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); |
1526 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout); | 1542 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout); |
1527 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); | 1543 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash)); |
1528 Goto(if_keyisindex); | 1544 Goto(if_keyisindex); |
1529 } | 1545 } |
1530 | 1546 |
1531 template <typename Dictionary> | 1547 template <typename Dictionary> |
| 1548 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { |
| 1549 Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); |
| 1550 return Int32Add(entry_index, |
| 1551 Int32Constant(Dictionary::kElementsStartIndex + field_index)); |
| 1552 } |
| 1553 |
| 1554 template <typename Dictionary> |
1532 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, | 1555 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
1533 Node* unique_name, Label* if_found, | 1556 Node* unique_name, Label* if_found, |
1534 Variable* var_entry, | 1557 Variable* var_name_index, |
1535 Label* if_not_found, | 1558 Label* if_not_found, |
1536 int inlined_probes) { | 1559 int inlined_probes) { |
1537 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); | 1560 DCHECK_EQ(MachineRepresentation::kWord32, var_name_index->rep()); |
1538 | 1561 Comment("NameDictionaryLookup"); |
1539 const int kElementsStartOffset = | |
1540 Dictionary::kElementsStartIndex * kPointerSize; | |
1541 | 1562 |
1542 Node* capacity = SmiToWord32(LoadFixedArrayElement( | 1563 Node* capacity = SmiToWord32(LoadFixedArrayElement( |
1543 dictionary, Int32Constant(Dictionary::kCapacityIndex))); | 1564 dictionary, Int32Constant(Dictionary::kCapacityIndex))); |
1544 Node* mask = Int32Sub(capacity, Int32Constant(1)); | 1565 Node* mask = Int32Sub(capacity, Int32Constant(1)); |
1545 Node* hash = LoadNameHash(unique_name); | 1566 Node* hash = LoadNameHash(unique_name); |
1546 | 1567 |
1547 // See Dictionary::FirstProbe(). | 1568 // See Dictionary::FirstProbe(). |
1548 Node* count = Int32Constant(0); | 1569 Node* count = Int32Constant(0); |
1549 Node* entry = Word32And(hash, mask); | 1570 Node* entry = Word32And(hash, mask); |
1550 | 1571 |
1551 for (int i = 0; i < inlined_probes; i++) { | 1572 for (int i = 0; i < inlined_probes; i++) { |
1552 // See Dictionary::EntryToIndex() | 1573 Node* index = EntryToIndex<Dictionary>(entry); |
1553 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); | 1574 var_name_index->Bind(index); |
1554 Node* current = | 1575 |
1555 LoadFixedArrayElement(dictionary, index, kElementsStartOffset); | 1576 Node* current = LoadFixedArrayElement(dictionary, index); |
1556 var_entry->Bind(entry); | |
1557 GotoIf(WordEqual(current, unique_name), if_found); | 1577 GotoIf(WordEqual(current, unique_name), if_found); |
1558 | 1578 |
1559 // See Dictionary::NextProbe(). | 1579 // See Dictionary::NextProbe(). |
1560 count = Int32Constant(i + 1); | 1580 count = Int32Constant(i + 1); |
1561 entry = Word32And(Int32Add(entry, count), mask); | 1581 entry = Word32And(Int32Add(entry, count), mask); |
1562 } | 1582 } |
1563 | 1583 |
1564 Node* undefined = UndefinedConstant(); | 1584 Node* undefined = UndefinedConstant(); |
1565 | 1585 |
1566 Variable var_count(this, MachineRepresentation::kWord32); | 1586 Variable var_count(this, MachineRepresentation::kWord32); |
1567 Variable* loop_vars[] = {&var_count, var_entry}; | 1587 Variable var_entry(this, MachineRepresentation::kWord32); |
1568 Label loop(this, 2, loop_vars); | 1588 Variable* loop_vars[] = {&var_count, &var_entry, var_name_index}; |
| 1589 Label loop(this, 3, loop_vars); |
1569 var_count.Bind(count); | 1590 var_count.Bind(count); |
1570 var_entry->Bind(entry); | 1591 var_entry.Bind(entry); |
1571 Goto(&loop); | 1592 Goto(&loop); |
1572 Bind(&loop); | 1593 Bind(&loop); |
1573 { | 1594 { |
1574 Node* count = var_count.value(); | 1595 Node* count = var_count.value(); |
1575 Node* entry = var_entry->value(); | 1596 Node* entry = var_entry.value(); |
1576 | 1597 |
1577 // See Dictionary::EntryToIndex() | 1598 Node* index = EntryToIndex<Dictionary>(entry); |
1578 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); | 1599 var_name_index->Bind(index); |
1579 Node* current = | 1600 |
1580 LoadFixedArrayElement(dictionary, index, kElementsStartOffset); | 1601 Node* current = LoadFixedArrayElement(dictionary, index); |
1581 GotoIf(WordEqual(current, undefined), if_not_found); | 1602 GotoIf(WordEqual(current, undefined), if_not_found); |
1582 GotoIf(WordEqual(current, unique_name), if_found); | 1603 GotoIf(WordEqual(current, unique_name), if_found); |
1583 | 1604 |
1584 // See Dictionary::NextProbe(). | 1605 // See Dictionary::NextProbe(). |
1585 count = Int32Add(count, Int32Constant(1)); | 1606 count = Int32Add(count, Int32Constant(1)); |
1586 entry = Word32And(Int32Add(entry, count), mask); | 1607 entry = Word32And(Int32Add(entry, count), mask); |
1587 | 1608 |
1588 var_count.Bind(count); | 1609 var_count.Bind(count); |
1589 var_entry->Bind(entry); | 1610 var_entry.Bind(entry); |
1590 Goto(&loop); | 1611 Goto(&loop); |
1591 } | 1612 } |
1592 } | 1613 } |
1593 | 1614 |
1594 // Instantiate template methods to workaround GCC compilation issue. | 1615 // Instantiate template methods to workaround GCC compilation issue. |
1595 template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( | 1616 template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( |
1596 Node*, Node*, Label*, Variable*, Label*, int); | 1617 Node*, Node*, Label*, Variable*, Label*, int); |
1597 template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( | 1618 template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( |
1598 Node*, Node*, Label*, Variable*, Label*, int); | 1619 Node*, Node*, Label*, Variable*, Label*, int); |
1599 | 1620 |
(...skipping 10 matching lines...) Expand all Loading... |
1610 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); | 1631 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); |
1611 return Word32And(hash, Int32Constant(0x3fffffff)); | 1632 return Word32And(hash, Int32Constant(0x3fffffff)); |
1612 } | 1633 } |
1613 | 1634 |
1614 template <typename Dictionary> | 1635 template <typename Dictionary> |
1615 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key, | 1636 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key, |
1616 Label* if_found, | 1637 Label* if_found, |
1617 Variable* var_entry, | 1638 Variable* var_entry, |
1618 Label* if_not_found) { | 1639 Label* if_not_found) { |
1619 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); | 1640 DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep()); |
1620 | 1641 Comment("NumberDictionaryLookup"); |
1621 const int kElementsStartOffset = | |
1622 Dictionary::kElementsStartIndex * kPointerSize; | |
1623 | 1642 |
1624 Node* capacity = SmiToWord32(LoadFixedArrayElement( | 1643 Node* capacity = SmiToWord32(LoadFixedArrayElement( |
1625 dictionary, Int32Constant(Dictionary::kCapacityIndex))); | 1644 dictionary, Int32Constant(Dictionary::kCapacityIndex))); |
1626 Node* mask = Int32Sub(capacity, Int32Constant(1)); | 1645 Node* mask = Int32Sub(capacity, Int32Constant(1)); |
1627 | 1646 |
1628 Node* seed; | 1647 Node* seed; |
1629 if (Dictionary::ShapeT::UsesSeed) { | 1648 if (Dictionary::ShapeT::UsesSeed) { |
1630 seed = HashSeed(); | 1649 seed = HashSeed(); |
1631 } else { | 1650 } else { |
1632 seed = Int32Constant(kZeroHashSeed); | 1651 seed = Int32Constant(kZeroHashSeed); |
(...skipping 12 matching lines...) Expand all Loading... |
1645 Variable* loop_vars[] = {&var_count, var_entry}; | 1664 Variable* loop_vars[] = {&var_count, var_entry}; |
1646 Label loop(this, 2, loop_vars); | 1665 Label loop(this, 2, loop_vars); |
1647 var_count.Bind(count); | 1666 var_count.Bind(count); |
1648 var_entry->Bind(entry); | 1667 var_entry->Bind(entry); |
1649 Goto(&loop); | 1668 Goto(&loop); |
1650 Bind(&loop); | 1669 Bind(&loop); |
1651 { | 1670 { |
1652 Node* count = var_count.value(); | 1671 Node* count = var_count.value(); |
1653 Node* entry = var_entry->value(); | 1672 Node* entry = var_entry->value(); |
1654 | 1673 |
1655 // See Dictionary::EntryToIndex() | 1674 Node* index = EntryToIndex<Dictionary>(entry); |
1656 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize)); | 1675 Node* current = LoadFixedArrayElement(dictionary, index); |
1657 Node* current = | |
1658 LoadFixedArrayElement(dictionary, index, kElementsStartOffset); | |
1659 GotoIf(WordEqual(current, undefined), if_not_found); | 1676 GotoIf(WordEqual(current, undefined), if_not_found); |
1660 Label next_probe(this); | 1677 Label next_probe(this); |
1661 { | 1678 { |
1662 Label if_currentissmi(this), if_currentisnotsmi(this); | 1679 Label if_currentissmi(this), if_currentisnotsmi(this); |
1663 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); | 1680 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi); |
1664 Bind(&if_currentissmi); | 1681 Bind(&if_currentissmi); |
1665 { | 1682 { |
1666 Node* current_value = SmiToWord32(current); | 1683 Node* current_value = SmiToWord32(current); |
1667 Branch(Word32Equal(current_value, key), if_found, &next_probe); | 1684 Branch(Word32Equal(current_value, key), if_found, &next_probe); |
1668 } | 1685 } |
(...skipping 11 matching lines...) Expand all Loading... |
1680 // See Dictionary::NextProbe(). | 1697 // See Dictionary::NextProbe(). |
1681 count = Int32Add(count, Int32Constant(1)); | 1698 count = Int32Add(count, Int32Constant(1)); |
1682 entry = Word32And(Int32Add(entry, count), mask); | 1699 entry = Word32And(Int32Add(entry, count), mask); |
1683 | 1700 |
1684 var_count.Bind(count); | 1701 var_count.Bind(count); |
1685 var_entry->Bind(entry); | 1702 var_entry->Bind(entry); |
1686 Goto(&loop); | 1703 Goto(&loop); |
1687 } | 1704 } |
1688 } | 1705 } |
1689 | 1706 |
1690 void CodeStubAssembler::TryLookupProperty(Node* object, Node* map, | 1707 void CodeStubAssembler::TryLookupProperty( |
1691 Node* instance_type, | 1708 Node* object, Node* map, Node* instance_type, Node* unique_name, |
1692 Node* unique_name, Label* if_found, | 1709 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, |
1693 Label* if_not_found, | 1710 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, |
1694 Label* if_bailout) { | 1711 Label* if_bailout) { |
| 1712 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); |
| 1713 DCHECK_EQ(MachineRepresentation::kWord32, var_name_index->rep()); |
| 1714 |
1695 Label if_objectisspecial(this); | 1715 Label if_objectisspecial(this); |
1696 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 1716 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
1697 GotoIf(Int32LessThanOrEqual(instance_type, | 1717 GotoIf(Int32LessThanOrEqual(instance_type, |
1698 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 1718 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
1699 &if_objectisspecial); | 1719 &if_objectisspecial); |
1700 | 1720 |
| 1721 Node* bit_field = LoadMapBitField(map); |
| 1722 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | |
| 1723 1 << Map::kIsAccessCheckNeeded); |
| 1724 Assert(Word32Equal(Word32And(bit_field, mask), Int32Constant(0))); |
| 1725 |
1701 Node* bit_field3 = LoadMapBitField3(map); | 1726 Node* bit_field3 = LoadMapBitField3(map); |
1702 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); | 1727 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); |
1703 Label if_isfastmap(this), if_isslowmap(this); | 1728 Label if_isfastmap(this), if_isslowmap(this); |
1704 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap); | 1729 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap); |
1705 Bind(&if_isfastmap); | 1730 Bind(&if_isfastmap); |
1706 { | 1731 { |
| 1732 Comment("DescriptorArrayLookup"); |
1707 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); | 1733 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); |
1708 // Bail out to the runtime for large numbers of own descriptors. The stub | 1734 // Bail out to the runtime for large numbers of own descriptors. The stub |
1709 // only does linear search, which becomes too expensive in that case. | 1735 // only does linear search, which becomes too expensive in that case. |
1710 { | 1736 { |
1711 static const int32_t kMaxLinear = 210; | 1737 static const int32_t kMaxLinear = 210; |
1712 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout); | 1738 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout); |
1713 } | 1739 } |
1714 Node* descriptors = LoadMapDescriptors(map); | 1740 Node* descriptors = LoadMapDescriptors(map); |
| 1741 var_meta_storage->Bind(descriptors); |
1715 | 1742 |
1716 Variable var_descriptor(this, MachineRepresentation::kWord32); | 1743 Variable var_descriptor(this, MachineRepresentation::kWord32); |
1717 Label loop(this, &var_descriptor); | 1744 Label loop(this, &var_descriptor); |
1718 var_descriptor.Bind(Int32Constant(0)); | 1745 var_descriptor.Bind(Int32Constant(0)); |
1719 Goto(&loop); | 1746 Goto(&loop); |
1720 Bind(&loop); | 1747 Bind(&loop); |
1721 { | 1748 { |
1722 Node* index = var_descriptor.value(); | 1749 Node* index = var_descriptor.value(); |
1723 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0)); | 1750 Node* name_offset = Int32Constant(DescriptorArray::ToKeyIndex(0)); |
1724 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize); | 1751 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize); |
1725 GotoIf(Word32Equal(index, nof), if_not_found); | 1752 GotoIf(Word32Equal(index, nof), if_not_found); |
1726 | 1753 |
1727 Node* array_index = Int32Add(offset, Int32Mul(index, factor)); | 1754 Node* name_index = Int32Add(name_offset, Int32Mul(index, factor)); |
1728 Node* current = LoadFixedArrayElement(descriptors, array_index); | 1755 Node* name = LoadFixedArrayElement(descriptors, name_index); |
1729 GotoIf(WordEqual(current, unique_name), if_found); | 1756 |
| 1757 var_name_index->Bind(name_index); |
| 1758 GotoIf(WordEqual(name, unique_name), if_found_fast); |
1730 | 1759 |
1731 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); | 1760 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); |
1732 Goto(&loop); | 1761 Goto(&loop); |
1733 } | 1762 } |
1734 } | 1763 } |
1735 Bind(&if_isslowmap); | 1764 Bind(&if_isslowmap); |
1736 { | 1765 { |
1737 Variable var_entry(this, MachineRepresentation::kWord32); | |
1738 Node* dictionary = LoadProperties(object); | 1766 Node* dictionary = LoadProperties(object); |
1739 | 1767 var_meta_storage->Bind(dictionary); |
1740 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found, | 1768 |
1741 &var_entry, if_not_found); | 1769 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, |
| 1770 var_name_index, if_not_found); |
1742 } | 1771 } |
1743 Bind(&if_objectisspecial); | 1772 Bind(&if_objectisspecial); |
1744 { | 1773 { |
1745 // Handle global object here and other special objects in runtime. | 1774 // Handle global object here and other special objects in runtime. |
1746 GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), | 1775 GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), |
1747 if_bailout); | 1776 if_bailout); |
1748 Variable var_entry(this, MachineRepresentation::kWord32); | 1777 |
| 1778 // Handle interceptors and access checks in runtime. |
| 1779 Node* bit_field = LoadMapBitField(map); |
| 1780 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | |
| 1781 1 << Map::kIsAccessCheckNeeded); |
| 1782 GotoIf(Word32NotEqual(Word32And(bit_field, mask), Int32Constant(0)), |
| 1783 if_bailout); |
| 1784 |
1749 Node* dictionary = LoadProperties(object); | 1785 Node* dictionary = LoadProperties(object); |
1750 | 1786 var_meta_storage->Bind(dictionary); |
1751 NameDictionaryLookup<GlobalDictionary>(dictionary, unique_name, if_found, | 1787 |
1752 &var_entry, if_not_found); | 1788 NameDictionaryLookup<GlobalDictionary>( |
1753 } | 1789 dictionary, unique_name, if_found_global, var_name_index, if_not_found); |
1754 } | 1790 } |
1755 | 1791 } |
| 1792 |
| 1793 void CodeStubAssembler::TryHasOwnProperty(compiler::Node* object, |
| 1794 compiler::Node* map, |
| 1795 compiler::Node* instance_type, |
| 1796 compiler::Node* unique_name, |
| 1797 Label* if_found, Label* if_not_found, |
| 1798 Label* if_bailout) { |
| 1799 Comment("TryHasOwnProperty"); |
| 1800 Variable var_meta_storage(this, MachineRepresentation::kTagged); |
| 1801 Variable var_name_index(this, MachineRepresentation::kWord32); |
| 1802 |
| 1803 Label if_found_global(this); |
| 1804 TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found, |
| 1805 &if_found_global, &var_meta_storage, &var_name_index, |
| 1806 if_not_found, if_bailout); |
| 1807 Bind(&if_found_global); |
| 1808 { |
| 1809 Variable var_value(this, MachineRepresentation::kTagged); |
| 1810 Variable var_details(this, MachineRepresentation::kWord32); |
| 1811 // Check if the property cell is not deleted. |
| 1812 LoadPropertyFromGlobalDictionary(var_meta_storage.value(), |
| 1813 var_name_index.value(), &var_value, |
| 1814 &var_details, if_not_found); |
| 1815 Goto(if_found); |
| 1816 } |
| 1817 } |
| 1818 |
| 1819 void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, |
| 1820 Node* descriptors, |
| 1821 Node* name_index, |
| 1822 Variable* var_details, |
| 1823 Variable* var_value) { |
| 1824 DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep()); |
| 1825 DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); |
| 1826 Comment("[ LoadPropertyFromFastObject"); |
| 1827 |
| 1828 const int name_to_details_offset = |
| 1829 (DescriptorArray::kDescriptorDetails - DescriptorArray::kDescriptorKey) * |
| 1830 kPointerSize; |
| 1831 const int name_to_value_offset = |
| 1832 (DescriptorArray::kDescriptorValue - DescriptorArray::kDescriptorKey) * |
| 1833 kPointerSize; |
| 1834 |
| 1835 Node* details = SmiToWord32( |
| 1836 LoadFixedArrayElement(descriptors, name_index, name_to_details_offset)); |
| 1837 var_details->Bind(details); |
| 1838 |
| 1839 Node* location = BitFieldDecode<PropertyDetails::LocationField>(details); |
| 1840 |
| 1841 Label if_in_field(this), if_in_descriptor(this), done(this); |
| 1842 Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, |
| 1843 &if_in_descriptor); |
| 1844 Bind(&if_in_field); |
| 1845 { |
| 1846 Node* field_index = |
| 1847 BitFieldDecode<PropertyDetails::FieldIndexField>(details); |
| 1848 Node* representation = |
| 1849 BitFieldDecode<PropertyDetails::RepresentationField>(details); |
| 1850 |
| 1851 Node* inobject_properties = LoadMapInobjectProperties(map); |
| 1852 |
| 1853 Label if_inobject(this), if_backing_store(this); |
| 1854 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 1855 Label rebox_double(this, &var_double_value); |
| 1856 BranchIfInt32LessThan(field_index, inobject_properties, &if_inobject, |
| 1857 &if_backing_store); |
| 1858 Bind(&if_inobject); |
| 1859 { |
| 1860 Comment("if_inobject"); |
| 1861 Node* field_offset = ChangeInt32ToIntPtr( |
| 1862 Int32Mul(Int32Sub(LoadMapInstanceSize(map), |
| 1863 Int32Sub(inobject_properties, field_index)), |
| 1864 Int32Constant(kPointerSize))); |
| 1865 |
| 1866 Label if_double(this), if_tagged(this); |
| 1867 BranchIfWord32NotEqual(representation, |
| 1868 Int32Constant(Representation::kDouble), &if_tagged, |
| 1869 &if_double); |
| 1870 Bind(&if_tagged); |
| 1871 { |
| 1872 var_value->Bind(LoadObjectField(object, field_offset)); |
| 1873 Goto(&done); |
| 1874 } |
| 1875 Bind(&if_double); |
| 1876 { |
| 1877 if (FLAG_unbox_double_fields) { |
| 1878 var_double_value.Bind( |
| 1879 LoadObjectField(object, field_offset, MachineType::Float64())); |
| 1880 } else { |
| 1881 Node* mutable_heap_number = LoadObjectField(object, field_offset); |
| 1882 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
| 1883 } |
| 1884 Goto(&rebox_double); |
| 1885 } |
| 1886 } |
| 1887 Bind(&if_backing_store); |
| 1888 { |
| 1889 Comment("if_backing_store"); |
| 1890 Node* properties = LoadProperties(object); |
| 1891 field_index = Int32Sub(field_index, inobject_properties); |
| 1892 Node* value = LoadFixedArrayElement(properties, field_index); |
| 1893 |
| 1894 Label if_double(this), if_tagged(this); |
| 1895 BranchIfWord32NotEqual(representation, |
| 1896 Int32Constant(Representation::kDouble), &if_tagged, |
| 1897 &if_double); |
| 1898 Bind(&if_tagged); |
| 1899 { |
| 1900 var_value->Bind(value); |
| 1901 Goto(&done); |
| 1902 } |
| 1903 Bind(&if_double); |
| 1904 { |
| 1905 var_double_value.Bind(LoadHeapNumberValue(value)); |
| 1906 Goto(&rebox_double); |
| 1907 } |
| 1908 } |
| 1909 Bind(&rebox_double); |
| 1910 { |
| 1911 Comment("rebox_double"); |
| 1912 Node* heap_number = AllocateHeapNumber(); |
| 1913 StoreHeapNumberValue(heap_number, var_double_value.value()); |
| 1914 var_value->Bind(heap_number); |
| 1915 Goto(&done); |
| 1916 } |
| 1917 } |
| 1918 Bind(&if_in_descriptor); |
| 1919 { |
| 1920 Node* value = |
| 1921 LoadFixedArrayElement(descriptors, name_index, name_to_value_offset); |
| 1922 var_value->Bind(value); |
| 1923 Goto(&done); |
| 1924 } |
| 1925 Bind(&done); |
| 1926 |
| 1927 Comment("] LoadPropertyFromFastObject"); |
| 1928 } |
| 1929 |
| 1930 void CodeStubAssembler::LoadPropertyFromNameDictionary(Node* dictionary, |
| 1931 Node* name_index, |
| 1932 Variable* var_details, |
| 1933 Variable* var_value) { |
| 1934 Comment("LoadPropertyFromNameDictionary"); |
| 1935 |
| 1936 const int name_to_details_offset = |
| 1937 (NameDictionary::kEntryDetailsIndex - NameDictionary::kEntryKeyIndex) * |
| 1938 kPointerSize; |
| 1939 const int name_to_value_offset = |
| 1940 (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) * |
| 1941 kPointerSize; |
| 1942 |
| 1943 Node* details = SmiToWord32( |
| 1944 LoadFixedArrayElement(dictionary, name_index, name_to_details_offset)); |
| 1945 |
| 1946 var_details->Bind(details); |
| 1947 var_value->Bind( |
| 1948 LoadFixedArrayElement(dictionary, name_index, name_to_value_offset)); |
| 1949 |
| 1950 Comment("] LoadPropertyFromNameDictionary"); |
| 1951 } |
| 1952 |
| 1953 void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary, |
| 1954 Node* name_index, |
| 1955 Variable* var_details, |
| 1956 Variable* var_value, |
| 1957 Label* if_deleted) { |
| 1958 Comment("[ LoadPropertyFromGlobalDictionary"); |
| 1959 |
| 1960 const int name_to_value_offset = |
| 1961 (GlobalDictionary::kEntryValueIndex - GlobalDictionary::kEntryKeyIndex) * |
| 1962 kPointerSize; |
| 1963 |
| 1964 Node* property_cell = |
| 1965 LoadFixedArrayElement(dictionary, name_index, name_to_value_offset); |
| 1966 |
| 1967 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); |
| 1968 GotoIf(WordEqual(value, TheHoleConstant()), if_deleted); |
| 1969 |
| 1970 var_value->Bind(value); |
| 1971 |
| 1972 Node* details = |
| 1973 SmiToWord32(LoadObjectField(property_cell, PropertyCell::kDetailsOffset)); |
| 1974 var_details->Bind(details); |
| 1975 |
| 1976 Comment("] LoadPropertyFromGlobalDictionary"); |
| 1977 } |
| 1978 |
| 1979 void CodeStubAssembler::TryGetOwnProperty( |
| 1980 Node* context, Node* receiver, Node* object, Node* map, Node* instance_type, |
| 1981 Node* unique_name, Label* if_found_value, Variable* var_value, |
| 1982 Label* if_not_found, Label* if_bailout) { |
| 1983 DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); |
| 1984 Comment("TryGetOwnProperty"); |
| 1985 |
| 1986 Variable var_meta_storage(this, MachineRepresentation::kTagged); |
| 1987 Variable var_entry(this, MachineRepresentation::kWord32); |
| 1988 |
| 1989 Label if_found_fast(this), if_found_dict(this), if_found_global(this); |
| 1990 |
| 1991 Variable var_details(this, MachineRepresentation::kWord32); |
| 1992 Variable* vars[] = {var_value, &var_details}; |
| 1993 Label if_found(this, 2, vars); |
| 1994 |
| 1995 TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast, |
| 1996 &if_found_dict, &if_found_global, &var_meta_storage, |
| 1997 &var_entry, if_not_found, if_bailout); |
| 1998 Bind(&if_found_fast); |
| 1999 { |
| 2000 Node* descriptors = var_meta_storage.value(); |
| 2001 Node* name_index = var_entry.value(); |
| 2002 |
| 2003 LoadPropertyFromFastObject(object, map, descriptors, name_index, |
| 2004 &var_details, var_value); |
| 2005 Goto(&if_found); |
| 2006 } |
| 2007 Bind(&if_found_dict); |
| 2008 { |
| 2009 Node* dictionary = var_meta_storage.value(); |
| 2010 Node* entry = var_entry.value(); |
| 2011 LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value); |
| 2012 Goto(&if_found); |
| 2013 } |
| 2014 Bind(&if_found_global); |
| 2015 { |
| 2016 Node* dictionary = var_meta_storage.value(); |
| 2017 Node* entry = var_entry.value(); |
| 2018 |
| 2019 LoadPropertyFromGlobalDictionary(dictionary, entry, &var_details, var_value, |
| 2020 if_not_found); |
| 2021 Goto(&if_found); |
| 2022 } |
| 2023 // Here we have details and value which could be an accessor. |
| 2024 Bind(&if_found); |
| 2025 { |
| 2026 Node* details = var_details.value(); |
| 2027 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); |
| 2028 |
| 2029 Label if_accessor(this); |
| 2030 Branch(Word32Equal(kind, Int32Constant(kData)), if_found_value, |
| 2031 &if_accessor); |
| 2032 Bind(&if_accessor); |
| 2033 { |
| 2034 Node* accessor_pair = var_value->value(); |
| 2035 GotoIf(Word32Equal(LoadInstanceType(accessor_pair), |
| 2036 Int32Constant(ACCESSOR_INFO_TYPE)), |
| 2037 if_bailout); |
| 2038 AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE); |
| 2039 Node* getter = |
| 2040 LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); |
| 2041 Node* getter_map = LoadMap(getter); |
| 2042 Node* instance_type = LoadMapInstanceType(getter_map); |
| 2043 // FunctionTemplateInfo getters are not supported yet. |
| 2044 GotoIf(Word32Equal(instance_type, |
| 2045 Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)), |
| 2046 if_bailout); |
| 2047 |
| 2048 // Return undefined if the {getter} is not callable. |
| 2049 var_value->Bind(UndefinedConstant()); |
| 2050 GotoIf(Word32Equal(Word32And(LoadMapBitField(getter_map), |
| 2051 Int32Constant(1 << Map::kIsCallable)), |
| 2052 Int32Constant(0)), |
| 2053 if_found_value); |
| 2054 |
| 2055 // Call the accessor. |
| 2056 Callable callable = CodeFactory::Call(isolate()); |
| 2057 Node* result = CallJS(callable, context, getter, receiver); |
| 2058 var_value->Bind(result); |
| 2059 Goto(if_found_value); |
| 2060 } |
| 2061 } |
| 2062 } |
| 2063 |
1756 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, | 2064 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, |
1757 Node* instance_type, Node* index, | 2065 Node* instance_type, Node* index, |
1758 Label* if_found, Label* if_not_found, | 2066 Label* if_found, Label* if_not_found, |
1759 Label* if_bailout) { | 2067 Label* if_bailout) { |
1760 // Handle special objects in runtime. | 2068 // Handle special objects in runtime. |
1761 GotoIf(Int32LessThanOrEqual(instance_type, | 2069 GotoIf(Int32LessThanOrEqual(instance_type, |
1762 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 2070 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
1763 if_bailout); | 2071 if_bailout); |
1764 | 2072 |
1765 Node* bit_field2 = LoadMapBitField2(map); | 2073 Node* bit_field2 = LoadMapBitField2(map); |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2355 } | 2663 } |
2356 Bind(&miss); | 2664 Bind(&miss); |
2357 { | 2665 { |
2358 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, | 2666 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, |
2359 p->vector); | 2667 p->vector); |
2360 } | 2668 } |
2361 } | 2669 } |
2362 | 2670 |
2363 } // namespace internal | 2671 } // namespace internal |
2364 } // namespace v8 | 2672 } // namespace v8 |
OLD | NEW |