OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 code = compiler.CompileStoreField(receiver, field_index, transition, name); | 434 code = compiler.CompileStoreField(receiver, field_index, transition, name); |
435 if (code->IsFailure()) return code; | 435 if (code->IsFailure()) return code; |
436 PROFILE(CodeCreateEvent( | 436 PROFILE(CodeCreateEvent( |
437 Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); | 437 Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); |
438 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 438 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); |
439 if (result->IsFailure()) return result; | 439 if (result->IsFailure()) return result; |
440 } | 440 } |
441 return code; | 441 return code; |
442 } | 442 } |
443 | 443 |
| 444 #define CALL_LOGGER_TAG(kind, type) \ |
| 445 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
444 | 446 |
445 Object* StubCache::ComputeCallConstant(int argc, | 447 Object* StubCache::ComputeCallConstant(int argc, |
446 InLoopFlag in_loop, | 448 InLoopFlag in_loop, |
| 449 Code::Kind kind, |
447 String* name, | 450 String* name, |
448 Object* object, | 451 Object* object, |
449 JSObject* holder, | 452 JSObject* holder, |
450 JSFunction* function) { | 453 JSFunction* function) { |
451 // Compute the check type and the map. | 454 // Compute the check type and the map. |
452 Map* map = IC::GetCodeCacheMapForObject(object); | 455 Map* map = IC::GetCodeCacheMapForObject(object); |
453 | 456 |
454 // Compute check type based on receiver/holder. | 457 // Compute check type based on receiver/holder. |
455 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; | 458 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; |
456 if (object->IsString()) { | 459 if (object->IsString()) { |
457 check = StubCompiler::STRING_CHECK; | 460 check = StubCompiler::STRING_CHECK; |
458 } else if (object->IsNumber()) { | 461 } else if (object->IsNumber()) { |
459 check = StubCompiler::NUMBER_CHECK; | 462 check = StubCompiler::NUMBER_CHECK; |
460 } else if (object->IsBoolean()) { | 463 } else if (object->IsBoolean()) { |
461 check = StubCompiler::BOOLEAN_CHECK; | 464 check = StubCompiler::BOOLEAN_CHECK; |
462 } | 465 } |
463 | 466 |
464 Code::Flags flags = | 467 Code::Flags flags = |
465 Code::ComputeMonomorphicFlags(Code::CALL_IC, | 468 Code::ComputeMonomorphicFlags(kind, |
466 CONSTANT_FUNCTION, | 469 CONSTANT_FUNCTION, |
467 in_loop, | 470 in_loop, |
468 argc); | 471 argc); |
469 Object* code = map->FindInCodeCache(name, flags); | 472 Object* code = map->FindInCodeCache(name, flags); |
470 if (code->IsUndefined()) { | 473 if (code->IsUndefined()) { |
471 // If the function hasn't been compiled yet, we cannot do it now | 474 // If the function hasn't been compiled yet, we cannot do it now |
472 // because it may cause GC. To avoid this issue, we return an | 475 // because it may cause GC. To avoid this issue, we return an |
473 // internal error which will make sure we do not update any | 476 // internal error which will make sure we do not update any |
474 // caches. | 477 // caches. |
475 if (!function->is_compiled()) return Failure::InternalError(); | 478 if (!function->is_compiled()) return Failure::InternalError(); |
476 // Compile the stub - only create stubs for fully compiled functions. | 479 // Compile the stub - only create stubs for fully compiled functions. |
477 CallStubCompiler compiler(argc, in_loop); | 480 CallStubCompiler compiler(argc, in_loop, kind); |
478 code = compiler.CompileCallConstant(object, holder, function, name, check); | 481 code = compiler.CompileCallConstant(object, holder, function, name, check); |
479 if (code->IsFailure()) return code; | 482 if (code->IsFailure()) return code; |
480 ASSERT_EQ(flags, Code::cast(code)->flags()); | 483 ASSERT_EQ(flags, Code::cast(code)->flags()); |
481 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 484 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 485 Code::cast(code), name)); |
482 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 486 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
483 if (result->IsFailure()) return result; | 487 if (result->IsFailure()) return result; |
484 } | 488 } |
485 return Set(name, map, Code::cast(code)); | 489 return Set(name, map, Code::cast(code)); |
486 } | 490 } |
487 | 491 |
488 | 492 |
489 Object* StubCache::ComputeCallField(int argc, | 493 Object* StubCache::ComputeCallField(int argc, |
490 InLoopFlag in_loop, | 494 InLoopFlag in_loop, |
| 495 Code::Kind kind, |
491 String* name, | 496 String* name, |
492 Object* object, | 497 Object* object, |
493 JSObject* holder, | 498 JSObject* holder, |
494 int index) { | 499 int index) { |
495 // Compute the check type and the map. | 500 // Compute the check type and the map. |
496 Map* map = IC::GetCodeCacheMapForObject(object); | 501 Map* map = IC::GetCodeCacheMapForObject(object); |
497 | 502 |
498 // TODO(1233596): We cannot do receiver map check for non-JS objects | 503 // TODO(1233596): We cannot do receiver map check for non-JS objects |
499 // because they may be represented as immediates without a | 504 // because they may be represented as immediates without a |
500 // map. Instead, we check against the map in the holder. | 505 // map. Instead, we check against the map in the holder. |
501 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 506 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
502 object = holder; | 507 object = holder; |
503 } | 508 } |
504 | 509 |
505 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 510 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
506 FIELD, | 511 FIELD, |
507 in_loop, | 512 in_loop, |
508 argc); | 513 argc); |
509 Object* code = map->FindInCodeCache(name, flags); | 514 Object* code = map->FindInCodeCache(name, flags); |
510 if (code->IsUndefined()) { | 515 if (code->IsUndefined()) { |
511 CallStubCompiler compiler(argc, in_loop); | 516 CallStubCompiler compiler(argc, in_loop, kind); |
512 code = compiler.CompileCallField(JSObject::cast(object), | 517 code = compiler.CompileCallField(JSObject::cast(object), |
513 holder, | 518 holder, |
514 index, | 519 index, |
515 name); | 520 name); |
516 if (code->IsFailure()) return code; | 521 if (code->IsFailure()) return code; |
517 ASSERT_EQ(flags, Code::cast(code)->flags()); | 522 ASSERT_EQ(flags, Code::cast(code)->flags()); |
518 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 523 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 524 Code::cast(code), name)); |
519 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 525 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
520 if (result->IsFailure()) return result; | 526 if (result->IsFailure()) return result; |
521 } | 527 } |
522 return Set(name, map, Code::cast(code)); | 528 return Set(name, map, Code::cast(code)); |
523 } | 529 } |
524 | 530 |
525 | 531 |
526 Object* StubCache::ComputeCallInterceptor(int argc, | 532 Object* StubCache::ComputeCallInterceptor(int argc, |
| 533 Code::Kind kind, |
527 String* name, | 534 String* name, |
528 Object* object, | 535 Object* object, |
529 JSObject* holder) { | 536 JSObject* holder) { |
530 // Compute the check type and the map. | 537 // Compute the check type and the map. |
531 // If the object is a value, we use the prototype map for the cache. | 538 // If the object is a value, we use the prototype map for the cache. |
532 Map* map = IC::GetCodeCacheMapForObject(object); | 539 Map* map = IC::GetCodeCacheMapForObject(object); |
533 | 540 |
534 // TODO(1233596): We cannot do receiver map check for non-JS objects | 541 // TODO(1233596): We cannot do receiver map check for non-JS objects |
535 // because they may be represented as immediates without a | 542 // because they may be represented as immediates without a |
536 // map. Instead, we check against the map in the holder. | 543 // map. Instead, we check against the map in the holder. |
537 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 544 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
538 object = holder; | 545 object = holder; |
539 } | 546 } |
540 | 547 |
541 Code::Flags flags = | 548 Code::Flags flags = |
542 Code::ComputeMonomorphicFlags(Code::CALL_IC, | 549 Code::ComputeMonomorphicFlags(kind, |
543 INTERCEPTOR, | 550 INTERCEPTOR, |
544 NOT_IN_LOOP, | 551 NOT_IN_LOOP, |
545 argc); | 552 argc); |
546 Object* code = map->FindInCodeCache(name, flags); | 553 Object* code = map->FindInCodeCache(name, flags); |
547 if (code->IsUndefined()) { | 554 if (code->IsUndefined()) { |
548 CallStubCompiler compiler(argc, NOT_IN_LOOP); | 555 CallStubCompiler compiler(argc, NOT_IN_LOOP, kind); |
549 code = compiler.CompileCallInterceptor(JSObject::cast(object), | 556 code = compiler.CompileCallInterceptor(JSObject::cast(object), |
550 holder, | 557 holder, |
551 name); | 558 name); |
552 if (code->IsFailure()) return code; | 559 if (code->IsFailure()) return code; |
553 ASSERT_EQ(flags, Code::cast(code)->flags()); | 560 ASSERT_EQ(flags, Code::cast(code)->flags()); |
554 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 561 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 562 Code::cast(code), name)); |
555 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 563 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
556 if (result->IsFailure()) return result; | 564 if (result->IsFailure()) return result; |
557 } | 565 } |
558 return Set(name, map, Code::cast(code)); | 566 return Set(name, map, Code::cast(code)); |
559 } | 567 } |
560 | 568 |
561 | 569 |
562 Object* StubCache::ComputeCallNormal(int argc, | 570 Object* StubCache::ComputeCallNormal(int argc, |
563 InLoopFlag in_loop, | 571 InLoopFlag in_loop, |
| 572 Code::Kind kind, |
564 String* name, | 573 String* name, |
565 JSObject* receiver) { | 574 JSObject* receiver) { |
566 Object* code = ComputeCallNormal(argc, in_loop); | 575 Object* code = ComputeCallNormal(argc, in_loop, kind); |
567 if (code->IsFailure()) return code; | 576 if (code->IsFailure()) return code; |
568 return Set(name, receiver->map(), Code::cast(code)); | 577 return Set(name, receiver->map(), Code::cast(code)); |
569 } | 578 } |
570 | 579 |
571 | 580 |
572 Object* StubCache::ComputeCallGlobal(int argc, | 581 Object* StubCache::ComputeCallGlobal(int argc, |
573 InLoopFlag in_loop, | 582 InLoopFlag in_loop, |
| 583 Code::Kind kind, |
574 String* name, | 584 String* name, |
575 JSObject* receiver, | 585 JSObject* receiver, |
576 GlobalObject* holder, | 586 GlobalObject* holder, |
577 JSGlobalPropertyCell* cell, | 587 JSGlobalPropertyCell* cell, |
578 JSFunction* function) { | 588 JSFunction* function) { |
579 Code::Flags flags = | 589 Code::Flags flags = |
580 Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc); | 590 Code::ComputeMonomorphicFlags(kind, |
| 591 NORMAL, |
| 592 in_loop, |
| 593 argc); |
581 Object* code = receiver->map()->FindInCodeCache(name, flags); | 594 Object* code = receiver->map()->FindInCodeCache(name, flags); |
582 if (code->IsUndefined()) { | 595 if (code->IsUndefined()) { |
583 // If the function hasn't been compiled yet, we cannot do it now | 596 // If the function hasn't been compiled yet, we cannot do it now |
584 // because it may cause GC. To avoid this issue, we return an | 597 // because it may cause GC. To avoid this issue, we return an |
585 // internal error which will make sure we do not update any | 598 // internal error which will make sure we do not update any |
586 // caches. | 599 // caches. |
587 if (!function->is_compiled()) return Failure::InternalError(); | 600 if (!function->is_compiled()) return Failure::InternalError(); |
588 CallStubCompiler compiler(argc, in_loop); | 601 CallStubCompiler compiler(argc, in_loop, kind); |
589 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 602 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
590 if (code->IsFailure()) return code; | 603 if (code->IsFailure()) return code; |
591 ASSERT_EQ(flags, Code::cast(code)->flags()); | 604 ASSERT_EQ(flags, Code::cast(code)->flags()); |
592 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 605 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 606 Code::cast(code), name)); |
593 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 607 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); |
594 if (result->IsFailure()) return result; | 608 if (result->IsFailure()) return result; |
595 } | 609 } |
596 return Set(name, receiver->map(), Code::cast(code)); | 610 return Set(name, receiver->map(), Code::cast(code)); |
597 } | 611 } |
598 | 612 |
599 | 613 |
600 static Object* GetProbeValue(Code::Flags flags) { | 614 static Object* GetProbeValue(Code::Flags flags) { |
601 // Use raw_unchecked... so we don't get assert failures during GC. | 615 // Use raw_unchecked... so we don't get assert failures during GC. |
602 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); | 616 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); |
(...skipping 27 matching lines...) Expand all Loading... |
630 ASSERT(entry != -1); | 644 ASSERT(entry != -1); |
631 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == | 645 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == |
632 Heap::undefined_value()); | 646 Heap::undefined_value()); |
633 Heap::non_monomorphic_cache()->ValueAtPut(entry, code); | 647 Heap::non_monomorphic_cache()->ValueAtPut(entry, code); |
634 CHECK(GetProbeValue(Code::cast(code)->flags()) == code); | 648 CHECK(GetProbeValue(Code::cast(code)->flags()) == code); |
635 } | 649 } |
636 return code; | 650 return code; |
637 } | 651 } |
638 | 652 |
639 | 653 |
640 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) { | 654 Code* StubCache::FindCallInitialize(int argc, |
| 655 InLoopFlag in_loop, |
| 656 Code::Kind kind) { |
641 Code::Flags flags = | 657 Code::Flags flags = |
642 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 658 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); |
643 Object* result = ProbeCache(flags); | 659 Object* result = ProbeCache(flags); |
644 ASSERT(!result->IsUndefined()); | 660 ASSERT(!result->IsUndefined()); |
645 // This might be called during the marking phase of the collector | 661 // This might be called during the marking phase of the collector |
646 // hence the unchecked cast. | 662 // hence the unchecked cast. |
647 return reinterpret_cast<Code*>(result); | 663 return reinterpret_cast<Code*>(result); |
648 } | 664 } |
649 | 665 |
650 | 666 |
651 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) { | 667 Object* StubCache::ComputeCallInitialize(int argc, |
| 668 InLoopFlag in_loop, |
| 669 Code::Kind kind) { |
652 Code::Flags flags = | 670 Code::Flags flags = |
653 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 671 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); |
654 Object* probe = ProbeCache(flags); | 672 Object* probe = ProbeCache(flags); |
655 if (!probe->IsUndefined()) return probe; | 673 if (!probe->IsUndefined()) return probe; |
656 StubCompiler compiler; | 674 StubCompiler compiler; |
657 return FillCache(compiler.CompileCallInitialize(flags)); | 675 return FillCache(compiler.CompileCallInitialize(flags)); |
658 } | 676 } |
659 | 677 |
660 | 678 |
661 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) { | 679 Object* StubCache::ComputeCallPreMonomorphic(int argc, |
| 680 InLoopFlag in_loop, |
| 681 Code::Kind kind) { |
662 Code::Flags flags = | 682 Code::Flags flags = |
663 Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc); | 683 Code::ComputeFlags(kind, in_loop, PREMONOMORPHIC, NORMAL, argc); |
664 Object* probe = ProbeCache(flags); | 684 Object* probe = ProbeCache(flags); |
665 if (!probe->IsUndefined()) return probe; | 685 if (!probe->IsUndefined()) return probe; |
666 StubCompiler compiler; | 686 StubCompiler compiler; |
667 return FillCache(compiler.CompileCallPreMonomorphic(flags)); | 687 return FillCache(compiler.CompileCallPreMonomorphic(flags)); |
668 } | 688 } |
669 | 689 |
670 | 690 |
671 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) { | 691 Object* StubCache::ComputeCallNormal(int argc, |
| 692 InLoopFlag in_loop, |
| 693 Code::Kind kind) { |
672 Code::Flags flags = | 694 Code::Flags flags = |
673 Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc); | 695 Code::ComputeFlags(kind, in_loop, MONOMORPHIC, NORMAL, argc); |
674 Object* probe = ProbeCache(flags); | 696 Object* probe = ProbeCache(flags); |
675 if (!probe->IsUndefined()) return probe; | 697 if (!probe->IsUndefined()) return probe; |
676 StubCompiler compiler; | 698 StubCompiler compiler; |
677 return FillCache(compiler.CompileCallNormal(flags)); | 699 return FillCache(compiler.CompileCallNormal(flags)); |
678 } | 700 } |
679 | 701 |
680 | 702 |
681 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) { | 703 Object* StubCache::ComputeCallMegamorphic(int argc, |
| 704 InLoopFlag in_loop, |
| 705 Code::Kind kind) { |
682 Code::Flags flags = | 706 Code::Flags flags = |
683 Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc); | 707 Code::ComputeFlags(kind, in_loop, MEGAMORPHIC, NORMAL, argc); |
684 Object* probe = ProbeCache(flags); | 708 Object* probe = ProbeCache(flags); |
685 if (!probe->IsUndefined()) return probe; | 709 if (!probe->IsUndefined()) return probe; |
686 StubCompiler compiler; | 710 StubCompiler compiler; |
687 return FillCache(compiler.CompileCallMegamorphic(flags)); | 711 return FillCache(compiler.CompileCallMegamorphic(flags)); |
688 } | 712 } |
689 | 713 |
690 | 714 |
691 Object* StubCache::ComputeCallMiss(int argc) { | 715 Object* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { |
692 Code::Flags flags = | 716 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs |
693 Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc); | 717 // and monomorphic stubs are not mixed up together in the stub cache. |
| 718 Code::Flags flags = Code::ComputeFlags( |
| 719 kind, NOT_IN_LOOP, MONOMORPHIC_PROTOTYPE_FAILURE, NORMAL, argc); |
694 Object* probe = ProbeCache(flags); | 720 Object* probe = ProbeCache(flags); |
695 if (!probe->IsUndefined()) return probe; | 721 if (!probe->IsUndefined()) return probe; |
696 StubCompiler compiler; | 722 StubCompiler compiler; |
697 return FillCache(compiler.CompileCallMiss(flags)); | 723 return FillCache(compiler.CompileCallMiss(flags)); |
698 } | 724 } |
699 | 725 |
700 | 726 |
701 #ifdef ENABLE_DEBUGGER_SUPPORT | 727 #ifdef ENABLE_DEBUGGER_SUPPORT |
702 Object* StubCache::ComputeCallDebugBreak(int argc) { | 728 Object* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) { |
703 Code::Flags flags = | 729 Code::Flags flags = |
704 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); | 730 Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); |
705 Object* probe = ProbeCache(flags); | 731 Object* probe = ProbeCache(flags); |
706 if (!probe->IsUndefined()) return probe; | 732 if (!probe->IsUndefined()) return probe; |
707 StubCompiler compiler; | 733 StubCompiler compiler; |
708 return FillCache(compiler.CompileCallDebugBreak(flags)); | 734 return FillCache(compiler.CompileCallDebugBreak(flags)); |
709 } | 735 } |
710 | 736 |
711 | 737 |
712 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) { | 738 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { |
713 Code::Flags flags = | 739 Code::Flags flags = |
714 Code::ComputeFlags(Code::CALL_IC, | 740 Code::ComputeFlags(kind, |
715 NOT_IN_LOOP, | 741 NOT_IN_LOOP, |
716 DEBUG_PREPARE_STEP_IN, | 742 DEBUG_PREPARE_STEP_IN, |
717 NORMAL, | 743 NORMAL, |
718 argc); | 744 argc); |
719 Object* probe = ProbeCache(flags); | 745 Object* probe = ProbeCache(flags); |
720 if (!probe->IsUndefined()) return probe; | 746 if (!probe->IsUndefined()) return probe; |
721 StubCompiler compiler; | 747 StubCompiler compiler; |
722 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); | 748 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); |
723 } | 749 } |
724 #endif | 750 #endif |
(...skipping 26 matching lines...) Expand all Loading... |
751 secondary_[j].value = Builtins::builtin(Builtins::Illegal); | 777 secondary_[j].value = Builtins::builtin(Builtins::Illegal); |
752 } | 778 } |
753 } | 779 } |
754 | 780 |
755 | 781 |
756 // ------------------------------------------------------------------------ | 782 // ------------------------------------------------------------------------ |
757 // StubCompiler implementation. | 783 // StubCompiler implementation. |
758 | 784 |
759 | 785 |
760 // Support function for computing call IC miss stubs. | 786 // Support function for computing call IC miss stubs. |
761 Handle<Code> ComputeCallMiss(int argc) { | 787 Handle<Code> ComputeCallMiss(int argc, Code::Kind kind) { |
762 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code); | 788 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc, kind), Code); |
763 } | 789 } |
764 | 790 |
765 | 791 |
766 | 792 |
767 Object* LoadCallbackProperty(Arguments args) { | 793 Object* LoadCallbackProperty(Arguments args) { |
768 ASSERT(args[0]->IsJSObject()); | 794 ASSERT(args[0]->IsJSObject()); |
769 ASSERT(args[1]->IsJSObject()); | 795 ASSERT(args[1]->IsJSObject()); |
770 AccessorInfo* callback = AccessorInfo::cast(args[2]); | 796 AccessorInfo* callback = AccessorInfo::cast(args[2]); |
771 Address getter_address = v8::ToCData<Address>(callback->getter()); | 797 Address getter_address = v8::ToCData<Address>(callback->getter()); |
772 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); | 798 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { | 985 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { |
960 JSObject* receiver = JSObject::cast(args[0]); | 986 JSObject* receiver = JSObject::cast(args[0]); |
961 uint32_t index = Smi::cast(args[1])->value(); | 987 uint32_t index = Smi::cast(args[1])->value(); |
962 return receiver->GetElementWithInterceptor(receiver, index); | 988 return receiver->GetElementWithInterceptor(receiver, index); |
963 } | 989 } |
964 | 990 |
965 | 991 |
966 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { | 992 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { |
967 HandleScope scope; | 993 HandleScope scope; |
968 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 994 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
969 CallIC::GenerateInitialize(masm(), argc); | 995 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 996 if (kind == Code::CALL_IC) { |
| 997 CallIC::GenerateInitialize(masm(), argc); |
| 998 } else { |
| 999 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1000 } |
970 Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); | 1001 Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); |
971 if (!result->IsFailure()) { | 1002 if (!result->IsFailure()) { |
972 Counters::call_initialize_stubs.Increment(); | 1003 Counters::call_initialize_stubs.Increment(); |
973 Code* code = Code::cast(result); | 1004 Code* code = Code::cast(result); |
974 USE(code); | 1005 USE(code); |
975 PROFILE(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG, | 1006 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), |
976 code, code->arguments_count())); | 1007 code, code->arguments_count())); |
977 } | 1008 } |
978 return result; | 1009 return result; |
979 } | 1010 } |
980 | 1011 |
981 | 1012 |
982 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | 1013 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { |
983 HandleScope scope; | 1014 HandleScope scope; |
984 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1015 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
985 // The code of the PreMonomorphic stub is the same as the code | 1016 // The code of the PreMonomorphic stub is the same as the code |
986 // of the Initialized stub. They just differ on the code object flags. | 1017 // of the Initialized stub. They just differ on the code object flags. |
987 CallIC::GenerateInitialize(masm(), argc); | 1018 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1019 if (kind == Code::CALL_IC) { |
| 1020 CallIC::GenerateInitialize(masm(), argc); |
| 1021 } else { |
| 1022 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1023 } |
988 Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | 1024 Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); |
989 if (!result->IsFailure()) { | 1025 if (!result->IsFailure()) { |
990 Counters::call_premonomorphic_stubs.Increment(); | 1026 Counters::call_premonomorphic_stubs.Increment(); |
991 Code* code = Code::cast(result); | 1027 Code* code = Code::cast(result); |
992 USE(code); | 1028 USE(code); |
993 PROFILE(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG, | 1029 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), |
994 code, code->arguments_count())); | 1030 code, code->arguments_count())); |
995 } | 1031 } |
996 return result; | 1032 return result; |
997 } | 1033 } |
998 | 1034 |
999 | 1035 |
1000 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { | 1036 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { |
1001 HandleScope scope; | 1037 HandleScope scope; |
1002 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1038 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
1003 CallIC::GenerateNormal(masm(), argc); | 1039 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1040 if (kind == Code::CALL_IC) { |
| 1041 CallIC::GenerateNormal(masm(), argc); |
| 1042 } else { |
| 1043 KeyedCallIC::GenerateNormal(masm(), argc); |
| 1044 } |
1004 Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); | 1045 Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); |
1005 if (!result->IsFailure()) { | 1046 if (!result->IsFailure()) { |
1006 Counters::call_normal_stubs.Increment(); | 1047 Counters::call_normal_stubs.Increment(); |
1007 Code* code = Code::cast(result); | 1048 Code* code = Code::cast(result); |
1008 USE(code); | 1049 USE(code); |
1009 PROFILE(CodeCreateEvent(Logger::CALL_NORMAL_TAG, | 1050 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), |
1010 code, code->arguments_count())); | 1051 code, code->arguments_count())); |
1011 } | 1052 } |
1012 return result; | 1053 return result; |
1013 } | 1054 } |
1014 | 1055 |
1015 | 1056 |
1016 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | 1057 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { |
1017 HandleScope scope; | 1058 HandleScope scope; |
1018 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1059 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
1019 CallIC::GenerateMegamorphic(masm(), argc); | 1060 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1061 if (kind == Code::CALL_IC) { |
| 1062 CallIC::GenerateMegamorphic(masm(), argc); |
| 1063 } else { |
| 1064 KeyedCallIC::GenerateMegamorphic(masm(), argc); |
| 1065 } |
| 1066 |
1020 Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | 1067 Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); |
1021 if (!result->IsFailure()) { | 1068 if (!result->IsFailure()) { |
1022 Counters::call_megamorphic_stubs.Increment(); | 1069 Counters::call_megamorphic_stubs.Increment(); |
1023 Code* code = Code::cast(result); | 1070 Code* code = Code::cast(result); |
1024 USE(code); | 1071 USE(code); |
1025 PROFILE(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG, | 1072 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), |
1026 code, code->arguments_count())); | 1073 code, code->arguments_count())); |
1027 } | 1074 } |
1028 return result; | 1075 return result; |
1029 } | 1076 } |
1030 | 1077 |
1031 | 1078 |
1032 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { | 1079 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { |
1033 HandleScope scope; | 1080 HandleScope scope; |
1034 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1081 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
1035 CallIC::GenerateMiss(masm(), argc); | 1082 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1083 if (kind == Code::CALL_IC) { |
| 1084 CallIC::GenerateMiss(masm(), argc); |
| 1085 } else { |
| 1086 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1087 } |
1036 Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); | 1088 Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); |
1037 if (!result->IsFailure()) { | 1089 if (!result->IsFailure()) { |
1038 Counters::call_megamorphic_stubs.Increment(); | 1090 Counters::call_megamorphic_stubs.Increment(); |
1039 Code* code = Code::cast(result); | 1091 Code* code = Code::cast(result); |
1040 USE(code); | 1092 USE(code); |
1041 PROFILE(CodeCreateEvent(Logger::CALL_MISS_TAG, | 1093 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), |
1042 code, code->arguments_count())); | 1094 code, code->arguments_count())); |
1043 } | 1095 } |
1044 return result; | 1096 return result; |
1045 } | 1097 } |
1046 | 1098 |
1047 | 1099 |
1048 #ifdef ENABLE_DEBUGGER_SUPPORT | 1100 #ifdef ENABLE_DEBUGGER_SUPPORT |
1049 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 1101 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { |
1050 HandleScope scope; | 1102 HandleScope scope; |
1051 Debug::GenerateCallICDebugBreak(masm()); | 1103 Debug::GenerateCallICDebugBreak(masm()); |
1052 Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | 1104 Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); |
1053 if (!result->IsFailure()) { | 1105 if (!result->IsFailure()) { |
1054 Code* code = Code::cast(result); | 1106 Code* code = Code::cast(result); |
1055 USE(code); | 1107 USE(code); |
1056 PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG, | 1108 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1109 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), |
1057 code, code->arguments_count())); | 1110 code, code->arguments_count())); |
1058 } | 1111 } |
1059 return result; | 1112 return result; |
1060 } | 1113 } |
1061 | 1114 |
1062 | 1115 |
1063 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | 1116 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { |
1064 HandleScope scope; | 1117 HandleScope scope; |
1065 // Use the same code for the the step in preparations as we do for | 1118 // Use the same code for the the step in preparations as we do for |
1066 // the miss case. | 1119 // the miss case. |
1067 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1120 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
1068 CallIC::GenerateMiss(masm(), argc); | 1121 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1122 if (kind == Code::CALL_IC) { |
| 1123 CallIC::GenerateMiss(masm(), argc); |
| 1124 } else { |
| 1125 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1126 } |
1069 Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | 1127 Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); |
1070 if (!result->IsFailure()) { | 1128 if (!result->IsFailure()) { |
1071 Code* code = Code::cast(result); | 1129 Code* code = Code::cast(result); |
1072 USE(code); | 1130 USE(code); |
1073 PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG, | 1131 PROFILE(CodeCreateEvent( |
1074 code, code->arguments_count())); | 1132 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), |
| 1133 code, |
| 1134 code->arguments_count())); |
1075 } | 1135 } |
1076 return result; | 1136 return result; |
1077 } | 1137 } |
1078 #endif | 1138 #endif |
1079 | 1139 |
| 1140 #undef CALL_LOGGER_TAG |
1080 | 1141 |
1081 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { | 1142 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { |
1082 // Check for allocation failures during stub compilation. | 1143 // Check for allocation failures during stub compilation. |
1083 if (failure_->IsFailure()) return failure_; | 1144 if (failure_->IsFailure()) return failure_; |
1084 | 1145 |
1085 // Create code object in the heap. | 1146 // Create code object in the heap. |
1086 CodeDesc desc; | 1147 CodeDesc desc; |
1087 masm_.GetCode(&desc); | 1148 masm_.GetCode(&desc); |
1088 Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); | 1149 Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); |
1089 #ifdef ENABLE_DISASSEMBLER | 1150 #ifdef ENABLE_DISASSEMBLER |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1221 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
1161 #undef CALL_GENERATOR_CASE | 1222 #undef CALL_GENERATOR_CASE |
1162 } | 1223 } |
1163 UNREACHABLE(); | 1224 UNREACHABLE(); |
1164 return Heap::undefined_value(); | 1225 return Heap::undefined_value(); |
1165 } | 1226 } |
1166 | 1227 |
1167 | 1228 |
1168 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1229 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { |
1169 int argc = arguments_.immediate(); | 1230 int argc = arguments_.immediate(); |
1170 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 1231 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
1171 type, | 1232 type, |
1172 in_loop_, | 1233 in_loop_, |
1173 argc); | 1234 argc); |
1174 return GetCodeWithFlags(flags, name); | 1235 return GetCodeWithFlags(flags, name); |
1175 } | 1236 } |
1176 | 1237 |
1177 | 1238 |
1178 Object* CallStubCompiler::GetCode(JSFunction* function) { | 1239 Object* CallStubCompiler::GetCode(JSFunction* function) { |
1179 String* function_name = NULL; | 1240 String* function_name = NULL; |
1180 if (function->shared()->name()->IsString()) { | 1241 if (function->shared()->name()->IsString()) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 expected_receiver_type_ = | 1318 expected_receiver_type_ = |
1258 FunctionTemplateInfo::cast(signature->receiver()); | 1319 FunctionTemplateInfo::cast(signature->receiver()); |
1259 } | 1320 } |
1260 } | 1321 } |
1261 | 1322 |
1262 is_simple_api_call_ = true; | 1323 is_simple_api_call_ = true; |
1263 } | 1324 } |
1264 | 1325 |
1265 | 1326 |
1266 } } // namespace v8::internal | 1327 } } // namespace v8::internal |
OLD | NEW |