Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2632) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -97,6 +97,78 @@ |
} |
+// ------------------------------------------------------------------------- |
+// Deferred code objects |
+// |
+// These subclasses of DeferredCode add pieces of code to the end of generated |
+// code. They are branched to from the generated code, and |
+// keep some slower code out of the main body of the generated code. |
+// Many of them call a code stub or a runtime function. |
+ |
+class DeferredInlineSmiAdd: public DeferredCode { |
+ public: |
+ DeferredInlineSmiAdd(Register dst, |
+ Smi* value, |
+ OverwriteMode overwrite_mode) |
+ : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
+ set_comment("[ DeferredInlineSmiAdd"); |
+ } |
+ |
+ virtual void Generate(); |
+ |
+ private: |
+ Register dst_; |
+ Smi* value_; |
+ OverwriteMode overwrite_mode_; |
+}; |
+ |
+ |
+class DeferredInlineSmiSub: public DeferredCode { |
+ public: |
+ DeferredInlineSmiSub(Register dst, |
+ Smi* value, |
+ OverwriteMode overwrite_mode) |
+ : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
+ set_comment("[ DeferredInlineSmiSub"); |
+ } |
+ |
+ virtual void Generate(); |
+ |
+ private: |
+ Register dst_; |
+ Smi* value_; |
+ OverwriteMode overwrite_mode_; |
+}; |
+ |
+ |
+// Call the appropriate binary operation stub to compute src op value |
+// and leave the result in dst. |
+class DeferredInlineSmiOperation: public DeferredCode { |
+ public: |
+ DeferredInlineSmiOperation(Token::Value op, |
+ Register dst, |
+ Register src, |
+ Smi* value, |
+ OverwriteMode overwrite_mode) |
+ : op_(op), |
+ dst_(dst), |
+ src_(src), |
+ value_(value), |
+ overwrite_mode_(overwrite_mode) { |
+ set_comment("[ DeferredInlineSmiOperation"); |
+ } |
+ |
+ virtual void Generate(); |
+ |
+ private: |
+ Token::Value op_; |
+ Register dst_; |
+ Register src_; |
+ Smi* value_; |
+ OverwriteMode overwrite_mode_; |
+}; |
+ |
+ |
// ----------------------------------------------------------------------------- |
// CodeGenerator implementation. |
@@ -4771,29 +4843,6 @@ |
} |
- |
- |
-// The result of src + value is in dst. It either overflowed or was not |
-// smi tagged. Undo the speculative addition and call the appropriate |
-// specialized stub for add. The result is left in dst. |
-class DeferredInlineSmiAdd: public DeferredCode { |
- public: |
- DeferredInlineSmiAdd(Register dst, |
- Smi* value, |
- OverwriteMode overwrite_mode) |
- : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
- set_comment("[ DeferredInlineSmiAdd"); |
- } |
- |
- virtual void Generate(); |
- |
- private: |
- Register dst_; |
- Smi* value_; |
- OverwriteMode overwrite_mode_; |
-}; |
- |
- |
void DeferredInlineSmiAdd::Generate() { |
__ push(dst_); |
__ push(Immediate(value_)); |
@@ -4825,7 +4874,7 @@ |
void DeferredInlineSmiAddReversed::Generate() { |
- __ push(Immediate(value_)); |
+ __ push(Immediate(value_)); // Note: sign extended. |
__ push(dst_); |
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
__ CallStub(&igostub); |
@@ -4833,37 +4882,28 @@ |
} |
-// The result of src - value is in dst. It either overflowed or was not |
-// smi tagged. Undo the speculative subtraction and call the |
-// appropriate specialized stub for subtract. The result is left in |
-// dst. |
-class DeferredInlineSmiSub: public DeferredCode { |
- public: |
- DeferredInlineSmiSub(Register dst, |
- Smi* value, |
- OverwriteMode overwrite_mode) |
- : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
- set_comment("[ DeferredInlineSmiSub"); |
- } |
- |
- virtual void Generate(); |
- |
- private: |
- Register dst_; |
- Smi* value_; |
- OverwriteMode overwrite_mode_; |
-}; |
- |
- |
void DeferredInlineSmiSub::Generate() { |
__ push(dst_); |
- __ push(Immediate(value_)); |
+ __ push(Immediate(value_)); // Note: sign extended. |
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
__ CallStub(&igostub); |
if (!dst_.is(rax)) __ movq(dst_, rax); |
} |
+void DeferredInlineSmiOperation::Generate() { |
+ __ push(src_); |
+ __ push(Immediate(value_)); // Note: sign extended. |
+ // For mod we don't generate all the Smi code inline. |
+ GenericBinaryOpStub stub( |
+ op_, |
+ overwrite_mode_, |
+ (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED); |
+ __ CallStub(&stub); |
+ if (!dst_.is(rax)) __ movq(dst_, rax); |
+} |
+ |
+ |
void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, |
Result* operand, |
Handle<Object> value, |
@@ -4892,6 +4932,7 @@ |
// Get the literal value. |
Smi* smi_value = Smi::cast(*value); |
+ int int_value = smi_value->value(); |
switch (op) { |
case Token::ADD: { |
@@ -4921,6 +4962,36 @@ |
break; |
} |
// TODO(X64): Move other implementations from ia32 to here. |
+ |
+ // Generate inline code for mod of powers of 2 and negative powers of 2. |
+ case Token::MOD: |
+ if (!reversed && |
+ int_value != 0 && |
+ (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
+ operand->ToRegister(); |
+ frame_->Spill(operand->reg()); |
+ DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
+ operand->reg(), |
+ operand->reg(), |
+ smi_value, |
+ overwrite_mode); |
+ // Check for negative or non-Smi left hand side. |
+ __ testl(operand->reg(), |
+ Immediate(static_cast<int32_t>(kSmiTagMask | 0x80000000))); |
+ deferred->Branch(not_zero); |
+ if (int_value < 0) int_value = -int_value; |
+ if (int_value == 1) { |
+ __ movl(operand->reg(), Immediate(Smi::FromInt(0))); |
+ } else { |
+ __ and_(operand->reg(), Immediate((int_value << kSmiTagSize) - 1)); |
+ } |
+ deferred->BindExit(); |
+ frame_->Push(operand); |
+ break; // This break only applies if we generated code for MOD. |
+ } |
+ // Fall through if we did not find a power of 2 on the right hand side! |
+ // The next case must be the default. |
+ |
default: { |
Result constant_operand(value); |
if (reversed) { |