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 |