aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-09-29 15:05:20 +0200
committerBjörn Gustavsson <[email protected]>2011-11-07 14:00:26 +0100
commita772f06a2de3b83e8b21072eeae837e05f7b46e7 (patch)
tree65723e3695d7d1e35e2602e2d6f5ed52ca5c6210 /lib/compiler
parentaf5edfe20b24116fa892a37a746f4053fde6039b (diff)
downloadotp-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.
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_asm.erl4
-rw-r--r--lib/compiler/src/beam_dict.erl10
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,