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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
| 5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
| 7 #include "src/frames.h" | 7 #include "src/frames.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1576 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, | 1576 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, |
| 1577 MutableMode mode) { | 1577 MutableMode mode) { |
| 1578 Node* result = AllocateHeapNumber(mode); | 1578 Node* result = AllocateHeapNumber(mode); |
| 1579 StoreHeapNumberValue(result, value); | 1579 StoreHeapNumberValue(result, value); |
| 1580 return result; | 1580 return result; |
| 1581 } | 1581 } |
| 1582 | 1582 |
| 1583 Node* CodeStubAssembler::AllocateSeqOneByteString(int length, | 1583 Node* CodeStubAssembler::AllocateSeqOneByteString(int length, |
| 1584 AllocationFlags flags) { | 1584 AllocationFlags flags) { |
| 1585 Comment("AllocateSeqOneByteString"); | 1585 Comment("AllocateSeqOneByteString"); |
| 1586 if (length == 0) { | |
| 1587 return LoadRoot(Heap::kempty_stringRootIndex); | |
| 1588 } | |
| 1586 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags); | 1589 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags); |
| 1587 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); | 1590 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); |
| 1588 StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); | 1591 StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); |
| 1589 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, | 1592 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, |
| 1590 SmiConstant(Smi::FromInt(length))); | 1593 SmiConstant(Smi::FromInt(length))); |
| 1591 // Initialize both used and unused parts of hash field slot at once. | 1594 // Initialize both used and unused parts of hash field slot at once. |
| 1592 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot, | 1595 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot, |
| 1593 IntPtrConstant(String::kEmptyHashField), | 1596 IntPtrConstant(String::kEmptyHashField), |
| 1594 MachineType::PointerRepresentation()); | 1597 MachineType::PointerRepresentation()); |
| 1595 return result; | 1598 return result; |
| 1596 } | 1599 } |
| 1597 | 1600 |
| 1598 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, | 1601 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, |
| 1599 ParameterMode mode, | 1602 ParameterMode mode, |
| 1600 AllocationFlags flags) { | 1603 AllocationFlags flags) { |
| 1601 Comment("AllocateSeqOneByteString"); | 1604 Comment("AllocateSeqOneByteString"); |
| 1602 Variable var_result(this, MachineRepresentation::kTagged); | 1605 Variable var_result(this, MachineRepresentation::kTagged); |
| 1603 | 1606 |
| 1604 // Compute the SeqOneByteString size and check if it fits into new space. | 1607 // Compute the SeqOneByteString size and check if it fits into new space. |
| 1605 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), | 1608 Label if_lengthiszero(this), if_sizeissmall(this), |
| 1606 if_join(this); | 1609 if_notsizeissmall(this, Label::kDeferred), if_join(this); |
| 1610 GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); | |
| 1611 | |
| 1607 Node* raw_size = GetArrayAllocationSize( | 1612 Node* raw_size = GetArrayAllocationSize( |
| 1608 length, UINT8_ELEMENTS, mode, | 1613 length, UINT8_ELEMENTS, mode, |
| 1609 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); | 1614 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); |
| 1610 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); | 1615 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); |
| 1611 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), | 1616 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), |
| 1612 &if_sizeissmall, &if_notsizeissmall); | 1617 &if_sizeissmall, &if_notsizeissmall); |
| 1613 | 1618 |
| 1614 Bind(&if_sizeissmall); | 1619 Bind(&if_sizeissmall); |
| 1615 { | 1620 { |
| 1616 // Just allocate the SeqOneByteString in new space. | 1621 // Just allocate the SeqOneByteString in new space. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1629 | 1634 |
| 1630 Bind(&if_notsizeissmall); | 1635 Bind(&if_notsizeissmall); |
| 1631 { | 1636 { |
| 1632 // We might need to allocate in large object space, go to the runtime. | 1637 // We might need to allocate in large object space, go to the runtime. |
| 1633 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, | 1638 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, |
| 1634 ParameterToTagged(length, mode)); | 1639 ParameterToTagged(length, mode)); |
| 1635 var_result.Bind(result); | 1640 var_result.Bind(result); |
| 1636 Goto(&if_join); | 1641 Goto(&if_join); |
| 1637 } | 1642 } |
| 1638 | 1643 |
| 1644 Bind(&if_lengthiszero); | |
| 1645 { | |
| 1646 var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); | |
| 1647 Goto(&if_join); | |
| 1648 } | |
| 1649 | |
| 1639 Bind(&if_join); | 1650 Bind(&if_join); |
| 1640 return var_result.value(); | 1651 return var_result.value(); |
| 1641 } | 1652 } |
| 1642 | 1653 |
| 1643 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length, | 1654 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length, |
| 1644 AllocationFlags flags) { | 1655 AllocationFlags flags) { |
| 1645 Comment("AllocateSeqTwoByteString"); | 1656 Comment("AllocateSeqTwoByteString"); |
| 1657 if (length == 0) { | |
| 1658 return LoadRoot(Heap::kempty_stringRootIndex); | |
| 1659 } | |
| 1646 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags); | 1660 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags); |
| 1647 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); | 1661 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); |
| 1648 StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); | 1662 StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); |
| 1649 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, | 1663 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, |
| 1650 SmiConstant(Smi::FromInt(length))); | 1664 SmiConstant(Smi::FromInt(length))); |
| 1651 // Initialize both used and unused parts of hash field slot at once. | 1665 // Initialize both used and unused parts of hash field slot at once. |
| 1652 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot, | 1666 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot, |
| 1653 IntPtrConstant(String::kEmptyHashField), | 1667 IntPtrConstant(String::kEmptyHashField), |
| 1654 MachineType::PointerRepresentation()); | 1668 MachineType::PointerRepresentation()); |
| 1655 return result; | 1669 return result; |
| 1656 } | 1670 } |
| 1657 | 1671 |
| 1658 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, | 1672 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, |
| 1659 ParameterMode mode, | 1673 ParameterMode mode, |
| 1660 AllocationFlags flags) { | 1674 AllocationFlags flags) { |
| 1661 Comment("AllocateSeqTwoByteString"); | 1675 Comment("AllocateSeqTwoByteString"); |
| 1662 Variable var_result(this, MachineRepresentation::kTagged); | 1676 Variable var_result(this, MachineRepresentation::kTagged); |
| 1663 | 1677 |
| 1664 // Compute the SeqTwoByteString size and check if it fits into new space. | 1678 // Compute the SeqTwoByteString size and check if it fits into new space. |
| 1665 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), | 1679 Label if_lengthiszero(this), if_sizeissmall(this), |
| 1666 if_join(this); | 1680 if_notsizeissmall(this, Label::kDeferred), if_join(this); |
| 1681 GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); | |
| 1682 | |
| 1667 Node* raw_size = GetArrayAllocationSize( | 1683 Node* raw_size = GetArrayAllocationSize( |
| 1668 length, UINT16_ELEMENTS, mode, | 1684 length, UINT16_ELEMENTS, mode, |
| 1669 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); | 1685 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); |
| 1670 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); | 1686 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); |
| 1671 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), | 1687 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), |
| 1672 &if_sizeissmall, &if_notsizeissmall); | 1688 &if_sizeissmall, &if_notsizeissmall); |
| 1673 | 1689 |
| 1674 Bind(&if_sizeissmall); | 1690 Bind(&if_sizeissmall); |
| 1675 { | 1691 { |
| 1676 // Just allocate the SeqTwoByteString in new space. | 1692 // Just allocate the SeqTwoByteString in new space. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1691 Bind(&if_notsizeissmall); | 1707 Bind(&if_notsizeissmall); |
| 1692 { | 1708 { |
| 1693 // We might need to allocate in large object space, go to the runtime. | 1709 // We might need to allocate in large object space, go to the runtime. |
| 1694 Node* result = | 1710 Node* result = |
| 1695 CallRuntime(Runtime::kAllocateSeqTwoByteString, context, | 1711 CallRuntime(Runtime::kAllocateSeqTwoByteString, context, |
| 1696 mode == SMI_PARAMETERS ? length : SmiFromWord(length)); | 1712 mode == SMI_PARAMETERS ? length : SmiFromWord(length)); |
| 1697 var_result.Bind(result); | 1713 var_result.Bind(result); |
| 1698 Goto(&if_join); | 1714 Goto(&if_join); |
| 1699 } | 1715 } |
| 1700 | 1716 |
| 1717 Bind(&if_lengthiszero); | |
| 1718 { | |
| 1719 var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); | |
| 1720 Goto(&if_join); | |
| 1721 } | |
| 1722 | |
| 1701 Bind(&if_join); | 1723 Bind(&if_join); |
| 1702 return var_result.value(); | 1724 return var_result.value(); |
| 1703 } | 1725 } |
| 1704 | 1726 |
| 1705 Node* CodeStubAssembler::AllocateSlicedString( | 1727 Node* CodeStubAssembler::AllocateSlicedString( |
| 1706 Heap::RootListIndex map_root_index, Node* length, Node* parent, | 1728 Heap::RootListIndex map_root_index, Node* length, Node* parent, |
| 1707 Node* offset) { | 1729 Node* offset) { |
| 1708 CSA_ASSERT(this, TaggedIsSmi(length)); | 1730 CSA_ASSERT(this, TaggedIsSmi(length)); |
| 1709 Node* result = Allocate(SlicedString::kSize); | 1731 Node* result = Allocate(SlicedString::kSize); |
| 1710 DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); | 1732 DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); |
| (...skipping 1431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3142 // The {string} might be compressed, call the runtime. | 3164 // The {string} might be compressed, call the runtime. |
| 3143 var_result.Bind(SmiToWord32( | 3165 var_result.Bind(SmiToWord32( |
| 3144 CallRuntime(Runtime::kExternalStringGetChar, | 3166 CallRuntime(Runtime::kExternalStringGetChar, |
| 3145 NoContextConstant(), string, SmiTag(index)))); | 3167 NoContextConstant(), string, SmiTag(index)))); |
| 3146 Goto(&done_loop); | 3168 Goto(&done_loop); |
| 3147 } | 3169 } |
| 3148 } | 3170 } |
| 3149 | 3171 |
| 3150 Bind(&if_stringisnotexternal); | 3172 Bind(&if_stringisnotexternal); |
| 3151 { | 3173 { |
| 3152 // The {string} is a SlicedString, continue with its parent. | 3174 Label if_stringissliced(this), if_stringisthin(this); |
| 3153 Node* string_offset = | 3175 Branch( |
| 3154 LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); | 3176 Word32Equal(Word32And(string_instance_type, |
| 3155 Node* string_parent = | 3177 Int32Constant(kStringRepresentationMask)), |
| 3156 LoadObjectField(string, SlicedString::kParentOffset); | 3178 Int32Constant(kSlicedStringTag)), |
| 3157 var_index.Bind(IntPtrAdd(index, string_offset)); | 3179 &if_stringissliced, &if_stringisthin); |
| 3158 var_string.Bind(string_parent); | 3180 Bind(&if_stringissliced); |
| 3159 Goto(&loop); | 3181 { |
| 3182 // The {string} is a SlicedString, continue with its parent. | |
| 3183 Node* string_offset = | |
| 3184 LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); | |
| 3185 Node* string_parent = | |
| 3186 LoadObjectField(string, SlicedString::kParentOffset); | |
| 3187 var_index.Bind(IntPtrAdd(index, string_offset)); | |
| 3188 var_string.Bind(string_parent); | |
| 3189 Goto(&loop); | |
| 3190 } | |
| 3191 Bind(&if_stringisthin); | |
| 3192 { | |
| 3193 // The {string} is a ThinString, continue with its actual value. | |
| 3194 var_string.Bind(LoadObjectField(string, ThinString::kActualOffset)); | |
| 3195 Goto(&loop); | |
| 3196 } | |
| 3160 } | 3197 } |
| 3161 } | 3198 } |
| 3162 } | 3199 } |
| 3163 } | 3200 } |
| 3164 | 3201 |
| 3165 Bind(&done_loop); | 3202 Bind(&done_loop); |
| 3166 return var_result.value(); | 3203 return var_result.value(); |
| 3167 } | 3204 } |
| 3168 | 3205 |
| 3169 Node* CodeStubAssembler::StringFromCharCode(Node* code) { | 3206 Node* CodeStubAssembler::StringFromCharCode(Node* code) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3325 | 3362 |
| 3326 Label single_char(this); | 3363 Label single_char(this); |
| 3327 GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char); | 3364 GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char); |
| 3328 | 3365 |
| 3329 // TODO(jgruber): Add an additional case for substring of length == 0? | 3366 // TODO(jgruber): Add an additional case for substring of length == 0? |
| 3330 | 3367 |
| 3331 // Deal with different string types: update the index if necessary | 3368 // Deal with different string types: update the index if necessary |
| 3332 // and put the underlying string into var_string. | 3369 // and put the underlying string into var_string. |
| 3333 | 3370 |
| 3334 // If the string is not indirect, it can only be sequential or external. | 3371 // If the string is not indirect, it can only be sequential or external. |
| 3335 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | 3372 STATIC_ASSERT(kIsIndirectStringMask == |
| 3373 (kSlicedStringTag & kConsStringTag & kThinStringTag)); | |
| 3336 STATIC_ASSERT(kIsIndirectStringMask != 0); | 3374 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 3337 Label underlying_unpacked(this); | 3375 Label underlying_unpacked(this); |
| 3338 GotoIf(Word32Equal( | 3376 GotoIf(Word32Equal( |
| 3339 Word32And(instance_type, Int32Constant(kIsIndirectStringMask)), | 3377 Word32And(instance_type, Int32Constant(kIsIndirectStringMask)), |
| 3340 Int32Constant(0)), | 3378 Int32Constant(0)), |
| 3341 &underlying_unpacked); | 3379 &underlying_unpacked); |
| 3342 | 3380 |
| 3343 // The subject string is either a sliced or cons string. | 3381 // The subject string is either a sliced or cons string. |
|
Igor Sheludko
2016/12/20 23:46:58
or thin string.
Jakob Kummerow
2017/01/04 12:45:06
Done.
| |
| 3344 | 3382 |
| 3345 Label sliced_string(this); | 3383 Label sliced_string(this), thin_or_sliced(this); |
| 3346 GotoIf(Word32NotEqual( | 3384 GotoIf(Word32NotEqual( |
| 3347 Word32And(instance_type, Int32Constant(kSlicedNotConsMask)), | 3385 Word32And(instance_type, Int32Constant(kStringRepresentationMask)), |
| 3348 Int32Constant(0)), | 3386 Int32Constant(kConsStringTag)), |
| 3349 &sliced_string); | 3387 &thin_or_sliced); |
| 3350 | 3388 |
| 3351 // Cons string. Check whether it is flat, then fetch first part. | 3389 // Cons string. Check whether it is flat, then fetch first part. |
| 3352 // Flat cons strings have an empty second part. | 3390 // Flat cons strings have an empty second part. |
| 3353 { | 3391 { |
| 3354 GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset), | 3392 GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset), |
| 3355 EmptyStringConstant()), | 3393 EmptyStringConstant()), |
| 3356 &runtime); | 3394 &runtime); |
| 3357 | 3395 |
| 3358 Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset); | 3396 Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset); |
| 3359 var_string.Bind(first_string_part); | 3397 var_string.Bind(first_string_part); |
| 3360 var_instance_type.Bind(LoadInstanceType(first_string_part)); | 3398 var_instance_type.Bind(LoadInstanceType(first_string_part)); |
| 3361 | 3399 |
| 3362 Goto(&underlying_unpacked); | 3400 Goto(&underlying_unpacked); |
| 3363 } | 3401 } |
| 3364 | 3402 |
| 3403 Bind(&thin_or_sliced); | |
| 3404 { | |
| 3405 GotoIf(Word32Equal(Word32And(instance_type, | |
|
Igor Sheludko
2016/12/20 23:46:58
Maybe reuse the result of "Word32And(instance_type
Jakob Kummerow
2017/01/04 12:45:06
Done.
| |
| 3406 Int32Constant(kStringRepresentationMask)), | |
| 3407 Int32Constant(kSlicedStringTag)), | |
| 3408 &sliced_string); | |
| 3409 Node* actual_string = LoadObjectField(string, ThinString::kActualOffset); | |
| 3410 var_string.Bind(actual_string); | |
| 3411 var_instance_type.Bind(LoadInstanceType(actual_string)); | |
| 3412 Goto(&underlying_unpacked); | |
| 3413 } | |
| 3414 | |
| 3365 Bind(&sliced_string); | 3415 Bind(&sliced_string); |
| 3366 { | 3416 { |
| 3367 // Fetch parent and correct start index by offset. | 3417 // Fetch parent and correct start index by offset. |
| 3368 Node* sliced_offset = LoadObjectField(string, SlicedString::kOffsetOffset); | 3418 Node* sliced_offset = LoadObjectField(string, SlicedString::kOffsetOffset); |
| 3369 var_from.Bind(SmiAdd(from, sliced_offset)); | 3419 var_from.Bind(SmiAdd(from, sliced_offset)); |
| 3370 | 3420 |
| 3371 Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset); | 3421 Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset); |
| 3372 var_string.Bind(slice_parent); | 3422 var_string.Bind(slice_parent); |
| 3373 | 3423 |
| 3374 Node* slice_parent_instance_type = LoadInstanceType(slice_parent); | 3424 Node* slice_parent_instance_type = LoadInstanceType(slice_parent); |
| (...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4311 variable.Bind( | 4361 variable.Bind( |
| 4312 IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode)); | 4362 IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode)); |
| 4313 } | 4363 } |
| 4314 | 4364 |
| 4315 void CodeStubAssembler::Use(Label* label) { | 4365 void CodeStubAssembler::Use(Label* label) { |
| 4316 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); | 4366 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); |
| 4317 } | 4367 } |
| 4318 | 4368 |
| 4319 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, | 4369 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, |
| 4320 Variable* var_index, Label* if_keyisunique, | 4370 Variable* var_index, Label* if_keyisunique, |
| 4321 Label* if_bailout) { | 4371 Variable* var_unique, Label* if_bailout) { |
| 4322 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); | 4372 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); |
| 4373 DCHECK_EQ(MachineRepresentation::kTagged, var_unique->rep()); | |
| 4323 Comment("TryToName"); | 4374 Comment("TryToName"); |
| 4324 | 4375 |
| 4325 Label if_hascachedindex(this), if_keyisnotindex(this); | 4376 Label if_hascachedindex(this), if_keyisnotindex(this), if_thinstring(this); |
| 4326 // Handle Smi and HeapNumber keys. | 4377 // Handle Smi and HeapNumber keys. |
| 4327 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); | 4378 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); |
| 4328 Goto(if_keyisindex); | 4379 Goto(if_keyisindex); |
| 4329 | 4380 |
| 4330 Bind(&if_keyisnotindex); | 4381 Bind(&if_keyisnotindex); |
| 4331 Node* key_map = LoadMap(key); | 4382 Node* key_map = LoadMap(key); |
| 4383 var_unique->Bind(key); | |
| 4332 // Symbols are unique. | 4384 // Symbols are unique. |
| 4333 GotoIf(IsSymbolMap(key_map), if_keyisunique); | 4385 GotoIf(IsSymbolMap(key_map), if_keyisunique); |
| 4334 Node* key_instance_type = LoadMapInstanceType(key_map); | 4386 Node* key_instance_type = LoadMapInstanceType(key_map); |
| 4335 // Miss if |key| is not a String. | 4387 // Miss if |key| is not a String. |
| 4336 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 4388 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
| 4337 GotoUnless(IsStringInstanceType(key_instance_type), if_bailout); | 4389 GotoUnless(IsStringInstanceType(key_instance_type), if_bailout); |
| 4338 // |key| is a String. Check if it has a cached array index. | 4390 // |key| is a String. Check if it has a cached array index. |
| 4339 Node* hash = LoadNameHashField(key); | 4391 Node* hash = LoadNameHashField(key); |
| 4340 Node* contains_index = | 4392 Node* contains_index = |
| 4341 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); | 4393 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); |
| 4342 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); | 4394 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); |
| 4343 // No cached array index. If the string knows that it contains an index, | 4395 // No cached array index. If the string knows that it contains an index, |
| 4344 // then it must be an uncacheable index. Handle this case in the runtime. | 4396 // then it must be an uncacheable index. Handle this case in the runtime. |
| 4345 Node* not_an_index = | 4397 Node* not_an_index = |
| 4346 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); | 4398 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); |
| 4347 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); | 4399 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); |
| 4400 // Check if we have a ThinString. | |
| 4401 GotoIf(Word32Equal(key_instance_type, Int32Constant(THIN_STRING_TYPE)), | |
| 4402 &if_thinstring); | |
| 4403 GotoIf( | |
| 4404 Word32Equal(key_instance_type, Int32Constant(THIN_ONE_BYTE_STRING_TYPE)), | |
| 4405 &if_thinstring); | |
| 4348 // Finally, check if |key| is internalized. | 4406 // Finally, check if |key| is internalized. |
| 4349 STATIC_ASSERT(kNotInternalizedTag != 0); | 4407 STATIC_ASSERT(kNotInternalizedTag != 0); |
| 4350 Node* not_internalized = | 4408 Node* not_internalized = |
| 4351 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); | 4409 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); |
| 4352 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); | 4410 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); |
| 4353 Goto(if_keyisunique); | 4411 Goto(if_keyisunique); |
| 4354 | 4412 |
| 4413 Bind(&if_thinstring); | |
| 4414 var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset)); | |
| 4415 Goto(if_keyisunique); | |
| 4416 | |
| 4355 Bind(&if_hascachedindex); | 4417 Bind(&if_hascachedindex); |
| 4356 var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); | 4418 var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); |
| 4357 Goto(if_keyisindex); | 4419 Goto(if_keyisindex); |
| 4358 } | 4420 } |
| 4359 | 4421 |
| 4360 template <typename Dictionary> | 4422 template <typename Dictionary> |
| 4361 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { | 4423 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { |
| 4362 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); | 4424 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); |
| 4363 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + | 4425 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + |
| 4364 field_index)); | 4426 field_index)); |
| (...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5194 Label if_objectisreceiver(this); | 5256 Label if_objectisreceiver(this); |
| 5195 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 5257 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 5196 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); | 5258 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); |
| 5197 Branch( | 5259 Branch( |
| 5198 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), | 5260 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), |
| 5199 &if_objectisreceiver, if_bailout); | 5261 &if_objectisreceiver, if_bailout); |
| 5200 Bind(&if_objectisreceiver); | 5262 Bind(&if_objectisreceiver); |
| 5201 } | 5263 } |
| 5202 | 5264 |
| 5203 Variable var_index(this, MachineType::PointerRepresentation()); | 5265 Variable var_index(this, MachineType::PointerRepresentation()); |
| 5266 Variable var_unique(this, MachineRepresentation::kTagged); | |
| 5204 | 5267 |
| 5205 Label if_keyisindex(this), if_iskeyunique(this); | 5268 Label if_keyisindex(this), if_iskeyunique(this); |
| 5206 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); | 5269 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique, |
| 5270 if_bailout); | |
| 5207 | 5271 |
| 5208 Bind(&if_iskeyunique); | 5272 Bind(&if_iskeyunique); |
| 5209 { | 5273 { |
| 5210 Variable var_holder(this, MachineRepresentation::kTagged); | 5274 Variable var_holder(this, MachineRepresentation::kTagged); |
| 5211 Variable var_holder_map(this, MachineRepresentation::kTagged); | 5275 Variable var_holder_map(this, MachineRepresentation::kTagged); |
| 5212 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); | 5276 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); |
| 5213 | 5277 |
| 5214 Variable* merged_variables[] = {&var_holder, &var_holder_map, | 5278 Variable* merged_variables[] = {&var_holder, &var_holder_map, |
| 5215 &var_holder_instance_type}; | 5279 &var_holder_instance_type}; |
| 5216 Label loop(this, arraysize(merged_variables), merged_variables); | 5280 Label loop(this, arraysize(merged_variables), merged_variables); |
| 5217 var_holder.Bind(receiver); | 5281 var_holder.Bind(receiver); |
| 5218 var_holder_map.Bind(map); | 5282 var_holder_map.Bind(map); |
| 5219 var_holder_instance_type.Bind(instance_type); | 5283 var_holder_instance_type.Bind(instance_type); |
| 5220 Goto(&loop); | 5284 Goto(&loop); |
| 5221 Bind(&loop); | 5285 Bind(&loop); |
| 5222 { | 5286 { |
| 5223 Node* holder_map = var_holder_map.value(); | 5287 Node* holder_map = var_holder_map.value(); |
| 5224 Node* holder_instance_type = var_holder_instance_type.value(); | 5288 Node* holder_instance_type = var_holder_instance_type.value(); |
| 5225 | 5289 |
| 5226 Label next_proto(this); | 5290 Label next_proto(this); |
| 5227 lookup_property_in_holder(receiver, var_holder.value(), holder_map, | 5291 lookup_property_in_holder(receiver, var_holder.value(), holder_map, |
| 5228 holder_instance_type, key, &next_proto, | 5292 holder_instance_type, var_unique.value(), |
| 5229 if_bailout); | 5293 &next_proto, if_bailout); |
| 5230 Bind(&next_proto); | 5294 Bind(&next_proto); |
| 5231 | 5295 |
| 5232 // Bailout if it can be an integer indexed exotic case. | 5296 // Bailout if it can be an integer indexed exotic case. |
| 5233 GotoIf( | 5297 GotoIf( |
| 5234 Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), | 5298 Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), |
| 5235 if_bailout); | 5299 if_bailout); |
| 5236 | 5300 |
| 5237 Node* proto = LoadMapPrototype(holder_map); | 5301 Node* proto = LoadMapPrototype(holder_map); |
| 5238 | 5302 |
| 5239 Label if_not_null(this); | 5303 Label if_not_null(this); |
| (...skipping 3053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8293 Heap::kUndefinedValueRootIndex); | 8357 Heap::kUndefinedValueRootIndex); |
| 8294 StoreObjectFieldRoot(result, PromiseReactionJobInfo::kDebugNameOffset, | 8358 StoreObjectFieldRoot(result, PromiseReactionJobInfo::kDebugNameOffset, |
| 8295 Heap::kUndefinedValueRootIndex); | 8359 Heap::kUndefinedValueRootIndex); |
| 8296 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset, | 8360 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset, |
| 8297 context); | 8361 context); |
| 8298 return result; | 8362 return result; |
| 8299 } | 8363 } |
| 8300 | 8364 |
| 8301 } // namespace internal | 8365 } // namespace internal |
| 8302 } // namespace v8 | 8366 } // namespace v8 |
| OLD | NEW |