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

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

Issue 2407813002: [stubs] Port StringAddStub to TF (Closed)
Patch Set: Make ASSERT cheaper 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
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.h » ('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 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 12 matching lines...) Expand all
23 23
24 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone, 24 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
25 int parameter_count, Code::Flags flags, 25 int parameter_count, Code::Flags flags,
26 const char* name) 26 const char* name)
27 : compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {} 27 : compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {}
28 28
29 void CodeStubAssembler::Assert(Node* condition, const char* message, 29 void CodeStubAssembler::Assert(Node* condition, const char* message,
30 const char* file, int line) { 30 const char* file, int line) {
31 #if defined(DEBUG) 31 #if defined(DEBUG)
32 Label ok(this); 32 Label ok(this);
33 Label not_ok(this, Label::kDeferred);
33 if (message != nullptr && FLAG_code_comments) { 34 if (message != nullptr && FLAG_code_comments) {
34 Comment("[ Assert: %s", message); 35 Comment("[ Assert: %s", message);
35 } else { 36 } else {
36 Comment("[ Assert "); 37 Comment("[ Assert ");
37 } 38 }
38 39
39 GotoIf(condition, &ok); 40 Branch(condition, &ok, &not_ok);
41 Bind(&not_ok);
40 if (message != nullptr) { 42 if (message != nullptr) {
41 char chars[1024]; 43 char chars[1024];
42 Vector<char> buffer(chars); 44 Vector<char> buffer(chars);
43 if (file != nullptr) { 45 if (file != nullptr) {
44 SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file, line); 46 SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file, line);
45 } else { 47 } else {
46 SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message); 48 SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message);
47 } 49 }
48 CallRuntime( 50 CallRuntime(
49 Runtime::kGlobalPrint, SmiConstant(Smi::kZero), 51 Runtime::kGlobalPrint, SmiConstant(Smi::kZero),
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 84
83 Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) { 85 Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
84 if (mode == SMI_PARAMETERS) { 86 if (mode == SMI_PARAMETERS) {
85 return SmiConstant(Smi::FromInt(value)); 87 return SmiConstant(Smi::FromInt(value));
86 } else { 88 } else {
87 DCHECK(mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS); 89 DCHECK(mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS);
88 return IntPtrConstant(value); 90 return IntPtrConstant(value);
89 } 91 }
90 } 92 }
91 93
94 Node* CodeStubAssembler::IntPtrAddFoldConstants(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 if (left_constant == 0) {
104 return right;
105 }
106 } else if (is_right_constant) {
107 if (right_constant == 0) {
108 return left;
109 }
110 }
111 return IntPtrAdd(left, right);
112 }
113
114 Node* CodeStubAssembler::IntPtrSubFoldConstants(Node* left, Node* right) {
115 int32_t left_constant;
116 bool is_left_constant = ToInt32Constant(left, left_constant);
117 int32_t right_constant;
118 bool is_right_constant = ToInt32Constant(right, right_constant);
119 if (is_left_constant) {
120 if (is_right_constant) {
121 return IntPtrConstant(left_constant - right_constant);
122 }
123 } else if (is_right_constant) {
124 if (right_constant == 0) {
125 return left;
126 }
127 }
128 return IntPtrSub(left, right);
129 }
130
92 Node* CodeStubAssembler::Float64Round(Node* x) { 131 Node* CodeStubAssembler::Float64Round(Node* x) {
93 Node* one = Float64Constant(1.0); 132 Node* one = Float64Constant(1.0);
94 Node* one_half = Float64Constant(0.5); 133 Node* one_half = Float64Constant(0.5);
95 134
96 Variable var_x(this, MachineRepresentation::kFloat64); 135 Variable var_x(this, MachineRepresentation::kFloat64);
97 Label return_x(this); 136 Label return_x(this);
98 137
99 // Round up {x} towards Infinity. 138 // Round up {x} towards Infinity.
100 var_x.Bind(Float64Ceil(x)); 139 var_x.Bind(Float64Ceil(x));
101 140
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 return result; 1255 return result;
1217 } 1256 }
1218 1257
1219 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, 1258 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value,
1220 MutableMode mode) { 1259 MutableMode mode) {
1221 Node* result = AllocateHeapNumber(mode); 1260 Node* result = AllocateHeapNumber(mode);
1222 StoreHeapNumberValue(result, value); 1261 StoreHeapNumberValue(result, value);
1223 return result; 1262 return result;
1224 } 1263 }
1225 1264
1226 Node* CodeStubAssembler::AllocateSeqOneByteString(int length) { 1265 Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
1227 Node* result = Allocate(SeqOneByteString::SizeFor(length)); 1266 AllocationFlags flags) {
1267 Comment("AllocateSeqOneByteString");
1268 Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
1269 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
1228 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); 1270 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
1229 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1271 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
1230 SmiConstant(Smi::FromInt(length))); 1272 SmiConstant(Smi::FromInt(length)));
1231 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, 1273 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
1232 IntPtrConstant(String::kEmptyHashField), 1274 IntPtrConstant(String::kEmptyHashField),
1233 MachineRepresentation::kWord32); 1275 MachineRepresentation::kWord32);
1234 return result; 1276 return result;
1235 } 1277 }
1236 1278
1237 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) { 1279 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
1280 ParameterMode mode,
1281 AllocationFlags flags) {
1282 Comment("AllocateSeqOneByteString");
1238 Variable var_result(this, MachineRepresentation::kTagged); 1283 Variable var_result(this, MachineRepresentation::kTagged);
1239 1284
1240 // Compute the SeqOneByteString size and check if it fits into new space. 1285 // Compute the SeqOneByteString size and check if it fits into new space.
1241 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1286 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
1242 if_join(this); 1287 if_join(this);
1243 Node* size = WordAnd( 1288 Node* raw_size = GetArrayAllocationSize(
1244 IntPtrAdd( 1289 length, UINT8_ELEMENTS, mode,
1245 IntPtrAdd(length, IntPtrConstant(SeqOneByteString::kHeaderSize)), 1290 SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
1246 IntPtrConstant(kObjectAlignmentMask)), 1291 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
1247 IntPtrConstant(~kObjectAlignmentMask));
1248 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1292 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1249 &if_sizeissmall, &if_notsizeissmall); 1293 &if_sizeissmall, &if_notsizeissmall);
1250 1294
1251 Bind(&if_sizeissmall); 1295 Bind(&if_sizeissmall);
1252 { 1296 {
1253 // Just allocate the SeqOneByteString in new space. 1297 // Just allocate the SeqOneByteString in new space.
1254 Node* result = Allocate(size); 1298 Node* result = Allocate(size, flags);
1299 DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
1255 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); 1300 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
1256 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1301 StoreObjectFieldNoWriteBarrier(
1257 SmiFromWord(length)); 1302 result, SeqOneByteString::kLengthOffset,
1303 mode == SMI_PARAMETERS ? length : SmiFromWord(length));
1258 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, 1304 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
1259 IntPtrConstant(String::kEmptyHashField), 1305 IntPtrConstant(String::kEmptyHashField),
1260 MachineRepresentation::kWord32); 1306 MachineRepresentation::kWord32);
1261 var_result.Bind(result); 1307 var_result.Bind(result);
1262 Goto(&if_join); 1308 Goto(&if_join);
1263 } 1309 }
1264 1310
1265 Bind(&if_notsizeissmall); 1311 Bind(&if_notsizeissmall);
1266 { 1312 {
1267 // We might need to allocate in large object space, go to the runtime. 1313 // We might need to allocate in large object space, go to the runtime.
1268 Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, 1314 Node* result =
1269 SmiFromWord(length)); 1315 CallRuntime(Runtime::kAllocateSeqOneByteString, context,
1316 mode == SMI_PARAMETERS ? length : SmiFromWord(length));
1270 var_result.Bind(result); 1317 var_result.Bind(result);
1271 Goto(&if_join); 1318 Goto(&if_join);
1272 } 1319 }
1273 1320
1274 Bind(&if_join); 1321 Bind(&if_join);
1275 return var_result.value(); 1322 return var_result.value();
1276 } 1323 }
1277 1324
1278 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) { 1325 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
1279 Node* result = Allocate(SeqTwoByteString::SizeFor(length)); 1326 AllocationFlags flags) {
1327 Comment("AllocateSeqTwoByteString");
1328 Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
1329 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
1280 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); 1330 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
1281 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1331 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
1282 SmiConstant(Smi::FromInt(length))); 1332 SmiConstant(Smi::FromInt(length)));
1283 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, 1333 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
1284 IntPtrConstant(String::kEmptyHashField), 1334 IntPtrConstant(String::kEmptyHashField),
1285 MachineRepresentation::kWord32); 1335 MachineRepresentation::kWord32);
1286 return result; 1336 return result;
1287 } 1337 }
1288 1338
1289 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length) { 1339 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
1340 ParameterMode mode,
1341 AllocationFlags flags) {
1342 Comment("AllocateSeqTwoByteString");
1290 Variable var_result(this, MachineRepresentation::kTagged); 1343 Variable var_result(this, MachineRepresentation::kTagged);
1291 1344
1292 // Compute the SeqTwoByteString size and check if it fits into new space. 1345 // Compute the SeqTwoByteString size and check if it fits into new space.
1293 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred), 1346 Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
1294 if_join(this); 1347 if_join(this);
1295 Node* size = WordAnd( 1348 Node* raw_size = GetArrayAllocationSize(
1296 IntPtrAdd(IntPtrAdd(WordShl(length, 1), 1349 length, UINT16_ELEMENTS, mode,
1297 IntPtrConstant(SeqTwoByteString::kHeaderSize)), 1350 SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
1298 IntPtrConstant(kObjectAlignmentMask)), 1351 Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
1299 IntPtrConstant(~kObjectAlignmentMask));
1300 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 1352 Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
1301 &if_sizeissmall, &if_notsizeissmall); 1353 &if_sizeissmall, &if_notsizeissmall);
1302 1354
1303 Bind(&if_sizeissmall); 1355 Bind(&if_sizeissmall);
1304 { 1356 {
1305 // Just allocate the SeqTwoByteString in new space. 1357 // Just allocate the SeqTwoByteString in new space.
1306 Node* result = Allocate(size); 1358 Node* result = Allocate(size, flags);
1359 DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
1307 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); 1360 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
1308 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1361 StoreObjectFieldNoWriteBarrier(
1309 SmiFromWord(length)); 1362 result, SeqTwoByteString::kLengthOffset,
1363 mode == SMI_PARAMETERS ? length : SmiFromWord(length));
1310 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, 1364 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
1311 IntPtrConstant(String::kEmptyHashField), 1365 IntPtrConstant(String::kEmptyHashField),
1312 MachineRepresentation::kWord32); 1366 MachineRepresentation::kWord32);
1313 var_result.Bind(result); 1367 var_result.Bind(result);
1314 Goto(&if_join); 1368 Goto(&if_join);
1315 } 1369 }
1316 1370
1317 Bind(&if_notsizeissmall); 1371 Bind(&if_notsizeissmall);
1318 { 1372 {
1319 // We might need to allocate in large object space, go to the runtime. 1373 // We might need to allocate in large object space, go to the runtime.
1320 Node* result = CallRuntime(Runtime::kAllocateSeqTwoByteString, context, 1374 Node* result =
1321 SmiFromWord(length)); 1375 CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
1376 mode == SMI_PARAMETERS ? length : SmiFromWord(length));
1322 var_result.Bind(result); 1377 var_result.Bind(result);
1323 Goto(&if_join); 1378 Goto(&if_join);
1324 } 1379 }
1325 1380
1326 Bind(&if_join); 1381 Bind(&if_join);
1327 return var_result.value(); 1382 return var_result.value();
1328 } 1383 }
1329 1384
1330 Node* CodeStubAssembler::AllocateSlicedOneByteString(Node* length, Node* parent, 1385 Node* CodeStubAssembler::AllocateSlicedOneByteString(Node* length, Node* parent,
1331 Node* offset) { 1386 Node* offset) {
1332 Node* result = Allocate(SlicedString::kSize); 1387 Node* result = Allocate(SlicedString::kSize);
1333 Node* map = LoadRoot(Heap::kSlicedOneByteStringMapRootIndex); 1388 Node* map = LoadRoot(Heap::kSlicedOneByteStringMapRootIndex);
1334 StoreMapNoWriteBarrier(result, map); 1389 StoreMapNoWriteBarrier(result, map);
1335 StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length, 1390 StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length,
1336 MachineRepresentation::kTagged); 1391 MachineRepresentation::kTagged);
1337 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, 1392 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset,
1338 Int32Constant(String::kEmptyHashField), 1393 Int32Constant(String::kEmptyHashField),
1339 MachineRepresentation::kWord32); 1394 MachineRepresentation::kWord32);
1340 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, 1395 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent,
1341 MachineRepresentation::kTagged); 1396 MachineRepresentation::kTagged);
1342 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, 1397 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset,
1343 MachineRepresentation::kTagged); 1398 MachineRepresentation::kTagged);
1344 return result; 1399 return result;
1345 } 1400 }
1346 1401
1347 Node* CodeStubAssembler::AllocateSlicedTwoByteString(Node* length, Node* parent, 1402 Node* CodeStubAssembler::AllocateSlicedTwoByteString(Node* length, Node* parent,
1348 Node* offset) { 1403 Node* offset) {
1404 CSA_ASSERT(TaggedIsSmi(length));
1349 Node* result = Allocate(SlicedString::kSize); 1405 Node* result = Allocate(SlicedString::kSize);
1350 Node* map = LoadRoot(Heap::kSlicedStringMapRootIndex); 1406 Node* map = LoadRoot(Heap::kSlicedStringMapRootIndex);
1351 StoreMapNoWriteBarrier(result, map); 1407 StoreMapNoWriteBarrier(result, map);
1352 StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length, 1408 StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length,
1353 MachineRepresentation::kTagged); 1409 MachineRepresentation::kTagged);
1354 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, 1410 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset,
1355 Int32Constant(String::kEmptyHashField), 1411 Int32Constant(String::kEmptyHashField),
1356 MachineRepresentation::kWord32); 1412 MachineRepresentation::kWord32);
1357 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, 1413 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent,
1358 MachineRepresentation::kTagged); 1414 MachineRepresentation::kTagged);
1359 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, 1415 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset,
1360 MachineRepresentation::kTagged); 1416 MachineRepresentation::kTagged);
1361 return result; 1417 return result;
1362 } 1418 }
1363 1419
1364 Node* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first, 1420 Node* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first,
1365 Node* second) { 1421 Node* second,
1366 Node* result = Allocate(ConsString::kSize); 1422 AllocationFlags flags) {
1423 CSA_ASSERT(TaggedIsSmi(length));
1424 Node* result = Allocate(ConsString::kSize, flags);
1367 Node* map = LoadRoot(Heap::kConsOneByteStringMapRootIndex); 1425 Node* map = LoadRoot(Heap::kConsOneByteStringMapRootIndex);
1426 DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsOneByteStringMapRootIndex));
1368 StoreMapNoWriteBarrier(result, map); 1427 StoreMapNoWriteBarrier(result, map);
1369 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, 1428 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length,
1370 MachineRepresentation::kTagged); 1429 MachineRepresentation::kTagged);
1371 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, 1430 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset,
1372 Int32Constant(String::kEmptyHashField), 1431 Int32Constant(String::kEmptyHashField),
1373 MachineRepresentation::kWord32); 1432 MachineRepresentation::kWord32);
1374 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, 1433 bool const new_space = !(flags & kPretenured);
1375 MachineRepresentation::kTagged); 1434 if (new_space) {
1376 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, 1435 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first,
1377 MachineRepresentation::kTagged); 1436 MachineRepresentation::kTagged);
1437 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second,
1438 MachineRepresentation::kTagged);
1439 } else {
1440 StoreObjectField(result, ConsString::kFirstOffset, first);
1441 StoreObjectField(result, ConsString::kSecondOffset, second);
1442 }
1378 return result; 1443 return result;
1379 } 1444 }
1380 1445
1381 Node* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first, 1446 Node* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first,
1382 Node* second) { 1447 Node* second,
1383 Node* result = Allocate(ConsString::kSize); 1448 AllocationFlags flags) {
1449 CSA_ASSERT(TaggedIsSmi(length));
1450 Node* result = Allocate(ConsString::kSize, flags);
1384 Node* map = LoadRoot(Heap::kConsStringMapRootIndex); 1451 Node* map = LoadRoot(Heap::kConsStringMapRootIndex);
1452 DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsStringMapRootIndex));
1385 StoreMapNoWriteBarrier(result, map); 1453 StoreMapNoWriteBarrier(result, map);
1386 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, 1454 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length,
1387 MachineRepresentation::kTagged); 1455 MachineRepresentation::kTagged);
1388 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, 1456 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset,
1389 Int32Constant(String::kEmptyHashField), 1457 Int32Constant(String::kEmptyHashField),
1390 MachineRepresentation::kWord32); 1458 MachineRepresentation::kWord32);
1391 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, 1459 bool const new_space = !(flags & kPretenured);
1392 MachineRepresentation::kTagged); 1460 if (new_space) {
1393 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, 1461 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first,
1394 MachineRepresentation::kTagged); 1462 MachineRepresentation::kTagged);
1463 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second,
1464 MachineRepresentation::kTagged);
1465 } else {
1466 StoreObjectField(result, ConsString::kFirstOffset, first);
1467 StoreObjectField(result, ConsString::kSecondOffset, second);
1468 }
1395 return result; 1469 return result;
1396 } 1470 }
1397 1471
1472 Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left,
1473 Node* right, AllocationFlags flags) {
1474 CSA_ASSERT(TaggedIsSmi(length));
1475 // Added string can be a cons string.
1476 Comment("Allocating ConsString");
1477 Node* left_instance_type = LoadInstanceType(left);
1478 Node* right_instance_type = LoadInstanceType(right);
1479
1480 // Compute intersection and difference of instance types.
1481 Node* anded_instance_types = WordAnd(left_instance_type, right_instance_type);
1482 Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
1483
1484 // We create a one-byte cons string if
1485 // 1. both strings are one-byte, or
1486 // 2. at least one of the strings is two-byte, but happens to contain only
1487 // one-byte characters.
1488 // To do this, we check
1489 // 1. if both strings are one-byte, or if the one-byte data hint is set in
1490 // both strings, or
1491 // 2. if one of the strings has the one-byte data hint set and the other
1492 // string is one-byte.
1493 STATIC_ASSERT(kOneByteStringTag != 0);
1494 STATIC_ASSERT(kOneByteDataHintTag != 0);
1495 Label one_byte_map(this);
1496 Label two_byte_map(this);
1497 Variable result(this, MachineRepresentation::kTagged);
1498 Label done(this, &result);
1499 GotoIf(WordNotEqual(
1500 WordAnd(anded_instance_types,
1501 IntPtrConstant(kStringEncodingMask | kOneByteDataHintTag)),
1502 IntPtrConstant(0)),
1503 &one_byte_map);
1504 Branch(WordNotEqual(WordAnd(xored_instance_types,
1505 IntPtrConstant(kStringEncodingMask |
1506 kOneByteDataHintMask)),
1507 IntPtrConstant(kOneByteStringTag | kOneByteDataHintTag)),
1508 &two_byte_map, &one_byte_map);
1509
1510 Bind(&one_byte_map);
1511 Comment("One-byte ConsString");
1512 result.Bind(AllocateOneByteConsString(length, left, right, flags));
1513 Goto(&done);
1514
1515 Bind(&two_byte_map);
1516 Comment("Two-byte ConsString");
1517 result.Bind(AllocateTwoByteConsString(length, left, right, flags));
1518 Goto(&done);
1519
1520 Bind(&done);
1521
1522 return result.value();
1523 }
1524
1398 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, 1525 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length,
1399 Node* index, Node* input) { 1526 Node* index, Node* input) {
1400 Node* const max_length = 1527 Node* const max_length =
1401 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); 1528 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray));
1402 CSA_ASSERT(SmiLessThanOrEqual(length, max_length)); 1529 CSA_ASSERT(SmiLessThanOrEqual(length, max_length));
1403 1530
1404 // Allocate the JSRegExpResult. 1531 // Allocate the JSRegExpResult.
1405 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove 1532 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove
1406 // unneeded store of elements. 1533 // unneeded store of elements.
1407 Node* const result = Allocate(JSRegExpResult::kSize); 1534 Node* const result = Allocate(JSRegExpResult::kSize);
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1727 Bind(&done); 1854 Bind(&done);
1728 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); 1855 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1);
1729 Comment("] CopyFixedArrayElements"); 1856 Comment("] CopyFixedArrayElements");
1730 } 1857 }
1731 1858
1732 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, 1859 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string,
1733 compiler::Node* to_string, 1860 compiler::Node* to_string,
1734 compiler::Node* from_index, 1861 compiler::Node* from_index,
1735 compiler::Node* to_index, 1862 compiler::Node* to_index,
1736 compiler::Node* character_count, 1863 compiler::Node* character_count,
1737 String::Encoding encoding) { 1864 String::Encoding encoding,
1738 Label out(this); 1865 ParameterMode mode) {
1866 bool one_byte = encoding == String::ONE_BYTE_ENCODING;
1867 Comment(one_byte ? "CopyStringCharacters ONE_BYTE_ENCODING"
1868 : "CopyStringCharacters TWO_BYTE_ENCODING");
1739 1869
1740 // Nothing to do for zero characters. 1870 ElementsKind kind = one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
1871 int header_size = (one_byte ? SeqOneByteString::kHeaderSize
1872 : SeqTwoByteString::kHeaderSize) -
1873 kHeapObjectTag;
1874 Node* from_offset = ElementOffsetFromIndex(from_index, kind, mode);
1875 Node* to_offset = ElementOffsetFromIndex(to_index, kind, mode);
1876 Node* byte_count = ElementOffsetFromIndex(character_count, kind, mode);
1877 Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count);
1741 1878
1742 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::kZero)), &out); 1879 // Prepare the fast loop
1880 MachineType type = one_byte ? MachineType::Uint8() : MachineType::Uint16();
1881 MachineRepresentation rep =
1882 one_byte ? MachineRepresentation::kWord8 : MachineRepresentation::kWord16;
1883 int increment = -(1 << ElementsKindToShiftSize(kind));
1743 1884
1744 // Calculate offsets into the strings. 1885 Node* to_string_adjusted = IntPtrAddFoldConstants(
1886 to_string, IntPtrSubFoldConstants(to_offset, from_offset));
1887 limit_offset =
1888 IntPtrAddFoldConstants(limit_offset, IntPtrConstant(header_size));
1889 from_offset =
1890 IntPtrAddFoldConstants(from_offset, IntPtrConstant(header_size));
1745 1891
1746 Node* from_offset; 1892 BuildFastLoop(MachineType::PointerRepresentation(), limit_offset, from_offset,
1747 Node* limit_offset; 1893 [from_string, to_string_adjusted, type, rep](
1748 Node* to_offset; 1894 CodeStubAssembler* assembler, Node* offset) {
1749 1895 Node* value = assembler->Load(type, from_string, offset);
1750 { 1896 assembler->StoreNoWriteBarrier(rep, to_string_adjusted,
1751 Node* byte_count = SmiUntag(character_count); 1897 offset, value);
1752 Node* from_byte_index = SmiUntag(from_index); 1898 },
1753 Node* to_byte_index = SmiUntag(to_index); 1899 increment);
1754 if (encoding == String::ONE_BYTE_ENCODING) {
1755 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag;
1756 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
1757 limit_offset = IntPtrAdd(from_offset, byte_count);
1758 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
1759 } else {
1760 STATIC_ASSERT(2 == sizeof(uc16));
1761 byte_count = WordShl(byte_count, 1);
1762 from_byte_index = WordShl(from_byte_index, 1);
1763 to_byte_index = WordShl(to_byte_index, 1);
1764
1765 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag;
1766 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
1767 limit_offset = IntPtrAdd(from_offset, byte_count);
1768 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
1769 }
1770 }
1771
1772 Variable var_from_offset(this, MachineType::PointerRepresentation());
1773 Variable var_to_offset(this, MachineType::PointerRepresentation());
1774
1775 var_from_offset.Bind(from_offset);
1776 var_to_offset.Bind(to_offset);
1777
1778 Variable* vars[] = {&var_from_offset, &var_to_offset};
1779 Label decrement(this, 2, vars);
1780
1781 Label loop(this, 2, vars);
1782 Goto(&loop);
1783 Bind(&loop);
1784 {
1785 from_offset = var_from_offset.value();
1786 to_offset = var_to_offset.value();
1787
1788 // TODO(jgruber): We could make this faster through larger copy unit sizes.
1789 Node* value = Load(MachineType::Uint8(), from_string, from_offset);
1790 StoreNoWriteBarrier(MachineRepresentation::kWord8, to_string, to_offset,
1791 value);
1792
1793 Node* new_from_offset = IntPtrAdd(from_offset, IntPtrConstant(1));
1794 var_from_offset.Bind(new_from_offset);
1795 var_to_offset.Bind(IntPtrAdd(to_offset, IntPtrConstant(1)));
1796
1797 Branch(WordNotEqual(new_from_offset, limit_offset), &loop, &out);
1798 }
1799
1800 Bind(&out);
1801 } 1900 }
1802 1901
1803 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, 1902 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
1804 Node* offset, 1903 Node* offset,
1805 ElementsKind from_kind, 1904 ElementsKind from_kind,
1806 ElementsKind to_kind, 1905 ElementsKind to_kind,
1807 Label* if_hole) { 1906 Label* if_hole) {
1808 if (IsFastDoubleElementsKind(from_kind)) { 1907 if (IsFastDoubleElementsKind(from_kind)) {
1809 Node* value = 1908 Node* value =
1810 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); 1909 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64());
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
2569 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, 2668 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type,
2570 a->Int32Constant(kStringEncodingMask)), 2669 a->Int32Constant(kStringEncodingMask)),
2571 a->Int32Constant(0)), 2670 a->Int32Constant(0)),
2572 &two_byte_sequential); 2671 &two_byte_sequential);
2573 2672
2574 // The subject string is a sequential one-byte string. 2673 // The subject string is a sequential one-byte string.
2575 { 2674 {
2576 Node* result = 2675 Node* result =
2577 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); 2676 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
2578 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 2677 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
2579 String::ONE_BYTE_ENCODING); 2678 String::ONE_BYTE_ENCODING,
2679 CodeStubAssembler::SMI_PARAMETERS);
2580 var_result.Bind(result); 2680 var_result.Bind(result);
2581 2681
2582 a->Goto(&end); 2682 a->Goto(&end);
2583 } 2683 }
2584 2684
2585 // The subject string is a sequential two-byte string. 2685 // The subject string is a sequential two-byte string.
2586 a->Bind(&two_byte_sequential); 2686 a->Bind(&two_byte_sequential);
2587 { 2687 {
2588 Node* result = 2688 Node* result =
2589 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); 2689 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count));
2590 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 2690 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
2591 String::TWO_BYTE_ENCODING); 2691 String::TWO_BYTE_ENCODING,
2692 CodeStubAssembler::SMI_PARAMETERS);
2592 var_result.Bind(result); 2693 var_result.Bind(result);
2593 2694
2594 a->Goto(&end); 2695 a->Goto(&end);
2595 } 2696 }
2596 2697
2597 a->Bind(&end); 2698 a->Bind(&end);
2598 return var_result.value(); 2699 return var_result.value();
2599 } 2700 }
2600 2701
2601 } // namespace 2702 } // namespace
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 { 2916 {
2816 var_result.Bind( 2917 var_result.Bind(
2817 CallRuntime(Runtime::kSubString, context, string, from, to)); 2918 CallRuntime(Runtime::kSubString, context, string, from, to));
2818 Goto(&end); 2919 Goto(&end);
2819 } 2920 }
2820 2921
2821 Bind(&end); 2922 Bind(&end);
2822 return var_result.value(); 2923 return var_result.value();
2823 } 2924 }
2824 2925
2825 Node* CodeStubAssembler::StringConcat(Node* context, Node* first, 2926 Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
2826 Node* second) { 2927 AllocationFlags flags) {
2827 Variable var_result(this, MachineRepresentation::kTagged); 2928 Label check_right(this);
2929 Label runtime(this, Label::kDeferred);
2930 Label cons(this);
2931 Label non_cons(this);
2932 Variable result(this, MachineRepresentation::kTagged);
2933 Label done(this, &result);
2934 Label done_native(this, &result);
2935 Counters* counters = isolate()->counters();
2828 2936
2829 Label out(this), runtime(this, Label::kDeferred); 2937 Node* left_length = LoadStringLength(left);
2938 GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right);
2939 result.Bind(right);
2940 Goto(&done_native);
2830 2941
2831 // TODO(jgruber): Handle indirect, external, and two-byte strings. 2942 Bind(&check_right);
2943 Node* right_length = LoadStringLength(right);
2944 GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons);
2945 result.Bind(left);
2946 Goto(&done_native);
2832 2947
2833 Node* const one_byte_seq_mask = Int32Constant( 2948 Bind(&cons);
2834 kIsIndirectStringMask | kExternalStringTag | kStringEncodingMask); 2949 CSA_ASSERT(TaggedIsSmi(left_length));
2835 Node* const expected_masked = Int32Constant(kOneByteStringTag); 2950 CSA_ASSERT(TaggedIsSmi(right_length));
2951 Node* new_length = SmiAdd(left_length, right_length);
2952 GotoIf(UintPtrGreaterThanOrEqual(
2953 new_length, SmiConstant(Smi::FromInt(String::kMaxLength))),
2954 &runtime);
2836 2955
2837 Node* const first_instance_type = LoadInstanceType(first); 2956 GotoIf(IntPtrLessThan(new_length,
2838 GotoUnless(Word32Equal(Word32And(first_instance_type, one_byte_seq_mask), 2957 SmiConstant(Smi::FromInt(ConsString::kMinLength))),
2839 expected_masked), 2958 &non_cons);
2840 &runtime);
2841 2959
2842 Node* const second_instance_type = LoadInstanceType(second); 2960 result.Bind(NewConsString(context, new_length, left, right, flags));
2843 GotoUnless(Word32Equal(Word32And(second_instance_type, one_byte_seq_mask), 2961 Goto(&done_native);
2844 expected_masked),
2845 &runtime);
2846 2962
2847 Node* const smi_zero = SmiConstant(Smi::kZero); 2963 Bind(&non_cons);
2848 Node* const first_length = LoadStringLength(first);
2849 Node* const second_length = LoadStringLength(second);
2850 Node* const length = SmiAdd(first_length, second_length);
2851 2964
2852 Label if_makeseqstring(this), if_makeconsstring(this); 2965 Comment("Full string concatenate");
2853 Node* const min_cons_length = 2966 Node* left_instance_type = LoadInstanceType(left);
2854 SmiConstant(Smi::FromInt(ConsString::kMinLength)); 2967 Node* right_instance_type = LoadInstanceType(right);
2855 Branch(SmiLessThan(length, min_cons_length), &if_makeseqstring, 2968 // Compute intersection and difference of instance types.
2856 &if_makeconsstring);
2857 2969
2858 Bind(&if_makeseqstring); 2970 Node* ored_instance_types = WordOr(left_instance_type, right_instance_type);
2971 Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
2972
2973 // Check if both strings have the same encoding and both are sequential.
2974 GotoIf(WordNotEqual(
2975 WordAnd(xored_instance_types, IntPtrConstant(kStringEncodingMask)),
2976 IntPtrConstant(0)),
2977 &runtime);
2978 GotoIf(WordNotEqual(WordAnd(ored_instance_types,
2979 IntPtrConstant(kStringRepresentationMask)),
2980 IntPtrConstant(0)),
2981 &runtime);
2982
2983 Label two_byte(this);
2984 GotoIf(WordEqual(
2985 WordAnd(ored_instance_types, IntPtrConstant(kStringEncodingMask)),
2986 IntPtrConstant(kTwoByteStringTag)),
2987 &two_byte);
2988 // One-byte sequential string case
2989 Node* new_string =
2990 AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS);
2991 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
2992 SmiConstant(Smi::kZero), left_length,
2993 String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
2994 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length,
2995 right_length, String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
2996 result.Bind(new_string);
2997 Goto(&done_native);
2998
2999 Bind(&two_byte);
2859 { 3000 {
2860 Node* result = AllocateSeqOneByteString(context, SmiToWord(length)); 3001 // Two-byte sequential string case
2861 3002 new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
2862 CopyStringCharacters(first, result, smi_zero, smi_zero, first_length, 3003 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
2863 String::ONE_BYTE_ENCODING); 3004 SmiConstant(Smi::kZero), left_length,
2864 CopyStringCharacters(second, result, smi_zero, first_length, second_length, 3005 String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
2865 String::ONE_BYTE_ENCODING); 3006 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero),
2866 3007 left_length, right_length, String::TWO_BYTE_ENCODING,
2867 var_result.Bind(result); 3008 SMI_PARAMETERS);
2868 Goto(&out); 3009 result.Bind(new_string);
2869 } 3010 Goto(&done_native);
2870
2871 Bind(&if_makeconsstring);
2872 {
2873 Node* result = AllocateOneByteConsString(length, first, second);
2874 var_result.Bind(result);
2875 Goto(&out);
2876 } 3011 }
2877 3012
2878 Bind(&runtime); 3013 Bind(&runtime);
2879 { 3014 {
2880 Node* const result = 3015 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right));
2881 CallRuntime(Runtime::kStringAdd, context, first, second); 3016 Goto(&done);
2882 var_result.Bind(result);
2883 Goto(&out);
2884 } 3017 }
2885 3018
2886 Bind(&out); 3019 Bind(&done_native);
2887 return var_result.value(); 3020 {
3021 IncrementCounter(counters->string_add_native(), 1);
3022 Goto(&done);
3023 }
3024
3025 Bind(&done);
3026 return result.value();
2888 } 3027 }
2889 3028
2890 Node* CodeStubAssembler::StringIndexOfChar(Node* context, Node* string, 3029 Node* CodeStubAssembler::StringIndexOfChar(Node* context, Node* string,
2891 Node* needle_char, Node* from) { 3030 Node* needle_char, Node* from) {
2892 Variable var_result(this, MachineRepresentation::kTagged); 3031 Variable var_result(this, MachineRepresentation::kTagged);
2893 3032
2894 Label out(this), runtime(this, Label::kDeferred); 3033 Label out(this), runtime(this, Label::kDeferred);
2895 3034
2896 // Let runtime handle non-one-byte {needle_char}. 3035 // Let runtime handle non-one-byte {needle_char}.
2897 3036
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
3279 { 3418 {
3280 var_result.Bind(NonNumberToNumber(context, input)); 3419 var_result.Bind(NonNumberToNumber(context, input));
3281 Goto(&end); 3420 Goto(&end);
3282 } 3421 }
3283 } 3422 }
3284 3423
3285 Bind(&end); 3424 Bind(&end);
3286 return var_result.value(); 3425 return var_result.value();
3287 } 3426 }
3288 3427
3428 Node* CodeStubAssembler::ToString(Node* context, Node* input) {
3429 Label is_number(this);
3430 Label runtime(this, Label::kDeferred);
3431 Variable result(this, MachineRepresentation::kTagged);
3432 Label done(this, &result);
3433
3434 GotoIf(TaggedIsSmi(input), &is_number);
3435
3436 Node* input_map = LoadMap(input);
3437 Node* input_instance_type = LoadMapInstanceType(input_map);
3438
3439 result.Bind(input);
3440 GotoIf(IsStringInstanceType(input_instance_type), &done);
3441
3442 Label not_heap_number(this);
3443 Branch(WordNotEqual(input_map, HeapNumberMapConstant()), &not_heap_number,
3444 &is_number);
3445
3446 Bind(&is_number);
3447 result.Bind(NumberToString(context, input));
3448 Goto(&done);
3449
3450 Bind(&not_heap_number);
3451 {
3452 GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)),
3453 &runtime);
3454 result.Bind(LoadObjectField(input, Oddball::kToStringOffset));
3455 Goto(&done);
3456 }
3457
3458 Bind(&runtime);
3459 {
3460 result.Bind(CallRuntime(Runtime::kToString, context, input));
3461 Goto(&done);
3462 }
3463
3464 Bind(&done);
3465 return result.value();
3466 }
3467
3468 Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
3469 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3470 Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
3471 Variable result(this, MachineRepresentation::kTagged);
3472 Label done(this, &result);
3473
3474 GotoIf(TaggedIsSmi(input), &if_isnotreceiver);
3475
3476 Node* map = LoadMap(input);
3477 Node* instance_type = LoadMapInstanceType(map);
3478 Branch(IsJSReceiverInstanceType(instance_type), &if_isreceiver,
3479 &if_isnotreceiver);
3480
3481 Bind(&if_isreceiver);
3482 {
3483 // Convert {input} to a primitive first passing Number hint.
3484 Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
3485 result.Bind(CallStub(callable, context, input));
3486 Goto(&done);
3487 }
3488
3489 Bind(&if_isnotreceiver);
3490 {
3491 result.Bind(input);
3492 Goto(&done);
3493 }
3494
3495 Bind(&done);
3496 return result.value();
3497 }
3498
3289 Node* CodeStubAssembler::ToInteger(Node* context, Node* input, 3499 Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
3290 ToIntegerTruncationMode mode) { 3500 ToIntegerTruncationMode mode) {
3291 // We might need to loop once for ToNumber conversion. 3501 // We might need to loop once for ToNumber conversion.
3292 Variable var_arg(this, MachineRepresentation::kTagged); 3502 Variable var_arg(this, MachineRepresentation::kTagged);
3293 Label loop(this, &var_arg), out(this); 3503 Label loop(this, &var_arg), out(this);
3294 var_arg.Bind(input); 3504 var_arg.Bind(input);
3295 Goto(&loop); 3505 Goto(&loop);
3296 Bind(&loop); 3506 Bind(&loop);
3297 { 3507 {
3298 // Shared entry points. 3508 // Shared entry points.
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after
4325 ElementsKind kind, 4535 ElementsKind kind,
4326 ParameterMode mode, 4536 ParameterMode mode,
4327 int base_size) { 4537 int base_size) {
4328 int element_size_shift = ElementsKindToShiftSize(kind); 4538 int element_size_shift = ElementsKindToShiftSize(kind);
4329 int element_size = 1 << element_size_shift; 4539 int element_size = 1 << element_size_shift;
4330 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; 4540 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
4331 intptr_t index = 0; 4541 intptr_t index = 0;
4332 bool constant_index = false; 4542 bool constant_index = false;
4333 if (mode == SMI_PARAMETERS) { 4543 if (mode == SMI_PARAMETERS) {
4334 element_size_shift -= kSmiShiftBits; 4544 element_size_shift -= kSmiShiftBits;
4335 constant_index = ToIntPtrConstant(index_node, index); 4545 Smi* smi_index;
4336 index = index >> kSmiShiftBits; 4546 constant_index = ToSmiConstant(index_node, smi_index);
4547 if (constant_index) index = smi_index->value();
4337 index_node = BitcastTaggedToWord(index_node); 4548 index_node = BitcastTaggedToWord(index_node);
4338 } else if (mode == INTEGER_PARAMETERS) { 4549 } else if (mode == INTEGER_PARAMETERS) {
4339 int32_t temp = 0; 4550 int32_t temp = 0;
4340 constant_index = ToInt32Constant(index_node, temp); 4551 constant_index = ToInt32Constant(index_node, temp);
4341 index = static_cast<intptr_t>(temp); 4552 index = static_cast<intptr_t>(temp);
4342 } else { 4553 } else {
4343 DCHECK(mode == INTPTR_PARAMETERS); 4554 DCHECK(mode == INTPTR_PARAMETERS);
4344 constant_index = ToIntPtrConstant(index_node, index); 4555 constant_index = ToIntPtrConstant(index_node, index);
4345 } 4556 }
4346 if (constant_index) { 4557 if (constant_index) {
4347 return IntPtrConstant(base_size + element_size * index); 4558 return IntPtrConstant(base_size + element_size * index);
4348 } 4559 }
4349 if (Is64() && mode == INTEGER_PARAMETERS) { 4560 if (Is64() && mode == INTEGER_PARAMETERS) {
4350 index_node = ChangeInt32ToInt64(index_node); 4561 index_node = ChangeInt32ToInt64(index_node);
4351 } 4562 }
4352 if (base_size == 0) { 4563
4353 return (element_size_shift >= 0) 4564 Node* shifted_index =
4354 ? WordShl(index_node, IntPtrConstant(element_size_shift)) 4565 (element_size_shift == 0)
4355 : WordShr(index_node, IntPtrConstant(-element_size_shift)); 4566 ? index_node
4356 } 4567 : ((element_size_shift > 0)
4357 return IntPtrAdd( 4568 ? WordShl(index_node, IntPtrConstant(element_size_shift))
4358 IntPtrConstant(base_size), 4569 : WordShr(index_node, IntPtrConstant(-element_size_shift)));
4359 (element_size_shift >= 0) 4570 return IntPtrAddFoldConstants(IntPtrConstant(base_size), shifted_index);
4360 ? WordShl(index_node, IntPtrConstant(element_size_shift))
4361 : WordShr(index_node, IntPtrConstant(-element_size_shift)));
4362 } 4571 }
4363 4572
4364 compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() { 4573 compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() {
4365 Node* function = 4574 Node* function =
4366 LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset); 4575 LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset);
4367 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset); 4576 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset);
4368 return LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset); 4577 return LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset);
4369 } 4578 }
4370 4579
4371 void CodeStubAssembler::UpdateFeedback(compiler::Node* feedback, 4580 void CodeStubAssembler::UpdateFeedback(compiler::Node* feedback,
(...skipping 3113 matching lines...) Expand 10 before | Expand all | Expand 10 after
7485 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); 7694 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable));
7486 Goto(&end); 7695 Goto(&end);
7487 } 7696 }
7488 7697
7489 Bind(&end); 7698 Bind(&end);
7490 return result.value(); 7699 return result.value();
7491 } 7700 }
7492 7701
7493 } // namespace internal 7702 } // namespace internal
7494 } // namespace v8 7703 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698