Closed Bug 287644 Opened 20 years ago Closed 20 years ago

js_GetScriptLineExtent results wrong

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED INVALID

People

(Reporter: brendan, Assigned: brendan)

References

()

Details

(Keywords: js1.5)

See the URL.  Patch soon.

/be
Hmm. I looked at this quickly and convinced myself that it is probably doing
what it had always done. JS_GetScriptLineExtent returns the extent of the body
of the script for which the compiler has generated actual bytecodes. So, the
line before the opening '{' has never been included in the definition of the
function body extent. I believe the compiler has generated prolog code
associated with the line of the opening '{' since about the time I wrote that
code. I remember adjusting my use of this code not long after it was written,
and before Nav4 was released, to deal with the effects of the prolog code. The
closing '}' is on a line with no code at all and (I pretty darn sure) has never
been included in the extent.

I think the OP probably made the mistake passing in '0' as the start line for
the compilation (given that the top level script seems to have a start line of
0). If he fixed that, I think he'd see that each of the function bodies are
shown as starting on the line with the opening '{'.

As for the question of the extent of the top level script... I expect that the
last generated bytecode of the top level script happens to be at the line where
the last function starts. If there is no code generated for the top level script
(as opposed to the body of the final function) beyond that point then that is
where the top level script is seen to end (regardless of how long that final
function is). Of course, the fact that the final function is not called is
immaterial.

Anyway, although I'm not actually certain, I doubt that there is a bug here at
all or that the source notes this stuff is based on has changed over the years.
It may be that changing this would break existing debuggers that rely on the
current behavior. Or not :) 
jband reminded me (thanks!) that this function has always (since it was written
by jband, and modulo source note bugs long since fixed) returned the number of
lines starting from the first line of the script (which was specified when the
script was compiled, by the API user) up to and including the last line for
which bytecode was generated.

So in the example from the newsgroup:

     1  function fact(n)        /* line 1 */
     2  {
     3    if (n <= 1)
     4      return 1;
     5    return n * fact(n-1)
     6  }
     7  fact(5);                /* line 7 */
     8  WONKA(4);
     9  function WONKA(n)              /* line 9 */
    10  {
    11    if (n <= 1)
    12      return 1;
    13    return n * fact(n-1)
    14  }
    15  function WILLY(n)              /* line 15 */
    16  {
    17    if (n <= 1)
    18      return 1;
    19    return n * fact(n-1)\n
    20  }                              /* line 20 */

The top-level script has a JSOP_NOP no-operation opcode (for decompilation and
debugger purposes only -- hereafter I'll use lowercase and drop the JSOP_ prefix
for opcode names) for each opening brace of a function declared in that script.

It seems the reporter may have compiled the script in the example with a first
line number of 0, not 1.  That's just API user error, and never a good idea, but
as jband noted the API must allow the caller to specify the first line, for
embeddings such as a web browser where <script> tags may start after line 1 and
occur several times in a document.

Here is the bytecode, with source notes, for the above script:

00000:  deffun function fact(n) {if (n <= 1) {return 1;}return n * fact(n -
1);}00003:  deffun function WONKA(n) {if (n <= 1) {return 1;}return n * fact(n -
1);}
00006:  deffun function WILLY(n) {if (n <= 1) {return 1;}return n * fact(n - 1);}
main:
00009:  nop
00010:  name "fact"
00013:  pushobj
00014:  uint16 5
00017:  call 1
00020:  popv
00021:  name "WONKA"
00024:  pushobj
00025:  uint16 4
00028:  call 1
00031:  popv
00032:  nop
00033:  nop

Source notes:
  0:     2 [   2] xdelta
  1:     9 [   7] newline
  2:     9 [   0] funcdef  atom 0 (function fact(n) {if (n <= 1) {return
1;}return n * fact(n - 1);})
  4:    10 [   1] setline  lineno 7
  6:    17 [   7] pcbase   offset 7
  8:    21 [   4] newline
  9:    28 [   7] pcbase   offset 7
 11:    32 [   4] setline  lineno 10
 13:    32 [   0] funcdef  atom 3 (function WONKA(n) {if (n <= 1) {return
1;}return n * fact(n - 1);})
 15:    33 [   1] setline  lineno 16
 17:    33 [   0] funcdef  atom 4 (function WILLY(n) {if (n <= 1) {return
1;}return n * fact(n - 1);})

The first bytecode not in the script's prolog is a nop at offset 9.  According
to the source notes, that is at line 2 (the newline note applies to the bytecode
at offset 9, so it advances the line count by 1).  You can keep count as you
read the source notes, but notice that the setline note at source note byte 15,
applying to bytecode 33, coerces the line number to 16.

So the extent is the length of [1, 16] or (16 - 1 + 1) or 16.

The functions have their own scripts, which unlike the top-level script start at
the opening brace's line and continue through the last line for which bytecode
was generated.

This bug is invalid, but thanks to the reporter on the newsgroup for prodding. 
We could use some docs about this, perhaps most easily generated via the wiki
(http://wiki.mozilla.org).  I'll do something.

/be
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.