OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 } else { | 1153 } else { |
1154 EmitCmpI(left, right); | 1154 EmitCmpI(left, right); |
1155 } | 1155 } |
1156 | 1156 |
1157 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1157 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1158 EmitBranch(true_block, false_block, cc); | 1158 EmitBranch(true_block, false_block, cc); |
1159 } | 1159 } |
1160 | 1160 |
1161 | 1161 |
1162 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1162 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
1163 Abort("Unimplemented: %s", "DoCmpJSObjectEq"); | 1163 Register left = ToRegister(instr->InputAt(0)); |
| 1164 Register right = ToRegister(instr->InputAt(1)); |
| 1165 Register result = ToRegister(instr->result()); |
| 1166 |
| 1167 NearLabel different, done; |
| 1168 __ cmpq(left, right); |
| 1169 __ j(not_equal, &different); |
| 1170 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1171 __ jmp(&done); |
| 1172 __ bind(&different); |
| 1173 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1174 __ bind(&done); |
1164 } | 1175 } |
1165 | 1176 |
1166 | 1177 |
1167 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1178 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
1168 Register left = ToRegister(instr->InputAt(0)); | 1179 Register left = ToRegister(instr->InputAt(0)); |
1169 Register right = ToRegister(instr->InputAt(1)); | 1180 Register right = ToRegister(instr->InputAt(1)); |
1170 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1181 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1171 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1182 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1172 | 1183 |
1173 __ cmpq(left, right); | 1184 __ cmpq(left, right); |
1174 EmitBranch(true_block, false_block, equal); | 1185 EmitBranch(true_block, false_block, equal); |
1175 } | 1186 } |
1176 | 1187 |
1177 | 1188 |
1178 void LCodeGen::DoIsNull(LIsNull* instr) { | 1189 void LCodeGen::DoIsNull(LIsNull* instr) { |
1179 Abort("Unimplemented: %s", "DoIsNull"); | 1190 Register reg = ToRegister(instr->InputAt(0)); |
| 1191 Register result = ToRegister(instr->result()); |
| 1192 |
| 1193 // If the expression is known to be a smi, then it's |
| 1194 // definitely not null. Materialize false. |
| 1195 // Consider adding other type and representation tests too. |
| 1196 if (instr->hydrogen()->value()->type().IsSmi()) { |
| 1197 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1198 return; |
| 1199 } |
| 1200 |
| 1201 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1202 if (instr->is_strict()) { |
| 1203 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
| 1204 NearLabel load; |
| 1205 __ j(equal, &load); |
| 1206 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); |
| 1207 __ bind(&load); |
| 1208 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); |
| 1209 } else { |
| 1210 NearLabel true_value, false_value, done; |
| 1211 __ j(equal, &true_value); |
| 1212 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1213 __ j(equal, &true_value); |
| 1214 __ JumpIfSmi(reg, &false_value); |
| 1215 // Check for undetectable objects by looking in the bit field in |
| 1216 // the map. The object has already been smi checked. |
| 1217 Register scratch = result; |
| 1218 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1219 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
| 1220 Immediate(1 << Map::kIsUndetectable)); |
| 1221 __ j(not_zero, &true_value); |
| 1222 __ bind(&false_value); |
| 1223 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1224 __ jmp(&done); |
| 1225 __ bind(&true_value); |
| 1226 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1227 __ bind(&done); |
| 1228 } |
1180 } | 1229 } |
1181 | 1230 |
1182 | 1231 |
1183 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1232 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1184 Register reg = ToRegister(instr->InputAt(0)); | 1233 Register reg = ToRegister(instr->InputAt(0)); |
1185 | 1234 |
1186 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1235 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1187 | 1236 |
1188 if (instr->hydrogen()->representation().IsSpecialization() || | 1237 if (instr->hydrogen()->representation().IsSpecialization() || |
1189 instr->hydrogen()->type().IsSmi()) { | 1238 instr->hydrogen()->type().IsSmi()) { |
(...skipping 21 matching lines...) Expand all Loading... |
1211 Register scratch = ToRegister(instr->TempAt(0)); | 1260 Register scratch = ToRegister(instr->TempAt(0)); |
1212 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1261 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1213 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1262 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
1214 Immediate(1 << Map::kIsUndetectable)); | 1263 Immediate(1 << Map::kIsUndetectable)); |
1215 EmitBranch(true_block, false_block, not_zero); | 1264 EmitBranch(true_block, false_block, not_zero); |
1216 } | 1265 } |
1217 } | 1266 } |
1218 | 1267 |
1219 | 1268 |
1220 Condition LCodeGen::EmitIsObject(Register input, | 1269 Condition LCodeGen::EmitIsObject(Register input, |
1221 Register temp1, | |
1222 Register temp2, | |
1223 Label* is_not_object, | 1270 Label* is_not_object, |
1224 Label* is_object) { | 1271 Label* is_object) { |
1225 ASSERT(!input.is(temp1)); | 1272 ASSERT(!input.is(kScratchRegister)); |
1226 ASSERT(!input.is(temp2)); | |
1227 ASSERT(!temp1.is(temp2)); | |
1228 | 1273 |
1229 __ JumpIfSmi(input, is_not_object); | 1274 __ JumpIfSmi(input, is_not_object); |
1230 | 1275 |
1231 __ Cmp(input, Factory::null_value()); | 1276 __ CompareRoot(input, Heap::kNullValueRootIndex); |
1232 __ j(equal, is_object); | 1277 __ j(equal, is_object); |
1233 | 1278 |
1234 __ movq(temp1, FieldOperand(input, HeapObject::kMapOffset)); | 1279 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
1235 // Undetectable objects behave like undefined. | 1280 // Undetectable objects behave like undefined. |
1236 __ testb(FieldOperand(temp1, Map::kBitFieldOffset), | 1281 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), |
1237 Immediate(1 << Map::kIsUndetectable)); | 1282 Immediate(1 << Map::kIsUndetectable)); |
1238 __ j(not_zero, is_not_object); | 1283 __ j(not_zero, is_not_object); |
1239 | 1284 |
1240 __ movzxbl(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1285 __ movzxbl(kScratchRegister, |
1241 __ cmpb(temp2, Immediate(FIRST_JS_OBJECT_TYPE)); | 1286 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
| 1287 __ cmpb(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE)); |
1242 __ j(below, is_not_object); | 1288 __ j(below, is_not_object); |
1243 __ cmpb(temp2, Immediate(LAST_JS_OBJECT_TYPE)); | 1289 __ cmpb(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE)); |
1244 return below_equal; | 1290 return below_equal; |
1245 } | 1291 } |
1246 | 1292 |
1247 | 1293 |
1248 void LCodeGen::DoIsObject(LIsObject* instr) { | 1294 void LCodeGen::DoIsObject(LIsObject* instr) { |
1249 Abort("Unimplemented: %s", "DoIsObject"); | 1295 Register reg = ToRegister(instr->InputAt(0)); |
| 1296 Register result = ToRegister(instr->result()); |
| 1297 Label is_false, is_true, done; |
| 1298 |
| 1299 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); |
| 1300 __ j(true_cond, &is_true); |
| 1301 |
| 1302 __ bind(&is_false); |
| 1303 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1304 __ jmp(&done); |
| 1305 |
| 1306 __ bind(&is_true); |
| 1307 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1308 |
| 1309 __ bind(&done); |
1250 } | 1310 } |
1251 | 1311 |
1252 | 1312 |
1253 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1313 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1254 Register reg = ToRegister(instr->InputAt(0)); | 1314 Register reg = ToRegister(instr->InputAt(0)); |
1255 Register temp = ToRegister(instr->TempAt(0)); | |
1256 Register temp2 = ToRegister(instr->TempAt(1)); | |
1257 | 1315 |
1258 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1316 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1259 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1317 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1260 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1318 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1261 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1319 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1262 | 1320 |
1263 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1321 Condition true_cond = EmitIsObject(reg, false_label, true_label); |
1264 | 1322 |
1265 EmitBranch(true_block, false_block, true_cond); | 1323 EmitBranch(true_block, false_block, true_cond); |
1266 } | 1324 } |
1267 | 1325 |
1268 | 1326 |
1269 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1327 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
1270 Abort("Unimplemented: %s", "DoIsSmi"); | 1328 LOperand* input_operand = instr->InputAt(0); |
| 1329 Register result = ToRegister(instr->result()); |
| 1330 if (input_operand->IsRegister()) { |
| 1331 Register input = ToRegister(input_operand); |
| 1332 __ CheckSmiToIndicator(result, input); |
| 1333 } else { |
| 1334 Operand input = ToOperand(instr->InputAt(0)); |
| 1335 __ CheckSmiToIndicator(result, input); |
| 1336 } |
| 1337 // result is zero if input is a smi, and one otherwise. |
| 1338 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); |
| 1339 __ movq(result, Operand(kRootRegister, result, times_pointer_size, |
| 1340 Heap::kTrueValueRootIndex * kPointerSize)); |
1271 } | 1341 } |
1272 | 1342 |
1273 | 1343 |
1274 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1344 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1275 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1345 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1276 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1346 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1277 | 1347 |
1278 Condition is_smi; | 1348 Condition is_smi; |
1279 if (instr->InputAt(0)->IsRegister()) { | 1349 if (instr->InputAt(0)->IsRegister()) { |
1280 Register input = ToRegister(instr->InputAt(0)); | 1350 Register input = ToRegister(instr->InputAt(0)); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 // classes and it doesn't have to because you can't access it with natives | 1463 // classes and it doesn't have to because you can't access it with natives |
1394 // syntax. Since both sides are symbols it is sufficient to use an identity | 1464 // syntax. Since both sides are symbols it is sufficient to use an identity |
1395 // comparison. | 1465 // comparison. |
1396 ASSERT(class_name->IsSymbol()); | 1466 ASSERT(class_name->IsSymbol()); |
1397 __ Cmp(temp, class_name); | 1467 __ Cmp(temp, class_name); |
1398 // End with the answer in the z flag. | 1468 // End with the answer in the z flag. |
1399 } | 1469 } |
1400 | 1470 |
1401 | 1471 |
1402 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1472 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1403 Abort("Unimplemented: %s", "DoClassOfTest"); | 1473 Register input = ToRegister(instr->InputAt(0)); |
| 1474 Register result = ToRegister(instr->result()); |
| 1475 ASSERT(input.is(result)); |
| 1476 Register temp = ToRegister(instr->TempAt(0)); |
| 1477 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1478 NearLabel done; |
| 1479 Label is_true, is_false; |
| 1480 |
| 1481 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); |
| 1482 |
| 1483 __ j(not_equal, &is_false); |
| 1484 |
| 1485 __ bind(&is_true); |
| 1486 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1487 __ jmp(&done); |
| 1488 |
| 1489 __ bind(&is_false); |
| 1490 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1491 __ bind(&done); |
1404 } | 1492 } |
1405 | 1493 |
1406 | 1494 |
1407 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1495 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1408 Register input = ToRegister(instr->InputAt(0)); | 1496 Register input = ToRegister(instr->InputAt(0)); |
1409 Register temp = ToRegister(instr->TempAt(0)); | 1497 Register temp = ToRegister(instr->TempAt(0)); |
1410 Handle<String> class_name = instr->hydrogen()->class_name(); | 1498 Handle<String> class_name = instr->hydrogen()->class_name(); |
1411 | 1499 |
1412 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1500 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1413 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1501 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1414 | 1502 |
1415 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1416 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1417 | 1505 |
1418 EmitClassOfTest(true_label, false_label, class_name, input, temp); | 1506 EmitClassOfTest(true_label, false_label, class_name, input, temp); |
1419 | 1507 |
1420 EmitBranch(true_block, false_block, equal); | 1508 EmitBranch(true_block, false_block, equal); |
1421 } | 1509 } |
1422 | 1510 |
1423 | 1511 |
1424 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1512 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1425 Abort("Unimplemented: %s", "DoCmpMapAndBranch"); | 1513 Register reg = ToRegister(instr->InputAt(0)); |
| 1514 int true_block = instr->true_block_id(); |
| 1515 int false_block = instr->false_block_id(); |
| 1516 |
| 1517 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1518 EmitBranch(true_block, false_block, equal); |
1426 } | 1519 } |
1427 | 1520 |
1428 | 1521 |
1429 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1522 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1430 Abort("Unimplemented: %s", "DoInstanceOf"); | 1523 Abort("Unimplemented: %s", "DoInstanceOf"); |
1431 } | 1524 } |
1432 | 1525 |
1433 | 1526 |
1434 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1527 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
1435 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1528 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1707 Abort("Unimplemented: %s", "DoStoreKeyedFastElement"); | 1800 Abort("Unimplemented: %s", "DoStoreKeyedFastElement"); |
1708 } | 1801 } |
1709 | 1802 |
1710 | 1803 |
1711 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 1804 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
1712 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); | 1805 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); |
1713 } | 1806 } |
1714 | 1807 |
1715 | 1808 |
1716 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 1809 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
1717 Abort("Unimplemented: %s", "DoInteger32ToDouble"); | 1810 LOperand* input = instr->InputAt(0); |
| 1811 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 1812 LOperand* output = instr->result(); |
| 1813 ASSERT(output->IsDoubleRegister()); |
| 1814 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); |
1718 } | 1815 } |
1719 | 1816 |
1720 | 1817 |
1721 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 1818 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
1722 Abort("Unimplemented: %s", "DoNumberTagI"); | 1819 LOperand* input = instr->InputAt(0); |
1723 } | 1820 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 1821 Register reg = ToRegister(input); |
1724 | 1822 |
1725 | 1823 __ Integer32ToSmi(reg, reg); |
1726 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | |
1727 Abort("Unimplemented: %s", "DoDeferredNumberTagI"); | |
1728 } | 1824 } |
1729 | 1825 |
1730 | 1826 |
1731 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 1827 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
1732 Abort("Unimplemented: %s", "DoNumberTagD"); | 1828 class DeferredNumberTagD: public LDeferredCode { |
| 1829 public: |
| 1830 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 1831 : LDeferredCode(codegen), instr_(instr) { } |
| 1832 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 1833 private: |
| 1834 LNumberTagD* instr_; |
| 1835 }; |
| 1836 |
| 1837 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 1838 Register reg = ToRegister(instr->result()); |
| 1839 Register tmp = ToRegister(instr->TempAt(0)); |
| 1840 |
| 1841 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
| 1842 if (FLAG_inline_new) { |
| 1843 __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
| 1844 } else { |
| 1845 __ jmp(deferred->entry()); |
| 1846 } |
| 1847 __ bind(deferred->exit()); |
| 1848 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
1733 } | 1849 } |
1734 | 1850 |
1735 | 1851 |
1736 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 1852 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
1737 Abort("Unimplemented: %s", "DoDeferredNumberTagD"); | 1853 // TODO(3095996): Get rid of this. For now, we need to make the |
| 1854 // result register contain a valid pointer because it is already |
| 1855 // contained in the register pointer map. |
| 1856 Register reg = ToRegister(instr->result()); |
| 1857 __ Move(reg, Smi::FromInt(0)); |
| 1858 |
| 1859 __ PushSafepointRegisters(); |
| 1860 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 1861 RecordSafepointWithRegisters( |
| 1862 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 1863 // Ensure that value in rax survives popping registers. |
| 1864 __ movq(kScratchRegister, rax); |
| 1865 __ PopSafepointRegisters(); |
| 1866 __ movq(reg, kScratchRegister); |
1738 } | 1867 } |
1739 | 1868 |
1740 | 1869 |
1741 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 1870 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
1742 Abort("Unimplemented: %s", "DoSmiTag"); | 1871 Abort("Unimplemented: %s", "DoSmiTag"); |
1743 } | 1872 } |
1744 | 1873 |
1745 | 1874 |
1746 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 1875 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
1747 Abort("Unimplemented: %s", "DoSmiUntag"); | 1876 Abort("Unimplemented: %s", "DoSmiUntag"); |
1748 } | 1877 } |
1749 | 1878 |
1750 | 1879 |
1751 void LCodeGen::EmitNumberUntagD(Register input_reg, | 1880 void LCodeGen::EmitNumberUntagD(Register input_reg, |
1752 XMMRegister result_reg, | 1881 XMMRegister result_reg, |
1753 LEnvironment* env) { | 1882 LEnvironment* env) { |
1754 Abort("Unimplemented: %s", "EmitNumberUntagD"); | 1883 NearLabel load_smi, heap_number, done; |
| 1884 |
| 1885 // Smi check. |
| 1886 __ JumpIfSmi(input_reg, &load_smi); |
| 1887 |
| 1888 // Heap number map check. |
| 1889 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 1890 Heap::kHeapNumberMapRootIndex); |
| 1891 __ j(equal, &heap_number); |
| 1892 |
| 1893 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 1894 DeoptimizeIf(not_equal, env); |
| 1895 |
| 1896 // Convert undefined to NaN. Compute NaN as 0/0. |
| 1897 __ xorpd(result_reg, result_reg); |
| 1898 __ divsd(result_reg, result_reg); |
| 1899 __ jmp(&done); |
| 1900 |
| 1901 // Heap number to XMM conversion. |
| 1902 __ bind(&heap_number); |
| 1903 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 1904 __ jmp(&done); |
| 1905 |
| 1906 // Smi to XMM conversion |
| 1907 __ bind(&load_smi); |
| 1908 __ SmiToInteger32(kScratchRegister, input_reg); // Untag smi first. |
| 1909 __ cvtlsi2sd(result_reg, kScratchRegister); |
| 1910 __ bind(&done); |
1755 } | 1911 } |
1756 | 1912 |
1757 | 1913 |
1758 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 1914 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
1759 Abort("Unimplemented: %s", "DoDeferredTaggedToI"); | 1915 Abort("Unimplemented: %s", "DoDeferredTaggedToI"); |
1760 } | 1916 } |
1761 | 1917 |
1762 | 1918 |
1763 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 1919 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
1764 Abort("Unimplemented: %s", "DoTaggedToI"); | 1920 Abort("Unimplemented: %s", "DoTaggedToI"); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 | 2102 |
1947 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2103 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
1948 Abort("Unimplemented: %s", "DoOsrEntry"); | 2104 Abort("Unimplemented: %s", "DoOsrEntry"); |
1949 } | 2105 } |
1950 | 2106 |
1951 #undef __ | 2107 #undef __ |
1952 | 2108 |
1953 } } // namespace v8::internal | 2109 } } // namespace v8::internal |
1954 | 2110 |
1955 #endif // V8_TARGET_ARCH_X64 | 2111 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |