Make more use of the NumberInfo data.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 5 Mar 2010 23:54:13 +0000 (23:54 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 5 Mar 2010 23:54:13 +0000 (23:54 +0000)
Makes NumberInfo into a real class.
Fix bug where NumberInfo was lost in ToRegister.
Allow 17 bits in safe Smis instead of 16.
Review URL: http://codereview.chromium.org/668151

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4046 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

21 files changed:
src/arm/virtual-frame-arm.cc
src/arm/virtual-frame-arm.h
src/frame-element.h
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/ia32/full-codegen-ia32.cc
src/ia32/register-allocator-ia32.cc
src/ia32/virtual-frame-ia32.cc
src/ia32/virtual-frame-ia32.h
src/jump-target-inl.h
src/jump-target.cc
src/number-info.h
src/register-allocator-inl.h
src/register-allocator.cc
src/register-allocator.h
src/virtual-frame-inl.h
src/virtual-frame.cc
src/x64/codegen-x64.cc
src/x64/codegen-x64.h
src/x64/virtual-frame-x64.cc
src/x64/virtual-frame-x64.h

index bc9da842730ae5275e521eb8d83898321b455c43..ab6e5f8136ee58baa717124ab000e426b60c8904 100644 (file)
@@ -295,7 +295,7 @@ void VirtualFrame::EmitPop(Register reg) {
 
 void VirtualFrame::EmitPush(Register reg) {
   ASSERT(stack_pointer_ == element_count() - 1);
-  elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown));
+  elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown()));
   stack_pointer_++;
   __ push(reg);
 }
index b41cd74bc85c9662101561c91fa341cd80732014..6eb08119edb16da7e7085acb0230d1bcb1510f1e 100644 (file)
@@ -69,7 +69,7 @@ class VirtualFrame : public ZoneObject {
 
   // Create a duplicate of an existing valid frame element.
   FrameElement CopyElementAt(int index,
-                             NumberInfo::Type info = NumberInfo::kUnknown);
+                             NumberInfo info = NumberInfo::Unknown());
 
   // The number of elements on the virtual frame.
   int element_count() { return elements_.length(); }
@@ -344,7 +344,7 @@ class VirtualFrame : public ZoneObject {
   void EmitPushMultiple(int count, int src_regs);
 
   // Push an element on the virtual frame.
-  inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
+  inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown());
   inline void Push(Handle<Object> value);
   inline void Push(Smi* value);
 
index 5762814ff2744a20bd20b0c836d7167e92a359ec..af53b17b21b05f47e0af793ea44f1e64218dbb7d 100644 (file)
@@ -53,23 +53,25 @@ class FrameElement BASE_EMBEDDED {
     SYNCED
   };
 
