Closed Bug 600067 Opened 14 years ago Closed 14 years ago

fun->u.i.names is incorrect when a local function shadows an argument

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
blocking2.0 --- beta7+

People

(Reporter: dvander, Assigned: brendan)

References

Details

(4 keywords, Whiteboard: [same as bug 597408] fixed-in-tracemonkey)

Attachments

(1 file, 1 obsolete file)

Reduced from test case in bug 597408

// vim: set ts=4 sw=4 tw=99 et:
X = function (a) {
   function b() {
      print(a);
   }
   function a() {
   }
   print(a);
}

Assertion failure: localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST, at ../jsemit.cpp:4541
blocking2.0: --- → ?
Err, sorry, actual test case is:

YCore[JY5] = function (a) {
  var W = _R,
      Z = YCore.Threads,
      V = U[AE7],
      Q = U[NV5];

  function a() {
  }
};

The problem is we duplicate "a" in the property tree. If there are <=5 local variables, it works, because the linear search along the ancestor line hits the local variable "a" first.

If in dictionary mode, it hits the argument "a" first.
Summary: Test case asserts in jsemit.cpp → fun->u.i.names is incorrect when a variable aliases an argument
b7+ to fix Yahoo Mail!
blocking2.0: ? → beta7+
(In reply to comment #1)
> The problem is we duplicate "a" in the property tree. If there are <=5 local
> variables, it works, because the linear search along the ancestor line hits the
> local variable "a" first.

This was very frustrating at first since I couldn't tell exactly what was triggering the error (it wouldn't happen if I removed random functions).

The interesting thing though is, if I'd replace those letter-number combinations (which are really just shorthands for strings), the error would say: "void(0) is undefined" which was really comical if you ask me :)
Assignee: general → jwalden+bmo
Whiteboard: [same as bug 597408]
A little more copy-pastable:

[jwalden@find-waldo-now tests]$ echo '
function s(a)
{
  var b, c, d, e;
  function a() { }
}' | ../dbg/js -j
Assertion failure: localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST, at ../jsemit.cpp:4541
Aborted (core dumped)
Status: NEW → ASSIGNED
OS: Linux → All
Hardware: x86_64 → All
The first bad revision is:
changeset:   3dc4daa9621b
user:        Brendan Eich
date:        Mon Sep 13 18:44:34 2010 -0700
summary:     JSFunction::addLocal never calls Shape::maybeHash (bug 595918, r=jorendorff).
jsfunfuzz can now hit this bug. It was missing the ability to create a large number of local variables, and it tended not to create functions declaration statements with aliasing/shadowing names.
Attached patch minimal fix (obsolete) — Splinter Review
Assignee: jwalden+bmo → brendan
Attachment #479546 - Flags: review?(jorendorff)
How many places is js::PropertyTable used to store multiple shapes with the same id?  It seems very non-obvious to me that it would ever contain more than a single shape for an id.  Should some other structure more supportive of duplicate entries be used instead?
(In reply to comment #8)
> How many places is js::PropertyTable used to store multiple shapes with the
> same id?

No places, with this bug fixed.

/be
Summary: fun->u.i.names is incorrect when a variable aliases an argument → fun->u.i.names is incorrect when a local function shadows an argument
Attachment #479546 - Attachment is obsolete: true
Attachment #479607 - Flags: review?(jorendorff)
Attachment #479546 - Flags: review?(jorendorff)
Mega-nit: making the argument not start off the alphabet makes it easier to see just how many local variables are necessary to trigger the behavior (so I found when I was typing it out locally doing my own investigation):

function s(e)
{
  var a, b, c, d;
  function e() { }
}

Might be worth making that tweak to the test before pushing, really doesn't matter if it doesn't happen tho.
Comment on attachment 479607 [details] [diff] [review]
with test (plane landed)

r=me for the minimal fix.

It seems like it would be better for the compiler not to create property lineages with duplicate ids. I imagine that would be more involved.
Attachment #479607 - Flags: review?(jorendorff) → review+
(In reply to comment #12)
> Comment on attachment 479607 [details] [diff] [review]
> with test (plane landed)
> 
> r=me for the minimal fix.
> 
> It seems like it would be better for the compiler not to create property
> lineages with duplicate ids. I imagine that would be more involved.

Something has to, as in non-strict ES, duplicate parameters are allowed and they need to be decompiled as such, even though the last one wins so one could avoid allocating slots and shapes for all but the last.

In the pre-Shape code there was a fair amount of specialized code just to keep track of duplicates in a JSLocalNameMap. With shapes this simplifies to linking dups in reverse source order from fun->u.i.names (skipping upvars and vars to get to args) up to the first parameter.

Similarly for function binding trumping formal parameter, we could remove the param and append the duplicate-id  function as local var shape, but that is more code statically and more cycles than just allowing the duplication but keeping the last-one-wins rule when hashing.

/be
http://hg.mozilla.org/tracemonkey/rev/cdac8d48fcca

/be
Whiteboard: [same as bug 597408] → [same as bug 597408] fixed-in-tracemonkey
(In reply to comment #13)
> > It seems like it would be better for the compiler not to create property
> > lineages with duplicate ids. [...]
> 
> Something has to, as in non-strict ES, duplicate parameters are allowed and
> they need to be decompiled as such[...].

This is true.

decompiler_TCO++;
http://hg.mozilla.org/mozilla-central/rev/cdac8d48fcca
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
A testcase for this bug was automatically identified at js/src/tests/js1_8_5/regress/regress-600067.js.
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: