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

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

Issue 2852030: Inline some Smi multiplications. Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 6 months 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 | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/codegen-arm.cc
===================================================================
--- src/arm/codegen-arm.cc (revision 4966)
+++ src/arm/codegen-arm.cc (working copy)
@@ -869,7 +869,6 @@
} else {
// Fall through!
}
- case Token::MUL:
case Token::DIV:
case Token::MOD:
case Token::SHL:
@@ -884,6 +883,39 @@
break;
}
+ case Token::MUL: {
+ Register rhs = frame_->PopToRegister();
+ Register lhs = frame_->PopToRegister(rhs);
+ GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs);
+ if (inline_smi) {
+ JumpTarget slow, done;
+ Register smi_test_reg = VirtualFrame::scratch0();
+ Register low = VirtualFrame::scratch1();
+ Register high = smi_test_reg;
+ // We need to know whether we are dealing with two positive Smis. Set
+ // up smi_test_reg to tell us that.
+ __ orr(smi_test_reg, lhs, Operand(rhs));
+ __ tst(smi_test_reg, Operand(0x80000000 | kSmiTagMask));
+ smi_test_reg = no_reg;
+ slow.Branch(ne);
+ // Do multiplication
+ __ smull(low, high, lhs, rhs);
+ __ cmp(high, Operand(0));
+ // Remove double tag from answer.
+ __ mov(r0, Operand(low, LSR, kSmiTagSize), LeaveCC, eq);
+ done.Branch(eq);
+ slow.Bind();
+ frame_->SpillAll();
+ frame_->CallStub(&stub, 0);
+ done.Bind();
+ } else {
+ frame_->SpillAll();
+ frame_->CallStub(&stub, 0);
+ }
+ frame_->EmitPush(r0);
+ break;
+ }
+
case Token::COMMA: {
Register scratch = frame_->PopToRegister();
// Simply discard left value.
@@ -1036,58 +1068,60 @@
bool both_sides_are_smi = frame_->KnownSmiAt(0);
- bool something_to_inline;
+ bool inline_op_with_constant_smi;
+ GenerateInlineSmi inline_generic_smi_code = GENERATE_INLINE_SMI;
switch (op) {
case Token::ADD:
case Token::SUB:
case Token::BIT_AND:
case Token::BIT_OR:
case Token::BIT_XOR: {
- something_to_inline = true;
+ inline_op_with_constant_smi = true;
break;
}
case Token::SHL: {
- something_to_inline = (both_sides_are_smi || !reversed);
+ inline_op_with_constant_smi = (both_sides_are_smi || !reversed);
break;
}
case Token::SHR:
case Token::SAR: {
if (reversed) {
- something_to_inline = false;
+ inline_op_with_constant_smi = false;
} else {
- something_to_inline = true;
+ inline_op_with_constant_smi = true;
}
break;
}
+ case Token::MUL: {
+ // Multiplying by negative small constants is too annoying because of the
+ // -0 issues.
+ inline_op_with_constant_smi = (int_value >= 2);
+ inline_generic_smi_code = inline_op_with_constant_smi ?
+ GENERATE_INLINE_SMI :
+ DONT_GENERATE_INLINE_SMI;
+ break;
+ }
case Token::MOD: {
if (reversed || int_value < 2 || !IsPowerOf2(int_value)) {
- something_to_inline = false;
+ inline_op_with_constant_smi = false;
} else {
- something_to_inline = true;
+ inline_op_with_constant_smi = true;
}
break;
}
- case Token::MUL: {
- if (!IsEasyToMultiplyBy(int_value)) {
- something_to_inline = false;
- } else {
- something_to_inline = true;
- }
- break;
- }
default: {
- something_to_inline = false;
+ inline_op_with_constant_smi = false;
break;
}
}
- if (!something_to_inline) {
+ if (!inline_op_with_constant_smi) {
if (!reversed) {
// Push the rhs onto the virtual frame by putting it in a TOS register.
Register rhs = frame_->GetTOSRegister();
__ mov(rhs, Operand(value));
frame_->EmitPush(rhs, TypeInfo::Smi());
- GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, int_value);
+ GenericBinaryOperation(op, mode, inline_generic_smi_code, int_value);
} else {
// Pop the rhs, then push lhs and rhs in the right order. Only performs
// at most one pop, the rest takes place in TOS registers.
@@ -1097,7 +1131,7 @@
frame_->EmitPush(lhs, TypeInfo::Smi());
TypeInfo t = both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Unknown();
frame_->EmitPush(rhs, t);
- GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, kUnknownIntValue);
+ GenericBinaryOperation(op, mode, inline_generic_smi_code, kUnknownIntValue);
}
return;
}
@@ -1303,7 +1337,8 @@
}
case Token::MUL: {
- ASSERT(IsEasyToMultiplyBy(int_value));
+ ASSERT(int_value > 0);
+
DeferredCode* deferred =
new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos);
unsigned max_smi_that_wont_overflow = Smi::kMaxValue / int_value;
@@ -1312,14 +1347,25 @@
while ((mask & max_smi_that_wont_overflow) == 0) {
mask |= mask >> 1;
}
- mask |= kSmiTagMask;
+ if (!both_sides_are_smi) mask |= kSmiTagMask;
// This does a single mask that checks for a too high value in a
// conservative way and for a non-Smi. It also filters out negative
// numbers, unfortunately, but since this code is inline we prefer
// brevity to comprehensiveness.
__ tst(tos, Operand(mask));
deferred->Branch(ne);
- MultiplyByKnownInt(masm_, tos, tos, int_value);
+
+ if (IsEasyToMultiplyBy(int_value)) {
+ MultiplyByKnownInt(masm_, tos, tos, int_value);
+ } else {
+ Register high = VirtualFrame::scratch0();
+ Register low = VirtualFrame::scratch1();
+ __ mov(ip, Operand(int_value));
+ // Multiplying a tagged with an untagged value gives a tagged
+ // result.
+ __ smull(tos, high, tos, ip);
+ // Remove double tag from answer and make its sign bit 0.
+ }
deferred->BindExit();
frame_->EmitPush(tos);
break;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698