| 1506 | | auto isshared = ti.classinfo is TypeInfo_Shared.classinfo; |
|---|
| 1507 | | auto bic = !isshared ? __getBlkInfo(px.data) : null; |
|---|
| 1508 | | auto info = bic ? *bic : gc_query(px.data); |
|---|
| 1509 | | auto length = px.length; |
|---|
| 1510 | | auto newlength = length + y.length; |
|---|
| 1511 | | auto newsize = newlength * sizeelem; |
|---|
| 1512 | | auto size = length * sizeelem; |
|---|
| 1513 | | |
|---|
| 1514 | | // calculate the extent of the array given the base. |
|---|
| 1515 | | size_t offset = px.data - __arrayStart(info); |
|---|
| 1516 | | if(info.attr & BlkAttr.APPENDABLE) |
|---|
| 1517 | | { |
|---|
| 1518 | | if(info.size >= PAGESIZE) |
|---|
| 1519 | | { |
|---|
| 1520 | | // size of array is at the front of the block |
|---|
| 1521 | | if(!__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| 1522 | | { |
|---|
| 1523 | | // check to see if it failed because there is not |
|---|
| 1524 | | // enough space |
|---|
| 1525 | | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| 1526 | | if(*(cast(size_t*)info.base) == size + offset) |
|---|
| 1527 | | { |
|---|
| 1528 | | // not enough space, try extending |
|---|
| 1529 | | auto extendoffset = offset + LARGEPAD - info.size; |
|---|
| 1530 | | auto u = gc_extend(px.data, newsize + extendoffset, newcap + extendoffset); |
|---|
| 1531 | | if(u) |
|---|
| 1532 | | { |
|---|
| 1533 | | // extend worked, now try setting the length |
|---|
| 1534 | | // again. |
|---|
| 1535 | | info.size = u; |
|---|
| 1536 | | if(__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| 1537 | | { |
|---|
| 1538 | | if(!isshared) |
|---|
| 1539 | | __insertBlkInfoCache(info, bic); |
|---|
| 1540 | | goto L1; |
|---|
| 1541 | | } |
|---|
| 1542 | | } |
|---|
| 1543 | | } |
|---|
| 1544 | | |
|---|
| 1545 | | // couldn't do it, reallocate |
|---|
| 1546 | | info = gc_qalloc(newcap + LARGEPAD, info.attr); |
|---|
| 1547 | | __setArrayAllocLength(info, newsize, isshared); |
|---|
| 1548 | | if(!isshared) |
|---|
| 1549 | | __insertBlkInfoCache(info, bic); |
|---|
| 1550 | | auto newdata = cast(byte *)info.base + LARGEPREFIX; |
|---|
| 1551 | | memcpy(newdata, px.data, length * sizeelem); |
|---|
| 1552 | | px.data = newdata; |
|---|
| 1553 | | } |
|---|
| 1554 | | else if(!isshared && !bic) |
|---|
| 1555 | | { |
|---|
| 1556 | | __insertBlkInfoCache(info, null); |
|---|
| 1557 | | } |
|---|
| 1558 | | } |
|---|
| 1559 | | else if(!__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| 1560 | | { |
|---|
| 1561 | | // could not resize in place |
|---|
| 1562 | | auto allocsize = newCapacity(newlength, sizeelem); |
|---|
| 1563 | | info = gc_qalloc(allocsize + __arrayPad(allocsize), info.attr); |
|---|
| 1564 | | goto L2; |
|---|
| 1565 | | } |
|---|
| 1566 | | else if(!isshared && !bic) |
|---|
| 1567 | | { |
|---|
| 1568 | | __insertBlkInfoCache(info, null); |
|---|
| 1569 | | } |
|---|
| 1570 | | } |
|---|
| 1571 | | else |
|---|
| 1572 | | { |
|---|
| 1573 | | // not appendable or is null |
|---|
| 1574 | | auto allocsize = newCapacity(newlength, sizeelem); |
|---|
| 1575 | | info = gc_qalloc(allocsize + __arrayPad(allocsize), (info.base ? info.attr : !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0) | BlkAttr.APPENDABLE); |
|---|
| 1576 | | L2: |
|---|
| 1577 | | __setArrayAllocLength(info, newsize, isshared); |
|---|
| 1578 | | if(!isshared) |
|---|
| 1579 | | __insertBlkInfoCache(info, bic); |
|---|
| 1580 | | auto newdata = cast(byte *)__arrayStart(info); |
|---|
| 1581 | | memcpy(newdata, px.data, length * sizeelem); |
|---|
| 1582 | | px.data = newdata; |
|---|
| 1583 | | } |
|---|
| 1584 | | |
|---|
| 1585 | | |
|---|
| 1586 | | L1: |
|---|
| 1587 | | px.length = newlength; |
|---|
| 1588 | | memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); |
|---|
| 1589 | | return *cast(void[]*)px; |
|---|
| | 1505 | _d_arrayappendcTX(ti, x, y.length); |
|---|
| | 1506 | memcpy(x.ptr + length * sizeelem, y.ptr, y.length * sizeelem); |
|---|
| | 1507 | return x; |
|---|
| | 1631 | /************************************** |
|---|
| | 1632 | * Extend an array by n elements. |
|---|
| | 1633 | * Caller must initialize those elements. |
|---|
| | 1634 | */ |
|---|
| | 1635 | extern (C) |
|---|
| | 1636 | byte[] _d_arrayappendcTX(TypeInfo ti, ref byte[] px, size_t n) |
|---|
| | 1637 | { |
|---|
| | 1638 | // This is a cut&paste job from _d_arrayappendT(). Should be refactored. |
|---|
| | 1639 | |
|---|
| | 1640 | // only optimize array append where ti is not a shared type |
|---|
| | 1641 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 1642 | auto isshared = ti.classinfo is TypeInfo_Shared.classinfo; |
|---|
| | 1643 | auto bic = !isshared ? __getBlkInfo(px.ptr) : null; |
|---|
| | 1644 | auto info = bic ? *bic : gc_query(px.ptr); |
|---|
| | 1645 | auto length = px.length; |
|---|
| | 1646 | auto newlength = length + n; |
|---|
| | 1647 | auto newsize = newlength * sizeelem; |
|---|
| | 1648 | auto size = length * sizeelem; |
|---|
| | 1649 | |
|---|
| | 1650 | // calculate the extent of the array given the base. |
|---|
| | 1651 | size_t offset = px.ptr - __arrayStart(info); |
|---|
| | 1652 | if(info.attr & BlkAttr.APPENDABLE) |
|---|
| | 1653 | { |
|---|
| | 1654 | if(info.size >= PAGESIZE) |
|---|
| | 1655 | { |
|---|
| | 1656 | // size of array is at the front of the block |
|---|
| | 1657 | if(!__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| | 1658 | { |
|---|
| | 1659 | // check to see if it failed because there is not |
|---|
| | 1660 | // enough space |
|---|
| | 1661 | auto newcap = newCapacity(newlength, sizeelem); |
|---|
| | 1662 | if(*(cast(size_t*)info.base) == size + offset) |
|---|
| | 1663 | { |
|---|
| | 1664 | // not enough space, try extending |
|---|
| | 1665 | auto extendoffset = offset + LARGEPAD - info.size; |
|---|
| | 1666 | auto u = gc_extend(px.ptr, newsize + extendoffset, newcap + extendoffset); |
|---|
| | 1667 | if(u) |
|---|
| | 1668 | { |
|---|
| | 1669 | // extend worked, now try setting the length |
|---|
| | 1670 | // again. |
|---|
| | 1671 | info.size = u; |
|---|
| | 1672 | if(__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| | 1673 | { |
|---|
| | 1674 | if(!isshared) |
|---|
| | 1675 | __insertBlkInfoCache(info, bic); |
|---|
| | 1676 | goto L1; |
|---|
| | 1677 | } |
|---|
| | 1678 | } |
|---|
| | 1679 | } |
|---|
| | 1680 | |
|---|
| | 1681 | // couldn't do it, reallocate |
|---|
| | 1682 | info = gc_qalloc(newcap + LARGEPAD, info.attr); |
|---|
| | 1683 | __setArrayAllocLength(info, newsize, isshared); |
|---|
| | 1684 | if(!isshared) |
|---|
| | 1685 | __insertBlkInfoCache(info, bic); |
|---|
| | 1686 | auto newdata = cast(byte *)info.base + LARGEPREFIX; |
|---|
| | 1687 | memcpy(newdata, px.ptr, length * sizeelem); |
|---|
| | 1688 | (cast(void **)(&px))[1] = newdata; |
|---|
| | 1689 | } |
|---|
| | 1690 | else if(!isshared && !bic) |
|---|
| | 1691 | { |
|---|
| | 1692 | __insertBlkInfoCache(info, null); |
|---|
| | 1693 | } |
|---|
| | 1694 | } |
|---|
| | 1695 | else if(!__setArrayAllocLength(info, newsize + offset, isshared, size + offset)) |
|---|
| | 1696 | { |
|---|
| | 1697 | // could not resize in place |
|---|
| | 1698 | auto allocsize = newCapacity(newlength, sizeelem); |
|---|
| | 1699 | info = gc_qalloc(allocsize + __arrayPad(allocsize), info.attr); |
|---|
| | 1700 | goto L2; |
|---|
| | 1701 | } |
|---|
| | 1702 | else if(!isshared && !bic) |
|---|
| | 1703 | { |
|---|
| | 1704 | __insertBlkInfoCache(info, null); |
|---|
| | 1705 | } |
|---|
| | 1706 | } |
|---|
| | 1707 | else |
|---|
| | 1708 | { |
|---|
| | 1709 | // not appendable or is null |
|---|
| | 1710 | auto allocsize = newCapacity(newlength, sizeelem); |
|---|
| | 1711 | info = gc_qalloc(allocsize + __arrayPad(allocsize), (info.base ? info.attr : !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0) | BlkAttr.APPENDABLE); |
|---|
| | 1712 | L2: |
|---|
| | 1713 | __setArrayAllocLength(info, newsize, isshared); |
|---|
| | 1714 | if(!isshared) |
|---|
| | 1715 | __insertBlkInfoCache(info, bic); |
|---|
| | 1716 | auto newdata = cast(byte *)__arrayStart(info); |
|---|
| | 1717 | memcpy(newdata, px.ptr, length * sizeelem); |
|---|
| | 1718 | (cast(void **)(&px))[1] = newdata; |
|---|
| | 1719 | } |
|---|
| | 1720 | |
|---|
| | 1721 | L1: |
|---|
| | 1722 | *cast(size_t *)&px = newlength; |
|---|
| | 1723 | return px; |
|---|
| | 1724 | } |
|---|
| | 1725 | |
|---|
| | 1726 | |
|---|
| 1926 | | * |
|---|
| | 1940 | * Allocate the array, rely on the caller to do the initialization of the array. |
|---|
| | 1941 | */ |
|---|
| | 1942 | extern (C) |
|---|
| | 1943 | void* _d_arrayliteralTX(TypeInfo ti, size_t length) |
|---|
| | 1944 | { |
|---|
| | 1945 | auto sizeelem = ti.next.tsize(); // array element size |
|---|
| | 1946 | void* result; |
|---|
| | 1947 | |
|---|
| | 1948 | //printf("_d_arrayliteralTX(sizeelem = %d, length = %d)\n", sizeelem, length); |
|---|
| | 1949 | if (length == 0 || sizeelem == 0) |
|---|
| | 1950 | result = null; |
|---|
| | 1951 | else |
|---|
| | 1952 | { |
|---|
| | 1953 | auto allocsize = length * sizeelem; |
|---|
| | 1954 | auto info = gc_qalloc(allocsize + __arrayPad(allocsize), !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN | BlkAttr.APPENDABLE : BlkAttr.APPENDABLE); |
|---|
| | 1955 | auto isshared = ti.classinfo is TypeInfo_Shared.classinfo; |
|---|
| | 1956 | __setArrayAllocLength(info, allocsize, isshared); |
|---|
| | 1957 | result = __arrayStart(info); |
|---|
| | 1958 | } |
|---|
| | 1959 | return result; |
|---|
| | 1960 | } |
|---|
| | 1961 | |
|---|
| | 1962 | /** |
|---|
| | 1963 | * The old way, obsolete. |
|---|