| 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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 if (target()->is_keyed_stub()) { | 185 if (target()->is_keyed_stub()) { |
| 186 // Determine whether the failure is due to a name failure. | 186 // Determine whether the failure is due to a name failure. |
| 187 if (!name->IsName()) return false; | 187 if (!name->IsName()) return false; |
| 188 Name* stub_name = target()->FindFirstName(); | 188 Name* stub_name = target()->FindFirstName(); |
| 189 if (Name::cast(name) != stub_name) return false; | 189 if (Name::cast(name) != stub_name) return false; |
| 190 } | 190 } |
| 191 | 191 |
| 192 InlineCacheHolderFlag cache_holder = | 192 InlineCacheHolderFlag cache_holder = |
| 193 Code::ExtractCacheHolderFromFlags(target()->flags()); | 193 Code::ExtractCacheHolderFromFlags(target()->flags()); |
| 194 | 194 |
| 195 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { | 195 switch (cache_holder) { |
| 196 // The stub was generated for JSObject but called for non-JSObject. | 196 case OWN_MAP: |
| 197 // IC::GetCodeCacheHolder is not applicable. | 197 // The stub was generated for JSObject but called for non-JSObject. |
| 198 return false; | 198 // IC::GetCodeCacheHolder is not applicable. |
| 199 } else if (cache_holder == PROTOTYPE_MAP && | 199 if (!receiver->IsJSObject()) return false; |
| 200 receiver->GetPrototype(isolate())->IsNull()) { | 200 break; |
| 201 // IC::GetCodeCacheHolder is not applicable. | 201 case PROTOTYPE_MAP: |
| 202 return false; | 202 // IC::GetCodeCacheHolder is not applicable. |
| 203 if (receiver->GetPrototype(isolate())->IsNull()) return false; |
| 204 break; |
| 203 } | 205 } |
| 206 |
| 204 Map* map = IC::GetCodeCacheHolder(isolate(), receiver, cache_holder)->map(); | 207 Map* map = IC::GetCodeCacheHolder(isolate(), receiver, cache_holder)->map(); |
| 205 | 208 |
| 206 // Decide whether the inline cache failed because of changes to the | 209 // Decide whether the inline cache failed because of changes to the |
| 207 // receiver itself or changes to one of its prototypes. | 210 // receiver itself or changes to one of its prototypes. |
| 208 // | 211 // |
| 209 // If there are changes to the receiver itself, the map of the | 212 // If there are changes to the receiver itself, the map of the |
| 210 // receiver will have changed and the current target will not be in | 213 // receiver will have changed and the current target will not be in |
| 211 // the receiver map's code cache. Therefore, if the current target | 214 // the receiver map's code cache. Therefore, if the current target |
| 212 // is in the receiver map's code cache, the inline cache failed due | 215 // is in the receiver map's code cache, the inline cache failed due |
| 213 // to prototype check failure. | 216 // to prototype check failure. |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); | 447 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); |
| 445 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 448 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
| 446 } | 449 } |
| 447 | 450 |
| 448 | 451 |
| 449 static bool HasInterceptorGetter(JSObject* object) { | 452 static bool HasInterceptorGetter(JSObject* object) { |
| 450 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 453 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
| 451 } | 454 } |
| 452 | 455 |
| 453 | 456 |
| 457 static bool HasInterceptorSetter(JSObject* object) { |
| 458 return !object->GetNamedInterceptor()->setter()->IsUndefined(); |
| 459 } |
| 460 |
| 461 |
| 454 static void LookupForRead(Handle<Object> object, | 462 static void LookupForRead(Handle<Object> object, |
| 455 Handle<String> name, | 463 Handle<String> name, |
| 456 LookupResult* lookup) { | 464 LookupResult* lookup) { |
| 457 // Skip all the objects with named interceptors, but | 465 // Skip all the objects with named interceptors, but |
| 458 // without actual getter. | 466 // without actual getter. |
| 459 while (true) { | 467 while (true) { |
| 460 object->Lookup(*name, lookup); | 468 object->Lookup(*name, lookup); |
| 461 // Besides normal conditions (property not found or it's not | 469 // Besides normal conditions (property not found or it's not |
| 462 // an interceptor), bail out if lookup is not cacheable: we won't | 470 // an interceptor), bail out if lookup is not cacheable: we won't |
| 463 // be able to IC it anyway and regular lookup should work fine. | 471 // be able to IC it anyway and regular lookup should work fine. |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 Handle<String> name, | 1470 Handle<String> name, |
| 1463 Handle<Object> value, | 1471 Handle<Object> value, |
| 1464 LookupResult* lookup, | 1472 LookupResult* lookup, |
| 1465 IC* ic) { | 1473 IC* ic) { |
| 1466 Handle<JSObject> holder = receiver; | 1474 Handle<JSObject> holder = receiver; |
| 1467 receiver->Lookup(*name, lookup); | 1475 receiver->Lookup(*name, lookup); |
| 1468 if (lookup->IsFound()) { | 1476 if (lookup->IsFound()) { |
| 1469 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1477 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
| 1470 | 1478 |
| 1471 if (lookup->holder() == *receiver) { | 1479 if (lookup->holder() == *receiver) { |
| 1472 if (lookup->IsInterceptor() && | 1480 if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) { |
| 1473 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { | |
| 1474 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1481 receiver->LocalLookupRealNamedProperty(*name, lookup); |
| 1475 return lookup->IsFound() && | 1482 return lookup->IsFound() && |
| 1476 !lookup->IsReadOnly() && | 1483 !lookup->IsReadOnly() && |
| 1477 lookup->CanHoldValue(value) && | 1484 lookup->CanHoldValue(value) && |
| 1478 lookup->IsCacheable(); | 1485 lookup->IsCacheable(); |
| 1479 } | 1486 } |
| 1480 return lookup->CanHoldValue(value); | 1487 return lookup->CanHoldValue(value); |
| 1481 } | 1488 } |
| 1482 | 1489 |
| 1483 if (lookup->IsPropertyCallbacks()) return true; | 1490 if (lookup->IsPropertyCallbacks()) return true; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1644 void StoreIC::UpdateCaches(LookupResult* lookup, | 1651 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1645 Handle<JSObject> receiver, | 1652 Handle<JSObject> receiver, |
| 1646 Handle<String> name, | 1653 Handle<String> name, |
| 1647 Handle<Object> value) { | 1654 Handle<Object> value) { |
| 1648 ASSERT(!receiver->IsJSGlobalProxy()); | 1655 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1649 ASSERT(lookup->IsFound()); | 1656 ASSERT(lookup->IsFound()); |
| 1650 | 1657 |
| 1651 // These are not cacheable, so we never see such LookupResults here. | 1658 // These are not cacheable, so we never see such LookupResults here. |
| 1652 ASSERT(!lookup->IsHandler()); | 1659 ASSERT(!lookup->IsHandler()); |
| 1653 | 1660 |
| 1654 Handle<Code> code = ComputeStoreMonomorphic(lookup, receiver, name, value); | 1661 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); |
| 1655 if (code.is_null()) { | 1662 if (code.is_null()) { |
| 1656 set_target(*generic_stub()); | 1663 set_target(*generic_stub()); |
| 1657 return; | 1664 return; |
| 1658 } | 1665 } |
| 1659 | 1666 |
| 1660 PatchCache(receiver, name, code); | 1667 PatchCache(receiver, name, code); |
| 1661 TRACE_IC("StoreIC", name, target()); | 1668 TRACE_IC("StoreIC", name, target()); |
| 1662 } | 1669 } |
| 1663 | 1670 |
| 1664 | 1671 |
| 1665 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1672 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup, |
| 1666 Handle<JSObject> receiver, | 1673 Handle<JSObject> receiver, |
| 1667 Handle<String> name, | 1674 Handle<String> name, |
| 1668 Handle<Object> value) { | 1675 Handle<Object> value) { |
| 1669 Handle<JSObject> holder(lookup->holder()); | 1676 Handle<JSObject> holder(lookup->holder()); |
| 1670 switch (lookup->type()) { | 1677 switch (lookup->type()) { |
| 1671 case FIELD: | 1678 case FIELD: |
| 1672 return isolate()->stub_cache()->ComputeStoreField( | 1679 return isolate()->stub_cache()->ComputeStoreField( |
| 1673 name, receiver, lookup, strict_mode()); | 1680 name, receiver, lookup, strict_mode()); |
| 1674 case NORMAL: | 1681 case NORMAL: |
| 1675 if (receiver->IsGlobalObject()) { | 1682 if (receiver->IsGlobalObject()) { |
| 1676 // The stub generated for the global object picks the value directly | 1683 // The stub generated for the global object picks the value directly |
| 1677 // from the property cell. So the property must be directly on the | 1684 // from the property cell. So the property must be directly on the |
| 1678 // global object. | 1685 // global object. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1718 name, receiver, holder, Handle<JSFunction>::cast(setter), |
| 1712 strict_mode()); | 1719 strict_mode()); |
| 1713 } | 1720 } |
| 1714 // TODO(dcarney): Handle correctly. | 1721 // TODO(dcarney): Handle correctly. |
| 1715 if (callback->IsDeclaredAccessorInfo()) break; | 1722 if (callback->IsDeclaredAccessorInfo()) break; |
| 1716 ASSERT(callback->IsForeign()); | 1723 ASSERT(callback->IsForeign()); |
| 1717 // No IC support for old-style native accessors. | 1724 // No IC support for old-style native accessors. |
| 1718 break; | 1725 break; |
| 1719 } | 1726 } |
| 1720 case INTERCEPTOR: | 1727 case INTERCEPTOR: |
| 1721 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1728 ASSERT(HasInterceptorSetter(*receiver)); |
| 1722 return isolate()->stub_cache()->ComputeStoreInterceptor( | 1729 return isolate()->stub_cache()->ComputeStoreInterceptor( |
| 1723 name, receiver, strict_mode()); | 1730 name, receiver, strict_mode()); |
| 1724 case CONSTANT: | 1731 case CONSTANT: |
| 1725 break; | 1732 break; |
| 1726 case TRANSITION: { | 1733 case TRANSITION: { |
| 1727 // Explicitly pass in the receiver map since LookupForWrite may have | 1734 // Explicitly pass in the receiver map since LookupForWrite may have |
| 1728 // stored something else than the receiver in the holder. | 1735 // stored something else than the receiver in the holder. |
| 1729 Handle<Map> transition( | 1736 Handle<Map> transition( |
| 1730 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1737 lookup->GetTransitionTarget(receiver->map()), isolate()); |
| 1731 int descriptor = transition->LastAdded(); | 1738 int descriptor = transition->LastAdded(); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2044 ASSERT(!stub.is_null()); | 2051 ASSERT(!stub.is_null()); |
| 2045 set_target(*stub); | 2052 set_target(*stub); |
| 2046 TRACE_IC("KeyedStoreIC", key, target()); | 2053 TRACE_IC("KeyedStoreIC", key, target()); |
| 2047 } | 2054 } |
| 2048 | 2055 |
| 2049 return Runtime::SetObjectPropertyOrFail( | 2056 return Runtime::SetObjectPropertyOrFail( |
| 2050 isolate(), object , key, value, NONE, strict_mode()); | 2057 isolate(), object , key, value, NONE, strict_mode()); |
| 2051 } | 2058 } |
| 2052 | 2059 |
| 2053 | 2060 |
| 2054 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 2061 Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup, |
| 2055 Handle<JSObject> receiver, | 2062 Handle<JSObject> receiver, |
| 2056 Handle<String> name, | 2063 Handle<String> name, |
| 2057 Handle<Object> value) { | 2064 Handle<Object> value) { |
| 2058 // If the property has a non-field type allowing map transitions | 2065 // If the property has a non-field type allowing map transitions |
| 2059 // where there is extra room in the object, we leave the IC in its | 2066 // where there is extra room in the object, we leave the IC in its |
| 2060 // current state. | 2067 // current state. |
| 2061 switch (lookup->type()) { | 2068 switch (lookup->type()) { |
| 2062 case FIELD: | 2069 case FIELD: |
| 2063 return isolate()->stub_cache()->ComputeKeyedStoreField( | 2070 return isolate()->stub_cache()->ComputeKeyedStoreField( |
| 2064 name, receiver, lookup, strict_mode()); | 2071 name, receiver, lookup, strict_mode()); |
| 2065 case TRANSITION: { | 2072 case TRANSITION: { |
| 2066 // Explicitly pass in the receiver map since LookupForWrite may have | 2073 // Explicitly pass in the receiver map since LookupForWrite may have |
| 2067 // stored something else than the receiver in the holder. | 2074 // stored something else than the receiver in the holder. |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2971 #undef ADDR | 2978 #undef ADDR |
| 2972 }; | 2979 }; |
| 2973 | 2980 |
| 2974 | 2981 |
| 2975 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2982 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2976 return IC_utilities[id]; | 2983 return IC_utilities[id]; |
| 2977 } | 2984 } |
| 2978 | 2985 |
| 2979 | 2986 |
| 2980 } } // namespace v8::internal | 2987 } } // namespace v8::internal |
| OLD | NEW |