Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ic.cc

Issue 25260002: Always store stubs on the JSObject receiver, even when in slow mode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698