OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 | 870 |
871 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 871 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
872 Handle<Object> object, | 872 Handle<Object> object, |
873 Handle<String> name, | 873 Handle<String> name, |
874 Handle<Object> value) { | 874 Handle<Object> value) { |
875 bool receiver_is_holder = lookup->ReceiverIsHolder(object); | 875 bool receiver_is_holder = lookup->ReceiverIsHolder(object); |
876 CacheHolderFlag flag; | 876 CacheHolderFlag flag; |
877 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 877 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
878 *receiver_type(), receiver_is_holder, isolate(), &flag); | 878 *receiver_type(), receiver_is_holder, isolate(), &flag); |
879 | 879 |
880 Handle<Code> code = isolate()->stub_cache()->FindHandler( | 880 Handle<Code> code = PropertyHandlerCompiler::Find( |
881 name, stub_holder_map, handler_kind(), flag, | 881 name, stub_holder_map, handler_kind(), flag, |
882 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); | 882 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); |
883 // Use the cached value if it exists, and if it is different from the | 883 // Use the cached value if it exists, and if it is different from the |
884 // handler that just missed. | 884 // handler that just missed. |
885 if (!code.is_null()) { | 885 if (!code.is_null()) { |
886 if (!maybe_handler_.is_null() && | 886 if (!maybe_handler_.is_null() && |
887 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { | 887 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { |
888 return code; | 888 return code; |
889 } | 889 } |
890 if (maybe_handler_.is_null()) { | 890 if (maybe_handler_.is_null()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 StringLengthStub string_length_stub(isolate()); | 927 StringLengthStub string_length_stub(isolate()); |
928 return string_length_stub.GetCode(); | 928 return string_length_stub.GetCode(); |
929 } | 929 } |
930 | 930 |
931 // Use specialized code for getting prototype of functions. | 931 // Use specialized code for getting prototype of functions. |
932 if (object->IsJSFunction() && | 932 if (object->IsJSFunction() && |
933 String::Equals(isolate()->factory()->prototype_string(), name) && | 933 String::Equals(isolate()->factory()->prototype_string(), name) && |
934 Handle<JSFunction>::cast(object)->should_have_prototype() && | 934 Handle<JSFunction>::cast(object)->should_have_prototype() && |
935 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { | 935 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { |
936 Handle<Code> stub; | 936 Handle<Code> stub; |
937 FunctionPrototypeStub function_prototype_stub(isolate(), kind()); | 937 FunctionPrototypeStub function_prototype_stub(isolate()); |
938 return function_prototype_stub.GetCode(); | 938 return function_prototype_stub.GetCode(); |
939 } | 939 } |
940 | 940 |
941 Handle<HeapType> type = receiver_type(); | 941 Handle<HeapType> type = receiver_type(); |
942 Handle<JSObject> holder(lookup->holder()); | 942 Handle<JSObject> holder(lookup->holder()); |
943 bool receiver_is_holder = object.is_identical_to(holder); | 943 bool receiver_is_holder = object.is_identical_to(holder); |
944 LoadStubCompiler compiler(isolate(), handler_kind(), kNoExtraICState, | 944 NamedLoadHandlerCompiler compiler(isolate(), handler_kind(), kNoExtraICState, |
945 cache_holder); | 945 cache_holder); |
946 | 946 |
947 switch (lookup->type()) { | 947 switch (lookup->type()) { |
948 case FIELD: { | 948 case FIELD: { |
949 FieldIndex field = lookup->GetFieldIndex(); | 949 FieldIndex field = lookup->GetFieldIndex(); |
950 if (receiver_is_holder) { | 950 if (receiver_is_holder) { |
951 return SimpleFieldLoad(field); | 951 return SimpleFieldLoad(field); |
952 } | 952 } |
953 return compiler.CompileLoadField( | 953 return compiler.CompileLoadField( |
954 type, holder, name, field, lookup->representation()); | 954 type, holder, name, field, lookup->representation()); |
955 } | 955 } |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 Handle<Object> object, Handle<String> name, | 1385 Handle<Object> object, Handle<String> name, |
1386 Handle<Object> value, | 1386 Handle<Object> value, |
1387 CacheHolderFlag cache_holder) { | 1387 CacheHolderFlag cache_holder) { |
1388 if (object->IsAccessCheckNeeded()) return slow_stub(); | 1388 if (object->IsAccessCheckNeeded()) return slow_stub(); |
1389 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || | 1389 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || |
1390 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); | 1390 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); |
1391 // This is currently guaranteed by checks in StoreIC::Store. | 1391 // This is currently guaranteed by checks in StoreIC::Store. |
1392 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1392 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1393 | 1393 |
1394 Handle<JSObject> holder(lookup->holder()); | 1394 Handle<JSObject> holder(lookup->holder()); |
1395 // Handlers do not use strict mode. | 1395 NamedStoreHandlerCompiler compiler(isolate(), kind()); |
1396 StoreStubCompiler compiler(isolate(), SLOPPY, kind()); | 1396 |
1397 if (lookup->IsTransition()) { | 1397 if (lookup->IsTransition()) { |
1398 // Explicitly pass in the receiver map since LookupForWrite may have | 1398 // Explicitly pass in the receiver map since LookupForWrite may have |
1399 // stored something else than the receiver in the holder. | 1399 // stored something else than the receiver in the holder. |
1400 Handle<Map> transition(lookup->GetTransitionTarget()); | 1400 Handle<Map> transition(lookup->GetTransitionTarget()); |
1401 PropertyDetails details = lookup->GetPropertyDetails(); | 1401 PropertyDetails details = lookup->GetPropertyDetails(); |
1402 | 1402 |
1403 if (details.type() != CALLBACKS && details.attributes() == NONE) { | 1403 if (details.type() != CALLBACKS && details.attributes() == NONE) { |
1404 return compiler.CompileStoreTransition( | 1404 return compiler.CompileStoreTransition( |
1405 receiver, lookup, transition, name); | 1405 receiver, lookup, transition, name); |
1406 } | 1406 } |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 | 1739 |
1740 if (key->IsInternalizedString()) { | 1740 if (key->IsInternalizedString()) { |
1741 ASSIGN_RETURN_ON_EXCEPTION( | 1741 ASSIGN_RETURN_ON_EXCEPTION( |
1742 isolate(), | 1742 isolate(), |
1743 store_handle, | 1743 store_handle, |
1744 StoreIC::Store(object, | 1744 StoreIC::Store(object, |
1745 Handle<String>::cast(key), | 1745 Handle<String>::cast(key), |
1746 value, | 1746 value, |
1747 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 1747 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
1748 Object); | 1748 Object); |
1749 } else { | 1749 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
1750 bool use_ic = FLAG_use_ic && | 1750 set_target(*stub); |
1751 !object->IsStringWrapper() && | 1751 return store_handle; |
1752 !object->IsAccessCheckNeeded() && | 1752 } |
1753 !object->IsJSGlobalProxy() && | |
1754 !(object->IsJSObject() && | |
1755 JSObject::cast(*object)->map()->is_observed()); | |
1756 if (use_ic && !object->IsSmi()) { | |
1757 // Don't use ICs for maps of the objects in Array's prototype chain. We | |
1758 // expect to be able to trap element sets to objects with those maps in | |
1759 // the runtime to enable optimization of element hole access. | |
1760 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | |
1761 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | |
1762 } | |
1763 | 1753 |
1764 if (use_ic) { | 1754 bool use_ic = |
1765 ASSERT(!object->IsAccessCheckNeeded()); | 1755 FLAG_use_ic && !object->IsStringWrapper() && |
| 1756 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
| 1757 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
| 1758 if (use_ic && !object->IsSmi()) { |
| 1759 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 1760 // expect to be able to trap element sets to objects with those maps in |
| 1761 // the runtime to enable optimization of element hole access. |
| 1762 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 1763 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
| 1764 } |
1766 | 1765 |
1767 if (object->IsJSObject()) { | 1766 if (use_ic) { |
1768 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1767 ASSERT(!object->IsAccessCheckNeeded()); |
1769 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); | 1768 |
1770 if (receiver->elements()->map() == | 1769 if (object->IsJSObject()) { |
1771 isolate()->heap()->sloppy_arguments_elements_map()) { | 1770 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1772 if (strict_mode() == SLOPPY) { | 1771 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); |
1773 stub = sloppy_arguments_stub(); | 1772 if (receiver->elements()->map() == |
1774 } | 1773 isolate()->heap()->sloppy_arguments_elements_map()) { |
1775 } else if (key_is_smi_like && | 1774 if (strict_mode() == SLOPPY) { |
1776 !(target().is_identical_to(sloppy_arguments_stub()))) { | 1775 stub = sloppy_arguments_stub(); |
1777 // We should go generic if receiver isn't a dictionary, but our | 1776 } |
1778 // prototype chain does have dictionary elements. This ensures that | 1777 } else if (key_is_smi_like && |
1779 // other non-dictionary receivers in the polymorphic case benefit | 1778 !(target().is_identical_to(sloppy_arguments_stub()))) { |
1780 // from fast path keyed stores. | 1779 // We should go generic if receiver isn't a dictionary, but our |
1781 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 1780 // prototype chain does have dictionary elements. This ensures that |
1782 KeyedAccessStoreMode store_mode = | 1781 // other non-dictionary receivers in the polymorphic case benefit |
1783 GetStoreMode(receiver, key, value); | 1782 // from fast path keyed stores. |
1784 stub = StoreElementStub(receiver, store_mode); | 1783 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
1785 } | 1784 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
| 1785 stub = StoreElementStub(receiver, store_mode); |
1786 } | 1786 } |
1787 } | 1787 } |
1788 } | 1788 } |
1789 } | 1789 } |
1790 | 1790 |
1791 if (store_handle.is_null()) { | 1791 if (store_handle.is_null()) { |
1792 ASSIGN_RETURN_ON_EXCEPTION( | 1792 ASSIGN_RETURN_ON_EXCEPTION( |
1793 isolate(), | 1793 isolate(), |
1794 store_handle, | 1794 store_handle, |
1795 Runtime::SetObjectProperty( | 1795 Runtime::SetObjectProperty( |
1796 isolate(), object, key, value, strict_mode()), | 1796 isolate(), object, key, value, strict_mode()), |
1797 Object); | 1797 Object); |
1798 } | 1798 } |
1799 | 1799 |
1800 if (!is_target_set()) { | 1800 ASSERT(!is_target_set()); |
1801 Code* generic = *generic_stub(); | 1801 Code* generic = *generic_stub(); |
1802 if (*stub == generic) { | 1802 if (*stub == generic) { |
1803 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 1803 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
1804 } | |
1805 ASSERT(!stub.is_null()); | |
1806 set_target(*stub); | |
1807 TRACE_IC("StoreIC", key); | |
1808 } | 1804 } |
| 1805 ASSERT(!stub.is_null()); |
| 1806 set_target(*stub); |
| 1807 TRACE_IC("StoreIC", key); |
1809 | 1808 |
1810 return store_handle; | 1809 return store_handle; |
1811 } | 1810 } |
1812 | 1811 |
1813 | 1812 |
1814 CallIC::State::State(ExtraICState extra_ic_state) | 1813 CallIC::State::State(ExtraICState extra_ic_state) |
1815 : argc_(ArgcBits::decode(extra_ic_state)), | 1814 : argc_(ArgcBits::decode(extra_ic_state)), |
1816 call_type_(CallTypeBits::decode(extra_ic_state)) { | 1815 call_type_(CallTypeBits::decode(extra_ic_state)) { |
1817 } | 1816 } |
1818 | 1817 |
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3036 #undef ADDR | 3035 #undef ADDR |
3037 }; | 3036 }; |
3038 | 3037 |
3039 | 3038 |
3040 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3039 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3041 return IC_utilities[id]; | 3040 return IC_utilities[id]; |
3042 } | 3041 } |
3043 | 3042 |
3044 | 3043 |
3045 } } // namespace v8::internal | 3044 } } // namespace v8::internal |
OLD | NEW |