| 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 | 
|---|