Reviewers: Lasse Reichstein,
Description:
Added fast case for shift operations when the left parameter is a double
and we
know that the right parameter is a smi.
Please review this at http://codereview.chromium.org/955001
SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/
Affected files:
M src/ia32/codegen-ia32.cc
Index: src/ia32/codegen-ia32.cc
===================================================================
--- src/ia32/codegen-ia32.cc (revision 4124)
+++ src/ia32/codegen-ia32.cc (working copy)
@@ -1438,6 +1438,90 @@
return answer;
}
+ // If we have sse2 and we know that right is a smi we handle both
+ // the smi and heapnumber case for left inline.
+ if ((op == Token::SAR || op == Token::SHR || op == Token::SHL) &&
+ CpuFeatures::IsSupported(SSE2) &&
+ right->number_info().IsSmi()) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ // Move left out of ecx if necessary.
+ if (left->is_register() && left->reg().is(ecx)) {
+ *left = allocator_->Allocate();
+ ASSERT(left->is_valid());
+ __ mov(left->reg(), ecx);
+ }
+ Label left_nonsmi, done_left, do_op;
+ right->ToRegister(ecx);
+ left->ToRegister();
+ ASSERT(left->is_register() && !left->reg().is(ecx));
+ ASSERT(right->is_register() && right->reg().is(ecx));
+ // We will modify right, it must be spilled.
+ frame_->Spill(ecx);
+ answer = allocator_->Allocate();
+
+ DeferredInlineBinaryOperation* deferred =
+ new DeferredInlineBinaryOperation(op,
+ answer.reg(),
+ left->reg(),
+ ecx,
+ left->number_info(),
+ right->number_info(),
+ overwrite_mode);
+ __ mov(answer.reg(), left->reg());
+ // Fast case - both are actually smis.
+ __ test(answer.reg(), Immediate(kSmiTagMask));
+ __ j(not_zero, &left_nonsmi);
+ __ SmiUntag(answer.reg());
+ __ jmp(&do_op);
+
+ __ bind(&left_nonsmi);
+ // Branch if not a heapnumber.
+ __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
+ Factory::heap_number_map());
+ deferred->Branch(not_equal);
+
+ // Load integer value into answer register using truncation.
+ __ cvttsd2si(answer.reg(),
+ FieldOperand(answer.reg(), HeapNumber::kValueOffset));
+ // Branch if overflow.
+ __ cmp(answer.reg(), 0x80000000);
+ deferred->Branch(equal);
+
+ __ bind(&do_op);
+ // Since we know that ecx is a smi simply go ahead and untag it.
+ __ SmiUntag(ecx);
+ // Perform the operation - test if result fits in a smi afterwards.
+ switch (op) {
+ case Token::SAR:
+ __ sar_cl(answer.reg());
+ break;
+ case Token::SHR: {
+ __ shr_cl(answer.reg());
+ break;
+ }
+ case Token::SHL: {
+ __ shl_cl(answer.reg());
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ // Smi tag ecx in case we need to branch to runtime.
+ __ SmiTag(ecx);
+
+ // Check that the result is in smi-range.
+ __ test(answer.reg(), Immediate(0xc0000000));
+ deferred->Branch(not_zero);
+
+ __ SmiTag(answer.reg());
+ deferred->BindExit();
+ left->Unuse();
+ right->Unuse();
+ ASSERT(answer.is_valid());
+ return answer;
+ }
+
// Special handling of shift operations because they use fixed
// registers.
if (op == Token::SHL || op == Token::SHR || op == Token::SAR) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev