| 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 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 } | 1396 } |
| 1397 | 1397 |
| 1398 | 1398 |
| 1399 void LCodeGen::DoMulI(LMulI* instr) { | 1399 void LCodeGen::DoMulI(LMulI* instr) { |
| 1400 Register scratch = scratch0(); | 1400 Register scratch = scratch0(); |
| 1401 Register result = ToRegister(instr->result()); | 1401 Register result = ToRegister(instr->result()); |
| 1402 // Note that result may alias left. | 1402 // Note that result may alias left. |
| 1403 Register left = ToRegister(instr->left()); | 1403 Register left = ToRegister(instr->left()); |
| 1404 LOperand* right_op = instr->right(); | 1404 LOperand* right_op = instr->right(); |
| 1405 | 1405 |
| 1406 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | |
| 1407 bool bailout_on_minus_zero = | 1406 bool bailout_on_minus_zero = |
| 1408 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1407 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1408 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1409 | 1409 |
| 1410 if (right_op->IsConstantOperand() && !can_overflow) { | 1410 if (right_op->IsConstantOperand()) { |
| 1411 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1411 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1412 | 1412 |
| 1413 if (bailout_on_minus_zero && (constant < 0)) { | 1413 if (bailout_on_minus_zero && (constant < 0)) { |
| 1414 // The case of a null constant will be handled separately. | 1414 // The case of a null constant will be handled separately. |
| 1415 // If constant is negative and left is null, the result should be -0. | 1415 // If constant is negative and left is null, the result should be -0. |
| 1416 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1416 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
| 1417 } | 1417 } |
| 1418 | 1418 |
| 1419 switch (constant) { | 1419 switch (constant) { |
| 1420 case -1: | 1420 case -1: |
| 1421 __ Subu(result, zero_reg, left); | 1421 if (overflow) { |
| 1422 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
| 1423 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
| 1424 } else { |
| 1425 __ Subu(result, zero_reg, left); |
| 1426 } |
| 1422 break; | 1427 break; |
| 1423 case 0: | 1428 case 0: |
| 1424 if (bailout_on_minus_zero) { | 1429 if (bailout_on_minus_zero) { |
| 1425 // If left is strictly negative and the constant is null, the | 1430 // If left is strictly negative and the constant is null, the |
| 1426 // result is -0. Deoptimize if required, otherwise return 0. | 1431 // result is -0. Deoptimize if required, otherwise return 0. |
| 1427 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); | 1432 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); |
| 1428 } | 1433 } |
| 1429 __ mov(result, zero_reg); | 1434 __ mov(result, zero_reg); |
| 1430 break; | 1435 break; |
| 1431 case 1: | 1436 case 1: |
| 1432 // Nothing to do. | 1437 // Nothing to do. |
| 1433 __ Move(result, left); | 1438 __ Move(result, left); |
| 1434 break; | 1439 break; |
| 1435 default: | 1440 default: |
| 1436 // Multiplying by powers of two and powers of two plus or minus | 1441 // Multiplying by powers of two and powers of two plus or minus |
| 1437 // one can be done faster with shifted operands. | 1442 // one can be done faster with shifted operands. |
| 1438 // For other constants we emit standard code. | 1443 // For other constants we emit standard code. |
| 1439 int32_t mask = constant >> 31; | 1444 int32_t mask = constant >> 31; |
| 1440 uint32_t constant_abs = (constant + mask) ^ mask; | 1445 uint32_t constant_abs = (constant + mask) ^ mask; |
| 1441 | 1446 |
| 1442 if (IsPowerOf2(constant_abs) || | 1447 if (IsPowerOf2(constant_abs)) { |
| 1443 IsPowerOf2(constant_abs - 1) || | 1448 int32_t shift = WhichPowerOf2(constant_abs); |
| 1444 IsPowerOf2(constant_abs + 1)) { | 1449 __ sll(result, left, shift); |
| 1445 if (IsPowerOf2(constant_abs)) { | 1450 // Correct the sign of the result if the constant is negative. |
| 1446 int32_t shift = WhichPowerOf2(constant_abs); | 1451 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1447 __ sll(result, left, shift); | 1452 } else if (IsPowerOf2(constant_abs - 1)) { |
| 1448 } else if (IsPowerOf2(constant_abs - 1)) { | 1453 int32_t shift = WhichPowerOf2(constant_abs - 1); |
| 1449 int32_t shift = WhichPowerOf2(constant_abs - 1); | 1454 __ sll(scratch, left, shift); |
| 1450 __ sll(scratch, left, shift); | 1455 __ Addu(result, scratch, left); |
| 1451 __ Addu(result, scratch, left); | 1456 // Correct the sign of the result if the constant is negative. |
| 1452 } else if (IsPowerOf2(constant_abs + 1)) { | 1457 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1453 int32_t shift = WhichPowerOf2(constant_abs + 1); | 1458 } else if (IsPowerOf2(constant_abs + 1)) { |
| 1454 __ sll(scratch, left, shift); | 1459 int32_t shift = WhichPowerOf2(constant_abs + 1); |
| 1455 __ Subu(result, scratch, left); | 1460 __ sll(scratch, left, shift); |
| 1456 } | 1461 __ Subu(result, scratch, left); |
| 1457 | 1462 // Correct the sign of the result if the constant is negative. |
| 1458 // Correct the sign of the result is the constant is negative. | 1463 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1459 if (constant < 0) { | |
| 1460 __ Subu(result, zero_reg, result); | |
| 1461 } | |
| 1462 | |
| 1463 } else { | 1464 } else { |
| 1464 // Generate standard code. | 1465 // Generate standard code. |
| 1465 __ li(at, constant); | 1466 __ li(at, constant); |
| 1466 __ Mul(result, left, at); | 1467 __ Mul(result, left, at); |
| 1467 } | 1468 } |
| 1468 } | 1469 } |
| 1469 | 1470 |
| 1470 } else { | 1471 } else { |
| 1471 Register right = EmitLoadRegister(right_op, scratch); | 1472 ASSERT(right_op->IsRegister()); |
| 1472 if (bailout_on_minus_zero) { | 1473 Register right = ToRegister(right_op); |
| 1473 __ Or(ToRegister(instr->temp()), left, right); | |
| 1474 } | |
| 1475 | 1474 |
| 1476 if (can_overflow) { | 1475 if (overflow) { |
| 1477 // hi:lo = left * right. | 1476 // hi:lo = left * right. |
| 1478 if (instr->hydrogen()->representation().IsSmi()) { | 1477 if (instr->hydrogen()->representation().IsSmi()) { |
| 1479 __ SmiUntag(result, left); | 1478 __ SmiUntag(result, left); |
| 1480 __ mult(result, right); | 1479 __ mult(result, right); |
| 1481 __ mfhi(scratch); | 1480 __ mfhi(scratch); |
| 1482 __ mflo(result); | 1481 __ mflo(result); |
| 1483 } else { | 1482 } else { |
| 1484 __ mult(left, right); | 1483 __ mult(left, right); |
| 1485 __ mfhi(scratch); | 1484 __ mfhi(scratch); |
| 1486 __ mflo(result); | 1485 __ mflo(result); |
| 1487 } | 1486 } |
| 1488 __ sra(at, result, 31); | 1487 __ sra(at, result, 31); |
| 1489 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1488 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 1490 } else { | 1489 } else { |
| 1491 if (instr->hydrogen()->representation().IsSmi()) { | 1490 if (instr->hydrogen()->representation().IsSmi()) { |
| 1492 __ SmiUntag(result, left); | 1491 __ SmiUntag(result, left); |
| 1493 __ Mul(result, result, right); | 1492 __ Mul(result, result, right); |
| 1494 } else { | 1493 } else { |
| 1495 __ Mul(result, left, right); | 1494 __ Mul(result, left, right); |
| 1496 } | 1495 } |
| 1497 } | 1496 } |
| 1498 | 1497 |
| 1499 if (bailout_on_minus_zero) { | 1498 if (bailout_on_minus_zero) { |
| 1500 // Bail out if the result is supposed to be negative zero. | |
| 1501 Label done; | 1499 Label done; |
| 1502 __ Branch(&done, ne, result, Operand(zero_reg)); | 1500 __ Xor(at, left, right); |
| 1503 DeoptimizeIf(lt, | 1501 __ Branch(&done, ge, at, Operand(zero_reg)); |
| 1502 // Bail out if the result is minus zero. |
| 1503 DeoptimizeIf(eq, |
| 1504 instr->environment(), | 1504 instr->environment(), |
| 1505 ToRegister(instr->temp()), | 1505 result, |
| 1506 Operand(zero_reg)); | 1506 Operand(zero_reg)); |
| 1507 __ bind(&done); | 1507 __ bind(&done); |
| 1508 } | 1508 } |
| 1509 } | 1509 } |
| 1510 } | 1510 } |
| 1511 | 1511 |
| 1512 | 1512 |
| 1513 void LCodeGen::DoBitI(LBitI* instr) { | 1513 void LCodeGen::DoBitI(LBitI* instr) { |
| 1514 LOperand* left_op = instr->left(); | 1514 LOperand* left_op = instr->left(); |
| 1515 LOperand* right_op = instr->right(); | 1515 LOperand* right_op = instr->right(); |
| (...skipping 4252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5768 __ Subu(scratch, result, scratch); | 5768 __ Subu(scratch, result, scratch); |
| 5769 __ lw(result, FieldMemOperand(scratch, | 5769 __ lw(result, FieldMemOperand(scratch, |
| 5770 FixedArray::kHeaderSize - kPointerSize)); | 5770 FixedArray::kHeaderSize - kPointerSize)); |
| 5771 __ bind(&done); | 5771 __ bind(&done); |
| 5772 } | 5772 } |
| 5773 | 5773 |
| 5774 | 5774 |
| 5775 #undef __ | 5775 #undef __ |
| 5776 | 5776 |
| 5777 } } // namespace v8::internal | 5777 } } // namespace v8::internal |
| OLD | NEW |