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 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 } else { | 1139 } else { |
1140 EmitCmpI(left, right); | 1140 EmitCmpI(left, right); |
1141 } | 1141 } |
1142 | 1142 |
1143 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1143 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1144 EmitBranch(true_block, false_block, cc); | 1144 EmitBranch(true_block, false_block, cc); |
1145 } | 1145 } |
1146 | 1146 |
1147 | 1147 |
1148 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1148 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
1149 Abort("Unimplemented: %s", "DoCmpJSObjectEq"); | 1149 Register left = ToRegister(instr->InputAt(0)); |
1150 Register right = ToRegister(instr->InputAt(1)); | |
1151 Register result = ToRegister(instr->result()); | |
1152 | |
1153 __ cmpq(left, right); | |
1154 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | |
1155 NearLabel load; | |
1156 __ j(equal, &load); | |
1157 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); | |
William Hesse
2011/01/24 16:25:27
Why not move True and False directly to the result
Lasse Reichstein
2011/01/25 10:13:27
The change to the code relative to ia32 is because
| |
1158 __ bind(&load); | |
1159 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); | |
1150 } | 1160 } |
1151 | 1161 |
1152 | 1162 |
1153 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1163 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
1154 Register left = ToRegister(instr->InputAt(0)); | 1164 Register left = ToRegister(instr->InputAt(0)); |
1155 Register right = ToRegister(instr->InputAt(1)); | 1165 Register right = ToRegister(instr->InputAt(1)); |
1156 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1166 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1157 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1167 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1158 | 1168 |
1159 __ cmpq(left, right); | 1169 __ cmpq(left, right); |
1160 EmitBranch(true_block, false_block, equal); | 1170 EmitBranch(true_block, false_block, equal); |
1161 } | 1171 } |
1162 | 1172 |
1163 | 1173 |
1164 void LCodeGen::DoIsNull(LIsNull* instr) { | 1174 void LCodeGen::DoIsNull(LIsNull* instr) { |
1165 Abort("Unimplemented: %s", "DoIsNull"); | 1175 Register reg = ToRegister(instr->InputAt(0)); |
1176 Register result = ToRegister(instr->result()); | |
1177 | |
1178 // If the expression is known to be a smi, then it's | |
1179 // definitely not null. Materialize false. | |
1180 // Consider adding other type and representation tests too. | |
1181 if (instr->hydrogen()->value()->type().IsSmi()) { | |
1182 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1183 return; | |
1184 } | |
1185 | |
1186 __ CompareRoot(reg, Heap::kNullValueRootIndex); | |
1187 if (instr->is_strict()) { | |
1188 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | |
1189 NearLabel load; | |
1190 __ j(equal, &load); | |
1191 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); | |
1192 __ bind(&load); | |
1193 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); | |
1194 } else { | |
1195 NearLabel true_value, false_value, done; | |
1196 __ j(equal, &true_value); | |
1197 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | |
1198 __ j(equal, &true_value); | |
1199 __ JumpIfSmi(reg, &false_value); | |
1200 // Check for undetectable objects by looking in the bit field in | |
1201 // the map. The object has already been smi checked. | |
1202 Register scratch = result; | |
1203 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | |
1204 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | |
1205 Immediate(1 << Map::kIsUndetectable)); | |
1206 __ j(not_zero, &true_value); | |
1207 __ bind(&false_value); | |
1208 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1209 __ jmp(&done); | |
1210 __ bind(&true_value); | |
1211 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1212 __ bind(&done); | |
1213 } | |
1166 } | 1214 } |
1167 | 1215 |
1168 | 1216 |
1169 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1217 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1170 Register reg = ToRegister(instr->InputAt(0)); | 1218 Register reg = ToRegister(instr->InputAt(0)); |
1171 | 1219 |
1172 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1220 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1173 | 1221 |
1174 if (instr->hydrogen()->representation().IsSpecialization() || | 1222 if (instr->hydrogen()->representation().IsSpecialization() || |
1175 instr->hydrogen()->type().IsSmi()) { | 1223 instr->hydrogen()->type().IsSmi()) { |
(...skipping 23 matching lines...) Expand all Loading... | |
1199 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1247 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
1200 Immediate(1 << Map::kIsUndetectable)); | 1248 Immediate(1 << Map::kIsUndetectable)); |
1201 EmitBranch(true_block, false_block, not_zero); | 1249 EmitBranch(true_block, false_block, not_zero); |
1202 } | 1250 } |
1203 } | 1251 } |
1204 | 1252 |
1205 | 1253 |
1206 Condition LCodeGen::EmitIsObject(Register input, | 1254 Condition LCodeGen::EmitIsObject(Register input, |
1207 Register temp1, | 1255 Register temp1, |
1208 Register temp2, | 1256 Register temp2, |
1209 Label* is_not_object, | 1257 Label* is_not_object, |
William Hesse
2011/01/25 09:22:37
This function should drop the temp2 argument, use
Lasse Reichstein
2011/01/25 10:17:50
Dropped both. They seem to be used sequentially, a
| |
1210 Label* is_object) { | 1258 Label* is_object) { |
1211 ASSERT(!input.is(temp1)); | 1259 ASSERT(!input.is(temp1)); |
1212 ASSERT(!input.is(temp2)); | 1260 ASSERT(!input.is(temp2)); |
1213 ASSERT(!temp1.is(temp2)); | 1261 ASSERT(!temp1.is(temp2)); |
1214 | 1262 |
1215 __ JumpIfSmi(input, is_not_object); | 1263 __ JumpIfSmi(input, is_not_object); |
1216 | 1264 |
1217 __ Cmp(input, Factory::null_value()); | 1265 __ Cmp(input, Factory::null_value()); |
William Hesse
2011/01/25 09:22:37
Can we use the root array here?
Lasse Reichstein
2011/01/25 10:17:50
Done.
| |
1218 __ j(equal, is_object); | 1266 __ j(equal, is_object); |
1219 | 1267 |
1220 __ movq(temp1, FieldOperand(input, HeapObject::kMapOffset)); | 1268 __ movq(temp1, FieldOperand(input, HeapObject::kMapOffset)); |
1221 // Undetectable objects behave like undefined. | 1269 // Undetectable objects behave like undefined. |
1222 __ testb(FieldOperand(temp1, Map::kBitFieldOffset), | 1270 __ testb(FieldOperand(temp1, Map::kBitFieldOffset), |
1223 Immediate(1 << Map::kIsUndetectable)); | 1271 Immediate(1 << Map::kIsUndetectable)); |
1224 __ j(not_zero, is_not_object); | 1272 __ j(not_zero, is_not_object); |
1225 | 1273 |
1226 __ movzxbl(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1274 __ movzxbl(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
1227 __ cmpb(temp2, Immediate(FIRST_JS_OBJECT_TYPE)); | 1275 __ cmpb(temp2, Immediate(FIRST_JS_OBJECT_TYPE)); |
1228 __ j(below, is_not_object); | 1276 __ j(below, is_not_object); |
1229 __ cmpb(temp2, Immediate(LAST_JS_OBJECT_TYPE)); | 1277 __ cmpb(temp2, Immediate(LAST_JS_OBJECT_TYPE)); |
1230 return below_equal; | 1278 return below_equal; |
1231 } | 1279 } |
1232 | 1280 |
1233 | 1281 |
1234 void LCodeGen::DoIsObject(LIsObject* instr) { | 1282 void LCodeGen::DoIsObject(LIsObject* instr) { |
1235 Abort("Unimplemented: %s", "DoIsObject"); | 1283 Register reg = ToRegister(instr->InputAt(0)); |
1284 Register result = ToRegister(instr->result()); | |
1285 Register temp = ToRegister(instr->TempAt(0)); | |
Rico
2011/01/25 07:13:28
No need to the temp register here (and in the lith
Lasse Reichstein
2011/01/25 10:13:27
Removed, and EmitIsObject rewritten to use only kS
| |
1286 Label is_false, is_true, done; | |
1287 | |
1288 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); | |
1289 __ j(true_cond, &is_true); | |
1290 | |
1291 __ bind(&is_false); | |
1292 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1293 __ jmp(&done); | |
1294 | |
1295 __ bind(&is_true); | |
1296 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1297 | |
1298 __ bind(&done); | |
1236 } | 1299 } |
1237 | 1300 |
1238 | 1301 |
1239 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1302 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1240 Register reg = ToRegister(instr->InputAt(0)); | 1303 Register reg = ToRegister(instr->InputAt(0)); |
1241 Register temp = ToRegister(instr->TempAt(0)); | 1304 Register temp = ToRegister(instr->TempAt(0)); |
1242 Register temp2 = ToRegister(instr->TempAt(1)); | 1305 Register temp2 = ToRegister(instr->TempAt(1)); |
1243 | 1306 |
1244 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1307 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1245 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1308 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1246 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1309 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1247 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1310 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1248 | 1311 |
1249 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1312 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
1250 | 1313 |
1251 EmitBranch(true_block, false_block, true_cond); | 1314 EmitBranch(true_block, false_block, true_cond); |
1252 } | 1315 } |
1253 | 1316 |
1254 | 1317 |
1255 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1318 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
1256 Abort("Unimplemented: %s", "DoIsSmi"); | 1319 LOperand* input_operand = instr->InputAt(0); |
1320 Register result = ToRegister(instr->result()); | |
1321 if (input_operand->IsRegister()) { | |
1322 Register input = ToRegister(input_operand); | |
1323 __ CheckSmiToIndicator(result, input); | |
1324 } else { | |
1325 Operand input = ToOperand(instr->InputAt(0)); | |
1326 __ CheckSmiToIndicator(result, input); | |
1327 } | |
1328 // result is zero if input is a smi, and one otherwise. | |
1329 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); | |
1330 __ movq(result, Operand(kRootRegister, result, times_pointer_size, | |
1331 Heap::kTrueValueRootIndex)); | |
William Hesse
2011/01/24 16:25:27
I think you need to multiply the kTrueValueRootInd
Lasse Reichstein
2011/01/25 10:13:27
Well spotted.
| |
1257 } | 1332 } |
1258 | 1333 |
1259 | 1334 |
1260 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1335 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1261 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1336 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1262 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1337 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1263 | 1338 |
1264 Condition is_smi; | 1339 Condition is_smi; |
1265 if (instr->InputAt(0)->IsRegister()) { | 1340 if (instr->InputAt(0)->IsRegister()) { |
1266 Register input = ToRegister(instr->InputAt(0)); | 1341 Register input = ToRegister(instr->InputAt(0)); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1379 // classes and it doesn't have to because you can't access it with natives | 1454 // classes and it doesn't have to because you can't access it with natives |
1380 // syntax. Since both sides are symbols it is sufficient to use an identity | 1455 // syntax. Since both sides are symbols it is sufficient to use an identity |
1381 // comparison. | 1456 // comparison. |
1382 ASSERT(class_name->IsSymbol()); | 1457 ASSERT(class_name->IsSymbol()); |
1383 __ Cmp(temp, class_name); | 1458 __ Cmp(temp, class_name); |
1384 // End with the answer in the z flag. | 1459 // End with the answer in the z flag. |
1385 } | 1460 } |
1386 | 1461 |
1387 | 1462 |
1388 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1463 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1389 Abort("Unimplemented: %s", "DoClassOfTest"); | 1464 Register input = ToRegister(instr->InputAt(0)); |
1465 Register result = ToRegister(instr->result()); | |
1466 ASSERT(input.is(result)); | |
1467 Register temp = ToRegister(instr->TempAt(0)); | |
Rico
2011/01/25 07:13:28
Use r10?
Lasse Reichstein
2011/01/25 10:13:27
This temp is needed in EmitClassOfTest. It uses th
| |
1468 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1469 NearLabel done; | |
1470 Label is_true, is_false; | |
1471 | |
1472 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); | |
1473 | |
1474 __ j(not_equal, &is_false); | |
1475 | |
1476 __ bind(&is_true); | |
1477 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1478 __ jmp(&done); | |
1479 | |
1480 __ bind(&is_false); | |
1481 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1482 __ bind(&done); | |
1390 } | 1483 } |
1391 | 1484 |
1392 | 1485 |
1393 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1486 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1394 Register input = ToRegister(instr->InputAt(0)); | 1487 Register input = ToRegister(instr->InputAt(0)); |
1395 Register temp = ToRegister(instr->TempAt(0)); | 1488 Register temp = ToRegister(instr->TempAt(0)); |
1396 Handle<String> class_name = instr->hydrogen()->class_name(); | 1489 Handle<String> class_name = instr->hydrogen()->class_name(); |
1397 | 1490 |
1398 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1491 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1399 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1492 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1400 | 1493 |
1401 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1494 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1402 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1495 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1403 | 1496 |
1404 EmitClassOfTest(true_label, false_label, class_name, input, temp); | 1497 EmitClassOfTest(true_label, false_label, class_name, input, temp); |
1405 | 1498 |
1406 EmitBranch(true_block, false_block, equal); | 1499 EmitBranch(true_block, false_block, equal); |
1407 } | 1500 } |
1408 | 1501 |
1409 | 1502 |
1410 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1503 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1411 Abort("Unimplemented: %s", "DoCmpMapAndBranch"); | 1504 Register reg = ToRegister(instr->InputAt(0)); |
1505 int true_block = instr->true_block_id(); | |
1506 int false_block = instr->false_block_id(); | |
1507 | |
1508 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | |
1509 EmitBranch(true_block, false_block, equal); | |
1412 } | 1510 } |
1413 | 1511 |
1414 | 1512 |
1415 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1513 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1416 Abort("Unimplemented: %s", "DoInstanceOf"); | 1514 Abort("Unimplemented: %s", "DoInstanceOf"); |
1417 } | 1515 } |
1418 | 1516 |
1419 | 1517 |
1420 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1518 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
1421 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1519 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1693 Abort("Unimplemented: %s", "DoStoreKeyedFastElement"); | 1791 Abort("Unimplemented: %s", "DoStoreKeyedFastElement"); |
1694 } | 1792 } |
1695 | 1793 |
1696 | 1794 |
1697 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 1795 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
1698 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); | 1796 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); |
1699 } | 1797 } |
1700 | 1798 |
1701 | 1799 |
1702 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 1800 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
1703 Abort("Unimplemented: %s", "DoInteger32ToDouble"); | 1801 LOperand* input = instr->InputAt(0); |
1802 ASSERT(input->IsRegister() || input->IsStackSlot()); | |
1803 LOperand* output = instr->result(); | |
1804 ASSERT(output->IsDoubleRegister()); | |
1805 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); | |
William Hesse
2011/01/24 16:25:27
Operand cannot represent a register, so you need t
Lasse Reichstein
2011/01/25 10:13:27
We assert just above that input is not a register
| |
1704 } | 1806 } |
1705 | 1807 |
1706 | 1808 |
1707 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 1809 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
1708 Abort("Unimplemented: %s", "DoNumberTagI"); | 1810 LOperand* input = instr->InputAt(0); |
1709 } | 1811 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
1812 Register reg = ToRegister(input); | |
1710 | 1813 |
1711 | 1814 __ Integer32ToSmi(reg, reg); |
1712 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | |
1713 Abort("Unimplemented: %s", "DoDeferredNumberTagI"); | |
1714 } | 1815 } |
1715 | 1816 |
1716 | 1817 |
1717 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 1818 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
1718 Abort("Unimplemented: %s", "DoNumberTagD"); | 1819 class DeferredNumberTagD: public LDeferredCode { |
1820 public: | |
1821 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | |
1822 : LDeferredCode(codegen), instr_(instr) { } | |
1823 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | |
1824 private: | |
1825 LNumberTagD* instr_; | |
1826 }; | |
1827 | |
1828 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | |
1829 Register reg = ToRegister(instr->result()); | |
1830 Register tmp = ToRegister(instr->TempAt(0)); | |
1831 | |
1832 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | |
1833 if (FLAG_inline_new) { | |
1834 __ AllocateHeapNumber(reg, tmp, deferred->entry()); | |
1835 } else { | |
1836 __ jmp(deferred->entry()); | |
1837 } | |
1838 __ bind(deferred->exit()); | |
1839 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | |
1719 } | 1840 } |
1720 | 1841 |
1721 | 1842 |
1722 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 1843 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
1723 Abort("Unimplemented: %s", "DoDeferredNumberTagD"); | 1844 // TODO(3095996): Get rid of this. For now, we need to make the |
1845 // result register contain a valid pointer because it is already | |
1846 // contained in the register pointer map. | |
1847 Register reg = ToRegister(instr->result()); | |
1848 __ Set(reg, 0); | |
William Hesse
2011/01/24 16:25:27
How can 0 be a valid pointer? It isn't tagged.
Lasse Reichstein
2011/01/25 10:13:27
By chance, since it's the representation of Smi ze
| |
1849 | |
1850 __ PushSafepointRegisters(); | |
1851 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | |
1852 RecordSafepointWithRegisters( | |
1853 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
1854 // Ensure that value in rax survives popping registers. | |
1855 __ movq(kScratchRegister, rax); | |
1856 __ PopSafepointRegisters(); | |
1857 __ movq(reg, kScratchRegister); | |
1724 } | 1858 } |
1725 | 1859 |
1726 | 1860 |
1727 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 1861 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
1728 Abort("Unimplemented: %s", "DoSmiTag"); | 1862 Abort("Unimplemented: %s", "DoSmiTag"); |
1729 } | 1863 } |
1730 | 1864 |
1731 | 1865 |
1732 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 1866 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
1733 Abort("Unimplemented: %s", "DoSmiUntag"); | 1867 Abort("Unimplemented: %s", "DoSmiUntag"); |
1734 } | 1868 } |
1735 | 1869 |
1736 | 1870 |
1737 void LCodeGen::EmitNumberUntagD(Register input_reg, | 1871 void LCodeGen::EmitNumberUntagD(Register input_reg, |
1738 XMMRegister result_reg, | 1872 XMMRegister result_reg, |
1739 LEnvironment* env) { | 1873 LEnvironment* env) { |
1740 Abort("Unimplemented: %s", "EmitNumberUntagD"); | 1874 NearLabel load_smi, heap_number, done; |
1875 | |
1876 // Smi check. | |
1877 __ JumpIfSmi(input_reg, &load_smi); | |
1878 | |
1879 // Heap number map check. | |
1880 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | |
1881 Heap::kHeapNumberMapRootIndex); | |
1882 __ j(equal, &heap_number); | |
1883 | |
1884 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | |
1885 DeoptimizeIf(not_equal, env); | |
1886 | |
1887 // Convert undefined to NaN. Compute NaN as 0/0. | |
1888 __ xorpd(result_reg, result_reg); | |
1889 __ divsd(result_reg, result_reg); | |
1890 __ jmp(&done); | |
1891 | |
1892 // Heap number to XMM conversion. | |
1893 __ bind(&heap_number); | |
1894 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
1895 __ jmp(&done); | |
1896 | |
1897 // Smi to XMM conversion | |
1898 __ bind(&load_smi); | |
1899 __ SmiToInteger32(input_reg, input_reg); // Untag smi first. | |
1900 __ cvtlsi2sd(result_reg, input_reg); | |
1901 __ Integer32ToSmi(input_reg, input_reg); // Retag smi. | |
William Hesse
2011/01/24 16:25:27
Can't we have some way to make this optional, or u
Lasse Reichstein
2011/01/25 10:13:27
Using kScratchRegister seems like the easy way. We
| |
1902 __ bind(&done); | |
1741 } | 1903 } |
1742 | 1904 |
1743 | 1905 |
1744 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 1906 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
1745 Abort("Unimplemented: %s", "DoDeferredTaggedToI"); | 1907 Abort("Unimplemented: %s", "DoDeferredTaggedToI"); |
1746 } | 1908 } |
1747 | 1909 |
1748 | 1910 |
1749 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 1911 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
1750 Abort("Unimplemented: %s", "DoTaggedToI"); | 1912 Abort("Unimplemented: %s", "DoTaggedToI"); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1932 | 2094 |
1933 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2095 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
1934 Abort("Unimplemented: %s", "DoOsrEntry"); | 2096 Abort("Unimplemented: %s", "DoOsrEntry"); |
1935 } | 2097 } |
1936 | 2098 |
1937 #undef __ | 2099 #undef __ |
1938 | 2100 |
1939 } } // namespace v8::internal | 2101 } } // namespace v8::internal |
1940 | 2102 |
1941 #endif // V8_TARGET_ARCH_X64 | 2103 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |