diff options
author | Mike Pall <mike> | 2011-02-05 14:09:50 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-02-05 14:09:50 +0100 |
commit | 223d85aa06a30dcf4bfdbdda38114c49e9bc6cbe (patch) | |
tree | 6815c9210fcac4874fe686ebe16d17bc043f375e /src/lj_record.c | |
parent | c29ed4dbbf9089c6a7ba22c785e342c12862cbd8 (diff) | |
download | luajit-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.c | 38 |
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 | } |