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

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

Issue 2407813002: [stubs] Port StringAddStub to TF (Closed)
Patch Set: Remove stray change Created 4 years, 2 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
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 4
5 #include "src/code-stub-assembler.h" 5 #include "src/code-stub-assembler.h"
6 #include "src/code-factory.h" 6 #include "src/code-factory.h"
7 #include "src/frames-inl.h" 7 #include "src/frames-inl.h"
8 #include "src/frames.h" 8 #include "src/frames.h"
9 #include "src/ic/handler-configuration.h" 9 #include "src/ic/handler-configuration.h"
10 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 64
65 Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) { 65 Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
66 if (mode == SMI_PARAMETERS) { 66 if (mode == SMI_PARAMETERS) {
67 return SmiConstant(Smi::FromInt(value)); 67 return SmiConstant(Smi::FromInt(value));
68 } else { 68 } else {
69 DCHECK(mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS); 69 DCHECK(mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS);
70 return IntPtrConstant(value); 70 return IntPtrConstant(value);
71 } 71 }
72 } 72 }
73 73
74 Node* CodeStubAssembler::IntPtrAddFoldConstants(Node* left, Node* right) {
75 int32_t left_constant;
76 bool is_left_constant = ToInt32Constant(left, left_constant);
77 int32_t right_constant;
78 bool is_right_constant = ToInt32Constant(right, right_constant);
79 if (is_left_constant) {
80 if (is_right_constant) {
81 return IntPtrConstant(left_constant + right_constant);
82 }
83 if (left_constant == 0) {
84 return right;
85 }
86 } else if (is_right_constant) {
87 if (right_constant == 0) {
88 return left;
89 }
90 }
91 return IntPtrAdd(left, right);
92 }
93
94 Node* CodeStubAssembler::IntPtrSubFoldConstants(Node* left, Node* right) {
95 int32_t left_constant;
96 bool is_left_constant = ToInt32Constant(left, left_constant);
97 int32_t right_constant;
98 bool is_right_constant = ToInt32Constant(right, right_constant);
99 if (is_left_constant) {
100 if (is_right_constant) {
101 return IntPtrConstant(left_constant - right_constant);
102 }
103 } else if (is_right_constant) {
104 if (right_constant == 0) {
105 return left;
106 }
107 }
108 return IntPtrSub(left, right);
109 }
110
74 Node* CodeStubAssembler::Float64Round(Node* x) { 111 Node* CodeStubAssembler::Float64Round(Node* x) {
75 Node* one = Float64Constant(1.0); 112 Node* one = Float64Constant(1.0);
76 Node* one_half = Float64Constant(0.5); 113 Node* one_half = Float64Constant(0.5);
77 114
78 Variable var_x(this, MachineRepresentation::kFloat64); 115 Variable var_x(this, MachineRepresentation::kFloat64);
79 Label return_x(this); 116 Label return_x(this);
80 117
81 // Round up {x} towards Infinity. 118 // Round up {x} towards Infinity.
82 var_x.Bind(Float64Ceil(x)); 119 var_x.Bind(Float64Ceil(x));
83 120
(...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 return result; 1242 return result;
1206 } 1243 }
1207 1244
1208 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, 1245 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value,
1209 MutableMode mode) { 1246 MutableMode mode) {
1210 Node* result = AllocateHeapNumber(mode); 1247 Node* result = AllocateHeapNumber(mode);
1211 StoreHeapNumberValue(result, value); 1248 StoreHeapNumberValue(result, value);
1212 return result; 1249 return result;
1213 } 1250 }
1214 1251
1215 Node* CodeStubAssembler::AllocateSeqOneByteString(int length) { 1252 Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
1216 Node* result = Allocate(SeqOneByteString::SizeFor(length)); 1253 AllocationFlags flags) {
1254 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
1255 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
1217 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); 1256 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
1218 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1257 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
1219 SmiConstant(Smi::FromInt(length))); 1258 SmiConstant(Smi::FromInt(length)));
1220 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, 1259 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
1221 IntPtrConstant(String::kEmptyHashField), 1260 IntPtrConstant(String::kEmptyHashField),
1222 MachineRepresentation::kWord32); 1261 MachineRepresentation::kWord32);
1223 return result; 1262 return result;
1224 } 1263 }
1225 1264
1226 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) { 1265 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
1266 AllocationFlags flags) {
1227 Variable var_result(this, MachineRepresentation::kTagged); 1267 Variable var_result(this, MachineRepresentation::kTagged);
1228 1268
1229 // Compute the SeqOneByteString size and check if it fits into new space. 1269 // Compute the SeqOneByteString size and check if it fits into new space.
1230 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1270 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
1231 if_join(this); 1271 if_join(this);
1232 Node* size = WordAnd( 1272 Node* size = WordAnd(
1233 IntPtrAdd( 1273 IntPtrAdd(
1234 IntPtrAdd(length, IntPtrConstant(SeqOneByteString::kHeaderSize)), 1274 IntPtrAdd(length, IntPtrConstant(SeqOneByteString::kHeaderSize)),
1235 IntPtrConstant(kObjectAlignmentMask)), 1275 IntPtrConstant(kObjectAlignmentMask)),
1236 IntPtrConstant(~kObjectAlignmentMask)); 1276 IntPtrConstant(~kObjectAlignmentMask));
1237 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1277 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1238 &if_sizeissmall, &if_notsizeissmall); 1278 &if_sizeissmall, &if_notsizeissmall);
1239 1279
1240 Bind(&if_sizeissmall); 1280 Bind(&if_sizeissmall);
1241 { 1281 {
1242 // Just allocate the SeqOneByteString in new space. 1282 // Just allocate the SeqOneByteString in new space.
1243 Node* result = Allocate(size); 1283 Node* result = Allocate(size, flags);
1284 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
1244 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); 1285 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
1245 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1286 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
1246 SmiFromWord(length)); 1287 SmiFromWord(length));
1247 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, 1288 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
1248 IntPtrConstant(String::kEmptyHashField), 1289 IntPtrConstant(String::kEmptyHashField),
1249 MachineRepresentation::kWord32); 1290 MachineRepresentation::kWord32);
1250 var_result.Bind(result); 1291 var_result.Bind(result);
1251 Goto(&if_join); 1292 Goto(&if_join);
1252 } 1293 }
1253 1294
1254 Bind(&if_notsizeissmall); 1295 Bind(&if_notsizeissmall);
1255 { 1296 {
1256 // We might need to allocate in large object space, go to the runtime. 1297 // We might need to allocate in large object space, go to the runtime.
1257 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, 1298 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context,
1258 SmiFromWord(length)); 1299 SmiFromWord(length));
1259 var_result.Bind(result); 1300 var_result.Bind(result);
1260 Goto(&if_join); 1301 Goto(&if_join);
1261 } 1302 }
1262 1303
1263 Bind(&if_join); 1304 Bind(&if_join);
1264 return var_result.value(); 1305 return var_result.value();
1265 } 1306 }
1266 1307
1267 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) { 1308 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
1268 Node* result = Allocate(SeqTwoByteString::SizeFor(length)); 1309 AllocationFlags flags) {
1310 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
1311 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
1269 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); 1312 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
1270 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1313 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
1271 SmiConstant(Smi::FromInt(length))); 1314 SmiConstant(Smi::FromInt(length)));
1272 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, 1315 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
1273 IntPtrConstant(String::kEmptyHashField), 1316 IntPtrConstant(String::kEmptyHashField),
1274 MachineRepresentation::kWord32); 1317 MachineRepresentation::kWord32);
1275 return result; 1318 return result;
1276 } 1319 }
1277 1320
1278 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length) { 1321 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
1322 AllocationFlags flags) {
1279 Variable var_result(this, MachineRepresentation::kTagged); 1323 Variable var_result(this, MachineRepresentation::kTagged);
1280 1324
1281 // Compute the SeqTwoByteString size and check if it fits into new space. 1325 // Compute the SeqTwoByteString size and check if it fits into new space.
1282 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1326 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
1283 if_join(this); 1327 if_join(this);
1284 Node* size = WordAnd( 1328 Node* size = WordAnd(
1285 IntPtrAdd(IntPtrAdd(WordShl(length, 1), 1329 IntPtrAdd(IntPtrAdd(WordShl(length, 1),
1286 IntPtrConstant(SeqTwoByteString::kHeaderSize)), 1330 IntPtrConstant(SeqTwoByteString::kHeaderSize)),
1287 IntPtrConstant(kObjectAlignmentMask)), 1331 IntPtrConstant(kObjectAlignmentMask)),
1288 IntPtrConstant(~kObjectAlignmentMask)); 1332 IntPtrConstant(~kObjectAlignmentMask));
1289 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1333 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1290 &if_sizeissmall, &if_notsizeissmall); 1334 &if_sizeissmall, &if_notsizeissmall);
1291 1335
1292 Bind(&if_sizeissmall); 1336 Bind(&if_sizeissmall);
1293 { 1337 {
1294 // Just allocate the SeqTwoByteString in new space. 1338 // Just allocate the SeqTwoByteString in new space.
1295 Node* result = Allocate(size); 1339 Node* result = Allocate(size, flags);
1340 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
1296 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); 1341 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
1297 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1342 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
1298 SmiFromWord(length)); 1343 SmiFromWord(length));
1299 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, 1344 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
1300 IntPtrConstant(String::kEmptyHashField), 1345 IntPtrConstant(String::kEmptyHashField),
1301 MachineRepresentation::kWord32); 1346 MachineRepresentation::kWord32);
1302 var_result.Bind(result); 1347 var_result.Bind(result);
1303 Goto(&if_join); 1348 Goto(&if_join);
1304 } 1349 }
1305 1350
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 Bind(&done); 1761 Bind(&done);
1717 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); 1762 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1);
1718 Comment("] CopyFixedArrayElements"); 1763 Comment("] CopyFixedArrayElements");
1719 } 1764 }
1720 1765
1721 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, 1766 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string,
1722 compiler::Node* to_string, 1767 compiler::Node* to_string,
1723 compiler::Node* from_index, 1768 compiler::Node* from_index,
1724 compiler::Node* to_index, 1769 compiler::Node* to_index,
1725 compiler::Node* character_count, 1770 compiler::Node* character_count,
1726 String::Encoding encoding) { 1771 String::Encoding encoding,
1727 Label out(this); 1772 ParameterMode mode) {
1773 bool one_byte = encoding == String::ONE_BYTE_ENCODING;
1774 Comment(one_byte ? "CopyStringCharacters ONE_BYTE_ENCODING"
1775 : "CopyStringCharacters TWO_BYTE_ENCODING");
1728 1776
1729 // Nothing to do for zero characters. 1777 ElementsKind kind = one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
1778 int header_size = (one_byte ? SeqOneByteString::kHeaderSize
1779 : SeqTwoByteString::kHeaderSize) -
1780 kHeapObjectTag;
1781 Node* from_offset = ElementOffsetFromIndex(from_index, kind, mode);
1782 Node* to_offset = ElementOffsetFromIndex(to_index, kind, mode);
1783 Node* byte_count = ElementOffsetFromIndex(character_count, kind, mode);
1784 Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count);
1730 1785
1731 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::kZero)), &out); 1786 // Prepare the fast loop
1787 MachineType type = one_byte ? MachineType::Uint8() : MachineType::Uint16();
1788 MachineRepresentation rep =
1789 one_byte ? MachineRepresentation::kWord8 : MachineRepresentation::kWord16;
1790 int increment = -(1 << ElementsKindToShiftSize(kind));
1732 1791
1733 // Calculate offsets into the strings. 1792 Node* to_string_adjusted = IntPtrAddFoldConstants(
1793 to_string, IntPtrSubFoldConstants(to_offset, from_offset));
1794 limit_offset =
1795 IntPtrAddFoldConstants(limit_offset, IntPtrConstant(header_size));
1796 from_offset =
1797 IntPtrAddFoldConstants(from_offset, IntPtrConstant(header_size));
1734 1798
1735 Node* from_offset; 1799 BuildFastLoop(MachineType::PointerRepresentation(), limit_offset, from_offset,
1736 Node* limit_offset; 1800 [from_string, to_string_adjusted, type, rep](
1737 Node* to_offset; 1801 CodeStubAssembler* assembler, Node* offset) {
1738 1802 Node* value = assembler->Load(type, from_string, offset);
1739 { 1803 assembler->StoreNoWriteBarrier(rep, to_string_adjusted,
1740 Node* byte_count = SmiUntag(character_count); 1804 offset, value);
1741 Node* from_byte_index = SmiUntag(from_index); 1805 },
1742 Node* to_byte_index = SmiUntag(to_index); 1806 increment);
1743 if (encoding == String::ONE_BYTE_ENCODING) {
1744 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag;
1745 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
1746 limit_offset = IntPtrAdd(from_offset, byte_count);
1747 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
1748 } else {
1749 STATIC_ASSERT(2 == sizeof(uc16));
1750 byte_count = WordShl(byte_count, 1);
1751 from_byte_index = WordShl(from_byte_index, 1);
1752 to_byte_index = WordShl(to_byte_index, 1);
1753
1754 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag;
1755 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
1756 limit_offset = IntPtrAdd(from_offset, byte_count);
1757 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
1758 }
1759 }
1760
1761 Variable var_from_offset(this, MachineType::PointerRepresentation());
1762 Variable var_to_offset(this, MachineType::PointerRepresentation());
1763
1764 var_from_offset.Bind(from_offset);
1765 var_to_offset.Bind(to_offset);
1766
1767 Variable* vars[] = {&var_from_offset, &var_to_offset};
1768 Label decrement(this, 2, vars);
1769
1770 Label loop(this, 2, vars);
1771 Goto(&loop);
1772 Bind(&loop);
1773 {
1774 from_offset = var_from_offset.value();
1775 to_offset = var_to_offset.value();
1776
1777 // TODO(jgruber): We could make this faster through larger copy unit sizes.
1778 Node* value = Load(MachineType::Uint8(), from_string, from_offset);
1779 StoreNoWriteBarrier(MachineRepresentation::kWord8, to_string, to_offset,
1780 value);
1781
1782 Node* new_from_offset = IntPtrAdd(from_offset, IntPtrConstant(1));
1783 var_from_offset.Bind(new_from_offset);
1784 var_to_offset.Bind(IntPtrAdd(to_offset, IntPtrConstant(1)));
1785
1786 Branch(WordNotEqual(new_from_offset, limit_offset), &loop, &out);
1787 }
1788
1789 Bind(&out);
1790 } 1807 }
1791 1808
1792 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, 1809 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
1793 Node* offset, 1810 Node* offset,
1794 ElementsKind from_kind, 1811 ElementsKind from_kind,
1795 ElementsKind to_kind, 1812 ElementsKind to_kind,
1796 Label* if_hole) { 1813 Label* if_hole) {
1797 if (IsFastDoubleElementsKind(from_kind)) { 1814 if (IsFastDoubleElementsKind(from_kind)) {
1798 Node* value = 1815 Node* value =
1799 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); 1816 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64());
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
2558 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, 2575 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type,
2559 a->Int32Constant(kStringEncodingMask)), 2576 a->Int32Constant(kStringEncodingMask)),
2560 a->Int32Constant(0)), 2577 a->Int32Constant(0)),
2561 &two_byte_sequential); 2578 &two_byte_sequential);
2562 2579
2563 // The subject string is a sequential one-byte string. 2580 // The subject string is a sequential one-byte string.
2564 { 2581 {
2565 Node* result = 2582 Node* result =
2566 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); 2583 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
2567 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 2584 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
2568 String::ONE_BYTE_ENCODING); 2585 String::ONE_BYTE_ENCODING,
2586 CodeStubAssembler::SMI_PARAMETERS);
2569 var_result.Bind(result); 2587 var_result.Bind(result);
2570 2588
2571 a->Goto(&end); 2589 a->Goto(&end);
2572 } 2590 }
2573 2591
2574 // The subject string is a sequential two-byte string. 2592 // The subject string is a sequential two-byte string.
2575 a->Bind(&two_byte_sequential); 2593 a->Bind(&two_byte_sequential);
2576 { 2594 {
2577 Node* result = 2595 Node* result =
2578 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); 2596 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count));
2579 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 2597 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
2580 String::TWO_BYTE_ENCODING); 2598 String::TWO_BYTE_ENCODING,
2599 CodeStubAssembler::SMI_PARAMETERS);
2581 var_result.Bind(result); 2600 var_result.Bind(result);
2582 2601
2583 a->Goto(&end); 2602 a->Goto(&end);
2584 } 2603 }
2585 2604
2586 a->Bind(&end); 2605 a->Bind(&end);
2587 return var_result.value(); 2606 return var_result.value();
2588 } 2607 }
2589 2608
2590 } // namespace 2609 } // namespace
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2842 Node* const min_cons_length = 2861 Node* const min_cons_length =
2843 SmiConstant(Smi::FromInt(ConsString::kMinLength)); 2862 SmiConstant(Smi::FromInt(ConsString::kMinLength));
2844 Branch(SmiLessThan(length, min_cons_length), &if_makeseqstring, 2863 Branch(SmiLessThan(length, min_cons_length), &if_makeseqstring,
2845 &if_makeconsstring); 2864 &if_makeconsstring);
2846 2865
2847 Bind(&if_makeseqstring); 2866 Bind(&if_makeseqstring);
2848 { 2867 {
2849 Node* result = AllocateSeqOneByteString(context, SmiToWord(length)); 2868 Node* result = AllocateSeqOneByteString(context, SmiToWord(length));
2850 2869
2851 CopyStringCharacters(first, result, smi_zero, smi_zero, first_length, 2870 CopyStringCharacters(first, result, smi_zero, smi_zero, first_length,
2852 String::ONE_BYTE_ENCODING); 2871 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
2853 CopyStringCharacters(second, result, smi_zero, first_length, second_length, 2872 CopyStringCharacters(second, result, smi_zero, first_length, second_length,
2854 String::ONE_BYTE_ENCODING); 2873 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
2855 2874
2856 var_result.Bind(result); 2875 var_result.Bind(result);
2857 Goto(&out); 2876 Goto(&out);
2858 } 2877 }
2859 2878
2860 Bind(&if_makeconsstring); 2879 Bind(&if_makeconsstring);
2861 { 2880 {
2862 Node* result = AllocateOneByteConsString(length, first, second); 2881 Node* result = AllocateOneByteConsString(length, first, second);
2863 var_result.Bind(result); 2882 var_result.Bind(result);
2864 Goto(&out); 2883 Goto(&out);
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
3268 { 3287 {
3269 var_result.Bind(NonNumberToNumber(context, input)); 3288 var_result.Bind(NonNumberToNumber(context, input));
3270 Goto(&end); 3289 Goto(&end);
3271 } 3290 }
3272 } 3291 }
3273 3292
3274 Bind(&end); 3293 Bind(&end);
3275 return var_result.value(); 3294 return var_result.value();
3276 } 3295 }
3277 3296
3297 Node* CodeStubAssembler::ToString(Node* context, Node* input) {
3298 Label is_number(this);
3299 Label runtime(this, Label::kDeferred);
3300 Variable result(this, MachineRepresentation::kTagged);
3301 Label done(this, &result);
3302
3303 GotoIf(TaggedIsSmi(input), &is_number);
3304
3305 Node* input_map = LoadMap(input);
3306 Node* input_instance_type = LoadMapInstanceType(input_map);
3307
3308 result.Bind(input);
3309 GotoIf(IsStringInstanceType(input_instance_type), &done);
3310
3311 Label not_heap_number(this);
3312 Branch(WordNotEqual(input_map, HeapNumberMapConstant()), &not_heap_number,
3313 &is_number);
3314
3315 Bind(&is_number);
3316 result.Bind(NumberToString(context, input));
3317 Goto(&done);
3318
3319 Bind(&not_heap_number);
3320 {
3321 GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)),
3322 &runtime);
3323 result.Bind(LoadObjectField(input, Oddball::kToStringOffset));
3324 Goto(&done);
3325 }
3326
3327 Bind(&runtime);
3328 {
3329 result.Bind(CallRuntime(Runtime::kToString, context, input));
3330 Goto(&done);
3331 }
3332
3333 Bind(&done);
3334 return result.value();
3335 }
3336
3337 Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
3338 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3339 Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
3340 Variable result(this, MachineRepresentation::kTagged);
3341 Label done(this, &result);
3342
3343 GotoIf(TaggedIsSmi(input), &if_isnotreceiver);
3344
3345 Node* map = LoadMap(input);
3346 Node* instance_type = LoadMapInstanceType(map);
3347 Branch(IsJSReceiverInstanceType(instance_type), &if_isreceiver,
3348 &if_isnotreceiver);
3349
3350 Bind(&if_isreceiver);
3351 {
3352 // Convert {input} to a primitive first passing Number hint.
3353 Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
3354 result.Bind(CallStub(callable, context, input));
3355 Goto(&done);
3356 }
3357
3358 Bind(&if_isnotreceiver);
3359 {
3360 result.Bind(input);
3361 Goto(&done);
3362 }
3363
3364 Bind(&done);
3365 return result.value();
3366 }
3367
3368 Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left,
3369 Node* right, AllocationFlags flags) {
3370 // Added string can be a cons string.
3371 Comment("Allocating ConsString");
3372 Node* left_instance_type = LoadInstanceType(left);
3373 Node* right_instance_type = LoadInstanceType(right);
3374
3375 // Allocate the cons string object. After the allocation we decide whether the
3376 // cons string is one-byte or two-byte and set the appropriate map.
3377 Node* cons_string = Allocate(IntPtrConstant(ConsString::kSize), flags);
3378
3379 // Compute intersection and difference of instance types.
3380 Node* anded_instance_types = WordAnd(left_instance_type, right_instance_type);
3381 Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
3382
3383 // We create a one-byte cons string if
3384 // 1. both strings are one-byte, or
3385 // 2. at least one of the strings is two-byte, but happens to contain only
3386 // one-byte characters.
3387 // To do this, we check
3388 // 1. if both strings are one-byte, or if the one-byte data hint is set in
3389 // both strings, or
Igor Sheludko 2016/10/13 15:41:33 I wonder why does kOneByteStringTag not imply kOne
danno 2016/10/17 14:23:26 Good question, although before pulling on this str
3390 // 2. if one of the strings has the one-byte data hint set and the other
3391 // string is one-byte.
3392 STATIC_ASSERT(kOneByteStringTag != 0);
3393 STATIC_ASSERT(kOneByteDataHintMask != 0);
Igor Sheludko 2016/10/13 15:41:33 kOneByteDataHintTag != 0
danno 2016/10/17 14:23:26 Done.
3394 Label one_byte_map(this);
3395 Label two_byte_map(this);
3396 Label map_done(this);
3397 GotoIf(WordNotEqual(
3398 WordAnd(anded_instance_types,
3399 IntPtrConstant(kOneByteStringTag | kOneByteDataHintTag)),
3400 IntPtrConstant(0)),
3401 &one_byte_map);
3402 Branch(WordNotEqual(
3403 WordAnd(xored_instance_types,
3404 IntPtrConstant(kOneByteStringTag | kOneByteDataHintMask)),
Igor Sheludko 2016/10/13 15:41:33 kOneByteStringTag -> kStringEncodingMask
danno 2016/10/17 14:23:26 Done.
3405 IntPtrConstant(kOneByteStringTag | kOneByteDataHintTag)),
3406 &two_byte_map, &one_byte_map);
3407
3408 Bind(&one_byte_map);
3409 Comment("One-byte ConsString");
3410 DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsOneByteStringMapRootIndex));
3411 StoreMapNoWriteBarrier(cons_string,
3412 LoadRoot(Heap::kConsOneByteStringMapRootIndex));
jgruber 2016/10/13 14:10:16 Would it make sense to reuse Allocate{One,Two}Byte
danno 2016/10/17 14:23:26 Yes! Good catch!
3413 Goto(&map_done);
3414
3415 Bind(&two_byte_map);
3416 Comment("Two-byte ConsString");
3417 DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsStringMapRootIndex));
3418 StoreMapNoWriteBarrier(cons_string, LoadRoot(Heap::kConsStringMapRootIndex));
3419 Goto(&map_done);
3420
3421 Bind(&map_done);
3422 StoreObjectFieldNoWriteBarrier(cons_string, String::kHashFieldOffset,
3423 IntPtrConstant(String::kEmptyHashField));
3424 StoreObjectFieldNoWriteBarrier(cons_string, String::kLengthOffset,
3425 SmiTag(length));
3426 bool const new_space = !(flags & kPretenured);
3427 if (new_space) {
3428 StoreObjectFieldNoWriteBarrier(cons_string, ConsString::kFirstOffset, left);
3429 StoreObjectFieldNoWriteBarrier(cons_string, ConsString::kSecondOffset,
3430 right);
3431 } else {
3432 StoreObjectField(cons_string, ConsString::kFirstOffset, left);
3433 StoreObjectField(cons_string, ConsString::kSecondOffset, right);
3434 }
3435
3436 return cons_string;
3437 }
3438
3439 Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
jgruber 2016/10/13 14:10:16 This is basically a more complete version of Strin
danno 2016/10/17 14:23:26 I totally missed that this existed when I ported f
3440 AllocationFlags flags) {
3441 Label check_right(this);
3442 Label runtime(this, Label::kDeferred);
3443 Label cons(this);
3444 Label non_cons(this);
3445 Variable result(this, MachineRepresentation::kTagged);
3446 Label done(this, &result);
3447 Label done_native(this, &result);
3448 Counters* counters = isolate()->counters();
3449
3450 Node* left_length = LoadStringLength(left);
3451 GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right);
3452 result.Bind(right);
3453 Goto(&done_native);
3454
3455 Bind(&check_right);
3456 Node* right_length = LoadStringLength(right);
3457 GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons);
3458 result.Bind(left);
3459 Goto(&done_native);
3460
3461 Bind(&cons);
3462 Node* new_length = IntPtrAdd(SmiUntag(left_length), SmiUntag(right_length));
3463 GotoIf(IntPtrLessThan(new_length, IntPtrConstant(0)), &runtime);
3464 GotoIf(IntPtrGreaterThan(new_length, IntPtrConstant(String::kMaxLength)),
Igor Sheludko 2016/10/13 15:41:33 How about doing one unsigned comparison instead of
danno 2016/10/17 14:23:26 Done.
3465 &runtime);
3466
3467 GotoIf(IntPtrLessThan(new_length, IntPtrConstant(ConsString::kMinLength)),
3468 &non_cons);
3469
3470 result.Bind(NewConsString(context, new_length, left, right, flags));
3471 Goto(&done_native);
3472
3473 Bind(&non_cons);
3474
3475 Comment("Full string concatenate");
3476 Node* left_instance_type = LoadInstanceType(left);
3477 Node* right_instance_type = LoadInstanceType(right);
3478 // Compute intersection and difference of instance types.
3479
3480 Node* ored_instance_types = WordOr(left_instance_type, right_instance_type);
3481 Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
3482
3483 // Check if both strings have the same encoding and both are sequential.
3484 GotoIf(WordNotEqual(
3485 WordAnd(xored_instance_types, IntPtrConstant(kStringEncodingMask)),
3486 IntPtrConstant(0)),
3487 &runtime);
3488 GotoIf(WordNotEqual(WordAnd(ored_instance_types,
3489 IntPtrConstant(kStringRepresentationMask)),
3490 IntPtrConstant(0)),
3491 &runtime);
3492
3493 Label two_byte(this);
3494 GotoIf(WordEqual(
3495 WordAnd(ored_instance_types, IntPtrConstant(kStringEncodingMask)),
3496 IntPtrConstant(0)),
Igor Sheludko 2016/10/13 15:41:33 0 -> kTwoByteStringTag or STATIC_ASSERT
danno 2016/10/17 14:23:26 Done.
3497 &two_byte);
3498 // One-byte sequential string case
3499 Node* new_string = AllocateSeqOneByteString(context, new_length);
3500 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
3501 SmiConstant(Smi::kZero), left_length,
3502 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
3503 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length,
3504 right_length, String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
3505 result.Bind(new_string);
3506 Goto(&done_native);
3507
3508 Bind(&two_byte);
3509 {
3510 // Two-byte sequential string case
3511 new_string = AllocateSeqTwoByteString(context, new_length);
3512 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
3513 SmiConstant(Smi::kZero), left_length,
3514 String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
3515 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero),
3516 left_length, right_length, String::TWO_BYTE_ENCODING,
3517 SMI_PARAMETERS);
3518 result.Bind(new_string);
3519 Goto(&done_native);
3520 }
3521
3522 Bind(&runtime);
3523 {
3524 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right));
3525 Goto(&done);
3526 }
3527
3528 Bind(&done_native);
3529 {
3530 IncrementCounter(counters->string_add_native(), 1);
3531 Goto(&done);
3532 }
3533
3534 Bind(&done);
3535 return result.value();
3536 }
3537
3278 Node* CodeStubAssembler::ToInteger(Node* context, Node* input, 3538 Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
3279 ToIntegerTruncationMode mode) { 3539 ToIntegerTruncationMode mode) {
3280 // We might need to loop once for ToNumber conversion. 3540 // We might need to loop once for ToNumber conversion.
3281 Variable var_arg(this, MachineRepresentation::kTagged); 3541 Variable var_arg(this, MachineRepresentation::kTagged);
3282 Label loop(this, &var_arg), out(this); 3542 Label loop(this, &var_arg), out(this);
3283 var_arg.Bind(input); 3543 var_arg.Bind(input);
3284 Goto(&loop); 3544 Goto(&loop);
3285 Bind(&loop); 3545 Bind(&loop);
3286 { 3546 {
3287 // Shared entry points. 3547 // Shared entry points.
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
4331 } else { 4591 } else {
4332 DCHECK(mode == INTPTR_PARAMETERS); 4592 DCHECK(mode == INTPTR_PARAMETERS);
4333 constant_index = ToIntPtrConstant(index_node, index); 4593 constant_index = ToIntPtrConstant(index_node, index);
4334 } 4594 }
4335 if (constant_index) { 4595 if (constant_index) {
4336 return IntPtrConstant(base_size + element_size * index); 4596 return IntPtrConstant(base_size + element_size * index);
4337 } 4597 }
4338 if (Is64() && mode == INTEGER_PARAMETERS) { 4598 if (Is64() && mode == INTEGER_PARAMETERS) {
4339 index_node = ChangeInt32ToInt64(index_node); 4599 index_node = ChangeInt32ToInt64(index_node);
4340 } 4600 }
4341 if (base_size == 0) { 4601
4342 return (element_size_shift >= 0) 4602 Node* shifted_index =
4343 ? WordShl(index_node, IntPtrConstant(element_size_shift)) 4603 (element_size_shift == 0)
4344 : WordShr(index_node, IntPtrConstant(-element_size_shift)); 4604 ? index_node
4345 } 4605 : ((element_size_shift > 0)
4346 return IntPtrAdd( 4606 ? WordShl(index_node, IntPtrConstant(element_size_shift))
4347 IntPtrConstant(base_size), 4607 : WordShr(index_node, IntPtrConstant(-element_size_shift)));
4348 (element_size_shift >= 0) 4608 return IntPtrAddFoldConstants(IntPtrConstant(base_size), shifted_index);
4349 ? WordShl(index_node, IntPtrConstant(element_size_shift))
4350 : WordShr(index_node, IntPtrConstant(-element_size_shift)));
4351 } 4609 }
4352 4610
4353 compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() { 4611 compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() {
4354 Node* function = 4612 Node* function =
4355 LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset); 4613 LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset);
4356 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset); 4614 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset);
4357 return LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset); 4615 return LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset);
4358 } 4616 }
4359 4617
4360 void CodeStubAssembler::UpdateFeedback(compiler::Node* feedback, 4618 void CodeStubAssembler::UpdateFeedback(compiler::Node* feedback,
(...skipping 3055 matching lines...) Expand 10 before | Expand all | Expand 10 after
7416 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); 7674 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable));
7417 Goto(&end); 7675 Goto(&end);
7418 } 7676 }
7419 7677
7420 Bind(&end); 7678 Bind(&end);
7421 return result.value(); 7679 return result.value();
7422 } 7680 }
7423 7681
7424 } // namespace internal 7682 } // namespace internal
7425 } // namespace v8 7683 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698