rbs 3.6.1 → 3.9.5

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.
Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +2 -2
  3. data/.github/workflows/dependabot.yml +1 -1
  4. data/.github/workflows/ruby.yml +34 -10
  5. data/.github/workflows/windows.yml +20 -3
  6. data/.gitignore +1 -0
  7. data/.rubocop.yml +26 -1
  8. data/CHANGELOG.md +241 -0
  9. data/Rakefile +54 -4
  10. data/config.yml +317 -0
  11. data/core/array.rbs +1756 -1591
  12. data/core/basic_object.rbs +38 -35
  13. data/core/comparable.rbs +1 -1
  14. data/core/complex.rbs +166 -94
  15. data/core/data.rbs +2 -2
  16. data/core/dir.rbs +2 -18
  17. data/core/encoding.rbs +12 -32
  18. data/core/enumerable.rbs +270 -266
  19. data/core/enumerator.rbs +14 -4
  20. data/core/env.rbs +1 -1
  21. data/core/errno.rbs +33 -16
  22. data/core/errors.rbs +6 -2
  23. data/core/exception.rbs +342 -167
  24. data/core/fiber.rbs +3 -2
  25. data/core/file.rbs +26 -75
  26. data/core/float.rbs +125 -72
  27. data/core/gc.rbs +158 -42
  28. data/core/hash.rbs +122 -143
  29. data/core/integer.rbs +79 -50
  30. data/core/io/buffer.rbs +49 -43
  31. data/core/io.rbs +108 -151
  32. data/core/kernel.rbs +341 -209
  33. data/core/match_data.rbs +76 -2
  34. data/core/math.rbs +0 -36
  35. data/core/method.rbs +2 -2
  36. data/core/module.rbs +32 -27
  37. data/core/nil_class.rbs +2 -2
  38. data/core/numeric.rbs +101 -104
  39. data/core/object.rbs +1 -5
  40. data/core/object_space/weak_key_map.rbs +3 -4
  41. data/core/object_space.rbs +3 -3
  42. data/core/proc.rbs +82 -14
  43. data/core/process.rbs +110 -58
  44. data/core/ractor.rbs +57 -4
  45. data/core/range.rbs +114 -87
  46. data/core/rational.rbs +0 -2
  47. data/core/rbs/unnamed/argf.rbs +237 -36
  48. data/core/rbs/unnamed/env_class.rbs +35 -53
  49. data/core/rbs/unnamed/random.rbs +1 -2
  50. data/core/regexp.rbs +10 -56
  51. data/core/ruby_vm.rbs +88 -9
  52. data/core/rubygems/config_file.rbs +3 -0
  53. data/core/rubygems/errors.rbs +3 -6
  54. data/core/rubygems/platform.rbs +0 -9
  55. data/core/rubygems/rubygems.rbs +3 -6
  56. data/core/rubygems/version.rbs +8 -8
  57. data/core/set.rbs +4 -16
  58. data/core/string.rbs +271 -264
  59. data/core/struct.rbs +6 -18
  60. data/core/symbol.rbs +14 -21
  61. data/core/thread.rbs +32 -35
  62. data/core/time.rbs +131 -50
  63. data/core/trace_point.rbs +124 -113
  64. data/core/true_class.rbs +0 -1
  65. data/core/unbound_method.rbs +1 -1
  66. data/core/warning.rbs +9 -2
  67. data/docs/architecture.md +1 -1
  68. data/docs/syntax.md +17 -10
  69. data/ext/rbs_extension/extconf.rb +11 -0
  70. data/ext/rbs_extension/location.c +61 -29
  71. data/ext/rbs_extension/location.h +4 -3
  72. data/ext/rbs_extension/main.c +23 -1
  73. data/ext/rbs_extension/parser.c +506 -517
  74. data/ext/rbs_extension/parserstate.c +109 -30
  75. data/ext/rbs_extension/parserstate.h +6 -4
  76. data/ext/rbs_extension/rbs_extension.h +1 -10
  77. data/{ext/rbs_extension → include/rbs}/constants.h +21 -19
  78. data/include/rbs/ruby_objs.h +72 -0
  79. data/include/rbs/util/rbs_constant_pool.h +219 -0
  80. data/include/rbs.h +7 -0
  81. data/lib/rbs/annotate/annotations.rb +3 -3
  82. data/lib/rbs/annotate/rdoc_source.rb +2 -2
  83. data/lib/rbs/ast/declarations.rb +9 -4
  84. data/lib/rbs/ast/directives.rb +10 -0
  85. data/lib/rbs/ast/members.rb +2 -0
  86. data/lib/rbs/ast/type_param.rb +2 -12
  87. data/lib/rbs/cli/diff.rb +3 -3
  88. data/lib/rbs/cli/validate.rb +2 -1
  89. data/lib/rbs/cli.rb +16 -16
  90. data/lib/rbs/collection/config/lockfile_generator.rb +58 -8
  91. data/lib/rbs/collection/config.rb +5 -3
  92. data/lib/rbs/collection/sources/rubygems.rb +1 -1
  93. data/lib/rbs/collection.rb +1 -0
  94. data/lib/rbs/definition.rb +51 -34
  95. data/lib/rbs/definition_builder/ancestor_builder.rb +5 -3
  96. data/lib/rbs/definition_builder.rb +83 -24
  97. data/lib/rbs/environment.rb +33 -18
  98. data/lib/rbs/environment_loader.rb +6 -1
  99. data/lib/rbs/errors.rb +24 -0
  100. data/lib/rbs/locator.rb +2 -0
  101. data/lib/rbs/method_type.rb +2 -0
  102. data/lib/rbs/namespace.rb +1 -0
  103. data/lib/rbs/parser_aux.rb +40 -3
  104. data/lib/rbs/prototype/rb.rb +20 -12
  105. data/lib/rbs/prototype/rbi.rb +11 -6
  106. data/lib/rbs/prototype/runtime/value_object_generator.rb +7 -5
  107. data/lib/rbs/prototype/runtime.rb +7 -5
  108. data/lib/rbs/subtractor.rb +3 -3
  109. data/lib/rbs/test/hook.rb +47 -42
  110. data/lib/rbs/test/type_check.rb +7 -5
  111. data/lib/rbs/type_name.rb +14 -9
  112. data/lib/rbs/types.rb +63 -14
  113. data/lib/rbs/unit_test/spy.rb +4 -2
  114. data/lib/rbs/unit_test/type_assertions.rb +19 -13
  115. data/lib/rbs/unit_test/with_aliases.rb +3 -1
  116. data/lib/rbs/validator.rb +7 -1
  117. data/lib/rbs/version.rb +1 -1
  118. data/lib/rbs/writer.rb +10 -5
  119. data/lib/rbs.rb +1 -0
  120. data/lib/rdoc_plugin/parser.rb +2 -2
  121. data/rbs.gemspec +6 -2
  122. data/sig/ancestor_graph.rbs +5 -5
  123. data/sig/annotate/rdoc_source.rbs +2 -0
  124. data/sig/cli.rbs +2 -0
  125. data/sig/collection/config/lockfile_generator.rbs +9 -1
  126. data/sig/declarations.rbs +10 -3
  127. data/sig/definition.rbs +80 -12
  128. data/sig/definition_builder.rbs +18 -4
  129. data/sig/directives.rbs +17 -1
  130. data/sig/environment.rbs +3 -1
  131. data/sig/errors.rbs +19 -0
  132. data/sig/namespace.rbs +2 -3
  133. data/sig/parser.rbs +5 -1
  134. data/sig/prototype/rb.rbs +1 -1
  135. data/sig/resolver/constant_resolver.rbs +2 -2
  136. data/sig/resolver/context.rbs +1 -1
  137. data/sig/subtractor.rbs +1 -1
  138. data/sig/test/type_check.rbs +2 -2
  139. data/sig/type_alias_dependency.rbs +2 -2
  140. data/sig/type_alias_regularity.rbs +6 -6
  141. data/sig/type_param.rbs +4 -4
  142. data/sig/typename.rbs +8 -5
  143. data/sig/types.rbs +1 -1
  144. data/sig/unit_test/spy.rbs +2 -0
  145. data/sig/unit_test/type_assertions.rbs +2 -0
  146. data/sig/use_map.rbs +1 -1
  147. data/sig/validator.rbs +6 -2
  148. data/sig/vendorer.rbs +1 -1
  149. data/sig/writer.rbs +1 -1
  150. data/{ext/rbs_extension → src}/constants.c +35 -36
  151. data/src/ruby_objs.c +799 -0
  152. data/src/util/rbs_constant_pool.c +342 -0
  153. data/stdlib/base64/0/base64.rbs +0 -9
  154. data/stdlib/benchmark/0/benchmark.rbs +11 -2
  155. data/stdlib/bigdecimal/0/big_decimal.rbs +26 -182
  156. data/stdlib/cgi/0/core.rbs +60 -3
  157. data/stdlib/cgi/0/manifest.yaml +1 -0
  158. data/stdlib/coverage/0/coverage.rbs +0 -3
  159. data/stdlib/csv/0/csv.rbs +18 -58
  160. data/stdlib/csv/0/manifest.yaml +1 -0
  161. data/stdlib/date/0/date.rbs +27 -42
  162. data/stdlib/did_you_mean/0/did_you_mean.rbs +1 -6
  163. data/stdlib/digest/0/digest.rbs +25 -2
  164. data/stdlib/erb/0/erb.rbs +0 -1
  165. data/stdlib/etc/0/etc.rbs +51 -34
  166. data/stdlib/fileutils/0/fileutils.rbs +3 -44
  167. data/stdlib/io-console/0/io-console.rbs +69 -15
  168. data/stdlib/ipaddr/0/ipaddr.rbs +16 -4
  169. data/stdlib/json/0/json.rbs +107 -120
  170. data/stdlib/logger/0/log_device.rbs +1 -1
  171. data/stdlib/logger/0/logger.rbs +3 -18
  172. data/stdlib/minitest/0/kernel.rbs +2 -2
  173. data/stdlib/minitest/0/minitest/abstract_reporter.rbs +4 -1
  174. data/stdlib/minitest/0/minitest/assertion.rbs +1 -0
  175. data/stdlib/minitest/0/minitest/assertions.rbs +58 -13
  176. data/stdlib/minitest/0/minitest/backtrace_filter.rbs +7 -0
  177. data/stdlib/minitest/0/minitest/bench_spec.rbs +8 -8
  178. data/stdlib/minitest/0/minitest/benchmark.rbs +17 -16
  179. data/stdlib/minitest/0/minitest/compress.rbs +13 -0
  180. data/stdlib/minitest/0/minitest/error_on_warning.rbs +3 -0
  181. data/stdlib/minitest/0/minitest/mock.rbs +9 -5
  182. data/stdlib/minitest/0/minitest/parallel/executor.rbs +4 -0
  183. data/stdlib/minitest/0/minitest/parallel/test/class_methods.rbs +0 -1
  184. data/stdlib/minitest/0/minitest/pride_io.rbs +8 -0
  185. data/stdlib/minitest/0/minitest/pride_lol.rbs +2 -0
  186. data/stdlib/minitest/0/minitest/progress_reporter.rbs +1 -1
  187. data/stdlib/minitest/0/minitest/reportable.rbs +2 -0
  188. data/stdlib/minitest/0/minitest/runnable.rbs +33 -1
  189. data/stdlib/minitest/0/minitest/spec/dsl/instance_methods.rbs +1 -1
  190. data/stdlib/minitest/0/minitest/spec/dsl.rbs +10 -6
  191. data/stdlib/minitest/0/minitest/spec.rbs +1 -1
  192. data/stdlib/minitest/0/minitest/statistics_reporter.rbs +5 -0
  193. data/stdlib/minitest/0/minitest/summary_reporter.rbs +0 -7
  194. data/stdlib/minitest/0/minitest/test/lifecycle_hooks.rbs +1 -1
  195. data/stdlib/minitest/0/minitest/test.rbs +7 -14
  196. data/stdlib/minitest/0/minitest/unexpected_error.rbs +2 -0
  197. data/stdlib/minitest/0/minitest/unexpected_warning.rbs +6 -0
  198. data/stdlib/minitest/0/minitest/unit.rbs +1 -2
  199. data/stdlib/minitest/0/minitest.rbs +41 -892
  200. data/stdlib/monitor/0/monitor.rbs +13 -4
  201. data/stdlib/net-http/0/net-http.rbs +42 -109
  202. data/stdlib/nkf/0/nkf.rbs +30 -0
  203. data/stdlib/objspace/0/objspace.rbs +1 -2
  204. data/stdlib/observable/0/observable.rbs +1 -1
  205. data/stdlib/open-uri/0/manifest.yaml +1 -0
  206. data/stdlib/open-uri/0/open-uri.rbs +52 -0
  207. data/stdlib/open3/0/open3.rbs +0 -8
  208. data/stdlib/openssl/0/manifest.yaml +1 -0
  209. data/stdlib/openssl/0/openssl.rbs +235 -143
  210. data/stdlib/optparse/0/optparse.rbs +58 -18
  211. data/stdlib/pathname/0/pathname.rbs +2 -8
  212. data/stdlib/pp/0/pp.rbs +3 -1
  213. data/stdlib/prettyprint/0/prettyprint.rbs +0 -4
  214. data/stdlib/pstore/0/pstore.rbs +0 -6
  215. data/stdlib/psych/0/core_ext.rbs +12 -0
  216. data/stdlib/psych/0/psych.rbs +15 -4
  217. data/stdlib/pty/0/pty.rbs +46 -4
  218. data/stdlib/rdoc/0/code_object.rbs +0 -4
  219. data/stdlib/rdoc/0/markup.rbs +10 -12
  220. data/stdlib/rdoc/0/rdoc.rbs +13 -8
  221. data/stdlib/resolv/0/resolv.rbs +21 -12
  222. data/stdlib/ripper/0/ripper.rbs +0 -2
  223. data/stdlib/securerandom/0/securerandom.rbs +7 -2
  224. data/stdlib/shellwords/0/shellwords.rbs +11 -12
  225. data/stdlib/singleton/0/singleton.rbs +0 -1
  226. data/stdlib/socket/0/addrinfo.rbs +1 -2
  227. data/stdlib/socket/0/basic_socket.rbs +0 -5
  228. data/stdlib/socket/0/socket.rbs +32 -27
  229. data/stdlib/socket/0/tcp_server.rbs +0 -3
  230. data/stdlib/socket/0/tcp_socket.rbs +36 -3
  231. data/stdlib/socket/0/udp_socket.rbs +0 -1
  232. data/stdlib/socket/0/unix_server.rbs +0 -3
  233. data/stdlib/socket/0/unix_socket.rbs +4 -2
  234. data/{core/string_io.rbs → stdlib/stringio/0/stringio.rbs} +1 -1
  235. data/stdlib/strscan/0/string_scanner.rbs +1265 -422
  236. data/stdlib/tempfile/0/tempfile.rbs +135 -28
  237. data/stdlib/time/0/time.rbs +48 -35
  238. data/stdlib/timeout/0/timeout.rbs +11 -8
  239. data/stdlib/tmpdir/0/tmpdir.rbs +10 -3
  240. data/stdlib/tsort/0/tsort.rbs +0 -4
  241. data/stdlib/uri/0/common.rbs +28 -30
  242. data/stdlib/uri/0/ftp.rbs +1 -1
  243. data/stdlib/uri/0/generic.rbs +22 -18
  244. data/stdlib/uri/0/http.rbs +2 -2
  245. data/stdlib/uri/0/rfc2396_parser.rbs +3 -0
  246. data/stdlib/zlib/0/buf_error.rbs +1 -70
  247. data/stdlib/zlib/0/data_error.rbs +1 -70
  248. data/stdlib/zlib/0/deflate.rbs +8 -72
  249. data/stdlib/zlib/0/error.rbs +1 -70
  250. data/stdlib/zlib/0/gzip_file/crc_error.rbs +2 -105
  251. data/stdlib/zlib/0/gzip_file/error.rbs +2 -105
  252. data/stdlib/zlib/0/gzip_file/length_error.rbs +2 -105
  253. data/stdlib/zlib/0/gzip_file/no_footer.rbs +2 -105
  254. data/stdlib/zlib/0/gzip_file.rbs +1 -71
  255. data/stdlib/zlib/0/gzip_reader.rbs +3 -74
  256. data/stdlib/zlib/0/gzip_writer.rbs +1 -70
  257. data/stdlib/zlib/0/inflate.rbs +4 -71
  258. data/stdlib/zlib/0/mem_error.rbs +1 -70
  259. data/stdlib/zlib/0/need_dict.rbs +1 -70
  260. data/stdlib/zlib/0/stream_end.rbs +1 -70
  261. data/stdlib/zlib/0/stream_error.rbs +1 -70
  262. data/stdlib/zlib/0/version_error.rbs +1 -70
  263. data/stdlib/zlib/0/zlib.rbs +0 -2
  264. data/stdlib/zlib/0/zstream.rbs +4 -72
  265. metadata +17 -13
  266. data/ext/rbs_extension/ruby_objs.c +0 -602
  267. data/ext/rbs_extension/ruby_objs.h +0 -51
  268. data/stdlib/minitest/0/manifest.yaml +0 -2
@@ -0,0 +1,342 @@
1
+ #include "rbs/util/rbs_constant_pool.h"
2
+
3
+ /**
4
+ * Initialize a list of constant ids.
5
+ */
6
+ void
7
+ rbs_constant_id_list_init(rbs_constant_id_list_t *list) {
8
+ list->ids = NULL;
9
+ list->size = 0;
10
+ list->capacity = 0;
11
+ }
12
+
13
+ /**
14
+ * Initialize a list of constant ids with a given capacity.
15
+ */
16
+ void
17
+ rbs_constant_id_list_init_capacity(rbs_constant_id_list_t *list, size_t capacity) {
18
+ list->ids = calloc(capacity, sizeof(rbs_constant_id_t));
19
+ if (list->ids == NULL) abort();
20
+
21
+ list->size = 0;
22
+ list->capacity = capacity;
23
+ }
24
+
25
+ /**
26
+ * Append a constant id to a list of constant ids. Returns false if any
27
+ * potential reallocations fail.
28
+ */
29
+ bool
30
+ rbs_constant_id_list_append(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
31
+ if (list->size >= list->capacity) {
32
+ list->capacity = list->capacity == 0 ? 8 : list->capacity * 2;
33
+ list->ids = (rbs_constant_id_t *) realloc(list->ids, sizeof(rbs_constant_id_t) * list->capacity);
34
+ if (list->ids == NULL) return false;
35
+ }
36
+
37
+ list->ids[list->size++] = id;
38
+ return true;
39
+ }
40
+
41
+ /**
42
+ * Insert a constant id into a list of constant ids at the specified index.
43
+ */
44
+ void
45
+ rbs_constant_id_list_insert(rbs_constant_id_list_t *list, size_t index, rbs_constant_id_t id) {
46
+ assert(index < list->capacity);
47
+ assert(list->ids[index] == RBS_CONSTANT_ID_UNSET);
48
+
49
+ list->ids[index] = id;
50
+ list->size++;
51
+ }
52
+
53
+ /**
54
+ * Checks if the current constant id list includes the given constant id.
55
+ */
56
+ bool
57
+ rbs_constant_id_list_includes(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
58
+ for (size_t index = 0; index < list->size; index++) {
59
+ if (list->ids[index] == id) return true;
60
+ }
61
+ return false;
62
+ }
63
+
64
+ /**
65
+ * Free the memory associated with a list of constant ids.
66
+ */
67
+ void
68
+ rbs_constant_id_list_free(rbs_constant_id_list_t *list) {
69
+ if (list->ids != NULL) {
70
+ free(list->ids);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * A relatively simple hash function (djb2) that is used to hash strings. We are
76
+ * optimizing here for simplicity and speed.
77
+ */
78
+ static inline uint32_t
79
+ rbs_constant_pool_hash(const uint8_t *start, size_t length) {
80
+ // This is a prime number used as the initial value for the hash function.
81
+ uint32_t value = 5381;
82
+
83
+ for (size_t index = 0; index < length; index++) {
84
+ value = ((value << 5) + value) + start[index];
85
+ }
86
+
87
+ return value;
88
+ }
89
+
90
+ /**
91
+ * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
92
+ */
93
+ static uint32_t
94
+ next_power_of_two(uint32_t v) {
95
+ // Avoid underflow in subtraction on next line.
96
+ if (v == 0) {
97
+ // 1 is the nearest power of 2 to 0 (2^0)
98
+ return 1;
99
+ }
100
+ v--;
101
+ v |= v >> 1;
102
+ v |= v >> 2;
103
+ v |= v >> 4;
104
+ v |= v >> 8;
105
+ v |= v >> 16;
106
+ v++;
107
+ return v;
108
+ }
109
+
110
+ #ifndef NDEBUG
111
+ static bool
112
+ is_power_of_two(uint32_t size) {
113
+ return (size & (size - 1)) == 0;
114
+ }
115
+ #endif
116
+
117
+ /**
118
+ * Resize a constant pool to a given capacity.
119
+ */
120
+ static inline bool
121
+ rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
122
+ assert(is_power_of_two(pool->capacity));
123
+
124
+ uint32_t next_capacity = pool->capacity * 2;
125
+ if (next_capacity < pool->capacity) return false;
126
+
127
+ const uint32_t mask = next_capacity - 1;
128
+ const size_t element_size = sizeof(rbs_constant_pool_bucket_t) + sizeof(rbs_constant_t);
129
+
130
+ void *next = calloc(next_capacity, element_size);
131
+ if (next == NULL) return false;
132
+
133
+ rbs_constant_pool_bucket_t *next_buckets = next;
134
+ rbs_constant_t *next_constants = (void *)(((char *) next) + next_capacity * sizeof(rbs_constant_pool_bucket_t));
135
+
136
+ // For each bucket in the current constant pool, find the index in the
137
+ // next constant pool, and insert it.
138
+ for (uint32_t index = 0; index < pool->capacity; index++) {
139
+ rbs_constant_pool_bucket_t *bucket = &pool->buckets[index];
140
+
141
+ // If an id is set on this constant, then we know we have content here.
142
+ // In this case we need to insert it into the next constant pool.
143
+ if (bucket->id != RBS_CONSTANT_ID_UNSET) {
144
+ uint32_t next_index = bucket->hash & mask;
145
+
146
+ // This implements linear scanning to find the next available slot
147
+ // in case this index is already taken. We don't need to bother
148
+ // comparing the values since we know that the hash is unique.
149
+ while (next_buckets[next_index].id != RBS_CONSTANT_ID_UNSET) {
150
+ next_index = (next_index + 1) & mask;
151
+ }
152
+
153
+ // Here we copy over the entire bucket, which includes the id so
154
+ // that they are consistent between resizes.
155
+ next_buckets[next_index] = *bucket;
156
+ }
157
+ }
158
+
159
+ // The constants are stable with respect to hash table resizes.
160
+ memcpy(next_constants, pool->constants, pool->size * sizeof(rbs_constant_t));
161
+
162
+ // pool->constants and pool->buckets are allocated out of the same chunk
163
+ // of memory, with the buckets coming first.
164
+ free(pool->buckets);
165
+ pool->constants = next_constants;
166
+ pool->buckets = next_buckets;
167
+ pool->capacity = next_capacity;
168
+ return true;
169
+ }
170
+
171
+ // This storage is initialized by `Init_rbs_extension()` in `main.c`.
172
+ static rbs_constant_pool_t RBS_GLOBAL_CONSTANT_POOL_STORAGE = { 0 };
173
+ rbs_constant_pool_t *RBS_GLOBAL_CONSTANT_POOL = &RBS_GLOBAL_CONSTANT_POOL_STORAGE;
174
+
175
+ /**
176
+ * Initialize a new constant pool with a given capacity.
177
+ */
178
+ bool
179
+ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
180
+ const uint32_t maximum = (~((uint32_t) 0));
181
+ if (capacity >= ((maximum / 2) + 1)) return false;
182
+
183
+ capacity = next_power_of_two(capacity);
184
+ const size_t element_size = sizeof(rbs_constant_pool_bucket_t) + sizeof(rbs_constant_t);
185
+ void *memory = calloc(capacity, element_size);
186
+ if (memory == NULL) return false;
187
+
188
+ pool->buckets = memory;
189
+ pool->constants = (void *)(((char *)memory) + capacity * sizeof(rbs_constant_pool_bucket_t));
190
+ pool->size = 0;
191
+ pool->capacity = capacity;
192
+ return true;
193
+ }
194
+
195
+ /**
196
+ * Return a pointer to the constant indicated by the given constant id.
197
+ */
198
+ rbs_constant_t *
199
+ rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_id_t constant_id) {
200
+ assert(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size);
201
+ return &pool->constants[constant_id - 1];
202
+ }
203
+
204
+ /**
205
+ * Find a constant in a constant pool. Returns the id of the constant, or 0 if
206
+ * the constant is not found.
207
+ */
208
+ rbs_constant_id_t
209
+ rbs_constant_pool_find(const rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
210
+ assert(is_power_of_two(pool->capacity));
211
+ const uint32_t mask = pool->capacity - 1;
212
+
213
+ uint32_t hash = rbs_constant_pool_hash(start, length);
214
+ uint32_t index = hash & mask;
215
+ rbs_constant_pool_bucket_t *bucket;
216
+
217
+ while (bucket = &pool->buckets[index], bucket->id != RBS_CONSTANT_ID_UNSET) {
218
+ rbs_constant_t *constant = &pool->constants[bucket->id - 1];
219
+ if ((constant->length == length) && memcmp(constant->start, start, length) == 0) {
220
+ return bucket->id;
221
+ }
222
+
223
+ index = (index + 1) & mask;
224
+ }
225
+
226
+ return RBS_CONSTANT_ID_UNSET;
227
+ }
228
+
229
+ /**
230
+ * Insert a constant into a constant pool and return its index in the pool.
231
+ */
232
+ static inline rbs_constant_id_t
233
+ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t length, rbs_constant_pool_bucket_type_t type) {
234
+ if (pool->size >= (pool->capacity / 4 * 3)) {
235
+ if (!rbs_constant_pool_resize(pool)) return RBS_CONSTANT_ID_UNSET;
236
+ }
237
+
238
+ assert(is_power_of_two(pool->capacity));
239
+ const uint32_t mask = pool->capacity - 1;
240
+
241
+ uint32_t hash = rbs_constant_pool_hash(start, length);
242
+ uint32_t index = hash & mask;
243
+ rbs_constant_pool_bucket_t *bucket;
244
+
245
+ while (bucket = &pool->buckets[index], bucket->id != RBS_CONSTANT_ID_UNSET) {
246
+ // If there is a collision, then we need to check if the content is the
247
+ // same as the content we are trying to insert. If it is, then we can
248
+ // return the id of the existing constant.
249
+ rbs_constant_t *constant = &pool->constants[bucket->id - 1];
250
+
251
+ if ((constant->length == length) && memcmp(constant->start, start, length) == 0) {
252
+ // Since we have found a match, we need to check if this is
253
+ // attempting to insert a shared or an owned constant. We want to
254
+ // prefer shared constants since they don't require allocations.
255
+ if (type == RBS_CONSTANT_POOL_BUCKET_OWNED) {
256
+ // If we're attempting to insert an owned constant and we have
257
+ // an existing constant, then either way we don't want the given
258
+ // memory. Either it's duplicated with the existing constant or
259
+ // it's not necessary because we have a shared version.
260
+ free((void *) start);
261
+ } else if (bucket->type == RBS_CONSTANT_POOL_BUCKET_OWNED) {
262
+ // If we're attempting to insert a shared constant and the
263
+ // existing constant is owned, then we can free the owned
264
+ // constant and replace it with the shared constant.
265
+ free((void *) constant->start);
266
+ constant->start = start;
267
+ bucket->type = (unsigned int) (RBS_CONSTANT_POOL_BUCKET_DEFAULT & 0x3);
268
+ }
269
+
270
+ return bucket->id;
271
+ }
272
+
273
+ index = (index + 1) & mask;
274
+ }
275
+
276
+ // IDs are allocated starting at 1, since the value 0 denotes a non-existent
277
+ // constant.
278
+ uint32_t id = ++pool->size;
279
+ assert(pool->size < ((uint32_t) (1 << 30)));
280
+
281
+ *bucket = (rbs_constant_pool_bucket_t) {
282
+ .id = (unsigned int) (id & 0x3fffffff),
283
+ .type = (unsigned int) (type & 0x3),
284
+ .hash = hash
285
+ };
286
+
287
+ pool->constants[id - 1] = (rbs_constant_t) {
288
+ .start = start,
289
+ .length = length,
290
+ };
291
+
292
+ return id;
293
+ }
294
+
295
+ /**
296
+ * Insert a constant into a constant pool. Returns the id of the constant, or
297
+ * RBS_CONSTANT_ID_UNSET if any potential calls to resize fail.
298
+ */
299
+ rbs_constant_id_t
300
+ rbs_constant_pool_insert_shared(rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
301
+ return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_DEFAULT);
302
+ }
303
+
304
+ /**
305
+ * Insert a constant into a constant pool from memory that is now owned by the
306
+ * constant pool. Returns the id of the constant, or RBS_CONSTANT_ID_UNSET if any
307
+ * potential calls to resize fail.
308
+ */
309
+ rbs_constant_id_t
310
+ rbs_constant_pool_insert_owned(rbs_constant_pool_t *pool, uint8_t *start, size_t length) {
311
+ return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_OWNED);
312
+ }
313
+
314
+ /**
315
+ * Insert a constant into a constant pool from memory that is constant. Returns
316
+ * the id of the constant, or RBS_CONSTANT_ID_UNSET if any potential calls to
317
+ * resize fail.
318
+ */
319
+ rbs_constant_id_t
320
+ rbs_constant_pool_insert_constant(rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
321
+ return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_CONSTANT);
322
+ }
323
+
324
+ /**
325
+ * Free the memory associated with a constant pool.
326
+ */
327
+ void
328
+ rbs_constant_pool_free(rbs_constant_pool_t *pool) {
329
+ // For each constant in the current constant pool, free the contents if the
330
+ // contents are owned.
331
+ for (uint32_t index = 0; index < pool->capacity; index++) {
332
+ rbs_constant_pool_bucket_t *bucket = &pool->buckets[index];
333
+
334
+ // If an id is set on this constant, then we know we have content here.
335
+ if (bucket->id != RBS_CONSTANT_ID_UNSET && bucket->type == RBS_CONSTANT_POOL_BUCKET_OWNED) {
336
+ rbs_constant_t *constant = &pool->constants[bucket->id - 1];
337
+ free((void *) constant->start);
338
+ }
339
+ }
340
+
341
+ free(pool->buckets);
342
+ }
@@ -5,14 +5,12 @@
5
5
  # printable ASCII characters.
