summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2011-02-05 14:09:50 +0100
committerMike Pall <mike>2011-02-05 14:09:50 +0100
commit223d85aa06a30dcf4bfdbdda38114c49e9bc6cbe (patch)
tree6815c9210fcac4874fe686ebe16d17bc043f375e /src/lj_record.c
parentc29ed4dbbf9089c6a7ba22c785e342c12862cbd8 (diff)
downloadluajit-223d85aa06a30dcf4bfdbdda38114c49e9bc6cbe.tar.gz
luajit-223d85aa06a30dcf4bfdbdda38114c49e9bc6cbe.tar.bz2
luajit-223d85aa06a30dcf4bfdbdda38114c49e9bc6cbe.zip
Treat metatables of special userdata objects as immutable.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index f1dd8e3e..e9841102 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -661,7 +661,32 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
661 mt = tabref(tabV(&ix->tabv)->metatable); 661 mt = tabref(tabV(&ix->tabv)->metatable);
662 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META); 662 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META);
663 } else if (tref_isudata(ix->tab)) { 663 } else if (tref_isudata(ix->tab)) {
664 int udtype = udataV(&ix->tabv)->udtype;
664 mt = tabref(udataV(&ix->tabv)->metatable); 665 mt = tabref(udataV(&ix->tabv)->metatable);
666 /* The metatables of special userdata objects are treated as immutable. */
667 if (udtype != UDTYPE_USERDATA) {
668 cTValue *mo;
669 if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) {
670 /* Specialize to the C library namespace object. */
671 emitir(IRTG(IR_EQ, IRT_P32), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv)));
672 } else {
673 /* Specialize to the type of userdata. */
674 TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE);
675 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, udtype));
676 }
677 immutable_mt:
678 mo = lj_tab_getstr(mt, mmname_str(J2G(J), mm));
679 if (!mo || tvisnil(mo))
680 return 0; /* No metamethod. */
681 /* Treat metamethod or index table as immutable, too. */
682 if (!(tvisfunc(mo) || tvistab(mo)))
683 lj_trace_err(J, LJ_TRERR_BADTYPE);
684 copyTV(J->L, &ix->mobjv, mo);
685 ix->mobj = lj_ir_kgc(J, gcV(mo), tvisfunc(mo) ? IRT_FUNC : IRT_TAB);
686 ix->mtv = mt;
687 ix->mt = TREF_NIL; /* Dummy value for comparison semantics. */
688 return 1; /* Got metamethod or index table. */
689 }
665 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_UDATA_META); 690 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_UDATA_META);
666 } else { 691 } else {
667 /* Specialize to base metatable. Must flush mcode in lua_setmetatable(). */ 692 /* Specialize to base metatable. Must flush mcode in lua_setmetatable(). */
@@ -670,19 +695,8 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
670 ix->mt = TREF_NIL; 695 ix->mt = TREF_NIL;
671 return 0; /* No metamethod. */ 696 return 0; /* No metamethod. */
672 } 697 }
673#if LJ_HASFFI
674 /* The cdata metatable is treated as immutable. */ 698 /* The cdata metatable is treated as immutable. */
675 if (tref_iscdata(ix->tab)) { 699 if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt;
676 cTValue *mo = lj_tab_getstr(mt, mmname_str(J2G(J), mm));
677 if (!mo || tvisnil(mo))
678 return 0; /* No metamethod. */
679 setfuncV(J->L, &ix->mobjv, funcV(mo));
680 ix->mobj = lj_ir_kfunc(J, funcV(mo)); /* Immutable metamethod. */
681 ix->mtv = mt;
682 ix->mt = TREF_NIL; /* Dummy value for comparison semantics. */
683 return 1; /* Got cdata metamethod. */
684 }
685#endif
686 ix->mt = mix.tab = lj_ir_ktab(J, mt); 700 ix->mt = mix.tab = lj_ir_ktab(J, mt);
687 goto nocheck; 701 goto nocheck;
688 } 702 }