Revision: 15264
Author:   [email protected]
Date:     Fri Jun 21 04:10:06 2013
Log: Use AST's type field and merge types for unary, binary & compare ICs

[email protected]
BUG=

Review URL: https://codereview.chromium.org/17468003
http://code.google.com/p/v8/source/detail?r=15264

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/globals.h
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/type-info.cc
 /branches/bleeding_edge/src/type-info.h
 /branches/bleeding_edge/src/types.cc
 /branches/bleeding_edge/src/typing.cc
 /branches/bleeding_edge/src/typing.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Jun 14 09:06:12 2013 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Jun 21 04:10:06 2013
@@ -2075,7 +2075,7 @@
 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
   Label right_arg_changed, call_runtime;

-  if (op_ == Token::MOD && has_fixed_right_arg_) {
+  if (op_ == Token::MOD && encoded_right_arg_.has_value) {
     // It is guaranteed that the value will fit into a Smi, because if it
     // didn't, we wouldn't be here, see BinaryOp_Patch.
     __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value())));
@@ -2252,7 +2252,7 @@
         // to type transition.

       } else {
-        if (has_fixed_right_arg_) {
+        if (encoded_right_arg_.has_value) {
           __ Vmov(d8, fixed_right_arg_value(), scratch1);
           __ VFPCompareAndSetFlags(d1, d8);
           __ b(ne, &transition);
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Thu Jun 20 06:51:03 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Fri Jun 21 04:10:06 2013
@@ -1463,7 +1463,7 @@
               instr->CheckFlag(HValue::kBailoutOnMinusZero))
           ? AssignEnvironment(result)
           : result;
-    } else if (instr->has_fixed_right_arg()) {
+    } else if (instr->fixed_right_arg().has_value) {
       LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
                                      UseRegisterAtStart(right));
       return AssignEnvironment(DefineAsRegister(mod));
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jun 20 06:51:03 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Jun 21 04:10:06 2013
@@ -1154,12 +1154,12 @@
     __ and_(result_reg, left_reg, Operand(divisor - 1));
     __ bind(&done);

-  } else if (hmod->has_fixed_right_arg()) {
+  } else if (hmod->fixed_right_arg().has_value) {
     Register left_reg = ToRegister(instr->left());
     Register right_reg = ToRegister(instr->right());
     Register result_reg = ToRegister(instr->result());

-    int32_t divisor = hmod->fixed_right_arg_value();
+    int32_t divisor = hmod->fixed_right_arg().value;
     ASSERT(IsPowerOf2(divisor));

     // Check if our assumption of a fixed right operand still holds.
=======================================
--- /branches/bleeding_edge/src/ast.cc  Thu Jun 20 06:09:43 2013
+++ /branches/bleeding_edge/src/ast.cc  Fri Jun 21 04:10:06 2013
@@ -418,6 +418,10 @@
// ----------------------------------------------------------------------------
 // Recording of type feedback

+// TODO(rossberg): all RecordTypeFeedback functions should disappear
+// once we use the common type field in the AST consistently.
+
+
 void ForInStatement::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
   for_in_type_ = static_cast<ForInType>(oracle->ForInType(this));
 }
@@ -663,26 +667,6 @@
       ? oracle->GetObjectLiteralStoreMap(this)
       : Handle<Map>::null();
 }
-
-
-void UnaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
-  type_ = oracle->UnaryType(UnaryOperationFeedbackId());
-}
-
-
-void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
-  oracle->BinaryType(BinaryOperationFeedbackId(),
-                     &left_type_, &right_type_, &result_type_,
-                     &has_fixed_right_arg_, &fixed_right_arg_value_);
-}
-
-
-// TODO(rossberg): this function (and all other RecordTypeFeedback functions) -// should disappear once we use the common type field in the AST consistently.
-void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
-  oracle->CompareTypes(CompareOperationFeedbackId(),
-      &left_type_, &right_type_, &overall_type_, &compare_nil_type_);
-}


// ----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/ast.h   Thu Jun 20 06:09:43 2013
+++ /branches/bleeding_edge/src/ast.h   Fri Jun 21 04:10:06 2013
@@ -356,9 +356,11 @@
   // True iff the expression is the undefined literal.
   bool IsUndefinedLiteral();

-  // Expression type
-  Handle<Type> type() { return type_; }
-  void set_type(Handle<Type> type) { type_ = type; }
+  // Expression type bounds
+  Handle<Type> upper_type() { return upper_type_; }
+  Handle<Type> lower_type() { return lower_type_; }
+  void set_upper_type(Handle<Type> type) { upper_type_ = type; }
+  void set_lower_type(Handle<Type> type) { lower_type_ = type; }

   // Type feedback information for assignments and properties.
   virtual bool IsMonomorphic() {
@@ -389,12 +391,14 @@

  protected:
   explicit Expression(Isolate* isolate)
-      : type_(Type::None(), isolate),
+      : upper_type_(Type::Any(), isolate),
+        lower_type_(Type::None(), isolate),
         id_(GetNextId(isolate)),
         test_id_(GetNextId(isolate)) {}

  private:
-  Handle<Type> type_;
+  Handle<Type> upper_type_;
+  Handle<Type> lower_type_;
   byte to_boolean_types_;

   const BailoutId id_;
@@ -1836,8 +1840,6 @@
   BailoutId MaterializeFalseId() { return materialize_false_id_; }

   TypeFeedbackId UnaryOperationFeedbackId() const { return reuse(id()); }
-  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  Handle<Type> type() const { return type_; }

  protected:
   UnaryOperation(Isolate* isolate,
@@ -1858,8 +1860,6 @@
   Expression* expression_;
   int pos_;

-  Handle<Type> type_;
-
   // For unary not (Token::NOT), the AST ids where true and false will
   // actually be materialized, respectively.
   const BailoutId materialize_true_id_;
@@ -1881,12 +1881,11 @@
   BailoutId RightId() const { return right_id_; }

   TypeFeedbackId BinaryOperationFeedbackId() const { return reuse(id()); }
-  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  Handle<Type> left_type() const { return left_type_; }
-  Handle<Type> right_type() const { return right_type_; }
+  // TODO(rossberg): result_type should be subsumed by lower_type.
   Handle<Type> result_type() const { return result_type_; }
-  bool has_fixed_right_arg() const { return has_fixed_right_arg_; }
-  int fixed_right_arg_value() const { return fixed_right_arg_value_; }
+  void set_result_type(Handle<Type> type) { result_type_ = type; }
+  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
+  void set_fixed_right_arg(Maybe<int> arg) { fixed_right_arg_ = arg; }

  protected:
   BinaryOperation(Isolate* isolate,
@@ -1909,11 +1908,10 @@
   Expression* right_;
   int pos_;

-  Handle<Type> left_type_;
-  Handle<Type> right_type_;
   Handle<Type> result_type_;
-  bool has_fixed_right_arg_;
-  int fixed_right_arg_value_;
+ // TODO(rossberg): the fixed arg should probably be represented as a Constant
+  // type for the RHS.
+  Maybe<int> fixed_right_arg_;

   // The short-circuit logical operations need an AST ID for their
   // right-hand subexpression.
@@ -1994,11 +1992,8 @@

   // Type feedback information.
   TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); }
-  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  Handle<Type> left_type() const { return left_type_; }
-  Handle<Type> right_type() const { return right_type_; }
-  Handle<Type> overall_type() const { return overall_type_; }
-  Handle<Type> compare_nil_type() const { return compare_nil_type_; }
+  Handle<Type> combined_type() const { return combined_type_; }
+  void set_combined_type(Handle<Type> type) { combined_type_ = type; }

   // Match special cases.
   bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
@@ -2025,10 +2020,7 @@
   Expression* right_;
   int pos_;

-  Handle<Type> left_type_;
-  Handle<Type> right_type_;
-  Handle<Type> overall_type_;
-  Handle<Type> compare_nil_type_;
+  Handle<Type> combined_type_;
 };


=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Thu Jun 20 06:51:03 2013
+++ /branches/bleeding_edge/src/code-stubs.h    Fri Jun 21 04:10:06 2013
@@ -904,8 +904,7 @@
         left_type_(BinaryOpIC::UNINITIALIZED),
         right_type_(BinaryOpIC::UNINITIALIZED),
         result_type_(BinaryOpIC::UNINITIALIZED),
-        has_fixed_right_arg_(false),
-        encoded_right_arg_(encode_arg_value(1)) {
+        encoded_right_arg_(false, encode_arg_value(1)) {
     Initialize();
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
@@ -915,16 +914,15 @@
       BinaryOpIC::TypeInfo left_type,
       BinaryOpIC::TypeInfo right_type,
       BinaryOpIC::TypeInfo result_type,
-      bool has_fixed_right_arg,
-      int32_t fixed_right_arg_value)
+      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),
-        has_fixed_right_arg_(has_fixed_right_arg),
-        encoded_right_arg_(encode_arg_value(fixed_right_arg_value)) { }
+        encoded_right_arg_(fixed_right_arg.has_value,
+                           encode_arg_value(fixed_right_arg.value)) { }

   static void decode_types_from_minor_key(int minor_key,
                                           BinaryOpIC::TypeInfo* left_type,
@@ -942,16 +940,14 @@
     return static_cast<Token::Value>(OpBits::decode(minor_key));
   }

-  static bool decode_has_fixed_right_arg_from_minor_key(int minor_key) {
-    return HasFixedRightArgBits::decode(minor_key);
-  }
-
-  static int decode_fixed_right_arg_value_from_minor_key(int minor_key) {
-    return decode_arg_value(FixedRightArgValueBits::decode(minor_key));
+  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)));
   }

   int fixed_right_arg_value() const {
-    return decode_arg_value(encoded_right_arg_);
+    return decode_arg_value(encoded_right_arg_.value);
   }

   static bool can_encode_arg_value(int32_t value) {
@@ -975,8 +971,7 @@
   BinaryOpIC::TypeInfo right_type_;
   BinaryOpIC::TypeInfo result_type_;

-  bool has_fixed_right_arg_;
-  int encoded_right_arg_;
+  Maybe<int> encoded_right_arg_;

   static int encode_arg_value(int32_t value) {
     ASSERT(can_encode_arg_value(value));
@@ -1009,8 +1004,8 @@
            | LeftTypeBits::encode(left_type_)
            | RightTypeBits::encode(right_type_)
            | ResultTypeBits::encode(result_type_)
-           | HasFixedRightArgBits::encode(has_fixed_right_arg_)
-           | FixedRightArgValueBits::encode(encoded_right_arg_);
+           | HasFixedRightArgBits::encode(encoded_right_arg_.has_value)
+           | FixedRightArgValueBits::encode(encoded_right_arg_.value);
   }


@@ -1207,6 +1202,9 @@
   static byte ExtractTypesFromExtraICState(Code::ExtraICState state) {
     return state & ((1 << NUMBER_OF_TYPES) - 1);
   }
+ static NilValue ExtractNilValueFromExtraICState(Code::ExtraICState state) {
+    return NilValueField::decode(state);
+  }

   void Record(Handle<Object> object);

=======================================
--- /branches/bleeding_edge/src/globals.h       Wed Apr 17 01:27:40 2013
+++ /branches/bleeding_edge/src/globals.h       Fri Jun 21 04:10:06 2013
@@ -399,6 +399,18 @@
 };


+// A simple Maybe type, that can be passed by value.
+template<class T>
+struct Maybe {
+  Maybe() : has_value(false) {}
+  explicit Maybe(T t) : has_value(true), value(t) {}
+  Maybe(bool has, T t) : has_value(has), value(t) {}
+
+  bool has_value;
+  T value;
+};
+
+
 // The Strict Mode (ECMA-262 5th edition, 4.2.2).
 //
 // This flag is used in the backend to represent the language mode. So far
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Fri Jun 21 02:24:30 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Fri Jun 21 04:10:06 2013
@@ -3497,8 +3497,7 @@
                         HValue* context,
                         HValue* left,
                         HValue* right,
-                        bool has_fixed_right_arg,
-                        int fixed_right_arg_value) {
+                        Maybe<int> fixed_right_arg) {
   if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
     HConstant* c_left = HConstant::cast(left);
     HConstant* c_right = HConstant::cast(right);
@@ -3517,11 +3516,7 @@
       }
     }
   }
-  return new(zone) HMod(context,
-                        left,
-                        right,
-                        has_fixed_right_arg,
-                        fixed_right_arg_value);
+  return new(zone) HMod(context, left, right, fixed_right_arg);
 }


=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Jun 20 06:51:03 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Jun 21 04:10:06 2013
@@ -4468,11 +4468,9 @@
                            HValue* context,
                            HValue* left,
                            HValue* right,
-                           bool has_fixed_right_arg,
-                           int fixed_right_arg_value);
+                           Maybe<int> fixed_right_arg);

-  bool has_fixed_right_arg() const { return has_fixed_right_arg_; }
-  int fixed_right_arg_value() const { return fixed_right_arg_value_; }
+  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }

   bool HasPowerOf2Divisor() {
     if (right()->IsConstant() &&
@@ -4499,17 +4497,14 @@
   HMod(HValue* context,
        HValue* left,
        HValue* right,
-       bool has_fixed_right_arg,
-       int fixed_right_arg_value)
+       Maybe<int> fixed_right_arg)
       : HArithmeticBinaryOperation(context, left, right),
-        has_fixed_right_arg_(has_fixed_right_arg),
-        fixed_right_arg_value_(fixed_right_arg_value) {
+        fixed_right_arg_(fixed_right_arg) {
     SetFlag(kCanBeDivByZero);
     SetFlag(kCanOverflow);
   }

-  const bool has_fixed_right_arg_;
-  const int fixed_right_arg_value_;
+  const Maybe<int> fixed_right_arg_;
 };


=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Jun 20 09:53:22 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Fri Jun 21 04:10:06 2013
@@ -9036,11 +9036,10 @@
   HValue* context = environment()->LookupContext();
   HInstruction* instr =
       HMul::New(zone(), context, value, graph()->GetConstantMinus1());
-  Handle<Type> type = expr->type();
-  Representation rep = ToRepresentation(type);
-  if (type->Is(Type::None())) {
+  Handle<Type> operand_type = expr->expression()->lower_type();
+  Representation rep = ToRepresentation(operand_type);
+  if (operand_type->Is(Type::None())) {
     AddSoftDeoptimize();
-    type = handle(Type::Any(), isolate());
   }
   if (instr->IsBinaryOperation()) {
HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep);
@@ -9053,8 +9052,8 @@
 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
   CHECK_ALIVE(VisitForValue(expr->expression()));
   HValue* value = Pop();
-  Handle<Type> info = expr->type();
-  if (info->Is(Type::None())) {
+  Handle<Type> operand_type = expr->expression()->lower_type();
+  if (operand_type->Is(Type::None())) {
     AddSoftDeoptimize();
   }
   HInstruction* instr = new(zone()) HBitNot(value);
@@ -9417,16 +9416,16 @@
     HValue* left,
     HValue* right) {
   HValue* context = environment()->LookupContext();
-  Handle<Type> left_type = expr->left_type();
-  Handle<Type> right_type = expr->right_type();
+  Handle<Type> left_type = expr->left()->lower_type();
+  Handle<Type> right_type = expr->right()->lower_type();
   Handle<Type> result_type = expr->result_type();
-  bool has_fixed_right_arg = expr->has_fixed_right_arg();
-  int fixed_right_arg_value = expr->fixed_right_arg_value();
+  Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   Representation left_rep = ToRepresentation(left_type);
   Representation right_rep = ToRepresentation(right_type);
   Representation result_rep = ToRepresentation(result_type);
   if (left_type->Is(Type::None())) {
     AddSoftDeoptimize();
+ // TODO(rossberg): we should be able to get rid of non-continuous defaults.
     left_type = handle(Type::Any(), isolate());
   }
   if (right_type->Is(Type::None())) {
@@ -9453,12 +9452,7 @@
       instr = HMul::New(zone(), context, left, right);
       break;
     case Token::MOD:
-      instr = HMod::New(zone(),
-                        context,
-                        left,
-                        right,
-                        has_fixed_right_arg,
-                        fixed_right_arg_value);
+      instr = HMod::New(zone(), context, left, right, fixed_right_arg);
       break;
     case Token::DIV:
       instr = HDiv::New(zone(), context, left, right);
@@ -9765,17 +9759,17 @@
     return ast_context()->ReturnControl(instr, expr->id());
   }

-  Handle<Type> left_type = expr->left_type();
-  Handle<Type> right_type = expr->right_type();
-  Handle<Type> overall_type = expr->overall_type();
-  Representation combined_rep = ToRepresentation(overall_type);
+  Handle<Type> left_type = expr->left()->lower_type();
+  Handle<Type> right_type = expr->right()->lower_type();
+  Handle<Type> combined_type = expr->combined_type();
+  Representation combined_rep = ToRepresentation(combined_type);
   Representation left_rep = ToRepresentation(left_type);
   Representation right_rep = ToRepresentation(right_type);
   // Check if this expression was ever executed according to type feedback.
// Note that for the special typeof/null/undefined cases we get unknown here.
-  if (overall_type->Is(Type::None())) {
+  if (combined_type->Is(Type::None())) {
     AddSoftDeoptimize();
-    overall_type = left_type = right_type = handle(Type::Any(), isolate());
+ combined_type = left_type = right_type = handle(Type::Any(), isolate());
   }

   CHECK_ALIVE(VisitForValue(expr->left()));
@@ -9847,13 +9841,13 @@
     HIn* result = new(zone()) HIn(context, left, right);
     result->set_position(expr->position());
     return ast_context()->ReturnInstruction(result, expr->id());
-  } else if (overall_type->Is(Type::Receiver())) {
+  } else if (combined_type->Is(Type::Receiver())) {
     switch (op) {
       case Token::EQ:
       case Token::EQ_STRICT: {
         // Can we get away with map check and not instance type check?
-        if (overall_type->IsClass()) {
-          Handle<Map> map = overall_type->AsClass();
+        if (combined_type->IsClass()) {
+          Handle<Map> map = combined_type->AsClass();
           AddCheckMapsWithTransitions(left, map);
           AddCheckMapsWithTransitions(right, map);
           HCompareObjectEqAndBranch* result =
@@ -9874,7 +9868,7 @@
       default:
         return Bailout("Unsupported non-primitive compare");
     }
-  } else if (overall_type->Is(Type::InternalizedString()) &&
+  } else if (combined_type->Is(Type::InternalizedString()) &&
              Token::IsEqualityOp(op)) {
     BuildCheckNonSmi(left);
AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
@@ -9925,8 +9919,8 @@
     if_nil.CaptureContinuation(&continuation);
     return ast_context()->ReturnContinuation(&continuation, expr->id());
   }
-  Handle<Type> type = expr->compare_nil_type()->Is(Type::None())
-      ? handle(Type::Any(), isolate_) : expr->compare_nil_type();
+  Handle<Type> type = expr->combined_type()->Is(Type::None())
+      ? handle(Type::Any(), isolate_) : expr->combined_type();
   BuildCompareNil(value, type, expr->position(), &continuation);
   return ast_context()->ReturnContinuation(&continuation, expr->id());
 }
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Jun 20 05:59:45 2013 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Jun 21 04:10:06 2013
@@ -1527,7 +1527,7 @@
       UNREACHABLE();
   }

-  if (op_ == Token::MOD && has_fixed_right_arg_) {
+  if (op_ == Token::MOD && encoded_right_arg_.has_value) {
     // It is guaranteed that the value will fit into a Smi, because if it
     // didn't, we wouldn't be here, see BinaryOp_Patch.
     __ cmp(eax, Immediate(Smi::FromInt(fixed_right_arg_value())));
@@ -1669,7 +1669,7 @@
         FloatingPointHelper::CheckSSE2OperandIsInt32(
             masm, &not_int32, xmm1, edi, ecx, xmm2);
         if (op_ == Token::MOD) {
-          if (has_fixed_right_arg_) {
+          if (encoded_right_arg_.has_value) {
             __ cmp(edi, Immediate(fixed_right_arg_value()));
             __ j(not_equal, &right_arg_changed);
           }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Jun 20 06:51:03 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Jun 21 04:10:06 2013
@@ -1223,12 +1223,12 @@
     __ and_(left_reg, divisor - 1);
     __ bind(&done);

-  } else if (hmod->has_fixed_right_arg()) {
+  } else if (hmod->fixed_right_arg().has_value) {
     Register left_reg = ToRegister(instr->left());
     ASSERT(left_reg.is(ToRegister(instr->result())));
     Register right_reg = ToRegister(instr->right());

-    int32_t divisor = hmod->fixed_right_arg_value();
+    int32_t divisor = hmod->fixed_right_arg().value;
     ASSERT(IsPowerOf2(divisor));

     // Check if our assumption of a fixed right operand still holds.
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Jun 20 06:51:03 2013 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri Jun 21 04:10:06 2013
@@ -1551,7 +1551,7 @@
               instr->CheckFlag(HValue::kBailoutOnMinusZero))
           ? AssignEnvironment(result)
           : result;
-    } else if (instr->has_fixed_right_arg()) {
+    } else if (instr->fixed_right_arg().has_value) {
       LModI* mod = new(zone()) LModI(UseRegister(left),
                                      UseRegisterAtStart(right),
                                      NULL);
=======================================
--- /branches/bleeding_edge/src/ic.cc   Fri Jun 14 10:02:39 2013
+++ /branches/bleeding_edge/src/ic.cc   Fri Jun 21 04:10:06 2013
@@ -2653,11 +2653,10 @@
 #ifdef DEBUG
 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
                           BinaryOpIC::TypeInfo right,
-                          bool has_fixed_right_arg,
-                          int32_t fixed_right_arg_value,
+                          Maybe<int32_t> fixed_right_arg,
                           BinaryOpIC::TypeInfo result) {
   PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
-  if (has_fixed_right_arg) PrintF("{%d}", fixed_right_arg_value);
+  if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
   PrintF("->%s", BinaryOpIC::GetName(result));
 }
 #endif
@@ -2689,10 +2688,8 @@
   BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);

-  bool previous_has_fixed_right_arg =
-      BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(key);
-  int previous_fixed_right_arg_value =
-      BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(key);
+  Maybe<int> previous_fixed_right_arg =
+      BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);

   int32_t value;
   bool new_has_fixed_right_arg =
@@ -2700,11 +2697,12 @@
       right->ToInt32(&value) &&
       BinaryOpStub::can_encode_arg_value(value) &&
       (previous_overall == BinaryOpIC::UNINITIALIZED ||
-       (previous_has_fixed_right_arg &&
-        previous_fixed_right_arg_value == value));
-  int32_t new_fixed_right_arg_value = new_has_fixed_right_arg ? value : 1;
+       (previous_fixed_right_arg.has_value &&
+        previous_fixed_right_arg.value == value));
+  Maybe<int32_t> new_fixed_right_arg(
+      new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);

-  if (previous_has_fixed_right_arg == new_has_fixed_right_arg) {
+ if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) { if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
       if (op == Token::DIV ||
           op == Token::MUL ||
@@ -2728,8 +2726,7 @@
     }
   }

-  BinaryOpStub stub(key, new_left, new_right, result_type,
-                    new_has_fixed_right_arg, new_fixed_right_arg_value);
+ BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
   Handle<Code> code = stub.GetCode(isolate);
   if (!code.is_null()) {
 #ifdef DEBUG
@@ -2737,11 +2734,10 @@
       PrintF("[BinaryOpIC in ");
       JavaScriptFrame::PrintTop(isolate, stdout, false, true);
       PrintF(" ");
- TraceBinaryOp(previous_left, previous_right, previous_has_fixed_right_arg,
-                    previous_fixed_right_arg_value, previous_result);
+ TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
+                    previous_result);
       PrintF(" => ");
-      TraceBinaryOp(new_left, new_right, new_has_fixed_right_arg,
-                    new_fixed_right_arg_value, result_type);
+      TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
       PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
     }
 #endif
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Jun 20 07:47:35 2013
+++ /branches/bleeding_edge/src/objects.cc      Fri Jun 21 04:10:06 2013
@@ -9979,6 +9979,12 @@
   return CompareNilICStub::ExtractTypesFromExtraICState(
       extended_extra_ic_state());
 }
+
+byte Code::compare_nil_value() {
+  ASSERT(is_compare_nil_ic_stub());
+  return CompareNilICStub::ExtractNilValueFromExtraICState(
+      extended_extra_ic_state());
+}


 void Code::InvalidateRelocation() {
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jun 20 03:48:14 2013
+++ /branches/bleeding_edge/src/objects.h       Fri Jun 21 04:10:06 2013
@@ -4663,6 +4663,7 @@

// [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in.
   byte compare_nil_state();
+  byte compare_nil_value();

   // [has_function_cache]: For kind STUB tells whether there is a function
   // cache is passed to the stub.
=======================================
--- /branches/bleeding_edge/src/type-info.cc    Thu Jun 20 09:54:09 2013
+++ /branches/bleeding_edge/src/type-info.cc    Fri Jun 21 04:10:06 2013
@@ -352,13 +352,11 @@
 }


-void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id,
-                                      Handle<Type>* left_type,
-                                      Handle<Type>* right_type,
-                                      Handle<Type>* overall_type,
-                                      Handle<Type>* compare_nil_type) {
-  *left_type = *right_type = *overall_type = *compare_nil_type =
-      handle(Type::Any(), isolate_);
+void TypeFeedbackOracle::CompareType(TypeFeedbackId id,
+                                     Handle<Type>* left_type,
+                                     Handle<Type>* right_type,
+                                     Handle<Type>* combined_type) {
+ *left_type = *right_type = *combined_type = handle(Type::Any(), isolate_);
   Handle<Object> info = GetInfo(id);
   if (!info->IsCode()) return;
   Handle<Code> code = Handle<Code>::cast(info);
@@ -375,10 +373,14 @@
   if (code->is_compare_ic_stub()) {
     int stub_minor_key = code->stub_info();
     CompareIC::StubInfoToType(
- stub_minor_key, left_type, right_type, overall_type, map, isolate()); + stub_minor_key, left_type, right_type, combined_type, map, isolate());
   } else if (code->is_compare_nil_ic_stub()) {
     CompareNilICStub::State state(code->compare_nil_state());
- *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map);
+    *combined_type = CompareNilICStub::StateToType(isolate_, state, map);
+    Handle<Type> nil_type = handle(code->compare_nil_value() == kNullValue
+        ? Type::Null() : Type::Undefined(), isolate_);
+    *left_type = *right_type =
+        handle(Type::Union(*combined_type, nil_type), isolate_);
   }
 }

