| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1323 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
| 1324 } | 1324 } |
| 1325 | 1325 |
| 1326 | 1326 |
| 1327 void StoreIC::UpdateCaches(LookupResult* lookup, | 1327 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1328 State state, | 1328 State state, |
| 1329 StrictModeFlag strict_mode, | 1329 StrictModeFlag strict_mode, |
| 1330 Handle<JSObject> receiver, | 1330 Handle<JSObject> receiver, |
| 1331 Handle<String> name, | 1331 Handle<String> name, |
| 1332 Handle<Object> value) { | 1332 Handle<Object> value) { |
| 1333 // Skip JSGlobalProxy. | |
| 1334 ASSERT(!receiver->IsJSGlobalProxy()); | 1333 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1335 | |
| 1336 ASSERT(StoreICableLookup(lookup)); | 1334 ASSERT(StoreICableLookup(lookup)); |
| 1335 // These are not cacheable, so we never see such LookupResults here. |
| 1336 ASSERT(lookup->type() != HANDLER); |
| 1337 // We get only called for properties or transitions, see StoreICableLookup. |
| 1338 ASSERT(lookup->type() != NULL_DESCRIPTOR); |
| 1337 | 1339 |
| 1338 // If the property has a non-field type allowing map transitions | 1340 // If the property has a non-field type allowing map transitions |
| 1339 // where there is extra room in the object, we leave the IC in its | 1341 // where there is extra room in the object, we leave the IC in its |
| 1340 // current state. | 1342 // current state. |
| 1341 PropertyType type = lookup->type(); | 1343 PropertyType type = lookup->type(); |
| 1342 | 1344 |
| 1343 // Compute the code stub for this store; used for rewriting to | 1345 // Compute the code stub for this store; used for rewriting to |
| 1344 // monomorphic state and making sure that the code stub is in the | 1346 // monomorphic state and making sure that the code stub is in the |
| 1345 // stub cache. | 1347 // stub cache. |
| 1346 Handle<Code> code; | 1348 Handle<Code> code; |
| 1347 switch (type) { | 1349 switch (type) { |
| 1348 case FIELD: | 1350 case FIELD: |
| 1349 code = isolate()->stub_cache()->ComputeStoreField(name, | 1351 code = isolate()->stub_cache()->ComputeStoreField(name, |
| 1350 receiver, | 1352 receiver, |
| 1351 lookup->GetFieldIndex(), | 1353 lookup->GetFieldIndex(), |
| 1352 Handle<Map>::null(), | 1354 Handle<Map>::null(), |
| 1353 strict_mode); | 1355 strict_mode); |
| 1354 break; | 1356 break; |
| 1355 case MAP_TRANSITION: { | 1357 case MAP_TRANSITION: { |
| 1356 if (lookup->GetAttributes() != NONE) return; | 1358 if (lookup->GetAttributes() != NONE) return; |
| 1357 ASSERT(type == MAP_TRANSITION); | |
| 1358 Handle<Map> transition(lookup->GetTransitionMap()); | 1359 Handle<Map> transition(lookup->GetTransitionMap()); |
| 1359 int index = transition->PropertyIndexFor(*name); | 1360 int index = transition->PropertyIndexFor(*name); |
| 1360 code = isolate()->stub_cache()->ComputeStoreField( | 1361 code = isolate()->stub_cache()->ComputeStoreField( |
| 1361 name, receiver, index, transition, strict_mode); | 1362 name, receiver, index, transition, strict_mode); |
| 1362 break; | 1363 break; |
| 1363 } | 1364 } |
| 1364 case NORMAL: | 1365 case NORMAL: |
| 1365 if (receiver->IsGlobalObject()) { | 1366 if (receiver->IsGlobalObject()) { |
| 1366 // The stub generated for the global object picks the value directly | 1367 // The stub generated for the global object picks the value directly |
| 1367 // from the property cell. So the property must be directly on the | 1368 // from the property cell. So the property must be directly on the |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1383 if (v8::ToCData<Address>(callback->setter()) == 0) return; | 1384 if (v8::ToCData<Address>(callback->setter()) == 0) return; |
| 1384 code = isolate()->stub_cache()->ComputeStoreCallback( | 1385 code = isolate()->stub_cache()->ComputeStoreCallback( |
| 1385 name, receiver, callback, strict_mode); | 1386 name, receiver, callback, strict_mode); |
| 1386 break; | 1387 break; |
| 1387 } | 1388 } |
| 1388 case INTERCEPTOR: | 1389 case INTERCEPTOR: |
| 1389 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1390 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1390 code = isolate()->stub_cache()->ComputeStoreInterceptor( | 1391 code = isolate()->stub_cache()->ComputeStoreInterceptor( |
| 1391 name, receiver, strict_mode); | 1392 name, receiver, strict_mode); |
| 1392 break; | 1393 break; |
| 1393 default: | 1394 case CONSTANT_FUNCTION: |
| 1395 case CONSTANT_TRANSITION: |
| 1396 case ELEMENTS_TRANSITION: |
| 1397 return; |
| 1398 case HANDLER: |
| 1399 case NULL_DESCRIPTOR: |
| 1400 UNREACHABLE(); |
| 1394 return; | 1401 return; |
| 1395 } | 1402 } |
| 1396 | 1403 |
| 1397 // Patch the call site depending on the state of the cache. | 1404 // Patch the call site depending on the state of the cache. |
| 1398 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1405 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 1399 set_target(*code); | 1406 set_target(*code); |
| 1400 } else if (state == MONOMORPHIC) { | 1407 } else if (state == MONOMORPHIC) { |
| 1401 // Only move to megamorphic if the target changes. | 1408 // Only move to megamorphic if the target changes. |
| 1402 if (target() != *code) { | 1409 if (target() != *code) { |
| 1403 set_target((strict_mode == kStrictMode) | 1410 set_target((strict_mode == kStrictMode) |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1636 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1630 | 1637 |
| 1631 // Check if the given name is an array index. | 1638 // Check if the given name is an array index. |
| 1632 uint32_t index; | 1639 uint32_t index; |
| 1633 if (name->AsArrayIndex(&index)) { | 1640 if (name->AsArrayIndex(&index)) { |
| 1634 Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1641 Handle<Object> result = SetElement(receiver, index, value, strict_mode); |
| 1635 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1642 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1636 return *value; | 1643 return *value; |
| 1637 } | 1644 } |
| 1638 | 1645 |
| 1639 // Lookup the property locally in the receiver. | |
| 1640 LookupResult lookup(isolate()); | |
| 1641 receiver->LocalLookup(*name, &lookup); | |
| 1642 | |
| 1643 // Update inline cache and stub cache. | 1646 // Update inline cache and stub cache. |
| 1644 if (FLAG_use_ic) { | 1647 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
| 1645 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1648 LookupResult lookup(isolate()); |
| 1649 if (LookupForWrite(receiver, name, &lookup)) { |
| 1650 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1651 } |
| 1646 } | 1652 } |
| 1647 | 1653 |
| 1648 // Set the property. | 1654 // Set the property. |
| 1649 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1655 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
| 1650 } | 1656 } |
| 1651 | 1657 |
| 1652 // Do not use ICs for objects that require access checks (including | 1658 // Do not use ICs for objects that require access checks (including |
| 1653 // the global object). | 1659 // the global object). |
| 1654 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1660 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1655 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1661 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 isolate(), object , key, value, NONE, strict_mode); | 1697 isolate(), object , key, value, NONE, strict_mode); |
| 1692 } | 1698 } |
| 1693 | 1699 |
| 1694 | 1700 |
| 1695 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1701 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
| 1696 State state, | 1702 State state, |
| 1697 StrictModeFlag strict_mode, | 1703 StrictModeFlag strict_mode, |
| 1698 Handle<JSObject> receiver, | 1704 Handle<JSObject> receiver, |
| 1699 Handle<String> name, | 1705 Handle<String> name, |
| 1700 Handle<Object> value) { | 1706 Handle<Object> value) { |
| 1701 // Skip JSGlobalProxy. | 1707 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1702 if (receiver->IsJSGlobalProxy()) return; | 1708 ASSERT(StoreICableLookup(lookup)); |
| 1703 | 1709 // These are not cacheable, so we never see such LookupResults here. |
| 1704 // Bail out if we didn't find a result. | 1710 ASSERT(lookup->type() != HANDLER); |
| 1705 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; | 1711 // We get only called for properties or transitions, see StoreICableLookup. |
| 1706 | 1712 ASSERT(lookup->type() != NULL_DESCRIPTOR); |
| 1707 // If the property is read-only, we leave the IC in its current | |
| 1708 // state. | |
| 1709 if (lookup->IsReadOnly()) return; | |
| 1710 | 1713 |
| 1711 // If the property has a non-field type allowing map transitions | 1714 // If the property has a non-field type allowing map transitions |
| 1712 // where there is extra room in the object, we leave the IC in its | 1715 // where there is extra room in the object, we leave the IC in its |
| 1713 // current state. | 1716 // current state. |
| 1714 PropertyType type = lookup->type(); | 1717 PropertyType type = lookup->type(); |
| 1715 | 1718 |
| 1716 // Compute the code stub for this store; used for rewriting to | 1719 // Compute the code stub for this store; used for rewriting to |
| 1717 // monomorphic state and making sure that the code stub is in the | 1720 // monomorphic state and making sure that the code stub is in the |
| 1718 // stub cache. | 1721 // stub cache. |
| 1719 Handle<Code> code; | 1722 Handle<Code> code; |
| 1720 | 1723 |
| 1721 switch (type) { | 1724 switch (type) { |
| 1722 case FIELD: | 1725 case FIELD: |
| 1723 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1726 code = isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1724 name, receiver, lookup->GetFieldIndex(), | 1727 name, receiver, lookup->GetFieldIndex(), |
| 1725 Handle<Map>::null(), strict_mode); | 1728 Handle<Map>::null(), strict_mode); |
| 1726 break; | 1729 break; |
| 1727 case MAP_TRANSITION: | 1730 case MAP_TRANSITION: |
| 1728 if (lookup->GetAttributes() == NONE) { | 1731 if (lookup->GetAttributes() == NONE) { |
| 1729 ASSERT(type == MAP_TRANSITION); | |
| 1730 Handle<Map> transition(lookup->GetTransitionMap()); | 1732 Handle<Map> transition(lookup->GetTransitionMap()); |
| 1731 int index = transition->PropertyIndexFor(*name); | 1733 int index = transition->PropertyIndexFor(*name); |
| 1732 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1734 code = isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1733 name, receiver, index, transition, strict_mode); | 1735 name, receiver, index, transition, strict_mode); |
| 1734 break; | 1736 break; |
| 1735 } | 1737 } |
| 1736 // fall through. | 1738 // fall through. |
| 1737 default: | 1739 case NORMAL: |
| 1740 case CONSTANT_FUNCTION: |
| 1741 case CALLBACKS: |
| 1742 case INTERCEPTOR: |
| 1743 case CONSTANT_TRANSITION: |
| 1744 case ELEMENTS_TRANSITION: |
| 1738 // Always rewrite to the generic case so that we do not | 1745 // Always rewrite to the generic case so that we do not |
| 1739 // repeatedly try to rewrite. | 1746 // repeatedly try to rewrite. |
| 1740 code = (strict_mode == kStrictMode) | 1747 code = (strict_mode == kStrictMode) |
| 1741 ? generic_stub_strict() | 1748 ? generic_stub_strict() |
| 1742 : generic_stub(); | 1749 : generic_stub(); |
| 1743 break; | 1750 break; |
| 1751 case HANDLER: |
| 1752 case NULL_DESCRIPTOR: |
| 1753 UNREACHABLE(); |
| 1754 return; |
| 1744 } | 1755 } |
| 1745 | 1756 |
| 1746 ASSERT(!code.is_null()); | 1757 ASSERT(!code.is_null()); |
| 1747 | 1758 |
| 1748 // Patch the call site depending on the state of the cache. Make | 1759 // Patch the call site depending on the state of the cache. Make |
| 1749 // sure to always rewrite from monomorphic to megamorphic. | 1760 // sure to always rewrite from monomorphic to megamorphic. |
| 1750 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1761 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1751 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1762 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1752 set_target(*code); | 1763 set_target(*code); |
| 1753 } else if (state == MONOMORPHIC) { | 1764 } else if (state == MONOMORPHIC) { |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2377 #undef ADDR | 2388 #undef ADDR |
| 2378 }; | 2389 }; |
| 2379 | 2390 |
| 2380 | 2391 |
| 2381 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2392 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2382 return IC_utilities[id]; | 2393 return IC_utilities[id]; |
| 2383 } | 2394 } |
| 2384 | 2395 |
| 2385 | 2396 |
| 2386 } } // namespace v8::internal | 2397 } } // namespace v8::internal |
| OLD | NEW |