2424 stream /1 ,
2525 backend /1 ,
2626 beam_chunk_header /3 ,
27- compile /5
27+ compile /6
2828]).
2929
3030% NIFs
9898 line_offsets :: [{integer (), integer ()}],
9999 labels_count :: pos_integer (),
100100 atom_resolver :: fun ((integer ()) -> atom ()),
101- literal_resolver :: fun ((integer ()) -> any ())
101+ literal_resolver :: fun ((integer ()) -> any ()),
102+ type_resolver :: fun ((integer ()) -> any ())
102103}).
103104
104105-type stream () :: any ().
@@ -130,6 +131,7 @@ compile(
130131 <<16 :32 , 0 :32 , OpcodeMax :32 , LabelsCount :32 , _FunctionsCount :32 , Opcodes /binary >>,
131132 AtomResolver ,
132133 LiteralResolver ,
134+ TypeResolver ,
133135 MMod ,
134136 MSt0
135137) when OpcodeMax =< ? OPCODE_MAX ->
@@ -138,7 +140,8 @@ compile(
138140 line_offsets = [],
139141 labels_count = LabelsCount ,
140142 atom_resolver = AtomResolver ,
141- literal_resolver = LiteralResolver
143+ literal_resolver = LiteralResolver ,
144+ type_resolver = TypeResolver
142145 },
143146 {State1 , MSt2 } = first_pass (Opcodes , MMod , MSt1 , State0 ),
144147 MSt3 = second_pass (MMod , MSt2 , State1 ),
@@ -147,11 +150,12 @@ compile(
147150 <<16 :32 , 0 :32 , OpcodeMax :32 , _LabelsCount :32 , _FunctionsCount :32 , _Opcodes /binary >>,
148151 _AtomResolver ,
149152 _LiteralResolver ,
153+ _TypeResolver ,
150154 _MMod ,
151155 _MSt
152156) ->
153157 error (badarg , [OpcodeMax ]);
154- compile (CodeChunk , _AtomResolver , _LiteralResolver , _MMod , _MSt ) ->
158+ compile (CodeChunk , _AtomResolver , _LiteralResolver , _TypeResolver , _MMod , _MSt ) ->
155159 error (badarg , [CodeChunk ]).
156160
157161% 1
@@ -1143,7 +1147,7 @@ first_pass(<<?OP_IS_FUNCTION2, Rest0/binary>>, MMod, MSt0, State0) ->
11431147 ? ASSERT_ALL_NATIVE_FREE (MSt0 ),
11441148 {Label , Rest1 } = decode_label (Rest0 ),
11451149 {MSt1 , Arg1 , Rest2 } = decode_compact_term (Rest1 , MMod , MSt0 , State0 ),
1146- {MSt2 , ArityTerm , Rest3 } = decode_compact_term (Rest2 , MMod , MSt1 , State0 ),
1150+ {MSt2 , ArityTerm , Rest3 } = decode_typed_compact_term (Rest2 , MMod , MSt1 , State0 ),
11471151 ? TRACE (" OP_IS_FUNCTION2 ~p ,~p ,~p \n " , [Label , Arg1 , ArityTerm ]),
11481152 {MSt3 , FuncPtr } = term_is_boxed_with_tag_and_get_ptr (Label , Arg1 , ? TERM_BOXED_FUN , MMod , MSt2 ),
11491153 {MSt4 , Arity } = term_to_int (ArityTerm , Label , MMod , MSt3 ),
@@ -1174,7 +1178,7 @@ first_pass(<<?OP_BS_GET_INTEGER2, Rest0/binary>>, MMod, MSt0, State0) ->
11741178 {Fail , Rest1 } = decode_label (Rest0 ),
11751179 {MSt1 , Src , Rest2 } = decode_compact_term (Rest1 , MMod , MSt0 , State0 ),
11761180 {_Live , Rest3 } = decode_literal (Rest2 ),
1177- {MSt2 , Size , Rest4 } = decode_compact_term (Rest3 , MMod , MSt1 , State0 ),
1181+ {MSt2 , Size , Rest4 } = decode_typed_compact_term (Rest3 , MMod , MSt1 , State0 ),
11781182 {Unit , Rest5 } = decode_literal (Rest4 ),
11791183 {FlagsValue , Rest6 } = decode_literal (Rest5 ),
11801184 {MSt3 , SrcReg } = MMod :move_to_native_register (MSt2 , Src ),
@@ -1213,7 +1217,7 @@ first_pass(<<?OP_BS_GET_FLOAT2, Rest0/binary>>, MMod, MSt0, State0) ->
12131217 {Fail , Rest1 } = decode_label (Rest0 ),
12141218 {MSt1 , Src , Rest2 } = decode_compact_term (Rest1 , MMod , MSt0 , State0 ),
12151219 {_Live , Rest3 } = decode_literal (Rest2 ),
1216- {MSt2 , Size , Rest4 } = decode_compact_term (Rest3 , MMod , MSt1 , State0 ),
1220+ {MSt2 , Size , Rest4 } = decode_typed_compact_term (Rest3 , MMod , MSt1 , State0 ),
12171221 {Unit , Rest5 } = decode_literal (Rest4 ),
12181222 {FlagsValue , Rest6 } = decode_literal (Rest5 ),
12191223 {MSt3 , SrcReg } = MMod :move_to_native_register (MSt2 , Src ),
@@ -1338,7 +1342,7 @@ first_pass(<<?OP_BS_SKIP_BITS2, Rest0/binary>>, MMod, MSt0, State0) ->
13381342 ? ASSERT_ALL_NATIVE_FREE (MSt0 ),
13391343 {Fail , Rest1 } = decode_label (Rest0 ),
13401344 {MSt1 , Src , Rest2 } = decode_compact_term (Rest1 , MMod , MSt0 , State0 ),
1341- {MSt2 , Size , Rest3 } = decode_compact_term (Rest2 , MMod , MSt1 , State0 ),
1345+ {MSt2 , Size , Rest3 } = decode_typed_compact_term (Rest2 , MMod , MSt1 , State0 ),
13421346 {Unit , Rest4 } = decode_literal (Rest3 ),
13431347 {_FlagsValue , Rest5 } = decode_literal (Rest4 ),
13441348 ? TRACE (" OP_BS_SKIP_BITS2 ~p , ~p , ~p , ~p , ~p \n " , [Fail , Src , Size , Unit , _FlagsValue ]),
@@ -2071,7 +2075,7 @@ first_pass(<<?OP_BS_GET_POSITION, Rest0/binary>>, MMod, MSt0, State0) ->
20712075first_pass (<<? OP_BS_SET_POSITION , Rest0 /binary >>, MMod , MSt0 , State0 ) ->
20722076 ? ASSERT_ALL_NATIVE_FREE (MSt0 ),
20732077 {MSt1 , Src , Rest1 } = decode_compact_term (Rest0 , MMod , MSt0 , State0 ),
2074- {MSt2 , Pos , Rest2 } = decode_compact_term (Rest1 , MMod , MSt1 , State0 ),
2078+ {MSt2 , Pos , Rest2 } = decode_typed_compact_term (Rest1 , MMod , MSt1 , State0 ),
20752079 ? TRACE (" OP_BS_SET_POSITION ~p , ~p \n " , [Src , Pos ]),
20762080 {MSt3 , MatchStateReg } = MMod :move_to_native_register (MSt2 , Src ),
20772081 {MSt4 , MatchStateRegPtr } = verify_is_match_state_and_get_ptr (MMod , MSt3 , {free , MatchStateReg }),
@@ -2814,7 +2818,7 @@ first_pass_bs_match_integer(
28142818 {_Live , Rest1 } = decode_literal (Rest0 ),
28152819 {Flags , Rest2 } = decode_compile_time_literal (Rest1 , State0 ),
28162820 {MSt1 , FlagsValue } = decode_flags_list (Flags , MMod , MSt0 ),
2817- {MSt2 , Size , Rest3 } = decode_compact_term (Rest2 , MMod , MSt0 , State0 ),
2821+ {MSt2 , Size , Rest3 } = decode_typed_compact_term (Rest2 , MMod , MSt0 , State0 ),
28182822 {Unit , Rest4 } = decode_literal (Rest3 ),
28192823 ? TRACE (" {integer,~p ,~p ,~p , " , [Flags , Size , Unit ]),
28202824 {MSt3 , SizeReg } = term_to_int (Size , 0 , MMod , MSt1 ),
@@ -3185,6 +3189,14 @@ term_to_int(Term, _FailLabel, _MMod, MSt0) when is_integer(Term) ->
31853189 {MSt0 , Term bsr 4 };
31863190term_to_int ({literal , Val }, _FailLabel , _MMod , MSt0 ) when is_integer (Val ) ->
31873191 {MSt0 , Val };
3192+ % Optimized case: when we have type information showing this is an integer, skip the type check
3193+ term_to_int ({typed , Term , {t_integer , _Range }}, _FailLabel , MMod , MSt0 ) ->
3194+ {MSt1 , Reg } = MMod :move_to_native_register (MSt0 , Term ),
3195+ MSt2 = MMod :shift_right (MSt1 , Reg , 4 ),
3196+ {MSt2 , Reg };
3197+ term_to_int ({typed , Term , _NonIntegerType }, FailLabel , MMod , MSt0 ) ->
3198+ % Type information shows it's not an integer, fall back to generic path
3199+ term_to_int (Term , FailLabel , MMod , MSt0 );
31883200term_to_int (Term , FailLabel , MMod , MSt0 ) ->
31893201 {MSt1 , Reg } = MMod :move_to_native_register (MSt0 , Term ),
31903202 MSt2 = cond_raise_badarg_or_jump_to_fail_label (
@@ -3357,6 +3369,17 @@ decode_compact_term(<<_Value:5, ?COMPACT_LITERAL:3, _Rest/binary>> = Binary, _MM
33573369decode_compact_term (Other , MMod , MSt , _State ) ->
33583370 decode_dest (Other , MMod , MSt ).
33593371
3372+ % Decode compact term with type information awareness
3373+ decode_typed_compact_term (<<? COMPACT_EXTENDED_TYPED_REGISTER , Rest0 /binary >>, MMod , MSt0 , # state {
3374+ type_resolver = TypeResover
3375+ }) ->
3376+ {MSt1 , Dest , Rest1 } = decode_dest (Rest0 , MMod , MSt0 ),
3377+ {TypeIx , Rest2 } = decode_literal (Rest1 ),
3378+ Type = TypeResover (TypeIx ),
3379+ {MSt1 , {typed , Dest , Type }, Rest2 };
3380+ decode_typed_compact_term (Other , MMod , MSt , State ) ->
3381+ decode_compact_term (Other , MMod , MSt , State ).
3382+
33603383skip_compact_term (<<_ :4 , ? COMPACT_INTEGER :4 , _Rest /binary >> = Bin ) ->
33613384 {_Value , Rest } = decode_value64 (Bin ),
33623385 Rest ;
0 commit comments