6
6
  # * Decoding such an encoded string.
7
7
  #
8
- #
9
8
  # Base64 is commonly used in contexts where binary data is not allowed or
10
9
  # supported:
11
10
  #
12
11
  # * Images in HTML or CSS files, or in URLs.
13
12
  # * Email attachments.
14
13
  #
15
- #
16
14
  # A Base64-encoded string is about one-third larger that its source. See the
17
15
  # [Wikipedia article](https://en.wikipedia.org/wiki/Base64) for more
18
16
  # information.
@@ -24,7 +22,6 @@
24
22
  # * Whether "padding" is to be used.
25
23
  # * Whether encoded strings are to contain newlines.
26
24
  #
27
- #
28
25
  # Note: Examples on this page assume that the including program has executed:
29
26
  #
30
27
  # require 'base64'
@@ -45,22 +42,18 @@
45
42
  # [RFC-4648-compliant](https://datatracker.ietf.org/doc/html/rfc4648);
46
43
  # safe for URLs.
47
44
  #
48
- #
49
- #
50
45
  # If you are working with Base64-encoded strings that will come from or be put
51
46
  # into URLs, you should choose this encoder-decoder pair of RFC-4648-compliant
52
47
  # methods:
53
48
  #
54
49
  # * Base64.urlsafe_encode64 and Base64.urlsafe_decode64.
