Age | Commit message (Collapse) | Author |
|
|
|
This is a temporary solution for basic type tests. We'll need to
handle more-or-less arbitrary values once we introduce union
types, as we need to be able to subtract on tuple_arity tests as
well.
Without this, nearly all "no_opt" test suites will fail to compile
after the validator is migrated to 'beam_types' as a result of
atom subtraction producing 'none' when all alternatives have been
exhausted.
|
|
We didn't gain anything by tracking literals exactly, and it
greatly complicates sharing types between passes.
|
|
|
|
There's no need to have an id as part of the type, as the value
reference (through which the type is reached) uniquely identifies
the match context.
|
|
This simplifies a later migration to a unified type format, as the
literal representation may differ between passes, so passing
container types keyed by literals will fail.
|
|
|
|
* john/misc-fixes-and-additions:
beam_validator: Fail when trying to set the type of a dead value
beam_validator: Fix bad comment formatting/wording
erts: Assert that GC should not be disabled twice
|
|
|
|
BEAM has had a `swap` instruction for several releases, but it was not
known to the compiler. The loader would translate a sequence of three
`move` instructions to the `swap` instructions, but only when it was
possible to determine that it would be safe.
By making `swap` known to the compiler, it can be applied in more
situations since it is easier for the compiler than for the loader
to ensure that the usage is safe, and the loader shenanigans can be
eliminated.
|
|
The comment is outdated; trying to update the type of a dead value
will result in a type conflict, making this code unreachable.
|
|
|
|
|
|
Don't bother infering the return types for lists function that
beam_ssa_type does not handle.
|
|
|
|
This ensures that unreachable branches are properly ignored on
repeated checks (although tuple type subtraction isn't complete
yet).
|
|
Type subtraction never resulted in the 'none' type, even when it
was obvious that it should. Once that was fixed it became apparent
that inequality checks also fell into the same subtraction trap
that the type pass warned about in a comment.
This then led to another funny problem with select_val, consider
the following code:
{bif,'>=',{f,0},[{x,0},{integer,1}],{x,0}}.
{select_val,{x,0},{f,70},{list,[{atom,false},{f,69},
{atom,true},{f,68}]}}.
The validator knows that '>=' can only return a boolean, so once it
has subtracted 'false' and 'true' it killed the state because all
all valid branches had been taken, so validation would crash once
it tried to branch off the fail label.
|
|
|
|
|
|
|
|
The current type conflict resolution works well for the example
case in the comment, but doesn't handle branched code properly,
consider the following:
{label,2}.
{test,is_tagged_tuple,{f,ignored},[{x,0},3,{atom,r}]}.
{allocate_zero,2,1}.
{move,{x,0},{y,0}}.
%% {y,0} is known to be {r, _, _} now.
{get_tuple_element,{x,0},2,{x,0}}.
{'try',{y,1},{f,3}}.
%% ... snip ...
{jump,{f,5}}.
{label,3}.
{try_case,{y,1}}.
%% {x,0} is the error class (an atom), {x,1} is the error term.
{test,is_eq_exact,{f,ignored},[{x,0},{y,0}]}.
%% ... since tuples and atoms can't meet, the type of {y,0} is
%% now {atom,[]} because the current code assumes the type
%% we're updating with.
{move,{x,1},{x,0}}.
{jump,{f,5}}.
{label,5}.
%% ... joining tuple (block 2) and atom (block 3) means 'term',
%% so the get_tuple_element instruction fails to validate
%% despite this being unrechable from block 3.
{test_heap,3,1}.
{get_tuple_element,{y,0},1,{x,1}}.
{put_tuple2,{x,0},{list,[{x,1},{x,0}]}}.
{deallocate,2}.
return.
This commit kills the state on type conflicts, making unreachable
instructions truly unreachable.
|
|
While complex_test made certain branching instructions a lot easier
to read, we're still using `branch_state` for many others which is
hard to read and makes it impossible to "abort" branches on type
conflicts.
This commit replaces nearly all uses of `branch_state` with a
general branching mechanism, improving readability and paving the
way for proper type conflict resolution.
|
|
The element type can not be extracted before the tuple type has
been updated.
|
|
|
|
|
|
We used to cheat by checking if it were possible to meet the Given
and Required types, which caught the most common problems but
potentially let tuple element conflicts pass through.
This was a compromise to let the thing "work" while we were
refactoring the validator, but we can be a lot stricter now that
its type tracking capabilities approach those of the type
optimization pass.
|
|
Building terms with fragile contents is okay because the GC is
disabled during loop_rec, and the resulting term won't be reachable
from the root set afterwards.
ERL-862
|
|
|
|
This is possible now that we track types on a per-value basis, and
no longer need to care whether the source tuple's register has been
clobbered by the time we infer the type.
|
|
|
|
This is a rather subtle but important distinction. While tracking
types on a per-register basis is fairly effective, it forces us to
track which registers alias each other, and makes it tricky to infer
types over large blocks of code as instruction arguments may have
been clobbered between definition and inference.
Tracking types on a per-value basis makes us immune to these
problems.
|
|
|
|
I have no idea how this escaped us for so long...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This commit lets the compiler know about the return
type of some of the functions in the `lists` module.
Knowing about the return will allow the compiler to emit
fewer type test instructions, and also fewer instructions
for throwing `case_clause` or `badmatch` exceptions, thus
producing slightly faster and more compact code.
This change makes the `lists` module a part of the language, but it
could be argued that it already is because several functions
(e.g. `member/2` and `keymember/3`) are implemented in as BIFs in the
runtime system. Therefore, a user cannot simply change the
`lists` module and expect everything to continue working as before.
The compiler will now know the return types for the following
functions:
all/2
any/2
keymember/3
member/2
prefix/2
suffix/2
dropwhile/2
duplicate/2
filter/2
flatten/1
map/2
mapfoldl/3
mapfoldr/3
partition/2
reverse/1
sort/1
splitwith/1
takewhile/1
unzip/1
usort/1
zip/2
zipwith/3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Neither can be used for type subtraction, so the default BIF
handler suits them just fine.
|