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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 Isolate* isolate = new_target->GetIsolate(); | 74 Isolate* isolate = new_target->GetIsolate(); |
75 Code* apply_builtin = isolate->builtins()->builtin( | 75 Code* apply_builtin = isolate->builtins()->builtin( |
76 Builtins::kFunctionApply); | 76 Builtins::kFunctionApply); |
77 if (raw_frame->unchecked_code() == apply_builtin) { | 77 if (raw_frame->unchecked_code() == apply_builtin) { |
78 PrintF("apply from "); | 78 PrintF("apply from "); |
79 it.Advance(); | 79 it.Advance(); |
80 raw_frame = it.frame(); | 80 raw_frame = it.frame(); |
81 } | 81 } |
82 } | 82 } |
83 JavaScriptFrame::PrintTop(stdout, false, true); | 83 JavaScriptFrame::PrintTop(stdout, false, true); |
84 PrintF(" (%c->%c)", | 84 bool new_can_grow = |
| 85 Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) == |
| 86 ALLOW_JSARRAY_GROWTH; |
| 87 PrintF(" (%c->%c%s)", |
85 TransitionMarkFromState(old_state), | 88 TransitionMarkFromState(old_state), |
86 TransitionMarkFromState(new_state)); | 89 TransitionMarkFromState(new_state), |
| 90 new_can_grow ? ".GROW" : ""); |
87 name->Print(); | 91 name->Print(); |
88 PrintF("]\n"); | 92 PrintF("]\n"); |
89 } | 93 } |
90 } | 94 } |
91 | 95 |
92 #define TRACE_GENERIC_IC(type, reason) \ | 96 #define TRACE_GENERIC_IC(type, reason) \ |
93 do { \ | 97 do { \ |
94 if (FLAG_trace_ic) { \ | 98 if (FLAG_trace_ic) { \ |
95 PrintF("[%s patching generic stub in ", type); \ | 99 PrintF("[%s patching generic stub in ", type); \ |
96 JavaScriptFrame::PrintTop(stdout, false, true); \ | 100 JavaScriptFrame::PrintTop(stdout, false, true); \ |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 372 |
369 void LoadIC::Clear(Address address, Code* target) { | 373 void LoadIC::Clear(Address address, Code* target) { |
370 if (target->ic_state() == UNINITIALIZED) return; | 374 if (target->ic_state() == UNINITIALIZED) return; |
371 SetTargetAtAddress(address, initialize_stub()); | 375 SetTargetAtAddress(address, initialize_stub()); |
372 } | 376 } |
373 | 377 |
374 | 378 |
375 void StoreIC::Clear(Address address, Code* target) { | 379 void StoreIC::Clear(Address address, Code* target) { |
376 if (target->ic_state() == UNINITIALIZED) return; | 380 if (target->ic_state() == UNINITIALIZED) return; |
377 SetTargetAtAddress(address, | 381 SetTargetAtAddress(address, |
378 (target->extra_ic_state() == kStrictMode) | 382 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) |
379 ? initialize_stub_strict() | 383 ? initialize_stub_strict() |
380 : initialize_stub()); | 384 : initialize_stub()); |
381 } | 385 } |
382 | 386 |
383 | 387 |
384 void KeyedStoreIC::Clear(Address address, Code* target) { | 388 void KeyedStoreIC::Clear(Address address, Code* target) { |
385 if (target->ic_state() == UNINITIALIZED) return; | 389 if (target->ic_state() == UNINITIALIZED) return; |
386 SetTargetAtAddress(address, | 390 SetTargetAtAddress(address, |
387 (target->extra_ic_state() == kStrictMode) | 391 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) |
388 ? initialize_stub_strict() | 392 ? initialize_stub_strict() |
389 : initialize_stub()); | 393 : initialize_stub()); |
390 } | 394 } |
391 | 395 |
392 | 396 |
393 static bool HasInterceptorGetter(JSObject* object) { | 397 static bool HasInterceptorGetter(JSObject* object) { |
394 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 398 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
395 } | 399 } |
396 | 400 |
397 | 401 |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 // GenerateMonomorphicCacheProbe. | 993 // GenerateMonomorphicCacheProbe. |
990 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 994 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
991 } | 995 } |
992 | 996 |
993 TRACE_IC("LoadIC", name, state, target()); | 997 TRACE_IC("LoadIC", name, state, target()); |
994 } | 998 } |
995 | 999 |
996 | 1000 |
997 Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck( | 1001 Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck( |
998 bool is_js_array, | 1002 bool is_js_array, |
999 ElementsKind elements_kind) { | 1003 ElementsKind elements_kind, |
| 1004 KeyedAccessGrowMode grow_mode) { |
| 1005 ASSERT(grow_mode == DO_NOT_ALLOW_JSARRAY_GROWTH); |
1000 return KeyedLoadElementStub(elements_kind).GetCode(); | 1006 return KeyedLoadElementStub(elements_kind).GetCode(); |
1001 } | 1007 } |
1002 | 1008 |
1003 | 1009 |
1004 Handle<Code> KeyedLoadIC::ComputePolymorphicStub( | 1010 Handle<Code> KeyedLoadIC::ComputePolymorphicStub( |
1005 MapHandleList* receiver_maps, | 1011 MapHandleList* receiver_maps, |
1006 StrictModeFlag strict_mode) { | 1012 StrictModeFlag strict_mode, |
| 1013 KeyedAccessGrowMode growth_mode) { |
1007 CodeHandleList handler_ics(receiver_maps->length()); | 1014 CodeHandleList handler_ics(receiver_maps->length()); |
1008 for (int i = 0; i < receiver_maps->length(); ++i) { | 1015 for (int i = 0; i < receiver_maps->length(); ++i) { |
1009 Handle<Map> receiver_map = receiver_maps->at(i); | 1016 Handle<Map> receiver_map = receiver_maps->at(i); |
1010 Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck( | 1017 Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck( |
1011 receiver_map, strict_mode); | 1018 receiver_map, strict_mode, growth_mode); |
1012 handler_ics.Add(cached_stub); | 1019 handler_ics.Add(cached_stub); |
1013 } | 1020 } |
1014 KeyedLoadStubCompiler compiler(isolate()); | 1021 KeyedLoadStubCompiler compiler(isolate()); |
1015 Handle<Code> code = compiler.CompileLoadPolymorphic( | 1022 Handle<Code> code = compiler.CompileLoadPolymorphic( |
1016 receiver_maps, &handler_ics); | 1023 receiver_maps, &handler_ics); |
1017 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 1024 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
1018 PROFILE(isolate(), | 1025 PROFILE(isolate(), |
1019 CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0)); | 1026 CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0)); |
1020 return code; | 1027 return code; |
1021 } | 1028 } |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 } | 1493 } |
1487 } | 1494 } |
1488 } | 1495 } |
1489 | 1496 |
1490 | 1497 |
1491 Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver, | 1498 Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver, |
1492 StubKind stub_kind, | 1499 StubKind stub_kind, |
1493 StrictModeFlag strict_mode, | 1500 StrictModeFlag strict_mode, |
1494 Handle<Code> generic_stub) { | 1501 Handle<Code> generic_stub) { |
1495 State ic_state = target()->ic_state(); | 1502 State ic_state = target()->ic_state(); |
| 1503 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) |
| 1504 ? ALLOW_JSARRAY_GROWTH |
| 1505 : DO_NOT_ALLOW_JSARRAY_GROWTH; |
1496 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && | 1506 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && |
1497 !IsTransitionStubKind(stub_kind)) { | 1507 !IsTransitionStubKind(stub_kind)) { |
1498 return ComputeMonomorphicStub( | 1508 return ComputeMonomorphicStub( |
1499 receiver, stub_kind, strict_mode, generic_stub); | 1509 receiver, stub_kind, strict_mode, generic_stub); |
1500 } | 1510 } |
1501 ASSERT(target() != *generic_stub); | 1511 ASSERT(target() != *generic_stub); |
1502 | 1512 |
1503 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1513 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1504 // via megamorphic stubs, since they don't have a map in their relocation info | 1514 // via megamorphic stubs, since they don't have a map in their relocation info |
1505 // and so the stubs can't be harvested for the object needed for a map check. | 1515 // and so the stubs can't be harvested for the object needed for a map check. |
(...skipping 24 matching lines...) Expand all Loading... |
1530 return generic_stub; | 1540 return generic_stub; |
1531 } | 1541 } |
1532 | 1542 |
1533 // If the maximum number of receiver maps has been exceeded, use the generic | 1543 // If the maximum number of receiver maps has been exceeded, use the generic |
1534 // version of the IC. | 1544 // version of the IC. |
1535 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1545 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1536 TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded"); | 1546 TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded"); |
1537 return generic_stub; | 1547 return generic_stub; |
1538 } | 1548 } |
1539 | 1549 |
| 1550 if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) == |
| 1551 ALLOW_JSARRAY_GROWTH)) { |
| 1552 grow_mode = ALLOW_JSARRAY_GROWTH; |
| 1553 } |
| 1554 |
1540 Handle<PolymorphicCodeCache> cache = | 1555 Handle<PolymorphicCodeCache> cache = |
1541 isolate()->factory()->polymorphic_code_cache(); | 1556 isolate()->factory()->polymorphic_code_cache(); |
1542 Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode); | 1557 Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode, |
| 1558 strict_mode); |
| 1559 Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, extra_state); |
1543 Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags); | 1560 Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags); |
1544 if (probe->IsCode()) return Handle<Code>::cast(probe); | 1561 if (probe->IsCode()) return Handle<Code>::cast(probe); |
1545 | 1562 |
1546 Handle<Code> stub = | 1563 Handle<Code> stub = |
1547 ComputePolymorphicStub(&target_receiver_maps, strict_mode); | 1564 ComputePolymorphicStub(&target_receiver_maps, strict_mode, grow_mode); |
1548 PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub); | 1565 PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub); |
1549 return stub; | 1566 return stub; |
1550 } | 1567 } |
1551 | 1568 |
1552 | 1569 |
1553 Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck( | 1570 Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck( |
1554 Handle<Map> receiver_map, | 1571 Handle<Map> receiver_map, |
1555 StrictModeFlag strict_mode) { | 1572 StrictModeFlag strict_mode, |
| 1573 KeyedAccessGrowMode grow_mode) { |
1556 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1574 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
1557 ASSERT(!string_stub().is_null()); | 1575 ASSERT(!string_stub().is_null()); |
1558 return string_stub(); | 1576 return string_stub(); |
1559 } else { | 1577 } else { |
1560 ASSERT(receiver_map->has_dictionary_elements() || | 1578 ASSERT(receiver_map->has_dictionary_elements() || |
1561 receiver_map->has_fast_elements() || | 1579 receiver_map->has_fast_elements() || |
1562 receiver_map->has_fast_smi_only_elements() || | 1580 receiver_map->has_fast_smi_only_elements() || |
1563 receiver_map->has_fast_double_elements() || | 1581 receiver_map->has_fast_double_elements() || |
1564 receiver_map->has_external_array_elements()); | 1582 receiver_map->has_external_array_elements()); |
1565 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1583 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1566 return GetElementStubWithoutMapCheck(is_js_array, | 1584 return GetElementStubWithoutMapCheck(is_js_array, |
1567 receiver_map->elements_kind()); | 1585 receiver_map->elements_kind(), |
| 1586 grow_mode); |
1568 } | 1587 } |
1569 } | 1588 } |
1570 | 1589 |
1571 | 1590 |
1572 Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<JSObject> receiver, | 1591 Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<JSObject> receiver, |
1573 StubKind stub_kind, | 1592 StubKind stub_kind, |
1574 StrictModeFlag strict_mode, | 1593 StrictModeFlag strict_mode, |
1575 Handle<Code> generic_stub) { | 1594 Handle<Code> generic_stub) { |
1576 if (receiver->HasFastElements() || | 1595 if (receiver->HasFastElements() || |
1577 receiver->HasFastSmiOnlyElements() || | 1596 receiver->HasFastSmiOnlyElements() || |
1578 receiver->HasExternalArrayElements() || | 1597 receiver->HasExternalArrayElements() || |
1579 receiver->HasFastDoubleElements() || | 1598 receiver->HasFastDoubleElements() || |
1580 receiver->HasDictionaryElements()) { | 1599 receiver->HasDictionaryElements()) { |
1581 return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( | 1600 return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( |
1582 receiver, stub_kind, strict_mode); | 1601 receiver, stub_kind, strict_mode); |
1583 } else { | 1602 } else { |
1584 return generic_stub; | 1603 return generic_stub; |
1585 } | 1604 } |
1586 } | 1605 } |
1587 | 1606 |
1588 | 1607 |
1589 Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver, | 1608 Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver, |
1590 StubKind stub_kind) { | 1609 StubKind stub_kind) { |
1591 switch (stub_kind) { | 1610 switch (stub_kind) { |
1592 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT: | 1611 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT: |
1593 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT: | 1612 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT: |
| 1613 case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: |
| 1614 case KeyedIC::STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT: |
1594 return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS); | 1615 return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS); |
1595 break; | 1616 break; |
1596 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE: | 1617 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE: |
| 1618 case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE: |
1597 return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS); | 1619 return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS); |
1598 break; | 1620 break; |
1599 default: | 1621 default: |
1600 UNREACHABLE(); | 1622 UNREACHABLE(); |
1601 return Handle<Map>::null(); | 1623 return Handle<Map>::null(); |
1602 } | 1624 } |
1603 } | 1625 } |
1604 | 1626 |
1605 | 1627 |
1606 Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck( | 1628 Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck( |
1607 bool is_js_array, | 1629 bool is_js_array, |
1608 ElementsKind elements_kind) { | 1630 ElementsKind elements_kind, |
1609 return KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); | 1631 KeyedAccessGrowMode grow_mode) { |
| 1632 return KeyedStoreElementStub(is_js_array, elements_kind, grow_mode).GetCode(); |
1610 } | 1633 } |
1611 | 1634 |
1612 | 1635 |
1613 Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps, | 1636 Handle<Code> KeyedStoreIC::ComputePolymorphicStub( |
1614 StrictModeFlag strict_mode) { | 1637 MapHandleList* receiver_maps, |
| 1638 StrictModeFlag strict_mode, |
| 1639 KeyedAccessGrowMode grow_mode) { |
1615 // Collect MONOMORPHIC stubs for all target_receiver_maps. | 1640 // Collect MONOMORPHIC stubs for all target_receiver_maps. |
1616 CodeHandleList handler_ics(receiver_maps->length()); | 1641 CodeHandleList handler_ics(receiver_maps->length()); |
1617 MapHandleList transitioned_maps(receiver_maps->length()); | 1642 MapHandleList transitioned_maps(receiver_maps->length()); |
1618 for (int i = 0; i < receiver_maps->length(); ++i) { | 1643 for (int i = 0; i < receiver_maps->length(); ++i) { |
1619 Handle<Map> receiver_map(receiver_maps->at(i)); | 1644 Handle<Map> receiver_map(receiver_maps->at(i)); |
1620 Handle<Code> cached_stub; | 1645 Handle<Code> cached_stub; |
1621 Handle<Map> transitioned_map = | 1646 Handle<Map> transitioned_map = |
1622 receiver_map->FindTransitionedMap(receiver_maps); | 1647 receiver_map->FindTransitionedMap(receiver_maps); |
1623 if (!transitioned_map.is_null()) { | 1648 if (!transitioned_map.is_null()) { |
1624 cached_stub = ElementsTransitionAndStoreStub( | 1649 cached_stub = ElementsTransitionAndStoreStub( |
1625 receiver_map->elements_kind(), // original elements_kind | 1650 receiver_map->elements_kind(), // original elements_kind |
1626 transitioned_map->elements_kind(), | 1651 transitioned_map->elements_kind(), |
1627 receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array | 1652 receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array |
1628 strict_mode).GetCode(); | 1653 strict_mode, grow_mode).GetCode(); |
1629 } else { | 1654 } else { |
1630 cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map, | 1655 cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map, |
1631 strict_mode); | 1656 strict_mode, |
| 1657 grow_mode); |
1632 } | 1658 } |
1633 ASSERT(!cached_stub.is_null()); | 1659 ASSERT(!cached_stub.is_null()); |
1634 handler_ics.Add(cached_stub); | 1660 handler_ics.Add(cached_stub); |
1635 transitioned_maps.Add(transitioned_map); | 1661 transitioned_maps.Add(transitioned_map); |
1636 } | 1662 } |
1637 KeyedStoreStubCompiler compiler(isolate(), strict_mode); | 1663 KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode); |
1638 Handle<Code> code = compiler.CompileStorePolymorphic( | 1664 Handle<Code> code = compiler.CompileStorePolymorphic( |
1639 receiver_maps, &handler_ics, &transitioned_maps); | 1665 receiver_maps, &handler_ics, &transitioned_maps); |
1640 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | 1666 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
1641 PROFILE(isolate(), | 1667 PROFILE(isolate(), |
1642 CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0)); | 1668 CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0)); |
1643 return code; | 1669 return code; |
1644 } | 1670 } |
1645 | 1671 |
1646 | 1672 |
| 1673 KeyedIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver, |
| 1674 Handle<Object> key, |
| 1675 Handle<Object> value) { |
| 1676 ASSERT(key->IsSmi()); |
| 1677 int index = Smi::cast(*key)->value(); |
| 1678 bool allow_growth = receiver->IsJSArray() && |
| 1679 JSArray::cast(*receiver)->length()->IsSmi() && |
| 1680 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); |
| 1681 |
| 1682 if (allow_growth) { |
| 1683 // Handle growing array in stub if necessary. |
| 1684 if (receiver->HasFastSmiOnlyElements()) { |
| 1685 if (value->IsHeapNumber()) { |
| 1686 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; |
| 1687 } |
| 1688 if (value->IsHeapObject()) { |
| 1689 return STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT; |
| 1690 } |
| 1691 } else if (receiver->HasFastDoubleElements()) { |
| 1692 if (!value->IsSmi() && !value->IsHeapNumber()) { |
| 1693 return STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT; |
| 1694 } |
| 1695 } |
| 1696 return STORE_AND_GROW_NO_TRANSITION; |
| 1697 } else { |
| 1698 // Handle only in-bounds elements accesses. |
| 1699 if (receiver->HasFastSmiOnlyElements()) { |
| 1700 if (value->IsHeapNumber()) { |
| 1701 return STORE_TRANSITION_SMI_TO_DOUBLE; |
| 1702 } else if (value->IsHeapObject()) { |
| 1703 return STORE_TRANSITION_SMI_TO_OBJECT; |
| 1704 } |
| 1705 } else if (receiver->HasFastDoubleElements()) { |
| 1706 if (!value->IsSmi() && !value->IsHeapNumber()) { |
| 1707 return STORE_TRANSITION_DOUBLE_TO_OBJECT; |
| 1708 } |
| 1709 } |
| 1710 return STORE_NO_TRANSITION; |
| 1711 } |
| 1712 } |
| 1713 |
| 1714 |
1647 MaybeObject* KeyedStoreIC::Store(State state, | 1715 MaybeObject* KeyedStoreIC::Store(State state, |
1648 StrictModeFlag strict_mode, | 1716 StrictModeFlag strict_mode, |
1649 Handle<Object> object, | 1717 Handle<Object> object, |
1650 Handle<Object> key, | 1718 Handle<Object> key, |
1651 Handle<Object> value, | 1719 Handle<Object> value, |
1652 bool force_generic) { | 1720 bool force_generic) { |
1653 if (key->IsSymbol()) { | 1721 if (key->IsSymbol()) { |
1654 Handle<String> name = Handle<String>::cast(key); | 1722 Handle<String> name = Handle<String>::cast(key); |
1655 | 1723 |
1656 // Handle proxies. | 1724 // Handle proxies. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 Handle<Code> stub = (strict_mode == kStrictMode) | 1767 Handle<Code> stub = (strict_mode == kStrictMode) |
1700 ? generic_stub_strict() | 1768 ? generic_stub_strict() |
1701 : generic_stub(); | 1769 : generic_stub(); |
1702 if (object->IsJSObject()) { | 1770 if (object->IsJSObject()) { |
1703 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1771 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1704 if (receiver->elements()->map() == | 1772 if (receiver->elements()->map() == |
1705 isolate()->heap()->non_strict_arguments_elements_map()) { | 1773 isolate()->heap()->non_strict_arguments_elements_map()) { |
1706 stub = non_strict_arguments_stub(); | 1774 stub = non_strict_arguments_stub(); |
1707 } else if (!force_generic) { | 1775 } else if (!force_generic) { |
1708 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1776 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
1709 StubKind stub_kind = STORE_NO_TRANSITION; | 1777 StubKind stub_kind = GetStubKind(receiver, key, value); |
1710 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { | |
1711 if (value->IsHeapNumber()) { | |
1712 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE; | |
1713 } else if (value->IsHeapObject()) { | |
1714 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; | |
1715 } | |
1716 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { | |
1717 if (!value->IsSmi() && !value->IsHeapNumber()) { | |
1718 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; | |
1719 } | |
1720 } | |
1721 stub = ComputeStub(receiver, stub_kind, strict_mode, stub); | 1778 stub = ComputeStub(receiver, stub_kind, strict_mode, stub); |
1722 } | 1779 } |
1723 } else { | 1780 } else { |
1724 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); | 1781 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); |
1725 } | 1782 } |
1726 } | 1783 } |
1727 if (!stub.is_null()) set_target(*stub); | 1784 if (!stub.is_null()) set_target(*stub); |
1728 } | 1785 } |
1729 | 1786 |
1730 TRACE_IC("KeyedStoreIC", key, state, target()); | 1787 TRACE_IC("KeyedStoreIC", key, state, target()); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1893 | 1950 |
1894 | 1951 |
1895 // Used from ic-<arch>.cc. | 1952 // Used from ic-<arch>.cc. |
1896 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 1953 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
1897 HandleScope scope; | 1954 HandleScope scope; |
1898 ASSERT(args.length() == 3); | 1955 ASSERT(args.length() == 3); |
1899 StoreIC ic(isolate); | 1956 StoreIC ic(isolate); |
1900 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1957 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1901 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1958 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1902 return ic.Store(state, | 1959 return ic.Store(state, |
1903 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 1960 Code::GetStrictMode(extra_ic_state), |
1904 args.at<Object>(0), | 1961 args.at<Object>(0), |
1905 args.at<String>(1), | 1962 args.at<String>(1), |
1906 args.at<Object>(2)); | 1963 args.at<Object>(2)); |
1907 } | 1964 } |
1908 | 1965 |
1909 | 1966 |
1910 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 1967 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
1911 NoHandleAllocation nha; | 1968 NoHandleAllocation nha; |
1912 | 1969 |
1913 ASSERT(args.length() == 2); | 1970 ASSERT(args.length() == 2); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 | 2026 |
1970 | 2027 |
1971 // Used from ic-<arch>.cc. | 2028 // Used from ic-<arch>.cc. |
1972 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2029 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
1973 HandleScope scope(isolate); | 2030 HandleScope scope(isolate); |
1974 ASSERT(args.length() == 3); | 2031 ASSERT(args.length() == 3); |
1975 KeyedStoreIC ic(isolate); | 2032 KeyedStoreIC ic(isolate); |
1976 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2033 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1977 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2034 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1978 return ic.Store(state, | 2035 return ic.Store(state, |
1979 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 2036 Code::GetStrictMode(extra_ic_state), |
1980 args.at<Object>(0), | 2037 args.at<Object>(0), |
1981 args.at<Object>(1), | 2038 args.at<Object>(1), |
1982 args.at<Object>(2), | 2039 args.at<Object>(2), |
1983 false); | 2040 false); |
1984 } | 2041 } |
1985 | 2042 |
1986 | 2043 |
1987 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { | 2044 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { |
1988 NoHandleAllocation na; | 2045 NoHandleAllocation na; |
1989 ASSERT(args.length() == 3); | 2046 ASSERT(args.length() == 3); |
1990 KeyedStoreIC ic(isolate); | 2047 KeyedStoreIC ic(isolate); |
1991 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2048 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1992 Handle<Object> object = args.at<Object>(0); | 2049 Handle<Object> object = args.at<Object>(0); |
1993 Handle<Object> key = args.at<Object>(1); | 2050 Handle<Object> key = args.at<Object>(1); |
1994 Handle<Object> value = args.at<Object>(2); | 2051 Handle<Object> value = args.at<Object>(2); |
1995 StrictModeFlag strict_mode = | 2052 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); |
1996 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode); | |
1997 return Runtime::SetObjectProperty(isolate, | 2053 return Runtime::SetObjectProperty(isolate, |
1998 object, | 2054 object, |
1999 key, | 2055 key, |
2000 value, | 2056 value, |
2001 NONE, | 2057 NONE, |
2002 strict_mode); | 2058 strict_mode); |
2003 } | 2059 } |
2004 | 2060 |
2005 | 2061 |
2006 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2062 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
2007 HandleScope scope(isolate); | 2063 HandleScope scope(isolate); |
2008 ASSERT(args.length() == 3); | 2064 ASSERT(args.length() == 3); |
2009 KeyedStoreIC ic(isolate); | 2065 KeyedStoreIC ic(isolate); |
2010 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2066 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2011 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2067 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
2012 return ic.Store(state, | 2068 return ic.Store(state, |
2013 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 2069 Code::GetStrictMode(extra_ic_state), |
2014 args.at<Object>(0), | 2070 args.at<Object>(0), |
2015 args.at<Object>(1), | 2071 args.at<Object>(1), |
2016 args.at<Object>(2), | 2072 args.at<Object>(2), |
2017 true); | 2073 true); |
2018 } | 2074 } |
2019 | 2075 |
2020 | 2076 |
2021 void UnaryOpIC::patch(Code* code) { | 2077 void UnaryOpIC::patch(Code* code) { |
2022 set_target(code); | 2078 set_target(code); |
2023 } | 2079 } |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2452 #undef ADDR | 2508 #undef ADDR |
2453 }; | 2509 }; |
2454 | 2510 |
2455 | 2511 |
2456 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2512 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2457 return IC_utilities[id]; | 2513 return IC_utilities[id]; |
2458 } | 2514 } |
2459 | 2515 |
2460 | 2516 |
2461 } } // namespace v8::internal | 2517 } } // namespace v8::internal |
OLD | NEW |