| 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 |