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 27 matching lines...) Expand all Loading... |
38 CHECK_EQ(0, vector->ICSlots()); | 38 CHECK_EQ(0, vector->ICSlots()); |
39 | 39 |
40 vector = factory->NewTypeFeedbackVector(0, 1); | 40 vector = factory->NewTypeFeedbackVector(0, 1); |
41 CHECK_EQ(0, vector->Slots()); | 41 CHECK_EQ(0, vector->Slots()); |
42 CHECK_EQ(1, vector->ICSlots()); | 42 CHECK_EQ(1, vector->ICSlots()); |
43 | 43 |
44 vector = factory->NewTypeFeedbackVector(3, 5); | 44 vector = factory->NewTypeFeedbackVector(3, 5); |
45 CHECK_EQ(3, vector->Slots()); | 45 CHECK_EQ(3, vector->Slots()); |
46 CHECK_EQ(5, vector->ICSlots()); | 46 CHECK_EQ(5, vector->ICSlots()); |
47 | 47 |
| 48 int metadata_length = vector->ic_metadata_length(); |
| 49 if (!FLAG_vector_ics) { |
| 50 CHECK_EQ(0, metadata_length); |
| 51 } else { |
| 52 CHECK(metadata_length > 0); |
| 53 } |
| 54 |
48 int index = vector->GetIndex(FeedbackVectorSlot(0)); | 55 int index = vector->GetIndex(FeedbackVectorSlot(0)); |
49 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount, index); | 56 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length, index); |
50 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); | 57 CHECK(FeedbackVectorSlot(0) == vector->ToSlot(index)); |
51 | 58 |
52 index = vector->GetIndex(FeedbackVectorICSlot(0)); | 59 index = vector->GetIndex(FeedbackVectorICSlot(0)); |
53 CHECK_EQ(index, TypeFeedbackVector::kReservedIndexCount + 3); | 60 CHECK_EQ(index, |
| 61 TypeFeedbackVector::kReservedIndexCount + metadata_length + 3); |
54 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); | 62 CHECK(FeedbackVectorICSlot(0) == vector->ToICSlot(index)); |
55 | 63 |
56 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + 3 + 5, vector->length()); | 64 CHECK_EQ(TypeFeedbackVector::kReservedIndexCount + metadata_length + 3 + 5, |
| 65 vector->length()); |
57 } | 66 } |
58 | 67 |
59 | 68 |
| 69 // IC slots need an encoding to recognize what is in there. |
| 70 TEST(VectorICMetadata) { |
| 71 LocalContext context; |
| 72 v8::HandleScope scope(context->GetIsolate()); |
| 73 if (!FLAG_vector_ics) { |
| 74 // If FLAG_vector_ics is false, we only store CALL_ICs in the vector, so |
| 75 // there is no need for metadata to describe the slots. |
| 76 return; |
| 77 } |
| 78 Isolate* isolate = CcTest::i_isolate(); |
| 79 Factory* factory = isolate->factory(); |
| 80 |
| 81 Handle<TypeFeedbackVector> vector = |
| 82 factory->NewTypeFeedbackVector(10, 3 * 10); |
| 83 CHECK_EQ(10, vector->Slots()); |
| 84 CHECK_EQ(3 * 10, vector->ICSlots()); |
| 85 |
| 86 // Set metadata. |
| 87 for (int i = 0; i < 30; i++) { |
| 88 Code::Kind kind; |
| 89 if (i % 3 == 0) |
| 90 kind = Code::CALL_IC; |
| 91 else if (i % 3 == 1) |
| 92 kind = Code::LOAD_IC; |
| 93 else if (i % 3 == 2) |
| 94 kind = Code::KEYED_LOAD_IC; |
| 95 vector->SetKind(FeedbackVectorICSlot(i), kind); |
| 96 } |
| 97 |
| 98 // Meanwhile set some feedback values and type feedback values to |
| 99 // verify the data structure remains intact. |
| 100 vector->change_ic_with_type_info_count(100); |
| 101 vector->change_ic_generic_count(3333); |
| 102 vector->Set(FeedbackVectorSlot(0), *vector); |
| 103 |
| 104 // Verify the metadata remains the same. |
| 105 for (int i = 0; i < 30; i++) { |
| 106 Code::Kind kind = vector->GetKind(FeedbackVectorICSlot(i)); |
| 107 if (i % 3 == 0) { |
| 108 CHECK_EQ(Code::CALL_IC, kind); |
| 109 } else if (i % 3 == 1) { |
| 110 CHECK_EQ(Code::LOAD_IC, kind); |
| 111 } else { |
| 112 CHECK_EQ(Code::KEYED_LOAD_IC, kind); |
| 113 } |
| 114 } |
| 115 } |
| 116 |
| 117 |
60 TEST(VectorSlotClearing) { | 118 TEST(VectorSlotClearing) { |
61 LocalContext context; | 119 LocalContext context; |
62 v8::HandleScope scope(context->GetIsolate()); | 120 v8::HandleScope scope(context->GetIsolate()); |
63 Isolate* isolate = CcTest::i_isolate(); | 121 Isolate* isolate = CcTest::i_isolate(); |
64 Factory* factory = isolate->factory(); | 122 Factory* factory = isolate->factory(); |
65 | 123 |
66 // We only test clearing FeedbackVectorSlots, not FeedbackVectorICSlots. | 124 // We only test clearing FeedbackVectorSlots, not FeedbackVectorICSlots. |
67 // The reason is that FeedbackVectorICSlots need a full code environment | 125 // The reason is that FeedbackVectorICSlots need a full code environment |
68 // to fully test (See VectorICProfilerStatistics test below). | 126 // to fully test (See VectorICProfilerStatistics test below). |
69 Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(5, 0); | 127 Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(5, 0); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 CHECK_EQ(0, feedback_vector->ic_with_type_info_count()); | 180 CHECK_EQ(0, feedback_vector->ic_with_type_info_count()); |
123 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 181 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
124 | 182 |
125 // The Array function is special. A call to array remains monomorphic | 183 // The Array function is special. A call to array remains monomorphic |
126 // and isn't cleared by gc because an AllocationSite is being held. | 184 // and isn't cleared by gc because an AllocationSite is being held. |
127 CompileRun("f(Array);"); | 185 CompileRun("f(Array);"); |
128 feedback_vector = f->shared()->feedback_vector(); | 186 feedback_vector = f->shared()->feedback_vector(); |
129 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); | 187 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); |
130 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 188 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
131 | 189 |
132 CHECK(feedback_vector->Get(FeedbackVectorICSlot(0))->IsAllocationSite()); | 190 int ic_slot = FLAG_vector_ics ? 1 : 0; |
| 191 CHECK( |
| 192 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); |
133 heap->CollectAllGarbage(i::Heap::kNoGCFlags); | 193 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
134 feedback_vector = f->shared()->feedback_vector(); | 194 feedback_vector = f->shared()->feedback_vector(); |
135 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); | 195 CHECK_EQ(1, feedback_vector->ic_with_type_info_count()); |
136 CHECK_EQ(0, feedback_vector->ic_generic_count()); | 196 CHECK_EQ(0, feedback_vector->ic_generic_count()); |
137 CHECK(feedback_vector->Get(FeedbackVectorICSlot(0))->IsAllocationSite()); | 197 CHECK( |
| 198 feedback_vector->Get(FeedbackVectorICSlot(ic_slot))->IsAllocationSite()); |
| 199 } |
| 200 |
| 201 |
| 202 TEST(VectorCallICStates) { |
| 203 if (i::FLAG_always_opt) return; |
| 204 CcTest::InitializeVM(); |
| 205 LocalContext context; |
| 206 v8::HandleScope scope(context->GetIsolate()); |
| 207 Isolate* isolate = CcTest::i_isolate(); |
| 208 Heap* heap = isolate->heap(); |
| 209 |
| 210 // Make sure function f has a call that uses a type feedback slot. |
| 211 CompileRun( |
| 212 "function foo() { return 17; }" |
| 213 "function f(a) { a(); } f(foo);"); |
| 214 Handle<JSFunction> f = v8::Utils::OpenHandle( |
| 215 *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); |
| 216 // There should be one IC. |
| 217 Handle<TypeFeedbackVector> feedback_vector = |
| 218 Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); |
| 219 FeedbackVectorICSlot slot(FLAG_vector_ics ? 1 : 0); |
| 220 CallICNexus nexus(feedback_vector, slot); |
| 221 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 222 // CallIC doesn't return map feedback. |
| 223 CHECK_EQ(NULL, nexus.FindFirstMap()); |
| 224 |
| 225 CompileRun("f(function() { return 16; })"); |
| 226 CHECK_EQ(GENERIC, nexus.StateFromFeedback()); |
| 227 |
| 228 // After a collection, state should be reset to UNINITIALIZED. |
| 229 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 230 CHECK_EQ(UNINITIALIZED, nexus.StateFromFeedback()); |
| 231 |
| 232 // Array is special. It will remain monomorphic across gcs and it contains an |
| 233 // AllocationSite. |
| 234 CompileRun("f(Array)"); |
| 235 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
| 236 CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot))->IsAllocationSite()); |
| 237 |
| 238 heap->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 239 CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); |
138 } | 240 } |
139 } | 241 } |
OLD | NEW |