-  inline NumberInfo::Type number_info() {
+  inline NumberInfo number_info() {
     // Copied elements do not have number info. Instead
     // we have to inspect their backing element in the frame.
     ASSERT(!is_copy());
-    if (!is_constant()) return NumberInfoField::decode(value_);
+    if (!is_constant()) {
+      return NumberInfo::FromInt(NumberInfoField::decode(value_));
+    }
     Handle<Object> value = handle();
-    if (value->IsSmi()) return NumberInfo::kSmi;
-    if (value->IsHeapNumber()) return NumberInfo::kHeapNumber;
-    return NumberInfo::kUnknown;
+    if (value->IsSmi()) return NumberInfo::Smi();
+    if (value->IsHeapNumber()) return NumberInfo::HeapNumber();
+    return NumberInfo::Unknown();
   }
 
-  inline void set_number_info(NumberInfo::Type info) {
+  inline void set_number_info(NumberInfo info) {
     // Copied elements do not have number info. Instead
     // we have to inspect their backing element in the frame.
     ASSERT(!is_copy());
     value_ = value_ & ~NumberInfoField::mask();
-    value_ = value_ | NumberInfoField::encode(info);
+    value_ = value_ | NumberInfoField::encode(info.ToInt());
   }
 
   // The default constructor creates an invalid frame element.
@@ -77,7 +79,7 @@ class FrameElement BASE_EMBEDDED {
     value_ = TypeField::encode(INVALID)
         | CopiedField::encode(false)
         | SyncedField::encode(false)
-        | NumberInfoField::encode(NumberInfo::kUninitialized)
+        | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt())
         | DataField::encode(0);
   }
 
@@ -88,7 +90,7 @@ class FrameElement BASE_EMBEDDED {
   }
 
   // Factory function to construct an in-memory frame element.
-  static FrameElement MemoryElement(NumberInfo::Type info) {
+  static FrameElement MemoryElement(NumberInfo info) {
     FrameElement result(MEMORY, no_reg, SYNCED, info);
     return result;
   }
@@ -96,7 +98,7 @@ class FrameElement BASE_EMBEDDED {
   // Factory function to construct an in-register frame element.
   static FrameElement RegisterElement(Register reg,
                                       SyncFlag is_synced,
-                                      NumberInfo::Type info) {
+                                      NumberInfo info) {
     return FrameElement(REGISTER, reg, is_synced, info);
   }
 
@@ -210,11 +212,11 @@ class FrameElement BASE_EMBEDDED {
   FrameElement(Type type,
                Register reg,
                SyncFlag is_synced,
-               NumberInfo::Type info) {
+               NumberInfo info) {
     value_ = TypeField::encode(type)
         | CopiedField::encode(false)
         | SyncedField::encode(is_synced != NOT_SYNCED)
-        | NumberInfoField::encode(info)
+        | NumberInfoField::encode(info.ToInt())
         | DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
   }
 
@@ -223,7 +225,7 @@ class FrameElement BASE_EMBEDDED {
     value_ = TypeField::encode(CONSTANT)
         | CopiedField::encode(false)
         | SyncedField::encode(is_synced != NOT_SYNCED)
-        | NumberInfoField::encode(NumberInfo::kUninitialized)
+        | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt())
         | DataField::encode(ConstantList()->length());
     ConstantList()->Add(value);
   }
@@ -252,8 +254,8 @@ class FrameElement BASE_EMBEDDED {
   class TypeField: public BitField<Type, 0, 3> {};
   class CopiedField: public BitField<bool, 3, 1> {};
   class SyncedField: public BitField<bool, 4, 1> {};
-  class NumberInfoField: public BitField<NumberInfo::Type, 5, 3> {};
-  class DataField: public BitField<uint32_t, 8, 32 - 8> {};
+  class NumberInfoField: public BitField<int, 5, 4> {};
+  class DataField: public BitField<uint32_t, 9, 32 - 9> {};
 
   friend class VirtualFrame;
 };
index b611cd07d06d68b966a2bc78e57c4c40f2ca2b78..dfb5cd77928cb523c864508b8c4ed550913ce8e8 100644 (file)
@@ -733,7 +733,27 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) {
   Result value = frame_->Pop();
   value.ToRegister();
 
-  if (value.is_number()) {
+  if (value.is_integer32()) {  // Also takes Smi case.
+    Comment cmnt(masm_, "ONLY_INTEGER_32");
+    if (FLAG_debug_code) {
+      Label ok;
+      __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
+      __ test(value.reg(), Immediate(kSmiTagMask));
+      __ j(zero, &ok);
+      __ fldz();
+      __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
+      __ FCmp();
+      __ j(not_zero, &ok);
+      __ Abort("Smi was wrapped in HeapNumber in output from bitop");
+      __ bind(&ok);
+    }
+    // In the integer32 case there are no Smis hidden in heap numbers, so we
+    // need only test for Smi zero.
+    __ test(value.reg(), Operand(value.reg()));
+    dest->false_target()->Branch(zero);
+    value.Unuse();
+    dest->Split(not_zero);
+  } else if (value.is_number()) {
     Comment cmnt(masm_, "ONLY_NUMBER");
     // Fast case if NumberInfo indicates only numbers.
     if (FLAG_debug_code) {
@@ -817,8 +837,17 @@ class FloatingPointHelper : public AllStatic {
   // Takes the operands in edx and eax and loads them as integers in eax
   // and ecx.
   static void LoadAsIntegers(MacroAssembler* masm,
+                             NumberInfo number_info,
                              bool use_sse3,
                              Label* operand_conversion_failure);
+  static void LoadNumbersAsIntegers(MacroAssembler* masm,
+                                    NumberInfo number_info,
+                                    bool use_sse3,
+                                    Label* operand_conversion_failure);
+  static void LoadUnknownsAsIntegers(MacroAssembler* masm,
+                                     bool use_sse3,
+                                     Label* operand_conversion_failure);
+
   // Test if operands are smis or heap numbers and load them
   // into xmm0 and xmm1 if they are. Operands are in edx and eax.
   // Leaves operands unchanged.
@@ -856,7 +885,7 @@ const char* GenericBinaryOpStub::GetName() {
                (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
                args_in_registers_ ? "RegArgs" : "StackArgs",
                args_reversed_ ? "_R" : "",
-               NumberInfo::ToString(static_operands_type_),
+               static_operands_type_.ToString(),
                BinaryOpIC::GetName(runtime_operands_type_));
   return name_;
 }
@@ -869,8 +898,11 @@ class DeferredInlineBinaryOperation: public DeferredCode {
                                 Register dst,
                                 Register left,
                                 Register right,
+                                NumberInfo left_info,
+                                NumberInfo right_info,
                                 OverwriteMode mode)
-      : op_(op), dst_(dst), left_(left), right_(right), mode_(mode) {
+      : op_(op), dst_(dst), left_(left), right_(right),
+        left_info_(left_info), right_info_(right_info), mode_(mode) {
     set_comment("[ DeferredInlineBinaryOperation");
   }
 
@@ -881,6 +913,8 @@ class DeferredInlineBinaryOperation: public DeferredCode {
   Register dst_;
   Register left_;
   Register right_;
+  NumberInfo left_info_;
+  NumberInfo right_info_;
   OverwriteMode mode_;
 };
 
@@ -894,18 +928,22 @@ void DeferredInlineBinaryOperation::Generate() {
     CpuFeatures::Scope use_sse2(SSE2);
     Label call_runtime, after_alloc_failure;
     Label left_smi, right_smi, load_right, do_op;
-    __ test(left_, Immediate(kSmiTagMask));
-    __ j(zero, &left_smi);
-    __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
-           Factory::heap_number_map());
-    __ j(not_equal, &call_runtime);
-    __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
-    if (mode_ == OVERWRITE_LEFT) {
-      __ mov(dst_, left_);
-    }
-    __ jmp(&load_right);
+    if (!left_info_.IsSmi()) {
+      __ test(left_, Immediate(kSmiTagMask));
+      __ j(zero, &left_smi);
+      if (!left_info_.IsNumber()) {
+        __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
+               Factory::heap_number_map());
+        __ j(not_equal, &call_runtime);
+      }
+      __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
+      if (mode_ == OVERWRITE_LEFT) {
+        __ mov(dst_, left_);
+      }
+      __ jmp(&load_right);
 
-    __ bind(&left_smi);
+      __ bind(&left_smi);
+    }
     __ SmiUntag(left_);
     __ cvtsi2sd(xmm0, Operand(left_));
     __ SmiTag(left_);
@@ -917,23 +955,27 @@ void DeferredInlineBinaryOperation::Generate() {
     }
 
     __ bind(&load_right);
-    __ test(right_, Immediate(kSmiTagMask));
-    __ j(zero, &right_smi);
-    __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
-           Factory::heap_number_map());
-    __ j(not_equal, &call_runtime);
-    __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
-    if (mode_ == OVERWRITE_RIGHT) {
-      __ mov(dst_, right_);
-    } else if (mode_ == NO_OVERWRITE) {
-      Label alloc_failure;
-      __ push(left_);
-      __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
-      __ pop(left_);
-    }
-    __ jmp(&do_op);
+    if (!right_info_.IsSmi()) {
+      __ test(right_, Immediate(kSmiTagMask));
+      __ j(zero, &right_smi);
+      if (!right_info_.IsNumber()) {
+        __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
+               Factory::heap_number_map());
+        __ j(not_equal, &call_runtime);
+      }
+      __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
+      if (mode_ == OVERWRITE_RIGHT) {
+        __ mov(dst_, right_);
+      } else if (mode_ == NO_OVERWRITE) {
+        Label alloc_failure;
+        __ push(left_);
+        __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
+        __ pop(left_);
+      }
+      __ jmp(&do_op);
 
-    __ bind(&right_smi);
+      __ bind(&right_smi);
+    }
     __ SmiUntag(right_);
     __ cvtsi2sd(xmm1, Operand(right_));
     __ SmiTag(right_);
@@ -959,13 +1001,105 @@ void DeferredInlineBinaryOperation::Generate() {
     __ pop(left_);
     __ bind(&call_runtime);
   }
-  GenericBinaryOpStub stub(op_, mode_, NO_SMI_CODE_IN_STUB);
+  GenericBinaryOpStub stub(op_,
+                           mode_,
+                           NO_SMI_CODE_IN_STUB,
+                           NumberInfo::Combine(left_info_, right_info_));
   stub.GenerateCall(masm_, left_, right_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
   __ bind(&done);
 }
 
 
+static NumberInfo CalculateNumberInfo(NumberInfo operands_type,
+                                      Token::Value op,
+                                      const Result& right,
+                                      const Result& left) {
+  // Set NumberInfo of result according to the operation performed.
+  // Rely on the fact that smis have a 31 bit payload on ia32.
+  ASSERT(kSmiValueSize == 31);
+  switch (op) {
+    case Token::COMMA:
+      return right.number_info();
+    case Token::OR:
+    case Token::AND:
+      // Result type can be either of the two input types.
+      return operands_type;
+    case Token::BIT_AND: {
+      // Anding with positive Smis will give you a Smi.
+      if (right.is_constant() && right.handle()->IsSmi() &&
+          Smi::cast(*right.handle())->value() >= 0) {
+        return NumberInfo::Smi();
+      } else if (left.is_constant() && left.handle()->IsSmi() &&
+          Smi::cast(*left.handle())->value() >= 0) {
+        return NumberInfo::Smi();
+      }
+      return (operands_type.IsSmi())
+          ? NumberInfo::Smi()
+          : NumberInfo::Integer32();
+    }
+    case Token::BIT_OR: {
+      // Oring with negative Smis will give you a Smi.
+      if (right.is_constant() && right.handle()->IsSmi() &&
+          Smi::cast(*right.handle())->value() < 0) {
+        return NumberInfo::Smi();
+      } else if (left.is_constant() && left.handle()->IsSmi() &&
+          Smi::cast(*left.handle())->value() < 0) {
+        return NumberInfo::Smi();
+      }
+      return (operands_type.IsSmi())
+          ? NumberInfo::Smi()
+          : NumberInfo::Integer32();
+    }
+    case Token::BIT_XOR:
+      // Result is always a 32 bit integer. Smi property of inputs is preserved.
+      return (operands_type.IsSmi())
+          ? NumberInfo::Smi()
+          : NumberInfo::Integer32();
+    case Token::SAR:
+      if (left.is_smi()) return NumberInfo::Smi();
+      // Result is a smi if we shift by a constant >= 1, otherwise an integer32.
+      return (right.is_constant() && right.handle()->IsSmi()
+                     && Smi::cast(*right.handle())->value() >= 1)
+          ? NumberInfo::Smi()
+          : NumberInfo::Integer32();
+    case Token::SHR:
+      // Result is a smi if we shift by a constant >= 2, otherwise an integer32.
+      return (right.is_constant() && right.handle()->IsSmi()
+                     && Smi::cast(*right.handle())->value() >= 2)
+          ? NumberInfo::Smi()
+          : NumberInfo::Integer32();
+    case Token::ADD:
+      if (operands_type.IsSmi()) {
+        // The Integer32 range is big enough to take the sum of any two Smis.
+        return NumberInfo::Integer32();
+      } else {
+        // Result could be a string or a number. Check types of inputs.
+        return operands_type.IsNumber()
+            ? NumberInfo::Number()
+            : NumberInfo::Unknown();
+      }
+    case Token::SHL:
+      return NumberInfo::Integer32();
+    case Token::SUB:
+      // The Integer32 range is big enough to take the difference of any two
+      // Smis.
+      return (operands_type.IsSmi()) ?
+                    NumberInfo::Integer32() :
+                    NumberInfo::Number();
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD:
+      // Result is always a number.
+      return NumberInfo::Number();
+    default:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
+  return NumberInfo::Unknown();
+}
+
+
 void CodeGenerator::GenericBinaryOperation(Token::Value op,
                                            StaticType* type,
                                            OverwriteMode overwrite_mode) {
@@ -1021,9 +1155,11 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
   }
 
   // Get number type of left and right sub-expressions.
-  NumberInfo::Type operands_type =
+  NumberInfo operands_type =
       NumberInfo::Combine(left.number_info(), right.number_info());
 
+  NumberInfo result_type = CalculateNumberInfo(operands_type, op, right, left);
+
   Result answer;
   if (left_is_non_smi_constant || right_is_non_smi_constant) {
     // Go straight to the slow case, with no smi code.
@@ -1044,7 +1180,10 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
     // generate the inline Smi check code if this operation is part of a loop.
     // For all other operations only inline the Smi check code for likely smis
     // if the operation is part of a loop.
-    if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
+    if (loop_nesting() > 0 &&
+        (Token::IsBitOp(op) ||
+         operands_type.IsInteger32() ||
+         type->IsLikelySmi())) {
       answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
     } else {
       GenericBinaryOpStub stub(op,
@@ -1055,58 +1194,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
     }
   }
 
-  // Set NumberInfo of result according to the operation performed.
-  // Rely on the fact that smis have a 31 bit payload on ia32.
-  ASSERT(kSmiValueSize == 31);
-  NumberInfo::Type result_type = NumberInfo::kUnknown;
-  switch (op) {
-    case Token::COMMA:
-      result_type = right.number_info();
-      break;
-    case Token::OR:
-    case Token::AND:
-      // Result type can be either of the two input types.
-      result_type = operands_type;
-      break;
-    case Token::BIT_OR:
-    case Token::BIT_XOR:
-    case Token::BIT_AND:
-      // Result is always a number. Smi property of inputs is preserved.
-      result_type = (operands_type == NumberInfo::kSmi)
-          ? NumberInfo::kSmi
-          : NumberInfo::kNumber;
-      break;
-    case Token::SAR:
-      // Result is a smi if we shift by a constant >= 1, otherwise a number.
-      result_type = (right.is_constant() && right.handle()->IsSmi()
-                     && Smi::cast(*right.handle())->value() >= 1)
-          ? NumberInfo::kSmi
-          : NumberInfo::kNumber;
-      break;
-    case Token::SHR:
-      // Result is a smi if we shift by a constant >= 2, otherwise a number.
-      result_type = (right.is_constant() && right.handle()->IsSmi()
-                     && Smi::cast(*right.handle())->value() >= 2)
-          ? NumberInfo::kSmi
-          : NumberInfo::kNumber;
-      break;
-    case Token::ADD:
-      // Result could be a string or a number. Check types of inputs.
-      result_type = NumberInfo::IsNumber(operands_type)
-          ? NumberInfo::kNumber
-          : NumberInfo::kUnknown;
-      break;
-    case Token::SHL:
-    case Token::SUB:
-    case Token::MUL:
-    case Token::DIV:
-    case Token::MOD:
-      // Result is always a number.
-      result_type = NumberInfo::kNumber;
-      break;
-    default:
-      UNREACHABLE();
-  }
   answer.set_number_info(result_type);
   frame_->Push(&answer);
 }
@@ -1193,6 +1280,12 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
 }
 
 
+static void CheckTwoForSminess(MacroAssembler* masm,
+                               Register left, Register right, Register scratch,
+                               NumberInfo left_info, NumberInfo right_info,
+                               DeferredInlineBinaryOperation* deferred);
+
+
 // Implements a binary operation using a deferred code object and some
 // inline code to operate on smis quickly.
 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
@@ -1273,6 +1366,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
                                           (op == Token::DIV) ? eax : edx,
                                           left->reg(),
                                           right->reg(),
+                                          left->number_info(),
+                                          right->number_info(),
                                           overwrite_mode);
     if (left->reg().is(right->reg())) {
       __ test(left->reg(), Immediate(kSmiTagMask));
@@ -1370,11 +1465,11 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
                                           answer.reg(),
                                           left->reg(),
                                           ecx,
+                                          left->number_info(),
+                                          right->number_info(),
                                           overwrite_mode);
-    __ mov(answer.reg(), left->reg());
-    __ or_(answer.reg(), Operand(ecx));
-    __ test(answer.reg(), Immediate(kSmiTagMask));
-    deferred->Branch(not_zero);
+    CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
+                       left->number_info(), right->number_info(), deferred);
 
     // Untag both operands.
     __ mov(answer.reg(), left->reg());
@@ -1444,16 +1539,12 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
                                         answer.reg(),
                                         left->reg(),
                                         right->reg(),
+                                        left->number_info(),
+                                        right->number_info(),
                                         overwrite_mode);
-  if (left->reg().is(right->reg())) {
-    __ test(left->reg(), Immediate(kSmiTagMask));
-  } else {
-    __ mov(answer.reg(), left->reg());
-    __ or_(answer.reg(), Operand(right->reg()));
-    ASSERT(kSmiTag == 0);  // Adjust test if not the case.
-    __ test(answer.reg(), Immediate(kSmiTagMask));
-  }
-  deferred->Branch(not_zero);
+  CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
+                     left->number_info(), right->number_info(), deferred);
+
   __ mov(answer.reg(), left->reg());
   switch (op) {
     case Token::ADD:
@@ -1522,13 +1613,16 @@ class DeferredInlineSmiOperation: public DeferredCode {
   DeferredInlineSmiOperation(Token::Value op,
                              Register dst,
                              Register src,
+                             NumberInfo number_info,
                              Smi* value,
                              OverwriteMode overwrite_mode)
       : op_(op),
         dst_(dst),
         src_(src),
+        number_info_(number_info),
         value_(value),
         overwrite_mode_(overwrite_mode) {
+    if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
     set_comment("[ DeferredInlineSmiOperation");
   }
 
@@ -1538,6 +1632,7 @@ class DeferredInlineSmiOperation: public DeferredCode {
   Token::Value op_;
   Register dst_;
   Register src_;
+  NumberInfo number_info_;
   Smi* value_;
   OverwriteMode overwrite_mode_;
 };
@@ -1548,7 +1643,8 @@ void DeferredInlineSmiOperation::Generate() {
   GenericBinaryOpStub stub(
       op_,
       overwrite_mode_,
-      (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB);
+      (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB,
+      NumberInfo::Combine(NumberInfo::Smi(), number_info_));
   stub.GenerateCall(masm_, src_, value_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1562,9 +1658,11 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
                                      Register dst,
                                      Smi* value,
                                      Register src,
+                                     NumberInfo number_info,
                                      OverwriteMode overwrite_mode)
       : op_(op),
         dst_(dst),
+        number_info_(number_info),
         value_(value),
         src_(src),
         overwrite_mode_(overwrite_mode) {
@@ -1576,6 +1674,7 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
  private:
   Token::Value op_;
   Register dst_;
+  NumberInfo number_info_;
   Smi* value_;
   Register src_;
   OverwriteMode overwrite_mode_;
@@ -1583,7 +1682,11 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
 
 
 void DeferredInlineSmiOperationReversed::Generate() {
-  GenericBinaryOpStub igostub(op_, overwrite_mode_, NO_SMI_CODE_IN_STUB);
+  GenericBinaryOpStub igostub(
+      op_,
+      overwrite_mode_,
+      NO_SMI_CODE_IN_STUB,
+      NumberInfo::Combine(NumberInfo::Smi(), number_info_));
   igostub.GenerateCall(masm_, value_, src_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1595,9 +1698,14 @@ void DeferredInlineSmiOperationReversed::Generate() {
 class DeferredInlineSmiAdd: public DeferredCode {
  public:
   DeferredInlineSmiAdd(Register dst,
+                       NumberInfo number_info,
                        Smi* value,
                        OverwriteMode overwrite_mode)
-      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
+      : dst_(dst),
+        number_info_(number_info),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    if (number_info_.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
     set_comment("[ DeferredInlineSmiAdd");
   }
 
@@ -1605,6 +1713,7 @@ class DeferredInlineSmiAdd: public DeferredCode {
 
  private:
   Register dst_;
+  NumberInfo number_info_;
   Smi* value_;
   OverwriteMode overwrite_mode_;
 };
@@ -1613,7 +1722,11 @@ class DeferredInlineSmiAdd: public DeferredCode {
 void DeferredInlineSmiAdd::Generate() {
   // Undo the optimistic add operation and call the shared stub.
   __ sub(Operand(dst_), Immediate(value_));
-  GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB);
+  GenericBinaryOpStub igostub(
+      Token::ADD,
+      overwrite_mode_,
+      NO_SMI_CODE_IN_STUB,
+      NumberInfo::Combine(NumberInfo::Smi(), number_info_));
   igostub.GenerateCall(masm_, dst_, value_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1625,9 +1738,13 @@ void DeferredInlineSmiAdd::Generate() {
 class DeferredInlineSmiAddReversed: public DeferredCode {
  public:
   DeferredInlineSmiAddReversed(Register dst,
+                               NumberInfo number_info,
                                Smi* value,
                                OverwriteMode overwrite_mode)
-      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
+      : dst_(dst),
+        number_info_(number_info),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
     set_comment("[ DeferredInlineSmiAddReversed");
   }
 
@@ -1635,6 +1752,7 @@ class DeferredInlineSmiAddReversed: public DeferredCode {
 
  private:
   Register dst_;
+  NumberInfo number_info_;
   Smi* value_;
   OverwriteMode overwrite_mode_;
 };
@@ -1643,7 +1761,11 @@ class DeferredInlineSmiAddReversed: public DeferredCode {
 void DeferredInlineSmiAddReversed::Generate() {
   // Undo the optimistic add operation and call the shared stub.
   __ sub(Operand(dst_), Immediate(value_));
-  GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB);
+  GenericBinaryOpStub igostub(
+      Token::ADD,
+      overwrite_mode_,
+      NO_SMI_CODE_IN_STUB,
+      NumberInfo::Combine(NumberInfo::Smi(), number_info_));
   igostub.GenerateCall(masm_, value_, dst_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1656,9 +1778,14 @@ void DeferredInlineSmiAddReversed::Generate() {
 class DeferredInlineSmiSub: public DeferredCode {
  public:
   DeferredInlineSmiSub(Register dst,
+                       NumberInfo number_info,
                        Smi* value,
                        OverwriteMode overwrite_mode)
-      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
+      : dst_(dst),
+        number_info_(number_info),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
     set_comment("[ DeferredInlineSmiSub");
   }
 
@@ -1666,6 +1793,7 @@ class DeferredInlineSmiSub: public DeferredCode {
 
  private:
   Register dst_;
+  NumberInfo number_info_;
   Smi* value_;
   OverwriteMode overwrite_mode_;
 };
@@ -1674,7 +1802,11 @@ class DeferredInlineSmiSub: public DeferredCode {
 void DeferredInlineSmiSub::Generate() {
   // Undo the optimistic sub operation and call the shared stub.
   __ add(Operand(dst_), Immediate(value_));
-  GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, NO_SMI_CODE_IN_STUB);
+  GenericBinaryOpStub igostub(
+      Token::SUB,
+      overwrite_mode_,
+      NO_SMI_CODE_IN_STUB,
+      NumberInfo::Combine(NumberInfo::Smi(), number_info_));
   igostub.GenerateCall(masm_, dst_, value_);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1718,17 +1850,21 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
       DeferredCode* deferred = NULL;
       if (reversed) {
         deferred = new DeferredInlineSmiAddReversed(operand->reg(),
+                                                    operand->number_info(),
                                                     smi_value,
                                                     overwrite_mode);
       } else {
         deferred = new DeferredInlineSmiAdd(operand->reg(),
+                                            operand->number_info(),
                                             smi_value,
                                             overwrite_mode);
       }
       __ add(Operand(operand->reg()), Immediate(value));
       deferred->Branch(overflow);
-      __ test(operand->reg(), Immediate(kSmiTagMask));
-      deferred->Branch(not_zero);
+      if (!operand->number_info().IsSmi()) {
+        __ test(operand->reg(), Immediate(kSmiTagMask));
+        deferred->Branch(not_zero);
+      }
       deferred->BindExit();
       answer = *operand;
       break;
@@ -1743,24 +1879,29 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
         answer = allocator()->Allocate();
         ASSERT(answer.is_valid());
         __ Set(answer.reg(), Immediate(value));
-        deferred = new DeferredInlineSmiOperationReversed(op,
-                                                          answer.reg(),
-                                                          smi_value,
-                                                          operand->reg(),
-                                                          overwrite_mode);
+        deferred =
+            new DeferredInlineSmiOperationReversed(op,
+                                                   answer.reg(),
+                                                   smi_value,
+                                                   operand->reg(),
+                                                   operand->number_info(),
+                                                   overwrite_mode);
         __ sub(answer.reg(), Operand(operand->reg()));
       } else {
         operand->ToRegister();
         frame_->Spill(operand->reg());
         answer = *operand;
         deferred = new DeferredInlineSmiSub(operand->reg(),
+                                            operand->number_info(),
                                             smi_value,
                                             overwrite_mode);
         __ sub(Operand(operand->reg()), Immediate(value));
       }
       deferred->Branch(overflow);
-      __ test(answer.reg(), Immediate(kSmiTagMask));
-      deferred->Branch(not_zero);
+      if (!operand->number_info().IsSmi()) {
+        __ test(answer.reg(), Immediate(kSmiTagMask));
+        deferred->Branch(not_zero);
+      }
       deferred->BindExit();
       operand->Unuse();
       break;
@@ -1777,19 +1918,27 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
         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);
-        __ test(operand->reg(), Immediate(kSmiTagMask));
-        deferred->Branch(not_zero);
-        if (shift_value > 0) {
-          __ sar(operand->reg(), shift_value);
-          __ and_(operand->reg(), ~kSmiTagMask);
+        if (!operand->number_info().IsSmi()) {
+          DeferredInlineSmiOperation* deferred =
+              new DeferredInlineSmiOperation(op,
+                                             operand->reg(),
+                                             operand->reg(),
+                                             operand->number_info(),
+                                             smi_value,
+                                             overwrite_mode);
+          __ test(operand->reg(), Immediate(kSmiTagMask));
+          deferred->Branch(not_zero);
+          if (shift_value > 0) {
+            __ sar(operand->reg(), shift_value);
+            __ and_(operand->reg(), ~kSmiTagMask);
+          }
+          deferred->BindExit();
+        } else {
+          if (shift_value > 0) {
+            __ sar(operand->reg(), shift_value);
+            __ and_(operand->reg(), ~kSmiTagMask);
+          }
         }
-        deferred->BindExit();
         answer = *operand;
       }
       break;
@@ -1810,10 +1959,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
             new DeferredInlineSmiOperation(op,
                                            answer.reg(),
                                            operand->reg(),
+                                           operand->number_info(),
                                            smi_value,
                                            overwrite_mode);
-        __ test(operand->reg(), Immediate(kSmiTagMask));
-        deferred->Branch(not_zero);
+        if (!operand->number_info().IsSmi()) {
+          __ test(operand->reg(), Immediate(kSmiTagMask));
+          deferred->Branch(not_zero);
+        }
         __ mov(answer.reg(), operand->reg());
         __ SmiUntag(answer.reg());
         __ shr(answer.reg(), shift_value);
@@ -1855,10 +2007,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
                                                    answer.reg(),
                                                    smi_value,
                                                    right.reg(),
+                                                   right.number_info(),
                                                    overwrite_mode);
         __ mov(answer.reg(), Immediate(int_value));
         __ sar(ecx, kSmiTagSize);
-        deferred->Branch(carry);
+        if (!right.number_info().IsSmi()) {
+          deferred->Branch(carry);
+        }
         __ shl_cl(answer.reg());
         __ cmp(answer.reg(), 0xc0000000);
         deferred->Branch(sign);
@@ -1877,6 +2032,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
               new DeferredInlineSmiOperation(op,
                                              operand->reg(),
                                              operand->reg(),
+                                             operand->number_info(),
                                              smi_value,
                                              overwrite_mode);
           __ test(operand->reg(), Immediate(kSmiTagMask));
@@ -1891,10 +2047,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
               new DeferredInlineSmiOperation(op,
                                              answer.reg(),
                                              operand->reg(),
+                                             operand->number_info(),
                                              smi_value,
                                              overwrite_mode);
-          __ test(operand->reg(), Immediate(kSmiTagMask));
-          deferred->Branch(not_zero);
+          if (!operand->number_info().IsSmi()) {
+            __ test(operand->reg(), Immediate(kSmiTagMask));
+            deferred->Branch(not_zero);
+          }
           __ mov(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.
@@ -1918,20 +2077,25 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
       frame_->Spill(operand->reg());
       DeferredCode* deferred = NULL;
       if (reversed) {
-        deferred = new DeferredInlineSmiOperationReversed(op,
-                                                          operand->reg(),
-                                                          smi_value,
-                                                          operand->reg(),
-                                                          overwrite_mode);
+        deferred =
+            new DeferredInlineSmiOperationReversed(op,
+                                                   operand->reg(),
+                                                   smi_value,
+                                                   operand->reg(),
+                                                   operand->number_info(),
+                                                   overwrite_mode);
       } else {
         deferred =  new DeferredInlineSmiOperation(op,
                                                    operand->reg(),
                                                    operand->reg(),
+                                                   operand->number_info(),
                                                    smi_value,
                                                    overwrite_mode);
       }
-      __ test(operand->reg(), Immediate(kSmiTagMask));
-      deferred->Branch(not_zero);
+      if (!operand->number_info().IsSmi()) {
+        __ test(operand->reg(), Immediate(kSmiTagMask));
+        deferred->Branch(not_zero);
+      }
       if (op == Token::BIT_AND) {
         __ and_(Operand(operand->reg()), Immediate(value));
       } else if (op == Token::BIT_XOR) {
@@ -1958,6 +2122,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
             new DeferredInlineSmiOperation(op,
                                            operand->reg(),
                                            operand->reg(),
+                                           operand->number_info(),
                                            smi_value,
                                            overwrite_mode);
         // Check that lowest log2(value) bits of operand are zero, and test
@@ -1989,11 +2154,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
           (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);
+        DeferredCode* deferred =
+            new DeferredInlineSmiOperation(op,
+                                           operand->reg(),
+                                           operand->reg(),
+                                           operand->number_info(),
+                                           smi_value,
+                                           overwrite_mode);
         // Check for negative or non-Smi left hand side.
         __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
         deferred->Branch(not_zero);
@@ -2027,6 +2194,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
 
 
 static bool CouldBeNaN(const Result& result) {
+  if (result.number_info().IsSmi()) return false;
+  if (result.number_info().IsInteger32()) return false;
   if (!result.is_constant()) return true;
   if (!result.handle()->IsHeapNumber()) return false;
   return isnan(HeapNumber::cast(*result.handle())->value());
@@ -7130,8 +7299,10 @@ Result CodeGenerator::EmitKeyedLoad() {
     deferred->Branch(not_equal);
 
     // Check that the key is a smi.
-    __ test(key.reg(), Immediate(kSmiTagMask));
-    deferred->Branch(not_zero);
+    if (!key.is_smi()) {
+      __ test(key.reg(), Immediate(kSmiTagMask));
+      deferred->Branch(not_zero);
+    }
 
     // Get the elements array from the receiver and check that it
     // is not a dictionary.
@@ -7276,6 +7447,34 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
 #define __ ACCESS_MASM(masm)
 
 
+static void CheckTwoForSminess(MacroAssembler* masm,
+                               Register left, Register right, Register scratch,
+                               NumberInfo left_info, NumberInfo right_info,
+                               DeferredInlineBinaryOperation* deferred) {
+  if (left.is(right)) {
+    if (!left_info.IsSmi()) {
+      __ test(left, Immediate(kSmiTagMask));
+      deferred->Branch(not_zero);
+    }
+  } else if (!left_info.IsSmi()) {
+    if (!right_info.IsSmi()) {
+      __ mov(scratch, left);
+      __ or_(scratch, Operand(right));
+      __ test(scratch, Immediate(kSmiTagMask));
+      deferred->Branch(not_zero);
+    } else {
+      __ test(left, Immediate(kSmiTagMask));
+      deferred->Branch(not_zero);
+    }
+  } else {
+    if (!right_info.IsSmi()) {
+      __ test(right, Immediate(kSmiTagMask));
+      deferred->Branch(not_zero);
+    }
+  }
+}
+
+
 Handle<String> Reference::GetName() {
   ASSERT(type_ == NAMED);
   Property* property = expression_->AsProperty();
@@ -7776,6 +7975,22 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
     __ mov(left, Operand(esp, 2 * kPointerSize));
   }
 
+  if (static_operands_type_.IsSmi()) {
+    if (op_ == Token::BIT_OR) {
+      __ or_(right, Operand(left));
+      GenerateReturn(masm);
+      return;
+    } else if (op_ == Token::BIT_AND) {
+      __ and_(right, Operand(left));
+      GenerateReturn(masm);
+      return;
+    } else if (op_ == Token::BIT_XOR) {
+      __ xor_(right, Operand(left));
+      GenerateReturn(masm);
+      return;
+    }
+  }
+
   // 2. Prepare the smi check of both operands by oring them together.
   Comment smi_check_comment(masm, "-- Smi check arguments");
   Label not_smis;
@@ -8112,7 +8327,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         Label not_floats;
         if (CpuFeatures::IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
-          if (NumberInfo::IsNumber(static_operands_type_)) {
+          if (static_operands_type_.IsNumber()) {
             if (FLAG_debug_code) {
               // Assert at runtime that inputs are only numbers.
               __ AbortIfNotNumber(edx,
@@ -8120,7 +8335,11 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
               __ AbortIfNotNumber(eax,
                                   "GenericBinaryOpStub operand not a number.");
             }
-            FloatingPointHelper::LoadSSE2Operands(masm);
+            if (static_operands_type_.IsSmi()) {
+              FloatingPointHelper::LoadSSE2Smis(masm, ecx);
+            } else {
+              FloatingPointHelper::LoadSSE2Operands(masm);
+            }
           } else {
             FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
           }
@@ -8136,7 +8355,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
           GenerateReturn(masm);
         } else {  // SSE2 not available, use FPU.
-          if (NumberInfo::IsNumber(static_operands_type_)) {
+          if (static_operands_type_.IsNumber()) {
             if (FLAG_debug_code) {
               // Assert at runtime that inputs are only numbers.
               __ AbortIfNotNumber(edx,
@@ -8190,7 +8409,10 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
       case Token::SHL:
       case Token::SHR: {
         Label non_smi_result;
-        FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
+        FloatingPointHelper::LoadAsIntegers(masm,
+                                            static_operands_type_,
+                                            use_sse3_,
+                                            &call_runtime);
         switch (op_) {
           case Token::BIT_OR:  __ or_(eax, Operand(ecx)); break;
           case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
@@ -8719,24 +8941,29 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
 // trashed registers.
 void IntegerConvert(MacroAssembler* masm,
                     Register source,
+                    NumberInfo number_info,
                     bool use_sse3,
                     Label* conversion_failure) {
   ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx));
   Label done, right_exponent, normal_exponent;
   Register scratch = ebx;
   Register scratch2 = edi;
-  // Get exponent word.
-  __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
-  // Get exponent alone in scratch2.
-  __ mov(scratch2, scratch);
-  __ and_(scratch2, HeapNumber::kExponentMask);
+  if (!number_info.IsInteger32() || !use_sse3) {
+    // Get exponent word.
+    __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
+    // Get exponent alone in scratch2.
+    __ mov(scratch2, scratch);
+    __ and_(scratch2, HeapNumber::kExponentMask);
+  }
   if (use_sse3) {
     CpuFeatures::Scope scope(SSE3);
-    // Check whether the exponent is too big for a 64 bit signed integer.
-    static const uint32_t kTooBigExponent =
-        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
-    __ cmp(Operand(scratch2), Immediate(kTooBigExponent));
-    __ j(greater_equal, conversion_failure);
+    if (!number_info.IsInteger32()) {
+      // Check whether the exponent is too big for a 64 bit signed integer.
+      static const uint32_t kTooBigExponent =
+          (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
+      __ cmp(Operand(scratch2), Immediate(kTooBigExponent));
+      __ j(greater_equal, conversion_failure);
+    }
     // Load x87 register with heap number.
     __ fld_d(FieldOperand(source, HeapNumber::kValueOffset));
     // Reserve space for 64 bit answer.
@@ -8850,16 +9077,66 @@ void IntegerConvert(MacroAssembler* masm,
 
 // Input: edx, eax are the left and right objects of a bit op.
 // Output: eax, ecx are left and right integers for a bit op.
-void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
-                                         bool use_sse3,
-                                         Label* conversion_failure) {
+void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm,
+                                                NumberInfo number_info,
+                                                bool use_sse3,
+                                                Label* conversion_failure) {
   // Check float operands.
   Label arg1_is_object, check_undefined_arg1;
   Label arg2_is_object, check_undefined_arg2;
   Label load_arg2, done;
 
+  if (!number_info.IsHeapNumber()) {
+    if (!number_info.IsSmi()) {
+      __ test(edx, Immediate(kSmiTagMask));
+      __ j(not_zero, &arg1_is_object);
+    }
+    __ SmiUntag(edx);
+    __ jmp(&load_arg2);
+  }
+
+  __ bind(&arg1_is_object);
+
+  // Get the untagged integer version of the edx heap number in ecx.
+  IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure);
+  __ mov(edx, ecx);
+
+  // Here edx has the untagged integer, eax has a Smi or a heap number.
+  __ bind(&load_arg2);
+  if (!number_info.IsHeapNumber()) {
+    // Test if arg2 is a Smi.
+    if (!number_info.IsSmi()) {
+      __ test(eax, Immediate(kSmiTagMask));
+      __ j(not_zero, &arg2_is_object);
+    }
+    __ SmiUntag(eax);
+    __ mov(ecx, eax);
+    __ jmp(&done);
+  }
+
+  __ bind(&arg2_is_object);
+
+  // Get the untagged integer version of the eax heap number in ecx.
+  IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure);
+  __ bind(&done);
+  __ mov(eax, edx);
+}
+
+
+// Input: edx, eax are the left and right objects of a bit op.
+// Output: eax, ecx are left and right integers for a bit op.
+void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
+                                                 bool use_sse3,
+                                                 Label* conversion_failure) {
+  // Check float operands.
+  Label arg1_is_object, check_undefined_arg1;
+  Label arg2_is_object, check_undefined_arg2;
+  Label load_arg2, done;
+
+  // Test if arg1 is a Smi.
   __ test(edx, Immediate(kSmiTagMask));
   __ j(not_zero, &arg1_is_object);
+
   __ SmiUntag(edx);
   __ jmp(&load_arg2);
 
@@ -8874,15 +9151,22 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
   __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
   __ cmp(ebx, Factory::heap_number_map());
   __ j(not_equal, &check_undefined_arg1);
+
   // Get the untagged integer version of the edx heap number in ecx.
-  IntegerConvert(masm, edx, use_sse3, conversion_failure);
+  IntegerConvert(masm,
+                 edx,
+                 NumberInfo::Unknown(),
+                 use_sse3,
+                 conversion_failure);
   __ mov(edx, ecx);
 
   // Here edx has the untagged integer, eax has a Smi or a heap number.
   __ bind(&load_arg2);
+
   // Test if arg2 is a Smi.
   __ test(eax, Immediate(kSmiTagMask));
   __ j(not_zero, &arg2_is_object);
+
   __ SmiUntag(eax);
   __ mov(ecx, eax);
   __ jmp(&done);
@@ -8898,13 +9182,30 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
   __ cmp(ebx, Factory::heap_number_map());
   __ j(not_equal, &check_undefined_arg2);
+
   // Get the untagged integer version of the eax heap number in ecx.
-  IntegerConvert(masm, eax, use_sse3, conversion_failure);
+  IntegerConvert(masm,
+                 eax,
+                 NumberInfo::Unknown(),
+                 use_sse3,
+                 conversion_failure);
   __ bind(&done);
   __ mov(eax, edx);
 }
 
 
+void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
+                                         NumberInfo number_info,
+                                         bool use_sse3,
+                                         Label* conversion_failure) {
+  if (number_info.IsNumber()) {
+    LoadNumbersAsIntegers(masm, number_info, use_sse3, conversion_failure);
+  } else {
+    LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure);
+  }
+}
+
+
 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
                                            Register number) {
   Label load_smi, done;
@@ -9141,7 +9442,11 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
     __ j(not_equal, &slow, not_taken);
 
     // Convert the heap number in eax to an untagged integer in ecx.
-    IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), &slow);
+    IntegerConvert(masm,
+                   eax,
+                   NumberInfo::Unknown(),
+                   CpuFeatures::IsSupported(SSE3),
+                   &slow);
 
     // Do the bitwise operation and check if the result fits in a smi.
     Label try_float;
index 0b605b606c28e3f36b11dbe068f8a7250a751ad7..36c975b64e9b25f8d4d8980be8839586262babe9 100644 (file)
@@ -496,8 +496,8 @@ class CodeGenerator: public AstVisitor {
 
   // To prevent long attacker-controlled byte sequences, integer constants
   // from the JavaScript source are loaded in two parts if they are larger
-  // than 16 bits.
-  static const int kMaxSmiInlinedBits = 16;
+  // than 17 bits.
+  static const int kMaxSmiInlinedBits = 17;
   bool IsUnsafeSmi(Handle<Object> value);
   // Load an integer constant x into a register target or into the stack using
   // at most 16 bits of user-controlled data per assembly operation.
@@ -695,7 +695,7 @@ class GenericBinaryOpStub: public CodeStub {
   GenericBinaryOpStub(Token::Value op,
                       OverwriteMode mode,
                       GenericBinaryFlags flags,
-                      NumberInfo::Type operands_type = NumberInfo::kUnknown)
+                      NumberInfo operands_type)
       : op_(op),
         mode_(mode),
         flags_(flags),
@@ -704,6 +704,9 @@ class GenericBinaryOpStub: public CodeStub {
         static_operands_type_(operands_type),
         runtime_operands_type_(BinaryOpIC::DEFAULT),
         name_(NULL) {
+    if (static_operands_type_.IsSmi()) {
+      mode_ = NO_OVERWRITE;
+    }
     use_sse3_ = CpuFeatures::IsSupported(SSE3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
@@ -715,7 +718,8 @@ class GenericBinaryOpStub: public CodeStub {
         args_in_registers_(ArgsInRegistersBits::decode(key)),
         args_reversed_(ArgsReversedBits::decode(key)),
         use_sse3_(SSE3Bits::decode(key)),
-        static_operands_type_(StaticTypeInfoBits::decode(key)),
+        static_operands_type_(NumberInfo::ExpandedRepresentation(
+            StaticTypeInfoBits::decode(key))),
         runtime_operands_type_(runtime_operands_type),
         name_(NULL) {
   }
@@ -741,7 +745,7 @@ class GenericBinaryOpStub: public CodeStub {
   bool use_sse3_;
 
   // Number type information of operands, determined by code generator.
-  NumberInfo::Type static_operands_type_;
+  NumberInfo static_operands_type_;
 
   // Operand type information determined at runtime.
   BinaryOpIC::TypeInfo runtime_operands_type_;
@@ -760,7 +764,7 @@ class GenericBinaryOpStub: public CodeStub {
            static_cast<int>(flags_),
            static_cast<int>(args_in_registers_),
            static_cast<int>(args_reversed_),
-           NumberInfo::ToString(static_operands_type_));
+           static_operands_type_.ToString());
   }
 #endif
 
@@ -771,7 +775,7 @@ class GenericBinaryOpStub: public CodeStub {
   class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
   class ArgsReversedBits: public BitField<bool, 11, 1> {};
   class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
-  class StaticTypeInfoBits: public BitField<NumberInfo::Type, 13, 3> {};
+  class StaticTypeInfoBits: public BitField<int, 13, 3> {};
   class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 16, 2> {};
 
   Major MajorKey() { return GenericBinaryOp; }
@@ -783,7 +787,8 @@ class GenericBinaryOpStub: public CodeStub {
            | SSE3Bits::encode(use_sse3_)
            | ArgsInRegistersBits::encode(args_in_registers_)
            | ArgsReversedBits::encode(args_reversed_)
-           | StaticTypeInfoBits::encode(static_operands_type_)
+           | StaticTypeInfoBits::encode(
+                 static_operands_type_.ThreeBitRepresentation())
            | RuntimeTypeInfoBits::encode(runtime_operands_type_);
   }
 
index 6eefc024f0c2d119a74b5a577aa24a34b3541eb5..6e3ae105d1ab94997481c8888ebd08e8539a4bcf 100644 (file)
@@ -1130,7 +1130,8 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
   __ push(result_register());
   GenericBinaryOpStub stub(op,
                            NO_OVERWRITE,
-                           NO_GENERIC_BINARY_FLAGS);
+                           NO_GENERIC_BINARY_FLAGS,
+                           NumberInfo::Unknown());
   __ CallStub(&stub);
   Apply(context, eax);
 }
@@ -1744,7 +1745,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   // Call stub for +1/-1.
   GenericBinaryOpStub stub(expr->binary_op(),
                            NO_OVERWRITE,
-                           NO_GENERIC_BINARY_FLAGS);
+                           NO_GENERIC_BINARY_FLAGS,
+                           NumberInfo::Unknown());
   stub.GenerateCall(masm(), eax, Smi::FromInt(1));
   __ bind(&done);
 
index 20539bff957b8f521c3b307c590f02e53882f6fe..3ccfe8cd025334c7c280457eeb0717f2eebc62fc 100644 (file)
@@ -49,6 +49,7 @@ void Result::ToRegister() {
                                                  Immediate(handle()));
     }
     // This result becomes a copy of the fresh one.
+    fresh.set_number_info(number_info());
     *this = fresh;
   }
   ASSERT(is_register());
index 97b075518beecb0d7f65da370feaff4d93b7d91f..7b03a5b2f7264d347ae0a4c85565ea75bbdb0cc4 100644 (file)
@@ -162,7 +162,7 @@ void VirtualFrame::MakeMergable() {
     if (element.is_constant() || element.is_copy()) {
       if (element.is_synced()) {
         // Just spill.
-        elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown);
+        elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown());
       } else {
         // Allocate to a register.
         FrameElement backing_element;  // Invalid if not a copy.
@@ -174,7 +174,7 @@ void VirtualFrame::MakeMergable() {
         elements_[i] =
             FrameElement::RegisterElement(fresh.reg(),
                                           FrameElement::NOT_SYNCED,
-                                          NumberInfo::kUnknown);
+                                          NumberInfo::Unknown());
         Use(fresh.reg(), i);
 
         // Emit a move.
@@ -207,7 +207,7 @@ void VirtualFrame::MakeMergable() {
       // The copy flag is not relied on before the end of this loop,
       // including when registers are spilled.
       elements_[i].clear_copied();
-      elements_[i].set_number_info(NumberInfo::kUnknown);
+      elements_[i].set_number_info(NumberInfo::Unknown());
     }
   }
 }
@@ -1062,7 +1062,7 @@ Result VirtualFrame::Pop() {
   ASSERT(element.is_valid());
 
   // Get number type information of the result.
-  NumberInfo::Type info;
+  NumberInfo info;
   if (!element.is_copy()) {
     info = element.number_info();
   } else {
@@ -1137,7 +1137,7 @@ void VirtualFrame::EmitPop(Operand operand) {
 }
 
 
-void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Register reg, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -1145,7 +1145,7 @@ void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) {
 }
 
 
-void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Operand operand, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -1153,7 +1153,7 @@ void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) {
 }
 
 
-void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
index 407e2a1645bd53a43c4ab471e5a154fe2896b20c..cd2d18f432ddd8949ba50f174dc338cda86552a2 100644 (file)
@@ -84,7 +84,7 @@ class VirtualFrame: public ZoneObject {
 
   // Create a duplicate of an existing valid frame element.
   FrameElement CopyElementAt(int index,
-    NumberInfo::Type info = NumberInfo::kUninitialized);
+    NumberInfo info = NumberInfo::Uninitialized());
 
   // The number of elements on the virtual frame.
   int element_count() { return elements_.length(); }
@@ -388,14 +388,14 @@ class VirtualFrame: public ZoneObject {
   // Push an element on top of the expression stack and emit a
   // corresponding push instruction.
   void EmitPush(Register reg,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(Operand operand,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(Immediate immediate,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
 
   // Push an element on the virtual frame.
-  inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
+  inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown());
   inline void Push(Handle<Object> value);
   inline void Push(Smi* value);
 
index 12fabc329d434bf11ea38ce4fb1c5fc80b9be16e..6db008153625f895b54b202d443b28e9a7dc88a6 100644 (file)
@@ -46,7 +46,7 @@ void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
     entry_frame_->elements_[target->index()].set_copied();
   }
   if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
-    element->set_number_info(NumberInfo::kUnknown);
+    element->set_number_info(NumberInfo::Unknown());
   }
 }
 
index ab09870b952431bfd3c2190151a8ba3cd3c9bfea..7b1ced7eb30dd5e6e91b2969bcdd2bbb4dbf4e6f 100644 (file)
@@ -135,7 +135,7 @@ void JumpTarget::ComputeEntryFrame() {
     FrameElement* target = elements[index];
     if (target == NULL) {
       entry_frame_->elements_.Add(
-          FrameElement::MemoryElement(NumberInfo::kUninitialized));
+          FrameElement::MemoryElement(NumberInfo::Uninitialized()));
     } else {
       entry_frame_->elements_.Add(*target);
       InitializeEntryElement(index, target);
@@ -152,12 +152,12 @@ void JumpTarget::ComputeEntryFrame() {
       RegisterFile candidate_registers;
       int best_count = kMinInt;
       int best_reg_num = RegisterAllocator::kInvalidRegister;
-      NumberInfo::Type info = NumberInfo::kUninitialized;
+      NumberInfo info = NumberInfo::Uninitialized();
 
       for (int j = 0; j < reaching_frames_.length(); j++) {
         FrameElement element = reaching_frames_[j]->elements_[i];
         if (direction_ == BIDIRECTIONAL) {
-            info = NumberInfo::kUnknown;
+          info = NumberInfo::Unknown();
         } else if (!element.is_copy()) {
           info = NumberInfo::Combine(info, element.number_info());
         } else {
@@ -181,7 +181,7 @@ void JumpTarget::ComputeEntryFrame() {
 
       // We must have a number type information now (not for copied elements).
       ASSERT(entry_frame_->elements_[i].is_copy()
-             || info != NumberInfo::kUninitialized);
+             || !info.IsUninitialized());
 
       // If the value is synced on all frames, put it in memory.  This
       // costs nothing at the merge code but will incur a
@@ -211,7 +211,7 @@ void JumpTarget::ComputeEntryFrame() {
         Register reg = RegisterAllocator::ToRegister(best_reg_num);
         entry_frame_->elements_[i] =
             FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
-                                          NumberInfo::kUninitialized);
+                                          NumberInfo::Uninitialized());
         if (is_copied) entry_frame_->elements_[i].set_copied();
         entry_frame_->set_register_location(reg, i);
       }
@@ -225,8 +225,7 @@ void JumpTarget::ComputeEntryFrame() {
   if (direction_ == BIDIRECTIONAL) {
     for (int i = 0; i < length; ++i) {
       if (!entry_frame_->elements_[i].is_copy()) {
-        ASSERT(entry_frame_->elements_[i].number_info() ==
-               NumberInfo::kUnknown);
+        ASSERT(entry_frame_->elements_[i].number_info().IsUnknown());
       }
     }
   }
index c6f32e47c1d86b453dd1f1d82edb3b278272b28a..bfc0d9fd2dcc8a70031d66cb651bf6ec00f2da76 100644 (file)
 namespace v8 {
 namespace internal {
 
-class NumberInfo : public AllStatic {
+//        Unknown
+//           |
+//         Number
+//         /    |
+//  HeapNumber Integer32
+//        |      |
+//        |     Smi
+//        |     /
+//      Uninitialized.
+
+class NumberInfo {
  public:
-  enum Type {
-    kUnknown = 0,
-    kNumber = 1,
-    kSmi = 3,
-    kHeapNumber = 5,
-    kUninitialized = 7
-  };
+  NumberInfo() { }
+
+  static inline NumberInfo Unknown();
+  // We know it's a number of some sort.
+  static inline NumberInfo Number();
+  // We know it's signed or unsigned 32 bit integer.
+  static inline NumberInfo Integer32();
+  // We know it's a Smi.
+  static inline NumberInfo Smi();
+  // We know it's a heap number.
+  static inline NumberInfo HeapNumber();
+  // We haven't started collecting info yet.
+  static inline NumberInfo Uninitialized();
+
+  // Return compact representation.  Very sensitive to enum values below!
+  int ThreeBitRepresentation() {
+    ASSERT(type_ != kUninitializedType);
+    int answer = type_ > 6 ? type_ -2 : type_;
+    ASSERT(answer >= 0);
+    ASSERT(answer <= 7);
+    return answer;
+  }
+
+  // Decode compact representation.  Very sensitive to enum values below!
+  static NumberInfo ExpandedRepresentation(int three_bit_representation) {
+    Type t = static_cast<Type>(three_bit_representation >= 6 ?
+                               three_bit_representation + 2 :
+                               three_bit_representation);
+    ASSERT(t == kUnknownType ||
+           t == kNumberType ||
+           t == kInteger32Type ||
+           t == kSmiType ||
+           t == kHeapNumberType);
+    return NumberInfo(t);
+  }
+
+  int ToInt() {
+    return type_;
+  }
+
+  static NumberInfo FromInt(int bit_representation) {
+    Type t = static_cast<Type>(bit_representation);
+    ASSERT(t == kUnknownType ||
+           t == kNumberType ||
+           t == kInteger32Type ||
+           t == kSmiType ||
+           t == kHeapNumberType);
+    return NumberInfo(t);
+  }
 
   // Return the weakest (least precise) common type.
-  static Type Combine(Type a, Type b) {
-    // Make use of the order of enum values.
-    return static_cast<Type>(a & b);
+  static NumberInfo Combine(NumberInfo a, NumberInfo b) {
+    return NumberInfo(static_cast<Type>(a.type_ & b.type_));
+  }
+
+  inline bool IsUnknown() {
+    return type_ == kUnknownType;
+  }
+
+  inline bool IsNumber() {
+    ASSERT(type_ != kUninitializedType);
+    return ((type_ & kNumberType) == kNumberType);
+  }
+
+  inline bool IsSmi() {
+    ASSERT(type_ != kUninitializedType);
+    return ((type_ & kSmiType) == kSmiType);
+  }
+
+  inline bool IsInteger32() {
+    ASSERT(type_ != kUninitializedType);
+    return ((type_ & kInteger32Type) == kInteger32Type);
+  }
+
+  inline bool IsHeapNumber() {
+    ASSERT(type_ != kUninitializedType);
+    return ((type_ & kHeapNumberType) == kHeapNumberType);
   }
 
-  static bool IsNumber(Type a) {
-    ASSERT(a != kUninitialized);
-    return ((a & kNumber) != 0);
+  inline bool IsUninitialized() {
+    return type_ == kUninitializedType;
   }
 
-  static const char* ToString(Type a) {
-    switch (a) {
-      case kUnknown: return "UnknownType";
-      case kNumber: return "NumberType";
-      case kSmi: return "SmiType";
-      case kHeapNumber: return "HeapNumberType";
-      case kUninitialized:
+  const char* ToString() {
+    switch (type_) {
+      case kUnknownType: return "UnknownType";
+      case kNumberType: return "NumberType";
+      case kSmiType: return "SmiType";
+      case kHeapNumberType: return "HeapNumberType";
+      case kInteger32Type: return "Integer32Type";
+      case kUninitializedType:
         UNREACHABLE();
         return "UninitializedType";
     }
     UNREACHABLE();
     return "Unreachable code";
   }
+
+ private:
+  enum Type {
+    kUnknownType = 0,
+    kNumberType = 1,
+    kInteger32Type = 3,
+    kSmiType = 7,
+    kHeapNumberType = 9,
+    kUninitializedType = 15
+  };
+  explicit inline NumberInfo(Type t) : type_(t) { }
+
+  Type type_;
 };
 
+
+NumberInfo NumberInfo::Unknown() {
+  return NumberInfo(kUnknownType);
+}
+
+
+NumberInfo NumberInfo::Number() {
+  return NumberInfo(kNumberType);
+}
+
+
+NumberInfo NumberInfo::Integer32() {
+  return NumberInfo(kInteger32Type);
+}
+
+
+NumberInfo NumberInfo::Smi() {
+  return NumberInfo(kSmiType);
+}
+
+
+NumberInfo NumberInfo::HeapNumber() {
+  return NumberInfo(kHeapNumberType);
+}
+
+
+NumberInfo NumberInfo::Uninitialized() {
+  return NumberInfo(kUninitializedType);
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_NUMBER_INFO_H_
index 718da36012e450df8cd7c73b91413d46b37c8de3..8453104ee29ba5047aebfb8ba19042ff8c9f8e0a 100644 (file)
@@ -103,6 +103,45 @@ void RegisterAllocator::Unuse(Register reg) {
   registers_.Unuse(ToNumber(reg));
 }
 
+
+NumberInfo Result::number_info() const {
+  ASSERT(is_valid());
+  if (!is_constant()) {
+    return NumberInfo::FromInt(NumberInfoField::decode(value_));
+  }
+  Handle<Object> value = handle();
+  if (value->IsSmi()) return NumberInfo::Smi();
+  if (value->IsHeapNumber()) return NumberInfo::HeapNumber();
+  return NumberInfo::Unknown();
+}
+
+
+void Result::set_number_info(NumberInfo info) {
+  ASSERT(is_valid());
+  value_ &= ~NumberInfoField::mask();
+  value_ |= NumberInfoField::encode(info.ToInt());
+}
+
+
+bool Result::is_number() const {
+  return number_info().IsNumber();
+}
+
+
+bool Result::is_smi() const {
+  return number_info().IsSmi();
+}
+
+
+bool Result::is_integer32() const {
+  return number_info().IsInteger32();
+}
+
+
+bool Result::is_heap_number() const {
+  return number_info().IsHeapNumber();
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_REGISTER_ALLOCATOR_INL_H_
index 1655b4ac1206751e2a01b4f2a7bf847f759a1801..64e44287924212e49e4120c8bf1330becba322af 100644 (file)
@@ -38,11 +38,11 @@ namespace internal {
 // Result implementation.
 
 
-Result::Result(Register reg, NumberInfo::Type info) {
+Result::Result(Register reg, NumberInfo info) {
   ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
   CodeGeneratorScope::Current()->allocator()->Use(reg);
   value_ = TypeField::encode(REGISTER)
-      | NumberInfoField::encode(info)
+      | NumberInfoField::encode(info.ToInt())
       | DataField::encode(reg.code_);
 }
 
@@ -53,23 +53,6 @@ Result::ZoneObjectList* Result::ConstantList() {
 }
 
 
-NumberInfo::Type Result::number_info() {
-  ASSERT(is_valid());
-  if (!is_constant()) return NumberInfoField::decode(value_);
-  Handle<Object> value = handle();
-  if (value->IsSmi()) return NumberInfo::kSmi;
-  if (value->IsHeapNumber()) return NumberInfo::kHeapNumber;
-  return NumberInfo::kUnknown;
-}
-
-
-void Result::set_number_info(NumberInfo::Type info) {
-  ASSERT(is_valid());
-  value_ = value_ & ~NumberInfoField::mask();
-  value_ = value_ | NumberInfoField::encode(info);
-}
-
-
 // -------------------------------------------------------------------------
 // RegisterAllocator implementation.
 
index 747200a056bd9ddd04b359d78da0785e19c9e4e9..2a7b820a5314bed652cae81c8a05fc8704806aab 100644 (file)
@@ -65,12 +65,12 @@ class Result BASE_EMBEDDED {
   Result() { invalidate(); }
 
   // Construct a register Result.
-  explicit Result(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
+  explicit Result(Register reg, NumberInfo info = NumberInfo::Unknown());
 
   // Construct a Result whose value is a compile-time constant.
   explicit Result(Handle<Object> value) {
     value_ = TypeField::encode(CONSTANT)
-        | NumberInfoField::encode(NumberInfo::kUninitialized)
+        | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt())
         | DataField::encode(ConstantList()->length());
     ConstantList()->Add(value);
   }
@@ -101,13 +101,12 @@ class Result BASE_EMBEDDED {
 
   void invalidate() { value_ = TypeField::encode(INVALID); }
 
-  NumberInfo::Type number_info();
-  void set_number_info(NumberInfo::Type info);
-  bool is_number() {
-    return (number_info() & NumberInfo::kNumber) != 0;
-  }
-  bool is_smi() { return number_info() == NumberInfo::kSmi; }
-  bool is_heap_number() { return number_info() == NumberInfo::kHeapNumber; }
+  inline NumberInfo number_info() const;
+  inline void set_number_info(NumberInfo info);
+  inline bool is_number() const;
+  inline bool is_smi() const;
+  inline bool is_integer32() const;
+  inline bool is_heap_number() const;
 
   bool is_valid() const { return type() != INVALID; }
   bool is_register() const { return type() == REGISTER; }
@@ -140,8 +139,8 @@ class Result BASE_EMBEDDED {
   uint32_t value_;
 
   class TypeField: public BitField<Type, 0, 2> {};
-  class NumberInfoField : public BitField<NumberInfo::Type, 2, 3> {};
-  class DataField: public BitField<uint32_t, 5, 32 - 5> {};
+  class NumberInfoField : public BitField<int, 2, 4> {};
+  class DataField: public BitField<uint32_t, 6, 32 - 6> {};
 
   inline void CopyTo(Result* destination) const;
 
index 9a744f55090992f8199cc05f692c2299a45d9108..9aa88fe1846da6b1ec9f0d190cc4a3731e86b86f 100644 (file)
@@ -40,7 +40,7 @@ VirtualFrame::VirtualFrame()
     : elements_(parameter_count() + local_count() + kPreallocatedElements),
       stack_pointer_(parameter_count() + 1) {  // 0-based index of TOS.
   for (int i = 0; i <= stack_pointer_; i++) {
-    elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown));
+    elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown()));
   }
   for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
     register_locations_[i] = kIllegalIndex;
@@ -65,7 +65,7 @@ void VirtualFrame::PushFrameSlotAt(int index) {
 }
 
 
-void VirtualFrame::Push(Register reg, NumberInfo::Type info) {
+void VirtualFrame::Push(Register reg, NumberInfo info) {
   if (is_used(reg)) {
     int index = register_location(reg);
     FrameElement element = CopyElementAt(index, info);
index d5b5f42ae888c031381299420ad718b343b2bafb..8c13a6a862d07e619ffbadf99adbe44330dea251 100644 (file)
@@ -43,7 +43,7 @@ namespace internal {
 // not conflict with the existing type information and must be equally or
 // more precise. The default parameter value kUninitialized means that there
 // is no additional information.
-FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo::Type info) {
+FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo info) {
   ASSERT(index >= 0);
   ASSERT(index < element_count());
 
@@ -74,14 +74,14 @@ FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo::Type info) {
       result.set_index(index);
       elements_[index].set_copied();
       // Update backing element's number information.
-      NumberInfo::Type existing = elements_[index].number_info();
-      ASSERT(existing != NumberInfo::kUninitialized);
+      NumberInfo existing = elements_[index].number_info();
+      ASSERT(!existing.IsUninitialized());
       // Assert that the new type information (a) does not conflict with the
       // existing one and (b) is equally or more precise.
-      ASSERT((info == NumberInfo::kUninitialized) ||
-             (existing | info) != NumberInfo::kUninitialized);
-      ASSERT(existing <= info);
-      elements_[index].set_number_info(info != NumberInfo::kUninitialized
+      ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt());
+      ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt());
+
+      elements_[index].set_number_info(!info.IsUninitialized()
                                        ? info
                                        : existing);
       break;
@@ -104,7 +104,7 @@ void VirtualFrame::Adjust(int count) {
   ASSERT(stack_pointer_ == element_count() - 1);
 
   for (int i = 0; i < count; i++) {
-    elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown));
+    elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown()));
   }
   stack_pointer_ += count;
 }
@@ -152,7 +152,7 @@ void VirtualFrame::SpillElementAt(int index) {
   SyncElementAt(index);
   // Number type information is preserved.
   // Copies get their number information from their backing element.
-  NumberInfo::Type info;
+  NumberInfo info;
   if (!elements_[index].is_copy()) {
     info = elements_[index].number_info();
   } else {
index d3d2e55bce1b4776a4cf91cb66f44fb8164b92c8..e9dfe2901d756dc94d5509e7a39956a69ffe5525 100644 (file)
@@ -5280,7 +5280,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
   }
 
   // Get number type of left and right sub-expressions.
-  NumberInfo::Type operands_type =
+  NumberInfo operands_type =
       NumberInfo::Combine(left.number_info(), right.number_info());
 
   Result answer;
@@ -5316,7 +5316,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
   // Set NumberInfo of result according to the operation performed.
   // We rely on the fact that smis have a 32 bit payload on x64.
   ASSERT(kSmiValueSize == 32);
-  NumberInfo::Type result_type = NumberInfo::kUnknown;
+  NumberInfo result_type = NumberInfo::Unknown();
   switch (op) {
     case Token::COMMA:
       result_type = right.number_info();
@@ -5330,32 +5330,32 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
     case Token::BIT_XOR:
     case Token::BIT_AND:
       // Result is always a smi.
-      result_type = NumberInfo::kSmi;
+      result_type = NumberInfo::Smi();
       break;
     case Token::SAR:
     case Token::SHL:
       // Result is always a smi.
-      result_type = NumberInfo::kSmi;
+      result_type = NumberInfo::Smi();
       break;
     case Token::SHR:
       // Result of x >>> y is always a smi if y >= 1, otherwise a number.
       result_type = (right.is_constant() && right.handle()->IsSmi()
                      && Smi::cast(*right.handle())->value() >= 1)
-          ? NumberInfo::kSmi
-          : NumberInfo::kNumber;
+          ? NumberInfo::Smi()
+          : NumberInfo::Number();
       break;
     case Token::ADD:
       // Result could be a string or a number. Check types of inputs.
-      result_type = NumberInfo::IsNumber(operands_type)
-          ? NumberInfo::kNumber
-          : NumberInfo::kUnknown;
+      result_type = operands_type.IsNumber()
+          ? NumberInfo::Number()
+          : NumberInfo::Unknown();
       break;
     case Token::SUB:
     case Token::MUL:
     case Token::DIV:
     case Token::MOD:
       // Result is always a number.
-      result_type = NumberInfo::kNumber;
+      result_type = NumberInfo::Number();
       break;
     default:
       UNREACHABLE();
@@ -8332,7 +8332,7 @@ const char* GenericBinaryOpStub::GetName() {
                args_in_registers_ ? "RegArgs" : "StackArgs",
                args_reversed_ ? "_R" : "",
                use_sse3_ ? "SSE3" : "SSE2",
-               NumberInfo::ToString(operands_type_));
+               operands_type_.ToString());
   return name_;
 }
 
@@ -8656,7 +8656,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
     case Token::DIV: {
       // rax: y
       // rdx: x
-      if (NumberInfo::IsNumber(operands_type_)) {
+      if (operands_type_.IsNumber()) {
         if (FLAG_debug_code) {
           // Assert at runtime that inputs are only numbers.
           __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
index 62f82a28e9aa57de2a534a3284794228dce0f465..7c088303940d07742c2ee791b14517c659fb0344 100644 (file)
@@ -661,7 +661,7 @@ class GenericBinaryOpStub: public CodeStub {
   GenericBinaryOpStub(Token::Value op,
                       OverwriteMode mode,
                       GenericBinaryFlags flags,
-                      NumberInfo::Type operands_type = NumberInfo::kUnknown)
+                      NumberInfo operands_type = NumberInfo::Unknown())
       : op_(op),
         mode_(mode),
         flags_(flags),
@@ -693,7 +693,7 @@ class GenericBinaryOpStub: public CodeStub {
   bool args_reversed_;  // Left and right argument are swapped.
   bool use_sse3_;
   char* name_;
-  NumberInfo::Type operands_type_;
+  NumberInfo operands_type_;
 
   const char* GetName();
 
@@ -707,7 +707,7 @@ class GenericBinaryOpStub: public CodeStub {
            static_cast<int>(flags_),
            static_cast<int>(args_in_registers_),
            static_cast<int>(args_reversed_),
-           NumberInfo::ToString(operands_type_));
+           operands_type_.ToString());
   }
 #endif
 
@@ -718,7 +718,7 @@ class GenericBinaryOpStub: public CodeStub {
   class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
   class ArgsReversedBits: public BitField<bool, 11, 1> {};
   class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
-  class NumberInfoBits: public BitField<NumberInfo::Type, 13, 3> {};
+  class NumberInfoBits: public BitField<int, 13, 3> {};
 
   Major MajorKey() { return GenericBinaryOp; }
   int MinorKey() {
@@ -729,7 +729,7 @@ class GenericBinaryOpStub: public CodeStub {
            | SSE3Bits::encode(use_sse3_)
            | ArgsInRegistersBits::encode(args_in_registers_)
            | ArgsReversedBits::encode(args_reversed_)
-           | NumberInfoBits::encode(operands_type_);
+           | NumberInfoBits::encode(operands_type_.ThreeBitRepresentation());
   }
 
   void Generate(MacroAssembler* masm);
index de27ddacc0bbdbeed38dc9ee3e91dd3fcf22d799..79be20b1bd25f83c9ef52584b80fd68a7ff617f5 100644 (file)
@@ -177,7 +177,7 @@ void VirtualFrame::EmitPop(const Operand& operand) {
 }
 
 
-void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Register reg, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -185,7 +185,7 @@ void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) {
 }
 
 
-void VirtualFrame::EmitPush(const Operand& operand, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(const Operand& operand, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -193,7 +193,7 @@ void VirtualFrame::EmitPush(const Operand& operand, NumberInfo::Type info) {
 }
 
 
-void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -203,7 +203,7 @@ void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) {
 
 void VirtualFrame::EmitPush(Smi* smi_value) {
   ASSERT(stack_pointer_ == element_count() - 1);
-  elements_.Add(FrameElement::MemoryElement(NumberInfo::kSmi));
+  elements_.Add(FrameElement::MemoryElement(NumberInfo::Smi()));
   stack_pointer_++;
   __ Push(smi_value);
 }
@@ -211,11 +211,11 @@ void VirtualFrame::EmitPush(Smi* smi_value) {
 
 void VirtualFrame::EmitPush(Handle<Object> value) {
   ASSERT(stack_pointer_ == element_count() - 1);
-  NumberInfo::Type info = NumberInfo::kUnknown;
+  NumberInfo info = NumberInfo::Unknown();
   if (value->IsSmi()) {
-    info = NumberInfo::kSmi;
+    info = NumberInfo::Smi();
   } else if (value->IsHeapNumber()) {
-    info = NumberInfo::kHeapNumber;
+    info = NumberInfo::HeapNumber();
   }
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -223,7 +223,7 @@ void VirtualFrame::EmitPush(Handle<Object> value) {
 }
 
 
-void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo::Type info) {
+void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo info) {
   ASSERT(stack_pointer_ == element_count() - 1);
   elements_.Add(FrameElement::MemoryElement(info));
   stack_pointer_++;
@@ -480,7 +480,7 @@ void VirtualFrame::MakeMergable() {
     if (element.is_constant() || element.is_copy()) {
       if (element.is_synced()) {
         // Just spill.
-        elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown);
+        elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown());
       } else {
         // Allocate to a register.
         FrameElement backing_element;  // Invalid if not a copy.
@@ -492,7 +492,7 @@ void VirtualFrame::MakeMergable() {
         elements_[i] =
             FrameElement::RegisterElement(fresh.reg(),
                                           FrameElement::NOT_SYNCED,
-                                          NumberInfo::kUnknown);
+                                          NumberInfo::Unknown());
         Use(fresh.reg(), i);
 
         // Emit a move.
@@ -521,7 +521,7 @@ void VirtualFrame::MakeMergable() {
       // The copy flag is not relied on before the end of this loop,
       // including when registers are spilled.
       elements_[i].clear_copied();
-      elements_[i].set_number_info(NumberInfo::kUnknown);
+      elements_[i].set_number_info(NumberInfo::Unknown());
     }
   }
 }
@@ -728,7 +728,7 @@ Result VirtualFrame::Pop() {
   ASSERT(element.is_valid());
 
   // Get number type information of the result.
-  NumberInfo::Type info;
+  NumberInfo info;
   if (!element.is_copy()) {
     info = element.number_info();
   } else {
index 7f747e3b33d78174de3e7103a85ca3c3ddcc5e32..ddd606bf4ebd61911ced47d4deae79d352429da6 100644 (file)
@@ -83,7 +83,7 @@ class VirtualFrame : public ZoneObject {
 
   // Create a duplicate of an existing valid frame element.
   FrameElement CopyElementAt(int index,
-    NumberInfo::Type info = NumberInfo::kUninitialized);
+    NumberInfo info = NumberInfo::Uninitialized());
 
   // The number of elements on the virtual frame.
   int element_count() { return elements_.length(); }
@@ -383,19 +383,19 @@ class VirtualFrame : public ZoneObject {
   // Push an element on top of the expression stack and emit a
   // corresponding push instruction.
   void EmitPush(Register reg,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(const Operand& operand,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(Heap::RootListIndex index,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(Immediate immediate,
-                NumberInfo::Type info = NumberInfo::kUnknown);
+                NumberInfo info = NumberInfo::Unknown());
   void EmitPush(Smi* value);
   // Uses kScratchRegister, emits appropriate relocation info.
   void EmitPush(Handle<Object> value);
 
   // Push an element on the virtual frame.
-  inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
+  inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown());
   inline void Push(Handle<Object> value);
   inline void Push(Smi* value);