| 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 28 matching lines...) Expand all Loading... |
| 39 vector = factory->NewTypeFeedbackVector(&one_slot); | 39 vector = factory->NewTypeFeedbackVector(&one_slot); |
| 40 CHECK_EQ(1, vector->Slots()); | 40 CHECK_EQ(1, vector->Slots()); |
| 41 CHECK_EQ(0, vector->ICSlots()); | 41 CHECK_EQ(0, vector->ICSlots()); |
| 42 | 42 |
| 43 FeedbackVectorSpec one_icslot(0, Code::CALL_IC); | 43 FeedbackVectorSpec one_icslot(0, Code::CALL_IC); |
| 44 vector = factory->NewTypeFeedbackVector(&one_icslot); | 44 vector = factory->NewTypeFeedbackVector(&one_icslot); |
| 45 CHECK_EQ(0, vector->Slots()); | 45 CHECK_EQ(0, vector->Slots()); |
| 46 CHECK_EQ(1, vector->ICSlots()); | 46 CHECK_EQ(1, vector->ICSlots()); |
| 47 | 47 |
| 48 ZoneFeedbackVectorSpec spec(zone, 3, 5); | 48 ZoneFeedbackVectorSpec spec(zone, 3, 5); |
| 49 if (FLAG_vector_ics) { | 49 for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC); |
| 50 for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC); | |
| 51 } | |
| 52 vector = factory->NewTypeFeedbackVector(&spec); | 50 vector = factory->NewTypeFeedbackVector(&spec); |
| 53 CHECK_EQ(3, vector->Slots()); | 51 CHECK_EQ(3, vector->Slots()); |
| 54 CHECK_EQ(5, vector->ICSlots()); | 52 CHECK_EQ(5, vector->ICSlots()); |
| 55 | 53 |
| 56 int metadata_length = vector->ic_metadata_length(); | 54 int metadata_length = vector->ic_metadata_length(); |
| 57 if (!FLAG_vector_ics) { | 55 CHECK(metadata_length > 0); |
| 58 CHECK_EQ(0, metadata_length); | |
| 59 } else { | |
| 60 CHECK(metadata_length > 0); | |
| 61 } | |
| 62 | 56 |
| 63 int index = vector->GetIndex(FeedbackVectorSlot(0)); | 57 int index = vector->GetIndex(FeedbackVectorSlot(0)); |
| 64 | 58 |
| 65 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index); | 59 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index); |
| 66 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); | 60 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); |
| 67 | 61 |
| 68 index = vector->GetIndex(FeedbackVectorICSlot(0)); | 62 index = vector->GetIndex(FeedbackVectorICSlot(0)); |
| 69 CHECK_EQ(index, | 63 CHECK_EQ(index, |
| 70 TypeFeedbackVector::kReservedIndexCount + metadata_length + 3); | 64 TypeFeedbackVector::kReservedIndexCount + metadata_length + 3); |
| 71 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); | 65 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); |
| 72 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + | 66 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + |
| 73 5 * TypeFeedbackVector::elements_per_ic_slot(), | 67 5 * TypeFeedbackVector::elements_per_ic_slot(), |
| 74 vector->length()); | 68 vector->length()); |
| 75 } | 69 } |
| 76 | 70 |
| 77 | 71 |
| 78 // IC slots need an encoding to recognize what is in there. | 72 // IC slots need an encoding to recognize what is in there. |
| 79 TEST(VectorICMetadata) { | 73 TEST(VectorICMetadata) { |
| 80 LocalContext context; | 74 LocalContext context; |
| 81 v8::HandleScope scope(context->GetIsolate()); | 75 v8::HandleScope scope(context->GetIsolate()); |
| 82 if (!FLAG_vector_ics) { | |
| 83 // If FLAG_vector_ics is false, we only store CALL_ICs in the vector, so | |
| 84 // there is no need for metadata to describe the slots. | |
| 85 return; | |
| 86 } | |
| 87 Isolate* isolate = CcTest::i_isolate(); | 76 Isolate* isolate = CcTest::i_isolate(); |
| 88 Factory* factory = isolate->factory(); | 77 Factory* factory = isolate->factory(); |
| 89 Zone* zone = isolate->runtime_zone(); | 78 Zone* zone = isolate->runtime_zone(); |
| 90 | 79 |
| 91 ZoneFeedbackVectorSpec spec(zone, 10, 3 * 10); | 80 ZoneFeedbackVectorSpec spec(zone, 10, 3 * 10); |
| 92 // Set metadata. | 81 // Set metadata. |
| 93 for (int i = 0; i < 30; i++) { | 82 for (int i = 0; i < 30; i++) { |
| 94 Code::Kind kind; | 83 Code::Kind kind; |
| 95 if (i % 3 == 0) { | 84 if (i % 3 == 0) { |
| 96 kind = Code::CALL_IC; | 85 kind = Code::CALL_IC; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 CompileRun("f(Array)"); | 241 CompileRun("f(Array)"); |
| 253 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 242 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 254 CHECK(nexus.GetFeedback()->IsAllocationSite()); | 243 CHECK(nexus.GetFeedback()->IsAllocationSite()); |
| 255 | 244 |
| 256 heap->CollectAllGarbage(); | 245 heap->CollectAllGarbage(); |
| 257 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 246 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 258 } | 247 } |
| 259 | 248 |
| 260 | 249 |
| 261 TEST(VectorLoadICStates) { | 250 TEST(VectorLoadICStates) { |
| 262 if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; | 251 if (i::FLAG_always_opt) return; |
| 263 CcTest::InitializeVM(); | 252 CcTest::InitializeVM(); |
| 264 LocalContext context; | 253 LocalContext context; |
| 265 v8::HandleScope scope(context->GetIsolate()); | 254 v8::HandleScope scope(context->GetIsolate()); |
| 266 Isolate* isolate = CcTest::i_isolate(); | 255 Isolate* isolate = CcTest::i_isolate(); |
| 267 Heap* heap = isolate->heap(); | 256 Heap* heap = isolate->heap(); |
| 268 | 257 |
| 269 // 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. |
| 270 CompileRun( | 259 CompileRun( |
| 271 "var o = { foo: 3 };" | 260 "var o = { foo: 3 };" |
| 272 "function f(a) { return a.foo; } f(o);"); | 261 "function f(a) { return a.foo; } f(o);"); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback()); | 295 CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback()); |
| 307 CHECK(!nexus.FindFirstMap()); | 296 CHECK(!nexus.FindFirstMap()); |
| 308 | 297 |
| 309 // After a collection, state should not be reset to PREMONOMORPHIC. | 298 // After a collection, state should not be reset to PREMONOMORPHIC. |
| 310 heap->CollectAllGarbage(); | 299 heap->CollectAllGarbage(); |
| 311 CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback()); | 300 CHECK_EQ(MEGAMORPHIC, nexus.StateFromFeedback()); |
| 312 } | 301 } |
| 313 | 302 |
| 314 | 303 |
| 315 TEST(VectorLoadICSlotSharing) { | 304 TEST(VectorLoadICSlotSharing) { |
| 316 if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; | 305 if (i::FLAG_always_opt) return; |
| 317 CcTest::InitializeVM(); | 306 CcTest::InitializeVM(); |
| 318 LocalContext context; | 307 LocalContext context; |
| 319 v8::HandleScope scope(context->GetIsolate()); | 308 v8::HandleScope scope(context->GetIsolate()); |
| 320 Isolate* isolate = CcTest::i_isolate(); | 309 Isolate* isolate = CcTest::i_isolate(); |
| 321 | 310 |
| 322 // Function f has 3 LoadICs, one for each o, but the ICs share the same | 311 // Function f has 3 LoadICs, one for each o, but the ICs share the same |
| 323 // feedback vector IC slot. | 312 // feedback vector IC slot. |
| 324 CompileRun( | 313 CompileRun( |
| 325 "var o = 10;" | 314 "var o = 10;" |
| 326 "function f() {" | 315 "function f() {" |
| 327 " var x = o + 10;" | 316 " var x = o + 10;" |
| 328 " return o + x + o;" | 317 " return o + x + o;" |
| 329 "}" | 318 "}" |
| 330 "f();"); | 319 "f();"); |
| 331 Handle<JSFunction> f = v8::Utils::OpenHandle( | 320 Handle<JSFunction> f = v8::Utils::OpenHandle( |
| 332 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); | 321 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
| 333 // There should be one IC slot. | 322 // There should be one IC slot. |
| 334 Handle<TypeFeedbackVector> feedback_vector = | 323 Handle<TypeFeedbackVector> feedback_vector = |
| 335 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 324 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); |
| 336 CHECK_EQ(1, feedback_vector->ICSlots()); | 325 CHECK_EQ(1, feedback_vector->ICSlots()); |
| 337 FeedbackVectorICSlot slot(0); | 326 FeedbackVectorICSlot slot(0); |
| 338 LoadICNexus nexus(feedback_vector, slot); | 327 LoadICNexus nexus(feedback_vector, slot); |
| 339 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 328 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 340 } | 329 } |
| 341 | 330 |
| 342 | 331 |
| 343 TEST(VectorLoadICOnSmi) { | 332 TEST(VectorLoadICOnSmi) { |
| 344 if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; | 333 if (i::FLAG_always_opt) return; |
| 345 CcTest::InitializeVM(); | 334 CcTest::InitializeVM(); |
| 346 LocalContext context; | 335 LocalContext context; |
| 347 v8::HandleScope scope(context->GetIsolate()); | 336 v8::HandleScope scope(context->GetIsolate()); |
| 348 Isolate* isolate = CcTest::i_isolate(); | 337 Isolate* isolate = CcTest::i_isolate(); |
| 349 Heap* heap = isolate->heap(); | 338 Heap* heap = isolate->heap(); |
| 350 | 339 |
| 351 // Make sure function f has a call that uses a type feedback slot. | 340 // Make sure function f has a call that uses a type feedback slot. |
| 352 CompileRun( | 341 CompileRun( |
| 353 "var o = { foo: 3 };" | 342 "var o = { foo: 3 };" |
| 354 "function f(a) { return a.foo; } f(o);"); | 343 "function f(a) { return a.foo; } f(o);"); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 CHECK(number_map_found && o_map_found); | 379 CHECK(number_map_found && o_map_found); |
| 391 | 380 |
| 392 // The degree of polymorphism doesn't change. | 381 // The degree of polymorphism doesn't change. |
| 393 CompileRun("f(100)"); | 382 CompileRun("f(100)"); |
| 394 CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 383 CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); |
| 395 MapHandleList maps2; | 384 MapHandleList maps2; |
| 396 nexus.FindAllMaps(&maps2); | 385 nexus.FindAllMaps(&maps2); |
| 397 CHECK_EQ(2, maps2.length()); | 386 CHECK_EQ(2, maps2.length()); |
| 398 } | 387 } |
| 399 } | 388 } |
| OLD | NEW |