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.h" | 9 #include "src/debug.h" |
10 #include "src/execution.h" | 10 #include "src/execution.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 CHECK_EQ(5, vector->ICSlots()); | 46 CHECK_EQ(5, vector->ICSlots()); |
47 | 47 |
48 int metadata_length = vector->ic_metadata_length(); | 48 int metadata_length = vector->ic_metadata_length(); |
49 if (!FLAG_vector_ics) { | 49 if (!FLAG_vector_ics) { |
50 CHECK_EQ(0, metadata_length); | 50 CHECK_EQ(0, metadata_length); |
51 } else { | 51 } else { |
52 CHECK(metadata_length > 0); | 52 CHECK(metadata_length > 0); |
53 } | 53 } |
54 | 54 |
55 int index = vector->GetIndex(FeedbackVectorSlot(0)); | 55 int index = vector->GetIndex(FeedbackVectorSlot(0)); |
| 56 |
56 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index); | 57 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index); |
57 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); | 58 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); |
58 | 59 |
59 index = vector->GetIndex(FeedbackVectorICSlot(0)); | 60 index = vector->GetIndex(FeedbackVectorICSlot(0)); |
60 CHECK_EQ(index, | 61 CHECK_EQ(index, |
61 TypeFeedbackVector::kReservedIndexCount + metadata_length + 3); | 62 TypeFeedbackVector::kReservedIndexCount + metadata_length + 3); |
62 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); | 63 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); |
63 | 64 |
64 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + 5, | 65 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + 5, |
65 vector->length()); | 66 vector->length()); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 CHECK_EQ(0, feedback_vector->ic_with_type_info_count()); | 182 CHECK_EQ(0, feedback_vector->ic_with_type_info_count()); |
182 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 183 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
183 | 184 |
184 // The Array function is special. A call to array remains monomorphic | 185 // The Array function is special. A call to array remains monomorphic |
185 // and isn't cleared by gc because an AllocationSite is being held. | 186 // and isn't cleared by gc because an AllocationSite is being held. |
186 CompileRun("f(Array);"); | 187 CompileRun("f(Array);"); |
187 feedback_vector = f->shared()->feedback_vector(); | 188 feedback_vector = f->shared()->feedback_vector(); |
188 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); | 189 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); |
189 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 190 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
190 | 191 |
191 int ic_slot = FLAG_vector_ics ? 1 : 0; | 192 int ic_slot = 0; |
192 CHECK( | 193 CHECK( |
193 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); | 194 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); |
194 heap->CollectAllGarbage(i::Heap::kNoGCFlags); | 195 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
195 feedback_vector = f->shared()->feedback_vector(); | 196 feedback_vector = f->shared()->feedback_vector(); |
196 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); | 197 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); |
197 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 198 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
198 CHECK( | 199 CHECK( |
199 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); | 200 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); |
200 } | 201 } |
201 | 202 |
202 | 203 |
203 TEST(VectorCallICStates) { | 204 TEST(VectorCallICStates) { |
204 if (i::FLAG_always_opt) return; | 205 if (i::FLAG_always_opt) return; |
205 CcTest::InitializeVM(); | 206 CcTest::InitializeVM(); |
206 LocalContext context; | 207 LocalContext context; |
207 v8::HandleScope scope(context->GetIsolate()); | 208 v8::HandleScope scope(context->GetIsolate()); |
208 Isolate* isolate = CcTest::i_isolate(); | 209 Isolate* isolate = CcTest::i_isolate(); |
209 Heap* heap = isolate->heap(); | 210 Heap* heap = isolate->heap(); |
210 | 211 |
211 // Make sure function f has a call that uses a type feedback slot. | 212 // Make sure function f has a call that uses a type feedback slot. |
212 CompileRun( | 213 CompileRun( |
213 "function foo() { return 17; }" | 214 "function foo() { return 17; }" |
214 "function f(a) { a(); } f(foo);"); | 215 "function f(a) { a(); } f(foo);"); |
215 Handle<JSFunction> f = v8::Utils::OpenHandle( | 216 Handle<JSFunction> f = v8::Utils::OpenHandle( |
216 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); | 217 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
217 // There should be one IC. | 218 // There should be one IC. |
218 Handle<TypeFeedbackVector> feedback_vector = | 219 Handle<TypeFeedbackVector> feedback_vector = |
219 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 220 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); |
220 FeedbackVectorICSlot slot(FLAG_vector_ics ? 1 : 0); | 221 FeedbackVectorICSlot slot(0); |
221 CallICNexus nexus(feedback_vector, slot); | 222 CallICNexus nexus(feedback_vector, slot); |
222 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 223 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
223 // CallIC doesn't return map feedback. | 224 // CallIC doesn't return map feedback. |
224 CHECK_EQ(NULL, nexus.FindFirstMap()); | 225 CHECK_EQ(NULL, nexus.FindFirstMap()); |
225 | 226 |
226 CompileRun("f(function() { return 16; })"); | 227 CompileRun("f(function() { return 16; })"); |
227 CHECK_EQ(GENERIC, nexus.StateFromFeedback()); | 228 CHECK_EQ(GENERIC, nexus.StateFromFeedback()); |
228 | 229 |
229 // After a collection, state should be reset to UNINITIALIZED. | 230 // After a collection, state should be reset to UNINITIALIZED. |
230 heap->CollectAllGarbage(i::Heap::kNoGCFlags); | 231 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
231 CHECK_EQ(UNINITIALIZED, nexus.StateFromFeedback()); | 232 CHECK_EQ(UNINITIALIZED, nexus.StateFromFeedback()); |
232 | 233 |
233 // Array is special. It will remain monomorphic across gcs and it contains an | 234 // Array is special. It will remain monomorphic across gcs and it contains an |
234 // AllocationSite. | 235 // AllocationSite. |
235 CompileRun("f(Array)"); | 236 CompileRun("f(Array)"); |
236 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 237 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
237 CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot))->IsAllocationSite()); | 238 CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot))->IsAllocationSite()); |
238 | 239 |
239 heap->CollectAllGarbage(i::Heap::kNoGCFlags); | 240 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
240 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 241 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
241 } | 242 } |
| 243 |
| 244 |
| 245 TEST(VectorLoadICStates) { |
| 246 if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; |
| 247 CcTest::InitializeVM(); |
| 248 LocalContext context; |
| 249 v8::HandleScope scope(context->GetIsolate()); |
| 250 Isolate* isolate = CcTest::i_isolate(); |
| 251 Heap* heap = isolate->heap(); |
| 252 |
| 253 // Make sure function f has a call that uses a type feedback slot. |
| 254 CompileRun( |
| 255 "var o = { foo: 3 };" |
| 256 "function f(a) { return a.foo; } f(o);"); |
| 257 Handle<JSFunction> f = v8::Utils::OpenHandle( |
| 258 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
| 259 // There should be one IC. |
| 260 Handle<TypeFeedbackVector> feedback_vector = |
| 261 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); |
| 262 FeedbackVectorICSlot slot(0); |
| 263 LoadICNexus nexus(feedback_vector, slot); |
| 264 CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); |
| 265 |
| 266 CompileRun("f(o)"); |
| 267 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 268 // Verify that the monomorphic map is the one we expect. |
| 269 Handle<JSObject> o = v8::Utils::OpenHandle( |
| 270 *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str("o")))); |
| 271 CHECK_EQ(o->map(), nexus.FindFirstMap()); |
| 272 |
| 273 // Now go polymorphic. |
| 274 CompileRun("f({ blarg: 3, foo: 2 })"); |
| 275 CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); |
| 276 |
| 277 CompileRun( |
| 278 "delete o.foo;" |
| 279 "f(o)"); |
| 280 CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); |
| 281 |
| 282 CompileRun("f({ blarg: 3, torino: 10, foo: 2 })"); |
| 283 CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); |
| 284 MapHandleList maps; |
| 285 nexus.FindAllMaps(&maps); |
| 286 CHECK_EQ(4, maps.length()); |
| 287 |
| 288 // Finally driven megamorphic. |
| 289 CompileRun("f({ blarg: 3, gran: 3, torino: 10, foo: 2 })"); |
| 290 CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback()); |
| 291 CHECK_EQ(NULL, nexus.FindFirstMap()); |
| 292 |
| 293 // After a collection, state should be reset to PREMONOMORPHIC. |
| 294 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 295 CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); |
242 } | 296 } |
| 297 } |
OLD | NEW |