OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 | 581 |
582 if (FLAG_use_ic) { | 582 if (FLAG_use_ic) { |
583 // Use specialized code for getting prototype of functions. | 583 // Use specialized code for getting prototype of functions. |
584 if (object->IsJSFunction() && | 584 if (object->IsJSFunction() && |
585 String::Equals(isolate()->factory()->prototype_string(), name) && | 585 String::Equals(isolate()->factory()->prototype_string(), name) && |
586 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 586 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
587 Handle<Code> stub; | 587 Handle<Code> stub; |
588 if (state() == UNINITIALIZED) { | 588 if (state() == UNINITIALIZED) { |
589 stub = pre_monomorphic_stub(); | 589 stub = pre_monomorphic_stub(); |
590 } else if (state() == PREMONOMORPHIC) { | 590 } else if (state() == PREMONOMORPHIC) { |
591 FunctionPrototypeStub function_prototype_stub(kind()); | 591 FunctionPrototypeStub function_prototype_stub(isolate(), kind()); |
592 stub = function_prototype_stub.GetCode(isolate()); | 592 stub = function_prototype_stub.GetCode(isolate()); |
593 } else if (state() != MEGAMORPHIC) { | 593 } else if (state() != MEGAMORPHIC) { |
594 ASSERT(state() != GENERIC); | 594 ASSERT(state() != GENERIC); |
595 stub = megamorphic_stub(); | 595 stub = megamorphic_stub(); |
596 } | 596 } |
597 if (!stub.is_null()) { | 597 if (!stub.is_null()) { |
598 set_target(*stub); | 598 set_target(*stub); |
599 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 599 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
600 } | 600 } |
601 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 601 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 | 844 |
845 Handle<Code> LoadIC::megamorphic_stub() { | 845 Handle<Code> LoadIC::megamorphic_stub() { |
846 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); | 846 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); |
847 } | 847 } |
848 | 848 |
849 | 849 |
850 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 850 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
851 bool inobject, | 851 bool inobject, |
852 Representation representation) { | 852 Representation representation) { |
853 if (kind() == Code::LOAD_IC) { | 853 if (kind() == Code::LOAD_IC) { |
854 LoadFieldStub stub(inobject, offset, representation); | 854 LoadFieldStub stub(isolate(), inobject, offset, representation); |
855 return stub.GetCode(isolate()); | 855 return stub.GetCode(isolate()); |
856 } else { | 856 } else { |
857 KeyedLoadFieldStub stub(inobject, offset, representation); | 857 KeyedLoadFieldStub stub(isolate(), inobject, offset, representation); |
858 return stub.GetCode(isolate()); | 858 return stub.GetCode(isolate()); |
859 } | 859 } |
860 } | 860 } |
861 | 861 |
862 | 862 |
863 void LoadIC::UpdateCaches(LookupResult* lookup, | 863 void LoadIC::UpdateCaches(LookupResult* lookup, |
864 Handle<Object> object, | 864 Handle<Object> object, |
865 Handle<String> name) { | 865 Handle<String> name) { |
866 if (state() == UNINITIALIZED) { | 866 if (state() == UNINITIALIZED) { |
867 // This is the first time we execute this inline cache. | 867 // This is the first time we execute this inline cache. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 InlineCacheHolderFlag cache_holder) { | 933 InlineCacheHolderFlag cache_holder) { |
934 if (object->IsString() && | 934 if (object->IsString() && |
935 String::Equals(isolate()->factory()->length_string(), name)) { | 935 String::Equals(isolate()->factory()->length_string(), name)) { |
936 int length_index = String::kLengthOffset / kPointerSize; | 936 int length_index = String::kLengthOffset / kPointerSize; |
937 return SimpleFieldLoad(length_index); | 937 return SimpleFieldLoad(length_index); |
938 } | 938 } |
939 | 939 |
940 if (object->IsStringWrapper() && | 940 if (object->IsStringWrapper() && |
941 String::Equals(isolate()->factory()->length_string(), name)) { | 941 String::Equals(isolate()->factory()->length_string(), name)) { |
942 if (kind() == Code::LOAD_IC) { | 942 if (kind() == Code::LOAD_IC) { |
943 StringLengthStub string_length_stub; | 943 StringLengthStub string_length_stub(isolate()); |
944 return string_length_stub.GetCode(isolate()); | 944 return string_length_stub.GetCode(isolate()); |
945 } else { | 945 } else { |
946 KeyedStringLengthStub string_length_stub; | 946 KeyedStringLengthStub string_length_stub(isolate()); |
947 return string_length_stub.GetCode(isolate()); | 947 return string_length_stub.GetCode(isolate()); |
948 } | 948 } |
949 } | 949 } |
950 | 950 |
951 Handle<HeapType> type = CurrentTypeOf(object, isolate()); | 951 Handle<HeapType> type = CurrentTypeOf(object, isolate()); |
952 Handle<JSObject> holder(lookup->holder()); | 952 Handle<JSObject> holder(lookup->holder()); |
953 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); | 953 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); |
954 | 954 |
955 switch (lookup->type()) { | 955 switch (lookup->type()) { |
956 case FIELD: { | 956 case FIELD: { |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { | 1417 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { |
1418 // The stub generated for the global object picks the value directly | 1418 // The stub generated for the global object picks the value directly |
1419 // from the property cell. So the property must be directly on the | 1419 // from the property cell. So the property must be directly on the |
1420 // global object. | 1420 // global object. |
1421 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() | 1421 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() |
1422 ? handle(GlobalObject::cast(receiver->GetPrototype())) | 1422 ? handle(GlobalObject::cast(receiver->GetPrototype())) |
1423 : Handle<GlobalObject>::cast(receiver); | 1423 : Handle<GlobalObject>::cast(receiver); |
1424 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1424 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
1425 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1425 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
1426 StoreGlobalStub stub( | 1426 StoreGlobalStub stub( |
1427 union_type->IsConstant(), receiver->IsJSGlobalProxy()); | 1427 isolate(), union_type->IsConstant(), receiver->IsJSGlobalProxy()); |
1428 Handle<Code> code = stub.GetCodeCopyFromTemplate( | 1428 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
1429 isolate(), global, cell); | 1429 isolate(), global, cell); |
1430 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1430 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1431 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1431 HeapObject::UpdateMapCodeCache(receiver, name, code); |
1432 return code; | 1432 return code; |
1433 } | 1433 } |
1434 ASSERT(holder.is_identical_to(receiver)); | 1434 ASSERT(holder.is_identical_to(receiver)); |
1435 return isolate()->builtins()->StoreIC_Normal(); | 1435 return isolate()->builtins()->StoreIC_Normal(); |
1436 case CALLBACKS: { | 1436 case CALLBACKS: { |
1437 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1437 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2505 | 2505 |
2506 // Check if we have a string operation here. | 2506 // Check if we have a string operation here. |
2507 Handle<Code> target; | 2507 Handle<Code> target; |
2508 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) { | 2508 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) { |
2509 // Setup the allocation site on-demand. | 2509 // Setup the allocation site on-demand. |
2510 if (allocation_site.is_null()) { | 2510 if (allocation_site.is_null()) { |
2511 allocation_site = isolate()->factory()->NewAllocationSite(); | 2511 allocation_site = isolate()->factory()->NewAllocationSite(); |
2512 } | 2512 } |
2513 | 2513 |
2514 // Install the stub with an allocation site. | 2514 // Install the stub with an allocation site. |
2515 BinaryOpICWithAllocationSiteStub stub(state); | 2515 BinaryOpICWithAllocationSiteStub stub(isolate(), state); |
2516 target = stub.GetCodeCopyFromTemplate(isolate(), allocation_site); | 2516 target = stub.GetCodeCopyFromTemplate(isolate(), allocation_site); |
2517 | 2517 |
2518 // Sanity check the trampoline stub. | 2518 // Sanity check the trampoline stub. |
2519 ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite()); | 2519 ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite()); |
2520 } else { | 2520 } else { |
2521 // Install the generic stub. | 2521 // Install the generic stub. |
2522 BinaryOpICStub stub(state); | 2522 BinaryOpICStub stub(isolate(), state); |
2523 target = stub.GetCode(isolate()); | 2523 target = stub.GetCode(isolate()); |
2524 | 2524 |
2525 // Sanity check the generic stub. | 2525 // Sanity check the generic stub. |
2526 ASSERT_EQ(NULL, target->FindFirstAllocationSite()); | 2526 ASSERT_EQ(NULL, target->FindFirstAllocationSite()); |
2527 } | 2527 } |
2528 set_target(*target); | 2528 set_target(*target); |
2529 | 2529 |
2530 if (FLAG_trace_ic) { | 2530 if (FLAG_trace_ic) { |
2531 char buffer[150]; | 2531 char buffer[150]; |
2532 NoAllocationStringAllocator allocator( | 2532 NoAllocationStringAllocator allocator( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2584 Handle<Object> result; | 2584 Handle<Object> result; |
2585 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2585 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2586 isolate, | 2586 isolate, |
2587 result, | 2587 result, |
2588 ic.Transition(allocation_site, left, right)); | 2588 ic.Transition(allocation_site, left, right)); |
2589 return *result; | 2589 return *result; |
2590 } | 2590 } |
2591 | 2591 |
2592 | 2592 |
2593 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { | 2593 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { |
2594 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2594 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2595 Code* code = NULL; | 2595 Code* code = NULL; |
2596 CHECK(stub.FindCodeInCache(&code, isolate)); | 2596 CHECK(stub.FindCodeInCache(&code, isolate)); |
2597 return code; | 2597 return code; |
2598 } | 2598 } |
2599 | 2599 |
2600 | 2600 |
2601 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { | 2601 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { |
2602 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2602 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2603 return stub.GetCode(isolate); | 2603 return stub.GetCode(isolate); |
2604 } | 2604 } |
2605 | 2605 |
2606 | 2606 |
2607 const char* CompareIC::GetStateName(State state) { | 2607 const char* CompareIC::GetStateName(State state) { |
2608 switch (state) { | 2608 switch (state) { |
2609 case UNINITIALIZED: return "UNINITIALIZED"; | 2609 case UNINITIALIZED: return "UNINITIALIZED"; |
2610 case SMI: return "SMI"; | 2610 case SMI: return "SMI"; |
2611 case NUMBER: return "NUMBER"; | 2611 case NUMBER: return "NUMBER"; |
2612 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; | 2612 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2765 | 2765 |
2766 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2766 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
2767 HandleScope scope(isolate()); | 2767 HandleScope scope(isolate()); |
2768 State previous_left, previous_right, previous_state; | 2768 State previous_left, previous_right, previous_state; |
2769 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2769 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
2770 &previous_right, &previous_state, NULL); | 2770 &previous_right, &previous_state, NULL); |
2771 State new_left = NewInputState(previous_left, x); | 2771 State new_left = NewInputState(previous_left, x); |
2772 State new_right = NewInputState(previous_right, y); | 2772 State new_right = NewInputState(previous_right, y); |
2773 State state = TargetState(previous_state, previous_left, previous_right, | 2773 State state = TargetState(previous_state, previous_left, previous_right, |
2774 HasInlinedSmiCode(address()), x, y); | 2774 HasInlinedSmiCode(address()), x, y); |
2775 ICCompareStub stub(op_, new_left, new_right, state); | 2775 ICCompareStub stub(isolate(), op_, new_left, new_right, state); |
2776 if (state == KNOWN_OBJECT) { | 2776 if (state == KNOWN_OBJECT) { |
2777 stub.set_known_map( | 2777 stub.set_known_map( |
2778 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); | 2778 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); |
2779 } | 2779 } |
2780 Handle<Code> new_target = stub.GetCode(isolate()); | 2780 Handle<Code> new_target = stub.GetCode(isolate()); |
2781 set_target(*new_target); | 2781 set_target(*new_target); |
2782 | 2782 |
2783 if (FLAG_trace_ic) { | 2783 if (FLAG_trace_ic) { |
2784 PrintF("[CompareIC in "); | 2784 PrintF("[CompareIC in "); |
2785 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2785 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
(...skipping 25 matching lines...) Expand all Loading... |
2811 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2811 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2812 } | 2812 } |
2813 | 2813 |
2814 | 2814 |
2815 void CompareNilIC::Clear(Address address, | 2815 void CompareNilIC::Clear(Address address, |
2816 Code* target, | 2816 Code* target, |
2817 ConstantPoolArray* constant_pool) { | 2817 ConstantPoolArray* constant_pool) { |
2818 if (IsCleared(target)) return; | 2818 if (IsCleared(target)) return; |
2819 ExtraICState state = target->extra_ic_state(); | 2819 ExtraICState state = target->extra_ic_state(); |
2820 | 2820 |
2821 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2821 CompareNilICStub stub(target->GetIsolate(), |
| 2822 state, |
| 2823 HydrogenCodeStub::UNINITIALIZED); |
2822 stub.ClearState(); | 2824 stub.ClearState(); |
2823 | 2825 |
2824 Code* code = NULL; | 2826 Code* code = NULL; |
2825 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 2827 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
2826 | 2828 |
2827 SetTargetAtAddress(address, code, constant_pool); | 2829 SetTargetAtAddress(address, code, constant_pool); |
2828 } | 2830 } |
2829 | 2831 |
2830 | 2832 |
2831 Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, | 2833 Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, |
2832 NilValue nil, | 2834 NilValue nil, |
2833 Handle<Object> object) { | 2835 Handle<Object> object) { |
2834 if (object->IsNull() || object->IsUndefined()) { | 2836 if (object->IsNull() || object->IsUndefined()) { |
2835 return handle(Smi::FromInt(true), isolate); | 2837 return handle(Smi::FromInt(true), isolate); |
2836 } | 2838 } |
2837 return handle(Smi::FromInt(object->IsUndetectableObject()), isolate); | 2839 return handle(Smi::FromInt(object->IsUndetectableObject()), isolate); |
2838 } | 2840 } |
2839 | 2841 |
2840 | 2842 |
2841 Handle<Object> CompareNilIC::CompareNil(Handle<Object> object) { | 2843 Handle<Object> CompareNilIC::CompareNil(Handle<Object> object) { |
2842 ExtraICState extra_ic_state = target()->extra_ic_state(); | 2844 ExtraICState extra_ic_state = target()->extra_ic_state(); |
2843 | 2845 |
2844 CompareNilICStub stub(extra_ic_state); | 2846 CompareNilICStub stub(isolate(), extra_ic_state); |
2845 | 2847 |
2846 // Extract the current supported types from the patched IC and calculate what | 2848 // Extract the current supported types from the patched IC and calculate what |
2847 // types must be supported as a result of the miss. | 2849 // types must be supported as a result of the miss. |
2848 bool already_monomorphic = stub.IsMonomorphic(); | 2850 bool already_monomorphic = stub.IsMonomorphic(); |
2849 | 2851 |
2850 stub.UpdateStatus(object); | 2852 stub.UpdateStatus(object); |
2851 | 2853 |
2852 NilValue nil = stub.GetNilValue(); | 2854 NilValue nil = stub.GetNilValue(); |
2853 | 2855 |
2854 // Find or create the specialized stub to support the new set of types. | 2856 // Find or create the specialized stub to support the new set of types. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2916 return Builtins::SHR; | 2918 return Builtins::SHR; |
2917 break; | 2919 break; |
2918 case Token::SHL: | 2920 case Token::SHL: |
2919 return Builtins::SHL; | 2921 return Builtins::SHL; |
2920 break; | 2922 break; |
2921 } | 2923 } |
2922 } | 2924 } |
2923 | 2925 |
2924 | 2926 |
2925 Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) { | 2927 Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) { |
2926 ToBooleanStub stub(target()->extra_ic_state()); | 2928 ToBooleanStub stub(isolate(), target()->extra_ic_state()); |
2927 bool to_boolean_value = stub.UpdateStatus(object); | 2929 bool to_boolean_value = stub.UpdateStatus(object); |
2928 Handle<Code> code = stub.GetCode(isolate()); | 2930 Handle<Code> code = stub.GetCode(isolate()); |
2929 set_target(*code); | 2931 set_target(*code); |
2930 return handle(Smi::FromInt(to_boolean_value ? 1 : 0), isolate()); | 2932 return handle(Smi::FromInt(to_boolean_value ? 1 : 0), isolate()); |
2931 } | 2933 } |
2932 | 2934 |
2933 | 2935 |
2934 RUNTIME_FUNCTION(ToBooleanIC_Miss) { | 2936 RUNTIME_FUNCTION(ToBooleanIC_Miss) { |
2935 ASSERT(args.length() == 1); | 2937 ASSERT(args.length() == 1); |
2936 HandleScope scope(isolate); | 2938 HandleScope scope(isolate); |
(...skipping 10 matching lines...) Expand all Loading... |
2947 #undef ADDR | 2949 #undef ADDR |
2948 }; | 2950 }; |
2949 | 2951 |
2950 | 2952 |
2951 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2953 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2952 return IC_utilities[id]; | 2954 return IC_utilities[id]; |
2953 } | 2955 } |
2954 | 2956 |
2955 | 2957 |
2956 } } // namespace v8::internal | 2958 } } // namespace v8::internal |
OLD | NEW |