@@ -397,8 +399,7 @@
                                     Handle<Type>* left,
                                     Handle<Type>* right,
                                     Handle<Type>* result,
-                                    bool* has_fixed_right_arg,
-                                    int* fixed_right_arg_value) {
+                                    Maybe<int>* fixed_right_arg) {
   Handle<Object> object = GetInfo(id);
   *left = *right = *result = handle(Type::Any(), isolate_);
   if (!object->IsCode()) return;
@@ -407,10 +408,8 @@

   int minor_key = code->stub_info();
   BinaryOpIC::StubInfoToType(minor_key, left, right, result, isolate());
-  *has_fixed_right_arg =
-      BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key);
-  *fixed_right_arg_value =
-      BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key);
+  *fixed_right_arg =
+      BinaryOpStub::decode_fixed_right_arg_from_minor_key(minor_key);
 }


=======================================
--- /branches/bleeding_edge/src/type-info.h     Thu Jun 20 06:09:43 2013
+++ /branches/bleeding_edge/src/type-info.h     Fri Jun 21 04:10:06 2013
@@ -300,14 +300,12 @@
                   Handle<Type>* left,
                   Handle<Type>* right,
                   Handle<Type>* result,
-                  bool* has_fixed_right_arg,
-                  int* fixed_right_arg_value);
+                  Maybe<int>* fixed_right_arg);

-  void CompareTypes(TypeFeedbackId id,
-                    Handle<Type>* left_type,
-                    Handle<Type>* right_type,
-                    Handle<Type>* overall_type,
-                    Handle<Type>* compare_nil_type);
+  void CompareType(TypeFeedbackId id,
+                   Handle<Type>* left_type,
+                   Handle<Type>* right_type,
+                   Handle<Type>* combined_type);

   Handle<Type> ClauseType(TypeFeedbackId id);

=======================================
--- /branches/bleeding_edge/src/types.cc        Thu Jun 20 02:10:10 2013
+++ /branches/bleeding_edge/src/types.cc        Fri Jun 21 04:10:06 2013
@@ -335,6 +335,12 @@
   if (type1->is_bitset() && type2->is_bitset()) {
     return from_bitset(type1->as_bitset() | type2->as_bitset());
   }
+
+  // Fast case: top or bottom types.
+  if (type1->SameValue(Type::Any())) return *type1;
+  if (type2->SameValue(Type::Any())) return *type2;
+  if (type1->SameValue(Type::None())) return *type2;
+  if (type2->SameValue(Type::None())) return *type1;

   // Semi-fast case: Unioned objects are neither involved nor produced.
   if (!(type1->is_union() || type2->is_union())) {
@@ -405,6 +411,12 @@
   if (type1->is_bitset() && type2->is_bitset()) {
     return from_bitset(type1->as_bitset() & type2->as_bitset());
   }
+
+  // Fast case: top or bottom types.
+  if (type1->SameValue(Type::None())) return *type1;
+  if (type2->SameValue(Type::None())) return *type2;
+  if (type1->SameValue(Type::Any())) return *type2;
+  if (type2->SameValue(Type::Any())) return *type1;

   // Semi-fast case: Unioned objects are neither involved nor produced.
   if (!(type1->is_union() || type2->is_union())) {
=======================================
--- /branches/bleeding_edge/src/typing.cc       Wed Jun 12 10:20:37 2013
+++ /branches/bleeding_edge/src/typing.cc       Fri Jun 21 04:10:06 2013
@@ -404,7 +404,9 @@
   ASSERT(!HasStackOverflow());
   CHECK_ALIVE(Visit(expr->expression()));

-  expr->RecordTypeFeedback(oracle());
+  // Collect type feedback.
+ Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId());
+  MergeLowerType(expr->expression(), op_type);
   if (expr->op() == Token::NOT) {
     // TODO(rossberg): only do in test or value context.
     expr->expression()->RecordToBooleanTypeFeedback(oracle());
@@ -429,7 +431,15 @@
   CHECK_ALIVE(Visit(expr->left()));
   CHECK_ALIVE(Visit(expr->right()));

-  expr->RecordTypeFeedback(oracle());
+  // Collect type feedback.
+  Handle<Type> left_type, right_type, result_type;
+  Maybe<int> fixed_right_arg;
+  oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
+      &left_type, &right_type, &result_type, &fixed_right_arg);
+  MergeLowerType(expr->left(), left_type);
+  MergeLowerType(expr->right(), right_type);
+  expr->set_result_type(result_type);
+  expr->set_fixed_right_arg(fixed_right_arg);
   if (expr->op() == Token::OR || expr->op() == Token::AND) {
     expr->left()->RecordToBooleanTypeFeedback(oracle());
   }
@@ -441,7 +451,13 @@
   CHECK_ALIVE(Visit(expr->left()));
   CHECK_ALIVE(Visit(expr->right()));

-  expr->RecordTypeFeedback(oracle());
+  // Collect type feedback.
+  Handle<Type> left_type, right_type, combined_type;
+  oracle()->CompareType(expr->CompareOperationFeedbackId(),
+      &left_type, &right_type, &combined_type);
+  MergeLowerType(expr->left(), left_type);
+  MergeLowerType(expr->right(), right_type);
+  expr->set_combined_type(combined_type);
 }


=======================================
--- /branches/bleeding_edge/src/typing.h        Wed Jun 12 10:20:37 2013
+++ /branches/bleeding_edge/src/typing.h        Fri Jun 21 04:10:06 2013
@@ -61,6 +61,13 @@

   TypeFeedbackOracle* oracle() { return &oracle_; }
   Zone* zone() const { return info_->zone(); }
+
+  void MergeLowerType(Expression* e, Handle<Type> t) {
+    e->set_lower_type(handle(Type::Union(e->lower_type(), t), isolate_));
+  }
+  void MergeUpperType(Expression* e, Handle<Type> t) {
+ e->set_upper_type(handle(Type::Intersect(e->upper_type(), t), isolate_));
+  }

   void VisitDeclarations(ZoneList<Declaration*>* declarations);
   void VisitStatements(ZoneList<Statement*>* statements);
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Jun 13 23:06:00 2013 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Jun 21 04:10:06 2013
@@ -1232,7 +1232,7 @@
 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
   Label right_arg_changed, call_runtime;

-  if (op_ == Token::MOD && has_fixed_right_arg_) {
+  if (op_ == Token::MOD && encoded_right_arg_.has_value) {
     // It is guaranteed that the value will fit into a Smi, because if it
     // didn't, we wouldn't be here, see BinaryOp_Patch.
     __ Cmp(rax, Smi::FromInt(fixed_right_arg_value()));
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Jun 20 06:51:03 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Jun 21 04:10:06 2013
@@ -1034,12 +1034,12 @@
     __ andl(left_reg, Immediate(divisor - 1));
     __ bind(&done);

-  } else if (hmod->has_fixed_right_arg()) {
+  } else if (hmod->fixed_right_arg().has_value) {
     Register left_reg = ToRegister(instr->left());
     ASSERT(left_reg.is(ToRegister(instr->result())));
     Register right_reg = ToRegister(instr->right());

-    int32_t divisor = hmod->fixed_right_arg_value();
+    int32_t divisor = hmod->fixed_right_arg().value;
     ASSERT(IsPowerOf2(divisor));

     // Check if our assumption of a fixed right operand still holds.
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Thu Jun 20 06:51:03 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Fri Jun 21 04:10:06 2013
@@ -1459,7 +1459,7 @@
               instr->CheckFlag(HValue::kBailoutOnMinusZero))
           ? AssignEnvironment(result)
           : result;
-    } else if (instr->has_fixed_right_arg()) {
+    } else if (instr->fixed_right_arg().has_value) {
       LModI* mod = new(zone()) LModI(UseRegister(left),
                                      UseRegisterAtStart(right),
                                      NULL);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to