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