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 |