55
50
  #
56
- #
57
51
  # Otherwise, you may choose any of the pairs in this module, including the pair
58
52
  # above, or the RFC-2045-compliant pairs:
59
53
  #
60
54
  # * Base64.encode64 and Base64.decode64.
61
55
  # * Base64.strict_encode64 and Base64.strict_decode64.
62
56
  #
63
- #
64
57
  # ## Padding
65
58
  #
66
59
  # Base64-encoding changes a triplet of input bytes into a quartet of output
@@ -104,7 +97,6 @@
104
97
  # # n = 2: 8 bytes => 12 characters.
105
98
  # Base64.strict_encode64('12345678') # => "MDEyMzQ1Njc="
106
99
  #
107
- #
108
100
  # When padding is suppressed, for a positive integer *n*:
109
101
  #
110
102
  # * Input bytes of length *3n* generate unpadded output characters of length
@@ -131,7 +123,6 @@
131
123
  # # m = 2: 8 bytes => 11 characters.
132
124
  # Base64.urlsafe_encode64('12345678', padding: false) # => "MDEyMzQ1Njc"
133
125
  #
134
- #
135
126
  # **Padding in Decode Methods**
136
127
  #
137
128
  # All of the Base64 decode methods support (but do not require) padding.
@@ -46,7 +46,6 @@
46
46
  # x.report("upto:") { 1.upto(n) do ; a = "1"; end }
