| Index: src/code-stubs.h
 | 
| diff --git a/src/code-stubs.h b/src/code-stubs.h
 | 
| index ef5b48f819feb41965cbbe93224479ab849968e6..d1a5b73df0b2ec5ef145ebf636b5f4c151b82de4 100644
 | 
| --- a/src/code-stubs.h
 | 
| +++ b/src/code-stubs.h
 | 
| @@ -200,9 +200,6 @@ class CodeStub BASE_EMBEDDED {
 | 
|  
 | 
|    virtual void PrintName(StringStream* stream);
 | 
|  
 | 
| -  // Returns a name for logging/debugging purposes.
 | 
| -  SmartArrayPointer<const char> GetName();
 | 
| -
 | 
|   protected:
 | 
|    static bool CanUseFPRegisters();
 | 
|  
 | 
| @@ -214,6 +211,8 @@ class CodeStub BASE_EMBEDDED {
 | 
|    // a fixed (non-moveable) code object.
 | 
|    virtual bool NeedsImmovableCode() { return false; }
 | 
|  
 | 
| +  // Returns a name for logging/debugging purposes.
 | 
| +  SmartArrayPointer<const char> GetName();
 | 
|    virtual void PrintBaseName(StringStream* stream);
 | 
|    virtual void PrintState(StringStream* stream) { }
 | 
|  
 | 
| @@ -996,177 +995,156 @@ class KeyedLoadFieldStub: public LoadFieldStub {
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class BinaryOpStub: public HydrogenCodeStub {
 | 
| +class BinaryOpStub: public PlatformCodeStub {
 | 
|   public:
 | 
|    BinaryOpStub(Token::Value op, OverwriteMode mode)
 | 
| -      : HydrogenCodeStub(UNINITIALIZED), op_(op), mode_(mode) {
 | 
| -    ASSERT(op <= LAST_TOKEN && op >= FIRST_TOKEN);
 | 
| +      : op_(op),
 | 
| +        mode_(mode),
 | 
| +        platform_specific_bit_(false),
 | 
| +        left_type_(BinaryOpIC::UNINITIALIZED),
 | 
| +        right_type_(BinaryOpIC::UNINITIALIZED),
 | 
| +        result_type_(BinaryOpIC::UNINITIALIZED),
 | 
| +        encoded_right_arg_(false, encode_arg_value(1)) {
 | 
|      Initialize();
 | 
| +    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
 | 
|    }
 | 
|  
 | 
| -  explicit BinaryOpStub(Code::ExtraICState state)
 | 
| -      : op_(decode_token(OpBits::decode(state))),
 | 
| -        mode_(OverwriteModeField::decode(state)),
 | 
| -        fixed_right_arg_(
 | 
| -            Maybe<int>(HasFixedRightArgBits::decode(state),
 | 
| -                decode_arg_value(FixedRightArgValueBits::decode(state)))),
 | 
| -        left_state_(LeftStateField::decode(state)),
 | 
| -        left_bool_(LeftBoolField::decode(state)),
 | 
| -        right_state_(fixed_right_arg_.has_value
 | 
| -            ? ((fixed_right_arg_.value <= Smi::kMaxValue) ? SMI : INT32)
 | 
| -            : RightStateField::decode(state)),
 | 
| -        right_bool_(fixed_right_arg_.has_value
 | 
| -            ? false : RightBoolField::decode(state)),
 | 
| -        result_state_(ResultStateField::decode(state)) {
 | 
| -    // We don't deserialize the SSE2 Field, since this is only used to be able
 | 
| -    // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
 | 
| -    // generation we always want it to reflect the current state.
 | 
| -    ASSERT(!fixed_right_arg_.has_value ||
 | 
| -           can_encode_arg_value(fixed_right_arg_.value));
 | 
| -  }
 | 
| -
 | 
| -  static const int FIRST_TOKEN = Token::BIT_OR;
 | 
| -  static const int LAST_TOKEN = Token::MOD;
 | 
| +  BinaryOpStub(
 | 
| +      int key,
 | 
| +      BinaryOpIC::TypeInfo left_type,
 | 
| +      BinaryOpIC::TypeInfo right_type,
 | 
| +      BinaryOpIC::TypeInfo result_type,
 | 
| +      Maybe<int32_t> fixed_right_arg)
 | 
| +      : op_(OpBits::decode(key)),
 | 
| +        mode_(ModeBits::decode(key)),
 | 
| +        platform_specific_bit_(PlatformSpecificBits::decode(key)),
 | 
| +        left_type_(left_type),
 | 
| +        right_type_(right_type),
 | 
| +        result_type_(result_type),
 | 
| +        encoded_right_arg_(fixed_right_arg.has_value,
 | 
| +                           encode_arg_value(fixed_right_arg.value)) { }
 | 
|  
 | 
| -  static void GenerateAheadOfTime(Isolate* isolate);
 | 
| -  virtual void InitializeInterfaceDescriptor(
 | 
| -      Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
 | 
| -  static void InitializeForIsolate(Isolate* isolate) {
 | 
| -    BinaryOpStub binopStub(UNINITIALIZED);
 | 
| -    binopStub.InitializeInterfaceDescriptor(
 | 
| -        isolate, isolate->code_stub_interface_descriptor(CodeStub::BinaryOp));
 | 
| +  static void decode_types_from_minor_key(int minor_key,
 | 
| +                                          BinaryOpIC::TypeInfo* left_type,
 | 
| +                                          BinaryOpIC::TypeInfo* right_type,
 | 
| +                                          BinaryOpIC::TypeInfo* result_type) {
 | 
| +    *left_type =
 | 
| +        static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key));
 | 
| +    *right_type =
 | 
| +        static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key));
 | 
| +    *result_type =
 | 
| +        static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key));
 | 
|    }
 | 
|  
 | 
| -  virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
 | 
| -  virtual InlineCacheState GetICState() {
 | 
| -    if (Max(left_state_, right_state_) == NONE && !left_bool_ && !right_bool_) {
 | 
| -      return ::v8::internal::UNINITIALIZED;
 | 
| -    }
 | 
| -    if (Max(left_state_, right_state_) == GENERIC) return MEGAMORPHIC;
 | 
| -    return MONOMORPHIC;
 | 
| +  static Token::Value decode_op_from_minor_key(int minor_key) {
 | 
| +    return static_cast<Token::Value>(OpBits::decode(minor_key));
 | 
|    }
 | 
|  
 | 
| -  virtual Code::ExtraICState GetExtraICState() {
 | 
| -    bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
 | 
| -                     CpuFeatures::IsSafeForSnapshot(SSE2);
 | 
| -
 | 
| -    return OpBits::encode(encode_token(op_))
 | 
| -         | LeftStateField::encode(left_state_)
 | 
| -         | LeftBoolField::encode(left_bool_)
 | 
| -         | RightStateField::encode(fixed_right_arg_.has_value
 | 
| -                                       ? NONE : right_state_)
 | 
| -         | RightBoolField::encode(fixed_right_arg_.has_value
 | 
| -                                       ? false
 | 
| -                                       : right_bool_)
 | 
| -         | ResultStateField::encode(result_state_)
 | 
| -         | HasFixedRightArgBits::encode(fixed_right_arg_.has_value)
 | 
| -         | FixedRightArgValueBits::encode(fixed_right_arg_.has_value
 | 
| -                                              ? encode_arg_value(
 | 
| -                                                  fixed_right_arg_.value)
 | 
| -                                              : 0)
 | 
| -         | SSE2Field::encode(sse_field)
 | 
| -         | OverwriteModeField::encode(mode_);
 | 
| -  }
 | 
| -
 | 
| -  bool CanReuseDoubleBox() {
 | 
| -    return result_state_ <= NUMBER && result_state_ > SMI &&
 | 
| -      ((left_state_ > SMI && left_state_ <= NUMBER &&
 | 
| -        mode_ == OVERWRITE_LEFT) ||
 | 
| -       (right_state_ > SMI && right_state_ <= NUMBER &&
 | 
| -        mode_ == OVERWRITE_RIGHT));
 | 
| -  }
 | 
| -
 | 
| -  bool HasSideEffects(Isolate* isolate) const {
 | 
| -    return GetLeftType(isolate)->Maybe(Type::Receiver()) ||
 | 
| -           GetRightType(isolate)->Maybe(Type::Receiver());
 | 
| +  static Maybe<int> decode_fixed_right_arg_from_minor_key(int minor_key) {
 | 
| +    return Maybe<int>(
 | 
| +        HasFixedRightArgBits::decode(minor_key),
 | 
| +        decode_arg_value(FixedRightArgValueBits::decode(minor_key)));
 | 
|    }
 | 
|  
 | 
| -  virtual Handle<Code> GenerateCode(Isolate* isolate);
 | 
| +  int fixed_right_arg_value() const {
 | 
| +    return decode_arg_value(encoded_right_arg_.value);
 | 
| +  }
 | 
|  
 | 
| -  Maybe<Handle<Object> > Result(Handle<Object> left,
 | 
| -                         Handle<Object> right,
 | 
| -                         Isolate* isolate);
 | 
| +  static bool can_encode_arg_value(int32_t value) {
 | 
| +    return value > 0 &&
 | 
| +        IsPowerOf2(value) &&
 | 
| +        FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
 | 
| +  }
 | 
|  
 | 
| -  Token::Value operation() const { return op_; }
 | 
| -  OverwriteMode mode() const { return mode_; }
 | 
| -  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
 | 
| +  enum SmiCodeGenerateHeapNumberResults {
 | 
| +    ALLOW_HEAPNUMBER_RESULTS,
 | 
| +    NO_HEAPNUMBER_RESULTS
 | 
| +  };
 | 
|  
 | 
| -  Handle<Type> GetLeftType(Isolate* isolate) const;
 | 
| -  Handle<Type> GetRightType(Isolate* isolate) const;
 | 
| -  Handle<Type> GetResultType(Isolate* isolate) const;
 | 
| + private:
 | 
| +  Token::Value op_;
 | 
| +  OverwriteMode mode_;
 | 
| +  bool platform_specific_bit_;  // Indicates SSE3 on IA32.
 | 
|  
 | 
| -  void UpdateStatus(Handle<Object> left,
 | 
| -                    Handle<Object> right,
 | 
| -                    Maybe<Handle<Object> > result);
 | 
| +  // Operand type information determined at runtime.
 | 
| +  BinaryOpIC::TypeInfo left_type_;
 | 
| +  BinaryOpIC::TypeInfo right_type_;
 | 
| +  BinaryOpIC::TypeInfo result_type_;
 | 
|  
 | 
| -  void PrintState(StringStream* stream);
 | 
| +  Maybe<int> encoded_right_arg_;
 | 
|  
 | 
| - private:
 | 
| -  explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state),
 | 
| -                                                     op_(Token::ADD),
 | 
| -                                                     mode_(NO_OVERWRITE) {
 | 
| -    Initialize();
 | 
| +  static int encode_arg_value(int32_t value) {
 | 
| +    ASSERT(can_encode_arg_value(value));
 | 
| +    return WhichPowerOf2(value);
 | 
|    }
 | 
| -  void Initialize();
 | 
|  
 | 
| -  enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
 | 
| -
 | 
| -  // We truncate the last bit of the token.
 | 
| -  STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 5));
 | 
| -  class LeftStateField:         public BitField<State, 0,  3> {};
 | 
| -  class LeftBoolField:          public BitField<bool, 3,  1> {};
 | 
| -  // When fixed right arg is set, we don't need to store the right state.
 | 
| -  // Thus the two fields can overlap.
 | 
| -  class HasFixedRightArgBits:   public BitField<bool, 4, 1> {};
 | 
| -  class FixedRightArgValueBits: public BitField<int,  5, 4> {};
 | 
| -  class RightStateField:        public BitField<State, 5, 3> {};
 | 
| -  class RightBoolField:         public BitField<bool, 8, 1> {};
 | 
| -  class ResultStateField:       public BitField<State, 9, 3> {};
 | 
| -  class SSE2Field:              public BitField<bool, 12, 1> {};
 | 
| -  class OverwriteModeField:     public BitField<OverwriteMode, 13, 2> {};
 | 
| -  class OpBits:                 public BitField<int, 15,  5> {};
 | 
| -
 | 
| -  virtual CodeStub::Major MajorKey() { return BinaryOp; }
 | 
| -  virtual int NotMissMinorKey() { return GetExtraICState(); }
 | 
| +  static int32_t decode_arg_value(int value) {
 | 
| +    return 1 << value;
 | 
| +  }
 | 
|  
 | 
| -  static Handle<Type> StateToType(State state,
 | 
| -                                  bool seen_bool,
 | 
| -                                  Isolate* isolate);
 | 
| +  virtual void PrintName(StringStream* stream);
 | 
|  
 | 
| -  static void Generate(Token::Value op,
 | 
| -                       State left,
 | 
| -                       State right,
 | 
| -                       State result,
 | 
| -                       Isolate* isolate);
 | 
| +  // Minor key encoding in all 25 bits FFFFFHTTTRRRLLLPOOOOOOOMM.
 | 
| +  // Note: We actually do not need 7 bits for the operation, just 4 bits to
 | 
| +  // encode ADD, SUB, MUL, DIV, MOD, BIT_OR, BIT_AND, BIT_XOR, SAR, SHL, SHR.
 | 
| +  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
 | 
| +  class OpBits: public BitField<Token::Value, 2, 7> {};
 | 
| +  class PlatformSpecificBits: public BitField<bool, 9, 1> {};
 | 
| +  class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
 | 
| +  class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
 | 
| +  class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {};
 | 
| +  class HasFixedRightArgBits: public BitField<bool, 19, 1> {};
 | 
| +  class FixedRightArgValueBits: public BitField<int, 20, 5> {};
 | 
| +
 | 
| +  Major MajorKey() { return BinaryOp; }
 | 
| +  int MinorKey() {
 | 
| +    return OpBits::encode(op_)
 | 
| +           | ModeBits::encode(mode_)
 | 
| +           | PlatformSpecificBits::encode(platform_specific_bit_)
 | 
| +           | LeftTypeBits::encode(left_type_)
 | 
| +           | RightTypeBits::encode(right_type_)
 | 
| +           | ResultTypeBits::encode(result_type_)
 | 
| +           | HasFixedRightArgBits::encode(encoded_right_arg_.has_value)
 | 
| +           | FixedRightArgValueBits::encode(encoded_right_arg_.value);
 | 
| +  }
 | 
|  
 | 
| -  void UpdateStatus(Handle<Object> object,
 | 
| -                    State* state,
 | 
| -                    bool* bool_state);
 | 
|  
 | 
| -  bool can_encode_arg_value(int32_t value) const;
 | 
| -  int encode_arg_value(int32_t value) const;
 | 
| -  int32_t decode_arg_value(int value)  const;
 | 
| -  int encode_token(Token::Value op) const;
 | 
| -  Token::Value decode_token(int op) const;
 | 
| +  // Platform-independent implementation.
 | 
| +  void Generate(MacroAssembler* masm);
 | 
| +  void GenerateCallRuntime(MacroAssembler* masm);
 | 
|  
 | 
| -  bool has_int_result() const {
 | 
| -    return op_ == Token::BIT_XOR || op_ == Token::BIT_AND ||
 | 
| -           op_ == Token::BIT_OR || op_ == Token::SAR;
 | 
| -  }
 | 
| +  // Platform-independent signature, platform-specific implementation.
 | 
| +  void Initialize();
 | 
| +  void GenerateAddStrings(MacroAssembler* masm);
 | 
| +  void GenerateBothStringStub(MacroAssembler* masm);
 | 
| +  void GenerateGeneric(MacroAssembler* masm);
 | 
| +  void GenerateGenericStub(MacroAssembler* masm);
 | 
| +  void GenerateNumberStub(MacroAssembler* masm);
 | 
| +  void GenerateInt32Stub(MacroAssembler* masm);
 | 
| +  void GenerateLoadArguments(MacroAssembler* masm);
 | 
| +  void GenerateOddballStub(MacroAssembler* masm);
 | 
| +  void GenerateRegisterArgsPush(MacroAssembler* masm);
 | 
| +  void GenerateReturn(MacroAssembler* masm);
 | 
| +  void GenerateSmiStub(MacroAssembler* masm);
 | 
| +  void GenerateStringStub(MacroAssembler* masm);
 | 
| +  void GenerateTypeTransition(MacroAssembler* masm);
 | 
| +  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
 | 
| +  void GenerateUninitializedStub(MacroAssembler* masm);
 | 
| +
 | 
| +  // Entirely platform-specific methods are defined as static helper
 | 
| +  // functions in the <arch>/code-stubs-<arch>.cc files.
 | 
|  
 | 
| -  const char* StateToName(State state);
 | 
| +  virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
 | 
|  
 | 
| -  void PrintBaseName(StringStream* stream);
 | 
| +  virtual InlineCacheState GetICState() {
 | 
| +    return BinaryOpIC::ToState(Max(left_type_, right_type_));
 | 
| +  }
 | 
|  
 | 
| -  Token::Value op_;
 | 
| -  OverwriteMode mode_;
 | 
| +  virtual void FinishCode(Handle<Code> code) {
 | 
| +    code->set_stub_info(MinorKey());
 | 
| +  }
 | 
|  
 | 
| -  Maybe<int> fixed_right_arg_;
 | 
| -  State left_state_;
 | 
| -  bool left_bool_;
 | 
| -  State right_state_;
 | 
| -  bool right_bool_;
 | 
| -  State result_state_;
 | 
| +  friend class CodeGenerator;
 | 
|  };
 | 
|  
 | 
|  
 | 
| @@ -1739,9 +1717,7 @@ class DoubleToIStub : public PlatformCodeStub {
 | 
|        DestinationRegisterBits::encode(destination.code_) |
 | 
|        OffsetBits::encode(offset) |
 | 
|        IsTruncatingBits::encode(is_truncating) |
 | 
| -      SkipFastPathBits::encode(skip_fastpath) |
 | 
| -      SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
 | 
| -                          CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
 | 
| +      SkipFastPathBits::encode(skip_fastpath);
 | 
|    }
 | 
|  
 | 
|    Register source() {
 | 
| @@ -1784,8 +1760,6 @@ class DoubleToIStub : public PlatformCodeStub {
 | 
|        public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
 | 
|    class SkipFastPathBits:
 | 
|        public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
 | 
| -  class SSEBits:
 | 
| -      public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {};  // NOLINT
 | 
|  
 | 
|    Major MajorKey() { return DoubleToI; }
 | 
|    int MinorKey() { return bit_field_; }
 | 
| 
 |