[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / test / cctest / test-feedback-vector.cc
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.h"
15
16 using namespace v8::internal;
17
18 namespace {
19
20 #define CHECK_SLOT_KIND(vector, slot, expected_kind) \
21   CHECK_EQ(expected_kind, vector->GetKind(FeedbackVectorICSlot(slot)));
22
23
24 TEST(VectorStructure) {
25   LocalContext context;
26   v8::HandleScope scope(context->GetIsolate());
27   Isolate* isolate = CcTest::i_isolate();
28   Factory* factory = isolate->factory();
29   Zone* zone = isolate->runtime_zone();
30
31   // Empty vectors are the empty fixed array.
32   StaticFeedbackVectorSpec empty;
33   Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&empty);
34   CHECK(Handle<FixedArray>::cast(vector)
35             .is_identical_to(factory->empty_fixed_array()));
36   // Which can nonetheless be queried.
37   CHECK_EQ(0, vector->ic_with_type_info_count());
38   CHECK_EQ(0, vector->ic_generic_count());
39   CHECK_EQ(0, vector->Slots());
40   CHECK_EQ(0, vector->ICSlots());
41
42   FeedbackVectorSpec one_slot(zone);
43   one_slot.AddStubSlot();
44   vector = factory->NewTypeFeedbackVector(&one_slot);
45   CHECK_EQ(1, vector->Slots());
46   CHECK_EQ(0, vector->ICSlots());
47
48   FeedbackVectorSpec one_icslot(zone);
49   one_icslot.AddSlot(FeedbackVectorSlotKind::CALL_IC);
50   vector = factory->NewTypeFeedbackVector(&one_icslot);
51   CHECK_EQ(0, vector->Slots());
52   CHECK_EQ(1, vector->ICSlots());
53
54   FeedbackVectorSpec spec(zone);
55   spec.AddStubSlots(3);
56   spec.AddSlots(FeedbackVectorSlotKind::CALL_IC, 5);
57   vector = factory->NewTypeFeedbackVector(&spec);
58   CHECK_EQ(3, vector->Slots());
59   CHECK_EQ(5, vector->ICSlots());
60
61   int metadata_length = vector->ic_metadata_length();
62   CHECK(metadata_length > 0);
63
64   int index = vector->GetIndex(FeedbackVectorSlot(0));
65
66   CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index);
67   CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index));
68
69   index = vector->GetIndex(FeedbackVectorICSlot(0));
70   CHECK_EQ(index,
71            TypeFeedbackVector::kReservedIndexCount + metadata_length + 3);
72   CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index));
73   CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 +
74                5 * TypeFeedbackVector::elements_per_ic_slot(),
75            vector->length());
76 }
77
78
79 // IC slots need an encoding to recognize what is in there.
80 TEST(VectorICMetadata) {
81   LocalContext context;
82   v8::HandleScope scope(context->GetIsolate());
83   Isolate* isolate = CcTest::i_isolate();
84   Factory* factory = isolate->factory();
85   Zone* zone = isolate->runtime_zone();
86
87   FeedbackVectorSpec spec(zone);
88   // Set metadata.
89   spec.AddStubSlots(10);
90   for (int i = 0; i < 30; i++) {
91     switch (i % 3) {
92       case 0:
93         spec.AddSlot(FeedbackVectorSlotKind::CALL_IC);
94         break;
95       case 1:
96         spec.AddSlot(FeedbackVectorSlotKind::LOAD_IC);
97         break;
98       case 2:
99         spec.AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
100         break;
101     }
102   }
103
104   Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
105   CHECK_EQ(10, vector->Slots());
106   CHECK_EQ(3 * 10, vector->ICSlots());
107
108   // Meanwhile set some feedback values and type feedback values to
109   // verify the data structure remains intact.
110   vector->change_ic_with_type_info_count(100);
111   vector->change_ic_generic_count(3333);
112   vector->Set(FeedbackVectorSlot(0), *vector);
113
114   // Verify the metadata is correctly set up from the spec.
115   for (int i = 0; i < 30; i++) {
116     FeedbackVectorSlotKind kind = vector->GetKind(FeedbackVectorICSlot(i));
117     if (i % 3 == 0) {
118       CHECK_EQ(FeedbackVectorSlotKind::CALL_IC, kind);
119     } else if (i % 3 == 1) {
120       CHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, kind);
121     } else {
122       CHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind);
123     }
124   }
125 }
126
127
128 TEST(VectorSlotClearing) {
129   LocalContext context;
130   v8::HandleScope scope(context->GetIsolate());
131   Isolate* isolate = CcTest::i_isolate();
132   Factory* factory = isolate->factory();
133   Zone* zone = isolate->runtime_zone();
134
135   // We only test clearing FeedbackVectorSlots, not FeedbackVectorICSlots.
136   // The reason is that FeedbackVectorICSlots need a full code environment
137   // to fully test (See VectorICProfilerStatistics test below).
138   FeedbackVectorSpec spec(zone);
139   spec.AddStubSlots(5);
140   Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
141
142   // Fill with information
143   vector->Set(FeedbackVectorSlot(0), Smi::FromInt(1));
144   Handle<WeakCell> cell = factory->NewWeakCell(factory->fixed_array_map());
145   vector->Set(FeedbackVectorSlot(1), *cell);
146   Handle<AllocationSite> site = factory->NewAllocationSite();
147   vector->Set(FeedbackVectorSlot(2), *site);
148
149   // GC time clearing leaves slots alone.
150   vector->ClearSlotsAtGCTime(NULL);
151   Object* obj = vector->Get(FeedbackVectorSlot(1));
152   CHECK(obj->IsWeakCell() && !WeakCell::cast(obj)->cleared());
153
154   vector->ClearSlots(NULL);
155
156   // The feedback vector slots are cleared. AllocationSites are still granted
157   // an exemption from clearing, as are smis.
158   CHECK_EQ(Smi::FromInt(1), vector->Get(FeedbackVectorSlot(0)));
159   CHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(isolate),
160            vector->Get(FeedbackVectorSlot(1)));
161   CHECK(vector->Get(FeedbackVectorSlot(2))->IsAllocationSite());
162 }
163
164
165 TEST(VectorICProfilerStatistics) {
166   if (i::FLAG_always_opt) return;
167   CcTest::InitializeVM();
168   LocalContext context;
169   v8::HandleScope scope(context->GetIsolate());
170   Isolate* isolate = CcTest::i_isolate();
171   Heap* heap = isolate->heap();
172
173   // Make sure function f has a call that uses a type feedback slot.
174   CompileRun(
175       "function fun() {};"
176       "function f(a) { a(); } f(fun);");
177   Handle<JSFunction> f = v8::Utils::OpenHandle(
178       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
179   // There should be one IC.
180   Handle<Code> code = handle(f->shared()->code(), isolate);
181   TypeFeedbackInfo* feedback_info =
182       TypeFeedbackInfo::cast(code->type_feedback_info());
183   CHECK_EQ(1, feedback_info->ic_total_count());
184   CHECK_EQ(0, feedback_info->ic_with_type_info_count());
185   CHECK_EQ(0, feedback_info->ic_generic_count());
186   Handle<TypeFeedbackVector> feedback_vector =
187       handle(f->shared()->feedback_vector(), isolate);
188   int ic_slot = 0;
189   CallICNexus nexus(feedback_vector, FeedbackVectorICSlot(ic_slot));
190   CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
191   CHECK_EQ(0, feedback_vector->ic_generic_count());
192
193   // Now send the information generic.
194   CompileRun("f(Object);");
195   CHECK_EQ(0, feedback_vector->ic_with_type_info_count());
196   CHECK_EQ(1, feedback_vector->ic_generic_count());
197
198   // A collection will not affect the site.
199   heap->CollectAllGarbage();
200   CHECK_EQ(0, feedback_vector->ic_with_type_info_count());
201   CHECK_EQ(1, feedback_vector->ic_generic_count());
202
203   // The Array function is special. A call to array remains monomorphic
204   // and isn't cleared by gc because an AllocationSite is being held.
205   // Clear the IC manually in order to test this case.
206   nexus.Clear(*code);
207   CompileRun("f(Array);");
208   CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
209   CHECK_EQ(0, feedback_vector->ic_generic_count());
210
211
212   CHECK(nexus.GetFeedback()->IsAllocationSite());
213   heap->CollectAllGarbage();
214   CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
215   CHECK_EQ(0, feedback_vector->ic_generic_count());
216   CHECK(nexus.GetFeedback()->IsAllocationSite());
217 }
218
219
220 TEST(VectorCallICStates) {
221   if (i::FLAG_always_opt) return;
222   CcTest::InitializeVM();
223   LocalContext context;
224   v8::HandleScope scope(context->GetIsolate());
225   Isolate* isolate = CcTest::i_isolate();
226   Heap* heap = isolate->heap();
227
228   // Make sure function f has a call that uses a type feedback slot.
229   CompileRun(
230       "function foo() { return 17; }"
231       "function f(a) { a(); } f(foo);");
232   Handle<JSFunction> f = v8::Utils::OpenHandle(
233       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
234   // There should be one IC.
235   Handle<TypeFeedbackVector> feedback_vector =
236       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
237   FeedbackVectorICSlot slot(0);
238   CallICNexus nexus(feedback_vector, slot);
239   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
240   // CallIC doesn't return map feedback.
241   CHECK(!nexus.FindFirstMap());
242
243   CompileRun("f(function() { return 16; })");
244   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
245
246   // After a collection, state should remain GENERIC.
247   heap->CollectAllGarbage();
248   CHECK_EQ(GENERIC, nexus.StateFromFeedback());
249
250   // A call to Array is special, it contains an AllocationSite as feedback.
251   // Clear the IC manually in order to test this case.
252   nexus.Clear(f->shared()->code());
253   CompileRun("f(Array)");
254   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
255   CHECK(nexus.GetFeedback()->IsAllocationSite());
256
257   heap->CollectAllGarbage();
258   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
259 }
260
261
262 TEST(VectorLoadICStates) {
263   if (i::FLAG_always_opt) return;
264   CcTest::InitializeVM();
265   LocalContext context;
266   v8::HandleScope scope(context->GetIsolate());
267   Isolate* isolate = CcTest::i_isolate();
268   Heap* heap = isolate->heap();
269
270   // Make sure function f has a call that uses a type feedback slot.
271   CompileRun(
272       "var o = { foo: 3 };"
273       "function f(a) { return a.foo; } f(o);");
274   Handle<JSFunction> f = v8::Utils::OpenHandle(
275       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
276   // There should be one IC.
277   Handle<TypeFeedbackVector> feedback_vector =
278       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
279   FeedbackVectorICSlot slot(0);
280   LoadICNexus nexus(feedback_vector, slot);
281   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
282
283   CompileRun("f(o)");
284   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
285   // Verify that the monomorphic map is the one we expect.
286   Handle<JSObject> o = v8::Utils::OpenHandle(
287       *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str("o"))));
288   CHECK_EQ(o->map(), nexus.FindFirstMap());
289
290   // Now go polymorphic.
291   CompileRun("f({ blarg: 3, foo: 2 })");
292   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
293
294   CompileRun(
295       "delete o.foo;"
296       "f(o)");
297   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
298
299   CompileRun("f({ blarg: 3, torino: 10, foo: 2 })");
300   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
301   MapHandleList maps;
302   nexus.FindAllMaps(&maps);
303   CHECK_EQ(4, maps.length());
304
305   // Finally driven megamorphic.
306   CompileRun("f({ blarg: 3, gran: 3, torino: 10, foo: 2 })");
307   CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback());
308   CHECK(!nexus.FindFirstMap());
309
310   // After a collection, state should not be reset to PREMONOMORPHIC.
311   heap->CollectAllGarbage();
312   CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback());
313 }
314
315
316 TEST(VectorLoadICSlotSharing) {
317   if (i::FLAG_always_opt) return;
318   CcTest::InitializeVM();
319   LocalContext context;
320   v8::HandleScope scope(context->GetIsolate());
321   Isolate* isolate = CcTest::i_isolate();
322
323   // Function f has 3 LoadICs, one for each o, but the ICs share the same
324   // feedback vector IC slot.
325   CompileRun(
326       "o = 10;"
327       "function f() {"
328       "  var x = o + 10;"
329       "  return o + x + o;"
330       "}"
331       "f();");
332   Handle<JSFunction> f = v8::Utils::OpenHandle(
333       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
334   // There should be one IC slot.
335   Handle<TypeFeedbackVector> feedback_vector =
336       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
337   CHECK_EQ(1, feedback_vector->ICSlots());
338   FeedbackVectorICSlot slot(0);
339   LoadICNexus nexus(feedback_vector, slot);
340   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
341 }
342
343
344 TEST(VectorLoadICOnSmi) {
345   if (i::FLAG_always_opt) return;
346   CcTest::InitializeVM();
347   LocalContext context;
348   v8::HandleScope scope(context->GetIsolate());
349   Isolate* isolate = CcTest::i_isolate();
350   Heap* heap = isolate->heap();
351
352   // Make sure function f has a call that uses a type feedback slot.
353   CompileRun(
354       "var o = { foo: 3 };"
355       "function f(a) { return a.foo; } f(o);");
356   Handle<JSFunction> f = v8::Utils::OpenHandle(
357       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
358   // There should be one IC.
359   Handle<TypeFeedbackVector> feedback_vector =
360       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
361   FeedbackVectorICSlot slot(0);
362   LoadICNexus nexus(feedback_vector, slot);
363   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
364
365   CompileRun("f(34)");
366   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
367   // Verify that the monomorphic map is the one we expect.
368   Map* number_map = heap->heap_number_map();
369   CHECK_EQ(number_map, nexus.FindFirstMap());
370
371   // Now go polymorphic on o.
372   CompileRun("f(o)");
373   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
374
375   MapHandleList maps;
376   nexus.FindAllMaps(&maps);
377   CHECK_EQ(2, maps.length());
378
379   // One of the maps should be the o map.
380   Handle<JSObject> o = v8::Utils::OpenHandle(
381       *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str("o"))));
382   bool number_map_found = false;
383   bool o_map_found = false;
384   for (int i = 0; i < maps.length(); i++) {
385     Handle<Map> current = maps[i];
386     if (*current == number_map)
387       number_map_found = true;
388     else if (*current == o->map())
389       o_map_found = true;
390   }
391   CHECK(number_map_found && o_map_found);
392
393   // The degree of polymorphism doesn't change.
394   CompileRun("f(100)");
395   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback());
396   MapHandleList maps2;
397   nexus.FindAllMaps(&maps2);
398   CHECK_EQ(2, maps2.length());
399 }
400
401
402 static Handle<JSFunction> GetFunction(const char* name) {
403   Handle<JSFunction> f = v8::Utils::OpenHandle(
404       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str(name))));
405   return f;
406 }
407
408
409 TEST(ReferenceContextAllocatesNoSlots) {
410   if (i::FLAG_always_opt) return;
411   CcTest::InitializeVM();
412   LocalContext context;
413   v8::HandleScope scope(context->GetIsolate());
414   Isolate* isolate = CcTest::i_isolate();
415
416   CompileRun(
417       "function testvar(x) {"
418       "  y = x;"
419       "  y = a;"
420       "  return y;"
421       "}"
422       "a = 3;"
423       "testvar({});");
424
425   Handle<JSFunction> f = GetFunction("testvar");
426
427   // There should be two LOAD_ICs, one for a and one for y at the end.
428   Handle<TypeFeedbackVector> feedback_vector =
429       handle(f->shared()->feedback_vector(), isolate);
430   if (FLAG_vector_stores) {
431     CHECK_EQ(4, feedback_vector->ICSlots());
432     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::STORE_IC);
433     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::LOAD_IC);
434     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::STORE_IC);
435     CHECK_SLOT_KIND(feedback_vector, 3, FeedbackVectorSlotKind::LOAD_IC);
436   } else {
437     CHECK_EQ(2, feedback_vector->ICSlots());
438     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::LOAD_IC);
439     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::LOAD_IC);
440   }
441
442   CompileRun(
443       "function testprop(x) {"
444       "  x.blue = a;"
445       "}"
446       "testprop({ blue: 3 });");
447
448   f = GetFunction("testprop");
449
450   // There should be one LOAD_IC, for the load of a.
451   feedback_vector = handle(f->shared()->feedback_vector(), isolate);
452   if (FLAG_vector_stores) {
453     CHECK_EQ(2, feedback_vector->ICSlots());
454   } else {
455     CHECK_EQ(1, feedback_vector->ICSlots());
456   }
457
458   CompileRun(
459       "function testpropfunc(x) {"
460       "  x().blue = a;"
461       "  return x().blue;"
462       "}"
463       "function makeresult() { return { blue: 3 }; }"
464       "testpropfunc(makeresult);");
465
466   f = GetFunction("testpropfunc");
467
468   // There should be 2 LOAD_ICs and 2 CALL_ICs.
469   feedback_vector = handle(f->shared()->feedback_vector(), isolate);
470   if (FLAG_vector_stores) {
471     CHECK_EQ(5, feedback_vector->ICSlots());
472     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::CALL_IC);
473     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::LOAD_IC);
474     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::STORE_IC);
475     CHECK_SLOT_KIND(feedback_vector, 3, FeedbackVectorSlotKind::CALL_IC);
476     CHECK_SLOT_KIND(feedback_vector, 4, FeedbackVectorSlotKind::LOAD_IC);
477   } else {
478     CHECK_EQ(4, feedback_vector->ICSlots());
479     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::CALL_IC);
480     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::LOAD_IC);
481     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::CALL_IC);
482     CHECK_SLOT_KIND(feedback_vector, 3, FeedbackVectorSlotKind::LOAD_IC);
483   }
484
485   CompileRun(
486       "function testkeyedprop(x) {"
487       "  x[0] = a;"
488       "  return x[0];"
489       "}"
490       "testkeyedprop([0, 1, 2]);");
491
492   f = GetFunction("testkeyedprop");
493
494   // There should be 1 LOAD_ICs for the load of a, and one KEYED_LOAD_IC for the
495   // load of x[0] in the return statement.
496   feedback_vector = handle(f->shared()->feedback_vector(), isolate);
497   if (FLAG_vector_stores) {
498     CHECK_EQ(3, feedback_vector->ICSlots());
499     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::LOAD_IC);
500     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::KEYED_STORE_IC);
501     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::KEYED_LOAD_IC);
502   } else {
503     CHECK_EQ(2, feedback_vector->ICSlots());
504     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::LOAD_IC);
505     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::KEYED_LOAD_IC);
506   }
507
508   CompileRun(
509       "function testcompound(x) {"
510       "  x.old = x.young = x.in_between = a;"
511       "  return x.old + x.young;"
512       "}"
513       "testcompound({ old: 3, young: 3, in_between: 3 });");
514
515   f = GetFunction("testcompound");
516
517   // There should be 3 LOAD_ICs, for load of a and load of x.old and x.young.
518   feedback_vector = handle(f->shared()->feedback_vector(), isolate);
519   if (FLAG_vector_stores) {
520     CHECK_EQ(6, feedback_vector->ICSlots());
521     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::LOAD_IC);
522     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::STORE_IC);
523     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::STORE_IC);
524     CHECK_SLOT_KIND(feedback_vector, 3, FeedbackVectorSlotKind::STORE_IC);
525     CHECK_SLOT_KIND(feedback_vector, 4, FeedbackVectorSlotKind::LOAD_IC);
526     CHECK_SLOT_KIND(feedback_vector, 5, FeedbackVectorSlotKind::LOAD_IC);
527   } else {
528     CHECK_EQ(3, feedback_vector->ICSlots());
529     CHECK_SLOT_KIND(feedback_vector, 0, FeedbackVectorSlotKind::LOAD_IC);
530     CHECK_SLOT_KIND(feedback_vector, 1, FeedbackVectorSlotKind::LOAD_IC);
531     CHECK_SLOT_KIND(feedback_vector, 2, FeedbackVectorSlotKind::LOAD_IC);
532   }
533 }
534
535
536 TEST(VectorStoreICBasic) {
537   if (i::FLAG_always_opt) return;
538   if (!i::FLAG_vector_stores) return;
539
540   CcTest::InitializeVM();
541   LocalContext context;
542   v8::HandleScope scope(context->GetIsolate());
543   Isolate* isolate = CcTest::i_isolate();
544
545   CompileRun(
546       "function f(a) {"
547       "  a.foo = 5;"
548       "}"
549       "var a = { foo: 3 };"
550       "f(a);"
551       "f(a);"
552       "f(a);");
553   Handle<JSFunction> f = GetFunction("f");
554   // There should be one IC slot.
555   Handle<TypeFeedbackVector> feedback_vector =
556       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
557   CHECK_EQ(1, feedback_vector->ICSlots());
558   FeedbackVectorICSlot slot(0);
559   StoreICNexus nexus(feedback_vector, slot);
560   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
561 }
562
563 }  // namespace