diff options
author | John Högberg <[email protected]> | 2019-02-08 11:35:43 +0100 |
---|---|---|
committer | John Högberg <[email protected]> | 2019-02-08 15:47:13 +0100 |
commit | 9fc7477cb5452f7ca745f03fe10fbd895e9fff6c (patch) | |
tree | f1e991f263b3c0ade3db8c1ebf7ddb1d9ae38c3d /lib/compiler/src/beam_validator.erl | |
parent | 70aba8f1b77ebb40c9ea39cbcb5f78177c5c1283 (diff) | |
download | otp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.tar.gz otp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.tar.bz2 otp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.zip |
beam_validator: Explain why verify_get_map wipes dst registers
Diffstat (limited to 'lib/compiler/src/beam_validator.erl')
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index a336cf7680..3713d2c573 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -896,12 +896,20 @@ valfun_4(_, _) -> verify_get_map(Fail, Src, List, Vst0) -> assert_not_literal(Src), %OTP 22. assert_type(map, Src, Vst0), - Vst1 = foldl(fun(D, Vsti) -> - case is_reg_defined(D,Vsti) of - true -> create_term(term, D, Vsti); + + %% get_map_elements may leave its destinations in an inconsistent state + %% when the fail label is taken. Consider the following: + %% + %% {get_map_elements,{f,7},{x,1},{list,[{atom,a},{x,1},{atom,b},{x,2}]}}. + %% + %% If 'a' exists but not 'b', {x,1} is overwritten when we jump to {f,7}. + Vst1 = foldl(fun(Dst, Vsti) -> + case is_reg_defined(Dst,Vsti) of + true -> extract_term(term, [Src], Dst, Vsti); false -> Vsti end end, Vst0, extract_map_vals(List)), + Vst2 = branch_state(Fail, Vst1), Keys = extract_map_keys(List), assert_unique_map_keys(Keys), |