19 if (list->
ids == NULL) abort();
34 if (list->
ids == NULL)
return false;
46 assert(index < list->capacity);
49 list->
ids[index] = id;
58 for (
size_t index = 0; index < list->
size; index++) {
59 if (list->
ids[index] ==
id)
return true;
69 if (list->
ids != NULL) {
78 static inline uint32_t
79 pm_constant_pool_hash(
const uint8_t *start,
size_t length) {
81 uint32_t value = 5381;
83 for (
size_t index = 0; index < length; index++) {
84 value = ((value << 5) + value) + start[index];
94 next_power_of_two(uint32_t v) {
112 is_power_of_two(uint32_t size) {
113 return (size & (size - 1)) == 0;
122 assert(is_power_of_two(pool->
capacity));
124 uint32_t next_capacity = pool->
capacity * 2;
125 if (next_capacity < pool->capacity)
return false;
127 const uint32_t mask = next_capacity - 1;
130 void *next =
xcalloc(next_capacity, element_size);
131 if (next == NULL)
return false;
138 for (uint32_t index = 0; index < pool->
capacity; index++) {
144 uint32_t next_index = bucket->
hash & mask;
150 next_index = (next_index + 1) & mask;
155 next_buckets[next_index] = *bucket;
176 const uint32_t maximum = (~((uint32_t) 0));
177 if (capacity >= ((maximum / 2) + 1))
return false;
179 capacity = next_power_of_two(capacity);
181 void *memory =
xcalloc(capacity, element_size);
182 if (memory == NULL)
return false;
197 return &pool->
constants[constant_id - 1];
206 assert(is_power_of_two(pool->
capacity));
207 const uint32_t mask = pool->
capacity - 1;
209 uint32_t hash = pm_constant_pool_hash(start, length);
210 uint32_t index = hash & mask;
215 if ((constant->
length == length) && memcmp(constant->
start, start, length) == 0) {
219 index = (index + 1) & mask;
234 assert(is_power_of_two(pool->
capacity));
235 const uint32_t mask = pool->
capacity - 1;
237 uint32_t hash = pm_constant_pool_hash(start, length);
238 uint32_t index = hash & mask;
247 if ((constant->
length == length) && memcmp(constant->
start, start, length) == 0) {
256 xfree((
void *) start);
262 constant->
start = start;
269 index = (index + 1) & mask;
274 uint32_t
id = ++pool->
size;
275 assert(pool->
size < ((uint32_t) (1 << 30)));
278 .
id = (
unsigned int) (
id & 0x3fffffff),
279 .type = (
unsigned int) (
type & 0x3),
327 for (uint32_t index = 0; index < pool->
capacity; index++) {
#define xfree
Old name of ruby_xfree.
#define xrealloc
Old name of ruby_xrealloc.
#define xcalloc
Old name of ruby_xcalloc.
VALUE type(ANYARGS)
ANYARGS-ed function type.
A data structure that stores a set of strings.
pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length)
Find a constant in a constant pool.
static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT
By default, each constant is a slice of the source.
#define PM_CONSTANT_ID_UNSET
When we allocate constants into the pool, we reserve 0 to mean that the slot is not yet filled.
bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity)
Initialize a new constant pool with a given capacity.
pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, size_t length)
Insert a constant into a constant pool that is a slice of a source string.
void pm_constant_id_list_init(pm_constant_id_list_t *list)
Initialize a list of constant ids.
unsigned int pm_constant_pool_bucket_type_t
The type of bucket in the constant pool hash map.
void pm_constant_id_list_free(pm_constant_id_list_t *list)
Free the memory associated with a list of constant ids.
pm_constant_id_t pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length)
Insert a constant into a constant pool from memory that is constant.
uint32_t pm_constant_id_t
A constant id is a unique identifier for a constant in the constant pool.
void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id)
Insert a constant id into a list of constant ids at the specified index.
bool pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id)
Append a constant id to a list of constant ids.
pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t *start, size_t length)
Insert a constant into a constant pool from memory that is now owned by the constant pool.
static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED
An owned constant is one for which memory has been allocated.
void pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity)
Initialize a list of constant ids with a given capacity.
pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id)
Return a pointer to the constant indicated by the given constant id.
static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT
A constant constant is known at compile time.
bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id)
Checks if the current constant id list includes the given constant id.
void pm_constant_pool_free(pm_constant_pool_t *pool)
Free the memory associated with a constant pool.
size_t size
The number of constant ids in the list.
size_t capacity
The number of constant ids that have been allocated in the list.
pm_constant_id_t * ids
The constant ids in the list.
A bucket in the hash map.
uint32_t hash
The hash of the bucket.
unsigned int id
The incremental ID used for indexing back into the pool.
pm_constant_pool_bucket_type_t type
The type of the bucket, which determines how to free it.
The overall constant pool, which stores constants found while parsing.
uint32_t capacity
The number of buckets that have been allocated in the hash map.
pm_constant_pool_bucket_t * buckets
The buckets in the hash map.
uint32_t size
The number of buckets in the hash map.
pm_constant_t * constants
The constants that are stored in the buckets.
A constant in the pool which effectively stores a string.
size_t length
The length of the string.
const uint8_t * start
A pointer to the start of the string.