Revision: 6300
Author: [email protected]
Date: Thu Jan 13 06:16:08 2011
Log: Expose receiver check type in call type feedback.

This a preparatory step to support fast function calls on primitive
values. Not really used yet in hydrogen.

Review URL: http://codereview.chromium.org/6263001
http://code.google.com/p/v8/source/detail?r=6300

Modified:
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/type-info.cc
 /branches/bleeding_edge/src/type-info.h

=======================================
--- /branches/bleeding_edge/src/ast.cc  Wed Jan 12 01:29:20 2011
+++ /branches/bleeding_edge/src/ast.cc  Thu Jan 13 06:16:08 2011
@@ -645,10 +645,19 @@
     }
   }
 #endif
-  if (receiver_types_ != NULL && receiver_types_->length() > 0) {
-    Handle<Map> type = receiver_types_->at(0);
-    is_monomorphic_ = oracle->CallIsMonomorphic(this);
-    if (is_monomorphic_) is_monomorphic_ = ComputeTarget(type, name);
+  is_monomorphic_ = oracle->CallIsMonomorphic(this);
+  check_type_ = oracle->GetCallCheckType(this);
+  if (is_monomorphic_) {
+    Handle<Map> map;
+    if (receiver_types_ != NULL && receiver_types_->length() > 0) {
+      ASSERT(check_type_ == RECEIVER_MAP_CHECK);
+      map = receiver_types_->at(0);
+    } else {
+      ASSERT(check_type_ != RECEIVER_MAP_CHECK);
+      map = Handle<Map>(
+          oracle->GetPrototypeForPrimitiveCheck(check_type_)->map());
+    }
+    is_monomorphic_ = ComputeTarget(map, name);
   }
 }

=======================================
--- /branches/bleeding_edge/src/ast.h   Fri Jan  7 02:36:27 2011
+++ /branches/bleeding_edge/src/ast.h   Thu Jan 13 06:16:08 2011
@@ -1268,6 +1268,7 @@
         arguments_(arguments),
         pos_(pos),
         is_monomorphic_(false),
+        check_type_(RECEIVER_MAP_CHECK),
         receiver_types_(NULL),
         return_id_(GetNextId()) {
   }
@@ -1283,6 +1284,7 @@
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
   virtual bool IsMonomorphic() { return is_monomorphic_; }
+  CheckType check_type() const { return check_type_; }
   Handle<JSFunction> target() { return target_; }
   Handle<JSObject> holder() { return holder_; }
   Handle<JSGlobalPropertyCell> cell() { return cell_; }
@@ -1306,6 +1308,7 @@
   int pos_;

   bool is_monomorphic_;
+  CheckType check_type_;
   ZoneMapList* receiver_types_;
   Handle<JSFunction> target_;
   Handle<JSObject> holder_;
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Thu Dec  9 05:12:23 2010
+++ /branches/bleeding_edge/src/compiler.cc     Thu Jan 13 06:16:08 2011
@@ -262,7 +262,9 @@
     HTracer::Instance()->TraceCompilation(info->function());
   }

-  TypeFeedbackOracle oracle(Handle<Code>(info->shared_info()->code()));
+  TypeFeedbackOracle oracle(
+      Handle<Code>(info->shared_info()->code()),
+      Handle<Context>(info->closure()->context()->global_context()));
   HGraphBuilder builder(&oracle);
   HPhase phase(HPhase::kTotal);
   HGraph* graph = builder.CreateGraph(info);
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jan 11 04:38:19 2011
+++ /branches/bleeding_edge/src/heap.cc Thu Jan 13 06:16:08 2011
@@ -2724,6 +2724,9 @@
   code->set_instruction_size(desc.instr_size);
   code->set_relocation_info(ByteArray::cast(reloc_info));
   code->set_flags(flags);
+  if (code->is_call_stub() || code->is_keyed_call_stub()) {
+    code->set_check_type(RECEIVER_MAP_CHECK);
+  }
   code->set_deoptimization_data(empty_fixed_array());
   // Allow self references to created code object by patching the handle to
   // point to the newly allocated Code object.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Wed Jan 12 16:34:08 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Jan 13 06:16:08 2011
@@ -4009,7 +4009,9 @@
     function_return_->MarkAsInlineReturnTarget();
   }
   call_context_ = ast_context();
-  TypeFeedbackOracle new_oracle(Handle<Code>(shared->code()));
+  TypeFeedbackOracle new_oracle(
+      Handle<Code>(shared->code()),
+      Handle<Context>(target->context()->global_context()));
   oracle_ = &new_oracle;
   graph()->info()->SetOsrAstId(AstNode::kNoNumber);

@@ -4211,7 +4213,8 @@
   HValue* arg_two_value = environment()->Lookup(arg_two->var());
   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;

-  if (!expr->IsMonomorphic()) return false;
+  if (!expr->IsMonomorphic() ||
+      expr->check_type() != RECEIVER_MAP_CHECK) return false;

   // Found pattern f.apply(receiver, arguments).
   VisitForValue(prop->obj());
@@ -4280,7 +4283,7 @@
     expr->RecordTypeFeedback(oracle());
     ZoneMapList* types = expr->GetReceiverTypes();

-    if (expr->IsMonomorphic()) {
+ if (expr->IsMonomorphic() && expr->check_type() == RECEIVER_MAP_CHECK) {
       AddCheckConstantFunction(expr, receiver, types->first(), true);

       if (TryMathFunctionInline(expr)) {
@@ -4305,6 +4308,7 @@
       }

     } else if (types != NULL && types->length() > 1) {
+      ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
       HandlePolymorphicCallNamed(expr, receiver, types, name);
       return;

=======================================
--- /branches/bleeding_edge/src/type-info.cc    Fri Jan  7 02:36:27 2011
+++ /branches/bleeding_edge/src/type-info.cc    Thu Jan 13 06:16:08 2011
@@ -58,7 +58,9 @@
 }


-TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code) {
+TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
+                                       Handle<Context> global_context) {
+  global_context_ = global_context;
   Initialize(code);
 }

@@ -71,17 +73,18 @@


 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
-  return IsMonomorphic(expr->position());
+  return GetElement(map_, expr->position())->IsMap();
 }


 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
-  return IsMonomorphic(expr->position());
+  return GetElement(map_, expr->position())->IsMap();
 }


 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
-  return IsMonomorphic(expr->position());
+  Handle<Object> value = GetElement(map_, expr->position());
+  return value->IsMap() || value->IsSmi();
 }


@@ -95,12 +98,6 @@
   ASSERT(StoreIsMonomorphic(expr));
   return Handle<Map>::cast(GetElement(map_, expr->position()));
 }
-
-
-Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) {
-  ASSERT(CallIsMonomorphic(expr));
-  return Handle<Map>::cast(GetElement(map_, expr->position()));
-}


 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
@@ -124,6 +121,37 @@
       Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity);
   return CollectReceiverTypes(expr->position(), name, flags);
 }
+
+
+CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
+  Handle<Object> value = GetElement(map_, expr->position());
+  if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
+  CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
+  ASSERT(check != RECEIVER_MAP_CHECK);
+  return check;
+}
+
+
+Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
+    CheckType check) {
+  JSFunction* function = NULL;
+  switch (check) {
+    case RECEIVER_MAP_CHECK:
+      UNREACHABLE();
+      break;
+    case STRING_CHECK:
+      function = global_context_->string_function();
+      break;
+    case NUMBER_CHECK:
+      function = global_context_->number_function();
+      break;
+    case BOOLEAN_CHECK:
+      function = global_context_->boolean_function();
+      break;
+  }
+  ASSERT(function != NULL);
+  return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
+}


 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
@@ -219,6 +247,7 @@
   }
   return unknown;
 }
+

 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
   Handle<Object> object = GetElement(map_, clause->position());
@@ -245,14 +274,13 @@
       return unknown;
   }
 }
-


 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
                                                       Handle<String> name,
                                                       Code::Flags flags) {
   Handle<Object> object = GetElement(map_, position);
-  if (object->IsUndefined()) return NULL;
+  if (object->IsUndefined() || object->IsSmi()) return NULL;

   if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
     // TODO(fschneider): We could collect the maps and signal that
@@ -301,11 +329,20 @@
         SetElement(map_, position, target);
       }
     } else if (state == MONOMORPHIC) {
-      Handle<Map> map = Handle<Map>(target->FindFirstMap());
-      if (*map == NULL) {
-        SetElement(map_, position, target);
+      if (target->kind() != Code::CALL_IC ||
+          target->check_type() == RECEIVER_MAP_CHECK) {
+        Handle<Map> map = Handle<Map>(target->FindFirstMap());
+        if (*map == NULL) {
+          SetElement(map_, position, target);
+        } else {
+          SetElement(map_, position, map);
+        }
       } else {
-        SetElement(map_, position, map);
+        ASSERT(target->kind() == Code::CALL_IC);
+        CheckType check = target->check_type();
+        ASSERT(check != RECEIVER_MAP_CHECK);
+        SetElement(map_, position, Handle<Object>(Smi::FromInt(check)));
+        ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
       }
     } else if (state == MEGAMORPHIC) {
       SetElement(map_, position, target);
@@ -342,8 +379,6 @@
         } else if (kind == Code::COMPARE_IC) {
           if (target->compare_state() == CompareIC::GENERIC) continue;
         } else {
-          if (kind == Code::CALL_IC && state == MONOMORPHIC &&
-              target->check_type() != RECEIVER_MAP_CHECK) continue;
           if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
         }
         code_positions->Add(
=======================================
--- /branches/bleeding_edge/src/type-info.h     Fri Jan  7 02:36:27 2011
+++ /branches/bleeding_edge/src/type-info.h     Thu Jan 13 06:16:08 2011
@@ -236,7 +236,7 @@
     RESULT
   };

-  explicit TypeFeedbackOracle(Handle<Code> code);
+  TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);

   bool LoadIsMonomorphic(Property* expr);
   bool StoreIsMonomorphic(Assignment* expr);
@@ -244,12 +244,14 @@

   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
   Handle<Map> StoreMonomorphicReceiverType(Assignment* expr);
-  Handle<Map> CallMonomorphicReceiverType(Call* expr);

   ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
   ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
   ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);

+  CheckType GetCallCheckType(Call* expr);
+  Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
+
   bool LoadIsBuiltin(Property* expr, Builtins::Name id);

   // Get type information for arithmetic operations and compares.
@@ -259,8 +261,6 @@

  private:
   void Initialize(Handle<Code> code);
-
-  bool IsMonomorphic(int pos) { return GetElement(map_, pos)->IsMap(); }

   ZoneMapList* CollectReceiverTypes(int position,
                                     Handle<String> name,
@@ -272,6 +272,7 @@
                         List<int>* code_positions,
                         List<int>* source_positions);

+  Handle<Context> global_context_;
   Handle<JSObject> map_;

   DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to