Skip to content

Commit 3f0e61f

Browse files
committed
Speed up integer parsing in prism_compile.c
1 parent c45f781 commit 3f0e61f

1 file changed

Lines changed: 12 additions & 15 deletions

File tree

prism_compile.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -262,24 +262,21 @@ parse_integer_value(const pm_integer_t *integer)
262262
result = UINT2NUM(integer->value);
263263
}
264264
else {
265-
VALUE string = rb_str_new(NULL, integer->length * 8);
266-
unsigned char *bytes = (unsigned char *) RSTRING_PTR(string);
267-
268-
size_t offset = integer->length * 8;
269-
for (size_t value_index = 0; value_index < integer->length; value_index++) {
270-
uint32_t value = integer->values[value_index];
271-
272-
for (int index = 0; index < 8; index++) {
273-
int byte = (value >> (4 * index)) & 0xf;
274-
bytes[--offset] = byte < 10 ? byte + '0' : byte - 10 + 'a';
275-
}
276-
}
277-
278-
result = rb_funcall(string, rb_intern("to_i"), 1, UINT2NUM(16));
265+
// The pm_integer_t stores values as an array of uint32_t in
266+
// least-significant-word-first order (base 2^32). We can convert
267+
// directly to a Ruby Integer using rb_integer_unpack, avoiding the
268+
// overhead of constructing a hex string and calling rb_funcall.
269+
result = rb_integer_unpack(
270+
integer->values,
271+
integer->length,
272+
sizeof(uint32_t),
273+
0,
274+
INTEGER_PACK_LSWORD_FIRST | INTEGER_PACK_NATIVE_BYTE_ORDER
275+
);
279276
}
280277

281278
if (integer->negative) {
282-
result = rb_funcall(result, rb_intern("-@"), 0);
279+
result = rb_int_uminus(result);
283280
}
284281

285282
if (!SPECIAL_CONST_P(result)) {

0 commit comments

Comments
 (0)