diff options
-rw-r--r-- | ltable.c | 81 |
1 files changed, 63 insertions, 18 deletions
@@ -981,14 +981,19 @@ lu_byte luaH_getshortstr (Table *t, TString *key, TValue *res) { | |||
981 | } | 981 | } |
982 | 982 | ||
983 | 983 | ||
984 | static const TValue *Hgetlongstr (Table *t, TString *key) { | ||
985 | TValue ko; | ||
986 | lua_assert(!strisshr(key)); | ||
987 | setsvalue(cast(lua_State *, NULL), &ko, key); | ||
988 | return getgeneric(t, &ko, 0); /* for long strings, use generic case */ | ||
989 | } | ||
990 | |||
991 | |||
984 | static const TValue *Hgetstr (Table *t, TString *key) { | 992 | static const TValue *Hgetstr (Table *t, TString *key) { |
985 | if (key->tt == LUA_VSHRSTR) | 993 | if (strisshr(key)) |
986 | return luaH_Hgetshortstr(t, key); | 994 | return luaH_Hgetshortstr(t, key); |
987 | else { /* for long strings, use generic case */ | 995 | else |
988 | TValue ko; | 996 | return Hgetlongstr(t, key); |
989 | setsvalue(cast(lua_State *, NULL), &ko, key); | ||
990 | return getgeneric(t, &ko, 0); | ||
991 | } | ||
992 | } | 997 | } |
993 | 998 | ||
994 | 999 | ||
@@ -1025,15 +1030,25 @@ lu_byte luaH_get (Table *t, const TValue *key, TValue *res) { | |||
1025 | } | 1030 | } |
1026 | 1031 | ||
1027 | 1032 | ||
1033 | /* | ||
1034 | ** When a 'pset' cannot be completed, this function returns an encoding | ||
1035 | ** of its result, to be used by 'luaH_finishset'. | ||
1036 | */ | ||
1037 | static int retpsetcode (Table *t, const TValue *slot) { | ||
1038 | if (isabstkey(slot)) | ||
1039 | return HNOTFOUND; /* no slot with that key */ | ||
1040 | else /* return node encoded */ | ||
1041 | return cast_int((cast(Node*, slot) - t->node)) + HFIRSTNODE; | ||
1042 | } | ||
1043 | |||
1044 | |||
1028 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { | 1045 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { |
1029 | if (!ttisnil(slot)) { | 1046 | if (!ttisnil(slot)) { |
1030 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | 1047 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); |
1031 | return HOK; /* success */ | 1048 | return HOK; /* success */ |
1032 | } | 1049 | } |
1033 | else if (isabstkey(slot)) | 1050 | else |
1034 | return HNOTFOUND; /* no slot with that key */ | 1051 | return retpsetcode(t, slot); |
1035 | else /* return node encoded */ | ||
1036 | return cast_int((cast(Node*, slot) - t->node)) + HFIRSTNODE; | ||
1037 | } | 1052 | } |
1038 | 1053 | ||
1039 | 1054 | ||
@@ -1060,13 +1075,45 @@ static int psetint (Table *t, lua_Integer key, TValue *val) { | |||
1060 | } | 1075 | } |
1061 | 1076 | ||
1062 | 1077 | ||
1078 | /* | ||
1079 | ** This function could be just this: | ||
1080 | ** return finishnodeset(t, luaH_Hgetshortstr(t, key), val); | ||
1081 | ** However, it optimizes the common case created by constructors (e.g., | ||
1082 | ** {x=1, y=2}), which creates a key in a table that has no metatable, | ||
1083 | ** it is not old/black, and it already has space for the key. | ||
1084 | */ | ||
1085 | |||
1063 | int luaH_psetshortstr (Table *t, TString *key, TValue *val) { | 1086 | int luaH_psetshortstr (Table *t, TString *key, TValue *val) { |
1064 | return finishnodeset(t, luaH_Hgetshortstr(t, key), val); | 1087 | const TValue *slot = luaH_Hgetshortstr(t, key); |
1088 | if (!ttisnil(slot)) { /* key already has a value? (all too common) */ | ||
1089 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); /* update it */ | ||
1090 | return HOK; /* done */ | ||
1091 | } | ||
1092 | else if (checknoTM(t->metatable, TM_NEWINDEX)) { /* no metamethod? */ | ||
1093 | if (ttisnil(val)) /* new value is nil? */ | ||
1094 | return HOK; /* done (value is already nil/absent) */ | ||
1095 | if (isabstkey(slot) && /* key is absent? */ | ||
1096 | !(isblack(t) && iswhite(key))) { /* and don't need barrier? */ | ||
1097 | TValue tk; /* key as a TValue */ | ||
1098 | setsvalue(cast(lua_State *, NULL), &tk, key); | ||
1099 | if (insertkey(t, &tk, val)) { /* insert key, if there is space */ | ||
1100 | invalidateTMcache(t); | ||
1101 | return HOK; | ||
1102 | } | ||
1103 | } | ||
1104 | } | ||
1105 | /* Else, either table has new-index metamethod, or it needs barrier, | ||
1106 | or it needs to rehash for the new key. In any of these cases, the | ||
1107 | operation cannot be completed here. Return a code for the caller. */ | ||
1108 | return retpsetcode(t, slot); | ||
1065 | } | 1109 | } |
1066 | 1110 | ||
1067 | 1111 | ||
1068 | int luaH_psetstr (Table *t, TString *key, TValue *val) { | 1112 | int luaH_psetstr (Table *t, TString *key, TValue *val) { |
1069 | return finishnodeset(t, Hgetstr(t, key), val); | 1113 | if (strisshr(key)) |
1114 | return luaH_psetshortstr(t, key, val); | ||
1115 | else | ||
1116 | return finishnodeset(t, Hgetlongstr(t, key), val); | ||
1070 | } | 1117 | } |
1071 | 1118 | ||
1072 | 1119 | ||
@@ -1087,13 +1134,11 @@ int luaH_pset (Table *t, const TValue *key, TValue *val) { | |||
1087 | } | 1134 | } |
1088 | 1135 | ||
1089 | /* | 1136 | /* |
1090 | ** Finish a raw "set table" operation, where 'slot' is where the value | 1137 | ** Finish a raw "set table" operation, where 'hres' encodes where the |
1091 | ** should have been (the result of a previous "get table"). | 1138 | ** value should have been (the result of a previous 'pset' operation). |
1092 | ** Beware: when using this function you probably need to check a GC | 1139 | ** Beware: when using this function the caller probably need to check a |
1093 | ** barrier and invalidate the TM cache. | 1140 | ** GC barrier and invalidate the TM cache. |
1094 | */ | 1141 | */ |
1095 | |||
1096 | |||
1097 | void luaH_finishset (lua_State *L, Table *t, const TValue *key, | 1142 | void luaH_finishset (lua_State *L, Table *t, const TValue *key, |
1098 | TValue *value, int hres) { | 1143 | TValue *value, int hres) { |
1099 | lua_assert(hres != HOK); | 1144 | lua_assert(hres != HOK); |