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

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 6366010: X64 Crankshaft: Added a bunch of operations. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build-x64
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698