diff options
author | Björn Gustavsson <[email protected]> | 2016-06-02 09:58:46 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-06-02 12:51:18 +0200 |
commit | 5facb518a9ee2d756564eccd92a2c11f334d6282 (patch) | |
tree | 459b4574356863255a4e27aa017c04796780fdd9 /lib/compiler/src/beam_z.erl | |
parent | aab1db16d0a732823fa9e2964c6a52b109c61742 (diff) | |
download | otp-5facb518a9ee2d756564eccd92a2c11f334d6282.tar.gz otp-5facb518a9ee2d756564eccd92a2c11f334d6282.tar.bz2 otp-5facb518a9ee2d756564eccd92a2c11f334d6282.zip |
Eliminate crash for map updates in guards
beam_validator would complain that x(1) is uninitialized
in a test_heap instruction when attempting to compile
the following code with sys_core_fold turned off:
foo(M) when not (M#{true := 0}); [M] ->
ok.
Simplified, the generated BEAM assembly code looked like
this:
test is_map BadMap x(0)
put_map_exact Fail x(0) => x(1) ...
jump BooleanStuff
BadMap:
move ok => x(1)
jump Fail
BooleanStuff:
...
move Boolean => x(2)
jump Build
Fail:
move false => x(2)
Build:
test_heap 2 3 %% x(0), x(1), x(2) must be live.
...
That is, if put_map_exact failed, control would transfer
to the label Fail without initializing x(1).
Fix that by making sure that x(1) is initilized even if
put_map_exact fails:
test is_map BadMap x(0)
put_map_exact BadLbl x(0) => x(1) ...
jump OkLbl
BadLbl:
move ok => x(1)
jump Fail
OkLbl:
jump BooleanStuff
BadMap:
move ok => x(1)
jump Fail
BooleanStuff:
...
move Boolean => x(2)
jump Build
Fail:
move false => x(2)
Build:
test_heap 2 3 %% x(0), x(1), x(2) must be live.
...
Note that this situation is rare, and that other optimization passes
(beam_dead and beam_jump in particular) will clean up this mess.
Diffstat (limited to 'lib/compiler/src/beam_z.erl')
0 files changed, 0 insertions, 0 deletions