| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 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 Loading... |
| 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, ¬_ok); |
| 41 Bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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()), ¬_heap_number, |
| 3444 &is_number); |
| 3445 |
| 3446 Bind(&is_number); |
| 3447 result.Bind(NumberToString(context, input)); |
| 3448 Goto(&done); |
| 3449 |
| 3450 Bind(¬_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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |