aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/macros.tab
AgeCommit message (Collapse)Author
2017-11-06Warn when $REFRESH_GEN_DEST() is not used after a GCBjörn Gustavsson
It is easy to to forget to use $REFRESH_GEN_DEST() in an instruction that has a general destionation ('d'). Add a heuristic that should catch most if not all such problems.
2017-10-05macros.tab: Fix assertion in SET_I_REL()Björn Gustavsson
9a50a5d5fc1 changed the update of I, but forgot to update the preceding assertion.
2017-09-30Point out the correct line number in stack tracesBjörn Gustavsson
Sometimes the line number in a stack trace could be wrong, for example for this code: t() -> Res = id(x), %<== Wrong line number. Res + 1. id(I) -> I. The line number pointed out in the stack trace would be the line before the line where the exception occurred. The reason is the way the increment instruction instruction is implemented: OpCase(i_increment_rWtd): { increment_reg_val = r(0); } I -= 1; goto increment__execute; OpCase(i_increment_xWtd): { increment_reg_val = xb(I[1]); } goto increment__execute; increment__execute: /* Common code for increment */ . . . (The implementation in OTP 20 is similar, but hand-coded directly in beam_emu.c instead of generated.) The instruction i_increment_rWtd decrements the instruction pointer (I) before jumping to the common code. That means that I points *before* the 'increment' instruction. If there is a 'line' instruction directly before the 'increment' instruction (as there is in this example), the instruction pointer will point before that line. Thus the previous line will be picked up instead. To eliminate this bug, we must never decrement the instruction pointer. Instead, we can increment the other (longer) instructions in the same group of combined instructions: OpCase(i_increment_rWtd): { increment_reg_val = r(0); } goto increment__execute; OpCase(i_increment_xWtd): { increment_reg_val = xb(I[1]); } I += 1; goto increment__execute; increment__execute: /* Common code for increment */ . . . Also fix a bug that was only a potential bug when ddaed7774eb0a introduced relative jumps, but is now a real bug. See the added comment for SET_I_REL() in macros.tab.
2017-09-14Merge branch 'bjorn/erts/relative-jumps'Björn Gustavsson
* bjorn/erts/relative-jumps: Pack failure labels in i_select_val2 and i_select_tuple_arity2 Optimize i_select_tuple_arity2 and is_select_lins Rewrite select_val_bins so that its labels can be packed Pack sequences of trailing 'f' operands Implement packing of 'f' and 'j' Make sure that mask literals are 64 bits Use relative failure labels Add information about offset to common group start position Remove JUMP_OFFSET Refactor instructions to support relative jumps Introduce a new trace_jump/1 instruction for tracing Avoid using $Src more than once
2017-09-14Use relative failure labelsBjörn Gustavsson
Relative failure in itself is not an optimization, but we plan to pack failure labels in the future to save memory.
2017-09-14Remove JUMP_OFFSETBjörn Gustavsson
It has served its purpose.
2017-09-13Refactor instructions to support relative jumpsBjörn Gustavsson
Introduce new macros that can be used for relative jumps and use them consistently. Test that everything works by using a non-zero constant JUMP_OFFSET. The loader subtracts JUMP_OFFSET from loaded labels, and all instructions that use 'f' operands add it back.
2017-09-11Use the correct name of the parameterBjörn Gustavsson
2017-08-31Add annotations for likely/unlikelyBjörn Gustavsson
In a correct Erlang programs, we can expect that: * A GC test instruction (such as test_heap) is more likely not to do the GC. * A BIF is more likely to succeed than to fail. * A BIF is more likely to fail in a guard than in a body. * An apply or fun call is likely to succeed. Annotate conditions accordingly.
2017-08-15Slightly optimize updating of mapsBjörn Gustavsson
The instruction put_map_assoc/5 (used for updating a map) has a failure operand, but it can't actually fail provided that its "map" argument is a map. The following code: M#{key=>value}. will be compiled to: {test,is_map,{f,3},[{x,0}]}. {line,[...]}. {put_map_assoc,{f,0},{x,0},{x,0},1,{list,[{atom,key},{atom,value}]}}. return. {label,3}. %% Code that produces a 'badmap' exception follows. Because of the is_map instruction, {x,0} always contains a map when the put_map_assoc instruction is executed. Therefore we can remove the failure operand. That will save one word, and also eliminate two tests at run-time. The only problem is that the compiler in OTP 17 did not emit a is_map instruction before the put_map_assoc instruction. Therefore, we must add an instruction that tests for a map if the code was compiled with the OTP 17 compiler. Unfortunately, there is no safe and relatively easy way to known that the OTP 17 compiler was used, so we will check whether a compiler before OTP 20 was used. OTP 20 introduced a new chunk type for atoms, which is trivial to check.
2017-08-11Break out most instructions from beam_emu.cBjörn Gustavsson