MIPS: Increase sanity of integer division handling.

Port r15057 (c82c777)

Original commit message:
- In the INT32 BinaryOpStub, fix type feedback collection for DIV,
bringing it in line with other platforms.
- In Lithium codegen, emit proper inlined code, don't call the stub.
- Drive-by fix: assert appropriate CpuFeaturesScope for SDIV.

BUG=

Review URL: https://codereview.chromium.org/16857004
Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15127 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
palfia@homejinni.com 2013-06-13 16:44:54 +00:00
parent 1d74cfaaf4
commit 9e1c894a9e
2 changed files with 21 additions and 37 deletions

View File

@ -2488,47 +2488,36 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
UNREACHABLE();
}
if (op_ != Token::DIV) {
// These operations produce an integer result.
// Try to return a smi if we can.
// Otherwise return a heap number if allowed, or jump to type
// transition.
if (result_type_ <= BinaryOpIC::INT32) {
Register except_flag = scratch2;
__ EmitFPUTruncate(kRoundToZero,
const FPURoundingMode kRoundingMode = op_ == Token::DIV ?
kRoundToMinusInf : kRoundToZero;
const CheckForInexactConversion kConversion = op_ == Token::DIV ?
kCheckForInexactConversion : kDontCheckForInexactConversion;
__ EmitFPUTruncate(kRoundingMode,
scratch1,
f10,
at,
f16,
except_flag);
if (result_type_ <= BinaryOpIC::INT32) {
// If except_flag != 0, result does not fit in a 32-bit integer.
__ Branch(&transition, ne, except_flag, Operand(zero_reg));
}
// Check if the result fits in a smi.
__ Addu(scratch2, scratch1, Operand(0x40000000));
// If not try to return a heap number.
except_flag,
kConversion);
// If except_flag != 0, result does not fit in a 32-bit integer.
__ Branch(&transition, ne, except_flag, Operand(zero_reg));
// Try to tag the result as a Smi, return heap number on overflow.
__ SmiTagCheckOverflow(scratch1, scratch1, scratch2);
__ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg));
// Check for minus zero. Return heap number for minus zero if
// double results are allowed; otherwise transition.
// Check for minus zero, transition in that case (because we need
// to return a heap number).
Label not_zero;
ASSERT(kSmiTag == 0);
__ Branch(&not_zero, ne, scratch1, Operand(zero_reg));
__ mfc1(scratch2, f11);
__ And(scratch2, scratch2, HeapNumber::kSignMask);
__ Branch(result_type_ <= BinaryOpIC::INT32 ? &transition
: &return_heap_number,
ne,
scratch2,
Operand(zero_reg));
__ Branch(&transition, ne, scratch2, Operand(zero_reg));
__ bind(&not_zero);
// Tag the result and return.
__ Ret(USE_DELAY_SLOT);
__ SmiTag(v0, scratch1); // SmiTag emits one instruction.
} else {
// DIV just falls through to allocating a heap number.
__ mov(v0, scratch1);
}
__ bind(&return_heap_number);

View File

@ -1360,15 +1360,10 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
} else if (instr->representation().IsInteger32()) {
// TODO(1042) The fixed register allocation
// is needed because we call TypeRecordingBinaryOpStub from
// the generated code, which requires registers a0
// and a1 to be used. We should remove that
// when we provide a native implementation.
LOperand* dividend = UseFixed(instr->left(), a0);
LOperand* divisor = UseFixed(instr->right(), a1);
return AssignEnvironment(AssignPointerMap(
DefineFixed(new(zone()) LDivI(dividend, divisor), v0)));
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
LDivI* div = new(zone()) LDivI(dividend, divisor);
return AssignEnvironment(DefineAsRegister(div));
} else {
return DoArithmeticT(Token::DIV, instr);
}