@@ -107,10 +107,10 @@ yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity) {
107
107
}
108
108
109
109
// Insert a constant into a constant pool and return its index in the pool.
110
- static size_t
111
- yp_constant_pool_insert (yp_constant_pool_t * pool , const uint8_t * start , size_t length ) {
110
+ static inline yp_constant_id_t
111
+ yp_constant_pool_insert (yp_constant_pool_t * pool , const uint8_t * start , size_t length , bool owned ) {
112
112
if (pool -> size >= (pool -> capacity / 4 * 3 )) {
113
- if (!yp_constant_pool_resize (pool )) return pool -> capacity ;
113
+ if (!yp_constant_pool_resize (pool )) return 0 ;
114
114
}
115
115
116
116
size_t hash = yp_constant_pool_hash (start , length );
@@ -122,7 +122,24 @@ yp_constant_pool_insert(yp_constant_pool_t *pool, const uint8_t *start, size_t l
122
122
// same as the content we are trying to insert. If it is, then we can
123
123
// return the id of the existing constant.
124
124
if ((constant -> length == length ) && memcmp (constant -> start , start , length ) == 0 ) {
125
- return index ;
125
+ // Since we have found a match, we need to check if this is
126
+ // attempting to insert a shared or an owned constant. We want to
127
+ // prefer shared constants since they don't require allocations.
128
+ if (owned ) {
129
+ // If we're attempting to insert an owned constant and we have
130
+ // an existing constant, then either way we don't want the given
131
+ // memory. Either it's duplicated with the existing constant or
132
+ // it's not necessary because we have a shared version.
133
+ free ((void * ) start );
134
+ } else if (constant -> owned ) {
135
+ // If we're attempting to insert a shared constant and the
136
+ // existing constant is owned, then we can free the owned
137
+ // constant and replace it with the shared constant.
138
+ free ((void * ) constant -> start );
139
+ constant -> start = start ;
140
+ }
141
+
142
+ return constant -> id ;
126
143
}
127
144
128
145
index = (index + 1 ) % pool -> capacity ;
@@ -131,35 +148,30 @@ yp_constant_pool_insert(yp_constant_pool_t *pool, const uint8_t *start, size_t l
131
148
pool -> size ++ ;
132
149
assert (pool -> size < ((size_t ) (1 << 31 )));
133
150
134
- pool -> constants [ index ] = (yp_constant_t ) {
151
+ * constant = (yp_constant_t ) {
135
152
.id = (unsigned int ) (pool -> size & 0x7FFFFFFF ),
153
+ .owned = owned & 0x1 ,
136
154
.start = start ,
137
155
.length = length ,
138
156
.hash = hash
139
157
};
140
158
141
- return index ;
159
+ return constant -> id ;
142
160
}
143
161
144
162
// Insert a constant into a constant pool. Returns the id of the constant, or 0
145
163
// if any potential calls to resize fail.
146
164
yp_constant_id_t
147
165
yp_constant_pool_insert_shared (yp_constant_pool_t * pool , const uint8_t * start , size_t length ) {
148
- size_t index = yp_constant_pool_insert (pool , start , length );
149
- return index == pool -> capacity ? 0 : ((yp_constant_id_t ) pool -> constants [index ].id );
166
+ return yp_constant_pool_insert (pool , start , length , false);
150
167
}
151
168
152
169
// Insert a constant into a constant pool from memory that is now owned by the
153
170
// constant pool. Returns the id of the constant, or 0 if any potential calls to
154
171
// resize fail.
155
172
yp_constant_id_t
156
173
yp_constant_pool_insert_owned (yp_constant_pool_t * pool , const uint8_t * start , size_t length ) {
157
- size_t index = yp_constant_pool_insert (pool , start , length );
158
- if (index == pool -> capacity ) return 0 ;
159
-
160
- yp_constant_t * constant = & pool -> constants [index ];
161
- constant -> owned = true;
162
- return ((yp_constant_id_t ) constant -> id );
174
+ return yp_constant_pool_insert (pool , start , length , true);
163
175
}
164
176
165
177
// Free the memory associated with a constant pool.
0 commit comments