diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1996-02-12 15:32:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1996-02-12 15:32:40 -0300 |
commit | 41259bff31dbb904edfb8070006ccb15577f8f04 (patch) | |
tree | 664bf9cbe6394e9074435ecf2bd710712b4537c3 /tree.c | |
parent | afaa98a666acd5f596b50f56bb288815838c096e (diff) | |
download | lua-41259bff31dbb904edfb8070006ccb15577f8f04.tar.gz lua-41259bff31dbb904edfb8070006ccb15577f8f04.tar.bz2 lua-41259bff31dbb904edfb8070006ccb15577f8f04.zip |
BIG CHANGE: new data structure for constants, strings and globals, using
an array of hash tables for all them.
Diffstat (limited to 'tree.c')
-rw-r--r-- | tree.c | 152 |
1 files changed, 92 insertions, 60 deletions
@@ -3,7 +3,7 @@ | |||
3 | ** TecCGraf - PUC-Rio | 3 | ** TecCGraf - PUC-Rio |
4 | */ | 4 | */ |
5 | 5 | ||
6 | char *rcs_tree="$Id: tree.c,v 1.14 1995/10/17 11:53:53 roberto Exp roberto $"; | 6 | char *rcs_tree="$Id: tree.c,v 1.15 1996/01/26 18:03:19 roberto Exp $"; |
7 | 7 | ||
8 | 8 | ||
9 | #include <string.h> | 9 | #include <string.h> |
@@ -11,68 +11,98 @@ char *rcs_tree="$Id: tree.c,v 1.14 1995/10/17 11:53:53 roberto Exp roberto $"; | |||
11 | #include "mem.h" | 11 | #include "mem.h" |
12 | #include "lua.h" | 12 | #include "lua.h" |
13 | #include "tree.h" | 13 | #include "tree.h" |
14 | #include "hash.h" | ||
14 | #include "table.h" | 15 | #include "table.h" |
15 | 16 | ||
16 | 17 | ||
17 | #define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b))) | 18 | #define lua_streq(a,b) (a[0] == b[0] && strcmp(a,b) == 0) |
18 | 19 | ||
20 | #define NUM_HASHS 64 | ||
19 | 21 | ||
20 | typedef struct StringNode { | 22 | typedef struct { |
21 | struct StringNode *next; | 23 | int size; |
22 | TaggedString ts; | 24 | int nuse; /* number of elements (including EMPTYs) */ |
23 | } StringNode; | 25 | TaggedString **hash; |
26 | } stringtable; | ||
24 | 27 | ||
25 | static StringNode *string_root = NULL; | 28 | static stringtable string_root[NUM_HASHS]; |
26 | 29 | ||
27 | static TreeNode *constant_root = NULL; | 30 | static TaggedString EMPTY = {NOT_USED, NOT_USED, 0, 0, {0}}; |
28 | 31 | ||
29 | /* | 32 | static unsigned long hash (char *str) |
30 | ** Insert a new constant/variable at the tree. | ||
31 | */ | ||
32 | static TreeNode *tree_create (TreeNode **node, char *str) | ||
33 | { | 33 | { |
34 | if (*node == NULL) | 34 | unsigned long h = 0; |
35 | { | 35 | while (*str) |
36 | *node = (TreeNode *) luaI_malloc(sizeof(TreeNode)+strlen(str)); | 36 | h = ((h<<5)-h)^(unsigned char)*(str++); |
37 | (*node)->left = (*node)->right = NULL; | 37 | return h; |
38 | strcpy((*node)->ts.str, str); | ||
39 | (*node)->ts.marked = 0; | ||
40 | (*node)->ts.hash = 0; | ||
41 | (*node)->varindex = (*node)->constindex = NOT_USED; | ||
42 | return *node; | ||
43 | } | ||
44 | else | ||
45 | { | ||
46 | int c = lua_strcmp(str, (*node)->ts.str); | ||
47 | if (c < 0) | ||
48 | return tree_create(&(*node)->left, str); | ||
49 | else if (c > 0) | ||
50 | return tree_create(&(*node)->right, str); | ||
51 | else | ||
52 | return *node; | ||
53 | } | ||
54 | } | 38 | } |
55 | 39 | ||
56 | TaggedString *lua_createstring (char *str) | 40 | static void grow (stringtable *tb) |
57 | { | 41 | { |
58 | StringNode *newString; | 42 | int newsize = luaI_redimension(tb->size); |
59 | if (str == NULL) return NULL; | 43 | TaggedString **newhash = newvector(newsize, TaggedString *); |
60 | lua_pack(); | 44 | int i; |
61 | newString = (StringNode *)luaI_malloc(sizeof(StringNode)+strlen(str)); | 45 | for (i=0; i<newsize; i++) |
62 | newString->ts.marked = 0; | 46 | newhash[i] = NULL; |
63 | newString->ts.hash = 0; | 47 | if (tb->size > 0) |
64 | strcpy(newString->ts.str, str); | 48 | { /* rehash */ |
65 | newString->next = string_root; | 49 | tb->nuse = 0; |
66 | string_root = newString; | 50 | for (i=0; i<tb->size; i++) |
67 | return &(newString->ts); | 51 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) |
52 | { | ||
53 | int h = tb->hash[i]->hash%newsize; | ||
54 | while (newhash[h]) | ||
55 | h = (h+1)%newsize; | ||
56 | newhash[h] = tb->hash[i]; | ||
57 | tb->nuse++; | ||
58 | } | ||
59 | luaI_free(tb->hash); | ||
60 | } | ||
61 | tb->size = newsize; | ||
62 | tb->hash = newhash; | ||
68 | } | 63 | } |
69 | 64 | ||
65 | static TaggedString *insert (char *str, stringtable *tb) | ||
66 | { | ||
67 | TaggedString *ts; | ||
68 | unsigned long h = hash(str); | ||
69 | int i; | ||
70 | int j = -1; | ||
71 | if ((Long)tb->nuse*3 >= (Long)tb->size*2) | ||
72 | grow(tb); | ||
73 | i = h%tb->size; | ||
74 | while (tb->hash[i]) | ||
75 | { | ||
76 | if (tb->hash[i] == &EMPTY) | ||
77 | j = i; | ||
78 | else if (lua_streq(str, tb->hash[i]->str)) | ||
79 | return tb->hash[i]; | ||
80 | i = (i+1)%tb->size; | ||
81 | } | ||
82 | /* not found */ | ||
83 | if (j != -1) /* is there an EMPTY space? */ | ||
84 | i = j; | ||
85 | else | ||
86 | tb->nuse++; | ||
87 | ts = tb->hash[i] = (TaggedString *)luaI_malloc(sizeof(TaggedString)+strlen(str)); | ||
88 | strcpy(ts->str, str); | ||
89 | ts->marked = 0; | ||
90 | ts->hash = h; | ||
91 | ts->varindex = ts->constindex = NOT_USED; | ||
92 | return ts; | ||
93 | } | ||
70 | 94 | ||
71 | TreeNode *lua_constcreate (char *str) | 95 | TaggedString *lua_createstring (char *str) |
72 | { | 96 | { |
73 | return tree_create(&constant_root, str); | 97 | return insert(str, &string_root[(unsigned)str[0]%NUM_HASHS]); |
74 | } | 98 | } |
75 | 99 | ||
100 | TaggedString *luaI_createfixedstring (char *str) | ||
101 | { | ||
102 | TaggedString *ts = lua_createstring(str); | ||
103 | ts->marked = 2; /* to avoid GC */ | ||
104 | return ts; | ||
105 | } | ||
76 | 106 | ||
77 | /* | 107 | /* |
78 | ** Garbage collection function. | 108 | ** Garbage collection function. |
@@ -80,26 +110,28 @@ TreeNode *lua_constcreate (char *str) | |||
80 | */ | 110 | */ |
81 | Long lua_strcollector (void) | 111 | Long lua_strcollector (void) |
82 | { | 112 | { |
83 | StringNode *curr = string_root, *prev = NULL; | ||
84 | Long counter = 0; | 113 | Long counter = 0; |
85 | while (curr) | 114 | int i; |
115 | for (i=0; i<NUM_HASHS; i++) | ||
86 | { | 116 | { |
87 | StringNode *next = curr->next; | 117 | stringtable *tb = &string_root[i]; |
88 | if (!curr->ts.marked) | 118 | int j; |
89 | { | 119 | for (j=0; j<tb->size; j++) |
90 | if (prev == NULL) string_root = next; | ||
91 | else prev->next = next; | ||
92 | luaI_free(curr); | ||
93 | ++counter; | ||
94 | } | ||
95 | else | ||
96 | { | 120 | { |
97 | curr->ts.marked = 0; | 121 | TaggedString *t = tb->hash[j]; |
98 | prev = curr; | 122 | if (t != NULL && t != &EMPTY && t->marked != 2) |
123 | { | ||
124 | if (t->marked) | ||
125 | t->marked = 0; | ||
126 | else | ||
127 | { | ||
128 | luaI_free(t); | ||
129 | tb->hash[j] = &EMPTY; | ||
130 | counter++; | ||
131 | } | ||
132 | } | ||
99 | } | 133 | } |
100 | curr = next; | ||
101 | } | 134 | } |
102 | return counter; | 135 | return counter; |
103 | } | 136 | } |
104 | 137 | ||
105 | |||