diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2011-09-29 15:05:20 +0200 |
---|---|---|
committer | Björn Gustavsson <bjorn@erlang.org> | 2011-11-07 14:00:26 +0100 |
commit | a772f06a2de3b83e8b21072eeae837e05f7b46e7 (patch) | |
tree | 65723e3695d7d1e35e2602e2d6f5ed52ca5c6210 | |
parent | af5edfe20b24116fa892a37a746f4053fde6039b (diff) | |
download | otp-a772f06a2de3b83e8b21072eeae837e05f7b46e7.tar.gz otp-a772f06a2de3b83e8b21072eeae837e05f7b46e7.tar.bz2 otp-a772f06a2de3b83e8b21072eeae837e05f7b46e7.zip |
beam_asm: Fix broken NewIndex in fun entries
The calculation of the NewIndex field in fun entries is broken: the
sys_pre_expand and v3_kernel modules keep separate index counters
starting at zero; thus there is no guarantee that each fun within a
module will have its own unique NewIndex.
We don't really need the NewIndex any more (see below), but since
we do need the NewUniq field, we should fix NewIndex for cleanliness
sake. The simplest way is to assign NewIndex as late as possible,
namely in beam_asm, and to set it to the same value as Index.
Historical Note: Why NewIndex Was Introduced
There was once an idea that the debugger should be able to interpret
only a single function in a module (for speed). To make sure that
interpreted funs could be called from BEAM code and vice versa,
the fun identification must be visible in the abstract code.
Therefore a NewIndex field was introduced in each fun in the abstract
code.
However, it turned out that interpreting single functions does not
play well with aggressive code optimization. For example, in this
code:
f() ->
X = 1,
fun() -> X+2 end.
the variable X will seem to be free in the fun, but an aggressive
optimizer will replace X with 1 in the fun; thus the fun will no
longer have any free variables. Therefore, the debugger will always
interpret entire modules.
-rw-r--r-- | lib/compiler/src/beam_asm.erl | 4 | ||||
-rw-r--r-- | lib/compiler/src/beam_dict.erl | 10 |
2 files changed, 8 insertions, 6 deletions
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl index 9b46abe697..4a9c12dfea 100644 --- a/lib/compiler/src/beam_asm.erl +++ b/lib/compiler/src/beam_asm.erl @@ -328,8 +328,8 @@ make_op({test,Cond,Fail,Ops}, Dict) when is_list(Ops) -> encode_op(Cond, [Fail|Ops], Dict); make_op({test,Cond,Fail,Live,[Op|Ops],Dst}, Dict) when is_list(Ops) -> encode_op(Cond, [Fail,Op,Live|Ops++[Dst]], Dict); -make_op({make_fun2,{f,Lbl},Index,_OldUniq,NumFree}, Dict0) -> - {Fun,Dict} = beam_dict:lambda(Lbl, Index, NumFree, Dict0), +make_op({make_fun2,{f,Lbl},_Index,_OldUniq,NumFree}, Dict0) -> + {Fun,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0), make_op({make_fun2,Fun}, Dict); make_op({kill,Y}, Dict) -> make_op({init,Y}, Dict); diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index f82a8f2e3e..531968b3c8 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -22,7 +22,7 @@ -export([new/0,opcode/2,highest_opcode/1, atom/2,local/4,export/4,import/4, - string/2,lambda/4,literal/2,line/2,fname/2, + string/2,lambda/3,literal/2,line/2,fname/2, atom_table/1,local_table/1,export_table/1,import_table/1, string_table/1,lambda_table/1,literal_table/1, line_table/1]). @@ -134,12 +134,14 @@ string(Str, Dict) when is_list(Str) -> end. %% Returns the index for a fun entry. -%% lambda(Lbl, Index, NumFree, Dict) -> {Index,Dict'} --spec lambda(label(), non_neg_integer(), non_neg_integer(), bdict()) -> +%% lambda(Lbl, NumFree, Dict) -> {Index,Dict'} +-spec lambda(label(), non_neg_integer(), bdict()) -> {non_neg_integer(), bdict()}. -lambda(Lbl, Index, NumFree, #asm{lambdas=Lambdas0}=Dict) -> +lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) -> OldIndex = length(Lambdas0), + %% Set Index the same as OldIndex. + Index = OldIndex, %% Initialize OldUniq to 0. It will be set to an unique value %% based on the MD5 checksum of the BEAM code for the module. OldUniq = 0, |