OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 StoreNoWriteBarrier(MachineType::PointerRepresentation(), current.value(), | 1505 StoreNoWriteBarrier(MachineType::PointerRepresentation(), current.value(), |
1506 IntPtrConstant(first_element_offset), value); | 1506 IntPtrConstant(first_element_offset), value); |
1507 } | 1507 } |
1508 Node* compare = WordNotEqual(current.value(), limit); | 1508 Node* compare = WordNotEqual(current.value(), limit); |
1509 Branch(compare, &decrement, &done); | 1509 Branch(compare, &decrement, &done); |
1510 | 1510 |
1511 Bind(&done); | 1511 Bind(&done); |
1512 } | 1512 } |
1513 } | 1513 } |
1514 | 1514 |
1515 void CodeStubAssembler::CopyFixedArrayElements(ElementsKind kind, | 1515 void CodeStubAssembler::CopyFixedArrayElements( |
1516 compiler::Node* from_array, | 1516 ElementsKind from_kind, Node* from_array, ElementsKind to_kind, |
1517 compiler::Node* to_array, | 1517 Node* to_array, Node* element_count, Node* capacity, |
1518 compiler::Node* element_count, | 1518 WriteBarrierMode barrier_mode, ParameterMode mode) { |
1519 WriteBarrierMode barrier_mode, | 1519 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); |
1520 ParameterMode mode) { | 1520 const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag; |
1521 Label test(this); | 1521 Comment("[ CopyFixedArrayElements"); |
| 1522 |
| 1523 // Typed array elements are not supported. |
| 1524 DCHECK(!IsFixedTypedArrayElementsKind(from_kind)); |
| 1525 DCHECK(!IsFixedTypedArrayElementsKind(to_kind)); |
| 1526 |
1522 Label done(this); | 1527 Label done(this); |
1523 bool double_elements = IsFastDoubleElementsKind(kind); | 1528 bool from_double_elements = IsFastDoubleElementsKind(from_kind); |
| 1529 bool to_double_elements = IsFastDoubleElementsKind(to_kind); |
| 1530 bool element_size_matches = |
| 1531 Is64() || |
| 1532 IsFastDoubleElementsKind(from_kind) == IsFastDoubleElementsKind(to_kind); |
| 1533 bool doubles_to_objects_conversion = |
| 1534 IsFastDoubleElementsKind(from_kind) && IsFastObjectElementsKind(to_kind); |
1524 bool needs_write_barrier = | 1535 bool needs_write_barrier = |
1525 barrier_mode == UPDATE_WRITE_BARRIER && !IsFastObjectElementsKind(kind); | 1536 doubles_to_objects_conversion || (barrier_mode == UPDATE_WRITE_BARRIER && |
1526 Node* limit_offset = | 1537 IsFastObjectElementsKind(to_kind)); |
1527 ElementOffsetFromIndex(IntPtrOrSmiConstant(0, mode), kind, mode, | 1538 Node* double_hole = |
1528 FixedArray::kHeaderSize - kHeapObjectTag); | 1539 Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32); |
1529 Variable current_offset(this, MachineType::PointerRepresentation()); | |
1530 current_offset.Bind(ElementOffsetFromIndex( | |
1531 element_count, kind, mode, FixedArray::kHeaderSize - kHeapObjectTag)); | |
1532 Label decrement(this, ¤t_offset); | |
1533 | 1540 |
1534 Branch(WordEqual(current_offset.value(), limit_offset), &done, &decrement); | 1541 if (doubles_to_objects_conversion) { |
| 1542 // If the copy might trigger a GC, make sure that the FixedArray is |
| 1543 // pre-initialized with holes to make sure that it's always in a |
| 1544 // consistent state. |
| 1545 FillFixedArrayWithValue(to_kind, to_array, IntPtrOrSmiConstant(0, mode), |
| 1546 capacity, Heap::kTheHoleValueRootIndex, mode); |
| 1547 } else if (element_count != capacity) { |
| 1548 FillFixedArrayWithValue(to_kind, to_array, element_count, capacity, |
| 1549 Heap::kTheHoleValueRootIndex, mode); |
| 1550 } |
| 1551 |
| 1552 Node* limit_offset = ElementOffsetFromIndex( |
| 1553 IntPtrOrSmiConstant(0, mode), from_kind, mode, first_element_offset); |
| 1554 Variable var_from_offset(this, MachineType::PointerRepresentation()); |
| 1555 var_from_offset.Bind(ElementOffsetFromIndex(element_count, from_kind, mode, |
| 1556 first_element_offset)); |
| 1557 // This second variable is used only when the element sizes of source and |
| 1558 // destination arrays do not match. |
| 1559 Variable var_to_offset(this, MachineType::PointerRepresentation()); |
| 1560 if (element_size_matches) { |
| 1561 var_to_offset.Bind(var_from_offset.value()); |
| 1562 } else { |
| 1563 var_to_offset.Bind(ElementOffsetFromIndex(element_count, to_kind, mode, |
| 1564 first_element_offset)); |
| 1565 } |
| 1566 |
| 1567 Variable* vars[] = {&var_from_offset, &var_to_offset}; |
| 1568 Label decrement(this, 2, vars); |
| 1569 |
| 1570 Branch(WordEqual(var_from_offset.value(), limit_offset), &done, &decrement); |
1535 | 1571 |
1536 Bind(&decrement); | 1572 Bind(&decrement); |
1537 { | 1573 { |
1538 current_offset.Bind(IntPtrSub( | 1574 Node* from_offset = IntPtrSub( |
1539 current_offset.value(), | 1575 var_from_offset.value(), |
1540 IntPtrConstant(double_elements ? kDoubleSize : kPointerSize))); | 1576 IntPtrConstant(from_double_elements ? kDoubleSize : kPointerSize)); |
| 1577 var_from_offset.Bind(from_offset); |
1541 | 1578 |
1542 Node* value = | 1579 Node* to_offset; |
1543 Load(double_elements ? MachineType::Float64() : MachineType::Pointer(), | 1580 if (element_size_matches) { |
1544 from_array, current_offset.value()); | 1581 to_offset = from_offset; |
| 1582 } else { |
| 1583 to_offset = IntPtrSub( |
| 1584 var_to_offset.value(), |
| 1585 IntPtrConstant(to_double_elements ? kDoubleSize : kPointerSize)); |
| 1586 var_to_offset.Bind(to_offset); |
| 1587 } |
| 1588 |
| 1589 Label next_iter(this), store_double_hole(this); |
| 1590 Label* if_hole; |
| 1591 if (doubles_to_objects_conversion) { |
| 1592 // The target elements array is already preinitialized with holes, so we |
| 1593 // can just proceed with the next iteration. |
| 1594 if_hole = &next_iter; |
| 1595 } else if (IsFastDoubleElementsKind(to_kind)) { |
| 1596 if_hole = &store_double_hole; |
| 1597 } else { |
| 1598 // In all the other cases don't check for holes and copy the data as is. |
| 1599 if_hole = nullptr; |
| 1600 } |
| 1601 |
| 1602 Node* value = LoadElementAndPrepareForStore( |
| 1603 from_array, var_from_offset.value(), from_kind, to_kind, if_hole); |
| 1604 |
1545 if (needs_write_barrier) { | 1605 if (needs_write_barrier) { |
1546 Store(MachineType::PointerRepresentation(), to_array, | 1606 Store(MachineRepresentation::kTagged, to_array, to_offset, value); |
1547 current_offset.value(), value); | 1607 } else if (to_double_elements) { |
1548 } else if (double_elements) { | 1608 StoreNoWriteBarrier(MachineRepresentation::kFloat64, to_array, to_offset, |
1549 StoreNoWriteBarrier(MachineRepresentation::kFloat64, to_array, | 1609 value); |
1550 current_offset.value(), value); | |
1551 } else { | 1610 } else { |
1552 StoreNoWriteBarrier(MachineType::PointerRepresentation(), to_array, | 1611 StoreNoWriteBarrier(MachineType::PointerRepresentation(), to_array, |
1553 current_offset.value(), value); | 1612 to_offset, value); |
1554 } | 1613 } |
1555 Node* compare = WordNotEqual(current_offset.value(), limit_offset); | 1614 Goto(&next_iter); |
| 1615 |
| 1616 if (if_hole == &store_double_hole) { |
| 1617 Bind(&store_double_hole); |
| 1618 // Don't use doubles to store the hole double, since manipulating the |
| 1619 // signaling NaN used for the hole in C++, e.g. with bit_cast, will |
| 1620 // change its value on ia32 (the x87 stack is used to return values |
| 1621 // and stores to the stack silently clear the signalling bit). |
| 1622 // |
| 1623 // TODO(danno): When we have a Float32/Float64 wrapper class that |
| 1624 // preserves double bits during manipulation, remove this code/change |
| 1625 // this to an indexed Float64 store. |
| 1626 if (Is64()) { |
| 1627 StoreNoWriteBarrier(MachineRepresentation::kWord64, to_array, to_offset, |
| 1628 double_hole); |
| 1629 } else { |
| 1630 StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array, to_offset, |
| 1631 double_hole); |
| 1632 StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array, |
| 1633 IntPtrAdd(to_offset, IntPtrConstant(kPointerSize)), |
| 1634 double_hole); |
| 1635 } |
| 1636 Goto(&next_iter); |
| 1637 } |
| 1638 |
| 1639 Bind(&next_iter); |
| 1640 Node* compare = WordNotEqual(from_offset, limit_offset); |
1556 Branch(compare, &decrement, &done); | 1641 Branch(compare, &decrement, &done); |
1557 } | 1642 } |
1558 | 1643 |
1559 Bind(&done); | 1644 Bind(&done); |
| 1645 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); |
| 1646 Comment("] CopyFixedArrayElements"); |
| 1647 } |
| 1648 |
| 1649 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, |
| 1650 Node* offset, |
| 1651 ElementsKind from_kind, |
| 1652 ElementsKind to_kind, |
| 1653 Label* if_hole) { |
| 1654 if (IsFastDoubleElementsKind(from_kind)) { |
| 1655 Node* value = |
| 1656 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); |
| 1657 if (!IsFastDoubleElementsKind(to_kind)) { |
| 1658 value = AllocateHeapNumberWithValue(value); |
| 1659 } |
| 1660 return value; |
| 1661 |
| 1662 } else { |
| 1663 Node* value = Load(MachineType::Pointer(), array, offset); |
| 1664 if (if_hole) { |
| 1665 GotoIf(WordEqual(value, TheHoleConstant()), if_hole); |
| 1666 } |
| 1667 if (IsFastDoubleElementsKind(to_kind)) { |
| 1668 if (IsFastSmiElementsKind(from_kind)) { |
| 1669 value = SmiToFloat64(value); |
| 1670 } else { |
| 1671 value = LoadHeapNumberValue(value); |
| 1672 } |
| 1673 } |
| 1674 return value; |
| 1675 } |
1560 } | 1676 } |
1561 | 1677 |
1562 Node* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity, | 1678 Node* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity, |
1563 ParameterMode mode) { | 1679 ParameterMode mode) { |
1564 Node* half_old_capacity = WordShr(old_capacity, IntPtrConstant(1)); | 1680 Node* half_old_capacity = WordShr(old_capacity, IntPtrConstant(1)); |
1565 Node* new_capacity = IntPtrAdd(half_old_capacity, old_capacity); | 1681 Node* new_capacity = IntPtrAdd(half_old_capacity, old_capacity); |
1566 Node* unconditioned_result = | 1682 Node* unconditioned_result = |
1567 IntPtrAdd(new_capacity, IntPtrOrSmiConstant(16, mode)); | 1683 IntPtrAdd(new_capacity, IntPtrOrSmiConstant(16, mode)); |
1568 if (mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS) { | 1684 if (mode == INTEGER_PARAMETERS || mode == INTPTR_PARAMETERS) { |
1569 return unconditioned_result; | 1685 return unconditioned_result; |
(...skipping 2635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4205 Heap::kTheHoleValueRootIndex); | 4321 Heap::kTheHoleValueRootIndex); |
4206 | 4322 |
4207 // Store the WeakCell in the feedback vector. | 4323 // Store the WeakCell in the feedback vector. |
4208 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 4324 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
4209 CodeStubAssembler::SMI_PARAMETERS); | 4325 CodeStubAssembler::SMI_PARAMETERS); |
4210 return cell; | 4326 return cell; |
4211 } | 4327 } |
4212 | 4328 |
4213 } // namespace internal | 4329 } // namespace internal |
4214 } // namespace v8 | 4330 } // namespace v8 |
OLD | NEW |