| 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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 } | 797 } |
| 798 | 798 |
| 799 | 799 |
| 800 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 800 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 801 return AssignEnvironment(new LDeoptimize); | 801 return AssignEnvironment(new LDeoptimize); |
| 802 } | 802 } |
| 803 | 803 |
| 804 | 804 |
| 805 LInstruction* LChunkBuilder::DoBit(Token::Value op, | 805 LInstruction* LChunkBuilder::DoBit(Token::Value op, |
| 806 HBitwiseBinaryOperation* instr) { | 806 HBitwiseBinaryOperation* instr) { |
| 807 if (instr->representation().IsInteger32()) { | 807 if (instr->representation().IsInteger()) { |
| 808 ASSERT(instr->left()->representation().IsInteger32()); | 808 ASSERT(instr->left()->representation().IsInteger()); |
| 809 ASSERT(instr->right()->representation().IsInteger32()); | 809 ASSERT(instr->right()->representation().IsInteger()); |
| 810 | 810 |
| 811 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 811 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 812 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 812 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
| 813 return DefineSameAsFirst(new LBitI(op, left, right)); | 813 return DefineSameAsFirst(new LBitI(op, left, right)); |
| 814 } else { | 814 } else { |
| 815 ASSERT(instr->representation().IsTagged()); | 815 ASSERT(instr->representation().IsTagged()); |
| 816 ASSERT(instr->left()->representation().IsTagged()); | 816 ASSERT(instr->left()->representation().IsTagged()); |
| 817 ASSERT(instr->right()->representation().IsTagged()); | 817 ASSERT(instr->right()->representation().IsTagged()); |
| 818 | 818 |
| 819 LOperand* left = UseFixed(instr->left(), edx); | 819 LOperand* left = UseFixed(instr->left(), edx); |
| 820 LOperand* right = UseFixed(instr->right(), eax); | 820 LOperand* right = UseFixed(instr->right(), eax); |
| 821 LArithmeticT* result = new LArithmeticT(op, left, right); | 821 LArithmeticT* result = new LArithmeticT(op, left, right); |
| 822 return MarkAsCall(DefineFixed(result, eax), instr); | 822 return MarkAsCall(DefineFixed(result, eax), instr); |
| 823 } | 823 } |
| 824 } | 824 } |
| 825 | 825 |
| 826 | 826 |
| 827 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 827 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 828 HBitwiseBinaryOperation* instr) { | 828 HBitwiseBinaryOperation* instr) { |
| 829 if (instr->representation().IsTagged()) { | 829 if (instr->representation().IsTagged()) { |
| 830 ASSERT(instr->left()->representation().IsTagged()); | 830 ASSERT(instr->left()->representation().IsTagged()); |
| 831 ASSERT(instr->right()->representation().IsTagged()); | 831 ASSERT(instr->right()->representation().IsTagged()); |
| 832 | 832 |
| 833 LOperand* left = UseFixed(instr->left(), edx); | 833 LOperand* left = UseFixed(instr->left(), edx); |
| 834 LOperand* right = UseFixed(instr->right(), eax); | 834 LOperand* right = UseFixed(instr->right(), eax); |
| 835 LArithmeticT* result = new LArithmeticT(op, left, right); | 835 LArithmeticT* result = new LArithmeticT(op, left, right); |
| 836 return MarkAsCall(DefineFixed(result, eax), instr); | 836 return MarkAsCall(DefineFixed(result, eax), instr); |
| 837 } | 837 } |
| 838 | 838 |
| 839 ASSERT(instr->representation().IsInteger32()); | 839 ASSERT(instr->representation().IsInteger()); |
| 840 ASSERT(instr->OperandAt(0)->representation().IsInteger32()); | 840 ASSERT(instr->OperandAt(0)->representation().IsInteger32X()); |
| 841 ASSERT(instr->OperandAt(1)->representation().IsInteger32()); | 841 ASSERT(instr->OperandAt(1)->representation().IsInteger32X()); |
| 842 LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); | 842 LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); |
| 843 | 843 |
| 844 HValue* right_value = instr->OperandAt(1); | 844 HValue* right_value = instr->OperandAt(1); |
| 845 LOperand* right = NULL; | 845 LOperand* right = NULL; |
| 846 int constant_value = 0; | 846 int constant_value = 0; |
| 847 if (right_value->IsConstant()) { | 847 if (right_value->IsConstant()) { |
| 848 HConstant* constant = HConstant::cast(right_value); | 848 HConstant* constant = HConstant::cast(right_value); |
| 849 right = chunk_->DefineConstantOperand(constant); | 849 right = chunk_->DefineConstantOperand(constant); |
| 850 constant_value = constant->Integer32Value() & 0x1f; | 850 constant_value = constant->Integer32Value() & 0x1f; |
| 851 } else { | 851 } else { |
| 852 right = UseFixed(right_value, ecx); | 852 right = UseFixed(right_value, ecx); |
| 853 } | 853 } |
| 854 | 854 |
| 855 // Shift operations can only deoptimize if we do a logical shift | 855 // Shift operations can only deoptimize if we do a logical shift |
| 856 // by 0 and the result cannot be truncated to int32. | 856 // by 0 and the result cannot be truncated to int32. |
| 857 bool can_deopt = (op == Token::SHR && constant_value == 0); | 857 bool can_deopt = op == Token::SHR && |
| 858 if (can_deopt) { | 858 constant_value == 0 && |
| 859 bool can_truncate = true; | 859 !instr->representation().Equals(Representation::TruncatedInteger32()); |
| 860 for (int i = 0; i < instr->uses()->length(); i++) { | |
| 861 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { | |
| 862 can_truncate = false; | |
| 863 break; | |
| 864 } | |
| 865 } | |
| 866 can_deopt = !can_truncate; | |
| 867 } | |
| 868 | 860 |
| 869 LShiftI* result = new LShiftI(op, left, right, can_deopt); | 861 LShiftI* result = new LShiftI(op, left, right, can_deopt); |
| 870 return can_deopt | 862 return can_deopt |
| 871 ? AssignEnvironment(DefineSameAsFirst(result)) | 863 ? AssignEnvironment(DefineSameAsFirst(result)) |
| 872 : DefineSameAsFirst(result); | 864 : DefineSameAsFirst(result); |
| 873 } | 865 } |
| 874 | 866 |
| 875 | 867 |
| 876 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 868 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 877 HArithmeticBinaryOperation* instr) { | 869 HArithmeticBinaryOperation* instr) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 | 1038 |
| 1047 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | 1039 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), |
| 1048 TempRegister(), | 1040 TempRegister(), |
| 1049 TempRegister()); | 1041 TempRegister()); |
| 1050 } else if (v->IsCompare()) { | 1042 } else if (v->IsCompare()) { |
| 1051 HCompare* compare = HCompare::cast(v); | 1043 HCompare* compare = HCompare::cast(v); |
| 1052 Token::Value op = compare->token(); | 1044 Token::Value op = compare->token(); |
| 1053 HValue* left = compare->left(); | 1045 HValue* left = compare->left(); |
| 1054 HValue* right = compare->right(); | 1046 HValue* right = compare->right(); |
| 1055 Representation r = compare->GetInputRepresentation(); | 1047 Representation r = compare->GetInputRepresentation(); |
| 1056 if (r.IsInteger32()) { | 1048 if (r.IsInteger()) { |
| 1057 ASSERT(left->representation().IsInteger32()); | 1049 ASSERT(left->representation().IsInteger()); |
| 1058 ASSERT(right->representation().IsInteger32()); | 1050 ASSERT(right->representation().IsInteger()); |
| 1059 | 1051 |
| 1060 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 1052 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1061 UseOrConstantAtStart(right)); | 1053 UseOrConstantAtStart(right)); |
| 1062 } else if (r.IsDouble()) { | 1054 } else if (r.IsDouble()) { |
| 1063 ASSERT(left->representation().IsDouble()); | 1055 ASSERT(left->representation().IsDouble()); |
| 1064 ASSERT(right->representation().IsDouble()); | 1056 ASSERT(right->representation().IsDouble()); |
| 1065 | 1057 |
| 1066 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 1058 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1067 UseRegisterAtStart(right)); | 1059 UseRegisterAtStart(right)); |
| 1068 } else { | 1060 } else { |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 return DoShift(Token::SHL, instr); | 1334 return DoShift(Token::SHL, instr); |
| 1343 } | 1335 } |
| 1344 | 1336 |
| 1345 | 1337 |
| 1346 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { | 1338 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { |
| 1347 return DoBit(Token::BIT_AND, instr); | 1339 return DoBit(Token::BIT_AND, instr); |
| 1348 } | 1340 } |
| 1349 | 1341 |
| 1350 | 1342 |
| 1351 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { | 1343 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
| 1352 ASSERT(instr->value()->representation().IsInteger32()); | 1344 ASSERT(instr->value()->representation().IsInteger()); |
| 1353 ASSERT(instr->representation().IsInteger32()); | 1345 ASSERT(instr->representation().IsInteger32X()); |
| 1354 LOperand* input = UseRegisterAtStart(instr->value()); | 1346 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1355 LBitNotI* result = new LBitNotI(input); | 1347 LBitNotI* result = new LBitNotI(input); |
| 1356 return DefineSameAsFirst(result); | 1348 return DefineSameAsFirst(result); |
| 1357 } | 1349 } |
| 1358 | 1350 |
| 1359 | 1351 |
| 1360 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { | 1352 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { |
| 1361 return DoBit(Token::BIT_OR, instr); | 1353 return DoBit(Token::BIT_OR, instr); |
| 1362 } | 1354 } |
| 1363 | 1355 |
| 1364 | 1356 |
| 1365 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { | 1357 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { |
| 1366 return DoBit(Token::BIT_XOR, instr); | 1358 return DoBit(Token::BIT_XOR, instr); |
| 1367 } | 1359 } |
| 1368 | 1360 |
| 1369 | 1361 |
| 1370 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1362 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1371 if (instr->representation().IsDouble()) { | 1363 if (instr->representation().IsDouble()) { |
| 1372 return DoArithmeticD(Token::DIV, instr); | 1364 return DoArithmeticD(Token::DIV, instr); |
| 1373 } else if (instr->representation().IsInteger32()) { | 1365 } else if (instr->representation().IsInteger()) { |
| 1366 ASSERT(instr->representation().IsInteger32X()); |
| 1374 // The temporary operand is necessary to ensure that right is not allocated | 1367 // The temporary operand is necessary to ensure that right is not allocated |
| 1375 // into edx. | 1368 // into edx. |
| 1376 LOperand* temp = FixedTemp(edx); | 1369 LOperand* temp = FixedTemp(edx); |
| 1377 LOperand* dividend = UseFixed(instr->left(), eax); | 1370 LOperand* dividend = UseFixed(instr->left(), eax); |
| 1378 LOperand* divisor = UseRegister(instr->right()); | 1371 LOperand* divisor = UseRegister(instr->right()); |
| 1379 LDivI* result = new LDivI(dividend, divisor, temp); | 1372 LDivI* result = new LDivI(dividend, divisor, temp); |
| 1380 return AssignEnvironment(DefineFixed(result, eax)); | 1373 return AssignEnvironment(DefineFixed(result, eax)); |
| 1381 } else { | 1374 } else { |
| 1382 ASSERT(instr->representation().IsTagged()); | 1375 ASSERT(instr->representation().IsTagged()); |
| 1383 return DoArithmeticT(Token::DIV, instr); | 1376 return DoArithmeticT(Token::DIV, instr); |
| 1384 } | 1377 } |
| 1385 } | 1378 } |
| 1386 | 1379 |
| 1387 | 1380 |
| 1388 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1381 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1389 if (instr->representation().IsInteger32()) { | 1382 if (instr->representation().IsInteger32X()) { |
| 1390 ASSERT(instr->left()->representation().IsInteger32()); | 1383 ASSERT(instr->left()->representation().IsInteger()); |
| 1391 ASSERT(instr->right()->representation().IsInteger32()); | 1384 ASSERT(instr->right()->representation().IsInteger()); |
| 1392 | 1385 |
| 1393 LInstruction* result; | 1386 LInstruction* result; |
| 1394 if (instr->HasPowerOf2Divisor()) { | 1387 if (instr->HasPowerOf2Divisor()) { |
| 1395 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1388 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1396 LOperand* value = UseRegisterAtStart(instr->left()); | 1389 LOperand* value = UseRegisterAtStart(instr->left()); |
| 1397 LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL); | 1390 LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL); |
| 1398 result = DefineSameAsFirst(mod); | 1391 result = DefineSameAsFirst(mod); |
| 1399 } else { | 1392 } else { |
| 1400 // The temporary operand is necessary to ensure that right is | 1393 // The temporary operand is necessary to ensure that right is |
| 1401 // not allocated into edx. | 1394 // not allocated into edx. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1419 // TODO(fschneider): Allow any register as input registers. | 1412 // TODO(fschneider): Allow any register as input registers. |
| 1420 LOperand* left = UseFixedDouble(instr->left(), xmm2); | 1413 LOperand* left = UseFixedDouble(instr->left(), xmm2); |
| 1421 LOperand* right = UseFixedDouble(instr->right(), xmm1); | 1414 LOperand* right = UseFixedDouble(instr->right(), xmm1); |
| 1422 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); | 1415 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); |
| 1423 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); | 1416 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); |
| 1424 } | 1417 } |
| 1425 } | 1418 } |
| 1426 | 1419 |
| 1427 | 1420 |
| 1428 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1421 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1429 if (instr->representation().IsInteger32()) { | 1422 if (instr->representation().IsInteger32X()) { |
| 1430 ASSERT(instr->left()->representation().IsInteger32()); | 1423 ASSERT(instr->left()->representation().IsInteger()); |
| 1431 ASSERT(instr->right()->representation().IsInteger32()); | 1424 ASSERT(instr->right()->representation().IsInteger()); |
| 1432 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1425 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1433 LOperand* right = UseOrConstant(instr->MostConstantOperand()); | 1426 LOperand* right = UseOrConstant(instr->MostConstantOperand()); |
| 1434 LOperand* temp = NULL; | 1427 LOperand* temp = NULL; |
| 1435 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1428 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1436 temp = TempRegister(); | 1429 temp = TempRegister(); |
| 1437 } | 1430 } |
| 1438 LMulI* mul = new LMulI(left, right, temp); | 1431 LMulI* mul = new LMulI(left, right, temp); |
| 1439 return AssignEnvironment(DefineSameAsFirst(mul)); | 1432 return AssignEnvironment(DefineSameAsFirst(mul)); |
| 1440 } else if (instr->representation().IsDouble()) { | 1433 } else if (instr->representation().IsDouble()) { |
| 1441 return DoArithmeticD(Token::MUL, instr); | 1434 return DoArithmeticD(Token::MUL, instr); |
| 1442 } else { | 1435 } else { |
| 1443 ASSERT(instr->representation().IsTagged()); | 1436 ASSERT(instr->representation().IsTagged()); |
| 1444 return DoArithmeticT(Token::MUL, instr); | 1437 return DoArithmeticT(Token::MUL, instr); |
| 1445 } | 1438 } |
| 1446 } | 1439 } |
| 1447 | 1440 |
| 1448 | 1441 |
| 1449 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1442 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1450 if (instr->representation().IsInteger32()) { | 1443 if (instr->representation().IsInteger32X()) { |
| 1451 ASSERT(instr->left()->representation().IsInteger32()); | 1444 ASSERT(instr->left()->representation().IsInteger()); |
| 1452 ASSERT(instr->right()->representation().IsInteger32()); | 1445 ASSERT(instr->right()->representation().IsInteger()); |
| 1453 LOperand* left = UseRegisterAtStart(instr->left()); | 1446 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1454 LOperand* right = UseOrConstantAtStart(instr->right()); | 1447 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1455 LSubI* sub = new LSubI(left, right); | 1448 LSubI* sub = new LSubI(left, right); |
| 1456 LInstruction* result = DefineSameAsFirst(sub); | 1449 LInstruction* result = DefineSameAsFirst(sub); |
| 1457 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1450 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1458 result = AssignEnvironment(result); | 1451 result = AssignEnvironment(result); |
| 1459 } | 1452 } |
| 1460 return result; | 1453 return result; |
| 1461 } else if (instr->representation().IsDouble()) { | 1454 } else if (instr->representation().IsDouble()) { |
| 1462 return DoArithmeticD(Token::SUB, instr); | 1455 return DoArithmeticD(Token::SUB, instr); |
| 1463 } else { | 1456 } else { |
| 1464 ASSERT(instr->representation().IsTagged()); | 1457 ASSERT(instr->representation().IsTagged()); |
| 1465 return DoArithmeticT(Token::SUB, instr); | 1458 return DoArithmeticT(Token::SUB, instr); |
| 1466 } | 1459 } |
| 1467 } | 1460 } |
| 1468 | 1461 |
| 1469 | 1462 |
| 1470 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1463 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1471 if (instr->representation().IsInteger32()) { | 1464 if (instr->representation().IsInteger32X()) { |
| 1472 ASSERT(instr->left()->representation().IsInteger32()); | 1465 ASSERT(instr->left()->representation().IsInteger()); |
| 1473 ASSERT(instr->right()->representation().IsInteger32()); | 1466 ASSERT(instr->right()->representation().IsInteger()); |
| 1474 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1467 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1475 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 1468 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
| 1476 LAddI* add = new LAddI(left, right); | 1469 LAddI* add = new LAddI(left, right); |
| 1477 LInstruction* result = DefineSameAsFirst(add); | 1470 LInstruction* result = DefineSameAsFirst(add); |
| 1478 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1471 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1479 result = AssignEnvironment(result); | 1472 result = AssignEnvironment(result); |
| 1480 } | 1473 } |
| 1481 return result; | 1474 return result; |
| 1482 } else if (instr->representation().IsDouble()) { | 1475 } else if (instr->representation().IsDouble()) { |
| 1483 return DoArithmeticD(Token::ADD, instr); | 1476 return DoArithmeticD(Token::ADD, instr); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1500 UseFixed(instr->right(), eax); | 1493 UseFixed(instr->right(), eax); |
| 1501 LPower* result = new LPower(left, right); | 1494 LPower* result = new LPower(left, right); |
| 1502 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, | 1495 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, |
| 1503 CAN_DEOPTIMIZE_EAGERLY); | 1496 CAN_DEOPTIMIZE_EAGERLY); |
| 1504 } | 1497 } |
| 1505 | 1498 |
| 1506 | 1499 |
| 1507 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1500 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { |
| 1508 Token::Value op = instr->token(); | 1501 Token::Value op = instr->token(); |
| 1509 Representation r = instr->GetInputRepresentation(); | 1502 Representation r = instr->GetInputRepresentation(); |
| 1510 if (r.IsInteger32()) { | 1503 if (r.IsInteger32X()) { |
| 1511 ASSERT(instr->left()->representation().IsInteger32()); | 1504 ASSERT(instr->left()->representation().IsInteger()); |
| 1512 ASSERT(instr->right()->representation().IsInteger32()); | 1505 ASSERT(instr->right()->representation().IsInteger()); |
| 1513 LOperand* left = UseRegisterAtStart(instr->left()); | 1506 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1514 LOperand* right = UseOrConstantAtStart(instr->right()); | 1507 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1515 return DefineAsRegister(new LCmpID(left, right)); | 1508 return DefineAsRegister(new LCmpID(left, right)); |
| 1516 } else if (r.IsDouble()) { | 1509 } else if (r.IsDouble()) { |
| 1517 ASSERT(instr->left()->representation().IsDouble()); | 1510 ASSERT(instr->left()->representation().IsDouble()); |
| 1518 ASSERT(instr->right()->representation().IsDouble()); | 1511 ASSERT(instr->right()->representation().IsDouble()); |
| 1519 LOperand* left = UseRegisterAtStart(instr->left()); | 1512 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1520 LOperand* right = UseRegisterAtStart(instr->right()); | 1513 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1521 return DefineAsRegister(new LCmpID(left, right)); | 1514 return DefineAsRegister(new LCmpID(left, right)); |
| 1522 } else { | 1515 } else { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 | 1638 |
| 1646 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1639 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1647 Representation from = instr->from(); | 1640 Representation from = instr->from(); |
| 1648 Representation to = instr->to(); | 1641 Representation to = instr->to(); |
| 1649 if (from.IsTagged()) { | 1642 if (from.IsTagged()) { |
| 1650 if (to.IsDouble()) { | 1643 if (to.IsDouble()) { |
| 1651 LOperand* value = UseRegister(instr->value()); | 1644 LOperand* value = UseRegister(instr->value()); |
| 1652 LNumberUntagD* res = new LNumberUntagD(value); | 1645 LNumberUntagD* res = new LNumberUntagD(value); |
| 1653 return AssignEnvironment(DefineAsRegister(res)); | 1646 return AssignEnvironment(DefineAsRegister(res)); |
| 1654 } else { | 1647 } else { |
| 1655 ASSERT(to.IsInteger32()); | 1648 ASSERT(to.IsInteger()); |
| 1656 LOperand* value = UseRegister(instr->value()); | 1649 LOperand* value = UseRegister(instr->value()); |
| 1657 bool needs_check = !instr->value()->type().IsSmi(); | 1650 bool needs_check = !instr->value()->type().IsSmi(); |
| 1651 bool needs_temp = to.IsClampedRoundedInteger8() || |
| 1652 (!(CpuFeatures::IsSupported(SSE3) && to.IsTruncatedInteger32())); |
| 1653 ToIRoundingMode rounding_mode(RepresentationToRoundingMode(to)); |
| 1658 if (needs_check) { | 1654 if (needs_check) { |
| 1659 LOperand* xmm_temp = | 1655 LOperand* xmm_temp = needs_temp ? FixedTemp(xmm1) : NULL; |
| 1660 (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3)) | 1656 LTaggedToI* res = new LTaggedToI(value, xmm_temp, rounding_mode); |
| 1661 ? NULL | |
| 1662 : FixedTemp(xmm1); | |
| 1663 LTaggedToI* res = new LTaggedToI(value, xmm_temp); | |
| 1664 return AssignEnvironment(DefineSameAsFirst(res)); | 1657 return AssignEnvironment(DefineSameAsFirst(res)); |
| 1665 } else { | 1658 } else { |
| 1666 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1659 bool should_clamp = to.IsClampedRoundedInteger8(); |
| 1660 return DefineSameAsFirst(new LSmiUntag(value, |
| 1661 false, |
| 1662 should_clamp)); |
| 1667 } | 1663 } |
| 1668 } | 1664 } |
| 1669 } else if (from.IsDouble()) { | 1665 } else if (from.IsDouble()) { |
| 1670 if (to.IsTagged()) { | 1666 if (to.IsTagged()) { |
| 1671 LOperand* value = UseRegister(instr->value()); | 1667 LOperand* value = UseRegister(instr->value()); |
| 1672 LOperand* temp = TempRegister(); | 1668 LOperand* temp = TempRegister(); |
| 1673 | 1669 |
| 1674 // Make sure that temp and result_temp are different registers. | 1670 // Make sure that temp and result_temp are different registers. |
| 1675 LUnallocated* result_temp = TempRegister(); | 1671 LUnallocated* result_temp = TempRegister(); |
| 1676 LNumberTagD* result = new LNumberTagD(value, temp); | 1672 LNumberTagD* result = new LNumberTagD(value, temp); |
| 1677 return AssignPointerMap(Define(result, result_temp)); | 1673 return AssignPointerMap(Define(result, result_temp)); |
| 1678 } else { | 1674 } else { |
| 1679 ASSERT(to.IsInteger32()); | 1675 ASSERT(to.IsInteger()); |
| 1680 bool needs_temp = instr->CanTruncateToInt32() && | 1676 ToIRoundingMode rounding_mode(RepresentationToRoundingMode(to)); |
| 1681 !CpuFeatures::IsSupported(SSE3); | 1677 bool needs_temp = to.IsClampedRoundedInteger8() || |
| 1678 (!(CpuFeatures::IsSupported(SSE3) && to.IsTruncatedInteger32())); |
| 1682 LOperand* value = needs_temp ? | 1679 LOperand* value = needs_temp ? |
| 1683 UseTempRegister(instr->value()) : UseRegister(instr->value()); | 1680 UseTempRegister(instr->value()) : UseRegister(instr->value()); |
| 1684 LOperand* temp = needs_temp ? TempRegister() : NULL; | 1681 LOperand* temp = needs_temp ? TempRegister() : NULL; |
| 1685 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp))); | 1682 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, |
| 1683 temp, |
| 1684 rounding_mode))); |
| 1686 } | 1685 } |
| 1687 } else if (from.IsInteger32()) { | 1686 } else if (from.IsInteger()) { |
| 1688 if (to.IsTagged()) { | 1687 if (to.IsTagged()) { |
| 1689 HValue* val = instr->value(); | 1688 HValue* val = instr->value(); |
| 1690 LOperand* value = UseRegister(val); | 1689 LOperand* value = UseRegister(val); |
| 1691 if (val->HasRange() && val->range()->IsInSmiRange()) { | 1690 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 1692 return DefineSameAsFirst(new LSmiTag(value)); | 1691 return DefineSameAsFirst(new LSmiTag(value)); |
| 1693 } else { | 1692 } else { |
| 1694 LNumberTagI* result = new LNumberTagI(value); | 1693 LNumberTagI* result = new LNumberTagI(value); |
| 1695 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1694 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1696 } | 1695 } |
| 1696 } else if (to.IsClampedRoundedInteger8()) { |
| 1697 return DefineFixed(new LInteger32ToClamped( |
| 1698 UseFixed(instr->value(), eax)), eax); |
| 1697 } else { | 1699 } else { |
| 1698 ASSERT(to.IsDouble()); | 1700 ASSERT(to.IsDouble()); |
| 1699 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value()))); | 1701 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value()))); |
| 1700 } | 1702 } |
| 1701 } | 1703 } |
| 1702 UNREACHABLE(); | 1704 UNREACHABLE(); |
| 1703 return NULL; | 1705 return NULL; |
| 1704 } | 1706 } |
| 1705 | 1707 |
| 1706 | 1708 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 } | 1746 } |
| 1745 | 1747 |
| 1746 | 1748 |
| 1747 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1749 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1748 return new LReturn(UseFixed(instr->value(), eax)); | 1750 return new LReturn(UseFixed(instr->value(), eax)); |
| 1749 } | 1751 } |
| 1750 | 1752 |
| 1751 | 1753 |
| 1752 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1754 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1753 Representation r = instr->representation(); | 1755 Representation r = instr->representation(); |
| 1754 if (r.IsInteger32()) { | 1756 if (r.IsInteger()) { |
| 1755 return DefineAsRegister(new LConstantI); | 1757 return DefineAsRegister(new LConstantI); |
| 1756 } else if (r.IsDouble()) { | 1758 } else if (r.IsDouble()) { |
| 1757 double value = instr->DoubleValue(); | 1759 double value = instr->DoubleValue(); |
| 1758 LOperand* temp = (BitCast<uint64_t, double>(value) != 0) | 1760 LOperand* temp = (BitCast<uint64_t, double>(value) != 0) |
| 1759 ? TempRegister() | 1761 ? TempRegister() |
| 1760 : NULL; | 1762 : NULL; |
| 1761 return DefineAsRegister(new LConstantD(temp)); | 1763 return DefineAsRegister(new LConstantD(temp)); |
| 1762 } else if (r.IsTagged()) { | 1764 } else if (r.IsTagged()) { |
| 1763 return DefineAsRegister(new LConstantT); | 1765 return DefineAsRegister(new LConstantT); |
| 1764 } else { | 1766 } else { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1871 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | 1873 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
| 1872 HLoadExternalArrayPointer* instr) { | 1874 HLoadExternalArrayPointer* instr) { |
| 1873 LOperand* input = UseRegisterAtStart(instr->value()); | 1875 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1874 return DefineAsRegister(new LLoadExternalArrayPointer(input)); | 1876 return DefineAsRegister(new LLoadExternalArrayPointer(input)); |
| 1875 } | 1877 } |
| 1876 | 1878 |
| 1877 | 1879 |
| 1878 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1880 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1879 HLoadKeyedFastElement* instr) { | 1881 HLoadKeyedFastElement* instr) { |
| 1880 ASSERT(instr->representation().IsTagged()); | 1882 ASSERT(instr->representation().IsTagged()); |
| 1881 ASSERT(instr->key()->representation().IsInteger32()); | 1883 ASSERT(instr->key()->representation().IsInteger32X()); |
| 1882 LOperand* obj = UseRegisterAtStart(instr->object()); | 1884 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1883 LOperand* key = UseRegisterAtStart(instr->key()); | 1885 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1884 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); | 1886 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1885 return AssignEnvironment(DefineSameAsFirst(result)); | 1887 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1886 } | 1888 } |
| 1887 | 1889 |
| 1888 | 1890 |
| 1889 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( | 1891 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( |
| 1890 HLoadKeyedSpecializedArrayElement* instr) { | 1892 HLoadKeyedSpecializedArrayElement* instr) { |
| 1891 ExternalArrayType array_type = instr->array_type(); | 1893 ExternalArrayType array_type = instr->array_type(); |
| 1892 Representation representation(instr->representation()); | 1894 Representation representation(instr->representation()); |
| 1893 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) || | 1895 ASSERT((representation.IsInteger32X() && array_type != kExternalFloatArray) || |
| 1894 (representation.IsDouble() && array_type == kExternalFloatArray)); | 1896 (representation.IsDouble() && array_type == kExternalFloatArray)); |
| 1895 ASSERT(instr->key()->representation().IsInteger32()); | 1897 ASSERT(instr->key()->representation().IsInteger32X()); |
| 1896 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1898 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1897 LOperand* key = UseRegister(instr->key()); | 1899 LOperand* key = UseRegister(instr->key()); |
| 1898 LLoadKeyedSpecializedArrayElement* result = | 1900 LLoadKeyedSpecializedArrayElement* result = |
| 1899 new LLoadKeyedSpecializedArrayElement(external_pointer, | 1901 new LLoadKeyedSpecializedArrayElement(external_pointer, |
| 1900 key); | 1902 key); |
| 1901 LInstruction* load_instr = DefineAsRegister(result); | 1903 LInstruction* load_instr = DefineAsRegister(result); |
| 1902 // An unsigned int array load might overflow and cause a deopt, make sure it | 1904 // An unsigned int array load might overflow and cause a deopt, make sure it |
| 1903 // has an environment. | 1905 // has an environment. |
| 1904 return (array_type == kExternalUnsignedIntArray) | 1906 return (array_type == kExternalUnsignedIntArray) |
| 1905 ? AssignEnvironment(load_instr) | 1907 ? AssignEnvironment(load_instr) |
| 1906 : load_instr; | 1908 : load_instr; |
| 1907 } | 1909 } |
| 1908 | 1910 |
| 1909 | 1911 |
| 1910 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1912 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1911 LOperand* context = UseFixed(instr->context(), esi); | 1913 LOperand* context = UseFixed(instr->context(), esi); |
| 1912 LOperand* object = UseFixed(instr->object(), edx); | 1914 LOperand* object = UseFixed(instr->object(), edx); |
| 1913 LOperand* key = UseFixed(instr->key(), eax); | 1915 LOperand* key = UseFixed(instr->key(), eax); |
| 1914 | 1916 |
| 1915 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key); | 1917 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key); |
| 1916 return MarkAsCall(DefineFixed(result, eax), instr); | 1918 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1917 } | 1919 } |
| 1918 | 1920 |
| 1919 | 1921 |
| 1920 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( | 1922 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( |
| 1921 HStoreKeyedFastElement* instr) { | 1923 HStoreKeyedFastElement* instr) { |
| 1922 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1924 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1923 ASSERT(instr->value()->representation().IsTagged()); | 1925 ASSERT(instr->value()->representation().IsTagged()); |
| 1924 ASSERT(instr->object()->representation().IsTagged()); | 1926 ASSERT(instr->object()->representation().IsTagged()); |
| 1925 ASSERT(instr->key()->representation().IsInteger32()); | 1927 ASSERT(instr->key()->representation().IsInteger32X()); |
| 1926 | 1928 |
| 1927 LOperand* obj = UseTempRegister(instr->object()); | 1929 LOperand* obj = UseTempRegister(instr->object()); |
| 1928 LOperand* val = needs_write_barrier | 1930 LOperand* val = needs_write_barrier |
| 1929 ? UseTempRegister(instr->value()) | 1931 ? UseTempRegister(instr->value()) |
| 1930 : UseRegisterAtStart(instr->value()); | 1932 : UseRegisterAtStart(instr->value()); |
| 1931 LOperand* key = needs_write_barrier | 1933 LOperand* key = needs_write_barrier |
| 1932 ? UseTempRegister(instr->key()) | 1934 ? UseTempRegister(instr->key()) |
| 1933 : UseRegisterOrConstantAtStart(instr->key()); | 1935 : UseRegisterOrConstantAtStart(instr->key()); |
| 1934 | 1936 |
| 1935 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); | 1937 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); |
| 1936 } | 1938 } |
| 1937 | 1939 |
| 1938 | 1940 |
| 1939 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( | 1941 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( |
| 1940 HStoreKeyedSpecializedArrayElement* instr) { | 1942 HStoreKeyedSpecializedArrayElement* instr) { |
| 1941 Representation representation(instr->value()->representation()); | 1943 Representation representation(instr->value()->representation()); |
| 1942 ExternalArrayType array_type = instr->array_type(); | 1944 ExternalArrayType array_type = instr->array_type(); |
| 1943 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) || | |
| 1944 (representation.IsDouble() && array_type == kExternalFloatArray)); | |
| 1945 ASSERT(instr->external_pointer()->representation().IsExternal()); | 1945 ASSERT(instr->external_pointer()->representation().IsExternal()); |
| 1946 ASSERT(instr->key()->representation().IsInteger32()); | 1946 ASSERT(instr->key()->representation().IsInteger32X()); |
| 1947 | 1947 |
| 1948 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1948 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1949 LOperand* key = UseRegister(instr->key()); | 1949 LOperand* key = UseRegister(instr->key()); |
| 1950 LOperand* temp = NULL; | |
| 1951 | |
| 1952 if (array_type == kExternalPixelArray) { | |
| 1953 // The generated code for pixel array stores requires that the clamped value | |
| 1954 // is in a byte register. eax is an arbitrary choice to satisfy this | |
| 1955 // requirement. | |
| 1956 temp = FixedTemp(eax); | |
| 1957 } | |
| 1958 | 1950 |
| 1959 LOperand* val = NULL; | 1951 LOperand* val = NULL; |
| 1960 if (array_type == kExternalByteArray || | 1952 if (array_type == kExternalByteArray || |
| 1961 array_type == kExternalUnsignedByteArray) { | 1953 array_type == kExternalUnsignedByteArray || |
| 1954 array_type == kExternalPixelArray) { |
| 1962 // We need a byte register in this case for the value. | 1955 // We need a byte register in this case for the value. |
| 1963 val = UseFixed(instr->value(), eax); | 1956 val = UseFixed(instr->value(), eax); |
| 1964 } else { | 1957 } else { |
| 1965 val = UseRegister(instr->value()); | 1958 val = UseRegister(instr->value()); |
| 1966 } | 1959 } |
| 1967 | 1960 |
| 1968 return new LStoreKeyedSpecializedArrayElement(external_pointer, | 1961 return new LStoreKeyedSpecializedArrayElement(external_pointer, |
| 1969 key, | 1962 key, |
| 1970 val, | 1963 val); |
| 1971 temp); | |
| 1972 } | 1964 } |
| 1973 | 1965 |
| 1974 | 1966 |
| 1975 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 1967 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 1976 LOperand* context = UseFixed(instr->context(), esi); | 1968 LOperand* context = UseFixed(instr->context(), esi); |
| 1977 LOperand* object = UseFixed(instr->object(), edx); | 1969 LOperand* object = UseFixed(instr->object(), edx); |
| 1978 LOperand* key = UseFixed(instr->key(), ecx); | 1970 LOperand* key = UseFixed(instr->key(), ecx); |
| 1979 LOperand* value = UseFixed(instr->value(), eax); | 1971 LOperand* value = UseFixed(instr->value(), eax); |
| 1980 | 1972 |
| 1981 ASSERT(instr->object()->representation().IsTagged()); | 1973 ASSERT(instr->object()->representation().IsTagged()); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2197 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2189 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2198 HEnvironment* outer = current_block_->last_environment()->outer(); | 2190 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 2199 current_block_->UpdateEnvironment(outer); | 2191 current_block_->UpdateEnvironment(outer); |
| 2200 return NULL; | 2192 return NULL; |
| 2201 } | 2193 } |
| 2202 | 2194 |
| 2203 | 2195 |
| 2204 } } // namespace v8::internal | 2196 } } // namespace v8::internal |
| 2205 | 2197 |
| 2206 #endif // V8_TARGET_ARCH_IA32 | 2198 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |