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

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

Issue 164317: X64: Implement remaining constant smi optimizations. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 4 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 | test/mozilla/mozilla.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/codegen-x64.cc
===================================================================
--- src/x64/codegen-x64.cc (revision 2658)
+++ src/x64/codegen-x64.cc (working copy)
@@ -5192,8 +5192,159 @@
}
break;
}
- // TODO(X64): Move other implementations from ia32 to here.
+ case Token::SAR:
+ if (reversed) {
+ Result constant_operand(value);
+ LikelySmiBinaryOperation(op, &constant_operand, operand,
+ overwrite_mode);
+ } else {
+ // Only the least significant 5 bits of the shift value are used.
+ // In the slow case, this masking is done inside the runtime call.
+ int shift_value = int_value & 0x1f;
+ operand->ToRegister();
+ frame_->Spill(operand->reg());
+ DeferredInlineSmiOperation* deferred =
+ new DeferredInlineSmiOperation(op,
+ operand->reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ __ testl(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ if (shift_value > 0) {
+ __ sarl(operand->reg(), Immediate(shift_value));
+ __ and_(operand->reg(), Immediate(~kSmiTagMask));
+ }
+ deferred->BindExit();
+ frame_->Push(operand);
+ }
+ break;
+
+ case Token::SHR:
+ if (reversed) {
+ Result constant_operand(value);
+ LikelySmiBinaryOperation(op, &constant_operand, operand,
+ overwrite_mode);
+ } else {
+ // Only the least significant 5 bits of the shift value are used.
+ // 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());
+ DeferredInlineSmiOperation* deferred =
+ new DeferredInlineSmiOperation(op,
+ answer.reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ __ testl(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ __ movl(answer.reg(), operand->reg());
+ __ sarl(answer.reg(), Immediate(kSmiTagSize));
+ __ shrl(answer.reg(), Immediate(shift_value));
+ // A negative Smi shifted right two is in the positive Smi range.
+ if (shift_value < 2) {
+ __ testl(answer.reg(), Immediate(0xc0000000));
+ deferred->Branch(not_zero);
+ }
+ operand->Unuse();
+ ASSERT(kSmiTagSize == times_2); // Adjust the code if not true.
+ __ lea(answer.reg(),
+ Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+ deferred->BindExit();
+ frame_->Push(&answer);
+ }
+ break;
+
+ case Token::SHL:
+ if (reversed) {
+ Result constant_operand(value);
+ LikelySmiBinaryOperation(op, &constant_operand, operand,
+ overwrite_mode);
+ } else {
+ // Only the least significant 5 bits of the shift value are used.
+ // In the slow case, this masking is done inside the runtime call.
+ int shift_value = int_value & 0x1f;
+ operand->ToRegister();
+ if (shift_value == 0) {
+ // Spill operand so it can be overwritten in the slow case.
+ frame_->Spill(operand->reg());
+ DeferredInlineSmiOperation* deferred =
+ new DeferredInlineSmiOperation(op,
+ operand->reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ __ testl(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ deferred->BindExit();
+ frame_->Push(operand);
+ } else {
+ // Use a fresh temporary for nonzero shift values.
+ Result answer = allocator()->Allocate();
+ ASSERT(answer.is_valid());
+ DeferredInlineSmiOperation* deferred =
+ new DeferredInlineSmiOperation(op,
+ answer.reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ __ testl(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ __ movl(answer.reg(), operand->reg());
+ ASSERT(kSmiTag == 0); // adjust code if not the case
+ // We do no shifts, only the Smi conversion, if shift_value is 1.
+ if (shift_value > 1) {
+ __ shll(answer.reg(), Immediate(shift_value - 1));
+ }
+ // Convert int result to Smi, checking that it is in int range.
+ ASSERT(kSmiTagSize == 1); // adjust code if not the case
+ __ addl(answer.reg(), answer.reg());
+ deferred->Branch(overflow);
+ deferred->BindExit();
+ operand->Unuse();
+ frame_->Push(&answer);
+ }
+ }
+ break;
+
+ case Token::BIT_OR:
+ case Token::BIT_XOR:
+ case Token::BIT_AND: {
+ operand->ToRegister();
+ frame_->Spill(operand->reg());
+ if (reversed) {
+ // Bit operations with a constant smi are commutative.
+ // We can swap left and right operands with no problem.
+ // Swap left and right overwrite modes. 0->0, 1->2, 2->1.
+ overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3);
+ }
+ DeferredCode* deferred = new DeferredInlineSmiOperation(op,
+ operand->reg(),
+ operand->reg(),
+ smi_value,
+ overwrite_mode);
+ __ testl(operand->reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ if (op == Token::BIT_AND) {
+ __ and_(operand->reg(), Immediate(smi_value));
+ } else if (op == Token::BIT_XOR) {
+ if (int_value != 0) {
+ __ xor_(operand->reg(), Immediate(smi_value));
+ }
+ } else {
+ ASSERT(op == Token::BIT_OR);
+ if (int_value != 0) {
+ __ or_(operand->reg(), Immediate(smi_value));
+ }
+ }
+ deferred->BindExit();
+ frame_->Push(operand);
+ break;
+ }
+
// Generate inline code for mod of powers of 2 and negative powers of 2.
case Token::MOD:
if (!reversed &&
« no previous file with comments | « no previous file | test/mozilla/mozilla.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698