[erlang-questions] How to get the line number of current executable code?

Richard A. O'Keefe <>
Mon Aug 18 02:46:15 CEST 2008


On 16 Aug 2008, at 8:35 am, Kevin Scaldeferri wrote:

> Many languages are compiled to byte code, but able to recover line
> numbers at run time.  I assume they annotate the byte codes with file
> and line information.  Note that this is more powerful than the Erlang
> macros.  For example, Perl's caller() function allows you to inspect
> the full call stack in this way.

There is a tradeoff.
When your compiler does good stuff like constant propagation,
inlining, loop unrolling, loop fusion, &c, it gets hard to make
'the line number' mean anything.  For example, suppose we had

	Ns = [sum(L) || L <- Ls],
	Ds = [length(L) || L <- Ls],
	Aves = [N/D || {N,D} <- lists:zip(Ns, Ds)]

This is the kind of thing the GHC compiler eats for lunch;
assuming Ns and Ds are not used anywhere else it turns into
the equivalent of

	Aves = [sum(L)/length(L) || L <- Ls]

Which line does this correspond to?  ALL of them.
(Actually, I believe GHC will take this a stage further, and inline
and fuse the sum and length loops as well.  In which case we have
code within a single "line" coming from several files.)

The Erlang compiler isn't that smart.  (Yet.  A man can dream.)

One of the reasons that Perl can give you line numbers is that
Perl is to speed what a spent match is to illumination.

Debugging information can be bulky.
For a non-Erlang example, I tried a small Java file.
It has 172 lines, 116 of which count as SLOC.
javac -g:none Calls.java  => 2583 bytes
javac         Calls.java  => 3035 bytes; 452 bytes of line#
javac -g      Calls.java  => 3283 bytes; 248 bytes of other stuff
The Java compiler counted 96 lines it thought worth recording,
so that's 4.71 bytes per line.  (Clearly they are not bothering
to compress this much.)  There are about 1380 bytes of actual code,
so the line number table is about 1/3 as big as the code.

Even assuming that virtual memory is huge and close to free,
line number information should be used rarely enough that you
don't want to mix it in with the instructions; you want to
segregate it somewhere else.

The really interesting thing is that javap basically lists the
line number mappings backwards.  Instead of saying "block [a..z)
of byte code corresponds to line L", it says "line L corresponds
to byte code starting at x".  This suggests a fairly, um,
direct mapping from source code to byte code: inlining,
loop fusion, loop unrolling, &c are left to the JIT.

Now the Erlang compiler isn't as smart as GHC, but it _is_
smarter than that.  With inlining and tail recursion optimisation,
even the stack trace isn't what it seems.

A rather long-winded way of saying TANSTAAFL, I suppose.




More information about the erlang-questions mailing list