Browse Source

PPC: Add getmetatable(), setmetatable() and rawget() fast functions.

Mike Pall 15 years ago
parent
commit
08ac8b0c96
1 changed files with 72 additions and 4 deletions
  1. 72 4
      src/buildvm_ppc.dasc

+ 72 - 4
src/buildvm_ppc.dasc

@@ -240,6 +240,7 @@
 |.macro checkok, label; blt label; .endmacro
 |.macro checkfail, label; bge label; .endmacro
 |.macro checkanyfail, label; bns label; .endmacro
+|.macro checkallok, label; bso label; .endmacro
 |.endif
 |
 |.macro branch_RD
@@ -950,13 +951,80 @@ static void build_subroutines(BuildCtx *ctx)
   |//-- Base library: getters and setters ---------------------------------
   |
   |.ffunc_1 getmetatable
-  |  NYI
+  |  checktab CARG1
+  |   evmergehi TMP1, CARG1, CARG1
+  |  checkfail >6
+  |1:  // Field metatable must be at same offset for GCtab and GCudata!
+  |  lwz TAB:RB, TAB:CARG1->metatable
+  |2:
+  |  evmr CRET1, TISNIL
+  |   cmplwi TAB:RB, 0
+  |  lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH)
+  |   beq ->fff_restv
+  |  lwz TMP0, TAB:RB->hmask
+  |   evmergelo CRET1, TISTAB, TAB:RB	// Use metatable as default result.
+  |  lwz TMP1, STR:RC->hash
+  |  lwz NODE:TMP2, TAB:RB->node
+  |   evmergelo STR:RC, TISSTR, STR:RC
+  |  and TMP1, TMP1, TMP0		// idx = str->hash & tab->hmask
+  |  slwi TMP0, TMP1, 5
+  |  slwi TMP1, TMP1, 3
+  |  sub TMP1, TMP0, TMP1
+  |  add NODE:TMP2, NODE:TMP2, TMP1	// node = tab->node + (idx*32-idx*8)
+  |3:  // Rearranged logic, because we expect _not_ to find the key.
+  |  evldd TMP0, NODE:TMP2->key
+  |   evldd TMP1, NODE:TMP2->val
+  |  evcmpeq TMP0, STR:RC
+  |   lwz NODE:TMP2, NODE:TMP2->next
+  |  checkallok >5
+  |   cmplwi NODE:TMP2, 0
+  |   beq ->fff_restv			// Not found, keep default result.
+  |   b <3
+  |5:
+  |  checknil TMP1
+  |  checkok ->fff_restv		// Ditto for nil value.
+  |  evmr CRET1, TMP1			// Return value of mt.__metatable.
+  |  b ->fff_restv
+  |
+  |6:
+  |  cmpwi TMP1, LJ_TUDATA
+  |   not TMP1, TMP1
+  |  beq <1
+  |  checknum CARG1
+  |   slwi TMP1, TMP1, 2
+  |   li TMP2, 4*~LJ_TNUMX
+  |  isellt TMP1, TMP2, TMP1
+  |   la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH)
+  |  lwzx TAB:RB, TMP2, TMP1
+  |  b <2
   |
   |.ffunc_2 setmetatable
-  |  NYI
+  |  // Fast path: no mt for table yet and not clearing the mt.
+  |  evmergehi TMP0, TAB:CARG1, TAB:CARG2
+  |  checktab TMP0
+  |  checkanyfail ->fff_fallback
+  |  lwz TAB:TMP1, TAB:CARG1->metatable
+  |  cmplwi TAB:TMP1, 0
+  |   lbz TMP3, TAB:CARG1->marked
+  |  bne ->fff_fallback
+  |   andi. TMP0, TMP3, LJ_GC_BLACK	// isblack(table)
+  |    stw TAB:CARG2, TAB:CARG1->metatable
+  |   beq ->fff_restv
+  |  barrierback TAB:CARG1, TMP3, TMP0
+  |  b ->fff_restv
   |
-  |.ffunc_2 rawget
-  |  NYI
+  |.ffunc rawget
+  |  cmplwi NARGS8:RC, 16
+  |   evldd CARG2, 0(BASE)
+  |  blt ->fff_fallback
+  |  checktab CARG2
+  |   la CARG3, 8(BASE)
+  |  checkfail ->fff_fallback
+  |   mr CARG1, L
+  |  bl extern lj_tab_get  // (lua_State *L, GCtab *t, cTValue *key)
+  |  // Returns cTValue *.
+  |  evldd CRET1, 0(CRET1)
+  |  b ->fff_restv
   |
   |//-- Base library: conversions ------------------------------------------
   |