portable_mruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +195 -0
- data/exe/portable-mruby +6 -0
- data/lib/portable_mruby/binary_manager.rb +225 -0
- data/lib/portable_mruby/builder.rb +97 -0
- data/lib/portable_mruby/bytecode_compiler.rb +19 -0
- data/lib/portable_mruby/c_generator.rb +94 -0
- data/lib/portable_mruby/cli.rb +136 -0
- data/lib/portable_mruby/version.rb +6 -0
- data/lib/portable_mruby.rb +15 -0
- data/vendor/mruby/bin/mrbc.com +0 -0
- data/vendor/mruby/include/mrbconf.h +230 -0
- data/vendor/mruby/include/mruby/array.h +303 -0
- data/vendor/mruby/include/mruby/boxing_nan.h +169 -0
- data/vendor/mruby/include/mruby/boxing_no.h +59 -0
- data/vendor/mruby/include/mruby/boxing_word.h +251 -0
- data/vendor/mruby/include/mruby/class.h +104 -0
- data/vendor/mruby/include/mruby/common.h +118 -0
- data/vendor/mruby/include/mruby/compile.h +185 -0
- data/vendor/mruby/include/mruby/data.h +76 -0
- data/vendor/mruby/include/mruby/debug.h +75 -0
- data/vendor/mruby/include/mruby/dump.h +159 -0
- data/vendor/mruby/include/mruby/endian.h +44 -0
- data/vendor/mruby/include/mruby/error.h +132 -0
- data/vendor/mruby/include/mruby/gc.h +72 -0
- data/vendor/mruby/include/mruby/gems/mruby-dir/include/dir_hal.h +79 -0
- data/vendor/mruby/include/mruby/gems/mruby-io/include/io_hal.h +451 -0
- data/vendor/mruby/include/mruby/gems/mruby-io/include/mruby/ext/io.h +76 -0
- data/vendor/mruby/include/mruby/gems/mruby-socket/include/socket_hal.h +83 -0
- data/vendor/mruby/include/mruby/gems/mruby-time/include/mruby/time.h +27 -0
- data/vendor/mruby/include/mruby/hash.h +234 -0
- data/vendor/mruby/include/mruby/internal.h +274 -0
- data/vendor/mruby/include/mruby/irep.h +142 -0
- data/vendor/mruby/include/mruby/istruct.h +50 -0
- data/vendor/mruby/include/mruby/khash.h +455 -0
- data/vendor/mruby/include/mruby/mempool.h +19 -0
- data/vendor/mruby/include/mruby/numeric.h +174 -0
- data/vendor/mruby/include/mruby/object.h +45 -0
- data/vendor/mruby/include/mruby/opcode.h +69 -0
- data/vendor/mruby/include/mruby/ops.h +120 -0
- data/vendor/mruby/include/mruby/presym/disable.h +72 -0
- data/vendor/mruby/include/mruby/presym/enable.h +39 -0
- data/vendor/mruby/include/mruby/presym/id.h +1423 -0
- data/vendor/mruby/include/mruby/presym/scanning.h +81 -0
- data/vendor/mruby/include/mruby/presym/table.h +2847 -0
- data/vendor/mruby/include/mruby/presym.h +41 -0
- data/vendor/mruby/include/mruby/proc.h +186 -0
- data/vendor/mruby/include/mruby/range.h +77 -0
- data/vendor/mruby/include/mruby/re.h +16 -0
- data/vendor/mruby/include/mruby/string.h +428 -0
- data/vendor/mruby/include/mruby/throw.h +57 -0
- data/vendor/mruby/include/mruby/value.h +471 -0
- data/vendor/mruby/include/mruby/variable.h +108 -0
- data/vendor/mruby/include/mruby/version.h +143 -0
- data/vendor/mruby/include/mruby.h +1614 -0
- data/vendor/mruby/lib/libmruby.a +0 -0
- metadata +102 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
** @file mruby/irep.h - mrb_irep structure
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#ifndef MRUBY_IREP_H
|
|
8
|
+
#define MRUBY_IREP_H
|
|
9
|
+
|
|
10
|
+
#include "common.h"
|
|
11
|
+
#include <mruby/compile.h>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Compiled mruby scripts.
|
|
15
|
+
*/
|
|
16
|
+
MRB_BEGIN_DECL
|
|
17
|
+
|
|
18
|
+
enum irep_pool_type {
|
|
19
|
+
IREP_TT_STR = 0, /* string (need free) */
|
|
20
|
+
IREP_TT_SSTR = 2, /* string (static) */
|
|
21
|
+
IREP_TT_INT32 = 1, /* 32-bit integer */
|
|
22
|
+
IREP_TT_INT64 = 3, /* 64-bit integer */
|
|
23
|
+
IREP_TT_BIGINT = 7, /* big integer (not yet supported) */
|
|
24
|
+
IREP_TT_FLOAT = 5, /* float (double/float) */
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
#define IREP_TT_NFLAG 1 /* number (non string) flag */
|
|
28
|
+
#define IREP_TT_SFLAG 2 /* static string flag */
|
|
29
|
+
|
|
30
|
+
typedef struct mrb_irep_pool {
|
|
31
|
+
uint32_t tt; /* packed type and length (for string) */
|
|
32
|
+
union {
|
|
33
|
+
const char *str;
|
|
34
|
+
int32_t i32;
|
|
35
|
+
int64_t i64;
|
|
36
|
+
#ifndef MRB_NO_FLOAT
|
|
37
|
+
mrb_float f;
|
|
38
|
+
#endif
|
|
39
|
+
} u;
|
|
40
|
+
} mrb_irep_pool;
|
|
41
|
+
|
|
42
|
+
enum mrb_catch_type {
|
|
43
|
+
MRB_CATCH_RESCUE = 0,
|
|
44
|
+
MRB_CATCH_ENSURE = 1,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
struct mrb_irep_catch_handler {
|
|
48
|
+
uint8_t type; /* enum mrb_catch_type */
|
|
49
|
+
uint8_t begin[4]; /* The starting address to match the handler. Includes this. */
|
|
50
|
+
uint8_t end[4]; /* The endpoint address that matches the handler. Not Includes this. */
|
|
51
|
+
uint8_t target[4]; /* The address to jump to if a match is made. */
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/* Program data array struct */
|
|
55
|
+
struct mrb_irep {
|
|
56
|
+
uint16_t nlocals; /* Number of local variables */
|
|
57
|
+
uint16_t nregs; /* Number of register variables */
|
|
58
|
+
uint16_t clen; /* Number of catch handlers */
|
|
59
|
+
uint8_t flags;
|
|
60
|
+
|
|
61
|
+
const mrb_code *iseq;
|
|
62
|
+
/*
|
|
63
|
+
* A catch handler table is placed after the iseq entity.
|
|
64
|
+
* The reason it doesn't add fields to the structure is to keep the mrb_irep
|
|
65
|
+
* structure from bloating. The catch handler table can be obtained with
|
|
66
|
+
* `mrb_irep_catch_handler_table(irep)`.
|
|
67
|
+
*/
|
|
68
|
+
const mrb_irep_pool *pool;
|
|
69
|
+
const mrb_sym *syms;
|
|
70
|
+
const struct mrb_irep *const *reps;
|
|
71
|
+
|
|
72
|
+
const mrb_sym *lv;
|
|
73
|
+
/* debug info */
|
|
74
|
+
struct mrb_irep_debug_info *debug_info;
|
|
75
|
+
|
|
76
|
+
uint32_t ilen;
|
|
77
|
+
uint16_t plen, slen;
|
|
78
|
+
uint16_t rlen;
|
|
79
|
+
uint16_t refcnt;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
#define MRB_ISEQ_NO_FREE 1
|
|
83
|
+
#define MRB_IREP_NO_FREE 2
|
|
84
|
+
#define MRB_IREP_STATIC (MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE)
|
|
85
|
+
|
|
86
|
+
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* load mruby bytecode functions
|
|
90
|
+
*
|
|
91
|
+
* Please note! Currently due to interactions with the GC calling these
|
|
92
|
+
* functions will leak one RProc object per function call. To prevent this save
|
|
93
|
+
* the current memory arena before calling and restore the arena right after,
|
|
94
|
+
* like so
|
|
95
|
+
*
|
|
96
|
+
* int ai = mrb_gc_arena_save(mrb);
|
|
97
|
+
* mrb_value status = mrb_load_irep(mrb, buffer);
|
|
98
|
+
* mrb_gc_arena_restore(mrb, ai);
|
|
99
|
+
*
|
|
100
|
+
* Also, when called from a C function defined as a method, the current stack is
|
|
101
|
+
* destroyed. If processing continues after this function, the objects obtained
|
|
102
|
+
* from the arguments must be protected as needed before this function.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/* @param [const uint8_t*] irep code, expected as a literal */
|
|
106
|
+
MRB_API mrb_value mrb_load_irep(mrb_state *, const uint8_t *);
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
* @param [const void*] irep code
|
|
110
|
+
* @param [size_t] size of irep buffer.
|
|
111
|
+
*/
|
|
112
|
+
MRB_API mrb_value mrb_load_irep_buf(mrb_state *, const void *, size_t);
|
|
113
|
+
|
|
114
|
+
/* @param [const uint8_t*] irep code, expected as a literal */
|
|
115
|
+
MRB_API mrb_value mrb_load_irep_cxt(mrb_state *, const uint8_t *,
|
|
116
|
+
mrbc_context *);
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
* @param [const void*] irep code
|
|
120
|
+
* @param [size_t] size of irep buffer.
|
|
121
|
+
*/
|
|
122
|
+
MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state *, const void *, size_t,
|
|
123
|
+
mrbc_context *);
|
|
124
|
+
|
|
125
|
+
struct mrb_insn_data {
|
|
126
|
+
uint8_t insn;
|
|
127
|
+
uint32_t a;
|
|
128
|
+
uint16_t b;
|
|
129
|
+
uint16_t c;
|
|
130
|
+
const mrb_code *addr;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
#define mrb_irep_catch_handler_pack(n, v) uint32_to_bin(n, v)
|
|
134
|
+
#define mrb_irep_catch_handler_unpack(v) bin_to_uint32(v)
|
|
135
|
+
|
|
136
|
+
void mrb_irep_incref(mrb_state *, struct mrb_irep *);
|
|
137
|
+
void mrb_irep_decref(mrb_state *, struct mrb_irep *);
|
|
138
|
+
void mrb_irep_cutref(mrb_state *, struct mrb_irep *);
|
|
139
|
+
|
|
140
|
+
MRB_END_DECL
|
|
141
|
+
|
|
142
|
+
#endif /* MRUBY_IREP_H */
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
** @file mruby/istruct.h - Inline structures
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#ifndef MRUBY_ISTRUCT_H
|
|
8
|
+
#define MRUBY_ISTRUCT_H
|
|
9
|
+
|
|
10
|
+
#include "common.h"
|
|
11
|
+
#include <string.h>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Inline structures that fit in RVALUE
|
|
15
|
+
*
|
|
16
|
+
* They cannot have finalizer, and cannot have instance variables.
|
|
17
|
+
*/
|
|
18
|
+
MRB_BEGIN_DECL
|
|
19
|
+
|
|
20
|
+
#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3)
|
|
21
|
+
|
|
22
|
+
struct RIStruct {
|
|
23
|
+
MRB_OBJECT_HEADER;
|
|
24
|
+
union {
|
|
25
|
+
intptr_t inline_alignment[3];
|
|
26
|
+
char inline_data[ISTRUCT_DATA_SIZE];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
|
|
31
|
+
#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data)
|
|
32
|
+
|
|
33
|
+
MRB_INLINE mrb_int mrb_istruct_size(void)
|
|
34
|
+
{
|
|
35
|
+
return ISTRUCT_DATA_SIZE;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
MRB_INLINE void* mrb_istruct_ptr(mrb_value object)
|
|
39
|
+
{
|
|
40
|
+
return ISTRUCT_PTR(object);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src)
|
|
44
|
+
{
|
|
45
|
+
memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
MRB_END_DECL
|
|
49
|
+
|
|
50
|
+
#endif /* MRUBY_ISTRUCT_H */
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
** @file mruby/khash.h - Hash for mruby
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#ifndef MRUBY_KHASH_H
|
|
8
|
+
#define MRUBY_KHASH_H
|
|
9
|
+
|
|
10
|
+
#include <string.h>
|
|
11
|
+
|
|
12
|
+
#include <mruby.h>
|
|
13
|
+
#include "common.h"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* khash definitions used in mruby's hash table.
|
|
17
|
+
*/
|
|
18
|
+
MRB_BEGIN_DECL
|
|
19
|
+
|
|
20
|
+
typedef uint32_t khint_t;
|
|
21
|
+
typedef khint_t khiter_t;
|
|
22
|
+
|
|
23
|
+
#ifndef KHASH_INITIAL_SIZE
|
|
24
|
+
# define KHASH_INITIAL_SIZE 8
|
|
25
|
+
#endif
|
|
26
|
+
#define KHASH_MIN_SIZE 8
|
|
27
|
+
#define KHASH_SMALL_LIMIT 4
|
|
28
|
+
|
|
29
|
+
#define KH_UPPER_BOUND(x) ((x) - ((x)>>3)) /* 87.5% load factor */
|
|
30
|
+
|
|
31
|
+
/* extern uint8_t __m[]; */
|
|
32
|
+
|
|
33
|
+
/* mask for flags */
|
|
34
|
+
static const uint8_t __m_empty[] = {0x02, 0x08, 0x20, 0x80};
|
|
35
|
+
static const uint8_t __m_del[] = {0x01, 0x04, 0x10, 0x40};
|
|
36
|
+
static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4])
|
|
40
|
+
#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4])
|
|
41
|
+
#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4])
|
|
42
|
+
#define khash_power2(v) do { \
|
|
43
|
+
v--;\
|
|
44
|
+
v |= v >> 1;\
|
|
45
|
+
v |= v >> 2;\
|
|
46
|
+
v |= v >> 4;\
|
|
47
|
+
v |= v >> 8;\
|
|
48
|
+
v |= v >> 16;\
|
|
49
|
+
v++;\
|
|
50
|
+
} while (0)
|
|
51
|
+
#define khash_mask(h) ((h)->n_buckets-1)
|
|
52
|
+
#define khash_upper_bound(h) (KH_UPPER_BOUND((h)->n_buckets))
|
|
53
|
+
|
|
54
|
+
/* BREAKING CHANGE: khash structure optimized for 50% memory reduction
|
|
55
|
+
*
|
|
56
|
+
* The structure now uses a single data pointer instead of separate keys,
|
|
57
|
+
* vals, and ed_flags pointers, reducing size from 32 to 16 bytes.
|
|
58
|
+
*
|
|
59
|
+
* MIGRATION REQUIRED for field access macros:
|
|
60
|
+
* - OLD: kh_key(h, x) NEW: kh_key(typename, h, x)
|
|
61
|
+
* - OLD: kh_val(h, x) NEW: kh_val(typename, h, x)
|
|
62
|
+
* - OLD: kh_exist(h, x) NEW: kh_exist(typename, h, x)
|
|
63
|
+
* - OLD: KHASH_FOREACH() NEW: KHASH_FOREACH(typename, ...)
|
|
64
|
+
*
|
|
65
|
+
* Function-style macros (kh_get, kh_put, etc.) remain unchanged.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/* declare struct kh_xxx and kh_xxx_funcs
|
|
69
|
+
|
|
70
|
+
name: hash name
|
|
71
|
+
khkey_t: key data type
|
|
72
|
+
khval_t: value data type
|
|
73
|
+
kh_is_map: (0: hash set / 1: hash map)
|
|
74
|
+
*/
|
|
75
|
+
#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \
|
|
76
|
+
typedef struct kh_##name { \
|
|
77
|
+
void *data; /* Single allocation: [keys][vals][flags] */ \
|
|
78
|
+
khint_t n_buckets; /* Number of buckets (power of 2) */ \
|
|
79
|
+
khint_t size; /* Number of elements */ \
|
|
80
|
+
} kh_##name##_t; \
|
|
81
|
+
/* Address calculation functions for optimized memory layout */ \
|
|
82
|
+
static inline khkey_t* kh_keys_##name(const kh_##name##_t *h) { \
|
|
83
|
+
return (khkey_t*)(h)->data; \
|
|
84
|
+
} \
|
|
85
|
+
static inline khval_t* kh_vals_##name(const kh_##name##_t *h) { \
|
|
86
|
+
return kh_is_map ? \
|
|
87
|
+
(khval_t*)((uint8_t*)(h)->data + sizeof(khkey_t) * (h)->n_buckets) : NULL; \
|
|
88
|
+
} \
|
|
89
|
+
static inline uint8_t* kh_flags_##name(const kh_##name##_t *h) { \
|
|
90
|
+
return (uint8_t*)(h)->data + sizeof(khkey_t) * (h)->n_buckets + \
|
|
91
|
+
(kh_is_map ? sizeof(khval_t) * (h)->n_buckets : 0); \
|
|
92
|
+
} \
|
|
93
|
+
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \
|
|
94
|
+
kh_##name##_t *kh_init_##name(mrb_state *mrb); \
|
|
95
|
+
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h); \
|
|
96
|
+
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
|
|
97
|
+
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
|
|
98
|
+
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
|
|
99
|
+
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
|
|
100
|
+
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
|
|
101
|
+
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); \
|
|
102
|
+
void kh_init_data_##name(mrb_state *mrb, kh_##name##_t *h, khint_t size); \
|
|
103
|
+
void kh_destroy_data_##name(mrb_state *mrb, kh_##name##_t *h); \
|
|
104
|
+
void kh_replace_##name(mrb_state *mrb, kh_##name##_t *dst, const kh_##name##_t *src);
|
|
105
|
+
|
|
106
|
+
/* define kh_xxx_funcs
|
|
107
|
+
|
|
108
|
+
name: hash name
|
|
109
|
+
khkey_t: key data type
|
|
110
|
+
khval_t: value data type
|
|
111
|
+
kh_is_map: (0: hash set / 1: hash map)
|
|
112
|
+
__hash_func: hash function
|
|
113
|
+
__hash_equal: hash comparison function
|
|
114
|
+
*/
|
|
115
|
+
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
|
116
|
+
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
|
|
117
|
+
/* Internal helper functions */ \
|
|
118
|
+
static inline size_t kh__kv_size_##name(khint_t count) { \
|
|
119
|
+
return sizeof(khkey_t) * count + \
|
|
120
|
+
(kh_is_map ? sizeof(khval_t) * count : 0); \
|
|
121
|
+
} \
|
|
122
|
+
static inline size_t kh__htable_size_##name(khint_t n_buckets) { \
|
|
123
|
+
return kh__kv_size_##name(n_buckets) + n_buckets / 4; \
|
|
124
|
+
} \
|
|
125
|
+
static inline void kh__mark_occupied_##name(kh_##name##_t *h, khint_t i) { \
|
|
126
|
+
uint8_t *flags = kh_flags_##name(h); \
|
|
127
|
+
flags[i/4] &= ~__m_either[i%4]; /* Clear both empty and deleted bits */ \
|
|
128
|
+
} \
|
|
129
|
+
static inline void kh__mark_deleted_##name(kh_##name##_t *h, khint_t i) { \
|
|
130
|
+
uint8_t *flags = kh_flags_##name(h); \
|
|
131
|
+
flags[i/4] |= __m_del[i%4]; /* Set deleted bit */ \
|
|
132
|
+
} \
|
|
133
|
+
static inline khint_t kh__key_idx_##name(mrb_state *mrb, khkey_t key, kh_##name##_t *h) { \
|
|
134
|
+
return __hash_func(mrb, key) & khash_mask(h); \
|
|
135
|
+
} \
|
|
136
|
+
static inline khint_t kh__next_probe_##name(khint_t k, khint_t *step, kh_##name##_t *h) { \
|
|
137
|
+
return (k+(++(*step))) & khash_mask(h); \
|
|
138
|
+
} \
|
|
139
|
+
static inline khint_t kh__insert_key_##name(kh_##name##_t *h, khint_t index, khkey_t key) { \
|
|
140
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
141
|
+
keys[index] = key; \
|
|
142
|
+
kh__mark_occupied_##name(h, index); \
|
|
143
|
+
h->size++; \
|
|
144
|
+
return index; \
|
|
145
|
+
} \
|
|
146
|
+
static inline void kh__clear_flags_##name(kh_##name##_t *h, khint_t n_buckets) { \
|
|
147
|
+
memset(kh_flags_##name(h), 0xaa, n_buckets/4); \
|
|
148
|
+
} \
|
|
149
|
+
static inline void kh__alloc_##name(mrb_state *mrb, kh_##name##_t *h) { \
|
|
150
|
+
khint_t sz = h->n_buckets; \
|
|
151
|
+
uint8_t *p = (uint8_t*)mrb_malloc(mrb, kh__htable_size_##name(sz)); \
|
|
152
|
+
h->size = 0; \
|
|
153
|
+
h->data = p; /* Single data pointer for optimized layout */ \
|
|
154
|
+
kh__clear_flags_##name(h, sz); \
|
|
155
|
+
} \
|
|
156
|
+
/* Small table optimization functions */ \
|
|
157
|
+
static inline int kh__is_small_##name(const kh_##name##_t *h) { \
|
|
158
|
+
return h->n_buckets == 0; /* Small table marker */ \
|
|
159
|
+
} \
|
|
160
|
+
static inline khint_t kh__get_small_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) { \
|
|
161
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
162
|
+
for (khint_t i = 0; i < h->size; i++) { \
|
|
163
|
+
if (__hash_equal(mrb, keys[i], key)) return i; \
|
|
164
|
+
} \
|
|
165
|
+
return h->size; /* Not found - return end position */ \
|
|
166
|
+
} \
|
|
167
|
+
static inline void kh__rebuild_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) { \
|
|
168
|
+
kh_##name##_t hh; \
|
|
169
|
+
hh.data = NULL; \
|
|
170
|
+
hh.size = 0; \
|
|
171
|
+
kh_init_data_##name(mrb, &hh, new_n_buckets); \
|
|
172
|
+
/* Rehash from old 'h' to 'hh' */ \
|
|
173
|
+
khkey_t *old_keys = kh_keys_##name(h); \
|
|
174
|
+
khval_t *old_vals = kh_vals_##name(h); \
|
|
175
|
+
uint8_t *old_flags = kh__is_small_##name(h) ? NULL : kh_flags_##name(h); \
|
|
176
|
+
khint_t limit = old_flags ? h->n_buckets : h->size; \
|
|
177
|
+
for (khint_t i = 0; i < limit; i++) { \
|
|
178
|
+
if (old_flags && __ac_iseither(old_flags, i)) continue; \
|
|
179
|
+
khint_t k = kh_put_##name(mrb, &hh, old_keys[i], NULL); \
|
|
180
|
+
if (kh_is_map) { \
|
|
181
|
+
kh_val(name, &hh, k) = old_vals[i]; \
|
|
182
|
+
} \
|
|
183
|
+
} \
|
|
184
|
+
/* Final Swap */ \
|
|
185
|
+
mrb_free(mrb, h->data); \
|
|
186
|
+
h->data = hh.data; \
|
|
187
|
+
h->n_buckets = hh.n_buckets; \
|
|
188
|
+
h->size = hh.size; \
|
|
189
|
+
} \
|
|
190
|
+
static inline khint_t kh__put_small_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) { \
|
|
191
|
+
/* First check if key exists */ \
|
|
192
|
+
khint_t pos = kh__get_small_##name(mrb, h, key); \
|
|
193
|
+
if (pos < h->size) { \
|
|
194
|
+
if (ret) *ret = 0; /* Key exists */ \
|
|
195
|
+
return pos; \
|
|
196
|
+
} \
|
|
197
|
+
/* Check if we need to convert to hash table */ \
|
|
198
|
+
if (h->size >= KHASH_SMALL_LIMIT) { \
|
|
199
|
+
/* Convert from small table to hash table */ \
|
|
200
|
+
kh__rebuild_##name(mrb, h, KHASH_MIN_SIZE); \
|
|
201
|
+
/* Now add the new key using regular hash table */ \
|
|
202
|
+
return kh_put_##name(mrb, h, key, ret); \
|
|
203
|
+
} \
|
|
204
|
+
/* Add new element to small table */ \
|
|
205
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
206
|
+
keys[h->size] = key; \
|
|
207
|
+
h->size++; \
|
|
208
|
+
if (ret) *ret = 1; /* New key */ \
|
|
209
|
+
return h->size - 1; \
|
|
210
|
+
} \
|
|
211
|
+
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
|
|
212
|
+
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
|
|
213
|
+
kh_init_data_##name(mrb, h, size); \
|
|
214
|
+
return h; \
|
|
215
|
+
} \
|
|
216
|
+
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
|
|
217
|
+
return kh_init_##name##_size(mrb, KHASH_INITIAL_SIZE); \
|
|
218
|
+
} \
|
|
219
|
+
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \
|
|
220
|
+
{ \
|
|
221
|
+
kh_destroy_data_##name(mrb, h); \
|
|
222
|
+
mrb_free(mrb, h); \
|
|
223
|
+
} \
|
|
224
|
+
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h) \
|
|
225
|
+
{ \
|
|
226
|
+
(void)mrb; \
|
|
227
|
+
if (h && h->data) { \
|
|
228
|
+
kh__clear_flags_##name(h, h->n_buckets); \
|
|
229
|
+
h->size = 0; \
|
|
230
|
+
} \
|
|
231
|
+
} \
|
|
232
|
+
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \
|
|
233
|
+
{ \
|
|
234
|
+
if (kh__is_small_##name(h)) { \
|
|
235
|
+
return kh__get_small_##name(mrb, h, key); \
|
|
236
|
+
} \
|
|
237
|
+
/* Cache calculated pointers for performance */ \
|
|
238
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
239
|
+
uint8_t *ed_flags = kh_flags_##name(h); \
|
|
240
|
+
khint_t k = kh__key_idx_##name(mrb, key, h), step = 0; \
|
|
241
|
+
(void)mrb; \
|
|
242
|
+
while (!__ac_isempty(ed_flags, k)) { \
|
|
243
|
+
if (!__ac_isdel(ed_flags, k)) { \
|
|
244
|
+
if (__hash_equal(mrb, keys[k], key)) return k; \
|
|
245
|
+
} \
|
|
246
|
+
k = kh__next_probe_##name(k, &step, h); \
|
|
247
|
+
} \
|
|
248
|
+
return kh_end(h); \
|
|
249
|
+
} \
|
|
250
|
+
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) \
|
|
251
|
+
{ \
|
|
252
|
+
if (new_n_buckets < KHASH_MIN_SIZE) \
|
|
253
|
+
new_n_buckets = KHASH_MIN_SIZE; \
|
|
254
|
+
khash_power2(new_n_buckets); \
|
|
255
|
+
kh__rebuild_##name(mrb, h, new_n_buckets); \
|
|
256
|
+
} \
|
|
257
|
+
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
|
258
|
+
{ \
|
|
259
|
+
if (kh__is_small_##name(h)) { \
|
|
260
|
+
return kh__put_small_##name(mrb, h, key, ret); \
|
|
261
|
+
} \
|
|
262
|
+
khint_t k, del_k, step = 0; \
|
|
263
|
+
if (h->size >= khash_upper_bound(h)) { \
|
|
264
|
+
kh_resize_##name(mrb, h, h->n_buckets*2); \
|
|
265
|
+
} \
|
|
266
|
+
/* Cache calculated pointers for performance */ \
|
|
267
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
268
|
+
uint8_t *ed_flags = kh_flags_##name(h); \
|
|
269
|
+
k = kh__key_idx_##name(mrb, key, h); \
|
|
270
|
+
del_k = kh_end(h); \
|
|
271
|
+
while (!__ac_isempty(ed_flags, k)) { \
|
|
272
|
+
if (!__ac_isdel(ed_flags, k)) { \
|
|
273
|
+
if (__hash_equal(mrb, keys[k], key)) { \
|
|
274
|
+
if (ret) *ret = 0; \
|
|
275
|
+
return k; \
|
|
276
|
+
} \
|
|
277
|
+
} \
|
|
278
|
+
else if (del_k == kh_end(h)) { \
|
|
279
|
+
del_k = k; \
|
|
280
|
+
} \
|
|
281
|
+
k = kh__next_probe_##name(k, &step, h); \
|
|
282
|
+
} \
|
|
283
|
+
if (del_k != kh_end(h)) { \
|
|
284
|
+
/* put at del */ \
|
|
285
|
+
kh__insert_key_##name(h, del_k, key); \
|
|
286
|
+
if (ret) *ret = 2; \
|
|
287
|
+
return del_k; \
|
|
288
|
+
} \
|
|
289
|
+
else { \
|
|
290
|
+
/* put at empty */ \
|
|
291
|
+
kh__insert_key_##name(h, k, key); \
|
|
292
|
+
if (ret) *ret = 1; \
|
|
293
|
+
return k; \
|
|
294
|
+
} \
|
|
295
|
+
} \
|
|
296
|
+
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x) \
|
|
297
|
+
{ \
|
|
298
|
+
(void)mrb; \
|
|
299
|
+
if (kh__is_small_##name(h)) { \
|
|
300
|
+
/* Small table deletion: shift elements down */ \
|
|
301
|
+
mrb_assert(x < h->size); \
|
|
302
|
+
khkey_t *keys = kh_keys_##name(h); \
|
|
303
|
+
khval_t *vals = kh_vals_##name(h); \
|
|
304
|
+
for (khint_t i = x; i < h->size - 1; i++) { \
|
|
305
|
+
keys[i] = keys[i + 1]; \
|
|
306
|
+
if (kh_is_map) vals[i] = vals[i + 1]; \
|
|
307
|
+
} \
|
|
308
|
+
h->size--; \
|
|
309
|
+
} \
|
|
310
|
+
else { \
|
|
311
|
+
/* Regular hash table deletion */ \
|
|
312
|
+
mrb_assert(x != h->n_buckets && !__ac_iseither(kh_flags_##name(h), x)); \
|
|
313
|
+
kh__mark_deleted_##name(h, x); \
|
|
314
|
+
h->size--; \
|
|
315
|
+
} \
|
|
316
|
+
} \
|
|
317
|
+
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
|
|
318
|
+
{ \
|
|
319
|
+
kh_##name##_t *h2 = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
|
|
320
|
+
kh_replace_##name(mrb, h2, h); \
|
|
321
|
+
return h2; \
|
|
322
|
+
} \
|
|
323
|
+
void kh_init_data_##name(mrb_state *mrb, kh_##name##_t *h, khint_t size) { \
|
|
324
|
+
if (size <= KHASH_SMALL_LIMIT) { \
|
|
325
|
+
/* Start as small table */ \
|
|
326
|
+
h->n_buckets = 0; /* Small table marker */ \
|
|
327
|
+
h->data = mrb_malloc(mrb, kh__kv_size_##name(KHASH_SMALL_LIMIT)); \
|
|
328
|
+
h->size = 0; \
|
|
329
|
+
} \
|
|
330
|
+
else { \
|
|
331
|
+
/* Start as regular hash table */ \
|
|
332
|
+
if (size < KHASH_MIN_SIZE) \
|
|
333
|
+
size = KHASH_MIN_SIZE; \
|
|
334
|
+
khash_power2(size); \
|
|
335
|
+
h->n_buckets = size; \
|
|
336
|
+
kh__alloc_##name(mrb, h); \
|
|
337
|
+
} \
|
|
338
|
+
} \
|
|
339
|
+
void kh_destroy_data_##name(mrb_state *mrb, kh_##name##_t *h) \
|
|
340
|
+
{ \
|
|
341
|
+
if (h && h->data) { \
|
|
342
|
+
mrb_free(mrb, h->data); /* Free only the data allocation */ \
|
|
343
|
+
h->data = NULL; \
|
|
344
|
+
} \
|
|
345
|
+
} \
|
|
346
|
+
void kh_replace_##name(mrb_state *mrb, kh_##name##_t *dst, const kh_##name##_t *src) \
|
|
347
|
+
{ \
|
|
348
|
+
if (!src || (src->n_buckets == 0 && src->size == 0)) { \
|
|
349
|
+
/* Empty source */ \
|
|
350
|
+
kh_destroy_data_##name(mrb, dst); \
|
|
351
|
+
dst->data = NULL; \
|
|
352
|
+
dst->n_buckets = 0; \
|
|
353
|
+
dst->size = 0; \
|
|
354
|
+
} \
|
|
355
|
+
else if (src->n_buckets == 0) { \
|
|
356
|
+
/* Small table case */ \
|
|
357
|
+
size_t data_size = kh__kv_size_##name(KHASH_SMALL_LIMIT); \
|
|
358
|
+
dst->data = mrb_realloc(mrb, dst->data, data_size); \
|
|
359
|
+
dst->size = src->size; \
|
|
360
|
+
dst->n_buckets = 0; \
|
|
361
|
+
/* Copy only the used portion of keys and values */ \
|
|
362
|
+
size_t copy_size = kh__kv_size_##name(src->size); \
|
|
363
|
+
memcpy(dst->data, src->data, copy_size); \
|
|
364
|
+
} \
|
|
365
|
+
else { \
|
|
366
|
+
/* Regular hash table case */ \
|
|
367
|
+
size_t data_size = kh__htable_size_##name(src->n_buckets); \
|
|
368
|
+
dst->data = mrb_realloc(mrb, dst->data, data_size); \
|
|
369
|
+
dst->size = src->size; \
|
|
370
|
+
dst->n_buckets = src->n_buckets; \
|
|
371
|
+
/* Copy the entire data block: [keys][vals][flags] */ \
|
|
372
|
+
memcpy(dst->data, src->data, data_size); \
|
|
373
|
+
} \
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
#define khash_t(name) kh_##name##_t
|
|
378
|
+
|
|
379
|
+
#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size)
|
|
380
|
+
#define kh_init(name,mrb) kh_init_##name(mrb)
|
|
381
|
+
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
|
|
382
|
+
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
|
|
383
|
+
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
|
|
384
|
+
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
|
|
385
|
+
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
|
|
386
|
+
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
|
|
387
|
+
#define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k)
|
|
388
|
+
#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
|
|
389
|
+
#define kh_init_data(name, mrb, h, size) kh_init_data_##name(mrb, h, size)
|
|
390
|
+
#define kh_destroy_data(name, mrb, h) kh_destroy_data_##name(mrb, h)
|
|
391
|
+
#define kh_replace(name, mrb, dst, src) kh_replace_##name(mrb, dst, src)
|
|
392
|
+
|
|
393
|
+
/* BREAKING CHANGE: Field access macros now require type name as first parameter
|
|
394
|
+
* The macros keep their familiar names but now need the hash type name.
|
|
395
|
+
*
|
|
396
|
+
* MIGRATION: Add type name as first parameter:
|
|
397
|
+
* kh_key(h, x) -> kh_key(typename, h, x)
|
|
398
|
+
* kh_val(h, x) -> kh_val(typename, h, x)
|
|
399
|
+
* kh_exist(h, x) -> kh_exist(typename, h, x)
|
|
400
|
+
* kh_value(h, x) -> kh_value(typename, h, x)
|
|
401
|
+
*/
|
|
402
|
+
|
|
403
|
+
/* Type-aware access macros - same names, now with type parameter */
|
|
404
|
+
#define kh_exist(name, h, x) ((h)->n_buckets == 0 ? ((x) < (h)->size) : (!__ac_iseither(kh_flags_##name(h), (x))))
|
|
405
|
+
#define kh_key(name, h, x) (kh_keys_##name(h)[x])
|
|
406
|
+
#define kh_val(name, h, x) (kh_vals_##name(h)[x])
|
|
407
|
+
#define kh_value(name, h, x) (kh_vals_##name(h)[x])
|
|
408
|
+
#define kh_begin(h) (khint_t)(0)
|
|
409
|
+
#define kh_end(h) ((h)->n_buckets == 0 ? (h)->size : (h)->n_buckets)
|
|
410
|
+
#define kh_is_end(h, i) ((i) >= kh_end(h))
|
|
411
|
+
#define kh_size(h) ((h)->size)
|
|
412
|
+
#define kh_n_buckets(h) ((h)->n_buckets)
|
|
413
|
+
|
|
414
|
+
#define kh_int_hash_func(mrb,key) mrb_int_hash_func(mrb,key)
|
|
415
|
+
#define kh_int_hash_equal(mrb,a, b) (a == b)
|
|
416
|
+
#define kh_int64_hash_func(mrb,key) (khint_t)((key)>>33^(key)^(key)<<11)
|
|
417
|
+
#define kh_int64_hash_equal(mrb,a, b) (a == b)
|
|
418
|
+
static inline khint_t __ac_X31_hash_string(const char *s)
|
|
419
|
+
{
|
|
420
|
+
khint_t h = *s;
|
|
421
|
+
if (h) for (++s; *s; ++s) h = (h << 5) - h + *s;
|
|
422
|
+
return h;
|
|
423
|
+
}
|
|
424
|
+
#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key)
|
|
425
|
+
#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0)
|
|
426
|
+
|
|
427
|
+
typedef const char *kh_cstr_t;
|
|
428
|
+
|
|
429
|
+
MRB_END_DECL
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Macro for iterating over all elements in a khash.
|
|
433
|
+
*
|
|
434
|
+
* Usage:
|
|
435
|
+
* KHASH_FOREACH(typename, kh, k) {
|
|
436
|
+
* // k is the khiter_t iterator
|
|
437
|
+
* // Access the key with kh_key(typename, kh, k)
|
|
438
|
+
* // Access the value with kh_val(typename, kh, k) if applicable
|
|
439
|
+
* // Your code here
|
|
440
|
+
* }
|
|
441
|
+
*
|
|
442
|
+
* @param name The hash type name
|
|
443
|
+
* @param kh The khash to iterate over
|
|
444
|
+
* @param k The name to use for the khiter_t iterator variable
|
|
445
|
+
*/
|
|
446
|
+
/* BREAKING CHANGE: KHASH_FOREACH now requires type name as first parameter
|
|
447
|
+
* OLD: KHASH_FOREACH(mrb, kh, k)
|
|
448
|
+
* NEW: KHASH_FOREACH(name, kh, k)
|
|
449
|
+
*/
|
|
450
|
+
#define KHASH_FOREACH(name, kh, k) \
|
|
451
|
+
if (kh) \
|
|
452
|
+
for (khiter_t k = kh_begin(kh); !kh_is_end(kh, k); k++) \
|
|
453
|
+
if (kh_exist(name, kh, k))
|
|
454
|
+
|
|
455
|
+
#endif /* MRUBY_KHASH_H */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** mempool.h - memory pool
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* memory pool implementation */
|
|
8
|
+
typedef struct mempool mempool;
|
|
9
|
+
MRB_API struct mempool* mempool_open(void);
|
|
10
|
+
MRB_API void mempool_close(struct mempool*);
|
|
11
|
+
MRB_API void* mempool_alloc(struct mempool*, size_t);
|
|
12
|
+
MRB_API void* mempool_realloc(struct mempool*, void*, size_t oldlen, size_t newlen);
|
|
13
|
+
|
|
14
|
+
/* compatibility layer */
|
|
15
|
+
typedef struct mempool mrb_mempool;
|
|
16
|
+
#define mrb_mempool_open(m) mempool_open()
|
|
17
|
+
#define mrb_mempool_close(m) mempool_close(m)
|
|
18
|
+
#define mrb_mempool_alloc(m, size) mempool_alloc((m),(size))
|
|
19
|
+
#define mrb_mempool_realloc(m, ptr, oldlen, newlen) mempool_realloc((m),(ptr),(oldlen),(newlen))
|