summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc.c7
-rw-r--r--hash.c16
-rw-r--r--internal/hash.h16
3 files changed, 22 insertions, 17 deletions
diff --git a/gc.c b/gc.c
index 3cf3bdebce..8a0d051e8f 100644
--- a/gc.c
+++ b/gc.c
@@ -3601,7 +3601,12 @@ rb_gc_obj_optimal_size(VALUE obj)
}
case T_HASH:
- return sizeof(struct RHash) + (RHASH_ST_TABLE_P(obj) ? sizeof(st_table) : sizeof(ar_table));
+ {
+ if (RB_OBJ_FROZEN(obj) && RHASH_AR_TABLE_P(obj)) {
+ return sizeof(struct RHash) + offsetof(ar_table, pairs) + RHASH_AR_TABLE_BOUND(obj) * sizeof(ar_table_pair);
+ }
+ return sizeof(struct RHash) + (RHASH_ST_TABLE_P(obj) ? sizeof(st_table) : sizeof(ar_table));
+ }
default:
return 0;
diff --git a/hash.c b/hash.c
index 751d4564d5..4321f479fd 100644
--- a/hash.c
+++ b/hash.c
@@ -471,24 +471,8 @@ ar_set_entry(VALUE hash, unsigned int index, st_data_t key, st_data_t val, st_ha
#define RHASH_AR_TABLE_SIZE(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
RHASH_AR_TABLE_SIZE_RAW(h))
-#define RHASH_AR_TABLE_BOUND_RAW(h) \
- ((unsigned int)((RBASIC(h)->flags >> RHASH_AR_TABLE_BOUND_SHIFT) & \
- (RHASH_AR_TABLE_BOUND_MASK >> RHASH_AR_TABLE_BOUND_SHIFT)))
-
-#define RHASH_ST_TABLE_SET(h, s) rb_hash_st_table_set(h, s)
-#define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
-
#define HASH_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(HASH_DEBUG, expr, #expr)
-static inline unsigned int
-RHASH_AR_TABLE_BOUND(VALUE h)
-{
- HASH_ASSERT(RHASH_AR_TABLE_P(h));
- const unsigned int bound = RHASH_AR_TABLE_BOUND_RAW(h);
- HASH_ASSERT(bound <= RHASH_AR_TABLE_MAX_SIZE);
- return bound;
-}
-
#if HASH_DEBUG
#define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
diff --git a/internal/hash.h b/internal/hash.h
index 3a5be14ad7..8c5511e82b 100644
--- a/internal/hash.h
+++ b/internal/hash.h
@@ -193,4 +193,20 @@ RHASH_AR_TABLE_SIZE_RAW(VALUE h)
return (unsigned)ret;
}
+#define RHASH_AR_TABLE_BOUND_RAW(h) \
+ ((unsigned int)((RBASIC(h)->flags >> RHASH_AR_TABLE_BOUND_SHIFT) & \
+ (RHASH_AR_TABLE_BOUND_MASK >> RHASH_AR_TABLE_BOUND_SHIFT)))
+
+#define RHASH_ST_TABLE_SET(h, s) rb_hash_st_table_set(h, s)
+#define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
+
+static inline unsigned int
+RHASH_AR_TABLE_BOUND(VALUE h)
+{
+ RUBY_ASSERT(RHASH_AR_TABLE_P(h));
+ const unsigned int bound = RHASH_AR_TABLE_BOUND_RAW(h);
+ RUBY_ASSERT(bound <= RHASH_AR_TABLE_MAX_SIZE);
+ return bound;
+}
+
#endif /* INTERNAL_HASH_H */