| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); | 699 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); |
| 700 } | 700 } |
| 701 | 701 |
| 702 | 702 |
| 703 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 703 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
| 704 UNREACHABLE(); | 704 UNREACHABLE(); |
| 705 return NULL; | 705 return NULL; |
| 706 } | 706 } |
| 707 | 707 |
| 708 | 708 |
| 709 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { | |
| 710 return AssignEnvironment(new(zone()) LDeoptimize); | |
| 711 } | |
| 712 | |
| 713 | |
| 714 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 709 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 715 return AssignEnvironment(new(zone()) LDeoptimize); | 710 return AssignEnvironment(new(zone()) LDeoptimize); |
| 716 } | 711 } |
| 717 | 712 |
| 718 | 713 |
| 719 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 714 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 720 HBitwiseBinaryOperation* instr) { | 715 HBitwiseBinaryOperation* instr) { |
| 721 if (instr->representation().IsSmiOrTagged()) { | 716 if (instr->representation().IsTagged()) { |
| 722 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 717 ASSERT(instr->left()->representation().IsTagged()); |
| 723 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 718 ASSERT(instr->right()->representation().IsTagged()); |
| 724 | 719 |
| 725 LOperand* left = UseFixed(instr->left(), a1); | 720 LOperand* left = UseFixed(instr->left(), a1); |
| 726 LOperand* right = UseFixed(instr->right(), a0); | 721 LOperand* right = UseFixed(instr->right(), a0); |
| 727 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); | 722 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
| 728 return MarkAsCall(DefineFixed(result, v0), instr); | 723 return MarkAsCall(DefineFixed(result, v0), instr); |
| 729 } | 724 } |
| 730 | 725 |
| 731 ASSERT(instr->representation().IsInteger32()); | 726 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 732 ASSERT(instr->left()->representation().IsInteger32()); | 727 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 733 ASSERT(instr->right()->representation().IsInteger32()); | 728 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 734 LOperand* left = UseRegisterAtStart(instr->left()); | 729 LOperand* left = UseRegisterAtStart(instr->left()); |
| 735 | 730 |
| 736 HValue* right_value = instr->right(); | 731 HValue* right_value = instr->right(); |
| 737 LOperand* right = NULL; | 732 LOperand* right = NULL; |
| 738 int constant_value = 0; | 733 int constant_value = 0; |
| 734 bool does_deopt = false; |
| 739 if (right_value->IsConstant()) { | 735 if (right_value->IsConstant()) { |
| 740 HConstant* constant = HConstant::cast(right_value); | 736 HConstant* constant = HConstant::cast(right_value); |
| 741 right = chunk_->DefineConstantOperand(constant); | 737 right = chunk_->DefineConstantOperand(constant); |
| 742 constant_value = constant->Integer32Value() & 0x1f; | 738 constant_value = constant->Integer32Value() & 0x1f; |
| 739 // Left shifts can deoptimize if we shift by > 0 and the result cannot be |
| 740 // truncated to smi. |
| 741 if (instr->representation().IsSmi() && constant_value > 0) { |
| 742 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 743 if (!it.value()->CheckFlag(HValue::kTruncatingToSmi)) { |
| 744 does_deopt = true; |
| 745 break; |
| 746 } |
| 747 } |
| 748 } |
| 743 } else { | 749 } else { |
| 744 right = UseRegisterAtStart(right_value); | 750 right = UseRegisterAtStart(right_value); |
| 745 } | 751 } |
| 746 | 752 |
| 747 // Shift operations can only deoptimize if we do a logical shift | 753 // Shift operations can deoptimize if we do a logical shift |
| 748 // by 0 and the result cannot be truncated to int32. | 754 // by 0 and the result cannot be truncated to int32. |
| 749 bool does_deopt = false; | |
| 750 if (op == Token::SHR && constant_value == 0) { | 755 if (op == Token::SHR && constant_value == 0) { |
| 751 if (FLAG_opt_safe_uint32_operations) { | 756 if (FLAG_opt_safe_uint32_operations) { |
| 752 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | 757 does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
| 753 } else { | 758 } else { |
| 754 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { | 759 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 755 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { | 760 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { |
| 756 does_deopt = true; | 761 does_deopt = true; |
| 757 break; | 762 break; |
| 758 } | 763 } |
| 759 } | 764 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 781 | 786 |
| 782 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 787 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 783 HArithmeticBinaryOperation* instr) { | 788 HArithmeticBinaryOperation* instr) { |
| 784 ASSERT(op == Token::ADD || | 789 ASSERT(op == Token::ADD || |
| 785 op == Token::DIV || | 790 op == Token::DIV || |
| 786 op == Token::MOD || | 791 op == Token::MOD || |
| 787 op == Token::MUL || | 792 op == Token::MUL || |
| 788 op == Token::SUB); | 793 op == Token::SUB); |
| 789 HValue* left = instr->left(); | 794 HValue* left = instr->left(); |
| 790 HValue* right = instr->right(); | 795 HValue* right = instr->right(); |
| 791 ASSERT(left->representation().IsSmiOrTagged()); | 796 ASSERT(left->representation().IsTagged()); |
| 792 ASSERT(right->representation().IsSmiOrTagged()); | 797 ASSERT(right->representation().IsTagged()); |
| 793 LOperand* left_operand = UseFixed(left, a1); | 798 LOperand* left_operand = UseFixed(left, a1); |
| 794 LOperand* right_operand = UseFixed(right, a0); | 799 LOperand* right_operand = UseFixed(right, a0); |
| 795 LArithmeticT* result = | 800 LArithmeticT* result = |
| 796 new(zone()) LArithmeticT(op, left_operand, right_operand); | 801 new(zone()) LArithmeticT(op, left_operand, right_operand); |
| 797 return MarkAsCall(DefineFixed(result, v0), instr); | 802 return MarkAsCall(DefineFixed(result, v0), instr); |
| 798 } | 803 } |
| 799 | 804 |
| 800 | 805 |
| 801 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 806 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 802 ASSERT(is_building()); | 807 ASSERT(is_building()); |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 return DoShift(Token::SAR, instr); | 1318 return DoShift(Token::SAR, instr); |
| 1314 } | 1319 } |
| 1315 | 1320 |
| 1316 | 1321 |
| 1317 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1322 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1318 return DoShift(Token::SHL, instr); | 1323 return DoShift(Token::SHL, instr); |
| 1319 } | 1324 } |
| 1320 | 1325 |
| 1321 | 1326 |
| 1322 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1327 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1323 if (instr->representation().IsInteger32()) { | 1328 if (instr->representation().IsSmiOrInteger32()) { |
| 1324 ASSERT(instr->left()->representation().IsInteger32()); | 1329 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1325 ASSERT(instr->right()->representation().IsInteger32()); | 1330 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1326 | 1331 |
| 1327 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1332 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1328 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1333 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1329 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1334 return DefineAsRegister(new(zone()) LBitI(left, right)); |
| 1330 } else { | 1335 } else { |
| 1331 ASSERT(instr->representation().IsSmiOrTagged()); | 1336 ASSERT(instr->representation().IsTagged()); |
| 1332 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 1337 ASSERT(instr->left()->representation().IsTagged()); |
| 1333 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 1338 ASSERT(instr->right()->representation().IsTagged()); |
| 1334 | 1339 |
| 1335 LOperand* left = UseFixed(instr->left(), a1); | 1340 LOperand* left = UseFixed(instr->left(), a1); |
| 1336 LOperand* right = UseFixed(instr->right(), a0); | 1341 LOperand* right = UseFixed(instr->right(), a0); |
| 1337 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); | 1342 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
| 1338 return MarkAsCall(DefineFixed(result, v0), instr); | 1343 return MarkAsCall(DefineFixed(result, v0), instr); |
| 1339 } | 1344 } |
| 1340 } | 1345 } |
| 1341 | 1346 |
| 1342 | 1347 |
| 1343 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { | 1348 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
| 1344 ASSERT(instr->value()->representation().IsInteger32()); | 1349 ASSERT(instr->value()->representation().IsInteger32()); |
| 1345 ASSERT(instr->representation().IsInteger32()); | 1350 ASSERT(instr->representation().IsInteger32()); |
| 1346 if (instr->HasNoUses()) return NULL; | 1351 if (instr->HasNoUses()) return NULL; |
| 1347 LOperand* value = UseRegisterAtStart(instr->value()); | 1352 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1348 return DefineAsRegister(new(zone()) LBitNotI(value)); | 1353 return DefineAsRegister(new(zone()) LBitNotI(value)); |
| 1349 } | 1354 } |
| 1350 | 1355 |
| 1351 | 1356 |
| 1352 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1357 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1353 if (instr->representation().IsDouble()) { | 1358 if (instr->representation().IsDouble()) { |
| 1354 return DoArithmeticD(Token::DIV, instr); | 1359 return DoArithmeticD(Token::DIV, instr); |
| 1355 } else if (instr->representation().IsInteger32()) { | 1360 } else if (instr->representation().IsSmiOrInteger32()) { |
| 1361 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1362 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1356 LOperand* dividend = UseRegister(instr->left()); | 1363 LOperand* dividend = UseRegister(instr->left()); |
| 1357 LOperand* divisor = UseRegister(instr->right()); | 1364 LOperand* divisor = UseRegister(instr->right()); |
| 1358 LDivI* div = new(zone()) LDivI(dividend, divisor); | 1365 LDivI* div = new(zone()) LDivI(dividend, divisor); |
| 1359 return AssignEnvironment(DefineAsRegister(div)); | 1366 return AssignEnvironment(DefineAsRegister(div)); |
| 1360 } else { | 1367 } else { |
| 1361 return DoArithmeticT(Token::DIV, instr); | 1368 return DoArithmeticT(Token::DIV, instr); |
| 1362 } | 1369 } |
| 1363 } | 1370 } |
| 1364 | 1371 |
| 1365 | 1372 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 ASSERT(right->IsConstant() && | 1419 ASSERT(right->IsConstant() && |
| 1413 HConstant::cast(right)->HasInteger32Value()); | 1420 HConstant::cast(right)->HasInteger32Value()); |
| 1414 return AssignEnvironment(DefineAsRegister( | 1421 return AssignEnvironment(DefineAsRegister( |
| 1415 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); | 1422 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); |
| 1416 } | 1423 } |
| 1417 | 1424 |
| 1418 | 1425 |
| 1419 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1426 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1420 HValue* left = instr->left(); | 1427 HValue* left = instr->left(); |
| 1421 HValue* right = instr->right(); | 1428 HValue* right = instr->right(); |
| 1422 if (instr->representation().IsInteger32()) { | 1429 if (instr->representation().IsSmiOrInteger32()) { |
| 1423 ASSERT(left->representation().IsInteger32()); | 1430 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1424 ASSERT(right->representation().IsInteger32()); | 1431 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1425 if (instr->HasPowerOf2Divisor()) { | 1432 if (instr->HasPowerOf2Divisor()) { |
| 1426 ASSERT(!right->CanBeZero()); | 1433 ASSERT(!right->CanBeZero()); |
| 1427 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1434 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1428 UseOrConstant(right)); | 1435 UseOrConstant(right)); |
| 1429 LInstruction* result = DefineAsRegister(mod); | 1436 LInstruction* result = DefineAsRegister(mod); |
| 1430 return (left->CanBeNegative() && | 1437 return (left->CanBeNegative() && |
| 1431 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1438 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1432 ? AssignEnvironment(result) | 1439 ? AssignEnvironment(result) |
| 1433 : result; | 1440 : result; |
| 1434 } else if (instr->fixed_right_arg().has_value) { | 1441 } else if (instr->fixed_right_arg().has_value) { |
| 1435 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1442 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1436 UseRegisterAtStart(right)); | 1443 UseRegisterAtStart(right)); |
| 1437 return AssignEnvironment(DefineAsRegister(mod)); | 1444 return AssignEnvironment(DefineAsRegister(mod)); |
| 1438 } else { | 1445 } else { |
| 1439 LModI* mod = new(zone()) LModI(UseRegister(left), | 1446 LModI* mod = new(zone()) LModI(UseRegister(left), |
| 1440 UseRegister(right), | 1447 UseRegister(right), |
| 1441 TempRegister(), | 1448 TempRegister(), |
| 1442 FixedTemp(f20), | 1449 FixedTemp(f20), |
| 1443 FixedTemp(f22)); | 1450 FixedTemp(f22)); |
| 1444 LInstruction* result = DefineAsRegister(mod); | 1451 LInstruction* result = DefineAsRegister(mod); |
| 1445 return (right->CanBeZero() || | 1452 return (right->CanBeZero() || |
| 1446 (left->RangeCanInclude(kMinInt) && | 1453 (left->RangeCanInclude(kMinInt) && |
| 1447 right->RangeCanInclude(-1)) || | 1454 right->RangeCanInclude(-1)) || |
| 1448 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1455 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1449 ? AssignEnvironment(result) | 1456 ? AssignEnvironment(result) |
| 1450 : result; | 1457 : result; |
| 1451 } | 1458 } |
| 1452 } else if (instr->representation().IsSmiOrTagged()) { | 1459 } else if (instr->representation().IsTagged()) { |
| 1453 return DoArithmeticT(Token::MOD, instr); | 1460 return DoArithmeticT(Token::MOD, instr); |
| 1454 } else { | 1461 } else { |
| 1455 ASSERT(instr->representation().IsDouble()); | 1462 ASSERT(instr->representation().IsDouble()); |
| 1456 // We call a C function for double modulo. It can't trigger a GC. We need | 1463 // We call a C function for double modulo. It can't trigger a GC. We need |
| 1457 // to use fixed result register for the call. | 1464 // to use fixed result register for the call. |
| 1458 // TODO(fschneider): Allow any register as input registers. | 1465 // TODO(fschneider): Allow any register as input registers. |
| 1459 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | 1466 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
| 1460 UseFixedDouble(left, f2), | 1467 UseFixedDouble(left, f2), |
| 1461 UseFixedDouble(right, f4)); | 1468 UseFixedDouble(right, f4)); |
| 1462 return MarkAsCall(DefineFixedDouble(mod, f2), instr); | 1469 return MarkAsCall(DefineFixedDouble(mod, f2), instr); |
| 1463 } | 1470 } |
| 1464 } | 1471 } |
| 1465 | 1472 |
| 1466 | 1473 |
| 1467 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1474 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1468 if (instr->representation().IsInteger32()) { | 1475 if (instr->representation().IsSmiOrInteger32()) { |
| 1469 ASSERT(instr->left()->representation().IsInteger32()); | 1476 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1470 ASSERT(instr->right()->representation().IsInteger32()); | 1477 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1471 LOperand* left; | 1478 LOperand* left; |
| 1472 LOperand* right = UseOrConstant(instr->BetterRightOperand()); | 1479 LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
| 1473 LOperand* temp = NULL; | 1480 LOperand* temp = NULL; |
| 1474 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | 1481 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1475 (instr->CheckFlag(HValue::kCanOverflow) || | 1482 (instr->CheckFlag(HValue::kCanOverflow) || |
| 1476 !right->IsConstantOperand())) { | 1483 !right->IsConstantOperand())) { |
| 1477 left = UseRegister(instr->BetterLeftOperand()); | 1484 left = UseRegister(instr->BetterLeftOperand()); |
| 1478 temp = TempRegister(); | 1485 temp = TempRegister(); |
| 1479 } else { | 1486 } else { |
| 1480 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1487 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1503 } | 1510 } |
| 1504 } | 1511 } |
| 1505 return DoArithmeticD(Token::MUL, instr); | 1512 return DoArithmeticD(Token::MUL, instr); |
| 1506 } else { | 1513 } else { |
| 1507 return DoArithmeticT(Token::MUL, instr); | 1514 return DoArithmeticT(Token::MUL, instr); |
| 1508 } | 1515 } |
| 1509 } | 1516 } |
| 1510 | 1517 |
| 1511 | 1518 |
| 1512 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1519 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1513 if (instr->representation().IsInteger32()) { | 1520 if (instr->representation().IsSmiOrInteger32()) { |
| 1514 ASSERT(instr->left()->representation().IsInteger32()); | 1521 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1515 ASSERT(instr->right()->representation().IsInteger32()); | 1522 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1516 LOperand* left = UseRegisterAtStart(instr->left()); | 1523 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1517 LOperand* right = UseOrConstantAtStart(instr->right()); | 1524 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1518 LSubI* sub = new(zone()) LSubI(left, right); | 1525 LSubI* sub = new(zone()) LSubI(left, right); |
| 1519 LInstruction* result = DefineAsRegister(sub); | 1526 LInstruction* result = DefineAsRegister(sub); |
| 1520 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1527 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1521 result = AssignEnvironment(result); | 1528 result = AssignEnvironment(result); |
| 1522 } | 1529 } |
| 1523 return result; | 1530 return result; |
| 1524 } else if (instr->representation().IsDouble()) { | 1531 } else if (instr->representation().IsDouble()) { |
| 1525 return DoArithmeticD(Token::SUB, instr); | 1532 return DoArithmeticD(Token::SUB, instr); |
| 1526 } else { | 1533 } else { |
| 1527 return DoArithmeticT(Token::SUB, instr); | 1534 return DoArithmeticT(Token::SUB, instr); |
| 1528 } | 1535 } |
| 1529 } | 1536 } |
| 1530 | 1537 |
| 1531 | 1538 |
| 1532 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { | 1539 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { |
| 1533 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | 1540 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); |
| 1534 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | 1541 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); |
| 1535 LOperand* addend_op = UseRegisterAtStart(addend); | 1542 LOperand* addend_op = UseRegisterAtStart(addend); |
| 1536 return DefineSameAsFirst(new(zone()) LMultiplyAddD(addend_op, multiplier_op, | 1543 return DefineSameAsFirst(new(zone()) LMultiplyAddD(addend_op, multiplier_op, |
| 1537 multiplicand_op)); | 1544 multiplicand_op)); |
| 1538 } | 1545 } |
| 1539 | 1546 |
| 1540 | 1547 |
| 1541 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1548 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1542 if (instr->representation().IsInteger32()) { | 1549 if (instr->representation().IsSmiOrInteger32()) { |
| 1543 ASSERT(instr->left()->representation().IsInteger32()); | 1550 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1544 ASSERT(instr->right()->representation().IsInteger32()); | 1551 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1545 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1552 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1546 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1553 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1547 LAddI* add = new(zone()) LAddI(left, right); | 1554 LAddI* add = new(zone()) LAddI(left, right); |
| 1548 LInstruction* result = DefineAsRegister(add); | 1555 LInstruction* result = DefineAsRegister(add); |
| 1549 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1556 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1550 result = AssignEnvironment(result); | 1557 result = AssignEnvironment(result); |
| 1551 } | 1558 } |
| 1552 return result; | 1559 return result; |
| 1553 } else if (instr->representation().IsDouble()) { | 1560 } else if (instr->representation().IsDouble()) { |
| 1554 if (kArchVariant == kMips32r2) { | 1561 if (kArchVariant == kMips32r2) { |
| 1555 if (instr->left()->IsMul()) | 1562 if (instr->left()->IsMul()) |
| 1556 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1563 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
| 1557 | 1564 |
| 1558 if (instr->right()->IsMul()) { | 1565 if (instr->right()->IsMul()) { |
| 1559 ASSERT(!instr->left()->IsMul()); | 1566 ASSERT(!instr->left()->IsMul()); |
| 1560 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1567 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
| 1561 } | 1568 } |
| 1562 } | 1569 } |
| 1563 return DoArithmeticD(Token::ADD, instr); | 1570 return DoArithmeticD(Token::ADD, instr); |
| 1564 } else { | 1571 } else { |
| 1565 ASSERT(instr->representation().IsSmiOrTagged()); | 1572 ASSERT(instr->representation().IsTagged()); |
| 1566 return DoArithmeticT(Token::ADD, instr); | 1573 return DoArithmeticT(Token::ADD, instr); |
| 1567 } | 1574 } |
| 1568 } | 1575 } |
| 1569 | 1576 |
| 1570 | 1577 |
| 1571 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1578 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1572 LOperand* left = NULL; | 1579 LOperand* left = NULL; |
| 1573 LOperand* right = NULL; | 1580 LOperand* right = NULL; |
| 1574 if (instr->representation().IsInteger32()) { | 1581 if (instr->representation().IsSmiOrInteger32()) { |
| 1575 ASSERT(instr->left()->representation().IsInteger32()); | 1582 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1576 ASSERT(instr->right()->representation().IsInteger32()); | 1583 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1577 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1584 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1578 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1585 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1579 } else { | 1586 } else { |
| 1580 ASSERT(instr->representation().IsDouble()); | 1587 ASSERT(instr->representation().IsDouble()); |
| 1581 ASSERT(instr->left()->representation().IsDouble()); | 1588 ASSERT(instr->left()->representation().IsDouble()); |
| 1582 ASSERT(instr->right()->representation().IsDouble()); | 1589 ASSERT(instr->right()->representation().IsDouble()); |
| 1583 left = UseRegisterAtStart(instr->left()); | 1590 left = UseRegisterAtStart(instr->left()); |
| 1584 right = UseRegisterAtStart(instr->right()); | 1591 right = UseRegisterAtStart(instr->right()); |
| 1585 } | 1592 } |
| 1586 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); | 1593 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 | 1652 |
| 1646 | 1653 |
| 1647 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1654 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1648 HCompareObjectEqAndBranch* instr) { | 1655 HCompareObjectEqAndBranch* instr) { |
| 1649 LOperand* left = UseRegisterAtStart(instr->left()); | 1656 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1650 LOperand* right = UseRegisterAtStart(instr->right()); | 1657 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1651 return new(zone()) LCmpObjectEqAndBranch(left, right); | 1658 return new(zone()) LCmpObjectEqAndBranch(left, right); |
| 1652 } | 1659 } |
| 1653 | 1660 |
| 1654 | 1661 |
| 1655 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( | |
| 1656 HCompareConstantEqAndBranch* instr) { | |
| 1657 return new(zone()) LCmpConstantEqAndBranch( | |
| 1658 UseRegisterAtStart(instr->value())); | |
| 1659 } | |
| 1660 | |
| 1661 | |
| 1662 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { | 1662 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
| 1663 ASSERT(instr->value()->representation().IsTagged()); | 1663 ASSERT(instr->value()->representation().IsTagged()); |
| 1664 LOperand* temp = TempRegister(); | 1664 LOperand* temp = TempRegister(); |
| 1665 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()), | 1665 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()), |
| 1666 temp); | 1666 temp); |
| 1667 } | 1667 } |
| 1668 | 1668 |
| 1669 | 1669 |
| 1670 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1670 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
| 1671 ASSERT(instr->value()->representation().IsTagged()); | 1671 ASSERT(instr->value()->representation().IsTagged()); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1949 | 1949 |
| 1950 | 1950 |
| 1951 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1951 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 1952 LOperand* value = UseRegisterAtStart(instr->value()); | 1952 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1953 LInstruction* result = new(zone()) LCheckInstanceType(value); | 1953 LInstruction* result = new(zone()) LCheckInstanceType(value); |
| 1954 return AssignEnvironment(result); | 1954 return AssignEnvironment(result); |
| 1955 } | 1955 } |
| 1956 | 1956 |
| 1957 | 1957 |
| 1958 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 1958 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
| 1959 LUnallocated* temp1 = TempRegister(); | 1959 LUnallocated* temp1 = NULL; |
| 1960 LOperand* temp2 = TempRegister(); | 1960 LOperand* temp2 = NULL; |
| 1961 if (!instr->CanOmitPrototypeChecks()) { |
| 1962 temp1 = TempRegister(); |
| 1963 temp2 = TempRegister(); |
| 1964 } |
| 1961 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); | 1965 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); |
| 1966 if (instr->CanOmitPrototypeChecks()) return result; |
| 1962 return AssignEnvironment(result); | 1967 return AssignEnvironment(result); |
| 1963 } | 1968 } |
| 1964 | 1969 |
| 1965 | 1970 |
| 1966 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { | 1971 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { |
| 1967 LOperand* value = UseRegisterAtStart(instr->value()); | 1972 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1968 return AssignEnvironment(new(zone()) LCheckFunction(value)); | 1973 return AssignEnvironment(new(zone()) LCheckFunction(value)); |
| 1969 } | 1974 } |
| 1970 | 1975 |
| 1971 | 1976 |
| 1972 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1977 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
| 1973 LOperand* value = UseRegisterAtStart(instr->value()); | 1978 LOperand* value = NULL; |
| 1979 if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value()); |
| 1974 LInstruction* result = new(zone()) LCheckMaps(value); | 1980 LInstruction* result = new(zone()) LCheckMaps(value); |
| 1981 if (instr->CanOmitMapChecks()) return result; |
| 1975 return AssignEnvironment(result); | 1982 return AssignEnvironment(result); |
| 1976 } | 1983 } |
| 1977 | 1984 |
| 1978 | 1985 |
| 1979 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1986 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 1980 HValue* value = instr->value(); | 1987 HValue* value = instr->value(); |
| 1981 Representation input_rep = value->representation(); | 1988 Representation input_rep = value->representation(); |
| 1982 LOperand* reg = UseRegister(value); | 1989 LOperand* reg = UseRegister(value); |
| 1983 if (input_rep.IsDouble()) { | 1990 if (input_rep.IsDouble()) { |
| 1984 // Revisit this decision, here and 8 lines below. | 1991 // Revisit this decision, here and 8 lines below. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 | 2128 |
| 2122 | 2129 |
| 2123 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | 2130 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
| 2124 HLoadExternalArrayPointer* instr) { | 2131 HLoadExternalArrayPointer* instr) { |
| 2125 LOperand* input = UseRegisterAtStart(instr->value()); | 2132 LOperand* input = UseRegisterAtStart(instr->value()); |
| 2126 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); | 2133 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); |
| 2127 } | 2134 } |
| 2128 | 2135 |
| 2129 | 2136 |
| 2130 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2137 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2131 ASSERT(instr->key()->representation().IsInteger32() || | 2138 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
| 2132 instr->key()->representation().IsSmi()); | |
| 2133 ElementsKind elements_kind = instr->elements_kind(); | 2139 ElementsKind elements_kind = instr->elements_kind(); |
| 2134 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2140 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2135 LLoadKeyed* result = NULL; | 2141 LLoadKeyed* result = NULL; |
| 2136 | 2142 |
| 2137 if (!instr->is_external()) { | 2143 if (!instr->is_external()) { |
| 2138 LOperand* obj = NULL; | 2144 LOperand* obj = NULL; |
| 2139 if (instr->representation().IsDouble()) { | 2145 if (instr->representation().IsDouble()) { |
| 2140 obj = UseTempRegister(instr->elements()); | 2146 obj = UseTempRegister(instr->elements()); |
| 2141 } else { | 2147 } else { |
| 2142 ASSERT(instr->representation().IsSmiOrTagged()); | 2148 ASSERT(instr->representation().IsSmiOrTagged()); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); | 2238 return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); |
| 2233 } | 2239 } |
| 2234 | 2240 |
| 2235 | 2241 |
| 2236 LInstruction* LChunkBuilder::DoTransitionElementsKind( | 2242 LInstruction* LChunkBuilder::DoTransitionElementsKind( |
| 2237 HTransitionElementsKind* instr) { | 2243 HTransitionElementsKind* instr) { |
| 2238 LOperand* object = UseRegister(instr->object()); | 2244 LOperand* object = UseRegister(instr->object()); |
| 2239 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2245 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
| 2240 LOperand* new_map_reg = TempRegister(); | 2246 LOperand* new_map_reg = TempRegister(); |
| 2241 LTransitionElementsKind* result = | 2247 LTransitionElementsKind* result = |
| 2242 new(zone()) LTransitionElementsKind(object, new_map_reg, NULL); | 2248 new(zone()) LTransitionElementsKind(object, new_map_reg); |
| 2243 return result; | 2249 return result; |
| 2244 } else if (FLAG_compiled_transitions) { | 2250 } else { |
| 2245 LTransitionElementsKind* result = | 2251 LTransitionElementsKind* result = |
| 2246 new(zone()) LTransitionElementsKind(object, NULL, NULL); | 2252 new(zone()) LTransitionElementsKind(object, NULL); |
| 2247 return AssignPointerMap(result); | 2253 return AssignPointerMap(result); |
| 2248 } else { | |
| 2249 LOperand* object = UseFixed(instr->object(), a0); | |
| 2250 LOperand* fixed_object_reg = FixedTemp(a2); | |
| 2251 LOperand* new_map_reg = FixedTemp(a3); | |
| 2252 LTransitionElementsKind* result = | |
| 2253 new(zone()) LTransitionElementsKind(object, | |
| 2254 new_map_reg, | |
| 2255 fixed_object_reg); | |
| 2256 return MarkAsCall(result, instr); | |
| 2257 } | 2254 } |
| 2258 } | 2255 } |
| 2259 | 2256 |
| 2260 | 2257 |
| 2261 LInstruction* LChunkBuilder::DoTrapAllocationMemento( | 2258 LInstruction* LChunkBuilder::DoTrapAllocationMemento( |
| 2262 HTrapAllocationMemento* instr) { | 2259 HTrapAllocationMemento* instr) { |
| 2263 LOperand* object = UseRegister(instr->object()); | 2260 LOperand* object = UseRegister(instr->object()); |
| 2264 LOperand* temp = TempRegister(); | 2261 LOperand* temp = TempRegister(); |
| 2265 LTrapAllocationMemento* result = | 2262 LTrapAllocationMemento* result = |
| 2266 new(zone()) LTrapAllocationMemento(object, temp); | 2263 new(zone()) LTrapAllocationMemento(object, temp); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2563 | 2560 |
| 2564 | 2561 |
| 2565 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2562 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2566 LOperand* object = UseRegister(instr->object()); | 2563 LOperand* object = UseRegister(instr->object()); |
| 2567 LOperand* index = UseRegister(instr->index()); | 2564 LOperand* index = UseRegister(instr->index()); |
| 2568 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2565 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2569 } | 2566 } |
| 2570 | 2567 |
| 2571 | 2568 |
| 2572 } } // namespace v8::internal | 2569 } } // namespace v8::internal |
| OLD | NEW |