| 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) { | 
|  |