aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2011-04-05 00:25:31 +0200
committerMike Pall <mike>2011-04-05 00:25:31 +0200
commit314995aebf20ce47f854cdab3722085c944f9e74 (patch)
tree58f295ee039768e9529dd90c9ea283a93975bbfb
parenta7874cb29970b72fec106e6a8a4f22c42a15e580 (diff)
downloadluajit-314995aebf20ce47f854cdab3722085c944f9e74.tar.gz
luajit-314995aebf20ce47f854cdab3722085c944f9e74.tar.bz2
luajit-314995aebf20ce47f854cdab3722085c944f9e74.zip
ARM: Finish basic table indexing and add metamethod handlers.
-rw-r--r--src/buildvm_arm.dasc351
1 files changed, 335 insertions, 16 deletions
diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc
index b0b87ebf..e6c66de3 100644
--- a/src/buildvm_arm.dasc
+++ b/src/buildvm_arm.dasc
@@ -53,6 +53,11 @@
53|.define SAVE_MULTRES, [sp, #4] 53|.define SAVE_MULTRES, [sp, #4]
54|.define ARG5, [sp] 54|.define ARG5, [sp]
55| 55|
56|.define TMPDhi, [sp, #4]
57|.define TMPDlo, [sp]
58|.define TMPD, [sp]
59|.define TMPDp, sp
60|
56|.macro saveregs 61|.macro saveregs
57| push {r4, r5, r6, r7, r8, r9, r10, r11, lr} 62| push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
58| sub sp, sp, CFRAME_SPACE 63| sub sp, sp, CFRAME_SPACE
@@ -189,6 +194,15 @@
189|.macro mv_vmstate, reg, st; mvn reg, #LJ_VMST_..st; .endmacro 194|.macro mv_vmstate, reg, st; mvn reg, #LJ_VMST_..st; .endmacro
190|.macro st_vmstate, reg; str reg, [DISPATCH, #DISPATCH_GL(vmstate)]; .endmacro 195|.macro st_vmstate, reg; str reg, [DISPATCH, #DISPATCH_GL(vmstate)]; .endmacro
191| 196|
197|// Move table write barrier back. Overwrites mark and tmp.
198|.macro barrierback, tab, mark, tmp
199| ldr tmp, [DISPATCH, #DISPATCH_GL(gc.grayagain)]
200| bic mark, mark, #LJ_GC_BLACK // black2gray(tab)
201| str tab, [DISPATCH, #DISPATCH_GL(gc.grayagain)]
202| strb mark, tab->marked
203| str tmp, tab->gclist
204|.endmacro
205|
192|//----------------------------------------------------------------------- 206|//-----------------------------------------------------------------------
193 207
194#if !LJ_DUALNUM 208#if !LJ_DUALNUM
@@ -417,25 +431,113 @@ static void build_subroutines(BuildCtx *ctx)
417 | 431 |
418 |//-- Table indexing metamethods ----------------------------------------- 432 |//-- Table indexing metamethods -----------------------------------------
419 | 433 |
434 |->vmeta_tgets1:
435 | add CARG2, BASE, RB
436 | b >2
437 |
420 |->vmeta_tgets: 438 |->vmeta_tgets:
421 | NYI 439 | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv)
440 | mvn CARG4, #~LJ_TTAB
441 | str TAB:RB, [CARG2]
442 | str CARG4, [CARG2, #4]
443 |2:
444 | mvn CARG4, #~LJ_TISNUM
445 | str STR:RC, TMPDlo
446 | str CARG4, TMPDhi
447 | mov CARG3, TMPDp
448 | b >1
422 | 449 |
423 |->vmeta_tgetb: 450 |->vmeta_tgetb: // RC = index
424 | NYI 451 | decode_RB8 RB, INS
452 | str RC, TMPDlo
453 | mvn CARG4, #~LJ_TISNUM
454 | add CARG2, BASE, RB
455 | str CARG4, TMPDhi
456 | mov CARG3, TMPDp
457 | b >1
425 | 458 |
426 |->vmeta_tgetv: 459 |->vmeta_tgetv:
427 | NYI 460 | add CARG2, BASE, RB
461 | add CARG3, BASE, RC
462 |1:
463 | str BASE, L->base
464 | mov CARG1, L
465 | str PC, SAVE_PC
466 | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
467 | // Returns TValue * (finished) or NULL (metamethod).
468 | cmp CRET1, #0
469 | beq >3
470 | ldrd CARG34, [CRET1]
471 | ins_next1
472 | ins_next2
473 | strd CARG34, [BASE, RA]
474 | ins_next3
475 |
476 |3: // Call __index metamethod.
477 | // BASE = base, L->top = new base, stack = cont/func/t/k
478 | rsb CARG1, BASE, #FRAME_CONT
479 | ldr BASE, L->top
480 | mov NARGS8:RC, #16 // 2 args for func(t, k).
481 | str PC, [BASE, #-12] // [cont|PC]
482 | add PC, CARG1, BASE
483 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
484 | b ->vm_call_dispatch_f
428 | 485 |
429 |//----------------------------------------------------------------------- 486 |//-----------------------------------------------------------------------
430 | 487 |
488 |->vmeta_tsets1:
489 | add CARG2, BASE, RB
490 | b >2
491 |
431 |->vmeta_tsets: 492 |->vmeta_tsets:
432 | NYI 493 | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv)
494 | mvn CARG4, #~LJ_TTAB
495 | str TAB:RB, [CARG2]
496 | str CARG4, [CARG2, #4]
497 |2:
498 | mvn CARG4, #~LJ_TISNUM
499 | str STR:RC, TMPDlo
500 | str CARG4, TMPDhi
501 | mov CARG3, TMPDp
502 | b >1
433 | 503 |
434 |->vmeta_tsetb: 504 |->vmeta_tsetb: // RC = index
435 | NYI 505 | decode_RB8 RB, INS
506 | str RC, TMPDlo
507 | mvn CARG4, #~LJ_TISNUM
508 | add CARG2, BASE, RB
509 | str CARG4, TMPDhi
510 | mov CARG3, TMPDp
511 | b >1
436 | 512 |
437 |->vmeta_tsetv: 513 |->vmeta_tsetv:
438 | NYI 514 | add CARG2, BASE, RB
515 | add CARG3, BASE, RC
516 |1:
517 | str BASE, L->base
518 | mov CARG1, L
519 | str PC, SAVE_PC
520 | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
521 | // Returns TValue * (finished) or NULL (metamethod).
522 | cmp CRET1, #0
523 | ldrd CARG34, [BASE, RA]
524 | beq >3
525 | ins_next1
526 | // NOBARRIER: lj_meta_tset ensures the table is not black.
527 | strd CARG34, [CRET1]
528 | ins_next2
529 | ins_next3
530 |
531 |3: // Call __newindex metamethod.
532 | // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
533 | rsb CARG1, BASE, #FRAME_CONT
534 | ldr BASE, L->top
535 | mov NARGS8:RC, #24 // 3 args for func(t, k, v).
536 | strd CARG34, [BASE, #16] // Copy value to third argument.
537 | str PC, [BASE, #-12] // [cont|PC]
538 | add PC, CARG1, BASE
539 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
540 | b ->vm_call_dispatch_f
439 | 541 |
440 |//-- Comparison metamethods --------------------------------------------- 542 |//-- Comparison metamethods ---------------------------------------------
441 | 543 |
@@ -1462,7 +1564,43 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
1462 break; 1564 break;
1463 1565
1464 case BC_TGETV: 1566 case BC_TGETV:
1465 | NYI 1567 | decode_RB8 RB, INS
1568 | decode_RC8 RC, INS
1569 | // RA = dst*8, RB = table*8, RC = key*8
1570 | ldrd TAB:CARG12, [BASE, RB]
1571 | ldrd CARG34, [BASE, RC]
1572 | checktab CARG2, ->vmeta_tgetv // STALL: load CARG12.
1573 | checktp CARG4, LJ_TISNUM // Integer key?
1574 | ldreq CARG4, TAB:CARG1->array
1575 | ldreq CARG2, TAB:CARG1->asize
1576 | bne >9
1577 |
1578 | add CARG4, CARG4, CARG3, lsl #3
1579 | cmp CARG3, CARG2 // In array part?
1580 | ldrdlo CARG34, [CARG4]
1581 | bhs ->vmeta_tgetv
1582 | ins_next1
1583 | checktp CARG4, LJ_TNIL
1584 | beq >5
1585 |1:
1586 | ins_next2
1587 | strd CARG34, [BASE, RA]
1588 | ins_next3
1589 |
1590 |5: // Check for __index if table value is nil.
1591 | ldr TAB:CARG2, TAB:CARG1->metatable
1592 | cmp TAB:CARG2, #0
1593 | beq <1 // No metatable: done.
1594 | ldrb CARG2, TAB:CARG2->nomm
1595 | tst CARG2, #1<<MM_index
1596 | bne <1 // 'no __index' flag set: done.
1597 | b ->vmeta_tgetv
1598 |
1599 |9:
1600 | checktp CARG4, LJ_TSTR // String key?
1601 | moveq STR:RC, CARG3
1602 | beq ->BC_TGETS_Z
1603 | b ->vmeta_tgetv
1466 break; 1604 break;
1467 case BC_TGETS: 1605 case BC_TGETS:
1468 | decode_RB8 RB, INS 1606 | decode_RB8 RB, INS
@@ -1471,7 +1609,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
1471 | ldrd CARG12, [BASE, RB] 1609 | ldrd CARG12, [BASE, RB]
1472 | mvn RC, RC 1610 | mvn RC, RC
1473 | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC. 1611 | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC.
1474 | checktab CARG2, ->vmeta_tgets 1612 | checktab CARG2, ->vmeta_tgets1
1475 |->BC_TGETS_Z: 1613 |->BC_TGETS_Z:
1476 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 1614 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8
1477 | ldr CARG3, TAB:CARG1->hmask 1615 | ldr CARG3, TAB:CARG1->hmask
@@ -1506,25 +1644,206 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
1506 | mov CARG3, #0 // Optional clear of undef. value (during load stall). 1644 | mov CARG3, #0 // Optional clear of undef. value (during load stall).
1507 | mvn CARG4, #~LJ_TNIL 1645 | mvn CARG4, #~LJ_TNIL
1508 | cmp TAB:CARG1, #0 1646 | cmp TAB:CARG1, #0
1509 | beq <3 // No metatable: done. 1647 | beq <3 // No metatable: done.
1510 | ldrb CARG2, TAB:CARG1->nomm 1648 | ldrb CARG2, TAB:CARG1->nomm
1511 | tst CARG2, #1<<MM_index 1649 | tst CARG2, #1<<MM_index
1512 | bne <3 // 'no __index' flag set: done. 1650 | bne <3 // 'no __index' flag set: done.
1513 | b ->vmeta_tgets 1651 | b ->vmeta_tgets
1514 break; 1652 break;
1515 case BC_TGETB: 1653 case BC_TGETB:
1516 | NYI 1654 | decode_RB8 RB, INS
1655 | and RC, RC, #255
1656 | // RA = dst*8, RB = table*8, RC = index
1657 | ldrd CARG12, [BASE, RB]
1658 | checktab CARG2, ->vmeta_tgetb // STALL: load CARG12.
1659 | ldr CARG3, TAB:CARG1->asize
1660 | ldr CARG4, TAB:CARG1->array
1661 | lsl CARG2, RC, #3
1662 | cmp RC, CARG3
1663 | ldrdlo CARG34, [CARG4, CARG2]
1664 | bhs ->vmeta_tgetb
1665 | ins_next1 // Overwrites RB!
1666 | checktp CARG4, LJ_TNIL
1667 | beq >5
1668 |1:
1669 | ins_next2
1670 | strd CARG34, [BASE, RA]
1671 | ins_next3
1672 |
1673 |5: // Check for __index if table value is nil.
1674 | ldr TAB:CARG2, TAB:CARG1->metatable
1675 | cmp TAB:CARG2, #0
1676 | beq <1 // No metatable: done.
1677 | ldrb CARG2, TAB:CARG2->nomm
1678 | tst CARG2, #1<<MM_index
1679 | bne <1 // 'no __index' flag set: done.
1680 | b ->vmeta_tgetb
1517 break; 1681 break;
1518 1682
1519 case BC_TSETV: 1683 case BC_TSETV:
1520 | NYI 1684 | decode_RB8 RB, INS
1685 | decode_RC8 RC, INS
1686 | // RA = src*8, RB = table*8, RC = key*8
1687 | ldrd TAB:CARG12, [BASE, RB]
1688 | ldrd CARG34, [BASE, RC]
1689 | checktab CARG2, ->vmeta_tsetv // STALL: load CARG12.
1690 | checktp CARG4, LJ_TISNUM // Integer key?
1691 | ldreq CARG2, TAB:CARG1->array
1692 | ldreq CARG4, TAB:CARG1->asize
1693 | bne >9
1694 |
1695 | add CARG2, CARG2, CARG3, lsl #3
1696 | cmp CARG3, CARG4 // In array part?
1697 | ldrlo INS, [CARG2, #4]
1698 | bhs ->vmeta_tsetv
1699 | ins_next1 // Overwrites RB!
1700 | checktp INS, LJ_TNIL
1701 | ldrb INS, TAB:CARG1->marked
1702 | ldrd CARG34, [BASE, RA]
1703 | beq >5
1704 |1:
1705 | tst INS, #LJ_GC_BLACK // isblack(table)
1706 | strd CARG34, [CARG2]
1707 | bne >7
1708 |2:
1709 | ins_next2
1710 | ins_next3
1711 |
1712 |5: // Check for __newindex if previous value is nil.
1713 | ldr TAB:RA, TAB:CARG1->metatable
1714 | cmp TAB:RA, #0
1715 | beq <1 // No metatable: done.
1716 | ldrb RA, TAB:RA->nomm
1717 | tst RA, #1<<MM_newindex
1718 | bne <1 // 'no __newindex' flag set: done.
1719 | ldr INS, [PC, #-4] // Restore RA.
1720 | decode_RA8 RA, INS
1721 | b ->vmeta_tsetv
1722 |
1723 |7: // Possible table write barrier for the value. Skip valiswhite check.
1724 | barrierback TAB:CARG1, INS, CARG3
1725 | b <2
1726 |
1727 |9:
1728 | checktp CARG4, LJ_TSTR // String key?
1729 | moveq STR:RC, CARG3
1730 | beq ->BC_TSETS_Z
1731 | b ->vmeta_tsetv
1521 break; 1732 break;
1522 case BC_TSETS: 1733 case BC_TSETS:
1734 | decode_RB8 RB, INS
1735 | and RC, RC, #255
1736 | // RA = src*8, RB = table*8, RC = str_const (~)
1737 | ldrd CARG12, [BASE, RB]
1738 | mvn RC, RC
1739 | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC.
1740 | checktab CARG2, ->vmeta_tsets1
1523 |->BC_TSETS_Z: 1741 |->BC_TSETS_Z:
1524 | NYI 1742 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8
1743 | ldr CARG3, TAB:CARG1->hmask
1744 | ldr CARG4, STR:RC->hash
1745 | ldr NODE:INS, TAB:CARG1->node
1746 | mov TAB:RB, TAB:CARG1
1747 | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask
1748 | add CARG3, CARG3, CARG3, lsl #1
1749 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8
1750 |1:
1751 | ldrd CARG12, NODE:INS->key // STALL: early NODE:INS.
1752 | ldr CARG4, NODE:INS->val.it
1753 | ldr NODE:CARG3, NODE:INS->next
1754 | cmp CARG1, STR:RC
1755 | checktpeq CARG2, LJ_TSTR
1756 | bne >5
1757 | ldrb CARG2, TAB:RB->marked
1758 | checktp CARG4, LJ_TNIL // Key found, but nil value?
1759 | ldrd CARG34, [BASE, RA]
1760 | beq >4
1761 |2:
1762 | tst CARG2, #LJ_GC_BLACK // isblack(table)
1763 | strd CARG34, NODE:INS->val
1764 | bne >7
1765 |3:
1766 | ins_next
1767 |
1768 |4: // Check for __newindex if previous value is nil.
1769 | ldr TAB:CARG1, TAB:RB->metatable
1770 | cmp TAB:CARG1, #0
1771 | beq <2 // No metatable: done.
1772 | ldrb CARG1, TAB:CARG1->nomm
1773 | tst CARG1, #1<<MM_newindex
1774 | bne <2 // 'no __newindex' flag set: done.
1775 | b ->vmeta_tsets
1776 |
1777 |5: // Follow hash chain.
1778 | movs NODE:INS, NODE:CARG3
1779 | bne <1
1780 | // End of hash chain: key not found, add a new one.
1781 |
1782 | // But check for __newindex first.
1783 | ldr TAB:CARG1, TAB:RB->metatable
1784 | mov CARG3, TMPDp
1785 | str PC, SAVE_PC
1786 | cmp TAB:CARG1, #0 // No metatable: continue.
1787 | str BASE, L->base
1788 | ldrbne CARG2, TAB:CARG1->nomm
1789 | mov CARG1, L
1790 | beq >6
1791 | tst CARG2, #1<<MM_newindex
1792 | beq ->vmeta_tsets // 'no __newindex' flag NOT set: check.
1793 |6:
1794 | mvn CARG4, #~LJ_TSTR
1795 | str STR:RC, TMPDlo
1796 | mov CARG2, TAB:RB
1797 | str CARG4, TMPDhi
1798 | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k)
1799 | // Returns TValue *.
1800 | ldr BASE, L->base
1801 | ldrd CARG34, [BASE, RA]
1802 | strd CARG34, [CRET1]
1803 | b <3 // No 2nd write barrier needed.
1804 |
1805 |7: // Possible table write barrier for the value. Skip valiswhite check.
1806 | barrierback TAB:CARG1, CARG2, CARG3
1807 | b <3
1525 break; 1808 break;
1526 case BC_TSETB: 1809 case BC_TSETB:
1527 | NYI 1810 | decode_RB8 RB, INS
1811 | and RC, RC, #255
1812 | // RA = src*8, RB = table*8, RC = index
1813 | ldrd CARG12, [BASE, RB]
1814 | checktab CARG2, ->vmeta_tsetb // STALL: load CARG12.
1815 | ldr CARG3, TAB:CARG1->asize
1816 | ldr RB, TAB:CARG1->array
1817 | lsl CARG2, RC, #3
1818 | cmp RC, CARG3
1819 | ldrdlo CARG34, [CARG2, RB]!
1820 | bhs ->vmeta_tsetb
1821 | ins_next1 // Overwrites RB!
1822 | checktp CARG4, LJ_TNIL
1823 | ldrb INS, TAB:CARG1->marked
1824 | ldrd CARG34, [BASE, RA]
1825 | beq >5
1826 |1:
1827 | tst INS, #LJ_GC_BLACK // isblack(table)
1828 | strd CARG34, [CARG2]
1829 | bne >7
1830 |2:
1831 | ins_next2
1832 | ins_next3
1833 |
1834 |5: // Check for __newindex if previous value is nil.
1835 | ldr TAB:RA, TAB:CARG1->metatable
1836 | cmp TAB:RA, #0
1837 | beq <1 // No metatable: done.
1838 | ldrb RA, TAB:RA->nomm
1839 | tst RA, #1<<MM_newindex
1840 | bne <1 // 'no __newindex' flag set: done.
1841 | ldr INS, [PC, #-4] // Restore INS.
1842 | b ->vmeta_tsetb
1843 |
1844 |7: // Possible table write barrier for the value. Skip valiswhite check.
1845 | barrierback TAB:CARG1, INS, CARG3
1846 | b <2
1528 break; 1847 break;
1529 1848
1530 case BC_TSETM: 1849 case BC_TSETM: