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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 do { \ | 69 do { \ |
70 if (FLAG_trace_ic) { \ | 70 if (FLAG_trace_ic) { \ |
71 PrintF("[%s patching generic stub in ", type); \ | 71 PrintF("[%s patching generic stub in ", type); \ |
72 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ | 72 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ |
73 PrintF(" (%s)]\n", reason); \ | 73 PrintF(" (%s)]\n", reason); \ |
74 } \ | 74 } \ |
75 } while (false) | 75 } while (false) |
76 | 76 |
77 #else | 77 #else |
78 | 78 |
79 #define TRACE_GENERIC_IC(isolate, type, reason) | 79 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
| 80 do { \ |
| 81 if (FLAG_trace_ic) { \ |
| 82 PrintF("[%s patching generic stub in ", type); \ |
| 83 PrintF("(see below) (%s)]\n", reason); \ |
| 84 } \ |
| 85 } while (false) |
80 | 86 |
81 #endif // DEBUG | 87 #endif // DEBUG |
82 | 88 |
83 | 89 |
84 void IC::TraceIC(const char* type, Handle<Object> name) { | 90 void IC::TraceIC(const char* type, Handle<Object> name) { |
85 if (FLAG_trace_ic) { | 91 if (FLAG_trace_ic) { |
86 Code* new_target = raw_target(); | 92 Code* new_target = raw_target(); |
87 State new_state = new_target->ic_state(); | 93 State new_state = new_target->ic_state(); |
88 TraceIC(type, name, state(), new_state); | 94 TraceIC(type, name, state(), new_state); |
89 } | 95 } |
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1139 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
1134 } | 1140 } |
1135 | 1141 |
1136 DCHECK(state() != GENERIC); | 1142 DCHECK(state() != GENERIC); |
1137 | 1143 |
1138 // Determine the list of receiver maps that this call site has seen, | 1144 // Determine the list of receiver maps that this call site has seen, |
1139 // adding the map that was just encountered. | 1145 // adding the map that was just encountered. |
1140 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1146 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1141 // If the miss wasn't due to an unseen map, a polymorphic stub | 1147 // If the miss wasn't due to an unseen map, a polymorphic stub |
1142 // won't help, use the generic stub. | 1148 // won't help, use the generic stub. |
1143 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); | 1149 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
1144 return generic_stub(); | 1150 return generic_stub(); |
1145 } | 1151 } |
1146 | 1152 |
1147 // If the maximum number of receiver maps has been exceeded, use the generic | 1153 // If the maximum number of receiver maps has been exceeded, use the generic |
1148 // version of the IC. | 1154 // version of the IC. |
1149 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1155 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1150 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); | 1156 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
1151 return generic_stub(); | 1157 return generic_stub(); |
1152 } | 1158 } |
1153 | 1159 |
1154 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1160 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
1155 } | 1161 } |
1156 | 1162 |
1157 | 1163 |
1158 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1164 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1159 Handle<Object> key) { | 1165 Handle<Object> key) { |
1160 if (MigrateDeprecated(object)) { | 1166 if (MigrateDeprecated(object)) { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1370 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
1365 JSReceiver::StoreFromKeyed store_mode) { | 1371 JSReceiver::StoreFromKeyed store_mode) { |
1366 if (state() == UNINITIALIZED) { | 1372 if (state() == UNINITIALIZED) { |
1367 // This is the first time we execute this inline cache. Set the target to | 1373 // This is the first time we execute this inline cache. Set the target to |
1368 // the pre monomorphic stub to delay setting the monomorphic state. | 1374 // the pre monomorphic stub to delay setting the monomorphic state. |
1369 set_target(*pre_monomorphic_stub()); | 1375 set_target(*pre_monomorphic_stub()); |
1370 TRACE_IC("StoreIC", lookup->name()); | 1376 TRACE_IC("StoreIC", lookup->name()); |
1371 return; | 1377 return; |
1372 } | 1378 } |
1373 | 1379 |
1374 Handle<Code> code = LookupForWrite(lookup, value, store_mode) | 1380 bool use_ic = LookupForWrite(lookup, value, store_mode); |
1375 ? ComputeHandler(lookup, value) | 1381 if (!use_ic) { |
1376 : slow_stub(); | 1382 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
| 1383 } |
| 1384 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); |
1377 | 1385 |
1378 PatchCache(lookup->name(), code); | 1386 PatchCache(lookup->name(), code); |
1379 TRACE_IC("StoreIC", lookup->name()); | 1387 TRACE_IC("StoreIC", lookup->name()); |
1380 } | 1388 } |
1381 | 1389 |
1382 | 1390 |
1383 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, | 1391 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
1384 Handle<Object> value, | 1392 Handle<Object> value, |
1385 CacheHolderFlag cache_holder) { | 1393 CacheHolderFlag cache_holder) { |
1386 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 1394 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); |
1387 | 1395 |
1388 // This is currently guaranteed by checks in StoreIC::Store. | 1396 // This is currently guaranteed by checks in StoreIC::Store. |
1389 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1397 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
1390 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1398 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1391 DCHECK(!receiver->IsAccessCheckNeeded()); | 1399 DCHECK(!receiver->IsAccessCheckNeeded()); |
1392 | 1400 |
1393 switch (lookup->state()) { | 1401 switch (lookup->state()) { |
1394 case LookupIterator::TRANSITION: { | 1402 case LookupIterator::TRANSITION: { |
1395 Handle<Map> transition = lookup->transition_map(); | 1403 Handle<Map> transition = lookup->transition_map(); |
1396 // Currently not handled by CompileStoreTransition. | 1404 // Currently not handled by CompileStoreTransition. |
1397 if (!holder->HasFastProperties()) break; | 1405 if (!holder->HasFastProperties()) { |
| 1406 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); |
| 1407 break; |
| 1408 } |
1398 | 1409 |
1399 DCHECK(lookup->IsCacheableTransition()); | 1410 DCHECK(lookup->IsCacheableTransition()); |
1400 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1411 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1401 return compiler.CompileStoreTransition(transition, lookup->name()); | 1412 return compiler.CompileStoreTransition(transition, lookup->name()); |
1402 } | 1413 } |
1403 | 1414 |
1404 case LookupIterator::INTERCEPTOR: { | 1415 case LookupIterator::INTERCEPTOR: { |
1405 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | 1416 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
1406 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1417 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1407 return compiler.CompileStoreInterceptor(lookup->name()); | 1418 return compiler.CompileStoreInterceptor(lookup->name()); |
1408 } | 1419 } |
1409 | 1420 |
1410 case LookupIterator::ACCESSOR: { | 1421 case LookupIterator::ACCESSOR: { |
1411 if (!holder->HasFastProperties()) break; | 1422 if (!holder->HasFastProperties()) { |
| 1423 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); |
| 1424 break; |
| 1425 } |
1412 Handle<Object> accessors = lookup->GetAccessors(); | 1426 Handle<Object> accessors = lookup->GetAccessors(); |
1413 if (accessors->IsExecutableAccessorInfo()) { | 1427 if (accessors->IsExecutableAccessorInfo()) { |
1414 Handle<ExecutableAccessorInfo> info = | 1428 Handle<ExecutableAccessorInfo> info = |
1415 Handle<ExecutableAccessorInfo>::cast(accessors); | 1429 Handle<ExecutableAccessorInfo>::cast(accessors); |
1416 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1430 if (v8::ToCData<Address>(info->setter()) == 0) { |
| 1431 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); |
| 1432 break; |
| 1433 } |
1417 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( | 1434 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( |
1418 isolate(), info, receiver_type())) { | 1435 isolate(), info, receiver_type())) { |
| 1436 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); |
1419 break; | 1437 break; |
1420 } | 1438 } |
1421 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1439 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1422 return compiler.CompileStoreCallback(receiver, lookup->name(), info); | 1440 return compiler.CompileStoreCallback(receiver, lookup->name(), info); |
1423 } else if (accessors->IsAccessorPair()) { | 1441 } else if (accessors->IsAccessorPair()) { |
1424 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), | 1442 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
1425 isolate()); | 1443 isolate()); |
1426 if (!setter->IsJSFunction()) break; | 1444 if (!setter->IsJSFunction()) { |
| 1445 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); |
| 1446 break; |
| 1447 } |
1427 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1448 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
1428 CallOptimization call_optimization(function); | 1449 CallOptimization call_optimization(function); |
1429 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1450 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1430 if (call_optimization.is_simple_api_call() && | 1451 if (call_optimization.is_simple_api_call() && |
1431 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1452 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
1432 return compiler.CompileStoreCallback(receiver, lookup->name(), | 1453 return compiler.CompileStoreCallback(receiver, lookup->name(), |
1433 call_optimization); | 1454 call_optimization); |
1434 } | 1455 } |
1435 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | 1456 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
1436 Handle<JSFunction>::cast(setter)); | 1457 Handle<JSFunction>::cast(setter)); |
1437 } | 1458 } |
1438 // TODO(dcarney): Handle correctly. | 1459 // TODO(dcarney): Handle correctly. |
1439 DCHECK(accessors->IsDeclaredAccessorInfo()); | 1460 DCHECK(accessors->IsDeclaredAccessorInfo()); |
| 1461 TRACE_GENERIC_IC(isolate(), "StoreIC", "declared accessor info"); |
1440 break; | 1462 break; |
1441 } | 1463 } |
1442 | 1464 |
1443 case LookupIterator::DATA: { | 1465 case LookupIterator::DATA: { |
1444 if (lookup->is_dictionary_holder()) { | 1466 if (lookup->is_dictionary_holder()) { |
1445 if (holder->IsGlobalObject()) { | 1467 if (holder->IsGlobalObject()) { |
1446 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1468 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
1447 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1469 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
1448 StoreGlobalStub stub(isolate(), union_type->IsConstant(), | 1470 StoreGlobalStub stub(isolate(), union_type->IsConstant(), |
1449 receiver->IsJSGlobalProxy()); | 1471 receiver->IsJSGlobalProxy()); |
(...skipping 20 matching lines...) Expand all Loading... |
1470 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | 1492 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
1471 lookup->representation()); | 1493 lookup->representation()); |
1472 return stub.GetCode(); | 1494 return stub.GetCode(); |
1473 } | 1495 } |
1474 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1496 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1475 return compiler.CompileStoreField(lookup); | 1497 return compiler.CompileStoreField(lookup); |
1476 } | 1498 } |
1477 | 1499 |
1478 // -------------- Constant properties -------------- | 1500 // -------------- Constant properties -------------- |
1479 DCHECK(lookup->property_details().type() == CONSTANT); | 1501 DCHECK(lookup->property_details().type() == CONSTANT); |
| 1502 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
1480 break; | 1503 break; |
1481 } | 1504 } |
1482 | 1505 |
1483 case LookupIterator::ACCESS_CHECK: | 1506 case LookupIterator::ACCESS_CHECK: |
1484 case LookupIterator::JSPROXY: | 1507 case LookupIterator::JSPROXY: |
1485 case LookupIterator::NOT_FOUND: | 1508 case LookupIterator::NOT_FOUND: |
1486 UNREACHABLE(); | 1509 UNREACHABLE(); |
1487 } | 1510 } |
1488 return slow_stub(); | 1511 return slow_stub(); |
1489 } | 1512 } |
1490 | 1513 |
1491 | 1514 |
1492 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1515 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
1493 KeyedAccessStoreMode store_mode) { | 1516 KeyedAccessStoreMode store_mode) { |
1494 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1517 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1495 // via megamorphic stubs, since they don't have a map in their relocation info | 1518 // via megamorphic stubs, since they don't have a map in their relocation info |
1496 // and so the stubs can't be harvested for the object needed for a map check. | 1519 // and so the stubs can't be harvested for the object needed for a map check. |
1497 if (target()->type() != Code::NORMAL) { | 1520 if (target()->type() != Code::NORMAL) { |
1498 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1521 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); |
1499 return generic_stub(); | 1522 return generic_stub(); |
1500 } | 1523 } |
1501 | 1524 |
1502 Handle<Map> receiver_map(receiver->map(), isolate()); | 1525 Handle<Map> receiver_map(receiver->map(), isolate()); |
1503 MapHandleList target_receiver_maps; | 1526 MapHandleList target_receiver_maps; |
1504 TargetMaps(&target_receiver_maps); | 1527 TargetMaps(&target_receiver_maps); |
1505 if (target_receiver_maps.length() == 0) { | 1528 if (target_receiver_maps.length() == 0) { |
1506 Handle<Map> monomorphic_map = | 1529 Handle<Map> monomorphic_map = |
1507 ComputeTransitionedMap(receiver_map, store_mode); | 1530 ComputeTransitionedMap(receiver_map, store_mode); |
1508 store_mode = GetNonTransitioningStoreMode(store_mode); | 1531 store_mode = GetNonTransitioningStoreMode(store_mode); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 if (IsTransitionStoreMode(store_mode)) { | 1577 if (IsTransitionStoreMode(store_mode)) { |
1555 Handle<Map> transitioned_receiver_map = | 1578 Handle<Map> transitioned_receiver_map = |
1556 ComputeTransitionedMap(receiver_map, store_mode); | 1579 ComputeTransitionedMap(receiver_map, store_mode); |
1557 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1580 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
1558 transitioned_receiver_map); | 1581 transitioned_receiver_map); |
1559 } | 1582 } |
1560 | 1583 |
1561 if (!map_added) { | 1584 if (!map_added) { |
1562 // If the miss wasn't due to an unseen map, a polymorphic stub | 1585 // If the miss wasn't due to an unseen map, a polymorphic stub |
1563 // won't help, use the generic stub. | 1586 // won't help, use the generic stub. |
1564 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); | 1587 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice"); |
1565 return generic_stub(); | 1588 return generic_stub(); |
1566 } | 1589 } |
1567 | 1590 |
1568 // If the maximum number of receiver maps has been exceeded, use the generic | 1591 // If the maximum number of receiver maps has been exceeded, use the generic |
1569 // version of the IC. | 1592 // version of the IC. |
1570 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1593 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1571 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); | 1594 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "max polymorph exceeded"); |
1572 return generic_stub(); | 1595 return generic_stub(); |
1573 } | 1596 } |
1574 | 1597 |
1575 // Make sure all polymorphic handlers have the same store mode, otherwise the | 1598 // Make sure all polymorphic handlers have the same store mode, otherwise the |
1576 // generic stub must be used. | 1599 // generic stub must be used. |
1577 store_mode = GetNonTransitioningStoreMode(store_mode); | 1600 store_mode = GetNonTransitioningStoreMode(store_mode); |
1578 if (old_store_mode != STANDARD_STORE) { | 1601 if (old_store_mode != STANDARD_STORE) { |
1579 if (store_mode == STANDARD_STORE) { | 1602 if (store_mode == STANDARD_STORE) { |
1580 store_mode = old_store_mode; | 1603 store_mode = old_store_mode; |
1581 } else if (store_mode != old_store_mode) { | 1604 } else if (store_mode != old_store_mode) { |
1582 TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch"); | 1605 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch"); |
1583 return generic_stub(); | 1606 return generic_stub(); |
1584 } | 1607 } |
1585 } | 1608 } |
1586 | 1609 |
1587 // If the store mode isn't the standard mode, make sure that all polymorphic | 1610 // If the store mode isn't the standard mode, make sure that all polymorphic |
1588 // receivers are either external arrays, or all "normal" arrays. Otherwise, | 1611 // receivers are either external arrays, or all "normal" arrays. Otherwise, |
1589 // use the generic stub. | 1612 // use the generic stub. |
1590 if (store_mode != STANDARD_STORE) { | 1613 if (store_mode != STANDARD_STORE) { |
1591 int external_arrays = 0; | 1614 int external_arrays = 0; |
1592 for (int i = 0; i < target_receiver_maps.length(); ++i) { | 1615 for (int i = 0; i < target_receiver_maps.length(); ++i) { |
1593 if (target_receiver_maps[i]->has_external_array_elements() || | 1616 if (target_receiver_maps[i]->has_external_array_elements() || |
1594 target_receiver_maps[i]->has_fixed_typed_array_elements()) { | 1617 target_receiver_maps[i]->has_fixed_typed_array_elements()) { |
1595 external_arrays++; | 1618 external_arrays++; |
1596 } | 1619 } |
1597 } | 1620 } |
1598 if (external_arrays != 0 && | 1621 if (external_arrays != 0 && |
1599 external_arrays != target_receiver_maps.length()) { | 1622 external_arrays != target_receiver_maps.length()) { |
1600 TRACE_GENERIC_IC(isolate(), "KeyedIC", | 1623 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
1601 "unsupported combination of external and normal arrays"); | 1624 "unsupported combination of external and normal arrays"); |
1602 return generic_stub(); | 1625 return generic_stub(); |
1603 } | 1626 } |
1604 } | 1627 } |
1605 | 1628 |
1606 return PropertyICCompiler::ComputeKeyedStorePolymorphic( | 1629 return PropertyICCompiler::ComputeKeyedStorePolymorphic( |
1607 &target_receiver_maps, store_mode, strict_mode()); | 1630 &target_receiver_maps, store_mode, strict_mode()); |
1608 } | 1631 } |
1609 | 1632 |
1610 | 1633 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1745 | 1768 |
1746 Handle<Object> store_handle; | 1769 Handle<Object> store_handle; |
1747 Handle<Code> stub = generic_stub(); | 1770 Handle<Code> stub = generic_stub(); |
1748 | 1771 |
1749 if (key->IsInternalizedString()) { | 1772 if (key->IsInternalizedString()) { |
1750 ASSIGN_RETURN_ON_EXCEPTION( | 1773 ASSIGN_RETURN_ON_EXCEPTION( |
1751 isolate(), store_handle, | 1774 isolate(), store_handle, |
1752 StoreIC::Store(object, Handle<String>::cast(key), value, | 1775 StoreIC::Store(object, Handle<String>::cast(key), value, |
1753 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 1776 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
1754 Object); | 1777 Object); |
1755 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 1778 if (!is_target_set()) { |
1756 set_target(*stub); | 1779 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 1780 "unhandled internalized string key"); |
| 1781 TRACE_IC("StoreIC", key); |
| 1782 set_target(*stub); |
| 1783 } |
1757 return store_handle; | 1784 return store_handle; |
1758 } | 1785 } |
1759 | 1786 |
1760 bool use_ic = | 1787 bool use_ic = |
1761 FLAG_use_ic && !object->IsStringWrapper() && | 1788 FLAG_use_ic && !object->IsStringWrapper() && |
1762 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && | 1789 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
1763 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); | 1790 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
1764 if (use_ic && !object->IsSmi()) { | 1791 if (use_ic && !object->IsSmi()) { |
1765 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1792 // Don't use ICs for maps of the objects in Array's prototype chain. We |
1766 // expect to be able to trap element sets to objects with those maps in | 1793 // expect to be able to trap element sets to objects with those maps in |
1767 // the runtime to enable optimization of element hole access. | 1794 // the runtime to enable optimization of element hole access. |
1768 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 1795 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
1769 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 1796 if (heap_object->map()->IsMapInArrayPrototypeChain()) { |
| 1797 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); |
| 1798 use_ic = false; |
| 1799 } |
1770 } | 1800 } |
1771 | 1801 |
1772 if (use_ic) { | 1802 if (use_ic) { |
1773 DCHECK(!object->IsAccessCheckNeeded()); | 1803 DCHECK(!object->IsAccessCheckNeeded()); |
1774 | 1804 |
1775 if (object->IsJSObject()) { | 1805 if (object->IsJSObject()) { |
1776 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1806 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1777 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); | 1807 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); |
1778 if (receiver->elements()->map() == | 1808 if (receiver->elements()->map() == |
1779 isolate()->heap()->sloppy_arguments_elements_map()) { | 1809 isolate()->heap()->sloppy_arguments_elements_map()) { |
1780 if (strict_mode() == SLOPPY) { | 1810 if (strict_mode() == SLOPPY) { |
1781 stub = sloppy_arguments_stub(); | 1811 stub = sloppy_arguments_stub(); |
| 1812 } else { |
| 1813 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
1782 } | 1814 } |
1783 } else if (key_is_smi_like && | 1815 } else if (key_is_smi_like && |
1784 !(target().is_identical_to(sloppy_arguments_stub()))) { | 1816 !(target().is_identical_to(sloppy_arguments_stub()))) { |
1785 // We should go generic if receiver isn't a dictionary, but our | 1817 // We should go generic if receiver isn't a dictionary, but our |
1786 // prototype chain does have dictionary elements. This ensures that | 1818 // prototype chain does have dictionary elements. This ensures that |
1787 // other non-dictionary receivers in the polymorphic case benefit | 1819 // other non-dictionary receivers in the polymorphic case benefit |
1788 // from fast path keyed stores. | 1820 // from fast path keyed stores. |
1789 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 1821 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
1790 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 1822 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
1791 stub = StoreElementStub(receiver, store_mode); | 1823 stub = StoreElementStub(receiver, store_mode); |
| 1824 } else { |
| 1825 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); |
1792 } | 1826 } |
| 1827 } else { |
| 1828 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
1793 } | 1829 } |
| 1830 } else { |
| 1831 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
1794 } | 1832 } |
1795 } | 1833 } |
1796 | 1834 |
1797 if (store_handle.is_null()) { | 1835 if (store_handle.is_null()) { |
1798 ASSIGN_RETURN_ON_EXCEPTION( | 1836 ASSIGN_RETURN_ON_EXCEPTION( |
1799 isolate(), store_handle, | 1837 isolate(), store_handle, |
1800 Runtime::SetObjectProperty(isolate(), object, key, value, | 1838 Runtime::SetObjectProperty(isolate(), object, key, value, |
1801 strict_mode()), | 1839 strict_mode()), |
1802 Object); | 1840 Object); |
1803 } | 1841 } |
1804 | 1842 |
1805 DCHECK(!is_target_set()); | 1843 DCHECK(!is_target_set()); |
1806 Code* generic = *generic_stub(); | 1844 Code* generic = *generic_stub(); |
1807 if (*stub == generic) { | 1845 if (*stub == generic) { |
1808 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 1846 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
1809 } | 1847 } |
| 1848 if (*stub == *slow_stub()) { |
| 1849 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
| 1850 } |
1810 DCHECK(!stub.is_null()); | 1851 DCHECK(!stub.is_null()); |
1811 set_target(*stub); | 1852 set_target(*stub); |
1812 TRACE_IC("StoreIC", key); | 1853 TRACE_IC("StoreIC", key); |
1813 | 1854 |
1814 return store_handle; | 1855 return store_handle; |
1815 } | 1856 } |
1816 | 1857 |
1817 | 1858 |
1818 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, | 1859 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, |
1819 Handle<TypeFeedbackVector> vector, | 1860 Handle<TypeFeedbackVector> vector, |
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2607 static const Address IC_utilities[] = { | 2648 static const Address IC_utilities[] = { |
2608 #define ADDR(name) FUNCTION_ADDR(name), | 2649 #define ADDR(name) FUNCTION_ADDR(name), |
2609 IC_UTIL_LIST(ADDR) NULL | 2650 IC_UTIL_LIST(ADDR) NULL |
2610 #undef ADDR | 2651 #undef ADDR |
2611 }; | 2652 }; |
2612 | 2653 |
2613 | 2654 |
2614 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2655 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
2615 } | 2656 } |
2616 } // namespace v8::internal | 2657 } // namespace v8::internal |
OLD | NEW |