Chromium Code Reviews| 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 |