OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 target->extra_ic_state()); | 577 target->extra_ic_state()); |
578 SetTargetAtAddress(address, code, constant_pool); | 578 SetTargetAtAddress(address, code, constant_pool); |
579 } | 579 } |
580 | 580 |
581 | 581 |
582 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 582 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
583 ConstantPoolArray* constant_pool) { | 583 ConstantPoolArray* constant_pool) { |
584 if (IsCleared(target)) return; | 584 if (IsCleared(target)) return; |
585 SetTargetAtAddress( | 585 SetTargetAtAddress( |
586 address, *pre_monomorphic_stub( | 586 address, *pre_monomorphic_stub( |
587 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), | 587 isolate, StoreIC::GetLanguageMode(target->extra_ic_state())), |
588 constant_pool); | 588 constant_pool); |
589 } | 589 } |
590 | 590 |
591 | 591 |
592 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, | 592 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, |
593 ConstantPoolArray* constant_pool) { | 593 ConstantPoolArray* constant_pool) { |
594 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); | 594 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); |
595 CompareICStub stub(target->stub_key(), isolate); | 595 CompareICStub stub(target->stub_key(), isolate); |
596 // Only clear CompareICs that can retain objects. | 596 // Only clear CompareICs that can retain objects. |
597 if (stub.state() != CompareICState::KNOWN_OBJECT) return; | 597 if (stub.state() != CompareICState::KNOWN_OBJECT) return; |
(...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 cache_holder); | 1209 cache_holder); |
1210 return compiler.CompileLoadCallback(lookup->name(), info); | 1210 return compiler.CompileLoadCallback(lookup->name(), info); |
1211 } | 1211 } |
1212 if (accessors->IsAccessorPair()) { | 1212 if (accessors->IsAccessorPair()) { |
1213 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 1213 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
1214 isolate()); | 1214 isolate()); |
1215 if (!getter->IsJSFunction()) break; | 1215 if (!getter->IsJSFunction()) break; |
1216 if (!holder->HasFastProperties()) break; | 1216 if (!holder->HasFastProperties()) break; |
1217 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1217 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
1218 if (!receiver->IsJSObject() && !function->IsBuiltin() && | 1218 if (!receiver->IsJSObject() && !function->IsBuiltin() && |
1219 function->shared()->strict_mode() == SLOPPY) { | 1219 is_sloppy(function->shared()->language_mode())) { |
1220 // Calling sloppy non-builtins with a value as the receiver | 1220 // Calling sloppy non-builtins with a value as the receiver |
1221 // requires boxing. | 1221 // requires boxing. |
1222 break; | 1222 break; |
1223 } | 1223 } |
1224 CallOptimization call_optimization(function); | 1224 CallOptimization call_optimization(function); |
1225 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1225 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
1226 cache_holder); | 1226 cache_holder); |
1227 if (call_optimization.is_simple_api_call() && | 1227 if (call_optimization.is_simple_api_call() && |
1228 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1228 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
1229 return compiler.CompileLoadCallback(lookup->name(), call_optimization, | 1229 return compiler.CompileLoadCallback(lookup->name(), call_optimization, |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1533 return value; | 1533 return value; |
1534 } | 1534 } |
1535 } | 1535 } |
1536 | 1536 |
1537 // TODO(verwaest): Let SetProperty do the migration, since storing a property | 1537 // TODO(verwaest): Let SetProperty do the migration, since storing a property |
1538 // might deprecate the current map again, if value does not fit. | 1538 // might deprecate the current map again, if value does not fit. |
1539 if (MigrateDeprecated(object) || object->IsJSProxy()) { | 1539 if (MigrateDeprecated(object) || object->IsJSProxy()) { |
1540 Handle<Object> result; | 1540 Handle<Object> result; |
1541 ASSIGN_RETURN_ON_EXCEPTION( | 1541 ASSIGN_RETURN_ON_EXCEPTION( |
1542 isolate(), result, | 1542 isolate(), result, |
1543 Object::SetProperty(object, name, value, strict_mode()), Object); | 1543 Object::SetProperty(object, name, value, language_mode()), Object); |
1544 return result; | 1544 return result; |
1545 } | 1545 } |
1546 | 1546 |
1547 // If the object is undefined or null it's illegal to try to set any | 1547 // If the object is undefined or null it's illegal to try to set any |
1548 // properties on it; throw a TypeError in that case. | 1548 // properties on it; throw a TypeError in that case. |
1549 if (object->IsUndefined() || object->IsNull()) { | 1549 if (object->IsUndefined() || object->IsNull()) { |
1550 return TypeError("non_object_property_store", object, name); | 1550 return TypeError("non_object_property_store", object, name); |
1551 } | 1551 } |
1552 | 1552 |
1553 // Check if the given name is an array index. | 1553 // Check if the given name is an array index. |
1554 uint32_t index; | 1554 uint32_t index; |
1555 if (name->AsArrayIndex(&index)) { | 1555 if (name->AsArrayIndex(&index)) { |
1556 // Ignore other stores where the receiver is not a JSObject. | 1556 // Ignore other stores where the receiver is not a JSObject. |
1557 // TODO(1475): Must check prototype chains of object wrappers. | 1557 // TODO(1475): Must check prototype chains of object wrappers. |
1558 if (!object->IsJSObject()) return value; | 1558 if (!object->IsJSObject()) return value; |
1559 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1559 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1560 | 1560 |
1561 Handle<Object> result; | 1561 Handle<Object> result; |
1562 ASSIGN_RETURN_ON_EXCEPTION( | 1562 ASSIGN_RETURN_ON_EXCEPTION( |
1563 isolate(), result, | 1563 isolate(), result, |
1564 JSObject::SetElement(receiver, index, value, NONE, strict_mode()), | 1564 JSObject::SetElement(receiver, index, value, NONE, language_mode()), |
1565 Object); | 1565 Object); |
1566 return value; | 1566 return value; |
1567 } | 1567 } |
1568 | 1568 |
1569 // Observed objects are always modified through the runtime. | 1569 // Observed objects are always modified through the runtime. |
1570 if (object->IsHeapObject() && | 1570 if (object->IsHeapObject() && |
1571 Handle<HeapObject>::cast(object)->map()->is_observed()) { | 1571 Handle<HeapObject>::cast(object)->map()->is_observed()) { |
1572 Handle<Object> result; | 1572 Handle<Object> result; |
1573 ASSIGN_RETURN_ON_EXCEPTION( | 1573 ASSIGN_RETURN_ON_EXCEPTION( |
1574 isolate(), result, | 1574 isolate(), result, |
1575 Object::SetProperty(object, name, value, strict_mode(), store_mode), | 1575 Object::SetProperty(object, name, value, language_mode(), store_mode), |
1576 Object); | 1576 Object); |
1577 return result; | 1577 return result; |
1578 } | 1578 } |
1579 | 1579 |
1580 LookupIterator it(object, name); | 1580 LookupIterator it(object, name); |
1581 if (FLAG_use_ic) UpdateCaches(&it, value, store_mode); | 1581 if (FLAG_use_ic) UpdateCaches(&it, value, store_mode); |
1582 | 1582 |
1583 // Set the property. | 1583 // Set the property. |
1584 Handle<Object> result; | 1584 Handle<Object> result; |
1585 ASSIGN_RETURN_ON_EXCEPTION( | 1585 ASSIGN_RETURN_ON_EXCEPTION( |
1586 isolate(), result, | 1586 isolate(), result, |
1587 Object::SetProperty(&it, value, strict_mode(), store_mode), Object); | 1587 Object::SetProperty(&it, value, language_mode(), store_mode), Object); |
1588 return result; | 1588 return result; |
1589 } | 1589 } |
1590 | 1590 |
1591 | 1591 |
1592 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc, | 1592 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc, |
1593 CallICState::CallType call_type) { | 1593 CallICState::CallType call_type) { |
1594 CallICTrampolineStub stub(isolate, CallICState(argc, call_type)); | 1594 CallICTrampolineStub stub(isolate, CallICState(argc, call_type)); |
1595 Handle<Code> code = stub.GetCode(); | 1595 Handle<Code> code = stub.GetCode(); |
1596 return code; | 1596 return code; |
1597 } | 1597 } |
1598 | 1598 |
1599 | 1599 |
1600 Handle<Code> CallIC::initialize_stub_in_optimized_code( | 1600 Handle<Code> CallIC::initialize_stub_in_optimized_code( |
1601 Isolate* isolate, int argc, CallICState::CallType call_type) { | 1601 Isolate* isolate, int argc, CallICState::CallType call_type) { |
1602 CallICStub stub(isolate, CallICState(argc, call_type)); | 1602 CallICStub stub(isolate, CallICState(argc, call_type)); |
1603 Handle<Code> code = stub.GetCode(); | 1603 Handle<Code> code = stub.GetCode(); |
1604 return code; | 1604 return code; |
1605 } | 1605 } |
1606 | 1606 |
1607 | 1607 |
1608 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1608 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
1609 StrictMode strict_mode) { | 1609 LanguageMode language_mode) { |
1610 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1610 ExtraICState extra_state = ComputeExtraICState(language_mode); |
1611 Handle<Code> ic = | 1611 Handle<Code> ic = |
1612 PropertyICCompiler::ComputeStore(isolate, UNINITIALIZED, extra_state); | 1612 PropertyICCompiler::ComputeStore(isolate, UNINITIALIZED, extra_state); |
1613 return ic; | 1613 return ic; |
1614 } | 1614 } |
1615 | 1615 |
1616 | 1616 |
1617 Handle<Code> StoreIC::megamorphic_stub() { | 1617 Handle<Code> StoreIC::megamorphic_stub() { |
1618 if (kind() == Code::STORE_IC) { | 1618 if (kind() == Code::STORE_IC) { |
1619 return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC, | 1619 return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC, |
1620 extra_ic_state()); | 1620 extra_ic_state()); |
1621 } else { | 1621 } else { |
1622 DCHECK(kind() == Code::KEYED_STORE_IC); | 1622 DCHECK(kind() == Code::KEYED_STORE_IC); |
1623 if (strict_mode() == STRICT) { | 1623 if (is_strict(language_mode())) { |
1624 return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); | 1624 return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); |
1625 } else { | 1625 } else { |
1626 return isolate()->builtins()->KeyedStoreIC_Megamorphic(); | 1626 return isolate()->builtins()->KeyedStoreIC_Megamorphic(); |
1627 } | 1627 } |
1628 } | 1628 } |
1629 } | 1629 } |
1630 | 1630 |
1631 | 1631 |
1632 Handle<Code> StoreIC::slow_stub() const { | 1632 Handle<Code> StoreIC::slow_stub() const { |
1633 if (kind() == Code::STORE_IC) { | 1633 if (kind() == Code::STORE_IC) { |
1634 return isolate()->builtins()->StoreIC_Slow(); | 1634 return isolate()->builtins()->StoreIC_Slow(); |
1635 } else { | 1635 } else { |
1636 DCHECK(kind() == Code::KEYED_STORE_IC); | 1636 DCHECK(kind() == Code::KEYED_STORE_IC); |
1637 return isolate()->builtins()->KeyedStoreIC_Slow(); | 1637 return isolate()->builtins()->KeyedStoreIC_Slow(); |
1638 } | 1638 } |
1639 } | 1639 } |
1640 | 1640 |
1641 | 1641 |
1642 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, | 1642 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, |
1643 StrictMode strict_mode) { | 1643 LanguageMode language_mode) { |
1644 ExtraICState state = ComputeExtraICState(strict_mode); | 1644 ExtraICState state = ComputeExtraICState(language_mode); |
1645 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); | 1645 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); |
1646 } | 1646 } |
1647 | 1647 |
1648 | 1648 |
1649 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1649 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
1650 JSReceiver::StoreFromKeyed store_mode) { | 1650 JSReceiver::StoreFromKeyed store_mode) { |
1651 if (state() == UNINITIALIZED) { | 1651 if (state() == UNINITIALIZED) { |
1652 // This is the first time we execute this inline cache. Set the target to | 1652 // This is the first time we execute this inline cache. Set the target to |
1653 // the pre monomorphic stub to delay setting the monomorphic state. | 1653 // the pre monomorphic stub to delay setting the monomorphic state. |
1654 set_target(*pre_monomorphic_stub()); | 1654 set_target(*pre_monomorphic_stub()); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 } | 1806 } |
1807 | 1807 |
1808 Handle<Map> receiver_map(receiver->map(), isolate()); | 1808 Handle<Map> receiver_map(receiver->map(), isolate()); |
1809 MapHandleList target_receiver_maps; | 1809 MapHandleList target_receiver_maps; |
1810 TargetMaps(&target_receiver_maps); | 1810 TargetMaps(&target_receiver_maps); |
1811 if (target_receiver_maps.length() == 0) { | 1811 if (target_receiver_maps.length() == 0) { |
1812 Handle<Map> monomorphic_map = | 1812 Handle<Map> monomorphic_map = |
1813 ComputeTransitionedMap(receiver_map, store_mode); | 1813 ComputeTransitionedMap(receiver_map, store_mode); |
1814 store_mode = GetNonTransitioningStoreMode(store_mode); | 1814 store_mode = GetNonTransitioningStoreMode(store_mode); |
1815 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1815 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1816 monomorphic_map, strict_mode(), store_mode); | 1816 monomorphic_map, language_mode(), store_mode); |
1817 } | 1817 } |
1818 | 1818 |
1819 // There are several special cases where an IC that is MONOMORPHIC can still | 1819 // There are several special cases where an IC that is MONOMORPHIC can still |
1820 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1820 // transition to a different GetNonTransitioningStoreMode IC that handles a |
1821 // superset of the original IC. Handle those here if the receiver map hasn't | 1821 // superset of the original IC. Handle those here if the receiver map hasn't |
1822 // changed or it has transitioned to a more general kind. | 1822 // changed or it has transitioned to a more general kind. |
1823 KeyedAccessStoreMode old_store_mode = | 1823 KeyedAccessStoreMode old_store_mode = |
1824 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1824 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
1825 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1825 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
1826 if (state() == MONOMORPHIC) { | 1826 if (state() == MONOMORPHIC) { |
1827 Handle<Map> transitioned_receiver_map = receiver_map; | 1827 Handle<Map> transitioned_receiver_map = receiver_map; |
1828 if (IsTransitionStoreMode(store_mode)) { | 1828 if (IsTransitionStoreMode(store_mode)) { |
1829 transitioned_receiver_map = | 1829 transitioned_receiver_map = |
1830 ComputeTransitionedMap(receiver_map, store_mode); | 1830 ComputeTransitionedMap(receiver_map, store_mode); |
1831 } | 1831 } |
1832 if ((receiver_map.is_identical_to(previous_receiver_map) && | 1832 if ((receiver_map.is_identical_to(previous_receiver_map) && |
1833 IsTransitionStoreMode(store_mode)) || | 1833 IsTransitionStoreMode(store_mode)) || |
1834 IsTransitionOfMonomorphicTarget(*previous_receiver_map, | 1834 IsTransitionOfMonomorphicTarget(*previous_receiver_map, |
1835 *transitioned_receiver_map)) { | 1835 *transitioned_receiver_map)) { |
1836 // If the "old" and "new" maps are in the same elements map family, or | 1836 // If the "old" and "new" maps are in the same elements map family, or |
1837 // if they at least come from the same origin for a transitioning store, | 1837 // if they at least come from the same origin for a transitioning store, |
1838 // stay MONOMORPHIC and use the map for the most generic ElementsKind. | 1838 // stay MONOMORPHIC and use the map for the most generic ElementsKind. |
1839 store_mode = GetNonTransitioningStoreMode(store_mode); | 1839 store_mode = GetNonTransitioningStoreMode(store_mode); |
1840 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1840 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1841 transitioned_receiver_map, strict_mode(), store_mode); | 1841 transitioned_receiver_map, language_mode(), store_mode); |
1842 } else if (*previous_receiver_map == receiver->map() && | 1842 } else if (*previous_receiver_map == receiver->map() && |
1843 old_store_mode == STANDARD_STORE && | 1843 old_store_mode == STANDARD_STORE && |
1844 (store_mode == STORE_AND_GROW_NO_TRANSITION || | 1844 (store_mode == STORE_AND_GROW_NO_TRANSITION || |
1845 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1845 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1846 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1846 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1847 // A "normal" IC that handles stores can switch to a version that can | 1847 // A "normal" IC that handles stores can switch to a version that can |
1848 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1848 // grow at the end of the array, handle OOB accesses or copy COW arrays |
1849 // and still stay MONOMORPHIC. | 1849 // and still stay MONOMORPHIC. |
1850 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1850 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1851 receiver_map, strict_mode(), store_mode); | 1851 receiver_map, language_mode(), store_mode); |
1852 } | 1852 } |
1853 } | 1853 } |
1854 | 1854 |
1855 DCHECK(state() != GENERIC); | 1855 DCHECK(state() != GENERIC); |
1856 | 1856 |
1857 bool map_added = | 1857 bool map_added = |
1858 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1858 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
1859 | 1859 |
1860 if (IsTransitionStoreMode(store_mode)) { | 1860 if (IsTransitionStoreMode(store_mode)) { |
1861 Handle<Map> transitioned_receiver_map = | 1861 Handle<Map> transitioned_receiver_map = |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1902 } | 1902 } |
1903 if (external_arrays != 0 && | 1903 if (external_arrays != 0 && |
1904 external_arrays != target_receiver_maps.length()) { | 1904 external_arrays != target_receiver_maps.length()) { |
1905 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 1905 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
1906 "unsupported combination of external and normal arrays"); | 1906 "unsupported combination of external and normal arrays"); |
1907 return megamorphic_stub(); | 1907 return megamorphic_stub(); |
1908 } | 1908 } |
1909 } | 1909 } |
1910 | 1910 |
1911 return PropertyICCompiler::ComputeKeyedStorePolymorphic( | 1911 return PropertyICCompiler::ComputeKeyedStorePolymorphic( |
1912 &target_receiver_maps, store_mode, strict_mode()); | 1912 &target_receiver_maps, store_mode, language_mode()); |
1913 } | 1913 } |
1914 | 1914 |
1915 | 1915 |
1916 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 1916 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
1917 Handle<Map> map, KeyedAccessStoreMode store_mode) { | 1917 Handle<Map> map, KeyedAccessStoreMode store_mode) { |
1918 switch (store_mode) { | 1918 switch (store_mode) { |
1919 case STORE_TRANSITION_SMI_TO_OBJECT: | 1919 case STORE_TRANSITION_SMI_TO_OBJECT: |
1920 case STORE_TRANSITION_DOUBLE_TO_OBJECT: | 1920 case STORE_TRANSITION_DOUBLE_TO_OBJECT: |
1921 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: | 1921 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: |
1922 case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT: | 1922 case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT: |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 | 2032 |
2033 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, | 2033 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
2034 Handle<Object> key, | 2034 Handle<Object> key, |
2035 Handle<Object> value) { | 2035 Handle<Object> value) { |
2036 // TODO(verwaest): Let SetProperty do the migration, since storing a property | 2036 // TODO(verwaest): Let SetProperty do the migration, since storing a property |
2037 // might deprecate the current map again, if value does not fit. | 2037 // might deprecate the current map again, if value does not fit. |
2038 if (MigrateDeprecated(object)) { | 2038 if (MigrateDeprecated(object)) { |
2039 Handle<Object> result; | 2039 Handle<Object> result; |
2040 ASSIGN_RETURN_ON_EXCEPTION( | 2040 ASSIGN_RETURN_ON_EXCEPTION( |
2041 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key, | 2041 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key, |
2042 value, strict_mode()), | 2042 value, language_mode()), |
2043 Object); | 2043 Object); |
2044 return result; | 2044 return result; |
2045 } | 2045 } |
2046 | 2046 |
2047 // Check for non-string values that can be converted into an | 2047 // Check for non-string values that can be converted into an |
2048 // internalized string directly or is representable as a smi. | 2048 // internalized string directly or is representable as a smi. |
2049 key = TryConvertKey(key, isolate()); | 2049 key = TryConvertKey(key, isolate()); |
2050 | 2050 |
2051 Handle<Object> store_handle; | 2051 Handle<Object> store_handle; |
2052 Handle<Code> stub = megamorphic_stub(); | 2052 Handle<Code> stub = megamorphic_stub(); |
(...skipping 29 matching lines...) Expand all Loading... |
2082 } | 2082 } |
2083 | 2083 |
2084 if (use_ic) { | 2084 if (use_ic) { |
2085 DCHECK(!object->IsAccessCheckNeeded()); | 2085 DCHECK(!object->IsAccessCheckNeeded()); |
2086 | 2086 |
2087 if (object->IsJSObject()) { | 2087 if (object->IsJSObject()) { |
2088 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2088 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
2089 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); | 2089 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); |
2090 if (receiver->elements()->map() == | 2090 if (receiver->elements()->map() == |
2091 isolate()->heap()->sloppy_arguments_elements_map()) { | 2091 isolate()->heap()->sloppy_arguments_elements_map()) { |
2092 if (strict_mode() == SLOPPY) { | 2092 if (is_sloppy(language_mode())) { |
2093 stub = sloppy_arguments_stub(); | 2093 stub = sloppy_arguments_stub(); |
2094 } else { | 2094 } else { |
2095 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); | 2095 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
2096 } | 2096 } |
2097 } else if (key_is_smi_like && | 2097 } else if (key_is_smi_like && |
2098 !(target().is_identical_to(sloppy_arguments_stub()))) { | 2098 !(target().is_identical_to(sloppy_arguments_stub()))) { |
2099 // We should go generic if receiver isn't a dictionary, but our | 2099 // We should go generic if receiver isn't a dictionary, but our |
2100 // prototype chain does have dictionary elements. This ensures that | 2100 // prototype chain does have dictionary elements. This ensures that |
2101 // other non-dictionary receivers in the polymorphic case benefit | 2101 // other non-dictionary receivers in the polymorphic case benefit |
2102 // from fast path keyed stores. | 2102 // from fast path keyed stores. |
2103 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 2103 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
2104 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2104 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
2105 stub = StoreElementStub(receiver, store_mode); | 2105 stub = StoreElementStub(receiver, store_mode); |
2106 } else { | 2106 } else { |
2107 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); | 2107 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); |
2108 } | 2108 } |
2109 } else { | 2109 } else { |
2110 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); | 2110 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
2111 } | 2111 } |
2112 } else { | 2112 } else { |
2113 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); | 2113 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
2114 } | 2114 } |
2115 } | 2115 } |
2116 | 2116 |
2117 if (store_handle.is_null()) { | 2117 if (store_handle.is_null()) { |
2118 ASSIGN_RETURN_ON_EXCEPTION( | 2118 ASSIGN_RETURN_ON_EXCEPTION( |
2119 isolate(), store_handle, | 2119 isolate(), store_handle, |
2120 Runtime::SetObjectProperty(isolate(), object, key, value, | 2120 Runtime::SetObjectProperty(isolate(), object, key, value, |
2121 strict_mode()), | 2121 language_mode()), |
2122 Object); | 2122 Object); |
2123 } | 2123 } |
2124 | 2124 |
2125 DCHECK(!is_target_set()); | 2125 DCHECK(!is_target_set()); |
2126 Code* megamorphic = *megamorphic_stub(); | 2126 Code* megamorphic = *megamorphic_stub(); |
2127 if (*stub == megamorphic) { | 2127 if (*stub == megamorphic) { |
2128 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 2128 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
2129 } | 2129 } |
2130 if (*stub == *slow_stub()) { | 2130 if (*stub == *slow_stub()) { |
2131 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); | 2131 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2441 } | 2441 } |
2442 | 2442 |
2443 | 2443 |
2444 RUNTIME_FUNCTION(StoreIC_Slow) { | 2444 RUNTIME_FUNCTION(StoreIC_Slow) { |
2445 HandleScope scope(isolate); | 2445 HandleScope scope(isolate); |
2446 DCHECK(args.length() == 3); | 2446 DCHECK(args.length() == 3); |
2447 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2447 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2448 Handle<Object> object = args.at<Object>(0); | 2448 Handle<Object> object = args.at<Object>(0); |
2449 Handle<Object> key = args.at<Object>(1); | 2449 Handle<Object> key = args.at<Object>(1); |
2450 Handle<Object> value = args.at<Object>(2); | 2450 Handle<Object> value = args.at<Object>(2); |
2451 StrictMode strict_mode = ic.strict_mode(); | 2451 LanguageMode language_mode = ic.language_mode(); |
2452 Handle<Object> result; | 2452 Handle<Object> result; |
2453 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2453 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2454 isolate, result, | 2454 isolate, result, |
2455 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode)); | 2455 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
2456 return *result; | 2456 return *result; |
2457 } | 2457 } |
2458 | 2458 |
2459 | 2459 |
2460 RUNTIME_FUNCTION(KeyedStoreIC_Slow) { | 2460 RUNTIME_FUNCTION(KeyedStoreIC_Slow) { |
2461 HandleScope scope(isolate); | 2461 HandleScope scope(isolate); |
2462 DCHECK(args.length() == 3); | 2462 DCHECK(args.length() == 3); |
2463 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2463 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2464 Handle<Object> object = args.at<Object>(0); | 2464 Handle<Object> object = args.at<Object>(0); |
2465 Handle<Object> key = args.at<Object>(1); | 2465 Handle<Object> key = args.at<Object>(1); |
2466 Handle<Object> value = args.at<Object>(2); | 2466 Handle<Object> value = args.at<Object>(2); |
2467 StrictMode strict_mode = ic.strict_mode(); | 2467 LanguageMode language_mode = ic.language_mode(); |
2468 Handle<Object> result; | 2468 Handle<Object> result; |
2469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2470 isolate, result, | 2470 isolate, result, |
2471 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode)); | 2471 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
2472 return *result; | 2472 return *result; |
2473 } | 2473 } |
2474 | 2474 |
2475 | 2475 |
2476 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) { | 2476 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) { |
2477 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2477 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2478 HandleScope scope(isolate); | 2478 HandleScope scope(isolate); |
2479 DCHECK(args.length() == 4); | 2479 DCHECK(args.length() == 4); |
2480 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2480 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2481 Handle<Object> value = args.at<Object>(0); | 2481 Handle<Object> value = args.at<Object>(0); |
2482 Handle<Map> map = args.at<Map>(1); | 2482 Handle<Map> map = args.at<Map>(1); |
2483 Handle<Object> key = args.at<Object>(2); | 2483 Handle<Object> key = args.at<Object>(2); |
2484 Handle<Object> object = args.at<Object>(3); | 2484 Handle<Object> object = args.at<Object>(3); |
2485 StrictMode strict_mode = ic.strict_mode(); | 2485 LanguageMode language_mode = ic.language_mode(); |
2486 if (object->IsJSObject()) { | 2486 if (object->IsJSObject()) { |
2487 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), | 2487 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), |
2488 map->elements_kind()); | 2488 map->elements_kind()); |
2489 } | 2489 } |
2490 Handle<Object> result; | 2490 Handle<Object> result; |
2491 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2491 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2492 isolate, result, | 2492 isolate, result, |
2493 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode)); | 2493 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
2494 return *result; | 2494 return *result; |
2495 } | 2495 } |
2496 | 2496 |
2497 | 2497 |
2498 MaybeHandle<Object> BinaryOpIC::Transition( | 2498 MaybeHandle<Object> BinaryOpIC::Transition( |
2499 Handle<AllocationSite> allocation_site, Handle<Object> left, | 2499 Handle<AllocationSite> allocation_site, Handle<Object> left, |
2500 Handle<Object> right) { | 2500 Handle<Object> right) { |
2501 BinaryOpICState state(isolate(), target()->extra_ic_state()); | 2501 BinaryOpICState state(isolate(), target()->extra_ic_state()); |
2502 | 2502 |
2503 // Compute the actual result using the builtin for the binary operation. | 2503 // Compute the actual result using the builtin for the binary operation. |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2934 Handle<JSObject>::cast(current)->HasNamedInterceptor()) { | 2934 Handle<JSObject>::cast(current)->HasNamedInterceptor()) { |
2935 found = true; | 2935 found = true; |
2936 break; | 2936 break; |
2937 } | 2937 } |
2938 } | 2938 } |
2939 DCHECK(found); | 2939 DCHECK(found); |
2940 #endif | 2940 #endif |
2941 Handle<Object> result; | 2941 Handle<Object> result; |
2942 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2942 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2943 isolate, result, | 2943 isolate, result, |
2944 JSObject::SetProperty(receiver, name, value, ic.strict_mode())); | 2944 JSObject::SetProperty(receiver, name, value, ic.language_mode())); |
2945 return *result; | 2945 return *result; |
2946 } | 2946 } |
2947 | 2947 |
2948 | 2948 |
2949 RUNTIME_FUNCTION(LoadElementWithInterceptor) { | 2949 RUNTIME_FUNCTION(LoadElementWithInterceptor) { |
2950 HandleScope scope(isolate); | 2950 HandleScope scope(isolate); |
2951 Handle<JSObject> receiver = args.at<JSObject>(0); | 2951 Handle<JSObject> receiver = args.at<JSObject>(0); |
2952 DCHECK(args.smi_at(1) >= 0); | 2952 DCHECK(args.smi_at(1) >= 0); |
2953 uint32_t index = args.smi_at(1); | 2953 uint32_t index = args.smi_at(1); |
2954 Handle<Object> result; | 2954 Handle<Object> result; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3002 static const Address IC_utilities[] = { | 3002 static const Address IC_utilities[] = { |
3003 #define ADDR(name) FUNCTION_ADDR(name), | 3003 #define ADDR(name) FUNCTION_ADDR(name), |
3004 IC_UTIL_LIST(ADDR) NULL | 3004 IC_UTIL_LIST(ADDR) NULL |
3005 #undef ADDR | 3005 #undef ADDR |
3006 }; | 3006 }; |
3007 | 3007 |
3008 | 3008 |
3009 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3009 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
3010 } | 3010 } |
3011 } // namespace v8::internal | 3011 } // namespace v8::internal |
OLD | NEW |