| 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 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 956 return ReferenceError("not_defined", name); | 956 return ReferenceError("not_defined", name); |
| 957 } | 957 } |
| 958 return *result; | 958 return *result; |
| 959 } | 959 } |
| 960 | 960 |
| 961 // Get the property. | 961 // Get the property. |
| 962 return object->GetProperty(*object, &lookup, *name, &attr); | 962 return object->GetProperty(*object, &lookup, *name, &attr); |
| 963 } | 963 } |
| 964 | 964 |
| 965 | 965 |
| 966 void LoadIC::UpdateCaches(LookupResult* lookup, | 966 void IC::PatchCache(State state, |
| 967 State state, | 967 StrictModeFlag strict_mode, |
| 968 Handle<Object> object, | 968 Handle<JSObject> receiver, |
| 969 Handle<String> name) { | 969 Handle<String> name, |
| 970 // Bail out if the result is not cacheable. | 970 Handle<Code> code) { |
| 971 if (!lookup->IsCacheable()) return; | |
| 972 | |
| 973 // Loading properties from values is not common, so don't try to | |
| 974 // deal with non-JS objects here. | |
| 975 if (!object->IsJSObject()) return; | |
| 976 | |
| 977 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | |
| 978 | |
| 979 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 980 Handle<Code> code; | |
| 981 if (state == UNINITIALIZED) { | |
| 982 // This is the first time we execute this inline cache. | |
| 983 // Set the target to the pre monomorphic stub to delay | |
| 984 // setting the monomorphic state. | |
| 985 code = pre_monomorphic_stub(); | |
| 986 } else { | |
| 987 code = ComputeLoadMonomorphic(lookup, receiver, name); | |
| 988 if (code.is_null()) return; | |
| 989 } | |
| 990 | |
| 991 // Patch the call site depending on the state of the cache. | |
| 992 switch (state) { | 971 switch (state) { |
| 993 case UNINITIALIZED: | 972 case UNINITIALIZED: |
| 994 case PREMONOMORPHIC: | 973 case PREMONOMORPHIC: |
| 995 case MONOMORPHIC_PROTOTYPE_FAILURE: | 974 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 975 case POLYMORPHIC: |
| 996 set_target(*code); | 976 set_target(*code); |
| 997 break; | 977 break; |
| 998 case MONOMORPHIC: | 978 case MONOMORPHIC: |
| 979 // Only move to megamorphic if the target changes. |
| 999 if (target() != *code) { | 980 if (target() != *code) { |
| 1000 // We are transitioning from monomorphic to megamorphic case. | 981 // We are transitioning from monomorphic to megamorphic case. |
| 1001 // Place the current monomorphic stub and stub compiled for | 982 // Place the current monomorphic stub and stub compiled for |
| 1002 // the receiver into stub cache. | 983 // the receiver into stub cache. |
| 1003 Map* map = target()->FindFirstMap(); | 984 Map* map = target()->FindFirstMap(); |
| 1004 if (map != NULL) { | 985 if (map != NULL) { |
| 1005 UpdateMegamorphicCache(map, *name, target()); | 986 UpdateMegamorphicCache(map, *name, target()); |
| 1006 } | 987 } |
| 1007 UpdateMegamorphicCache(receiver->map(), *name, *code); | 988 UpdateMegamorphicCache(receiver->map(), *name, *code); |
| 1008 set_target(*megamorphic_stub()); | 989 set_target((strict_mode == kStrictMode) |
| 990 ? *megamorphic_stub_strict() |
| 991 : *megamorphic_stub()); |
| 1009 } | 992 } |
| 1010 break; | 993 break; |
| 1011 case MEGAMORPHIC: | 994 case MEGAMORPHIC: |
| 995 // Update the stub cache. |
| 1012 UpdateMegamorphicCache(receiver->map(), *name, *code); | 996 UpdateMegamorphicCache(receiver->map(), *name, *code); |
| 1013 break; | 997 break; |
| 998 case GENERIC: |
| 1014 case DEBUG_STUB: | 999 case DEBUG_STUB: |
| 1015 break; | 1000 break; |
| 1016 case POLYMORPHIC: | 1001 } |
| 1017 case GENERIC: | 1002 } |
| 1018 UNREACHABLE(); | 1003 |
| 1019 break; | 1004 |
| 1005 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 1006 State state, |
| 1007 Handle<Object> object, |
| 1008 Handle<String> name) { |
| 1009 // Bail out if the result is not cacheable. |
| 1010 if (!lookup->IsCacheable()) return; |
| 1011 |
| 1012 // Loading properties from values is not common, so don't try to |
| 1013 // deal with non-JS objects here. |
| 1014 if (!object->IsJSObject()) return; |
| 1015 |
| 1016 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
| 1017 |
| 1018 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1019 Handle<Code> code; |
| 1020 if (state == UNINITIALIZED) { |
| 1021 // This is the first time we execute this inline cache. |
| 1022 // Set the target to the pre monomorphic stub to delay |
| 1023 // setting the monomorphic state. |
| 1024 code = pre_monomorphic_stub(); |
| 1025 } else { |
| 1026 code = ComputeLoadMonomorphic(lookup, receiver, name); |
| 1027 if (code.is_null()) return; |
| 1020 } | 1028 } |
| 1021 | 1029 |
| 1030 PatchCache(state, kNonStrictMode, receiver, name, code); |
| 1022 TRACE_IC("LoadIC", name, state, target()); | 1031 TRACE_IC("LoadIC", name, state, target()); |
| 1023 } | 1032 } |
| 1024 | 1033 |
| 1025 | 1034 |
| 1026 void LoadIC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { | 1035 void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { |
| 1027 // Cache code holding map should be consistent with | 1036 // Cache code holding map should be consistent with |
| 1028 // GenerateMonomorphicCacheProbe. | 1037 // GenerateMonomorphicCacheProbe. |
| 1029 isolate()->stub_cache()->Set(name, map, code); | 1038 isolate()->stub_cache()->Set(name, map, code); |
| 1030 } | 1039 } |
| 1031 | 1040 |
| 1032 | 1041 |
| 1033 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup, | 1042 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup, |
| 1034 Handle<JSObject> receiver, | 1043 Handle<JSObject> receiver, |
| 1035 Handle<String> name) { | 1044 Handle<String> name) { |
| 1036 if (!lookup->IsProperty()) { | 1045 if (!lookup->IsProperty()) { |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 : global_proxy_stub(); | 1426 : global_proxy_stub(); |
| 1418 set_target(*stub); | 1427 set_target(*stub); |
| 1419 TRACE_IC("StoreIC", name, state, *stub); | 1428 TRACE_IC("StoreIC", name, state, *stub); |
| 1420 } | 1429 } |
| 1421 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1430 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
| 1422 } | 1431 } |
| 1423 | 1432 |
| 1424 LookupResult lookup(isolate()); | 1433 LookupResult lookup(isolate()); |
| 1425 if (LookupForWrite(receiver, name, &lookup)) { | 1434 if (LookupForWrite(receiver, name, &lookup)) { |
| 1426 if (FLAG_use_ic) { | 1435 if (FLAG_use_ic) { |
| 1427 UpdateStoreCaches(&lookup, state, strict_mode, receiver, name, value); | 1436 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1428 } | 1437 } |
| 1429 } else if (strict_mode == kStrictMode && | 1438 } else if (strict_mode == kStrictMode && |
| 1430 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1439 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1431 IsUndeclaredGlobal(object)) { | 1440 IsUndeclaredGlobal(object)) { |
| 1432 // Strict mode doesn't allow setting non-existent global property. | 1441 // Strict mode doesn't allow setting non-existent global property. |
| 1433 return ReferenceError("not_defined", name); | 1442 return ReferenceError("not_defined", name); |
| 1434 } | 1443 } |
| 1435 | 1444 |
| 1436 // Set the property. | 1445 // Set the property. |
| 1437 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1446 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
| 1438 } | 1447 } |
| 1439 | 1448 |
| 1440 | 1449 |
| 1441 void StoreIC::UpdateStoreCaches(LookupResult* lookup, | 1450 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1442 State state, | 1451 State state, |
| 1443 StrictModeFlag strict_mode, | 1452 StrictModeFlag strict_mode, |
| 1444 Handle<JSObject> receiver, | 1453 Handle<JSObject> receiver, |
| 1445 Handle<String> name, | 1454 Handle<String> name, |
| 1446 Handle<Object> value) { | 1455 Handle<Object> value) { |
| 1447 ASSERT(!receiver->IsJSGlobalProxy()); | 1456 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1448 ASSERT(StoreICableLookup(lookup)); | 1457 ASSERT(StoreICableLookup(lookup)); |
| 1449 ASSERT(lookup->IsFound()); | 1458 ASSERT(lookup->IsFound()); |
| 1450 | 1459 |
| 1451 // These are not cacheable, so we never see such LookupResults here. | 1460 // These are not cacheable, so we never see such LookupResults here. |
| 1452 ASSERT(!lookup->IsHandler()); | 1461 ASSERT(!lookup->IsHandler()); |
| 1453 | 1462 |
| 1454 // If the property has a non-field type allowing map transitions | 1463 Handle<Code> code = |
| 1455 // where there is extra room in the object, we leave the IC in its | 1464 ComputeStoreMonomorphic(lookup, strict_mode, receiver, name); |
| 1456 // current state. | 1465 if (code.is_null()) return; |
| 1457 PropertyType type = lookup->type(); | |
| 1458 | 1466 |
| 1459 // Compute the code stub for this store; used for rewriting to | 1467 PatchCache(state, strict_mode, receiver, name, code); |
| 1460 // monomorphic state and making sure that the code stub is in the | 1468 TRACE_IC("StoreIC", name, state, target()); |
| 1461 // stub cache. | 1469 } |
| 1470 |
| 1471 |
| 1472 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
| 1473 StrictModeFlag strict_mode, |
| 1474 Handle<JSObject> receiver, |
| 1475 Handle<String> name) { |
| 1462 Handle<JSObject> holder(lookup->holder()); | 1476 Handle<JSObject> holder(lookup->holder()); |
| 1463 Handle<Code> code; | 1477 switch (lookup->type()) { |
| 1464 switch (type) { | |
| 1465 case FIELD: | 1478 case FIELD: |
| 1466 code = isolate()->stub_cache()->ComputeStoreField( | 1479 return isolate()->stub_cache()->ComputeStoreField( |
| 1467 name, receiver, lookup->GetFieldIndex().field_index(), | 1480 name, receiver, lookup->GetFieldIndex().field_index(), |
| 1468 Handle<Map>::null(), strict_mode); | 1481 Handle<Map>::null(), strict_mode); |
| 1469 break; | |
| 1470 case NORMAL: | 1482 case NORMAL: |
| 1471 if (receiver->IsGlobalObject()) { | 1483 if (receiver->IsGlobalObject()) { |
| 1472 // The stub generated for the global object picks the value directly | 1484 // The stub generated for the global object picks the value directly |
| 1473 // from the property cell. So the property must be directly on the | 1485 // from the property cell. So the property must be directly on the |
| 1474 // global object. | 1486 // global object. |
| 1475 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1487 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 1476 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); | 1488 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
| 1477 code = isolate()->stub_cache()->ComputeStoreGlobal( | 1489 return isolate()->stub_cache()->ComputeStoreGlobal( |
| 1478 name, global, cell, strict_mode); | 1490 name, global, cell, strict_mode); |
| 1479 } else { | |
| 1480 if (!holder.is_identical_to(receiver)) return; | |
| 1481 code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | |
| 1482 } | 1491 } |
| 1483 break; | 1492 if (!holder.is_identical_to(receiver)) break; |
| 1493 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
| 1484 case CALLBACKS: { | 1494 case CALLBACKS: { |
| 1485 Handle<Object> callback(lookup->GetCallbackObject()); | 1495 Handle<Object> callback(lookup->GetCallbackObject()); |
| 1486 if (callback->IsAccessorInfo()) { | 1496 if (callback->IsAccessorInfo()) { |
| 1487 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback); | 1497 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback); |
| 1488 if (v8::ToCData<Address>(info->setter()) == 0) return; | 1498 if (v8::ToCData<Address>(info->setter()) == 0) break; |
| 1489 if (!holder->HasFastProperties()) return; | 1499 if (!holder->HasFastProperties()) break; |
| 1490 if (!info->IsCompatibleReceiver(*receiver)) return; | 1500 if (!info->IsCompatibleReceiver(*receiver)) break; |
| 1491 code = isolate()->stub_cache()->ComputeStoreCallback( | 1501 return isolate()->stub_cache()->ComputeStoreCallback( |
| 1492 name, receiver, holder, info, strict_mode); | 1502 name, receiver, holder, info, strict_mode); |
| 1493 } else if (callback->IsAccessorPair()) { | 1503 } else if (callback->IsAccessorPair()) { |
| 1494 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); | 1504 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); |
| 1495 if (!setter->IsJSFunction()) return; | 1505 if (!setter->IsJSFunction()) break; |
| 1496 if (holder->IsGlobalObject()) return; | 1506 if (holder->IsGlobalObject()) break; |
| 1497 if (!holder->HasFastProperties()) return; | 1507 if (!holder->HasFastProperties()) break; |
| 1498 code = isolate()->stub_cache()->ComputeStoreViaSetter( | 1508 return isolate()->stub_cache()->ComputeStoreViaSetter( |
| 1499 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1509 name, receiver, holder, Handle<JSFunction>::cast(setter), |
| 1500 strict_mode); | 1510 strict_mode); |
| 1501 } else { | |
| 1502 ASSERT(callback->IsForeign()); | |
| 1503 // No IC support for old-style native accessors. | |
| 1504 return; | |
| 1505 } | 1511 } |
| 1512 ASSERT(callback->IsForeign()); |
| 1513 // No IC support for old-style native accessors. |
| 1506 break; | 1514 break; |
| 1507 } | 1515 } |
| 1508 case INTERCEPTOR: | 1516 case INTERCEPTOR: |
| 1509 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1517 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1510 code = isolate()->stub_cache()->ComputeStoreInterceptor( | 1518 return isolate()->stub_cache()->ComputeStoreInterceptor( |
| 1511 name, receiver, strict_mode); | 1519 name, receiver, strict_mode); |
| 1520 case CONSTANT_FUNCTION: |
| 1512 break; | 1521 break; |
| 1513 case CONSTANT_FUNCTION: | |
| 1514 return; | |
| 1515 case TRANSITION: { | 1522 case TRANSITION: { |
| 1516 Handle<Map> transition(lookup->GetTransitionTarget()); | 1523 Handle<Map> transition(lookup->GetTransitionTarget()); |
| 1517 int descriptor = transition->LastAdded(); | 1524 int descriptor = transition->LastAdded(); |
| 1518 | 1525 |
| 1519 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1526 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1520 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1527 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1521 | 1528 |
| 1522 if (details.type() != FIELD || details.attributes() != NONE) return; | 1529 if (details.type() != FIELD || details.attributes() != NONE) break; |
| 1523 | 1530 |
| 1524 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1531 int field_index = target_descriptors->GetFieldIndex(descriptor); |
| 1525 code = isolate()->stub_cache()->ComputeStoreField( | 1532 return isolate()->stub_cache()->ComputeStoreField( |
| 1526 name, receiver, field_index, transition, strict_mode); | 1533 name, receiver, field_index, transition, strict_mode); |
| 1527 | |
| 1528 break; | |
| 1529 } | 1534 } |
| 1530 case NONEXISTENT: | 1535 case NONEXISTENT: |
| 1531 case HANDLER: | 1536 case HANDLER: |
| 1532 UNREACHABLE(); | 1537 UNREACHABLE(); |
| 1533 return; | |
| 1534 } | |
| 1535 | |
| 1536 // Patch the call site depending on the state of the cache. | |
| 1537 switch (state) { | |
| 1538 case UNINITIALIZED: | |
| 1539 case PREMONOMORPHIC: | |
| 1540 case MONOMORPHIC_PROTOTYPE_FAILURE: | |
| 1541 set_target(*code); | |
| 1542 break; | |
| 1543 case MONOMORPHIC: | |
| 1544 // Only move to megamorphic if the target changes. | |
| 1545 if (target() != *code) { | |
| 1546 // We are transitioning from monomorphic to megamorphic case. | |
| 1547 // Place the current monomorphic stub and stub compiled for | |
| 1548 // the receiver into stub cache. | |
| 1549 Map* map = target()->FindFirstMap(); | |
| 1550 if (map != NULL) { | |
| 1551 isolate()->stub_cache()->Set(*name, map, target()); | |
| 1552 } | |
| 1553 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | |
| 1554 set_target((strict_mode == kStrictMode) | |
| 1555 ? *megamorphic_stub_strict() | |
| 1556 : *megamorphic_stub()); | |
| 1557 } | |
| 1558 break; | |
| 1559 case MEGAMORPHIC: | |
| 1560 // Update the stub cache. | |
| 1561 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | |
| 1562 break; | |
| 1563 case DEBUG_STUB: | |
| 1564 break; | |
| 1565 case POLYMORPHIC: | |
| 1566 case GENERIC: | |
| 1567 UNREACHABLE(); | |
| 1568 break; | 1538 break; |
| 1569 } | 1539 } |
| 1570 | 1540 return Handle<Code>::null(); |
| 1571 TRACE_IC("StoreIC", name, state, target()); | |
| 1572 } | 1541 } |
| 1573 | 1542 |
| 1574 | 1543 |
| 1575 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1544 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
| 1576 StubKind stub_kind, | 1545 StubKind stub_kind, |
| 1577 StrictModeFlag strict_mode) { | 1546 StrictModeFlag strict_mode) { |
| 1578 State ic_state = target()->ic_state(); | 1547 State ic_state = target()->ic_state(); |
| 1579 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) | 1548 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) |
| 1580 ? ALLOW_JSARRAY_GROWTH | 1549 ? ALLOW_JSARRAY_GROWTH |
| 1581 : DO_NOT_ALLOW_JSARRAY_GROWTH; | 1550 : DO_NOT_ALLOW_JSARRAY_GROWTH; |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1797 } | 1766 } |
| 1798 | 1767 |
| 1799 TRACE_IC("KeyedStoreIC", key, state, target()); | 1768 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1800 | 1769 |
| 1801 // Set the property. | 1770 // Set the property. |
| 1802 return Runtime::SetObjectProperty( | 1771 return Runtime::SetObjectProperty( |
| 1803 isolate(), object , key, value, NONE, strict_mode); | 1772 isolate(), object , key, value, NONE, strict_mode); |
| 1804 } | 1773 } |
| 1805 | 1774 |
| 1806 | 1775 |
| 1807 void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup, | 1776 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
| 1808 State state, | 1777 StrictModeFlag strict_mode, |
| 1809 StrictModeFlag strict_mode, | 1778 Handle<JSObject> receiver, |
| 1810 Handle<JSObject> receiver, | 1779 Handle<String> name) { |
| 1811 Handle<String> name, | |
| 1812 Handle<Object> value) { | |
| 1813 ASSERT(!receiver->IsJSGlobalProxy()); | |
| 1814 ASSERT(StoreICableLookup(lookup)); | |
| 1815 ASSERT(lookup->IsFound()); | |
| 1816 | |
| 1817 // These are not cacheable, so we never see such LookupResults here. | |
| 1818 ASSERT(!lookup->IsHandler()); | |
| 1819 | |
| 1820 // If the property has a non-field type allowing map transitions | 1780 // If the property has a non-field type allowing map transitions |
| 1821 // where there is extra room in the object, we leave the IC in its | 1781 // where there is extra room in the object, we leave the IC in its |
| 1822 // current state. | 1782 // current state. |
| 1823 PropertyType type = lookup->type(); | 1783 switch (lookup->type()) { |
| 1824 | |
| 1825 // Compute the code stub for this store; used for rewriting to | |
| 1826 // monomorphic state and making sure that the code stub is in the | |
| 1827 // stub cache. | |
| 1828 Handle<Code> code; | |
| 1829 | |
| 1830 switch (type) { | |
| 1831 case FIELD: | 1784 case FIELD: |
| 1832 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1785 return isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1833 name, receiver, lookup->GetFieldIndex().field_index(), | 1786 name, receiver, lookup->GetFieldIndex().field_index(), |
| 1834 Handle<Map>::null(), strict_mode); | 1787 Handle<Map>::null(), strict_mode); |
| 1835 break; | |
| 1836 case TRANSITION: { | 1788 case TRANSITION: { |
| 1837 Handle<Map> transition(lookup->GetTransitionTarget()); | 1789 Handle<Map> transition(lookup->GetTransitionTarget()); |
| 1838 int descriptor = transition->LastAdded(); | 1790 int descriptor = transition->LastAdded(); |
| 1839 | 1791 |
| 1840 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1792 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1841 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1793 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1842 | 1794 |
| 1843 if (details.type() == FIELD && details.attributes() == NONE) { | 1795 if (details.type() == FIELD && details.attributes() == NONE) { |
| 1844 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1796 int field_index = target_descriptors->GetFieldIndex(descriptor); |
| 1845 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1797 return isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1846 name, receiver, field_index, transition, strict_mode); | 1798 name, receiver, field_index, transition, strict_mode); |
| 1847 break; | |
| 1848 } | 1799 } |
| 1849 // fall through. | 1800 // fall through. |
| 1850 } | 1801 } |
| 1851 case NORMAL: | 1802 case NORMAL: |
| 1852 case CONSTANT_FUNCTION: | 1803 case CONSTANT_FUNCTION: |
| 1853 case CALLBACKS: | 1804 case CALLBACKS: |
| 1854 case INTERCEPTOR: | 1805 case INTERCEPTOR: |
| 1855 // Always rewrite to the generic case so that we do not | 1806 // Always rewrite to the generic case so that we do not |
| 1856 // repeatedly try to rewrite. | 1807 // repeatedly try to rewrite. |
| 1857 code = (strict_mode == kStrictMode) | 1808 return (strict_mode == kStrictMode) |
| 1858 ? generic_stub_strict() | 1809 ? generic_stub_strict() |
| 1859 : generic_stub(); | 1810 : generic_stub(); |
| 1860 break; | |
| 1861 case HANDLER: | 1811 case HANDLER: |
| 1862 case NONEXISTENT: | 1812 case NONEXISTENT: |
| 1863 UNREACHABLE(); | 1813 UNREACHABLE(); |
| 1864 return; | |
| 1865 } | |
| 1866 | |
| 1867 ASSERT(!code.is_null()); | |
| 1868 | |
| 1869 // Patch the call site depending on the state of the cache. | |
| 1870 switch (state) { | |
| 1871 case UNINITIALIZED: | |
| 1872 case PREMONOMORPHIC: | |
| 1873 case POLYMORPHIC: | |
| 1874 set_target(*code); | |
| 1875 break; | |
| 1876 case MONOMORPHIC: | |
| 1877 // Only move to megamorphic if the target changes. | |
| 1878 if (target() != *code) { | |
| 1879 set_target((strict_mode == kStrictMode) | |
| 1880 ? *megamorphic_stub_strict() | |
| 1881 : *megamorphic_stub()); | |
| 1882 } | |
| 1883 break; | |
| 1884 case MEGAMORPHIC: | |
| 1885 case GENERIC: | |
| 1886 case DEBUG_STUB: | |
| 1887 break; | |
| 1888 case MONOMORPHIC_PROTOTYPE_FAILURE: | |
| 1889 UNREACHABLE(); | |
| 1890 break; | 1814 break; |
| 1891 } | 1815 } |
| 1892 | 1816 return Handle<Code>::null(); |
| 1893 TRACE_IC("KeyedStoreIC", name, state, target()); | |
| 1894 } | 1817 } |
| 1895 | 1818 |
| 1896 | 1819 |
| 1897 #undef TRACE_IC | 1820 #undef TRACE_IC |
| 1898 | 1821 |
| 1899 | 1822 |
| 1900 // ---------------------------------------------------------------------------- | 1823 // ---------------------------------------------------------------------------- |
| 1901 // Static IC stub generators. | 1824 // Static IC stub generators. |
| 1902 // | 1825 // |
| 1903 | 1826 |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2635 #undef ADDR | 2558 #undef ADDR |
| 2636 }; | 2559 }; |
| 2637 | 2560 |
| 2638 | 2561 |
| 2639 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2562 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2640 return IC_utilities[id]; | 2563 return IC_utilities[id]; |
| 2641 } | 2564 } |
| 2642 | 2565 |
| 2643 | 2566 |
| 2644 } } // namespace v8::internal | 2567 } } // namespace v8::internal |
| OLD | NEW |