LCOV - code coverage report
Current view: top level - test/cctest - test-feedback-vector.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 229 229 100.0 %
Date: 2017-10-20 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/v8.h"
       6             : #include "test/cctest/cctest.h"
       7             : 
       8             : #include "src/api.h"
       9             : #include "src/debug/debug.h"
      10             : #include "src/execution.h"
      11             : #include "src/factory.h"
      12             : #include "src/global-handles.h"
      13             : #include "src/macro-assembler.h"
      14             : #include "src/objects-inl.h"
      15             : #include "test/cctest/test-feedback-vector.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : namespace {
      21             : 
      22             : #define CHECK_SLOT_KIND(helper, index, expected_kind) \
      23             :   CHECK_EQ(expected_kind, helper.vector()->GetKind(helper.slot(index)));
      24             : 
      25             : 
      26          85 : static Handle<JSFunction> GetFunction(const char* name) {
      27             :   v8::MaybeLocal<v8::Value> v8_f = CcTest::global()->Get(
      28         255 :       v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str(name));
      29             :   Handle<JSFunction> f =
      30             :       Handle<JSFunction>::cast(v8::Utils::OpenHandle(*v8_f.ToLocalChecked()));
      31          85 :   return f;
      32             : }
      33             : 
      34             : 
      35       23724 : TEST(VectorStructure) {
      36           6 :   LocalContext context;
      37          12 :   v8::HandleScope scope(context->GetIsolate());
      38           6 :   Isolate* isolate = CcTest::i_isolate();
      39             :   Factory* factory = isolate->factory();
      40          12 :   Zone zone(isolate->allocator(), ZONE_NAME);
      41             : 
      42             :   Handle<FeedbackVector> vector;
      43             : 
      44             :   {
      45             :     FeedbackVectorSpec one_slot(&zone);
      46             :     one_slot.AddForInSlot();
      47           6 :     vector = NewFeedbackVector(isolate, &one_slot);
      48           6 :     FeedbackVectorHelper helper(vector);
      49           6 :     CHECK_EQ(1, helper.slot_count());
      50             :   }
      51             : 
      52             :   {
      53             :     FeedbackVectorSpec one_icslot(&zone);
      54             :     one_icslot.AddCallICSlot();
      55           6 :     vector = NewFeedbackVector(isolate, &one_icslot);
      56           6 :     FeedbackVectorHelper helper(vector);
      57           6 :     CHECK_EQ(1, helper.slot_count());
      58             :   }
      59             : 
      60             :   {
      61             :     FeedbackVectorSpec spec(&zone);
      62          24 :     for (int i = 0; i < 3; i++) {
      63             :       spec.AddForInSlot();
      64             :     }
      65          30 :     for (int i = 0; i < 5; i++) {
      66             :       spec.AddCallICSlot();
      67             :     }
      68           6 :     vector = NewFeedbackVector(isolate, &spec);
      69           6 :     FeedbackVectorHelper helper(vector);
      70           6 :     CHECK_EQ(8, helper.slot_count());
      71             : 
      72             :     int index = vector->GetIndex(helper.slot(0));
      73             : 
      74          12 :     CHECK_EQ(helper.slot(0), vector->ToSlot(index));
      75             : 
      76             :     index = vector->GetIndex(helper.slot(3));
      77          12 :     CHECK_EQ(helper.slot(3), vector->ToSlot(index));
      78             : 
      79             :     index = vector->GetIndex(helper.slot(7));
      80           6 :     CHECK_EQ(3 + 4 * FeedbackMetadata::GetSlotSize(FeedbackSlotKind::kCall),
      81             :              index);
      82          12 :     CHECK_EQ(helper.slot(7), vector->ToSlot(index));
      83             : 
      84           6 :     CHECK_EQ(3 + 5 * FeedbackMetadata::GetSlotSize(FeedbackSlotKind::kCall),
      85             :              vector->length());
      86             :   }
      87             : 
      88             :   {
      89             :     FeedbackVectorSpec spec(&zone);
      90             :     spec.AddForInSlot();
      91             :     spec.AddCreateClosureSlot();
      92             :     spec.AddForInSlot();
      93           6 :     vector = NewFeedbackVector(isolate, &spec);
      94           6 :     FeedbackVectorHelper helper(vector);
      95           6 :     CHECK_EQ(1,
      96             :              FeedbackMetadata::GetSlotSize(FeedbackSlotKind::kCreateClosure));
      97             :     FeedbackSlot slot = helper.slot(1);
      98             :     Cell* cell = Cell::cast(vector->Get(slot));
      99           6 :     CHECK_EQ(cell->value(), *factory->undefined_value());
     100           6 :   }
     101           6 : }
     102             : 
     103             : 
     104             : // IC slots need an encoding to recognize what is in there.
     105       23724 : TEST(VectorICMetadata) {
     106           6 :   LocalContext context;
     107          12 :   v8::HandleScope scope(context->GetIsolate());
     108           6 :   Isolate* isolate = CcTest::i_isolate();
     109          12 :   Zone zone(isolate->allocator(), ZONE_NAME);
     110             : 
     111             :   FeedbackVectorSpec spec(&zone);
     112             :   // Set metadata.
     113         246 :   for (int i = 0; i < 40; i++) {
     114         240 :     switch (i % 4) {
     115             :       case 0:
     116             :         spec.AddForInSlot();
     117             :         break;
     118             :       case 1:
     119             :         spec.AddCallICSlot();
     120             :         break;
     121             :       case 2:
     122             :         spec.AddLoadICSlot();
     123             :         break;
     124             :       case 3:
     125             :         spec.AddKeyedLoadICSlot();
     126             :         break;
     127             :     }
     128             :   }
     129             : 
     130           6 :   Handle<FeedbackVector> vector = NewFeedbackVector(isolate, &spec);
     131           6 :   FeedbackVectorHelper helper(vector);
     132           6 :   CHECK_EQ(40, helper.slot_count());
     133             : 
     134             :   // Meanwhile set some feedback values and type feedback values to
     135             :   // verify the data structure remains intact.
     136             :   vector->Set(FeedbackSlot(0), *vector);
     137             : 
     138             :   // Verify the metadata is correctly set up from the spec.
     139         246 :   for (int i = 0; i < 40; i++) {
     140         240 :     FeedbackSlotKind kind = vector->GetKind(helper.slot(i));
     141         240 :     switch (i % 4) {
     142             :       case 0:
     143          60 :         CHECK_EQ(FeedbackSlotKind::kForIn, kind);
     144             :         break;
     145             :       case 1:
     146          60 :         CHECK_EQ(FeedbackSlotKind::kCall, kind);
     147             :         break;
     148             :       case 2:
     149          60 :         CHECK_EQ(FeedbackSlotKind::kLoadProperty, kind);
     150             :         break;
     151             :       case 3:
     152          60 :         CHECK_EQ(FeedbackSlotKind::kLoadKeyed, kind);
     153             :         break;
     154             :     }
     155           6 :   }
     156           6 : }
     157             : 
     158             : 
     159       23724 : TEST(VectorCallICStates) {
     160           7 :   if (i::FLAG_always_opt) return;
     161           5 :   CcTest::InitializeVM();
     162           5 :   LocalContext context;
     163          10 :   v8::HandleScope scope(context->GetIsolate());
     164             :   Isolate* isolate = CcTest::i_isolate();
     165             :   // Make sure function f has a call that uses a type feedback slot.
     166             :   CompileRun(
     167             :       "function foo() { return 17; }"
     168             :       "function f(a) { a(); } f(foo);");
     169           5 :   Handle<JSFunction> f = GetFunction("f");
     170             :   // There should be one IC.
     171             :   Handle<FeedbackVector> feedback_vector =
     172             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     173             :   FeedbackSlot slot(0);
     174             :   CallICNexus nexus(feedback_vector, slot);
     175           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     176             :   // CallIC doesn't return map feedback.
     177           5 :   CHECK(!nexus.FindFirstMap());
     178             : 
     179             :   CompileRun("f(function() { return 16; })");
     180           5 :   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
     181             : 
     182             :   // After a collection, state should remain GENERIC.
     183           5 :   CcTest::CollectAllGarbage();
     184          10 :   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
     185             : }
     186             : 
     187       23724 : TEST(VectorCallFeedback) {
     188           7 :   if (i::FLAG_always_opt) return;
     189           5 :   CcTest::InitializeVM();
     190           5 :   LocalContext context;
     191          10 :   v8::HandleScope scope(context->GetIsolate());
     192             :   Isolate* isolate = CcTest::i_isolate();
     193             :   // Make sure function f has a call that uses a type feedback slot.
     194             :   CompileRun(
     195             :       "function foo() { return 17; }"
     196             :       "function f(a) { a(); } f(foo);");
     197           5 :   Handle<JSFunction> f = GetFunction("f");
     198           5 :   Handle<JSFunction> foo = GetFunction("foo");
     199             :   // There should be one IC.
     200             :   Handle<FeedbackVector> feedback_vector =
     201             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     202             :   FeedbackSlot slot(0);
     203             :   CallICNexus nexus(feedback_vector, slot);
     204             : 
     205           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     206          10 :   CHECK(nexus.GetFeedback()->IsWeakCell());
     207          10 :   CHECK(*foo == WeakCell::cast(nexus.GetFeedback())->value());
     208             : 
     209           5 :   CcTest::CollectAllGarbage();
     210             :   // It should stay monomorphic even after a GC.
     211          10 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     212             : }
     213             : 
     214       23724 : TEST(VectorCallFeedbackForArray) {
     215           7 :   if (i::FLAG_always_opt) return;
     216           5 :   CcTest::InitializeVM();
     217           5 :   LocalContext context;
     218          10 :   v8::HandleScope scope(context->GetIsolate());
     219             :   Isolate* isolate = CcTest::i_isolate();
     220             :   // Make sure function f has a call that uses a type feedback slot.
     221             :   CompileRun("function f(a) { a(); } f(Array);");
     222           5 :   Handle<JSFunction> f = GetFunction("f");
     223             :   // There should be one IC.
     224             :   Handle<FeedbackVector> feedback_vector =
     225             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     226             :   FeedbackSlot slot(0);
     227             :   CallICNexus nexus(feedback_vector, slot);
     228             : 
     229           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     230          10 :   CHECK(nexus.GetFeedback()->IsWeakCell());
     231          15 :   CHECK(*isolate->array_function() ==
     232             :         WeakCell::cast(nexus.GetFeedback())->value());
     233             : 
     234           5 :   CcTest::CollectAllGarbage();
     235             :   // It should stay monomorphic even after a GC.
     236          10 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     237             : }
     238             : 
     239       23724 : TEST(VectorCallCounts) {
     240           7 :   if (i::FLAG_always_opt) return;
     241           5 :   CcTest::InitializeVM();
     242           5 :   LocalContext context;
     243          10 :   v8::HandleScope scope(context->GetIsolate());
     244             :   Isolate* isolate = CcTest::i_isolate();
     245             : 
     246             :   // Make sure function f has a call that uses a type feedback slot.
     247             :   CompileRun(
     248             :       "function foo() { return 17; }"
     249             :       "function f(a) { a(); } f(foo);");
     250           5 :   Handle<JSFunction> f = GetFunction("f");
     251             :   // There should be one IC.
     252             :   Handle<FeedbackVector> feedback_vector =
     253             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     254             :   FeedbackSlot slot(0);
     255             :   CallICNexus nexus(feedback_vector, slot);
     256           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     257             : 
     258             :   CompileRun("f(foo); f(foo);");
     259           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     260           5 :   CHECK_EQ(3, nexus.ExtractCallCount());
     261             : 
     262             :   // Send the IC megamorphic, but we should still have incrementing counts.
     263             :   CompileRun("f(function() { return 12; });");
     264           5 :   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
     265          10 :   CHECK_EQ(4, nexus.ExtractCallCount());
     266             : }
     267             : 
     268       23724 : TEST(VectorConstructCounts) {
     269           7 :   if (i::FLAG_always_opt) return;
     270           5 :   CcTest::InitializeVM();
     271           5 :   LocalContext context;
     272          10 :   v8::HandleScope scope(context->GetIsolate());
     273             :   Isolate* isolate = CcTest::i_isolate();
     274             : 
     275             :   // Make sure function f has a call that uses a type feedback slot.
     276             :   CompileRun(
     277             :       "function Foo() {}"
     278             :       "function f(a) { new a(); } f(Foo);");
     279           5 :   Handle<JSFunction> f = GetFunction("f");
     280             :   Handle<FeedbackVector> feedback_vector =
     281             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     282             : 
     283             :   FeedbackSlot slot(0);
     284             :   CallICNexus nexus(feedback_vector, slot);
     285           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     286             : 
     287           5 :   CHECK(feedback_vector->Get(slot)->IsWeakCell());
     288             : 
     289             :   CompileRun("f(Foo); f(Foo);");
     290           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     291           5 :   CHECK_EQ(3, nexus.ExtractCallCount());
     292             : 
     293             :   // Send the IC megamorphic, but we should still have incrementing counts.
     294             :   CompileRun("f(function() {});");
     295           5 :   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
     296          10 :   CHECK_EQ(4, nexus.ExtractCallCount());
     297             : }
     298             : 
     299       23724 : TEST(VectorLoadICStates) {
     300           7 :   if (i::FLAG_always_opt) return;
     301           5 :   CcTest::InitializeVM();
     302           5 :   LocalContext context;
     303          10 :   v8::HandleScope scope(context->GetIsolate());
     304             :   Isolate* isolate = CcTest::i_isolate();
     305             : 
     306             :   // Make sure function f has a call that uses a type feedback slot.
     307             :   CompileRun(
     308             :       "var o = { foo: 3 };"
     309             :       "function f(a) { return a.foo; } f(o);");
     310           5 :   Handle<JSFunction> f = GetFunction("f");
     311             :   // There should be one IC.
     312             :   Handle<FeedbackVector> feedback_vector =
     313             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     314             :   FeedbackSlot slot(0);
     315             :   LoadICNexus nexus(feedback_vector, slot);
     316           5 :   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
     317             : 
     318             :   CompileRun("f(o)");
     319           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     320             :   // Verify that the monomorphic map is the one we expect.
     321             :   v8::MaybeLocal<v8::Value> v8_o =
     322          15 :       CcTest::global()->Get(context.local(), v8_str("o"));
     323             :   Handle<JSObject> o =
     324             :       Handle<JSObject>::cast(v8::Utils::OpenHandle(*v8_o.ToLocalChecked()));
     325          10 :   CHECK_EQ(o->map(), nexus.FindFirstMap());
     326             : 
     327             :   // Now go polymorphic.
     328             :   CompileRun("f({ blarg: 3, foo: 2 })");
     329           5 :   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
     330             : 
     331             :   CompileRun(
     332             :       "delete o.foo;"
     333             :       "f(o)");
     334           5 :   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
     335             : 
     336             :   CompileRun("f({ blarg: 3, torino: 10, foo: 2 })");
     337           5 :   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
     338             :   MapHandles maps;
     339           5 :   nexus.ExtractMaps(&maps);
     340          10 :   CHECK_EQ(4, maps.size());
     341             : 
     342             :   // Finally driven megamorphic.
     343             :   CompileRun("f({ blarg: 3, gran: 3, torino: 10, foo: 2 })");
     344           5 :   CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback());
     345           5 :   CHECK(!nexus.FindFirstMap());
     346             : 
     347             :   // After a collection, state should not be reset to PREMONOMORPHIC.
     348           5 :   CcTest::CollectAllGarbage();
     349          10 :   CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback());
     350             : }
     351             : 
     352       23724 : TEST(VectorLoadGlobalICSlotSharing) {
     353           7 :   if (i::FLAG_always_opt) return;
     354           5 :   CcTest::InitializeVM();
     355           5 :   LocalContext context;
     356          10 :   v8::HandleScope scope(context->GetIsolate());
     357             :   Isolate* isolate = CcTest::i_isolate();
     358             : 
     359             :   // Function f has 5 LoadGlobalICs: 3 for {o} references outside of "typeof"
     360             :   // operator and 2 for {o} references inside "typeof" operator.
     361             :   CompileRun(
     362             :       "o = 10;"
     363             :       "function f() {"
     364             :       "  var x = o || 10;"
     365             :       "  var y = typeof o;"
     366             :       "  return o , typeof o, x , y, o;"
     367             :       "}"
     368             :       "f();");
     369           5 :   Handle<JSFunction> f = GetFunction("f");
     370             :   // There should be two IC slots for {o} references outside and inside
     371             :   // typeof operator respectively.
     372             :   Handle<FeedbackVector> feedback_vector =
     373             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     374           5 :   FeedbackVectorHelper helper(feedback_vector);
     375           5 :   CHECK_EQ(2, helper.slot_count());
     376           5 :   CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     377           5 :   CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kLoadGlobalInsideTypeof);
     378             :   FeedbackSlot slot1 = helper.slot(0);
     379             :   FeedbackSlot slot2 = helper.slot(1);
     380          10 :   CHECK_EQ(MONOMORPHIC,
     381             :            LoadGlobalICNexus(feedback_vector, slot1).StateFromFeedback());
     382          10 :   CHECK_EQ(MONOMORPHIC,
     383           5 :            LoadGlobalICNexus(feedback_vector, slot2).StateFromFeedback());
     384             : }
     385             : 
     386             : 
     387       23724 : TEST(VectorLoadICOnSmi) {
     388           7 :   if (i::FLAG_always_opt) return;
     389           5 :   CcTest::InitializeVM();
     390           5 :   LocalContext context;
     391          10 :   v8::HandleScope scope(context->GetIsolate());
     392             :   Isolate* isolate = CcTest::i_isolate();
     393           5 :   Heap* heap = isolate->heap();
     394             : 
     395             :   // Make sure function f has a call that uses a type feedback slot.
     396             :   CompileRun(
     397             :       "var o = { foo: 3 };"
     398             :       "function f(a) { return a.foo; } f(o);");
     399           5 :   Handle<JSFunction> f = GetFunction("f");
     400             :   // There should be one IC.
     401             :   Handle<FeedbackVector> feedback_vector =
     402             :       Handle<FeedbackVector>(f->feedback_vector(), isolate);
     403             :   FeedbackSlot slot(0);
     404             :   LoadICNexus nexus(feedback_vector, slot);
     405           5 :   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
     406             : 
     407             :   CompileRun("f(34)");
     408           5 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     409             :   // Verify that the monomorphic map is the one we expect.
     410             :   Map* number_map = heap->heap_number_map();
     411           5 :   CHECK_EQ(number_map, nexus.FindFirstMap());
     412             : 
     413             :   // Now go polymorphic on o.
     414             :   CompileRun("f(o)");
     415           5 :   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
     416             : 
     417             :   MapHandles maps;
     418           5 :   nexus.ExtractMaps(&maps);
     419          10 :   CHECK_EQ(2, maps.size());
     420             : 
     421             :   // One of the maps should be the o map.
     422             :   v8::MaybeLocal<v8::Value> v8_o =
     423          15 :       CcTest::global()->Get(context.local(), v8_str("o"));
     424             :   Handle<JSObject> o =
     425             :       Handle<JSObject>::cast(v8::Utils::OpenHandle(*v8_o.ToLocalChecked()));
     426             :   bool number_map_found = false;
     427             :   bool o_map_found = false;
     428          20 :   for (Handle<Map> current : maps) {
     429          10 :     if (*current == number_map)
     430             :       number_map_found = true;
     431           5 :     else if (*current == o->map())
     432             :       o_map_found = true;
     433             :   }
     434           5 :   CHECK(number_map_found && o_map_found);
     435             : 
     436             :   // The degree of polymorphism doesn't change.
     437             :   CompileRun("f(100)");
     438           5 :   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
     439             :   MapHandles maps2;
     440           5 :   nexus.ExtractMaps(&maps2);
     441          15 :   CHECK_EQ(2, maps2.size());
     442             : }
     443             : 
     444             : 
     445       23724 : TEST(ReferenceContextAllocatesNoSlots) {
     446           7 :   if (i::FLAG_always_opt) return;
     447           5 :   CcTest::InitializeVM();
     448           5 :   LocalContext context;
     449          10 :   v8::HandleScope scope(context->GetIsolate());
     450             :   Isolate* isolate = CcTest::i_isolate();
     451             : 
     452             :   {
     453             :     CompileRun(
     454             :         "function testvar(x) {"
     455             :         "  y = x;"
     456             :         "  y = a;"
     457             :         "  return y;"
     458             :         "}"
     459             :         "a = 3;"
     460             :         "testvar({});");
     461             : 
     462           5 :     Handle<JSFunction> f = GetFunction("testvar");
     463             : 
     464             :     // There should be two LOAD_ICs, one for a and one for y at the end.
     465             :     Handle<FeedbackVector> feedback_vector =
     466           5 :         handle(f->feedback_vector(), isolate);
     467           5 :     FeedbackVectorHelper helper(feedback_vector);
     468           5 :     CHECK_EQ(4, helper.slot_count());
     469           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kStoreGlobalSloppy);
     470           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     471           5 :     CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreGlobalSloppy);
     472           5 :     CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     473             :   }
     474             : 
     475             :   {
     476             :     CompileRun(
     477             :         "function testprop(x) {"
     478             :         "  'use strict';"
     479             :         "  x.blue = a;"
     480             :         "}"
     481             :         "testprop({ blue: 3 });");
     482             : 
     483           5 :     Handle<JSFunction> f = GetFunction("testprop");
     484             : 
     485             :     // There should be one LOAD_IC, for the load of a.
     486             :     Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     487           5 :     FeedbackVectorHelper helper(feedback_vector);
     488           5 :     CHECK_EQ(2, helper.slot_count());
     489           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     490           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kStoreNamedStrict);
     491             :   }
     492             : 
     493             :   {
     494             :     CompileRun(
     495             :         "function testpropfunc(x) {"
     496             :         "  x().blue = a;"
     497             :         "  return x().blue;"
     498             :         "}"
     499             :         "function makeresult() { return { blue: 3 }; }"
     500             :         "testpropfunc(makeresult);");
     501             : 
     502           5 :     Handle<JSFunction> f = GetFunction("testpropfunc");
     503             : 
     504             :     // There should be 1 LOAD_GLOBAL_IC to load x (in both cases), 2 CALL_ICs
     505             :     // to call x and a LOAD_IC to load blue.
     506             :     Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     507           5 :     FeedbackVectorHelper helper(feedback_vector);
     508           5 :     CHECK_EQ(5, helper.slot_count());
     509           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kCall);
     510           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     511           5 :     CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreNamedSloppy);
     512           5 :     CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kCall);
     513           5 :     CHECK_SLOT_KIND(helper, 4, FeedbackSlotKind::kLoadProperty);
     514             :   }
     515             : 
     516             :   {
     517             :     CompileRun(
     518             :         "function testkeyedprop(x) {"
     519             :         "  x[0] = a;"
     520             :         "  return x[0];"
     521             :         "}"
     522             :         "testkeyedprop([0, 1, 2]);");
     523             : 
     524           5 :     Handle<JSFunction> f = GetFunction("testkeyedprop");
     525             : 
     526             :     // There should be 1 LOAD_GLOBAL_ICs for the load of a, and one
     527             :     // KEYED_LOAD_IC for the load of x[0] in the return statement.
     528             :     Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     529           5 :     FeedbackVectorHelper helper(feedback_vector);
     530           5 :     CHECK_EQ(3, helper.slot_count());
     531           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     532           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kStoreKeyedSloppy);
     533           5 :     CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kLoadKeyed);
     534             :   }
     535             : 
     536             :   {
     537             :     CompileRun(
     538             :         "function testkeyedprop(x) {"
     539             :         "  'use strict';"
     540             :         "  x[0] = a;"
     541             :         "  return x[0];"
     542             :         "}"
     543             :         "testkeyedprop([0, 1, 2]);");
     544             : 
     545           5 :     Handle<JSFunction> f = GetFunction("testkeyedprop");
     546             : 
     547             :     // There should be 1 LOAD_GLOBAL_ICs for the load of a, and one
     548             :     // KEYED_LOAD_IC for the load of x[0] in the return statement.
     549             :     Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     550           5 :     FeedbackVectorHelper helper(feedback_vector);
     551           5 :     CHECK_EQ(3, helper.slot_count());
     552           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     553           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kStoreKeyedStrict);
     554           5 :     CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kLoadKeyed);
     555             :   }
     556             : 
     557             :   {
     558             :     CompileRun(
     559             :         "function testcompound(x) {"
     560             :         "  'use strict';"
     561             :         "  x.old = x.young = x.in_between = a;"
     562             :         "  return x.old + x.young;"
     563             :         "}"
     564             :         "testcompound({ old: 3, young: 3, in_between: 3 });");
     565             : 
     566           5 :     Handle<JSFunction> f = GetFunction("testcompound");
     567             : 
     568             :     // There should be 1 LOAD_GLOBAL_IC for load of a and 2 LOAD_ICs, for load
     569             :     // of x.old and x.young.
     570             :     Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     571           5 :     FeedbackVectorHelper helper(feedback_vector);
     572           5 :     CHECK_EQ(7, helper.slot_count());
     573           5 :     CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     574           5 :     CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kStoreNamedStrict);
     575           5 :     CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreNamedStrict);
     576           5 :     CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kStoreNamedStrict);
     577           5 :     CHECK_SLOT_KIND(helper, 4, FeedbackSlotKind::kBinaryOp);
     578           5 :     CHECK_SLOT_KIND(helper, 5, FeedbackSlotKind::kLoadProperty);
     579           5 :     CHECK_SLOT_KIND(helper, 6, FeedbackSlotKind::kLoadProperty);
     580           5 :   }
     581             : }
     582             : 
     583             : 
     584       23724 : TEST(VectorStoreICBasic) {
     585           7 :   if (i::FLAG_always_opt) return;
     586             : 
     587           5 :   CcTest::InitializeVM();
     588           5 :   LocalContext context;
     589          10 :   v8::HandleScope scope(context->GetIsolate());
     590             : 
     591             :   CompileRun(
     592             :       "function f(a) {"
     593             :       "  a.foo = 5;"
     594             :       "}"
     595             :       "var a = { foo: 3 };"
     596             :       "f(a);"
     597             :       "f(a);"
     598             :       "f(a);");
     599           5 :   Handle<JSFunction> f = GetFunction("f");
     600             :   // There should be one IC slot.
     601             :   Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     602           5 :   FeedbackVectorHelper helper(feedback_vector);
     603           5 :   CHECK_EQ(1, helper.slot_count());
     604             :   FeedbackSlot slot(0);
     605             :   StoreICNexus nexus(feedback_vector, slot);
     606          10 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     607             : }
     608             : 
     609       23724 : TEST(StoreOwnIC) {
     610           7 :   if (i::FLAG_always_opt) return;
     611             : 
     612           5 :   CcTest::InitializeVM();
     613           5 :   LocalContext context;
     614          10 :   v8::HandleScope scope(context->GetIsolate());
     615             : 
     616             :   CompileRun(
     617             :       "function f(v) {"
     618             :       "  return {a: 0, b: v, c: 0};"
     619             :       "}"
     620             :       "f(1);"
     621             :       "f(2);"
     622             :       "f(3);");
     623           5 :   Handle<JSFunction> f = GetFunction("f");
     624             :   // There should be one IC slot.
     625             :   Handle<FeedbackVector> feedback_vector(f->feedback_vector());
     626           5 :   FeedbackVectorHelper helper(feedback_vector);
     627           5 :   CHECK_EQ(2, helper.slot_count());
     628           5 :   CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kLiteral);
     629           5 :   CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kStoreOwnNamed);
     630             :   StoreOwnICNexus nexus(feedback_vector, helper.slot(1));
     631          10 :   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
     632             : }
     633             : 
     634             : }  // namespace
     635             : 
     636             : }  // namespace internal
     637       71154 : }  // namespace v8

Generated by: LCOV version 1.10