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 | |
1715 { | |
1716 Node* bit_field = LoadMapBitField(map); | |
1717 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | | |
1718 1 << Map::kIsAccessCheckNeeded); | |
1719 GotoIf(Word32NotEqual(Word32And(bit_field, mask), Int32Constant(0)), | |
Toon Verwaest
2016/06/23 12:34:54
This shouldn't be possible if we check LAST_SPECIA
Igor Sheludko
2016/06/27 09:32:17
Done.
| |
1720 if_bailout); | |
1721 } | |
1722 | |
1695 Label if_objectisspecial(this); | 1723 Label if_objectisspecial(this); |
1696 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 1724 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
1697 GotoIf(Int32LessThanOrEqual(instance_type, | 1725 GotoIf(Int32LessThanOrEqual(instance_type, |
1698 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 1726 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
1699 &if_objectisspecial); | 1727 &if_objectisspecial); |
1700 | 1728 |
1701 Node* bit_field3 = LoadMapBitField3(map); | 1729 Node* bit_field3 = LoadMapBitField3(map); |
1702 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); | 1730 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); |
1703 Label if_isfastmap(this), if_isslowmap(this); | 1731 Label if_isfastmap(this), if_isslowmap(this); |
1704 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap); | 1732 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap); |
1705 Bind(&if_isfastmap); | 1733 Bind(&if_isfastmap); |
1706 { | 1734 { |
1735 Comment("DescriptorArrayLookup"); | |
1707 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); | 1736 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); |
1708 // Bail out to the runtime for large numbers of own descriptors. The stub | 1737 // 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. | 1738 // only does linear search, which becomes too expensive in that case. |
1710 { | 1739 { |
1711 static const int32_t kMaxLinear = 210; | 1740 static const int32_t kMaxLinear = 210; |
1712 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout); | 1741 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout); |
1713 } | 1742 } |
1714 Node* descriptors = LoadMapDescriptors(map); | 1743 Node* descriptors = LoadMapDescriptors(map); |
1744 var_meta_storage->Bind(descriptors); | |
1715 | 1745 |
1716 Variable var_descriptor(this, MachineRepresentation::kWord32); | 1746 Variable var_descriptor(this, MachineRepresentation::kWord32); |
1717 Label loop(this, &var_descriptor); | 1747 Label loop(this, &var_descriptor); |
1718 var_descriptor.Bind(Int32Constant(0)); | 1748 var_descriptor.Bind(Int32Constant(0)); |
1719 Goto(&loop); | 1749 Goto(&loop); |
1720 Bind(&loop); | 1750 Bind(&loop); |
1721 { | 1751 { |
1722 Node* index = var_descriptor.value(); | 1752 Node* index = var_descriptor.value(); |
1723 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0)); | 1753 Node* name_offset = Int32Constant(DescriptorArray::ToKeyIndex(0)); |
1724 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize); | 1754 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize); |
1725 GotoIf(Word32Equal(index, nof), if_not_found); | 1755 GotoIf(Word32Equal(index, nof), if_not_found); |
1726 | 1756 |
1727 Node* array_index = Int32Add(offset, Int32Mul(index, factor)); | 1757 Node* name_index = Int32Add(name_offset, Int32Mul(index, factor)); |
1728 Node* current = LoadFixedArrayElement(descriptors, array_index); | 1758 Node* name = LoadFixedArrayElement(descriptors, name_index); |
1729 GotoIf(WordEqual(current, unique_name), if_found); | 1759 |
1760 var_name_index->Bind(name_index); | |
1761 GotoIf(WordEqual(name, unique_name), if_found_fast); | |
1730 | 1762 |
1731 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); | 1763 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); |
1732 Goto(&loop); | 1764 Goto(&loop); |
1733 } | 1765 } |
1734 } | 1766 } |
1735 Bind(&if_isslowmap); | 1767 Bind(&if_isslowmap); |
1736 { | 1768 { |
1737 Variable var_entry(this, MachineRepresentation::kWord32); | |
1738 Node* dictionary = LoadProperties(object); | 1769 Node* dictionary = LoadProperties(object); |
1739 | 1770 var_meta_storage->Bind(dictionary); |
1740 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found, | 1771 |
1741 &var_entry, if_not_found); | 1772 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, |
1773 var_name_index, if_not_found); | |
1742 } | 1774 } |
1743 Bind(&if_objectisspecial); | 1775 Bind(&if_objectisspecial); |
1744 { | 1776 { |
1745 // Handle global object here and other special objects in runtime. | 1777 // Handle global object here and other special objects in runtime. |
1746 GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), | 1778 GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), |
1747 if_bailout); | 1779 if_bailout); |
1748 Variable var_entry(this, MachineRepresentation::kWord32); | 1780 |
1749 Node* dictionary = LoadProperties(object); | 1781 Node* dictionary = LoadProperties(object); |
1750 | 1782 var_meta_storage->Bind(dictionary); |
1751 NameDictionaryLookup<GlobalDictionary>(dictionary, unique_name, if_found, | 1783 |
1752 &var_entry, if_not_found); | 1784 NameDictionaryLookup<GlobalDictionary>( |
1753 } | 1785 dictionary, unique_name, if_found_global, var_name_index, if_not_found); |
1754 } | 1786 } |
1755 | 1787 } |
1788 | |
1789 void CodeStubAssembler::TryHasOwnProperty(compiler::Node* object, | |
1790 compiler::Node* map, | |
1791 compiler::Node* instance_type, | |
1792 compiler::Node* unique_name, | |
1793 Label* if_found, Label* if_not_found, | |
1794 Label* if_bailout) { | |
1795 Comment("TryHasOwnProperty"); | |
1796 Variable var_meta_storage(this, MachineRepresentation::kTagged); | |
1797 Variable var_name_index(this, MachineRepresentation::kWord32); | |
1798 | |
1799 TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found, | |
1800 if_found, &var_meta_storage, &var_name_index, if_not_found, | |
1801 if_bailout); | |
1802 } | |
1803 | |
1804 void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, | |
1805 Node* descriptors, | |
1806 Node* name_index, | |
1807 Variable* var_details, | |
1808 Variable* var_value) { | |
1809 DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep()); | |
1810 DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); | |
1811 Comment("[ LoadPropertyFromFastObject"); | |
1812 | |
1813 const int name_to_details_offset = | |
1814 (DescriptorArray::kDescriptorDetails - DescriptorArray::kDescriptorKey) * | |
1815 kPointerSize; | |
1816 const int name_to_value_offset = | |
1817 (DescriptorArray::kDescriptorValue - DescriptorArray::kDescriptorKey) * | |
1818 kPointerSize; | |
1819 | |
1820 Node* details = SmiToWord32( | |
1821 LoadFixedArrayElement(descriptors, name_index, name_to_details_offset)); | |
1822 var_details->Bind(details); | |
1823 | |
1824 Node* location = BitFieldDecode<PropertyDetails::LocationField>(details); | |
1825 | |
1826 Label if_in_field(this), if_in_descriptor(this), done(this); | |
1827 Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, | |
1828 &if_in_descriptor); | |
1829 Bind(&if_in_field); | |
1830 { | |
1831 Node* field_index = | |
1832 BitFieldDecode<PropertyDetails::FieldIndexField>(details); | |
1833 Node* representation = | |
1834 BitFieldDecode<PropertyDetails::RepresentationField>(details); | |
1835 | |
1836 Node* inobject_properties = LoadMapInobjectProperties(map); | |
1837 | |
1838 Label if_inobject(this), if_backing_store(this); | |
1839 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
1840 Label rebox_double(this, &var_double_value); | |
1841 BranchIfInt32LessThan(field_index, inobject_properties, &if_inobject, | |
1842 &if_backing_store); | |
1843 Bind(&if_inobject); | |
1844 { | |
1845 Comment("if_inobject"); | |
1846 Node* field_offset = ChangeInt32ToIntPtr( | |
1847 Int32Mul(Int32Sub(LoadMapInstanceSize(map), | |
1848 Int32Sub(inobject_properties, field_index)), | |
1849 Int32Constant(kPointerSize))); | |
1850 | |
1851 Label if_double(this), if_tagged(this); | |
1852 BranchIfWord32NotEqual(representation, | |
1853 Int32Constant(Representation::kDouble), &if_tagged, | |
1854 &if_double); | |
1855 Bind(&if_tagged); | |
1856 { | |
1857 var_value->Bind(LoadObjectField(object, field_offset)); | |
1858 Goto(&done); | |
1859 } | |
1860 Bind(&if_double); | |
1861 { | |
1862 if (FLAG_unbox_double_fields) { | |
1863 var_double_value.Bind( | |
1864 LoadObjectField(object, field_offset, MachineType::Float64())); | |
1865 } else { | |
1866 Node* mutable_heap_number = LoadObjectField(object, field_offset); | |
1867 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | |
1868 } | |
1869 Goto(&rebox_double); | |
1870 } | |
1871 } | |
1872 Bind(&if_backing_store); | |
1873 { | |
1874 Comment("if_backing_store"); | |
1875 Node* properties = LoadProperties(object); | |
1876 field_index = Int32Sub(field_index, inobject_properties); | |
1877 Node* value = LoadFixedArrayElement(properties, field_index); | |
1878 | |
1879 Label if_double(this), if_tagged(this); | |
1880 BranchIfWord32NotEqual(representation, | |
1881 Int32Constant(Representation::kDouble), &if_tagged, | |
1882 &if_double); | |
1883 Bind(&if_tagged); | |
1884 { | |
1885 var_value->Bind(value); | |
1886 Goto(&done); | |
1887 } | |
1888 Bind(&if_double); | |
1889 { | |
1890 var_double_value.Bind(LoadHeapNumberValue(value)); | |
1891 Goto(&rebox_double); | |
1892 } | |
1893 } | |
1894 Bind(&rebox_double); | |
1895 { | |
1896 Comment("rebox_double"); | |
1897 Node* heap_number = AllocateHeapNumber(); | |
1898 StoreHeapNumberValue(heap_number, var_double_value.value()); | |
1899 var_value->Bind(heap_number); | |
1900 Goto(&done); | |
1901 } | |
1902 } | |
1903 Bind(&if_in_descriptor); | |
1904 { | |
1905 Node* value = | |
1906 LoadFixedArrayElement(descriptors, name_index, name_to_value_offset); | |
1907 var_value->Bind(value); | |
1908 Goto(&done); | |
1909 } | |
1910 Bind(&done); | |
1911 | |
1912 Comment("] LoadPropertyFromFastObject"); | |
1913 } | |
1914 | |
1915 void CodeStubAssembler::LoadPropertyFromNameDictionary(Node* dictionary, | |
1916 Node* name_index, | |
1917 Variable* var_details, | |
1918 Variable* var_value) { | |
1919 Comment("LoadPropertyFromNameDictionary"); | |
1920 | |
1921 const int name_to_details_offset = | |
1922 (NameDictionary::kEntryDetailsIndex - NameDictionary::kEntryKeyIndex) * | |
1923 kPointerSize; | |
1924 const int name_to_value_offset = | |
1925 (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) * | |
1926 kPointerSize; | |
1927 | |
1928 Node* details = SmiToWord32( | |
1929 LoadFixedArrayElement(dictionary, name_index, name_to_details_offset)); | |
1930 | |
1931 var_details->Bind(details); | |
1932 var_value->Bind( | |
1933 LoadFixedArrayElement(dictionary, name_index, name_to_value_offset)); | |
1934 | |
1935 Comment("] LoadPropertyFromNameDictionary"); | |
1936 } | |
1937 | |
1938 void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary, | |
1939 Node* name_index, | |
1940 Variable* var_details, | |
1941 Variable* var_value, | |
1942 Label* if_deleted) { | |
1943 Comment("[ LoadPropertyFromGlobalDictionary"); | |
1944 | |
1945 const int name_to_value_offset = | |
1946 (GlobalDictionary::kEntryValueIndex - GlobalDictionary::kEntryKeyIndex) * | |
1947 kPointerSize; | |
1948 | |
1949 Node* property_cell = | |
1950 LoadFixedArrayElement(dictionary, name_index, name_to_value_offset); | |
1951 | |
1952 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); | |
1953 GotoIf(WordEqual(value, TheHoleConstant()), if_deleted); | |
Toon Verwaest
2016/06/23 12:34:54
This should already have been handled in TryLookup
Igor Sheludko
2016/06/27 09:32:17
Currently it's the caller responsibility to do a h
| |
1954 | |
1955 var_value->Bind(value); | |
1956 | |
1957 Node* details = | |
1958 SmiToWord32(LoadObjectField(property_cell, PropertyCell::kDetailsOffset)); | |
1959 var_details->Bind(details); | |
1960 | |
1961 Comment("] LoadPropertyFromGlobalDictionary"); | |
1962 } | |
1963 | |
1964 void CodeStubAssembler::TryGetOwnProperty( | |
1965 Node* context, Node* receiver, Node* object, Node* map, Node* instance_type, | |
1966 Node* unique_name, Label* if_found_value, Variable* var_value, | |
1967 Label* if_not_found, Label* if_bailout) { | |
1968 DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); | |
1969 Comment("TryGetOwnProperty"); | |
1970 | |
1971 Variable var_meta_storage(this, MachineRepresentation::kTagged); | |
1972 Variable var_entry(this, MachineRepresentation::kWord32); | |
1973 | |
1974 Label if_found_fast(this), if_found_dict(this), if_found_global(this); | |
1975 | |
1976 Variable var_details(this, MachineRepresentation::kWord32); | |
1977 Variable* vars[] = {var_value, &var_details}; | |
1978 Label if_found(this, 2, vars); | |
1979 | |
1980 TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast, | |
1981 &if_found_dict, &if_found_global, &var_meta_storage, | |
1982 &var_entry, if_not_found, if_bailout); | |
1983 Bind(&if_found_fast); | |
1984 { | |
1985 Node* descriptors = var_meta_storage.value(); | |
1986 Node* name_index = var_entry.value(); | |
1987 | |
1988 LoadPropertyFromFastObject(object, map, descriptors, name_index, | |
1989 &var_details, var_value); | |
1990 Goto(&if_found); | |
1991 } | |
1992 Bind(&if_found_dict); | |
1993 { | |
1994 Node* dictionary = var_meta_storage.value(); | |
1995 Node* entry = var_entry.value(); | |
1996 LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value); | |
1997 Goto(&if_found); | |
1998 } | |
1999 Bind(&if_found_global); | |
2000 { | |
2001 Node* dictionary = var_meta_storage.value(); | |
2002 Node* entry = var_entry.value(); | |
2003 | |
2004 LoadPropertyFromGlobalDictionary(dictionary, entry, &var_details, var_value, | |
2005 if_not_found); | |
2006 Goto(&if_found); | |
2007 } | |
2008 // Here we have details and value which could be an accessor. | |
2009 Bind(&if_found); | |
2010 { | |
2011 Node* details = var_details.value(); | |
2012 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); | |
2013 | |
2014 Label if_accessor(this); | |
2015 Branch(Word32Equal(kind, Int32Constant(kData)), if_found_value, | |
2016 &if_accessor); | |
2017 Bind(&if_accessor); | |
2018 { | |
2019 Node* accessor_pair = var_value->value(); | |
2020 GotoIf(Word32Equal(LoadInstanceType(accessor_pair), | |
2021 Int32Constant(ACCESSOR_INFO_TYPE)), | |
2022 if_bailout); | |
2023 AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE); | |
2024 Node* getter = | |
2025 LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); | |
2026 Node* getter_map = LoadMap(getter); | |
2027 Node* instance_type = LoadMapInstanceType(getter_map); | |
2028 // FunctionTemplateInfo getters are not supported yet. | |
2029 GotoIf(Word32Equal(instance_type, | |
2030 Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)), | |
2031 if_bailout); | |
2032 | |
2033 // Return undefined if the {getter} is not callable. | |
2034 var_value->Bind(UndefinedConstant()); | |
2035 GotoIf(Word32Equal(Word32And(LoadMapBitField(getter_map), | |
2036 Int32Constant(1 << Map::kIsCallable)), | |
2037 Int32Constant(0)), | |
2038 if_found_value); | |
2039 | |
2040 // Call the accessor. | |
2041 Callable callable = CodeFactory::Call(isolate()); | |
2042 Node* result = CallJS(callable, context, getter, receiver); | |
2043 var_value->Bind(result); | |
2044 Goto(if_found_value); | |
2045 } | |
2046 } | |
2047 } | |
2048 | |
1756 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, | 2049 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, |
1757 Node* instance_type, Node* index, | 2050 Node* instance_type, Node* index, |
1758 Label* if_found, Label* if_not_found, | 2051 Label* if_found, Label* if_not_found, |
1759 Label* if_bailout) { | 2052 Label* if_bailout) { |
1760 // Handle special objects in runtime. | 2053 // Handle special objects in runtime. |
1761 GotoIf(Int32LessThanOrEqual(instance_type, | 2054 GotoIf(Int32LessThanOrEqual(instance_type, |
1762 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 2055 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
1763 if_bailout); | 2056 if_bailout); |
1764 | 2057 |
1765 Node* bit_field2 = LoadMapBitField2(map); | 2058 Node* bit_field2 = LoadMapBitField2(map); |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2355 } | 2648 } |
2356 Bind(&miss); | 2649 Bind(&miss); |
2357 { | 2650 { |
2358 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, | 2651 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, |
2359 p->vector); | 2652 p->vector); |
2360 } | 2653 } |
2361 } | 2654 } |
2362 | 2655 |
2363 } // namespace internal | 2656 } // namespace internal |
2364 } // namespace v8 | 2657 } // namespace v8 |
OLD | NEW |