Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: src/ia32/codegen-ia32.cc

Issue 460060: Code generation for multiply-by-constant-smi.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/mjsunit/smi-ops.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/codegen-ia32.cc
===================================================================
--- src/ia32/codegen-ia32.cc (revision 3433)
+++ src/ia32/codegen-ia32.cc (working copy)
@@ -1616,30 +1616,33 @@
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
operand->ToRegister();
- Result answer = allocator()->Allocate();
- ASSERT(answer.is_valid());
+ frame_->Spill(operand->reg());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
- answer.reg(),
operand->reg(),
+ operand->reg(),
smi_value,
overwrite_mode);
- __ test(operand->reg(), Immediate(kSmiTagMask));
- deferred->Branch(not_zero);
- __ mov(answer.reg(), operand->reg());
- __ sar(answer.reg(), kSmiTagSize);
- __ shr(answer.reg(), shift_value);
- // A negative Smi shifted right two is in the positive Smi range.
if (shift_value < 2) {
- __ test(answer.reg(), Immediate(0xc0000000));
+ // A negative Smi shifted by 0 or 1 is too big to fit in the positive
+ // Smi range. Fold the test into the Smi tag test.
+ __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
deferred->Branch(not_zero);
+ if (shift_value == 1) {
+ __ shr(operand->reg(), 1);
+ __ and_(operand->reg(), ~kSmiTagMask);
+ }
+ } else {
+ __ test(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ __ sar(operand->reg(), 1);
+ __ shr(operand->reg(), shift_value - 1);
+ __ and_(operand->reg(), ~kSmiTagMask);
}
- operand->Unuse();
- ASSERT(kSmiTagSize == times_2); // Adjust the code if not true.
- __ lea(answer.reg(),
- Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+ ASSERT(kSmiTag == 0); // adjust code if not the case
+ ASSERT(kSmiTagSize == 1); // Adjust the code if not true.
deferred->BindExit();
- frame_->Push(&answer);
+ frame_->Push(operand);
}
break;
@@ -1733,6 +1736,74 @@
break;
}
+ case Token::MUL: {
+ operand->ToRegister();
+ frame_->Spill(operand->reg());
+ DeferredCode* deferred = NULL;
+ Result* answer = NULL;
+ Result answer_reg;
+ if (int_value == 0 || int_value == 1 || int_value == -1) {
+ // Re-use operand register.
+ answer = operand;
+ } else {
+ // Need a fresh register.
+ answer_reg = allocator()->Allocate();
+ answer = &answer_reg;
+ ASSERT(answer->is_valid());
+ }
+ if (reversed) {
+ deferred = new DeferredInlineSmiOperationReversed(op,
+ answer->reg(),
+ smi_value,
+ operand->reg(),
+ overwrite_mode);
+ } else {
+ deferred = new DeferredInlineSmiOperation(op,
+ answer->reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ }
+ __ test(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+
+ if (int_value == 1) {
+ // Already have correct value in 'answer'.
+ ASSERT(answer == operand);
+ } else if (int_value == 0) {
+ // The result is positive zero or negative zero depending on the sign of
+ // the operand.
+ __ test(operand->reg(), Operand(operand->reg()));
+ deferred->Branch(negative);
+ __ Set(answer->reg(), Immediate(0));
+ } else if (int_value == -1) {
+ ASSERT(answer == operand);
+ __ neg(answer->reg());
+ // The only value that can overflow is MIN_SMI, for which negation
+ // yields the same bit pattern. Thus the operand register, although
+ // negated, holds the original value, ready for the deferred code.
+ deferred->Branch(overflow);
+ // If the result is zero, it should be negative zero. Again, the
+ // operand register, although negated, contains the original value!
+ deferred->Branch(zero);
+ } else {
+ __ imul(answer->reg(), operand->reg(), int_value);
+ deferred->Branch(overflow);
+
+ if (int_value < 0) { // Negative zero test.
+ __ test(answer->reg(), Operand(answer->reg()));
+ deferred->Branch(zero);
+ }
+ }
+ deferred->BindExit();
+ if (operand != answer) {
+ operand->Unuse();
+ }
+ frame_->Push(answer);
+ break;
+ }
+
// Generate inline code for mod of powers of 2 and negative powers of 2.
case Token::MOD:
if (!reversed &&
@@ -7295,29 +7366,23 @@
void UnarySubStub::Generate(MacroAssembler* masm) {
Label undo;
Label slow;
- Label done;
Label try_float;
// Check whether the value is a smi.
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &try_float, not_taken);
- // Enter runtime system if the value of the expression is zero
- // to make sure that we switch between 0 and -0.
- __ test(eax, Operand(eax));
+ // Optimistically negate. There are two special case. (1) The
+ // smallest Smi value will overflow. (2) 0 should yield -0. Both of
+ // these cases enter the runtime system. No restoration of the
+ // operand's original value is necessary, as the two values are (the
+ // only) values such that x == -x in two's complement arithmetic.
+ __ neg(eax);
+ __ j(overflow, &slow, not_taken);
__ j(zero, &slow, not_taken);
- // The value of the expression is a smi that is not zero. Try
- // optimistic subtraction '0 - value'.
- __ mov(edx, Operand(eax));
- __ Set(eax, Immediate(0));
- __ sub(eax, Operand(edx));
- __ j(overflow, &undo, not_taken);
+ __ StubReturn(1);
- // If result is a smi we are done.
- __ test(eax, Immediate(kSmiTagMask));
- __ j(zero, &done, taken);
-
// Restore eax and enter runtime system.
__ bind(&undo);
__ mov(eax, Operand(edx));
@@ -7350,8 +7415,6 @@
__ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
}
- __ bind(&done);
-
__ StubReturn(1);
}
« no previous file with comments | « no previous file | test/mjsunit/smi-ops.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698