47
47
  # end
48
48
  #
49
- #
50
49
  # The result:
51
50
  #
52
51
  # user system total real
@@ -241,7 +240,11 @@ module Benchmark
241
240
  # rdoc-file=lib/benchmark.rb
242
241
  # - realtime() { || ... }
243
242
  # -->
244
- # Returns the elapsed real time used to execute the given block.
243
+ # Returns the elapsed real time used to execute the given block. The unit of
244
+ # time is seconds.
245
+ #
246
+ # Benchmark.realtime { "a" * 1_000_000_000 }
247
+ # #=> 0.5098029999935534
245
248
  #
246
249
  def self?.realtime: () { () -> void } -> Float
247
250
 
@@ -366,17 +369,23 @@ module Benchmark
366
369
  #
367
370
  # `%u`
368
371
  # : Replaced by the user CPU time, as reported by Tms#utime.
372
+ #
369
373
  # `%y`
370
374
  # : Replaced by the system CPU time, as reported by #stime (Mnemonic: y of
371
375
  # "s*y*stem")
376
+ #
372
377
  # `%U`
373
378
  # : Replaced by the children's user CPU time, as reported by Tms#cutime
379
+ #
374
380
  # `%Y`
375
381
  # : Replaced by the children's system CPU time, as reported by Tms#cstime
382
+ #
376
383
  # `%t`
377
384
  # : Replaced by the total CPU time, as reported by Tms#total
385
+ #
378
386
  # `%r`
379
387
  # : Replaced by the elapsed real time, as reported by Tms#real
388
+ #
380
389
  # `%n`
381
390
  # : Replaced by the label string, as reported by Tms#label (Mnemonic: n of
382
391
  # "*n*ame")