| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 case DEBUG_BREAK: break; | 54 case DEBUG_BREAK: break; |
| 55 case DEBUG_PREPARE_STEP_IN: break; | 55 case DEBUG_PREPARE_STEP_IN: break; |
| 56 } | 56 } |
| 57 UNREACHABLE(); | 57 UNREACHABLE(); |
| 58 return 0; | 58 return 0; |
| 59 } | 59 } |
| 60 | 60 |
| 61 void IC::TraceIC(const char* type, | 61 void IC::TraceIC(const char* type, |
| 62 Handle<Object> name, | 62 Handle<Object> name, |
| 63 State old_state, | 63 State old_state, |
| 64 Code* new_target, | 64 Code* new_target) { |
| 65 const char* extra_info) { | |
| 66 if (FLAG_trace_ic) { | 65 if (FLAG_trace_ic) { |
| 67 State new_state = StateFrom(new_target, | 66 State new_state = StateFrom(new_target, |
| 68 HEAP->undefined_value(), | 67 HEAP->undefined_value(), |
| 69 HEAP->undefined_value()); | 68 HEAP->undefined_value()); |
| 70 PrintF("[%s in ", type); | 69 PrintF("[%s in ", type); |
| 71 StackFrameIterator it; | 70 StackFrameIterator it; |
| 72 while (it.frame()->fp() != this->fp()) it.Advance(); | 71 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 73 StackFrame* raw_frame = it.frame(); | 72 StackFrame* raw_frame = it.frame(); |
| 74 if (raw_frame->is_internal()) { | 73 if (raw_frame->is_internal()) { |
| 75 Isolate* isolate = new_target->GetIsolate(); | 74 Isolate* isolate = new_target->GetIsolate(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 87 // Find the function on the stack and both the active code for the | 86 // Find the function on the stack and both the active code for the |
| 88 // function and the original code. | 87 // function and the original code. |
| 89 JSFunction* function = JSFunction::cast(frame->function()); | 88 JSFunction* function = JSFunction::cast(frame->function()); |
| 90 function->PrintName(); | 89 function->PrintName(); |
| 91 int code_offset = | 90 int code_offset = |
| 92 static_cast<int>(address() - js_code->instruction_start()); | 91 static_cast<int>(address() - js_code->instruction_start()); |
| 93 PrintF("+%d", code_offset); | 92 PrintF("+%d", code_offset); |
| 94 } else { | 93 } else { |
| 95 PrintF("<unknown>"); | 94 PrintF("<unknown>"); |
| 96 } | 95 } |
| 97 PrintF(" (%c->%c)%s", | 96 PrintF(" (%c->%c)", |
| 98 TransitionMarkFromState(old_state), | 97 TransitionMarkFromState(old_state), |
| 99 TransitionMarkFromState(new_state), | 98 TransitionMarkFromState(new_state)); |
| 100 extra_info); | |
| 101 name->Print(); | 99 name->Print(); |
| 102 PrintF("]\n"); | 100 PrintF("]\n"); |
| 103 } | 101 } |
| 104 } | 102 } |
| 105 #endif | 103 #endif |
| 106 | 104 |
| 107 | 105 |
| 108 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 106 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 109 ASSERT(isolate == Isolate::Current()); | 107 ASSERT(isolate == Isolate::Current()); |
| 110 // To improve the performance of the (much used) IC code, we unfold | 108 // To improve the performance of the (much used) IC code, we unfold |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 } | 317 } |
| 320 | 318 |
| 321 | 319 |
| 322 void CallICBase::Clear(Address address, Code* target) { | 320 void CallICBase::Clear(Address address, Code* target) { |
| 323 bool contextual = CallICBase::Contextual::decode(target->extra_ic_state()); | 321 bool contextual = CallICBase::Contextual::decode(target->extra_ic_state()); |
| 324 State state = target->ic_state(); | 322 State state = target->ic_state(); |
| 325 if (state == UNINITIALIZED) return; | 323 if (state == UNINITIALIZED) return; |
| 326 Code* code = | 324 Code* code = |
| 327 Isolate::Current()->stub_cache()->FindCallInitialize( | 325 Isolate::Current()->stub_cache()->FindCallInitialize( |
| 328 target->arguments_count(), | 326 target->arguments_count(), |
| 329 target->ic_in_loop(), | |
| 330 contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET, | 327 contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET, |
| 331 target->kind()); | 328 target->kind()); |
| 332 SetTargetAtAddress(address, code); | 329 SetTargetAtAddress(address, code); |
| 333 } | 330 } |
| 334 | 331 |
| 335 | 332 |
| 336 void KeyedLoadIC::Clear(Address address, Code* target) { | 333 void KeyedLoadIC::Clear(Address address, Code* target) { |
| 337 if (target->ic_state() == UNINITIALIZED) return; | 334 if (target->ic_state() == UNINITIALIZED) return; |
| 338 // Make sure to also clear the map used in inline fast cases. If we | 335 // Make sure to also clear the map used in inline fast cases. If we |
| 339 // do not clear these maps, cached code can keep objects alive | 336 // do not clear these maps, cached code can keep objects alive |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 } | 594 } |
| 598 | 595 |
| 599 | 596 |
| 600 MaybeObject* CallICBase::ComputeMonomorphicStub( | 597 MaybeObject* CallICBase::ComputeMonomorphicStub( |
| 601 LookupResult* lookup, | 598 LookupResult* lookup, |
| 602 State state, | 599 State state, |
| 603 Code::ExtraICState extra_ic_state, | 600 Code::ExtraICState extra_ic_state, |
| 604 Handle<Object> object, | 601 Handle<Object> object, |
| 605 Handle<String> name) { | 602 Handle<String> name) { |
| 606 int argc = target()->arguments_count(); | 603 int argc = target()->arguments_count(); |
| 607 InLoopFlag in_loop = target()->ic_in_loop(); | |
| 608 MaybeObject* maybe_code = NULL; | 604 MaybeObject* maybe_code = NULL; |
| 609 switch (lookup->type()) { | 605 switch (lookup->type()) { |
| 610 case FIELD: { | 606 case FIELD: { |
| 611 int index = lookup->GetFieldIndex(); | 607 int index = lookup->GetFieldIndex(); |
| 612 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 608 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, |
| 613 in_loop, | |
| 614 kind_, | 609 kind_, |
| 615 extra_ic_state, | 610 extra_ic_state, |
| 616 *name, | 611 *name, |
| 617 *object, | 612 *object, |
| 618 lookup->holder(), | 613 lookup->holder(), |
| 619 index); | 614 index); |
| 620 break; | 615 break; |
| 621 } | 616 } |
| 622 case CONSTANT_FUNCTION: { | 617 case CONSTANT_FUNCTION: { |
| 623 // Get the constant function and compute the code stub for this | 618 // Get the constant function and compute the code stub for this |
| 624 // call; used for rewriting to monomorphic state and making sure | 619 // call; used for rewriting to monomorphic state and making sure |
| 625 // that the code stub is in the stub cache. | 620 // that the code stub is in the stub cache. |
| 626 JSFunction* function = lookup->GetConstantFunction(); | 621 JSFunction* function = lookup->GetConstantFunction(); |
| 627 maybe_code = | 622 maybe_code = |
| 628 isolate()->stub_cache()->ComputeCallConstant(argc, | 623 isolate()->stub_cache()->ComputeCallConstant(argc, |
| 629 in_loop, | |
| 630 kind_, | 624 kind_, |
| 631 extra_ic_state, | 625 extra_ic_state, |
| 632 *name, | 626 *name, |
| 633 *object, | 627 *object, |
| 634 lookup->holder(), | 628 lookup->holder(), |
| 635 function); | 629 function); |
| 636 break; | 630 break; |
| 637 } | 631 } |
| 638 case NORMAL: { | 632 case NORMAL: { |
| 639 if (!object->IsJSObject()) return NULL; | 633 if (!object->IsJSObject()) return NULL; |
| 640 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 634 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 641 | 635 |
| 642 if (lookup->holder()->IsGlobalObject()) { | 636 if (lookup->holder()->IsGlobalObject()) { |
| 643 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 637 GlobalObject* global = GlobalObject::cast(lookup->holder()); |
| 644 JSGlobalPropertyCell* cell = | 638 JSGlobalPropertyCell* cell = |
| 645 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 639 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
| 646 if (!cell->value()->IsJSFunction()) return NULL; | 640 if (!cell->value()->IsJSFunction()) return NULL; |
| 647 JSFunction* function = JSFunction::cast(cell->value()); | 641 JSFunction* function = JSFunction::cast(cell->value()); |
| 648 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 642 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, |
| 649 in_loop, | |
| 650 kind_, | 643 kind_, |
| 651 extra_ic_state, | 644 extra_ic_state, |
| 652 *name, | 645 *name, |
| 653 *receiver, | 646 *receiver, |
| 654 global, | 647 global, |
| 655 cell, | 648 cell, |
| 656 function); | 649 function); |
| 657 } else { | 650 } else { |
| 658 // There is only one shared stub for calling normalized | 651 // There is only one shared stub for calling normalized |
| 659 // properties. It does not traverse the prototype chain, so the | 652 // properties. It does not traverse the prototype chain, so the |
| 660 // property must be found in the receiver for the stub to be | 653 // property must be found in the receiver for the stub to be |
| 661 // applicable. | 654 // applicable. |
| 662 if (lookup->holder() != *receiver) return NULL; | 655 if (lookup->holder() != *receiver) return NULL; |
| 663 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 656 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, |
| 664 in_loop, | |
| 665 kind_, | 657 kind_, |
| 666 extra_ic_state, | 658 extra_ic_state, |
| 667 *name, | 659 *name, |
| 668 *receiver); | 660 *receiver); |
| 669 } | 661 } |
| 670 break; | 662 break; |
| 671 } | 663 } |
| 672 case INTERCEPTOR: { | 664 case INTERCEPTOR: { |
| 673 ASSERT(HasInterceptorGetter(lookup->holder())); | 665 ASSERT(HasInterceptorGetter(lookup->holder())); |
| 674 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 666 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 699 if (lookup->holder() != *object && | 691 if (lookup->holder() != *object && |
| 700 HasNormalObjectsInPrototypeChain( | 692 HasNormalObjectsInPrototypeChain( |
| 701 isolate(), lookup, object->GetPrototype())) { | 693 isolate(), lookup, object->GetPrototype())) { |
| 702 // Suppress optimization for prototype chains with slow properties objects | 694 // Suppress optimization for prototype chains with slow properties objects |
| 703 // in the middle. | 695 // in the middle. |
| 704 return; | 696 return; |
| 705 } | 697 } |
| 706 | 698 |
| 707 // Compute the number of arguments. | 699 // Compute the number of arguments. |
| 708 int argc = target()->arguments_count(); | 700 int argc = target()->arguments_count(); |
| 709 InLoopFlag in_loop = target()->ic_in_loop(); | |
| 710 MaybeObject* maybe_code = NULL; | 701 MaybeObject* maybe_code = NULL; |
| 711 bool had_proto_failure = false; | 702 bool had_proto_failure = false; |
| 712 if (state == UNINITIALIZED) { | 703 if (state == UNINITIALIZED) { |
| 713 // This is the first time we execute this inline cache. | 704 // This is the first time we execute this inline cache. |
| 714 // Set the target to the pre monomorphic stub to delay | 705 // Set the target to the pre monomorphic stub to delay |
| 715 // setting the monomorphic state. | 706 // setting the monomorphic state. |
| 716 maybe_code = | 707 maybe_code = |
| 717 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 708 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, |
| 718 in_loop, | |
| 719 kind_, | 709 kind_, |
| 720 extra_ic_state); | 710 extra_ic_state); |
| 721 } else if (state == MONOMORPHIC) { | 711 } else if (state == MONOMORPHIC) { |
| 722 if (kind_ == Code::CALL_IC && | 712 if (kind_ == Code::CALL_IC && |
| 723 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 713 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
| 724 maybe_code = ComputeMonomorphicStub(lookup, | 714 maybe_code = ComputeMonomorphicStub(lookup, |
| 725 state, | 715 state, |
| 726 extra_ic_state, | 716 extra_ic_state, |
| 727 object, | 717 object, |
| 728 name); | 718 name); |
| 729 } else if (kind_ == Code::CALL_IC && | 719 } else if (kind_ == Code::CALL_IC && |
| 730 TryRemoveInvalidPrototypeDependentStub(target(), | 720 TryRemoveInvalidPrototypeDependentStub(target(), |
| 731 *object, | 721 *object, |
| 732 *name)) { | 722 *name)) { |
| 733 had_proto_failure = true; | 723 had_proto_failure = true; |
| 734 maybe_code = ComputeMonomorphicStub(lookup, | 724 maybe_code = ComputeMonomorphicStub(lookup, |
| 735 state, | 725 state, |
| 736 extra_ic_state, | 726 extra_ic_state, |
| 737 object, | 727 object, |
| 738 name); | 728 name); |
| 739 } else { | 729 } else { |
| 740 maybe_code = | 730 maybe_code = |
| 741 isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 731 isolate()->stub_cache()->ComputeCallMegamorphic(argc, |
| 742 in_loop, | |
| 743 kind_, | 732 kind_, |
| 744 extra_ic_state); | 733 extra_ic_state); |
| 745 } | 734 } |
| 746 } else { | 735 } else { |
| 747 maybe_code = ComputeMonomorphicStub(lookup, | 736 maybe_code = ComputeMonomorphicStub(lookup, |
| 748 state, | 737 state, |
| 749 extra_ic_state, | 738 extra_ic_state, |
| 750 object, | 739 object, |
| 751 name); | 740 name); |
| 752 } | 741 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 769 object->GetPrototype())->map(); | 758 object->GetPrototype())->map(); |
| 770 | 759 |
| 771 // Update the stub cache. | 760 // Update the stub cache. |
| 772 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 761 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); |
| 773 } | 762 } |
| 774 | 763 |
| 775 USE(had_proto_failure); | 764 USE(had_proto_failure); |
| 776 #ifdef DEBUG | 765 #ifdef DEBUG |
| 777 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 766 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
| 778 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 767 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
| 779 name, state, target(), in_loop ? " (in-loop)" : ""); | 768 name, state, target()); |
| 780 #endif | 769 #endif |
| 781 } | 770 } |
| 782 | 771 |
| 783 | 772 |
| 784 MaybeObject* KeyedCallIC::LoadFunction(State state, | 773 MaybeObject* KeyedCallIC::LoadFunction(State state, |
| 785 Handle<Object> object, | 774 Handle<Object> object, |
| 786 Handle<Object> key) { | 775 Handle<Object> key) { |
| 787 if (key->IsSymbol()) { | 776 if (key->IsSymbol()) { |
| 788 return CallICBase::LoadFunction(state, | 777 return CallICBase::LoadFunction(state, |
| 789 Code::kNoExtraICState, | 778 Code::kNoExtraICState, |
| 790 object, | 779 object, |
| 791 Handle<String>::cast(key)); | 780 Handle<String>::cast(key)); |
| 792 } | 781 } |
| 793 | 782 |
| 794 if (object->IsUndefined() || object->IsNull()) { | 783 if (object->IsUndefined() || object->IsNull()) { |
| 795 return TypeError("non_object_property_call", object, key); | 784 return TypeError("non_object_property_call", object, key); |
| 796 } | 785 } |
| 797 | 786 |
| 798 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 787 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { |
| 799 int argc = target()->arguments_count(); | 788 int argc = target()->arguments_count(); |
| 800 InLoopFlag in_loop = target()->ic_in_loop(); | |
| 801 Heap* heap = Handle<HeapObject>::cast(object)->GetHeap(); | 789 Heap* heap = Handle<HeapObject>::cast(object)->GetHeap(); |
| 802 Map* map = heap->non_strict_arguments_elements_map(); | 790 Map* map = heap->non_strict_arguments_elements_map(); |
| 803 if (object->IsJSObject() && | 791 if (object->IsJSObject() && |
| 804 Handle<JSObject>::cast(object)->elements()->map() == map) { | 792 Handle<JSObject>::cast(object)->elements()->map() == map) { |
| 805 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( | 793 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( |
| 806 argc, in_loop, Code::KEYED_CALL_IC); | 794 argc, Code::KEYED_CALL_IC); |
| 807 Object* code; | 795 Object* code; |
| 808 if (maybe_code->ToObject(&code)) { | 796 if (maybe_code->ToObject(&code)) { |
| 809 set_target(Code::cast(code)); | 797 set_target(Code::cast(code)); |
| 810 #ifdef DEBUG | 798 #ifdef DEBUG |
| 811 TraceIC( | 799 TraceIC("KeyedCallIC", key, state, target()); |
| 812 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | |
| 813 #endif | 800 #endif |
| 814 } | 801 } |
| 815 } else if (FLAG_use_ic && state != MEGAMORPHIC && | 802 } else if (FLAG_use_ic && state != MEGAMORPHIC && |
| 816 !object->IsAccessCheckNeeded()) { | 803 !object->IsAccessCheckNeeded()) { |
| 817 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 804 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 818 argc, in_loop, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 805 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 819 Object* code; | 806 Object* code; |
| 820 if (maybe_code->ToObject(&code)) { | 807 if (maybe_code->ToObject(&code)) { |
| 821 set_target(Code::cast(code)); | 808 set_target(Code::cast(code)); |
| 822 #ifdef DEBUG | 809 #ifdef DEBUG |
| 823 TraceIC( | 810 TraceIC("KeyedCallIC", key, state, target()); |
| 824 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | |
| 825 #endif | 811 #endif |
| 826 } | 812 } |
| 827 } | 813 } |
| 828 } | 814 } |
| 829 | 815 |
| 830 HandleScope scope(isolate()); | 816 HandleScope scope(isolate()); |
| 831 Handle<Object> result = GetProperty(object, key); | 817 Handle<Object> result = GetProperty(object, key); |
| 832 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 818 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 833 | 819 |
| 834 // Make receiver an object if the callee requires it. Strict mode or builtin | 820 // Make receiver an object if the callee requires it. Strict mode or builtin |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 } | 1629 } |
| 1644 | 1630 |
| 1645 // If the maximum number of receiver maps has been exceeded, use the generic | 1631 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1646 // version of the IC. | 1632 // version of the IC. |
| 1647 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1633 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1648 return generic_stub; | 1634 return generic_stub; |
| 1649 } | 1635 } |
| 1650 | 1636 |
| 1651 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); | 1637 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); |
| 1652 Code::Flags flags = Code::ComputeFlags(this->kind(), | 1638 Code::Flags flags = Code::ComputeFlags(this->kind(), |
| 1653 NOT_IN_LOOP, | |
| 1654 MEGAMORPHIC, | 1639 MEGAMORPHIC, |
| 1655 strict_mode); | 1640 strict_mode); |
| 1656 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); | 1641 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); |
| 1657 // If there is a cached stub, use it. | 1642 // If there is a cached stub, use it. |
| 1658 if (!maybe_cached_stub->IsUndefined()) { | 1643 if (!maybe_cached_stub->IsUndefined()) { |
| 1659 ASSERT(maybe_cached_stub->IsCode()); | 1644 ASSERT(maybe_cached_stub->IsCode()); |
| 1660 return Code::cast(maybe_cached_stub); | 1645 return Code::cast(maybe_cached_stub); |
| 1661 } | 1646 } |
| 1662 // Collect MONOMORPHIC stubs for all target_receiver_maps. | 1647 // Collect MONOMORPHIC stubs for all target_receiver_maps. |
| 1663 CodeList handler_ics(target_receiver_maps.length()); | 1648 CodeList handler_ics(target_receiver_maps.length()); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1898 TraceIC("KeyedStoreIC", name, state, target()); | 1883 TraceIC("KeyedStoreIC", name, state, target()); |
| 1899 #endif | 1884 #endif |
| 1900 } | 1885 } |
| 1901 | 1886 |
| 1902 | 1887 |
| 1903 // ---------------------------------------------------------------------------- | 1888 // ---------------------------------------------------------------------------- |
| 1904 // Static IC stub generators. | 1889 // Static IC stub generators. |
| 1905 // | 1890 // |
| 1906 | 1891 |
| 1907 static JSFunction* CompileFunction(Isolate* isolate, | 1892 static JSFunction* CompileFunction(Isolate* isolate, |
| 1908 JSFunction* function, | 1893 JSFunction* function) { |
| 1909 InLoopFlag in_loop) { | |
| 1910 // Compile now with optimization. | 1894 // Compile now with optimization. |
| 1911 HandleScope scope(isolate); | 1895 HandleScope scope(isolate); |
| 1912 Handle<JSFunction> function_handle(function, isolate); | 1896 Handle<JSFunction> function_handle(function, isolate); |
| 1913 if (in_loop == IN_LOOP) { | 1897 CompileLazy(function_handle, CLEAR_EXCEPTION); |
| 1914 CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); | |
| 1915 } else { | |
| 1916 CompileLazy(function_handle, CLEAR_EXCEPTION); | |
| 1917 } | |
| 1918 return *function_handle; | 1898 return *function_handle; |
| 1919 } | 1899 } |
| 1920 | 1900 |
| 1921 | 1901 |
| 1922 // Used from ic-<arch>.cc. | 1902 // Used from ic-<arch>.cc. |
| 1923 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 1903 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
| 1924 NoHandleAllocation na; | 1904 NoHandleAllocation na; |
| 1925 ASSERT(args.length() == 2); | 1905 ASSERT(args.length() == 2); |
| 1926 CallIC ic(isolate); | 1906 CallIC ic(isolate); |
| 1927 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1907 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1928 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1908 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 1929 MaybeObject* maybe_result = ic.LoadFunction(state, | 1909 MaybeObject* maybe_result = ic.LoadFunction(state, |
| 1930 extra_ic_state, | 1910 extra_ic_state, |
| 1931 args.at<Object>(0), | 1911 args.at<Object>(0), |
| 1932 args.at<String>(1)); | 1912 args.at<String>(1)); |
| 1933 Object* result; | 1913 Object* result; |
| 1934 if (!maybe_result->ToObject(&result)) return maybe_result; | 1914 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1935 | 1915 |
| 1936 // The first time the inline cache is updated may be the first time the | 1916 // The first time the inline cache is updated may be the first time the |
| 1937 // function it references gets called. If the function was lazily compiled | 1917 // function it references gets called. If the function was lazily compiled |
| 1938 // then the first call will trigger a compilation. We check for this case | 1918 // then the first call will trigger a compilation. We check for this case |
| 1939 // and we do the compilation immediately, instead of waiting for the stub | 1919 // and we do the compilation immediately, instead of waiting for the stub |
| 1940 // currently attached to the JSFunction object to trigger compilation. We | 1920 // currently attached to the JSFunction object to trigger compilation. We |
| 1941 // do this in the case where we know that the inline cache is inside a loop, | 1921 // do this in the case where we know that the inline cache is inside a loop, |
| 1942 // because then we know that we want to optimize the function. | 1922 // because then we know that we want to optimize the function. |
| 1943 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1923 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
| 1944 return result; | 1924 return result; |
| 1945 } | 1925 } |
| 1946 return CompileFunction(isolate, | 1926 return CompileFunction(isolate, JSFunction::cast(result)); |
| 1947 JSFunction::cast(result), | |
| 1948 ic.target()->ic_in_loop()); | |
| 1949 } | 1927 } |
| 1950 | 1928 |
| 1951 | 1929 |
| 1952 // Used from ic-<arch>.cc. | 1930 // Used from ic-<arch>.cc. |
| 1953 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | 1931 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { |
| 1954 NoHandleAllocation na; | 1932 NoHandleAllocation na; |
| 1955 ASSERT(args.length() == 2); | 1933 ASSERT(args.length() == 2); |
| 1956 KeyedCallIC ic(isolate); | 1934 KeyedCallIC ic(isolate); |
| 1957 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1935 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1958 Object* result; | 1936 Object* result; |
| 1959 { MaybeObject* maybe_result = | 1937 { MaybeObject* maybe_result = |
| 1960 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 1938 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
| 1961 if (!maybe_result->ToObject(&result)) return maybe_result; | 1939 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1962 } | 1940 } |
| 1963 | 1941 |
| 1964 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1942 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
| 1965 return result; | 1943 return result; |
| 1966 } | 1944 } |
| 1967 return CompileFunction(isolate, | 1945 return CompileFunction(isolate, JSFunction::cast(result)); |
| 1968 JSFunction::cast(result), | |
| 1969 ic.target()->ic_in_loop()); | |
| 1970 } | 1946 } |
| 1971 | 1947 |
| 1972 | 1948 |
| 1973 // Used from ic-<arch>.cc. | 1949 // Used from ic-<arch>.cc. |
| 1974 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1950 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
| 1975 NoHandleAllocation na; | 1951 NoHandleAllocation na; |
| 1976 ASSERT(args.length() == 2); | 1952 ASSERT(args.length() == 2); |
| 1977 LoadIC ic(isolate); | 1953 LoadIC ic(isolate); |
| 1978 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1954 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1979 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1955 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 #undef ADDR | 2508 #undef ADDR |
| 2533 }; | 2509 }; |
| 2534 | 2510 |
| 2535 | 2511 |
| 2536 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2512 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2537 return IC_utilities[id]; | 2513 return IC_utilities[id]; |
| 2538 } | 2514 } |
| 2539 | 2515 |
| 2540 | 2516 |
| 2541 } } // namespace v8::internal | 2517 } } // namespace v8::internal |
| OLD | NEW |