Chromium Code Reviews| 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 |