Commit 3afe4700 authored by kasperl@chromium.org's avatar kasperl@chromium.org

Improve generated code for non-smi bit operations by

converting the operands to 32-bit ints directly in the 
machine code stub instead of just checking if the heap 
numbers really just represent 32-bit ints and going
through the runtime system in that case.
Review URL: http://codereview.chromium.org/21536

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1330 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent aeafc3bb
......@@ -1614,6 +1614,14 @@ void Assembler::fistp_s(const Operand& adr) {
}
void Assembler::fisttp_d(const Operand& adr) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xDD);
emit_operand(ecx, adr);
}
void Assembler::fist_s(const Operand& adr) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......@@ -1809,6 +1817,14 @@ void Assembler::frndint() {
}
void Assembler::fnclex() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xDB);
EMIT(0xE2);
}
void Assembler::sahf() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -635,6 +635,8 @@ class Assembler : public Malloced {
void fistp_s(const Operand& adr);
void fistp_d(const Operand& adr);
void fisttp_d(const Operand& adr);
void fabs();
void fchs();
......@@ -663,6 +665,7 @@ class Assembler : public Malloced {
void fcompp();
void fnstsw_ax();
void fwait();
void fnclex();
void frndint();
......
......@@ -4482,31 +4482,63 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
FloatingPointHelper::LoadFloatOperands(masm, ecx);
Label non_int32_operands, non_smi_result, skip_allocation;
// Reserve space for converted numbers.
__ sub(Operand(esp), Immediate(2 * kPointerSize));
Label non_smi_result, skip_allocation, operands_too_large;
// Make sure that the operands can be truncated into 64-bit
// integers. Otherwise, the fistt instruction will signal an IA
// exception which will cause us to overwrite the operand with
// zero.
__ push(Immediate(0x7fffffff));
__ push(Immediate(-1));
__ fild_d(Operand(esp, 0));
__ add(Operand(esp), Immediate(2 * kPointerSize));
// Check if right operand is int32.
__ fist_s(Operand(esp, 1 * kPointerSize));
__ fild_s(Operand(esp, 1 * kPointerSize));
__ fucompp();
// Convert the operands to absolute values before comparing
// against the limit.
__ fld(2);
__ fabs();
__ fld(2);
__ fabs();
// Do the comparison. If the operands are too large we go
// slow-case through the runtime system.
__ fucomp(2);
__ fnstsw_ax();
__ sahf();
__ j(not_zero, &non_int32_operands);
__ j(parity_even, &non_int32_operands);
// Check if left operand is int32.
__ fist_s(Operand(esp, 0 * kPointerSize));
__ fild_s(Operand(esp, 0 * kPointerSize));
__ j(above, &operands_too_large);
__ fucompp();
__ fnstsw_ax();
__ sahf();
__ j(not_zero, &non_int32_operands);
__ j(parity_even, &non_int32_operands);
__ j(above, &operands_too_large);
// Reserve space for converted numbers.
__ sub(Operand(esp), Immediate(4 * kPointerSize));
// Convert right operand to int32.
Label done_right;
__ fnclex();
__ fisttp_d(Operand(esp, 2 * kPointerSize));
__ fnstsw_ax();
__ test(eax, Immediate(1));
__ j(zero, &done_right);
__ fnclex();
__ mov(Operand(esp, 2 * kPointerSize), Immediate(0));
__ bind(&done_right);
// Convert left operand to int32.
Label done_left;
__ fisttp_d(Operand(esp, 0 * kPointerSize));
__ fnstsw_ax();
__ test(eax, Immediate(1));
__ j(zero, &done_left);
__ mov(Operand(esp, 0 * kPointerSize), Immediate(0));
__ bind(&done_left);
// Get int32 operands and perform bitop.
__ pop(eax);
__ add(Operand(esp), Immediate(kPointerSize));
__ pop(ecx);
__ add(Operand(esp), Immediate(kPointerSize));
switch (op_) {
case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
......@@ -4554,10 +4586,11 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
__ ret(2 * kPointerSize);
}
__ bind(&non_int32_operands);
// Restore stacks and operands before calling runtime.
// Free ST(0) and ST(1) before calling runtime.
__ bind(&operands_too_large);
__ ffree(0);
__ add(Operand(esp), Immediate(2 * kPointerSize));
__ ffree(1);
// SHR should return uint32 - go to runtime for non-smi/negative result.
if (op_ == Token::SHR) __ bind(&non_smi_result);
......
......@@ -78,3 +78,95 @@ assertEquals(1, toInt32(-4294967295.75));
assertEquals(1294967296, toInt32(-3000000000.25));
assertEquals(1294967296, toInt32(-3000000000.5));
assertEquals(1294967296, toInt32(-3000000000.75));
var base = Math.pow(2, 64);
assertEquals(0, toInt32(base + 0));
assertEquals(0, toInt32(base + 1117));
assertEquals(4096, toInt32(base + 2234));
assertEquals(4096, toInt32(base + 3351));
assertEquals(4096, toInt32(base + 4468));
assertEquals(4096, toInt32(base + 5585));
assertEquals(8192, toInt32(base + 6702));
assertEquals(8192, toInt32(base + 7819));
assertEquals(8192, toInt32(base + 8936));
assertEquals(8192, toInt32(base + 10053));
assertEquals(12288, toInt32(base + 11170));
assertEquals(12288, toInt32(base + 12287));
assertEquals(12288, toInt32(base + 13404));
assertEquals(16384, toInt32(base + 14521));
assertEquals(16384, toInt32(base + 15638));
assertEquals(16384, toInt32(base + 16755));
assertEquals(16384, toInt32(base + 17872));
assertEquals(20480, toInt32(base + 18989));
assertEquals(20480, toInt32(base + 20106));
assertEquals(20480, toInt32(base + 21223));
assertEquals(20480, toInt32(base + 22340));
assertEquals(24576, toInt32(base + 23457));
assertEquals(24576, toInt32(base + 24574));
assertEquals(24576, toInt32(base + 25691));
assertEquals(28672, toInt32(base + 26808));
assertEquals(28672, toInt32(base + 27925));
assertEquals(28672, toInt32(base + 29042));
assertEquals(28672, toInt32(base + 30159));
assertEquals(32768, toInt32(base + 31276));
assertEquals(32768, toInt32(base + 32393));
assertEquals(32768, toInt32(base + 33510));
assertEquals(32768, toInt32(base + 34627));
assertEquals(36864, toInt32(base + 35744));
assertEquals(36864, toInt32(base + 36861));
assertEquals(36864, toInt32(base + 37978));
assertEquals(40960, toInt32(base + 39095));
assertEquals(40960, toInt32(base + 40212));
assertEquals(40960, toInt32(base + 41329));
assertEquals(40960, toInt32(base + 42446));
assertEquals(45056, toInt32(base + 43563));
assertEquals(45056, toInt32(base + 44680));
assertEquals(45056, toInt32(base + 45797));
assertEquals(45056, toInt32(base + 46914));
assertEquals(49152, toInt32(base + 48031));
assertEquals(49152, toInt32(base + 49148));
assertEquals(49152, toInt32(base + 50265));
assertEquals(53248, toInt32(base + 51382));
assertEquals(53248, toInt32(base + 52499));
assertEquals(53248, toInt32(base + 53616));
assertEquals(53248, toInt32(base + 54733));
assertEquals(57344, toInt32(base + 55850));
assertEquals(57344, toInt32(base + 56967));
assertEquals(57344, toInt32(base + 58084));
assertEquals(57344, toInt32(base + 59201));
assertEquals(61440, toInt32(base + 60318));
assertEquals(61440, toInt32(base + 61435));
assertEquals(61440, toInt32(base + 62552));
assertEquals(65536, toInt32(base + 63669));
assertEquals(65536, toInt32(base + 64786));
assertEquals(65536, toInt32(base + 65903));
assertEquals(65536, toInt32(base + 67020));
assertEquals(69632, toInt32(base + 68137));
assertEquals(69632, toInt32(base + 69254));
assertEquals(69632, toInt32(base + 70371));
assertEquals(69632, toInt32(base + 71488));
assertEquals(73728, toInt32(base + 72605));
assertEquals(73728, toInt32(base + 73722));
assertEquals(73728, toInt32(base + 74839));
assertEquals(77824, toInt32(base + 75956));
assertEquals(77824, toInt32(base + 77073));
assertEquals(77824, toInt32(base + 78190));
assertEquals(77824, toInt32(base + 79307));
assertEquals(81920, toInt32(base + 80424));
assertEquals(81920, toInt32(base + 81541));
assertEquals(81920, toInt32(base + 82658));
assertEquals(81920, toInt32(base + 83775));
assertEquals(86016, toInt32(base + 84892));
assertEquals(86016, toInt32(base + 86009));
assertEquals(86016, toInt32(base + 87126));
assertEquals(90112, toInt32(base + 88243));
assertEquals(90112, toInt32(base + 89360));
assertEquals(90112, toInt32(base + 90477));
assertEquals(90112, toInt32(base + 91594));
assertEquals(94208, toInt32(base + 92711));
assertEquals(94208, toInt32(base + 93828));
assertEquals(94208, toInt32(base + 94945));
assertEquals(94208, toInt32(base + 96062));
assertEquals(98304, toInt32(base + 97179));
assertEquals(98304, toInt32(base + 98296));
assertEquals(98304, toInt32(base + 99413));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment