Move feedback slot allocation to post-pass
authorAndy Wingo <wingo@igalia.com>
Fri, 14 Nov 2014 08:21:13 +0000 (09:21 +0100)
committerAndy Wingo <wingo@igalia.com>
Fri, 14 Nov 2014 08:21:33 +0000 (08:21 +0000)
R=mvstanton@chromium.org, svenpanne@chromium.org

Review URL: https://codereview.chromium.org/670953003

Cr-Commit-Position: refs/heads/master@{#25348}

src/ast-numbering.cc
src/ast.cc
src/ast.h
src/compiler.cc
src/compiler.h
src/full-codegen.cc
src/liveedit.cc
src/liveedit.h
src/parser.cc
src/preparser.h
test/cctest/test-compiler.cc

index 3894492..5ebbde8 100644 (file)
@@ -64,6 +64,21 @@ class AstNumberingVisitor FINAL : public AstVisitor {
     properties_.flags()->Add(kDontCache);
   }
 
+  template <typename Node>
+  void ReserveFeedbackSlots(Node* node) {
+    FeedbackVectorRequirements reqs = node->ComputeFeedbackRequirements();
+    if (reqs.slots() > 0) {
+      node->SetFirstFeedbackSlot(
+          FeedbackVectorSlot(properties_.feedback_slots()));
+      properties_.increase_feedback_slots(reqs.slots());
+    }
+    if (reqs.ic_slots() > 0) {
+      node->SetFirstFeedbackICSlot(
+          FeedbackVectorICSlot(properties_.ic_feedback_slots()));
+      properties_.increase_ic_feedback_slots(reqs.ic_slots());
+    }
+  }
+
   BailoutReason dont_optimize_reason() const {
     return (dont_turbofan_reason_ != kNoReason) ? dont_turbofan_reason_
                                                 : dont_crankshaft_reason_;
@@ -145,6 +160,7 @@ void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
   if (node->var()->IsLookupSlot()) {
     DisableCrankshaft(kReferenceToAVariableWhichRequiresDynamicLookup);
   }
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
 }
 
@@ -158,6 +174,7 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
 void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
   IncrementNodeCount();
   DisableTurbofan(kSuperReference);
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
   Visit(node->this_var());
 }
@@ -215,6 +232,7 @@ void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
 void AstNumberingVisitor::VisitYield(Yield* node) {
   IncrementNodeCount();
   DisableCrankshaft(kYield);
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(Yield::num_ids()));
   Visit(node->generator_object());
   Visit(node->expression());
@@ -319,6 +337,7 @@ void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
 
 void AstNumberingVisitor::VisitProperty(Property* node) {
   IncrementNodeCount();
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(Property::num_ids()));
   Visit(node->key());
   Visit(node->obj());
@@ -353,6 +372,7 @@ void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
   IncrementNodeCount();
   DisableSelfOptimization();
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
   Visit(node->each());
   Visit(node->enumerable());
@@ -461,6 +481,7 @@ void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
 
 void AstNumberingVisitor::VisitCall(Call* node) {
   IncrementNodeCount();
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(Call::num_ids()));
   Visit(node->expression());
   VisitArguments(node->arguments());
@@ -469,6 +490,7 @@ void AstNumberingVisitor::VisitCall(Call* node) {
 
 void AstNumberingVisitor::VisitCallNew(CallNew* node) {
   IncrementNodeCount();
+  ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(CallNew::num_ids()));
   Visit(node->expression());
   VisitArguments(node->arguments());
@@ -507,10 +529,6 @@ void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
 
 
 void AstNumberingVisitor::Renumber(FunctionLiteral* node) {
-  properties_.flags()->Add(*node->flags());
-  properties_.increase_feedback_slots(node->slot_count());
-  properties_.increase_ic_feedback_slots(node->ic_slot_count());
-
   if (node->scope()->HasIllegalRedeclaration()) {
     node->scope()->VisitIllegalRedeclaration(this);
     return;
index 220dc04..92a9ce6 100644 (file)
@@ -1006,28 +1006,24 @@ CaseClause::CaseClause(Zone* zone, Expression* label,
   }
 #define REGULAR_NODE_WITH_FEEDBACK_SLOTS(NodeType)               \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
-    add_slot_node(node);                                         \
   }
 #define DONT_OPTIMIZE_NODE(NodeType)                             \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
   }
 #define DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType)         \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
-    add_slot_node(node);                                         \
   }
 #define DONT_TURBOFAN_NODE(NodeType)                             \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
   }
 #define DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(NodeType)         \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
-    add_slot_node(node);                                         \
   }
 #define DONT_SELFOPTIMIZE_NODE(NodeType)                         \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
   }
 #define DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType)     \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
-    add_slot_node(node);                                         \
   }
 #define DONT_CACHE_NODE(NodeType)                                \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
@@ -1101,7 +1097,6 @@ DONT_CACHE_NODE(ModuleLiteral)
 
 
 void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
-  add_slot_node(node);
 }
 
 #undef REGULAR_NODE
index deead81..5e1eaa1 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1705,6 +1705,7 @@ class VariableProxy FINAL : public Expression {
   }
 
   FeedbackVectorICSlot VariableFeedbackSlot() {
+    DCHECK(!FLAG_vector_ics || !variable_feedback_slot_.IsInvalid());
     return variable_feedback_slot_;
   }
 
@@ -1790,6 +1791,7 @@ class Property FINAL : public Expression {
   }
 
   FeedbackVectorICSlot PropertyFeedbackSlot() const {
+    DCHECK(!FLAG_vector_ics || !property_feedback_slot_.IsInvalid());
     return property_feedback_slot_;
   }
 
@@ -1834,7 +1836,10 @@ class Call FINAL : public Expression {
   }
 
   bool HasCallFeedbackSlot() const { return !call_feedback_slot_.IsInvalid(); }
-  FeedbackVectorICSlot CallFeedbackSlot() const { return call_feedback_slot_; }
+  FeedbackVectorICSlot CallFeedbackSlot() const {
+    DCHECK(!call_feedback_slot_.IsInvalid());
+    return call_feedback_slot_;
+  }
 
   virtual SmallMapList* GetReceiverTypes() OVERRIDE {
     if (expression()->IsProperty()) {
@@ -1933,7 +1938,10 @@ class CallNew FINAL : public Expression {
     callnew_feedback_slot_ = slot;
   }
 
-  FeedbackVectorSlot CallNewFeedbackSlot() { return callnew_feedback_slot_; }
+  FeedbackVectorSlot CallNewFeedbackSlot() {
+    DCHECK(!callnew_feedback_slot_.IsInvalid());
+    return callnew_feedback_slot_;
+  }
   FeedbackVectorSlot AllocationSiteFeedbackSlot() {
     DCHECK(FLAG_pretenuring_call_new);
     return CallNewFeedbackSlot().next();
@@ -1997,6 +2005,8 @@ class CallRuntime FINAL : public Expression {
   }
 
   FeedbackVectorICSlot CallRuntimeFeedbackSlot() {
+    DCHECK(!(FLAG_vector_ics && is_jsruntime()) ||
+           !callruntime_feedback_slot_.IsInvalid());
     return callruntime_feedback_slot_;
   }
 
@@ -2383,6 +2393,7 @@ class Yield FINAL : public Expression {
   }
 
   FeedbackVectorICSlot KeyedLoadFeedbackSlot() {
+    DCHECK(!FLAG_vector_ics || !yield_first_feedback_slot_.IsInvalid());
     return yield_first_feedback_slot_;
   }
 
@@ -3159,8 +3170,6 @@ class AstConstructionVisitor BASE_EMBEDDED {
  public:
   AstConstructionVisitor() {}
 
-  AstProperties* ast_properties() { return &properties_; }
-
  private:
   template<class> friend class AstNodeFactory;
 
@@ -3169,22 +3178,6 @@ class AstConstructionVisitor BASE_EMBEDDED {
   void Visit##type(type* node);
   AST_NODE_LIST(DEF_VISIT)
 #undef DEF_VISIT
-
-  void add_slot_node(AstNode* slot_node) {
-    FeedbackVectorRequirements reqs = slot_node->ComputeFeedbackRequirements();
-    if (reqs.slots() > 0) {
-      slot_node->SetFirstFeedbackSlot(
-          FeedbackVectorSlot(properties_.feedback_slots()));
-      properties_.increase_feedback_slots(reqs.slots());
-    }
-    if (reqs.ic_slots() > 0) {
-      slot_node->SetFirstFeedbackICSlot(
-          FeedbackVectorICSlot(properties_.ic_feedback_slots()));
-      properties_.increase_ic_feedback_slots(reqs.ic_slots());
-    }
-  }
-
-  AstProperties properties_;
 };
 
 
index 4472afa..c4eed84 100644 (file)
@@ -291,9 +291,11 @@ bool CompilationInfo::ShouldSelfOptimize() {
 void CompilationInfo::PrepareForCompilation(Scope* scope) {
   DCHECK(scope_ == NULL);
   scope_ = scope;
+}
+
 
+void CompilationInfo::EnsureFeedbackVector() {
   if (feedback_vector_.is_null()) {
-    // Allocate the feedback vector too.
     feedback_vector_ = isolate()->factory()->NewTypeFeedbackVector(
         function()->slot_count(), function()->ic_slot_count());
   }
@@ -1326,8 +1328,18 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
   if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
     Handle<Code> code = isolate->builtins()->CompileLazy();
     info.SetCode(code);
+    // There's no need in theory for a lazy-compiled function to have a type
+    // feedback vector, but some parts of the system expect all
+    // SharedFunctionInfo instances to have one.  The size of the vector depends
+    // on how many feedback-needing nodes are in the tree, and when lazily
+    // parsing we might not know that, if this function was never parsed before.
+    // In that case the vector will be replaced the next time MakeCode is
+    // called.
+    info.EnsureFeedbackVector();
     scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
   } else if (Renumber(&info) && FullCodeGenerator::MakeCode(&info)) {
+    // MakeCode will ensure that the feedback vector is present and
+    // appropriately sized.
     DCHECK(!info.code().is_null());
     scope_info = ScopeInfo::Create(info.scope(), info.zone());
   } else {
index 822151d..07bc92a 100644 (file)
@@ -235,6 +235,7 @@ class CompilationInfo {
     DCHECK(script_scope_ == NULL);
     script_scope_ = script_scope;
   }
+  void EnsureFeedbackVector();
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
index e399a34..a993d48 100644 (file)
@@ -306,6 +306,9 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
 
   TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
 
+  // Ensure that the feedback vector is large enough.
+  info->EnsureFeedbackVector();
+
   Handle<Script> script = info->script();
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
index b1476a0..29eaa97 100644 (file)
@@ -605,17 +605,17 @@ static int GetArrayLength(Handle<JSArray> array) {
 }
 
 
-void FunctionInfoWrapper::SetInitialProperties(
-    Handle<String> name, int start_position, int end_position, int param_num,
-    int literal_count, int slot_count, int ic_slot_count, int parent_index) {
+void FunctionInfoWrapper::SetInitialProperties(Handle<String> name,
+                                               int start_position,
+                                               int end_position, int param_num,
+                                               int literal_count,
+                                               int parent_index) {
   HandleScope scope(isolate());
   this->SetField(kFunctionNameOffset_, name);
   this->SetSmiValueField(kStartPositionOffset_, start_position);
   this->SetSmiValueField(kEndPositionOffset_, end_position);
   this->SetSmiValueField(kParamNumOffset_, param_num);
   this->SetSmiValueField(kLiteralNumOffset_, literal_count);
-  this->SetSmiValueField(kSlotNumOffset_, slot_count);
-  this->SetSmiValueField(kICSlotNumOffset_, ic_slot_count);
   this->SetSmiValueField(kParentIndexOffset_, parent_index);
 }
 
@@ -646,26 +646,18 @@ Handle<Code> FunctionInfoWrapper::GetFunctionCode() {
 }
 
 
-Handle<TypeFeedbackVector> FunctionInfoWrapper::GetFeedbackVector() {
+MaybeHandle<TypeFeedbackVector> FunctionInfoWrapper::GetFeedbackVector() {
   Handle<Object> element = this->GetField(kSharedFunctionInfoOffset_);
-  Handle<TypeFeedbackVector> result;
   if (element->IsJSValue()) {
     Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
     Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
     Handle<SharedFunctionInfo> shared =
         Handle<SharedFunctionInfo>::cast(raw_result);
-    result = Handle<TypeFeedbackVector>(shared->feedback_vector(), isolate());
-    CHECK_EQ(result->Slots(), GetSlotCount());
-    CHECK_EQ(result->ICSlots(), GetICSlotCount());
+    return Handle<TypeFeedbackVector>(shared->feedback_vector(), isolate());
   } else {
-    // Scripts may never have a SharedFunctionInfo created, so
-    // create a type feedback vector here.
-    int slot_count = GetSlotCount();
-    int ic_slot_count = GetICSlotCount();
-    result =
-        isolate()->factory()->NewTypeFeedbackVector(slot_count, ic_slot_count);
+    // Scripts may never have a SharedFunctionInfo created.
+    return MaybeHandle<TypeFeedbackVector>();
   }
-  return result;
 }
 
 
@@ -706,10 +698,10 @@ class FunctionInfoListener {
   void FunctionStarted(FunctionLiteral* fun) {
     HandleScope scope(isolate());
     FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
-    info.SetInitialProperties(
-        fun->name(), fun->start_position(), fun->end_position(),
-        fun->parameter_count(), fun->materialized_literal_count(),
-        fun->slot_count(), fun->ic_slot_count(), current_parent_index_);
+    info.SetInitialProperties(fun->name(), fun->start_position(),
+                              fun->end_position(), fun->parameter_count(),
+                              fun->materialized_literal_count(),
+                              current_parent_index_);
     current_parent_index_ = len_;
     SetElementSloppy(result_, len_, info.GetJSArray());
     len_++;
@@ -1201,10 +1193,12 @@ void LiveEdit::ReplaceFunctionCode(
       shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
     }
     shared_info->DisableOptimization(kLiveEdit);
-    // Update the type feedback vector
-    Handle<TypeFeedbackVector> feedback_vector =
+    // Update the type feedback vector, if needed.
+    MaybeHandle<TypeFeedbackVector> feedback_vector =
         compile_info_wrapper.GetFeedbackVector();
-    shared_info->set_feedback_vector(*feedback_vector);
+    if (!feedback_vector.is_null()) {
+      shared_info->set_feedback_vector(*feedback_vector.ToHandleChecked());
+    }
   }
 
   if (shared_info->debug_info()->IsDebugInfo()) {
index 6534b7e..65fe1a6 100644 (file)
@@ -282,7 +282,6 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
 
   void SetInitialProperties(Handle<String> name, int start_position,
                             int end_position, int param_num, int literal_count,
-                            int slot_count, int ic_slot_count,
                             int parent_index);
 
   void SetFunctionCode(Handle<Code> function_code,
@@ -304,7 +303,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
 
   Handle<Code> GetFunctionCode();
 
-  Handle<TypeFeedbackVector> GetFeedbackVector();
+  MaybeHandle<TypeFeedbackVector> GetFeedbackVector();
 
   Handle<Object> GetCodeScopeInfo();
 
@@ -314,12 +313,6 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
 
   int GetEndPosition() { return this->GetSmiValueField(kEndPositionOffset_); }
 
-  int GetSlotCount() {
-    return this->GetSmiValueField(kSlotNumOffset_);
-  }
-
-  int GetICSlotCount() { return this->GetSmiValueField(kICSlotNumOffset_); }
-
  private:
   static const int kFunctionNameOffset_ = 0;
   static const int kStartPositionOffset_ = 1;
@@ -331,9 +324,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
   static const int kParentIndexOffset_ = 7;
   static const int kSharedFunctionInfoOffset_ = 8;
   static const int kLiteralNumOffset_ = 9;
-  static const int kSlotNumOffset_ = 10;
-  static const int kICSlotNumOffset_ = 11;
-  static const int kSize_ = 12;
+  static const int kSize_ = 10;
 
   friend class JSArrayBasedStruct<FunctionInfoWrapper>;
 };
index e202afe..decb3ea 100644 (file)
@@ -277,7 +277,6 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
   int expected_property_count = -1;
   int handler_count = 0;
   int parameter_count = 0;
-  AstProperties ast_properties;
   const AstRawString* name = ast_value_factory()->empty_string();
 
   Scope* function_scope = NewScope(scope, FUNCTION_SCOPE);
@@ -308,8 +307,6 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
     materialized_literal_count = function_state.materialized_literal_count();
     expected_property_count = function_state.expected_property_count();
     handler_count = function_state.handler_count();
-
-    ast_properties = *factory()->visitor()->ast_properties();
   }
 
   FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
@@ -320,8 +317,6 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
       FunctionLiteral::kNotParenthesized, FunctionKind::kDefaultConstructor,
       pos);
 
-  function_literal->set_ast_properties(&ast_properties);
-
   return function_literal;
 }
 
@@ -968,7 +963,6 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
           FunctionLiteral::kNoDuplicateParameters,
           FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
           FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
-      result->set_ast_properties(factory()->visitor()->ast_properties());
     }
   }
 
@@ -3553,7 +3547,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
       ? FunctionLiteral::kIsParenthesized
       : FunctionLiteral::kNotParenthesized;
-  AstProperties ast_properties;
   // Parse function body.
   {
     AstNodeFactory<AstConstructionVisitor> function_factory(
@@ -3721,8 +3714,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
                         scope->end_position(),
                         CHECK_OK);
     }
-    ast_properties = *factory()->visitor()->ast_properties();
-
     if (allow_harmony_scoping() && strict_mode() == STRICT) {
       CheckConflictingVarDeclarations(scope, CHECK_OK);
     }
@@ -3734,7 +3725,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
       num_parameters, duplicate_parameters, function_type,
       FunctionLiteral::kIsFunction, parenthesized, kind, pos);
   function_literal->set_function_token_position(function_token_pos);
-  function_literal->set_ast_properties(&ast_properties);
 
   if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
   return function_literal;
index 8b78d46..c447312 100644 (file)
@@ -815,7 +815,6 @@ class PreParserExpression {
 
   int position() const { return RelocInfo::kNoPosition; }
   void set_function_token_position(int position) {}
-  void set_ast_properties(int* ast_properties) {}
 
  private:
   enum Type {
@@ -1098,14 +1097,6 @@ class PreParserFactory {
                                       int start_position, int end_position) {
     return PreParserExpression::Default();
   }
-
-  // Return the object itself as AstVisitor and implement the needed
-  // dummy method right in this class.
-  PreParserFactory* visitor() { return this; }
-  int* ast_properties() {
-    static int dummy = 42;
-    return &dummy;
-  }
 };
 
 
@@ -2632,7 +2623,6 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
                                        bool* ok) {
   typename Traits::Type::ScopePtr scope = this->NewScope(scope_, ARROW_SCOPE);
   typename Traits::Type::StatementList body;
-  typename Traits::Type::AstProperties ast_properties;
   int num_parameters = -1;
   int materialized_literal_count = -1;
   int expected_property_count = -1;
@@ -2714,8 +2704,6 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
 
     if (allow_harmony_scoping() && strict_mode() == STRICT)
       this->CheckConflictingVarDeclarations(scope, CHECK_OK);
-
-    ast_properties = *factory()->visitor()->ast_properties();
   }
 
   FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
@@ -2727,7 +2715,6 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
       start_pos);
 
   function_literal->set_function_token_position(start_pos);
-  function_literal->set_ast_properties(&ast_properties);
 
   if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
 
index d3c06ba..9cda13b 100644 (file)
@@ -348,20 +348,19 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) {
           *v8::Handle<v8::Function>::Cast(
               CcTest::global()->Get(v8_str("morphing_call"))));
 
-  int expected_slots = 0;
-  int expected_ic_slots = FLAG_vector_ics ? 2 : 1;
-  CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots());
-  CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots());
-
-  // And yet it's not compiled.
+  // Not compiled, and so no feedback vector allocated yet.
   CHECK(!f->shared()->is_compiled());
+  CHECK_EQ(0, f->shared()->feedback_vector()->Slots());
+  CHECK_EQ(0, f->shared()->feedback_vector()->ICSlots());
 
   CompileRun("morphing_call();");
 
-  // The vector should have the same size despite the new scoping.
+  // Now a feedback vector is allocated.
+  CHECK(f->shared()->is_compiled());
+  int expected_slots = 0;
+  int expected_ic_slots = FLAG_vector_ics ? 2 : 1;
   CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots());
   CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots());
-  CHECK(f->shared()->is_compiled());
 }