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 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
9 #include "src/ic/ic-state.h" | 9 #include "src/ic/ic-state.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 Code::Kind kind = GetKind(slot); | 204 Code::Kind kind = GetKind(slot); |
205 if (kind == Code::CALL_IC) { | 205 if (kind == Code::CALL_IC) { |
206 CallICNexus nexus(this, slot); | 206 CallICNexus nexus(this, slot); |
207 nexus.Clear(host); | 207 nexus.Clear(host); |
208 } else if (kind == Code::LOAD_IC) { | 208 } else if (kind == Code::LOAD_IC) { |
209 LoadICNexus nexus(this, slot); | 209 LoadICNexus nexus(this, slot); |
210 nexus.Clear(host); | 210 nexus.Clear(host); |
211 } else if (kind == Code::KEYED_LOAD_IC) { | 211 } else if (kind == Code::KEYED_LOAD_IC) { |
212 KeyedLoadICNexus nexus(this, slot); | 212 KeyedLoadICNexus nexus(this, slot); |
213 nexus.Clear(host); | 213 nexus.Clear(host); |
| 214 } else if (kind == Code::STORE_IC) { |
| 215 DCHECK(FLAG_vector_stores); |
| 216 StoreICNexus nexus(this, slot); |
| 217 nexus.Clear(host); |
| 218 } else if (kind == Code::KEYED_STORE_IC) { |
| 219 DCHECK(FLAG_vector_stores); |
| 220 KeyedStoreICNexus nexus(this, slot); |
| 221 nexus.Clear(host); |
214 } | 222 } |
215 // TODO(mvstanton): Handle clearing of store ics when FLAG_vector_stores | |
216 // is true. | |
217 } | 223 } |
218 } | 224 } |
219 } | 225 } |
220 | 226 |
221 | 227 |
222 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { | 228 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
223 Isolate* isolate = GetIsolate(); | 229 Isolate* isolate = GetIsolate(); |
224 Handle<Object> feedback = handle(GetFeedback(), isolate); | 230 Handle<Object> feedback = handle(GetFeedback(), isolate); |
225 if (!feedback->IsFixedArray() || | 231 if (!feedback->IsFixedArray() || |
226 FixedArray::cast(*feedback)->length() != length) { | 232 FixedArray::cast(*feedback)->length() != length) { |
(...skipping 24 matching lines...) Expand all Loading... |
251 int receiver_count = maps->length(); | 257 int receiver_count = maps->length(); |
252 for (int current = 0; current < receiver_count; ++current) { | 258 for (int current = 0; current < receiver_count; ++current) { |
253 Handle<Map> map = maps->at(current); | 259 Handle<Map> map = maps->at(current); |
254 Handle<WeakCell> cell = Map::WeakCellForMap(map); | 260 Handle<WeakCell> cell = Map::WeakCellForMap(map); |
255 array->set(current * 2, *cell); | 261 array->set(current * 2, *cell); |
256 array->set(current * 2 + 1, *handlers->at(current)); | 262 array->set(current * 2 + 1, *handlers->at(current)); |
257 } | 263 } |
258 } | 264 } |
259 | 265 |
260 | 266 |
| 267 void FeedbackNexus::ConfigureUninitialized() { |
| 268 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 269 SKIP_WRITE_BARRIER); |
| 270 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 271 SKIP_WRITE_BARRIER); |
| 272 } |
| 273 |
| 274 |
| 275 void FeedbackNexus::ConfigurePremonomorphic() { |
| 276 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()), |
| 277 SKIP_WRITE_BARRIER); |
| 278 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 279 SKIP_WRITE_BARRIER); |
| 280 } |
| 281 |
| 282 |
| 283 void FeedbackNexus::ConfigureMegamorphic() { |
| 284 Isolate* isolate = GetIsolate(); |
| 285 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), |
| 286 SKIP_WRITE_BARRIER); |
| 287 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 288 SKIP_WRITE_BARRIER); |
| 289 } |
| 290 |
| 291 |
261 InlineCacheState LoadICNexus::StateFromFeedback() const { | 292 InlineCacheState LoadICNexus::StateFromFeedback() const { |
262 Isolate* isolate = GetIsolate(); | 293 Isolate* isolate = GetIsolate(); |
263 Object* feedback = GetFeedback(); | 294 Object* feedback = GetFeedback(); |
264 | 295 |
265 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { | 296 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
266 return UNINITIALIZED; | 297 return UNINITIALIZED; |
267 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { | 298 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
268 return MEGAMORPHIC; | 299 return MEGAMORPHIC; |
269 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { | 300 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
270 return PREMONOMORPHIC; | 301 return PREMONOMORPHIC; |
(...skipping 30 matching lines...) Expand all Loading... |
301 } else if (feedback->IsName()) { | 332 } else if (feedback->IsName()) { |
302 Object* extra = GetFeedbackExtra(); | 333 Object* extra = GetFeedbackExtra(); |
303 FixedArray* extra_array = FixedArray::cast(extra); | 334 FixedArray* extra_array = FixedArray::cast(extra); |
304 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; | 335 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
305 } | 336 } |
306 | 337 |
307 return UNINITIALIZED; | 338 return UNINITIALIZED; |
308 } | 339 } |
309 | 340 |
310 | 341 |
| 342 InlineCacheState StoreICNexus::StateFromFeedback() const { |
| 343 Isolate* isolate = GetIsolate(); |
| 344 Object* feedback = GetFeedback(); |
| 345 |
| 346 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 347 return UNINITIALIZED; |
| 348 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 349 return MEGAMORPHIC; |
| 350 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 351 return PREMONOMORPHIC; |
| 352 } else if (feedback->IsFixedArray()) { |
| 353 // Determine state purely by our structure, don't check if the maps are |
| 354 // cleared. |
| 355 return POLYMORPHIC; |
| 356 } else if (feedback->IsWeakCell()) { |
| 357 // Don't check if the map is cleared. |
| 358 return MONOMORPHIC; |
| 359 } |
| 360 |
| 361 return UNINITIALIZED; |
| 362 } |
| 363 |
| 364 |
| 365 InlineCacheState KeyedStoreICNexus::StateFromFeedback() const { |
| 366 Isolate* isolate = GetIsolate(); |
| 367 Object* feedback = GetFeedback(); |
| 368 |
| 369 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 370 return UNINITIALIZED; |
| 371 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 372 return PREMONOMORPHIC; |
| 373 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 374 return MEGAMORPHIC; |
| 375 } else if (feedback->IsFixedArray()) { |
| 376 // Determine state purely by our structure, don't check if the maps are |
| 377 // cleared. |
| 378 return POLYMORPHIC; |
| 379 } else if (feedback->IsWeakCell()) { |
| 380 // Don't check if the map is cleared. |
| 381 return MONOMORPHIC; |
| 382 } else if (feedback->IsName()) { |
| 383 Object* extra = GetFeedbackExtra(); |
| 384 FixedArray* extra_array = FixedArray::cast(extra); |
| 385 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
| 386 } |
| 387 |
| 388 return UNINITIALIZED; |
| 389 } |
| 390 |
| 391 |
311 InlineCacheState CallICNexus::StateFromFeedback() const { | 392 InlineCacheState CallICNexus::StateFromFeedback() const { |
312 Isolate* isolate = GetIsolate(); | 393 Isolate* isolate = GetIsolate(); |
313 Object* feedback = GetFeedback(); | 394 Object* feedback = GetFeedback(); |
314 DCHECK(GetFeedbackExtra() == | 395 DCHECK(GetFeedbackExtra() == |
315 *TypeFeedbackVector::UninitializedSentinel(isolate) || | 396 *TypeFeedbackVector::UninitializedSentinel(isolate) || |
316 GetFeedbackExtra()->IsSmi()); | 397 GetFeedbackExtra()->IsSmi()); |
317 | 398 |
318 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { | 399 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
319 return GENERIC; | 400 return GENERIC; |
320 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) { | 401 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) { |
(...skipping 11 matching lines...) Expand all Loading... |
332 int value = Smi::cast(call_count)->value() / 2; | 413 int value = Smi::cast(call_count)->value() / 2; |
333 return value; | 414 return value; |
334 } | 415 } |
335 return -1; | 416 return -1; |
336 } | 417 } |
337 | 418 |
338 | 419 |
339 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } | 420 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } |
340 | 421 |
341 | 422 |
342 void CallICNexus::ConfigureGeneric() { | |
343 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), | |
344 SKIP_WRITE_BARRIER); | |
345 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), | |
346 SKIP_WRITE_BARRIER); | |
347 } | |
348 | |
349 | |
350 void CallICNexus::ConfigureMonomorphicArray() { | 423 void CallICNexus::ConfigureMonomorphicArray() { |
351 Object* feedback = GetFeedback(); | 424 Object* feedback = GetFeedback(); |
352 if (!feedback->IsAllocationSite()) { | 425 if (!feedback->IsAllocationSite()) { |
353 Handle<AllocationSite> new_site = | 426 Handle<AllocationSite> new_site = |
354 GetIsolate()->factory()->NewAllocationSite(); | 427 GetIsolate()->factory()->NewAllocationSite(); |
355 SetFeedback(*new_site); | 428 SetFeedback(*new_site); |
356 } | 429 } |
357 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); | 430 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); |
358 } | 431 } |
359 | 432 |
360 | 433 |
361 void CallICNexus::ConfigureUninitialized() { | |
362 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), | |
363 SKIP_WRITE_BARRIER); | |
364 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), | |
365 SKIP_WRITE_BARRIER); | |
366 } | |
367 | |
368 | |
369 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { | 434 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
370 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function); | 435 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function); |
371 SetFeedback(*new_cell); | 436 SetFeedback(*new_cell); |
372 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); | 437 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); |
373 } | 438 } |
374 | 439 |
375 | 440 |
376 void KeyedLoadICNexus::ConfigureMegamorphic() { | |
377 Isolate* isolate = GetIsolate(); | |
378 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), | |
379 SKIP_WRITE_BARRIER); | |
380 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), | |
381 SKIP_WRITE_BARRIER); | |
382 } | |
383 | |
384 | |
385 void LoadICNexus::ConfigureMegamorphic() { | |
386 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), | |
387 SKIP_WRITE_BARRIER); | |
388 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), | |
389 SKIP_WRITE_BARRIER); | |
390 } | |
391 | |
392 | |
393 void LoadICNexus::ConfigurePremonomorphic() { | |
394 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()), | |
395 SKIP_WRITE_BARRIER); | |
396 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), | |
397 SKIP_WRITE_BARRIER); | |
398 } | |
399 | |
400 | |
401 void KeyedLoadICNexus::ConfigurePremonomorphic() { | |
402 Isolate* isolate = GetIsolate(); | |
403 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(isolate), | |
404 SKIP_WRITE_BARRIER); | |
405 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), | |
406 SKIP_WRITE_BARRIER); | |
407 } | |
408 | |
409 | |
410 void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, | 441 void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
411 Handle<Code> handler) { | 442 Handle<Code> handler) { |
412 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | 443 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
413 SetFeedback(*cell); | 444 SetFeedback(*cell); |
414 SetFeedbackExtra(*handler); | 445 SetFeedbackExtra(*handler); |
415 } | 446 } |
416 | 447 |
417 | 448 |
418 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, | 449 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, |
419 Handle<Map> receiver_map, | 450 Handle<Map> receiver_map, |
420 Handle<Code> handler) { | 451 Handle<Code> handler) { |
421 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | 452 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
422 if (name.is_null()) { | 453 if (name.is_null()) { |
423 SetFeedback(*cell); | 454 SetFeedback(*cell); |
| 455 SetFeedbackExtra(*handler); |
| 456 } else { |
| 457 SetFeedback(*name); |
| 458 Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
| 459 array->set(0, *cell); |
| 460 array->set(1, *handler); |
| 461 } |
| 462 } |
| 463 |
| 464 |
| 465 void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
| 466 Handle<Code> handler) { |
| 467 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 468 SetFeedback(*cell); |
| 469 SetFeedbackExtra(*handler); |
| 470 } |
| 471 |
| 472 |
| 473 void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name, |
| 474 Handle<Map> receiver_map, |
| 475 Handle<Code> handler) { |
| 476 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 477 if (name.is_null()) { |
| 478 SetFeedback(*cell); |
424 SetFeedbackExtra(*handler); | 479 SetFeedbackExtra(*handler); |
425 } else { | 480 } else { |
426 SetFeedback(*name); | 481 SetFeedback(*name); |
427 Handle<FixedArray> array = EnsureExtraArrayOfSize(2); | 482 Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
428 array->set(0, *cell); | 483 array->set(0, *cell); |
429 array->set(1, *handler); | 484 array->set(1, *handler); |
430 } | 485 } |
431 } | 486 } |
432 | 487 |
433 | 488 |
(...skipping 20 matching lines...) Expand all Loading... |
454 SKIP_WRITE_BARRIER); | 509 SKIP_WRITE_BARRIER); |
455 } else { | 510 } else { |
456 SetFeedback(*name); | 511 SetFeedback(*name); |
457 array = EnsureExtraArrayOfSize(receiver_count * 2); | 512 array = EnsureExtraArrayOfSize(receiver_count * 2); |
458 } | 513 } |
459 | 514 |
460 InstallHandlers(array, maps, handlers); | 515 InstallHandlers(array, maps, handlers); |
461 } | 516 } |
462 | 517 |
463 | 518 |
| 519 void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 520 CodeHandleList* handlers) { |
| 521 Isolate* isolate = GetIsolate(); |
| 522 int receiver_count = maps->length(); |
| 523 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2); |
| 524 InstallHandlers(array, maps, handlers); |
| 525 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 526 SKIP_WRITE_BARRIER); |
| 527 } |
| 528 |
| 529 |
| 530 void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name, |
| 531 MapHandleList* maps, |
| 532 CodeHandleList* handlers) { |
| 533 int receiver_count = maps->length(); |
| 534 DCHECK(receiver_count > 1); |
| 535 Handle<FixedArray> array; |
| 536 if (name.is_null()) { |
| 537 array = EnsureArrayOfSize(receiver_count * 2); |
| 538 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 539 SKIP_WRITE_BARRIER); |
| 540 } else { |
| 541 SetFeedback(*name); |
| 542 array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 543 } |
| 544 |
| 545 InstallHandlers(array, maps, handlers); |
| 546 } |
| 547 |
| 548 |
464 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { | 549 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { |
465 Isolate* isolate = GetIsolate(); | 550 Isolate* isolate = GetIsolate(); |
466 Object* feedback = GetFeedback(); | 551 Object* feedback = GetFeedback(); |
467 if (feedback->IsFixedArray() || feedback->IsString()) { | 552 if (feedback->IsFixedArray() || feedback->IsString()) { |
468 int found = 0; | 553 int found = 0; |
469 if (feedback->IsString()) { | 554 if (feedback->IsString()) { |
470 feedback = GetFeedbackExtra(); | 555 feedback = GetFeedbackExtra(); |
471 } | 556 } |
472 FixedArray* array = FixedArray::cast(feedback); | 557 FixedArray* array = FixedArray::cast(feedback); |
473 // The array should be of the form [<optional name>], then | 558 // The array should be of the form [<optional name>], then |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 } | 658 } |
574 | 659 |
575 | 660 |
576 Name* KeyedLoadICNexus::FindFirstName() const { | 661 Name* KeyedLoadICNexus::FindFirstName() const { |
577 Object* feedback = GetFeedback(); | 662 Object* feedback = GetFeedback(); |
578 if (feedback->IsString()) { | 663 if (feedback->IsString()) { |
579 return Name::cast(feedback); | 664 return Name::cast(feedback); |
580 } | 665 } |
581 return NULL; | 666 return NULL; |
582 } | 667 } |
| 668 |
| 669 |
| 670 Name* KeyedStoreICNexus::FindFirstName() const { |
| 671 Object* feedback = GetFeedback(); |
| 672 if (feedback->IsString()) { |
| 673 return Name::cast(feedback); |
| 674 } |
| 675 return NULL; |
| 676 } |
| 677 |
| 678 |
| 679 void StoreICNexus::Clear(Code* host) { |
| 680 StoreIC::Clear(GetIsolate(), host, this); |
| 681 } |
| 682 |
| 683 |
| 684 void KeyedStoreICNexus::Clear(Code* host) { |
| 685 KeyedStoreIC::Clear(GetIsolate(), host, this); |
| 686 } |
583 } // namespace internal | 687 } // namespace internal |
584 } // namespace v8 | 688 } // namespace v8 |
OLD | NEW |