@@ -1814,6 +1814,40 @@ static bool maybe_call_native(Context *ctx, atom_index_t module_name, atom_index
18141814#endif
18151815
18161816#ifndef AVM_NO_EMU
1817+ static term extract_nbits_integer (Context * ctx , const uint8_t * bytes , size_t bytes_size , intn_from_integer_options_t opts )
1818+ {
1819+ intn_integer_sign_t sign ;
1820+ intn_digit_t bigint [INTN_MAX_RES_LEN ];
1821+ int count = intn_from_integer_bytes (bytes , bytes_size , opts , bigint , & sign );
1822+ if (UNLIKELY (count < 0 )) {
1823+ // this is likely unreachable, compiler seem to generate an external term
1824+ // and to encode this as SMALL_BIG_EXT, so I don't think this code is executed
1825+ ctx -> x [0 ] = ERROR_ATOM ;
1826+ ctx -> x [1 ] = OVERFLOW_ATOM ;
1827+ return term_invalid_term ();
1828+ }
1829+
1830+ size_t intn_data_size ;
1831+ size_t rounded_res_len ;
1832+ term_bigint_size_requirements (count , & intn_data_size , & rounded_res_len );
1833+
1834+ Heap heap ;
1835+ if (UNLIKELY (
1836+ memory_init_heap (& heap , BOXED_BIGINT_HEAP_SIZE (intn_data_size )) != MEMORY_GC_OK )) {
1837+ ctx -> x [0 ] = ERROR_ATOM ;
1838+ ctx -> x [1 ] = OUT_OF_MEMORY_ATOM ;
1839+ return term_invalid_term ();
1840+ }
1841+
1842+ term bigint_term
1843+ = term_create_uninitialized_bigint (intn_data_size , (term_integer_sign_t ) sign , & heap );
1844+ term_initialize_bigint (bigint_term , bigint , count , rounded_res_len );
1845+
1846+ memory_heap_append_heap (& ctx -> heap , & heap );
1847+
1848+ return bigint_term ;
1849+ }
1850+
18171851 static size_t decode_nbits_integer (Context * ctx , const uint8_t * encoded , term * out_term )
18181852 {
18191853 const uint8_t * new_encoded = encoded ;
@@ -1826,41 +1860,9 @@ static bool maybe_call_native(Context *ctx, atom_index_t module_name, atom_index
18261860 len += 9 ;
18271861
18281862 if (out_term ) {
1829- intn_integer_sign_t sign ;
1830- intn_digit_t bigint [INTN_MAX_RES_LEN ];
1831- int count = intn_from_integer_bytes (new_encoded , len , IntnSigned , bigint , & sign );
1832- if (UNLIKELY (count < 0 )) {
1833- // this is likely unreachable, compiler seem to generate an external term
1834- // and to encode this as SMALL_BIG_EXT, so I don't think this code is executed
1835- ctx -> x [0 ] = ERROR_ATOM ;
1836- ctx -> x [1 ] = OVERFLOW_ATOM ;
1837- * out_term = term_invalid_term ();
1838- goto return_size ;
1839- }
1840-
1841- size_t intn_data_size ;
1842- size_t rounded_res_len ;
1843- term_bigint_size_requirements (count , & intn_data_size , & rounded_res_len );
1844-
1845- Heap heap ;
1846- if (UNLIKELY (
1847- memory_init_heap (& heap , BOXED_BIGINT_HEAP_SIZE (intn_data_size )) != MEMORY_GC_OK )) {
1848- ctx -> x [0 ] = ERROR_ATOM ;
1849- ctx -> x [1 ] = OUT_OF_MEMORY_ATOM ;
1850- * out_term = term_invalid_term ();
1851- goto return_size ;
1852- }
1853-
1854- term bigint_term
1855- = term_create_uninitialized_bigint (intn_data_size , (term_integer_sign_t ) sign , & heap );
1856- term_initialize_bigint (bigint_term , bigint , count , rounded_res_len );
1857-
1858- memory_heap_append_heap (& ctx -> heap , & heap );
1859-
1860- * out_term = bigint_term ;
1863+ * out_term = extract_nbits_integer (ctx , new_encoded , len , IntnSigned );
18611864 }
18621865
1863- return_size :
18641866 return (new_encoded - encoded ) + len ;
18651867 }
18661868#endif
@@ -5298,25 +5300,44 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
52985300 union maybe_unsigned_int64 value ;
52995301 term bs_bin = term_get_match_state_binary (src );
53005302 avm_int_t bs_offset = term_get_match_state_offset (src );
5301- bool status = bitstring_extract_integer (bs_bin , bs_offset , increment , flags_value , & value );
5302- if (UNLIKELY (!status )) {
5303- TRACE ("bs_get_integer2: error extracting integer.\n" );
5304- JUMP_TO_ADDRESS (mod -> labels [fail ]);
5305- } else {
5306- term_set_match_state_offset (src , bs_offset + increment );
5303+ term t ;
5304+ if (increment <= 64 ) {
5305+ bool status = bitstring_extract_integer (bs_bin , bs_offset , increment , flags_value , & value );
5306+ if (UNLIKELY (!status )) {
5307+ TRACE ("bs_get_integer2: error extracting integer.\n" );
5308+ JUMP_TO_ADDRESS (mod -> labels [fail ]);
5309+ } else {
5310+ term_set_match_state_offset (src , bs_offset + increment );
53075311
5308- term t = maybe_alloc_boxed_integer_fragment (ctx , value .s );
5309- if (UNLIKELY (term_is_invalid_term (t ))) {
5312+ t = maybe_alloc_boxed_integer_fragment (ctx , value .s );
5313+ if (UNLIKELY (term_is_invalid_term (t ))) {
5314+ HANDLE_ERROR ();
5315+ }
5316+ }
5317+ } else if ((bs_offset % 8 == 0 ) && (increment % 8 == 0 ) && (increment <= INTN_MAX_UNSIGNED_BITS_SIZE )) {
5318+ unsigned long capacity = term_binary_size (bs_bin );
5319+ if (8 * capacity - bs_offset < (unsigned long ) increment ) {
5320+ JUMP_TO_ADDRESS (mod -> labels [fail ]);
5321+ }
5322+ size_t byte_offset = bs_offset / 8 ;
5323+ const uint8_t * int_bytes = (const uint8_t * ) term_binary_data (bs_bin );
5324+
5325+ t = extract_nbits_integer (ctx , int_bytes + byte_offset , increment / 8 ,
5326+ bitstring_flags_to_intn_opts (flags_value ));
5327+ term_set_match_state_offset (src , bs_offset + increment );
5328+ if (term_is_invalid_term (t )) {
53105329 HANDLE_ERROR ();
53115330 }
5331+ } else {
5332+ JUMP_TO_ADDRESS (mod -> labels [fail ]);
5333+ }
53125334 #endif
53135335
53145336 DEST_REGISTER (dreg );
53155337 DECODE_DEST_REGISTER (dreg , pc );
53165338
53175339 #ifdef IMPL_EXECUTE_LOOP
5318- WRITE_REGISTER (dreg , t );
5319- }
5340+ WRITE_REGISTER (dreg , t );
53205341 #endif
53215342 break ;
53225343 }
@@ -7273,15 +7294,35 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
72737294 avm_int_t size_val = term_to_int (size );
72747295 avm_int_t increment = size_val * unit ;
72757296 union maybe_unsigned_int64 value ;
7276- bool status = bitstring_extract_integer (bs_bin , bs_offset , increment , flags_value , & value );
7277- if (UNLIKELY (!status )) {
7278- TRACE ("bs_match/3: error extracting integer.\n" );
7297+ term t ;
7298+ if (increment <= 64 ) {
7299+ bool status = bitstring_extract_integer (bs_bin , bs_offset , increment , flags_value , & value );
7300+ if (UNLIKELY (!status )) {
7301+ TRACE ("bs_match/3: error extracting integer.\n" );
7302+ goto bs_match_jump_to_fail ;
7303+ }
7304+ //FIXME: handling of 64-bit unsigned integers is not reliable
7305+ t = maybe_alloc_boxed_integer_fragment (ctx , value .s );
7306+ if (UNLIKELY (term_is_invalid_term (t ))) {
7307+ RAISE_ERROR (OUT_OF_MEMORY_ATOM );
7308+ }
7309+ } else if ((bs_offset % 8 == 0 ) && (increment % 8 == 0 ) && (increment <= INTN_MAX_UNSIGNED_BITS_SIZE )) {
7310+ unsigned long capacity = term_binary_size (bs_bin );
7311+ if (8 * capacity - bs_offset < (unsigned long ) increment ) {
7312+ goto bs_match_jump_to_fail ;
7313+ }
7314+ size_t byte_offset = bs_offset / 8 ;
7315+ const uint8_t * int_bytes
7316+ = (const uint8_t * ) term_binary_data (bs_bin );
7317+
7318+ t = extract_nbits_integer (ctx , int_bytes + byte_offset ,
7319+ increment / 8 , bitstring_flags_to_intn_opts (flags_value ));
7320+ if (term_is_invalid_term (t )) {
7321+ HANDLE_ERROR ();
7322+ }
7323+ } else {
72797324 goto bs_match_jump_to_fail ;
72807325 }
7281- term t = maybe_alloc_boxed_integer_fragment (ctx , value .s );
7282- if (UNLIKELY (term_is_invalid_term (t ))) {
7283- RAISE_ERROR (OUT_OF_MEMORY_ATOM );
7284- }
72857326 #endif
72867327 DEST_REGISTER (dreg );
72877328 DECODE_DEST_REGISTER (dreg , pc );
@@ -7388,6 +7429,10 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
73887429 DECODE_LITERAL (pattern_value , pc );
73897430 j ++ ;
73907431 #ifdef IMPL_EXECUTE_LOOP
7432+ if (size > 64 ) {
7433+ // TODO: implement support for big integers also here
7434+ RAISE_ERROR (BADARG_ATOM );
7435+ }
73917436 union maybe_unsigned_int64 matched_value ;
73927437 bool status = bitstring_extract_integer (bs_bin , bs_offset , size , 0 , & matched_value );
73937438 if (UNLIKELY (!status )) {
0 commit comments