Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2549773002: Internalize strings in-place (Closed)
Patch Set: fix performance Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, 1565 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value,
1566 MutableMode mode) { 1566 MutableMode mode) {
1567 Node* result = AllocateHeapNumber(mode); 1567 Node* result = AllocateHeapNumber(mode);
1568 StoreHeapNumberValue(result, value); 1568 StoreHeapNumberValue(result, value);
1569 return result; 1569 return result;
1570 } 1570 }
1571 1571
1572 Node* CodeStubAssembler::AllocateSeqOneByteString(int length, 1572 Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
1573 AllocationFlags flags) { 1573 AllocationFlags flags) {
1574 Comment("AllocateSeqOneByteString"); 1574 Comment("AllocateSeqOneByteString");
1575 if (length == 0) {
1576 return LoadRoot(Heap::kempty_stringRootIndex);
1577 }
1575 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags); 1578 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
1576 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); 1579 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
1577 StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); 1580 StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
1578 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1581 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
1579 SmiConstant(Smi::FromInt(length))); 1582 SmiConstant(Smi::FromInt(length)));
1580 // Initialize both used and unused parts of hash field slot at once. 1583 // Initialize both used and unused parts of hash field slot at once.
1581 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot, 1584 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot,
1582 IntPtrConstant(String::kEmptyHashField), 1585 IntPtrConstant(String::kEmptyHashField),
1583 MachineType::PointerRepresentation()); 1586 MachineType::PointerRepresentation());
1584 return result; 1587 return result;
1585 } 1588 }
1586 1589
1587 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, 1590 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
1588 ParameterMode mode, 1591 ParameterMode mode,
1589 AllocationFlags flags) { 1592 AllocationFlags flags) {
1590 Comment("AllocateSeqOneByteString"); 1593 Comment("AllocateSeqOneByteString");
1591 Variable var_result(this, MachineRepresentation::kTagged); 1594 Variable var_result(this, MachineRepresentation::kTagged);
1592 1595
1593 // Compute the SeqOneByteString size and check if it fits into new space. 1596 // Compute the SeqOneByteString size and check if it fits into new space.
1594 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1597 Label if_lengthiszero(this), if_sizeissmall(this),
1595 if_join(this); 1598 if_notsizeissmall(this, Label::kDeferred), if_join(this);
1599 GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
1600
1596 Node* raw_size = GetArrayAllocationSize( 1601 Node* raw_size = GetArrayAllocationSize(
1597 length, UINT8_ELEMENTS, mode, 1602 length, UINT8_ELEMENTS, mode,
1598 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); 1603 SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
1599 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); 1604 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
1600 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1605 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1601 &if_sizeissmall, &if_notsizeissmall); 1606 &if_sizeissmall, &if_notsizeissmall);
1602 1607
1603 Bind(&if_sizeissmall); 1608 Bind(&if_sizeissmall);
1604 { 1609 {
1605 // Just allocate the SeqOneByteString in new space. 1610 // Just allocate the SeqOneByteString in new space.
(...skipping 12 matching lines...) Expand all
1618 1623
1619 Bind(&if_notsizeissmall); 1624 Bind(&if_notsizeissmall);
1620 { 1625 {
1621 // We might need to allocate in large object space, go to the runtime. 1626 // We might need to allocate in large object space, go to the runtime.
1622 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, 1627 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context,
1623 ParameterToTagged(length, mode)); 1628 ParameterToTagged(length, mode));
1624 var_result.Bind(result); 1629 var_result.Bind(result);
1625 Goto(&if_join); 1630 Goto(&if_join);
1626 } 1631 }
1627 1632
1633 Bind(&if_lengthiszero);
1634 {
1635 var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
1636 Goto(&if_join);
1637 }
1638
1628 Bind(&if_join); 1639 Bind(&if_join);
1629 return var_result.value(); 1640 return var_result.value();
1630 } 1641 }
1631 1642
1632 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length, 1643 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
1633 AllocationFlags flags) { 1644 AllocationFlags flags) {
1634 Comment("AllocateSeqTwoByteString"); 1645 Comment("AllocateSeqTwoByteString");
1646 if (length == 0) {
1647 return LoadRoot(Heap::kempty_stringRootIndex);
1648 }
1635 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags); 1649 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
1636 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); 1650 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
1637 StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); 1651 StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
1638 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1652 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
1639 SmiConstant(Smi::FromInt(length))); 1653 SmiConstant(Smi::FromInt(length)));
1640 // Initialize both used and unused parts of hash field slot at once. 1654 // Initialize both used and unused parts of hash field slot at once.
1641 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot, 1655 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot,
1642 IntPtrConstant(String::kEmptyHashField), 1656 IntPtrConstant(String::kEmptyHashField),
1643 MachineType::PointerRepresentation()); 1657 MachineType::PointerRepresentation());
1644 return result; 1658 return result;
1645 } 1659 }
1646 1660
1647 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, 1661 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
1648 ParameterMode mode, 1662 ParameterMode mode,
1649 AllocationFlags flags) { 1663 AllocationFlags flags) {
1650 Comment("AllocateSeqTwoByteString"); 1664 Comment("AllocateSeqTwoByteString");
1651 Variable var_result(this, MachineRepresentation::kTagged); 1665 Variable var_result(this, MachineRepresentation::kTagged);
1652 1666
1653 // Compute the SeqTwoByteString size and check if it fits into new space. 1667 // Compute the SeqTwoByteString size and check if it fits into new space.
1654 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1668 Label if_lengthiszero(this), if_sizeissmall(this),
1655 if_join(this); 1669 if_notsizeissmall(this, Label::kDeferred), if_join(this);
1670 GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
1671
1656 Node* raw_size = GetArrayAllocationSize( 1672 Node* raw_size = GetArrayAllocationSize(
1657 length, UINT16_ELEMENTS, mode, 1673 length, UINT16_ELEMENTS, mode,
1658 SeqOneByteString::kHeaderSize + kObjectAlignmentMask); 1674 SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
1659 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); 1675 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
1660 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1676 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1661 &if_sizeissmall, &if_notsizeissmall); 1677 &if_sizeissmall, &if_notsizeissmall);
1662 1678
1663 Bind(&if_sizeissmall); 1679 Bind(&if_sizeissmall);
1664 { 1680 {
1665 // Just allocate the SeqTwoByteString in new space. 1681 // Just allocate the SeqTwoByteString in new space.
(...skipping 14 matching lines...) Expand all
1680 Bind(&if_notsizeissmall); 1696 Bind(&if_notsizeissmall);
1681 { 1697 {
1682 // We might need to allocate in large object space, go to the runtime. 1698 // We might need to allocate in large object space, go to the runtime.
1683 Node* result = 1699 Node* result =
1684 CallRuntime(Runtime::kAllocateSeqTwoByteString, context, 1700 CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
1685 mode == SMI_PARAMETERS ? length : SmiFromWord(length)); 1701 mode == SMI_PARAMETERS ? length : SmiFromWord(length));
1686 var_result.Bind(result); 1702 var_result.Bind(result);
1687 Goto(&if_join); 1703 Goto(&if_join);
1688 } 1704 }
1689 1705
1706 Bind(&if_lengthiszero);
1707 {
1708 var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
1709 Goto(&if_join);
1710 }
1711
1690 Bind(&if_join); 1712 Bind(&if_join);
1691 return var_result.value(); 1713 return var_result.value();
1692 } 1714 }
1693 1715
1694 Node* CodeStubAssembler::AllocateSlicedString( 1716 Node* CodeStubAssembler::AllocateSlicedString(
1695 Heap::RootListIndex map_root_index, Node* length, Node* parent, 1717 Heap::RootListIndex map_root_index, Node* length, Node* parent,
1696 Node* offset) { 1718 Node* offset) {
1697 CSA_ASSERT(this, TaggedIsSmi(length)); 1719 CSA_ASSERT(this, TaggedIsSmi(length));
1698 Node* result = Allocate(SlicedString::kSize); 1720 Node* result = Allocate(SlicedString::kSize);
1699 DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); 1721 DCHECK(Heap::RootIsImmortalImmovable(map_root_index));
(...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 Node* CodeStubAssembler::IsJSFunction(Node* object) { 3017 Node* CodeStubAssembler::IsJSFunction(Node* object) {
2996 return HasInstanceType(object, JS_FUNCTION_TYPE); 3018 return HasInstanceType(object, JS_FUNCTION_TYPE);
2997 } 3019 }
2998 3020
2999 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index, 3021 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index,
3000 ParameterMode parameter_mode) { 3022 ParameterMode parameter_mode) {
3001 CSA_ASSERT(this, IsString(string)); 3023 CSA_ASSERT(this, IsString(string));
3002 // Translate the {index} into a Word. 3024 // Translate the {index} into a Word.
3003 index = ParameterToWord(index, parameter_mode); 3025 index = ParameterToWord(index, parameter_mode);
3004 3026
3005 // We may need to loop in case of cons or sliced strings. 3027 // We may need to loop in case of cons, thin, or sliced strings.
3006 Variable var_index(this, MachineType::PointerRepresentation()); 3028 Variable var_index(this, MachineType::PointerRepresentation());
3007 Variable var_result(this, MachineRepresentation::kWord32); 3029 Variable var_result(this, MachineRepresentation::kWord32);
3008 Variable var_string(this, MachineRepresentation::kTagged); 3030 Variable var_string(this, MachineRepresentation::kTagged);
3009 Variable* loop_vars[] = {&var_index, &var_string}; 3031 Variable* loop_vars[] = {&var_index, &var_string};
3010 Label done_loop(this, &var_result), loop(this, 2, loop_vars); 3032 Label done_loop(this, &var_result), loop(this, 2, loop_vars);
3011 var_string.Bind(string); 3033 var_string.Bind(string);
3012 var_index.Bind(index); 3034 var_index.Bind(index);
3013 Goto(&loop); 3035 Goto(&loop);
3014 Bind(&loop); 3036 Bind(&loop);
3015 { 3037 {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
3147 // The {string} might be compressed, call the runtime. 3169 // The {string} might be compressed, call the runtime.
3148 var_result.Bind(SmiToWord32( 3170 var_result.Bind(SmiToWord32(
3149 CallRuntime(Runtime::kExternalStringGetChar, 3171 CallRuntime(Runtime::kExternalStringGetChar,
3150 NoContextConstant(), string, SmiTag(index)))); 3172 NoContextConstant(), string, SmiTag(index))));
3151 Goto(&done_loop); 3173 Goto(&done_loop);
3152 } 3174 }
3153 } 3175 }
3154 3176
3155 Bind(&if_stringisnotexternal); 3177 Bind(&if_stringisnotexternal);
3156 { 3178 {
3157 // The {string} is a SlicedString, continue with its parent. 3179 Label if_stringissliced(this), if_stringisthin(this);
3158 Node* string_offset = 3180 Branch(
3159 LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); 3181 Word32Equal(Word32And(string_instance_type,
3160 Node* string_parent = 3182 Int32Constant(kStringRepresentationMask)),
3161 LoadObjectField(string, SlicedString::kParentOffset); 3183 Int32Constant(kSlicedStringTag)),
3162 var_index.Bind(IntPtrAdd(index, string_offset)); 3184 &if_stringissliced, &if_stringisthin);
3163 var_string.Bind(string_parent); 3185 Bind(&if_stringissliced);
3164 Goto(&loop); 3186 {
3187 // The {string} is a SlicedString, continue with its parent.
3188 Node* string_offset =
3189 LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
3190 Node* string_parent =
3191 LoadObjectField(string, SlicedString::kParentOffset);
3192 var_index.Bind(IntPtrAdd(index, string_offset));
3193 var_string.Bind(string_parent);
3194 Goto(&loop);
3195 }
3196 Bind(&if_stringisthin);
3197 {
3198 // The {string} is a ThinString, continue with its actual value.
3199 var_string.Bind(LoadObjectField(string, ThinString::kActualOffset));
3200 Goto(&loop);
3201 }
3165 } 3202 }
3166 } 3203 }
3167 } 3204 }
3168 } 3205 }
3169 3206
3170 Bind(&done_loop); 3207 Bind(&done_loop);
3171 return var_result.value(); 3208 return var_result.value();
3172 } 3209 }
3173 3210
3174 Node* CodeStubAssembler::StringFromCharCode(Node* code) { 3211 Node* CodeStubAssembler::StringFromCharCode(Node* code) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3285 } 3322 }
3286 3323
3287 } // namespace 3324 } // namespace
3288 3325
3289 Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, 3326 Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
3290 Node* to) { 3327 Node* to) {
3291 Label end(this); 3328 Label end(this);
3292 Label runtime(this); 3329 Label runtime(this);
3293 3330
3294 Variable var_instance_type(this, MachineRepresentation::kWord32); // Int32. 3331 Variable var_instance_type(this, MachineRepresentation::kWord32); // Int32.
3332 Variable var_representation(this, MachineRepresentation::kWord32); // Int32.
3295 Variable var_result(this, MachineRepresentation::kTagged); // String. 3333 Variable var_result(this, MachineRepresentation::kTagged); // String.
3296 Variable var_from(this, MachineRepresentation::kTagged); // Smi. 3334 Variable var_from(this, MachineRepresentation::kTagged); // Smi.
3297 Variable var_string(this, MachineRepresentation::kTagged); // String. 3335 Variable var_string(this, MachineRepresentation::kTagged); // String.
3298 3336
3299 var_instance_type.Bind(Int32Constant(0)); 3337 var_instance_type.Bind(Int32Constant(0));
3338 var_representation.Bind(Int32Constant(0));
3300 var_string.Bind(string); 3339 var_string.Bind(string);
3301 var_from.Bind(from); 3340 var_from.Bind(from);
3302 3341
3303 // Make sure first argument is a string. 3342 // Make sure first argument is a string.
3304 3343
3305 // Bailout if receiver is a Smi. 3344 // Bailout if receiver is a Smi.
3306 GotoIf(TaggedIsSmi(string), &runtime); 3345 GotoIf(TaggedIsSmi(string), &runtime);
3307 3346
3308 // Load the instance type of the {string}. 3347 // Load the instance type of the {string}.
3309 Node* const instance_type = LoadInstanceType(string); 3348 Node* const instance_type = LoadInstanceType(string);
(...skipping 20 matching lines...) Expand all
3330 3369
3331 Label single_char(this); 3370 Label single_char(this);
3332 GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char); 3371 GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char);
3333 3372
3334 // TODO(jgruber): Add an additional case for substring of length == 0? 3373 // TODO(jgruber): Add an additional case for substring of length == 0?
3335 3374
3336 // Deal with different string types: update the index if necessary 3375 // Deal with different string types: update the index if necessary
3337 // and put the underlying string into var_string. 3376 // and put the underlying string into var_string.
3338 3377
3339 // If the string is not indirect, it can only be sequential or external. 3378 // If the string is not indirect, it can only be sequential or external.
3340 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 3379 STATIC_ASSERT(kIsIndirectStringMask ==
3380 (kSlicedStringTag & kConsStringTag & kThinStringTag));
3341 STATIC_ASSERT(kIsIndirectStringMask != 0); 3381 STATIC_ASSERT(kIsIndirectStringMask != 0);
3342 Label underlying_unpacked(this); 3382 Label underlying_unpacked(this);
3343 GotoIf(Word32Equal( 3383 GotoIf(Word32Equal(
3344 Word32And(instance_type, Int32Constant(kIsIndirectStringMask)), 3384 Word32And(instance_type, Int32Constant(kIsIndirectStringMask)),
3345 Int32Constant(0)), 3385 Int32Constant(0)),
3346 &underlying_unpacked); 3386 &underlying_unpacked);
3347 3387
3348 // The subject string is either a sliced or cons string. 3388 // The subject string is a sliced, cons, or thin string.
3349 3389
3350 Label sliced_string(this); 3390 Label sliced_string(this), thin_or_sliced(this);
3351 GotoIf(Word32NotEqual( 3391 var_representation.Bind(
3352 Word32And(instance_type, Int32Constant(kSlicedNotConsMask)), 3392 Word32And(instance_type, Int32Constant(kStringRepresentationMask)));
3353 Int32Constant(0)), 3393 GotoIf(
3354 &sliced_string); 3394 Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)),
3395 &thin_or_sliced);
3355 3396
3356 // Cons string. Check whether it is flat, then fetch first part. 3397 // Cons string. Check whether it is flat, then fetch first part.
3357 // Flat cons strings have an empty second part. 3398 // Flat cons strings have an empty second part.
3358 { 3399 {
3359 GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset), 3400 GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset),
3360 EmptyStringConstant()), 3401 EmptyStringConstant()),
3361 &runtime); 3402 &runtime);
3362 3403
3363 Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset); 3404 Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset);
3364 var_string.Bind(first_string_part); 3405 var_string.Bind(first_string_part);
3365 var_instance_type.Bind(LoadInstanceType(first_string_part)); 3406 var_instance_type.Bind(LoadInstanceType(first_string_part));
3407 var_representation.Bind(Word32And(
3408 var_instance_type.value(), Int32Constant(kStringRepresentationMask)));
3366 3409
3410 // The loaded first part might be a thin string.
3411 Branch(Word32Equal(Word32And(var_instance_type.value(),
3412 Int32Constant(kIsIndirectStringMask)),
3413 Int32Constant(0)),
3414 &underlying_unpacked, &thin_or_sliced);
3415 }
3416
3417 Bind(&thin_or_sliced);
3418 {
3419 GotoIf(Word32Equal(var_representation.value(),
3420 Int32Constant(kSlicedStringTag)),
3421 &sliced_string);
3422 Node* actual_string =
3423 LoadObjectField(var_string.value(), ThinString::kActualOffset);
3424 var_string.Bind(actual_string);
3425 var_instance_type.Bind(LoadInstanceType(actual_string));
3367 Goto(&underlying_unpacked); 3426 Goto(&underlying_unpacked);
3368 } 3427 }
3369 3428
3370 Bind(&sliced_string); 3429 Bind(&sliced_string);
3371 { 3430 {
3372 // Fetch parent and correct start index by offset. 3431 // Fetch parent and correct start index by offset.
3373 Node* sliced_offset = LoadObjectField(string, SlicedString::kOffsetOffset); 3432 Node* sliced_offset =
3433 LoadObjectField(var_string.value(), SlicedString::kOffsetOffset);
3374 var_from.Bind(SmiAdd(from, sliced_offset)); 3434 var_from.Bind(SmiAdd(from, sliced_offset));
3375 3435
3376 Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset); 3436 Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset);
3377 var_string.Bind(slice_parent); 3437 var_string.Bind(slice_parent);
3378 3438
3379 Node* slice_parent_instance_type = LoadInstanceType(slice_parent); 3439 Node* slice_parent_instance_type = LoadInstanceType(slice_parent);
3380 var_instance_type.Bind(slice_parent_instance_type); 3440 var_instance_type.Bind(slice_parent_instance_type);
3381 3441
3382 Goto(&underlying_unpacked); 3442 Goto(&underlying_unpacked);
3383 } 3443 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3502 { 3562 {
3503 var_result.Bind( 3563 var_result.Bind(
3504 CallRuntime(Runtime::kSubString, context, string, from, to)); 3564 CallRuntime(Runtime::kSubString, context, string, from, to));
3505 Goto(&end); 3565 Goto(&end);
3506 } 3566 }
3507 3567
3508 Bind(&end); 3568 Bind(&end);
3509 return var_result.value(); 3569 return var_result.value();
3510 } 3570 }
3511 3571
3572 void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string,
3573 Node* instance_type,
3574 Variable* var_did_something) {
3575 Label deref(this), done(this, var_did_something);
3576 Node* representation =
3577 Word32And(instance_type, Int32Constant(kStringRepresentationMask));
3578 STATIC_ASSERT(ThinString::kActualOffset == ConsString::kFirstOffset);
3579 GotoIf(Word32Equal(representation, Int32Constant(kThinStringTag)), &deref);
3580 GotoIf(Word32NotEqual(representation, Int32Constant(kConsStringTag)), &done);
3581 // Cons string.
3582 Node* rhs = LoadObjectField(var_string->value(), ConsString::kSecondOffset);
3583 GotoIf(WordEqual(rhs, EmptyStringConstant()), &deref);
Igor Sheludko 2017/01/18 14:55:20 Maybe we should stop using ConsStrings this way on
Jakob Kummerow 2017/01/19 10:20:16 Yes, maybe. Pro: code checking for indirect strin
3584 Goto(&done);
3585
3586 Bind(&deref);
Igor Sheludko 2017/01/18 14:55:20 STATIC_ASSERT(ConsString::kFirstOffset == ThinStri
Jakob Kummerow 2017/01/19 10:20:16 Done.
3587 var_string->Bind(
3588 LoadObjectField(var_string->value(), ThinString::kActualOffset));
3589 var_did_something->Bind(IntPtrConstant(1));
3590 Goto(&done);
3591
3592 Bind(&done);
3593 }
3594
3595 void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left,
3596 Node* left_instance_type,
3597 Variable* var_right,
3598 Node* right_instance_type,
3599 Label* did_something) {
3600 Variable var_did_something(this, MachineType::PointerRepresentation());
3601 var_did_something.Bind(IntPtrConstant(0));
3602 MaybeDerefIndirectString(var_left, left_instance_type, &var_did_something);
3603 MaybeDerefIndirectString(var_right, right_instance_type, &var_did_something);
3604
3605 GotoIf(WordNotEqual(var_did_something.value(), IntPtrConstant(0)),
3606 did_something);
3607 // Fall through if neither string was an indirect string.
3608 }
3609
3512 Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, 3610 Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
3513 AllocationFlags flags) { 3611 AllocationFlags flags) {
3514 Label check_right(this); 3612 Label check_right(this);
3515 Label runtime(this, Label::kDeferred); 3613 Label runtime(this, Label::kDeferred);
3516 Label cons(this); 3614 Label cons(this);
3517 Label non_cons(this);
3518 Variable result(this, MachineRepresentation::kTagged); 3615 Variable result(this, MachineRepresentation::kTagged);
3519 Label done(this, &result); 3616 Label done(this, &result);
3520 Label done_native(this, &result); 3617 Label done_native(this, &result);
3521 Counters* counters = isolate()->counters(); 3618 Counters* counters = isolate()->counters();
3522 3619
3523 Node* left_length = LoadStringLength(left); 3620 Node* left_length = LoadStringLength(left);
3524 GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right); 3621 GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right);
3525 result.Bind(right); 3622 result.Bind(right);
3526 Goto(&done_native); 3623 Goto(&done_native);
3527 3624
3528 Bind(&check_right); 3625 Bind(&check_right);
3529 Node* right_length = LoadStringLength(right); 3626 Node* right_length = LoadStringLength(right);
3530 GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons); 3627 GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons);
3531 result.Bind(left); 3628 result.Bind(left);
3532 Goto(&done_native); 3629 Goto(&done_native);
3533 3630
3534 Bind(&cons); 3631 Bind(&cons);
3535 CSA_ASSERT(this, TaggedIsSmi(left_length)); 3632 {
3536 CSA_ASSERT(this, TaggedIsSmi(right_length)); 3633 CSA_ASSERT(this, TaggedIsSmi(left_length));
3537 Node* new_length = SmiAdd(left_length, right_length); 3634 CSA_ASSERT(this, TaggedIsSmi(right_length));
3538 GotoIf(SmiAboveOrEqual(new_length, SmiConstant(String::kMaxLength)), 3635 Node* new_length = SmiAdd(left_length, right_length);
3539 &runtime); 3636 GotoIf(SmiAboveOrEqual(new_length, SmiConstant(String::kMaxLength)),
3637 &runtime);
3540 3638
3541 GotoIf(SmiLessThan(new_length, SmiConstant(ConsString::kMinLength)), 3639 Variable var_left(this, MachineRepresentation::kTagged);
3542 &non_cons); 3640 Variable var_right(this, MachineRepresentation::kTagged);
3641 Variable* input_vars[2] = {&var_left, &var_right};
3642 Label non_cons(this, 2, input_vars);
3643 Label slow(this, Label::kDeferred);
3644 var_left.Bind(left);
3645 var_right.Bind(right);
3646 GotoIf(SmiLessThan(new_length, SmiConstant(ConsString::kMinLength)),
3647 &non_cons);
3543 3648
3544 result.Bind(NewConsString(context, new_length, left, right, flags)); 3649 result.Bind(NewConsString(context, new_length, var_left.value(),
3545 Goto(&done_native); 3650 var_right.value(), flags));
3651 Goto(&done_native);
3546 3652
3547 Bind(&non_cons); 3653 Bind(&non_cons);
3548 3654
3549 Comment("Full string concatenate"); 3655 Comment("Full string concatenate");
3550 Node* left_instance_type = LoadInstanceType(left); 3656 Node* left_instance_type = LoadInstanceType(var_left.value());
3551 Node* right_instance_type = LoadInstanceType(right); 3657 Node* right_instance_type = LoadInstanceType(var_right.value());
3552 // Compute intersection and difference of instance types. 3658 // Compute intersection and difference of instance types.
3553 3659
3554 Node* ored_instance_types = Word32Or(left_instance_type, right_instance_type); 3660 Node* ored_instance_types =
3555 Node* xored_instance_types = 3661 Word32Or(left_instance_type, right_instance_type);
3556 Word32Xor(left_instance_type, right_instance_type); 3662 Node* xored_instance_types =
3663 Word32Xor(left_instance_type, right_instance_type);
3557 3664
3558 // Check if both strings have the same encoding and both are sequential. 3665 // Check if both strings have the same encoding and both are sequential.
3559 GotoIf(Word32NotEqual(Word32And(xored_instance_types, 3666 GotoIf(Word32NotEqual(Word32And(xored_instance_types,
3560 Int32Constant(kStringEncodingMask)), 3667 Int32Constant(kStringEncodingMask)),
3561 Int32Constant(0)), 3668 Int32Constant(0)),
3562 &runtime); 3669 &runtime);
3563 GotoIf(Word32NotEqual(Word32And(ored_instance_types, 3670 GotoIf(Word32NotEqual(Word32And(ored_instance_types,
3564 Int32Constant(kStringRepresentationMask)), 3671 Int32Constant(kStringRepresentationMask)),
3565 Int32Constant(0)), 3672 Int32Constant(0)),
3566 &runtime); 3673 &slow);
3567 3674
3568 Label two_byte(this); 3675 Label two_byte(this);
3569 GotoIf(Word32Equal( 3676 GotoIf(Word32Equal(Word32And(ored_instance_types,
3570 Word32And(ored_instance_types, Int32Constant(kStringEncodingMask)), 3677 Int32Constant(kStringEncodingMask)),
3571 Int32Constant(kTwoByteStringTag)), 3678 Int32Constant(kTwoByteStringTag)),
3572 &two_byte); 3679 &two_byte);
3573 // One-byte sequential string case 3680 // One-byte sequential string case
3574 Node* new_string = 3681 Node* new_string =
3575 AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); 3682 AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS);
3576 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), 3683 CopyStringCharacters(var_left.value(), new_string, SmiConstant(Smi::kZero),
3577 SmiConstant(Smi::kZero), left_length,
3578 String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
3579 SMI_PARAMETERS);
3580 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length,
3581 right_length, String::ONE_BYTE_ENCODING,
3582 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
3583 result.Bind(new_string);
3584 Goto(&done_native);
3585
3586 Bind(&two_byte);
3587 {
3588 // Two-byte sequential string case
3589 new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
3590 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
3591 SmiConstant(Smi::kZero), left_length, 3684 SmiConstant(Smi::kZero), left_length,
3592 String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, 3685 String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
3593 SMI_PARAMETERS); 3686 SMI_PARAMETERS);
3594 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), 3687 CopyStringCharacters(var_right.value(), new_string, SmiConstant(Smi::kZero),
3595 left_length, right_length, String::TWO_BYTE_ENCODING, 3688 left_length, right_length, String::ONE_BYTE_ENCODING,
3596 String::TWO_BYTE_ENCODING, SMI_PARAMETERS); 3689 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
3597 result.Bind(new_string); 3690 result.Bind(new_string);
3598 Goto(&done_native); 3691 Goto(&done_native);
3692
3693 Bind(&two_byte);
3694 {
3695 // Two-byte sequential string case
3696 new_string =
3697 AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
3698 CopyStringCharacters(var_left.value(), new_string,
3699 SmiConstant(Smi::kZero), SmiConstant(Smi::kZero),
3700 left_length, String::TWO_BYTE_ENCODING,
3701 String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
3702 CopyStringCharacters(var_right.value(), new_string,
3703 SmiConstant(Smi::kZero), left_length, right_length,
3704 String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
3705 SMI_PARAMETERS);
3706 result.Bind(new_string);
3707 Goto(&done_native);
3708 }
3709
3710 Bind(&slow);
3711 {
3712 // Try to unwrap indirect strings, restart the above attempt on success.
3713 MaybeDerefIndirectStrings(&var_left, left_instance_type, &var_right,
3714 right_instance_type, &non_cons);
3715 Goto(&runtime);
3716 }
3599 } 3717 }
3600
3601 Bind(&runtime); 3718 Bind(&runtime);
3602 { 3719 {
3603 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right)); 3720 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right));
3604 Goto(&done); 3721 Goto(&done);
3605 } 3722 }
3606 3723
3607 Bind(&done_native); 3724 Bind(&done_native);
3608 { 3725 {
3609 IncrementCounter(counters->string_add_native(), 1); 3726 IncrementCounter(counters->string_add_native(), 1);
3610 Goto(&done); 3727 Goto(&done);
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
4136 Bind(&runtime); 4253 Bind(&runtime);
4137 { 4254 {
4138 result.Bind(CallRuntime(Runtime::kToString, context, input)); 4255 result.Bind(CallRuntime(Runtime::kToString, context, input));
4139 Goto(&done); 4256 Goto(&done);
4140 } 4257 }
4141 4258
4142 Bind(&done); 4259 Bind(&done);
4143 return result.value(); 4260 return result.value();
4144 } 4261 }
4145 4262
4146 Node* CodeStubAssembler::FlattenString(Node* string) {
4147 CSA_ASSERT(this, IsString(string));
4148 Variable var_result(this, MachineRepresentation::kTagged);
4149 var_result.Bind(string);
4150
4151 Node* instance_type = LoadInstanceType(string);
4152
4153 // Check if the {string} is not a ConsString (i.e. already flat).
4154 Label is_cons(this, Label::kDeferred), is_flat_in_cons(this), end(this);
4155 {
4156 GotoUnless(Word32Equal(Word32And(instance_type,
4157 Int32Constant(kStringRepresentationMask)),
4158 Int32Constant(kConsStringTag)),
4159 &end);
4160
4161 // Check whether the right hand side is the empty string (i.e. if
4162 // this is really a flat string in a cons string).
4163 Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
4164 Branch(WordEqual(rhs, EmptyStringConstant()), &is_flat_in_cons, &is_cons);
4165 }
4166
4167 // Bail out to the runtime.
4168 Bind(&is_cons);
4169 {
4170 var_result.Bind(
4171 CallRuntime(Runtime::kFlattenString, NoContextConstant(), string));
4172 Goto(&end);
4173 }
4174
4175 Bind(&is_flat_in_cons);
4176 {
4177 var_result.Bind(LoadObjectField(string, ConsString::kFirstOffset));
4178 Goto(&end);
4179 }
4180
4181 Bind(&end);
4182 return var_result.value();
4183 }
4184
4185 Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) { 4263 Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
4186 Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this); 4264 Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
4187 Variable result(this, MachineRepresentation::kTagged); 4265 Variable result(this, MachineRepresentation::kTagged);
4188 Label done(this, &result); 4266 Label done(this, &result);
4189 4267
4190 BranchIfJSReceiver(input, &if_isreceiver, &if_isnotreceiver); 4268 BranchIfJSReceiver(input, &if_isreceiver, &if_isnotreceiver);
4191 4269
4192 Bind(&if_isreceiver); 4270 Bind(&if_isreceiver);
4193 { 4271 {
4194 // Convert {input} to a primitive first passing Number hint. 4272 // Convert {input} to a primitive first passing Number hint.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
4316 variable.Bind( 4394 variable.Bind(
4317 IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode)); 4395 IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode));
4318 } 4396 }
4319 4397
4320 void CodeStubAssembler::Use(Label* label) { 4398 void CodeStubAssembler::Use(Label* label) {
4321 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); 4399 GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label);
4322 } 4400 }
4323 4401
4324 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, 4402 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
4325 Variable* var_index, Label* if_keyisunique, 4403 Variable* var_index, Label* if_keyisunique,
4326 Label* if_bailout) { 4404 Variable* var_unique, Label* if_bailout) {
4327 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); 4405 DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep());
4406 DCHECK_EQ(MachineRepresentation::kTagged, var_unique->rep());
4328 Comment("TryToName"); 4407 Comment("TryToName");
4329 4408
4330 Label if_hascachedindex(this), if_keyisnotindex(this); 4409 Label if_hascachedindex(this), if_keyisnotindex(this), if_thinstring(this);
4331 // Handle Smi and HeapNumber keys. 4410 // Handle Smi and HeapNumber keys.
4332 var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); 4411 var_index->Bind(TryToIntptr(key, &if_keyisnotindex));
4333 Goto(if_keyisindex); 4412 Goto(if_keyisindex);
4334 4413
4335 Bind(&if_keyisnotindex); 4414 Bind(&if_keyisnotindex);
4336 Node* key_map = LoadMap(key); 4415 Node* key_map = LoadMap(key);
4416 var_unique->Bind(key);
4337 // Symbols are unique. 4417 // Symbols are unique.
4338 GotoIf(IsSymbolMap(key_map), if_keyisunique); 4418 GotoIf(IsSymbolMap(key_map), if_keyisunique);
4339 Node* key_instance_type = LoadMapInstanceType(key_map); 4419 Node* key_instance_type = LoadMapInstanceType(key_map);
4340 // Miss if |key| is not a String. 4420 // Miss if |key| is not a String.
4341 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 4421 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
4342 GotoUnless(IsStringInstanceType(key_instance_type), if_bailout); 4422 GotoUnless(IsStringInstanceType(key_instance_type), if_bailout);
4343 // |key| is a String. Check if it has a cached array index. 4423 // |key| is a String. Check if it has a cached array index.
4344 Node* hash = LoadNameHashField(key); 4424 Node* hash = LoadNameHashField(key);
4345 Node* contains_index = 4425 Node* contains_index =
4346 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); 4426 Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
4347 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); 4427 GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex);
4348 // No cached array index. If the string knows that it contains an index, 4428 // No cached array index. If the string knows that it contains an index,
4349 // then it must be an uncacheable index. Handle this case in the runtime. 4429 // then it must be an uncacheable index. Handle this case in the runtime.
4350 Node* not_an_index = 4430 Node* not_an_index =
4351 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); 4431 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
4352 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); 4432 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout);
4433 // Check if we have a ThinString.
4434 GotoIf(Word32Equal(key_instance_type, Int32Constant(THIN_STRING_TYPE)),
4435 &if_thinstring);
4436 GotoIf(
4437 Word32Equal(key_instance_type, Int32Constant(THIN_ONE_BYTE_STRING_TYPE)),
4438 &if_thinstring);
4353 // Finally, check if |key| is internalized. 4439 // Finally, check if |key| is internalized.
4354 STATIC_ASSERT(kNotInternalizedTag != 0); 4440 STATIC_ASSERT(kNotInternalizedTag != 0);
4355 Node* not_internalized = 4441 Node* not_internalized =
4356 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); 4442 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
4357 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); 4443 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout);
4358 Goto(if_keyisunique); 4444 Goto(if_keyisunique);
4359 4445
4446 Bind(&if_thinstring);
4447 var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset));
4448 Goto(if_keyisunique);
4449
4360 Bind(&if_hascachedindex); 4450 Bind(&if_hascachedindex);
4361 var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); 4451 var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash));
4362 Goto(if_keyisindex); 4452 Goto(if_keyisindex);
4363 } 4453 }
4364 4454
4365 template <typename Dictionary> 4455 template <typename Dictionary>
4366 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { 4456 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) {
4367 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); 4457 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize));
4368 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + 4458 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex +
4369 field_index)); 4459 field_index));
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after
5199 Label if_objectisreceiver(this); 5289 Label if_objectisreceiver(this);
5200 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 5290 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
5201 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); 5291 STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE);
5202 Branch( 5292 Branch(
5203 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), 5293 Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)),
5204 &if_objectisreceiver, if_bailout); 5294 &if_objectisreceiver, if_bailout);
5205 Bind(&if_objectisreceiver); 5295 Bind(&if_objectisreceiver);
5206 } 5296 }
5207 5297
5208 Variable var_index(this, MachineType::PointerRepresentation()); 5298 Variable var_index(this, MachineType::PointerRepresentation());
5299 Variable var_unique(this, MachineRepresentation::kTagged);
5209 5300
5210 Label if_keyisindex(this), if_iskeyunique(this); 5301 Label if_keyisindex(this), if_iskeyunique(this);
5211 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, if_bailout); 5302 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique,
5303 if_bailout);
5212 5304
5213 Bind(&if_iskeyunique); 5305 Bind(&if_iskeyunique);
5214 { 5306 {
5215 Variable var_holder(this, MachineRepresentation::kTagged); 5307 Variable var_holder(this, MachineRepresentation::kTagged);
5216 Variable var_holder_map(this, MachineRepresentation::kTagged); 5308 Variable var_holder_map(this, MachineRepresentation::kTagged);
5217 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); 5309 Variable var_holder_instance_type(this, MachineRepresentation::kWord32);
5218 5310
5219 Variable* merged_variables[] = {&var_holder, &var_holder_map, 5311 Variable* merged_variables[] = {&var_holder, &var_holder_map,
5220 &var_holder_instance_type}; 5312 &var_holder_instance_type};
5221 Label loop(this, arraysize(merged_variables), merged_variables); 5313 Label loop(this, arraysize(merged_variables), merged_variables);
5222 var_holder.Bind(receiver); 5314 var_holder.Bind(receiver);
5223 var_holder_map.Bind(map); 5315 var_holder_map.Bind(map);
5224 var_holder_instance_type.Bind(instance_type); 5316 var_holder_instance_type.Bind(instance_type);
5225 Goto(&loop); 5317 Goto(&loop);
5226 Bind(&loop); 5318 Bind(&loop);
5227 { 5319 {
5228 Node* holder_map = var_holder_map.value(); 5320 Node* holder_map = var_holder_map.value();
5229 Node* holder_instance_type = var_holder_instance_type.value(); 5321 Node* holder_instance_type = var_holder_instance_type.value();
5230 5322
5231 Label next_proto(this); 5323 Label next_proto(this);
5232 lookup_property_in_holder(receiver, var_holder.value(), holder_map, 5324 lookup_property_in_holder(receiver, var_holder.value(), holder_map,
5233 holder_instance_type, key, &next_proto, 5325 holder_instance_type, var_unique.value(),
5234 if_bailout); 5326 &next_proto, if_bailout);
5235 Bind(&next_proto); 5327 Bind(&next_proto);
5236 5328
5237 // Bailout if it can be an integer indexed exotic case. 5329 // Bailout if it can be an integer indexed exotic case.
5238 GotoIf( 5330 GotoIf(
5239 Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), 5331 Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
5240 if_bailout); 5332 if_bailout);
5241 5333
5242 Node* proto = LoadMapPrototype(holder_map); 5334 Node* proto = LoadMapPrototype(holder_map);
5243 5335
5244 Label if_not_null(this); 5336 Label if_not_null(this);
(...skipping 3005 matching lines...) Expand 10 before | Expand all | Expand 10 after
8250 deferred_on_reject); 8342 deferred_on_reject);
8251 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kDebugIdOffset, 8343 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kDebugIdOffset,
8252 SmiConstant(kDebugPromiseNoID)); 8344 SmiConstant(kDebugPromiseNoID));
8253 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset, 8345 StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset,
8254 context); 8346 context);
8255 return result; 8347 return result;
8256 } 8348 }
8257 8349
8258 } // namespace internal 8350 } // namespace internal
8259 } // namespace v8 8351 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698