| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 3939)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -889,69 +889,103 @@
|
| void DeferredInlineBinaryOperation::Generate() {
|
| Label done;
|
| if (CpuFeatures::IsSupported(SSE2) && ((op_ == Token::ADD) ||
|
| - (op_ ==Token::SUB) ||
|
| + (op_ == Token::SUB) ||
|
| (op_ == Token::MUL) ||
|
| (op_ == Token::DIV))) {
|
| CpuFeatures::Scope use_sse2(SSE2);
|
| Label call_runtime, after_alloc_failure;
|
| - Label left_smi, right_smi, load_right, do_op;
|
| - __ test(left_, Immediate(kSmiTagMask));
|
| - __ j(zero, &left_smi);
|
| - __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
|
| - Factory::heap_number_map());
|
| - __ j(not_equal, &call_runtime);
|
| - __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
|
| - if (mode_ == OVERWRITE_LEFT) {
|
| - __ mov(dst_, left_);
|
| - }
|
| - __ jmp(&load_right);
|
| + Label left_smi, right_smi, load_right, do_op, allocate_dst;
|
| + if (left_.is(right_)) {
|
| + __ test(left_, Immediate(kSmiTagMask));
|
| + __ j(zero, &left_smi);
|
| + __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
|
| + Factory::heap_number_map());
|
| + __ j(not_equal, &call_runtime);
|
| + __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
|
| + if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) {
|
| + __ mov(dst_, left_);
|
| + __ jmp(&do_op);
|
| + } else {
|
| + __ jmp(&allocate_dst);
|
| + }
|
|
|
| - __ bind(&left_smi);
|
| - __ SmiUntag(left_);
|
| - __ cvtsi2sd(xmm0, Operand(left_));
|
| - __ SmiTag(left_);
|
| - if (mode_ == OVERWRITE_LEFT) {
|
| - Label alloc_failure;
|
| - __ push(left_);
|
| - __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| - __ pop(left_);
|
| - }
|
| + __ bind(&left_smi);
|
| + __ SmiUntag(left_);
|
| + __ cvtsi2sd(xmm0, Operand(left_));
|
| + __ SmiTag(left_);
|
|
|
| - __ bind(&load_right);
|
| - __ test(right_, Immediate(kSmiTagMask));
|
| - __ j(zero, &right_smi);
|
| - __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
|
| - Factory::heap_number_map());
|
| - __ j(not_equal, &call_runtime);
|
| - __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
|
| - if (mode_ == OVERWRITE_RIGHT) {
|
| - __ mov(dst_, right_);
|
| - } else if (mode_ == NO_OVERWRITE) {
|
| - Label alloc_failure;
|
| + __ bind(&allocate_dst);
|
| __ push(left_);
|
| __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| __ pop(left_);
|
| - }
|
| - __ jmp(&do_op);
|
|
|
| - __ bind(&right_smi);
|
| - __ SmiUntag(right_);
|
| - __ cvtsi2sd(xmm1, Operand(right_));
|
| - __ SmiTag(right_);
|
| - if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
|
| - Label alloc_failure;
|
| - __ push(left_);
|
| - __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| - __ pop(left_);
|
| - }
|
| + __ bind(&do_op);
|
| + switch (op_) {
|
| + case Token::ADD: __ addsd(xmm0, xmm0); break;
|
| + case Token::SUB: __ subsd(xmm0, xmm0); break;
|
| + case Token::MUL: __ mulsd(xmm0, xmm0); break;
|
| + case Token::DIV: __ divsd(xmm0, xmm0); break;
|
| + default: UNREACHABLE();
|
| + }
|
| + } else {
|
| + __ test(left_, Immediate(kSmiTagMask));
|
| + __ j(zero, &left_smi);
|
| + __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
|
| + Factory::heap_number_map());
|
| + __ j(not_equal, &call_runtime);
|
| + __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
|
| + if (mode_ == OVERWRITE_LEFT) {
|
| + __ mov(dst_, left_);
|
| + }
|
| + __ jmp(&load_right);
|
|
|
| - __ bind(&do_op);
|
| - switch (op_) {
|
| - case Token::ADD: __ addsd(xmm0, xmm1); break;
|
| - case Token::SUB: __ subsd(xmm0, xmm1); break;
|
| - case Token::MUL: __ mulsd(xmm0, xmm1); break;
|
| - case Token::DIV: __ divsd(xmm0, xmm1); break;
|
| - default: UNREACHABLE();
|
| + __ bind(&left_smi);
|
| + __ SmiUntag(left_);
|
| + __ cvtsi2sd(xmm0, Operand(left_));
|
| + __ SmiTag(left_);
|
| + if (mode_ == OVERWRITE_LEFT) {
|
| + Label alloc_failure;
|
| + __ push(left_);
|
| + __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| + __ pop(left_);
|
| + }
|
| +
|
| + __ bind(&load_right);
|
| + __ test(right_, Immediate(kSmiTagMask));
|
| + __ j(zero, &right_smi);
|
| + __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
|
| + Factory::heap_number_map());
|
| + __ j(not_equal, &call_runtime);
|
| + __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
|
| + if (mode_ == OVERWRITE_RIGHT) {
|
| + __ mov(dst_, right_);
|
| + } else if (mode_ == NO_OVERWRITE) {
|
| + Label alloc_failure;
|
| + __ push(left_);
|
| + __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| + __ pop(left_);
|
| + }
|
| + __ jmp(&do_op);
|
| +
|
| + __ bind(&right_smi);
|
| + __ SmiUntag(right_);
|
| + __ cvtsi2sd(xmm1, Operand(right_));
|
| + __ SmiTag(right_);
|
| + if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
|
| + Label alloc_failure;
|
| + __ push(left_);
|
| + __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
|
| + __ pop(left_);
|
| + }
|
| +
|
| + __ bind(&do_op);
|
| + switch (op_) {
|
| + case Token::ADD: __ addsd(xmm0, xmm1); break;
|
| + case Token::SUB: __ subsd(xmm0, xmm1); break;
|
| + case Token::MUL: __ mulsd(xmm0, xmm1); break;
|
| + case Token::DIV: __ divsd(xmm0, xmm1); break;
|
| + default: UNREACHABLE();
|
| + }
|
| }
|
| __ movdbl(FieldOperand(dst_, HeapNumber::kValueOffset), xmm0);
|
| __ jmp(&done);
|
|
|