aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ltable.c81
1 files changed, 63 insertions, 18 deletions
diff --git a/ltable.c b/ltable.c
index eb5abf9f..f6785367 100644
--- a/ltable.c
+++ b/ltable.c
@@ -981,14 +981,19 @@ lu_byte luaH_getshortstr (Table *t, TString *key, TValue *res) {
981} 981}
982 982
983 983
984static 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
984static const TValue *Hgetstr (Table *t, TString *key) { 992static 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*/
1037static 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
1028static int finishnodeset (Table *t, const TValue *slot, TValue *val) { 1045static 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
1063int luaH_psetshortstr (Table *t, TString *key, TValue *val) { 1086int 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
1068int luaH_psetstr (Table *t, TString *key, TValue *val) { 1112int 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
1097void luaH_finishset (lua_State *L, Table *t, const TValue *key, 1142void 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);