summaryrefslogtreecommitdiff
path: root/internal/hash.h
diff options
context:
space:
mode:
Diffstat (limited to 'internal/hash.h')
-rw-r--r--internal/hash.h140
1 files changed, 58 insertions, 82 deletions
diff --git a/internal/hash.h b/internal/hash.h
index 90a27fd189..0386a5009c 100644
--- a/internal/hash.h
+++ b/internal/hash.h
@@ -1,17 +1,16 @@
-#ifndef INTERNAL_HASH_H /* -*- C -*- */
+#ifndef INTERNAL_HASH_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_HASH_H
/**
- * @file
- * @brief Internal header for Hash.
- * @author \@shyouhei
+ * @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
+ * @brief Internal header for Hash.
*/
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#include <stddef.h> /* for size_t */
-#include "internal/stdbool.h" /* for bool */
+#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for struct RBasic */
#include "ruby/st.h" /* for struct st_table */
@@ -29,10 +28,6 @@ enum ruby_rhash_flags {
RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */
RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8),
-#if USE_TRANSIENT_HEAP
- RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */
-#endif
-
// we can not put it in "enum" because it can exceed "int" range.
#define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \
FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19)
@@ -41,20 +36,26 @@ enum ruby_rhash_flags {
RHASH_LEV_MAX = 127, /* 7 bits */
};
-struct RHash {
- struct RBasic basic;
- union {
- st_table *st;
- struct ar_table_struct *ar; /* possibly 0 */
- } as;
- const VALUE ifnone;
+typedef struct ar_table_pair_struct {
+ VALUE key;
+ VALUE val;
+} ar_table_pair;
+
+typedef struct ar_table_struct {
union {
ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE];
VALUE word;
} ar_hint;
+ /* 64bit CPU: 8B * 2 * 8 = 128B */
+ ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE];
+} ar_table;
+
+struct RHash {
+ struct RBasic basic;
+ const VALUE ifnone;
};
-#define RHASH(obj) (R_CAST(RHash)(obj))
+#define RHASH(obj) ((struct RHash *)(obj))
#ifdef RHASH_IFNONE
# undef RHASH_IFNONE
@@ -64,12 +65,18 @@ struct RHash {
# undef RHASH_SIZE
#endif
+#ifdef RHASH_EMPTY_P
+# undef RHASH_EMPTY_P
+#endif
+
/* hash.c */
-void rb_hash_st_table_set(VALUE hash, st_table *st);
VALUE rb_hash_default_value(VALUE hash, VALUE key);
+VALUE rb_hash_set_default(VALUE hash, VALUE ifnone);
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
long rb_dbl_long_hash(double d);
st_table *rb_init_identtable(void);
+st_index_t rb_any_hash(VALUE a);
+int rb_any_cmp(VALUE a, VALUE b);
VALUE rb_to_hash_type(VALUE obj);
VALUE rb_hash_key_str(VALUE);
VALUE rb_hash_values(VALUE hash);
@@ -79,18 +86,22 @@ VALUE rb_hash_set_pair(VALUE hash, VALUE pair);
int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval);
int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg);
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg);
+bool rb_hash_default_unredefined(VALUE hash);
+VALUE rb_hash_alloc_fixed_size(VALUE klass, st_index_t size);
+VALUE rb_ident_hash_new_with_size(st_index_t size);
+void rb_hash_free(VALUE hash);
+RUBY_EXTERN VALUE rb_cHash_empty_frozen;
+
static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h);
static inline VALUE RHASH_IFNONE(VALUE h);
static inline size_t RHASH_SIZE(VALUE h);
+static inline bool RHASH_EMPTY_P(VALUE h);
static inline bool RHASH_AR_TABLE_P(VALUE h);
static inline bool RHASH_ST_TABLE_P(VALUE h);
static inline struct ar_table_struct *RHASH_AR_TABLE(VALUE h);
static inline st_table *RHASH_ST_TABLE(VALUE h);
static inline size_t RHASH_ST_SIZE(VALUE h);
static inline void RHASH_ST_CLEAR(VALUE h);
-static inline bool RHASH_TRANSIENT_P(VALUE h);
-static inline void RHASH_SET_TRANSIENT_FLAG(VALUE h);
-static inline void RHASH_UNSET_TRANSIENT_FLAG(VALUE h);
RUBY_SYMBOL_EXPORT_BEGIN
/* hash.c (export) */
@@ -99,47 +110,18 @@ VALUE rb_ident_hash_new(void);
int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg);
RUBY_SYMBOL_EXPORT_END
-MJIT_SYMBOL_EXPORT_BEGIN
VALUE rb_hash_new_with_size(st_index_t size);
+VALUE rb_hash_new_with_bulk_insert(long argc, const VALUE *argv);
VALUE rb_hash_resurrect(VALUE hash);
int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval);
VALUE rb_hash_keys(VALUE hash);
VALUE rb_hash_has_key(VALUE hash, VALUE key);
VALUE rb_hash_compare_by_id_p(VALUE hash);
-#if RHASH_CONVERT_TABLE_DEBUG
st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line);
#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
-#else
-st_table *rb_hash_tbl_raw(VALUE hash);
-#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h)
-#endif
-MJIT_SYMBOL_EXPORT_END
-#if 0 /* for debug */
-
-static inline bool
-RHASH_AR_TABLE_P(VALUE h)
-{
- extern int rb_hash_ar_table_p(VALUE hash);
- return rb_hash_ar_table_p(h)
-}
-
-static inline struct ar_table_struct *
-RHASH_AR_TABLE(VALUE h)
-{
- extern struct ar_table_struct *rb_hash_ar_table(VALUE hash);
- return rb_hash_ar_table(h)
-}
-
-static inline st_table *
-RHASH_ST_TABLE(VALUE h)
-{
- extern st_table *rb_hash_st_table(VALUE hash);
- return rb_hash_st_table(h)
-}
-
-#else
+VALUE rb_hash_compare_by_id(VALUE hash);
static inline bool
RHASH_AR_TABLE_P(VALUE h)
@@ -147,20 +129,20 @@ RHASH_AR_TABLE_P(VALUE h)
return ! FL_TEST_RAW(h, RHASH_ST_TABLE_FLAG);
}
+RBIMPL_ATTR_RETURNS_NONNULL()
static inline struct ar_table_struct *
RHASH_AR_TABLE(VALUE h)
{
- return RHASH(h)->as.ar;
+ return (struct ar_table_struct *)((uintptr_t)h + sizeof(struct RHash));
}
+RBIMPL_ATTR_RETURNS_NONNULL()
static inline st_table *
RHASH_ST_TABLE(VALUE h)
{
- return RHASH(h)->as.st;
+ return (st_table *)((uintptr_t)h + sizeof(struct RHash));
}
-#endif
-
static inline VALUE
RHASH_IFNONE(VALUE h)
{
@@ -179,6 +161,12 @@ RHASH_SIZE(VALUE h)
}
static inline bool
+RHASH_EMPTY_P(VALUE h)
+{
+ return RHASH_SIZE(h) == 0;
+}
+
+static inline bool
RHASH_ST_TABLE_P(VALUE h)
{
return ! RHASH_AR_TABLE_P(h);
@@ -193,42 +181,30 @@ RHASH_ST_SIZE(VALUE h)
static inline void
RHASH_ST_CLEAR(VALUE h)
{
- FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG);
- RHASH(h)->as.ar = NULL;
+ memset(RHASH_ST_TABLE(h), 0, sizeof(st_table));
}
static inline unsigned
RHASH_AR_TABLE_SIZE_RAW(VALUE h)
{
- unsigned ret = FL_TEST_RAW(h, RHASH_AR_TABLE_SIZE_MASK);
+ VALUE ret = FL_TEST_RAW(h, RHASH_AR_TABLE_SIZE_MASK);
ret >>= RHASH_AR_TABLE_SIZE_SHIFT;
- return ret;
+ return (unsigned)ret;
}
-static inline bool
-RHASH_TRANSIENT_P(VALUE h)
-{
-#if USE_TRANSIENT_HEAP
- return FL_TEST_RAW(h, RHASH_TRANSIENT_FLAG);
-#else
- return false;
-#endif
-}
+#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)))
-static inline void
-RHASH_SET_TRANSIENT_FLAG(VALUE h)
-{
-#if USE_TRANSIENT_HEAP
- FL_SET_RAW(h, RHASH_TRANSIENT_FLAG);
-#endif
-}
+#define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
-static inline void
-RHASH_UNSET_TRANSIENT_FLAG(VALUE h)
+static inline unsigned int
+RHASH_AR_TABLE_BOUND(VALUE h)
{
-#if USE_TRANSIENT_HEAP
- FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG);
-#endif
+ 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 */