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