Closed
Bug 661330
Opened 13 years ago
Closed 13 years ago
Array.length behavior doesn't follow ECMA262 near 2^32-1
Categories
(Tamarin Graveyard :: Virtual Machine, defect, P3)
Tamarin Graveyard
Virtual Machine
Tracking
(Not tracked)
RESOLVED
FIXED
Q1 12 - Brannan
People
(Reporter: stejohns, Assigned: pnkfelix)
References
Details
(Whiteboard: has-patch)
Attachments
(2 files, 2 obsolete files)
(deleted),
patch
|
dschaffe
:
review+
|
Details | Diff | Splinter Review |
(deleted),
patch
|
lhansen
:
review+
edwsmith
:
superreview+
|
Details | Diff | Splinter Review |
(See Bug 658677 for history)
ECMA262 requires that using index=2^32-1 not affect Array.length; different code paths in our Array handle this differently (most code paths wrap to zero, but some leave it unaffected). Furthermore, the behavior differs subtly between interp/jit modes, and 32/64 bit builds.
Also, ECMA262 specifies that RangeError be thrown in other situations (eg calling push() on an Array with length=2^32-1), which we have never done.
IMHO, existing behavior should be preserved as closely as possible (though we may have to exterminate interp/jit, 32/64 differences), but a fully-conforming Array implementation should be added as a future versioned fix.
Comment 1•13 years ago
|
||
Also note that the behavior is different depending on whether or not it is compiled with the -AS3 asc.jar swtich.
Updated•13 years ago
|
Flags: flashplayer-qrb?
Updated•13 years ago
|
Assignee: nobody → wmaddox
Status: NEW → ASSIGNED
Flags: flashplayer-triage+
Flags: flashplayer-qrb?
Flags: flashplayer-qrb+
Flags: flashplayer-injection-
Flags: flashplayer-bug+
Target Milestone: --- → Q1 12 - Brannan
Assignee | ||
Updated•13 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → DUPLICATE
Assignee | ||
Comment 3•13 years ago
|
||
More careful reading of this bug's description implies that Bug 677923 does not subsume it.
Bug 677923 was largely dedicated to identifying the different axes on which inconsistencies could arise. This bug (Bug 661330) says it is dedicated to implementing a versioned, ECMA262-conforming Array implementation.
They certainly seem related though; I'll mark Bug 677923 as blocking 661330.
Status: RESOLVED → REOPENED
Resolution: DUPLICATE → ---
Assignee | ||
Updated•13 years ago
|
Assignee: wmaddox → fklockii
Assignee | ||
Comment 4•13 years ago
|
||
I got sucked into fixing this in order to address Bug 681399, comment 27 in a semi-disciplined manner.
Attachment #556063 -
Flags: superreview?(lhansen)
Attachment #556063 -
Flags: review?(wmaddox)
Comment 5•13 years ago
|
||
Comment on attachment 556063 [details] [diff] [review]
patch A v1: guard assignment to Array length, non-AS3 mode
Seems reasonable enough.
Attachment #556063 -
Flags: superreview?(lhansen) → superreview+
Assignee | ||
Comment 6•13 years ago
|
||
(In reply to Lars T Hansen from comment #5)
> Comment on attachment 556063 [details] [diff] [review]
> patch A v1: guard assignment to Array length, non-AS3 mode
>
> Seems reasonable enough.
Now that you've brought up subclassing Arrays (in Bugzilla 681399, comment 32, and Bugzilla 681803, comment 5), I am worried about changing the type signature of the length setter in Array.as...
Notably here:
// E262 {DontEnum, DontDelete}
public native function get length():uint
- public native function set length(newLength:uint)
+ private native function set_uint_length(newLength:uint):void
+ public function set length(newLength:*) {
...
Its necessary to expand the domain of 'set length' if we're going to throw a RangeError on a non-uint, but I don't yet know how that interacts with subclasses that were previously overriding 'set length'
Will investigate.
Comment 7•13 years ago
|
||
(In reply to Felix S Klock II from comment #6)
> Now that you've brought up subclassing Arrays (in Bugzilla 681399, comment
> 32, and Bugzilla 681803, comment 5), I am worried about changing the type
> signature of the length setter in Array.as...
Gosh, I completely missed that. An overriding subclass that uses 'uint' in the signature will fail to compile in strict mode, and will probably fail to verify if compiled in standard mode.
Assignee | ||
Comment 8•13 years ago
|
||
(In reply to Lars T Hansen from comment #7)
> Gosh, I completely missed that. An overriding subclass that uses 'uint' in
> the signature will fail to compile in strict mode, and will probably fail to
> verify if compiled in standard mode.
That means we can't land this, unless we can version it (and even then we might not be able to land it), right?
If we are restricted to uint for the length setter, then I don't know what is best for the generic Array operations to do. I don't want to write a value that is going to be silently wrapped mod 2^32. I guess I could bubble up the throwing of RangeError to all the sites that would write to .length when (this is Array)...
Comment 9•13 years ago
|
||
(In reply to Felix S Klock II from comment #8)
> (In reply to Lars T Hansen from comment #7)
> > Gosh, I completely missed that. An overriding subclass that uses 'uint' in
> > the signature will fail to compile in strict mode, and will probably fail to
> > verify if compiled in standard mode.
>
> That means we can't land this, unless we can version it (and even then we
> might not be able to land it), right?
The current versioning system does not allow for variant interfaces; it only allows us to add new classes and add methods to existing classes (to the best of my knowledge). Thus non-final signatures, once introduced, pretty much have to stay that way forever.
I think that a versioning system that allows variant definitions of types and methods will eventually be necessary.
> If we are restricted to uint for the length setter, then I don't know what
> is best for the generic Array operations to do. I don't want to write a
> value that is going to be silently wrapped mod 2^32. I guess I could bubble
> up the throwing of RangeError to all the sites that would write to .length
> when (this is Array)...
Yeah. Sucks to be us. The simpler alternative might be to have a private length-setter method that does not take uint, and have all the builtin methods call that, ie, the opposite of what you just tried. After all a setter is just a method, nothing magic about it; the value to be set can be set by other means too. (Even if it's simpler it's annoyingly complex and brittle.)
Assignee | ||
Comment 10•13 years ago
|
||
(In reply to Lars T Hansen from comment #7)
> An overriding subclass that uses 'uint' in
> the signature will fail to compile in strict mode, and will probably fail to
> verify if compiled in standard mode.
From my attempts to check this statement, it looks to me like:
- As expected, you get "Incompatible override" failures at compile-time in strict mode,
- You also get the same failures at compile-time when in non-strict mode,
- If you attempt to run an .abc compiled with the previous builtins, *then* you get a verification failure at run-time.
(In reply to Lars T Hansen from comment #9)
> (In reply to Felix S Klock II from comment #8)
> > (In reply to Lars T Hansen from comment #7)
> > > Gosh, I completely missed that. An overriding subclass that uses 'uint' in
> > > the signature will fail to compile in strict mode, and will probably fail to
> > > verify if compiled in standard mode.
> >
> > That means we can't land this, unless we can version it (and even then we
> > might not be able to land it), right?
>
> The current versioning system does not allow for variant interfaces; it only
> allows us to add new classes and add methods to existing classes (to the
> best of my knowledge). Thus non-final signatures, once introduced, pretty
> much have to stay that way forever.
>
> I think that a versioning system that allows variant definitions of types
> and methods will eventually be necessary.
Okay, I won't bother trying to see if I introduce a verision variant interface here then.
> > If we are restricted to uint for the length setter, then I don't know what
> > is best for the generic Array operations to do. I don't want to write a
> > value that is going to be silently wrapped mod 2^32. I guess I could bubble
> > up the throwing of RangeError to all the sites that would write to .length
> > when (this is Array)...
>
> Yeah. Sucks to be us. The simpler alternative might be to have a private
> length-setter method that does not take uint, and have all the builtin
> methods call that, ie, the opposite of what you just tried. After all a
> setter is just a method, nothing magic about it; the value to be set can be
> set by other means too. (Even if it's simpler it's annoyingly complex and
> brittle.)
Okay. The calls would still need to be special-cased on (this is Array), but that sounds preferable to putting the uint-or-RangeError checks on all the call sites.
Assignee | ||
Comment 11•13 years ago
|
||
Comment on attachment 556063 [details] [diff] [review]
patch A v1: guard assignment to Array length, non-AS3 mode
(retracting review request; see comment 6 and comment 7 for why. I'll work on something following the outline of comment 8 and comment 9.)
Attachment #556063 -
Flags: review?(wmaddox)
Assignee | ||
Comment 12•13 years ago
|
||
Comment on attachment 556063 [details] [diff] [review]
patch A v1: guard assignment to Array length, non-AS3 mode
(removing the SR+ so that no one gets fooled into thinking that this patch is okay as is.)
Attachment #556063 -
Flags: superreview+
Assignee | ||
Updated•13 years ago
|
Assignee | ||
Comment 13•13 years ago
|
||
(Filed Bug 685220 as an obvious sub-task that comment 7 is screaming out for.)
Assignee | ||
Updated•13 years ago
|
Assignee | ||
Comment 14•13 years ago
|
||
(In reply to Felix S Klock II from comment #10)
> (In reply to Lars T Hansen from comment #7)
[...]
> > > If we are restricted to uint for the length setter, then I don't know what
> > > is best for the generic Array operations to do. I don't want to write a
> > > value that is going to be silently wrapped mod 2^32. I guess I could bubble
> > > up the throwing of RangeError to all the sites that would write to .length
> > > when (this is Array)...
> >
> > Yeah. Sucks to be us. The simpler alternative might be to have a private
> > length-setter method that does not take uint, and have all the builtin
> > methods call that, ie, the opposite of what you just tried. After all a
> > setter is just a method, nothing magic about it; the value to be set can be
> > set by other means too. (Even if it's simpler it's annoyingly complex and
> > brittle.)
>
> Okay. The calls would still need to be special-cased on (this is Array),
> but that sounds preferable to putting the uint-or-RangeError checks on all
> the call sites.
The call sites in question are also the subject of Bug 681803 (for push) and Bug 685323 (for unshift); arguably all of these problems should just get fixed in one swoop through the code.
Assignee | ||
Comment 15•13 years ago
|
||
After thinking further about this bug, I think there are some semi-clean approaches we can use to get ES5 semantics. but before I put them in, I wanted to make sure that I had a reasonable test suite to cover the different pathological cases where wrap-around can occur.
(Some cases are explicitly skipped because they consume so much time/memory that they are unlikely to occur in practice. See comments in the code.)
Assignee | ||
Comment 16•13 years ago
|
||
(In reply to Felix S Klock II from comment #15)
> After thinking further about this bug, I think there are some semi-clean
> approaches we can use to get ES5 semantics
The thinking I was employing above was flawed. I had thought that I might be able to catch the coercion from Atom to uint within AVM, and throw the RangeError from there (in a version-checked manner). (I was willing to accept that I would only be able to perform such interception for a subset of the array length assignment forms, e.g. forms like ``arr["length"] = newlen'' or similar.)
But this thinking, as I said, was flawed. The place where the coercion from an Atom to a uint happens is in the nativegen.py generated code for avmplus::NativeID::Array_length_set_thunk. I don't want to mess with nativegen.py.
So I'm going back to decorating the call-sites, as described in comment 8 and comment 9 and comment 10.
Assignee | ||
Comment 17•13 years ago
|
||
(realized while working on the patch that I should cover subclasses of Array too.)
Attachment #559241 -
Attachment is obsolete: true
Assignee | ||
Updated•13 years ago
|
Attachment #559294 -
Attachment is patch: true
Assignee | ||
Comment 18•13 years ago
|
||
(In reply to Felix S Klock II from comment #10)
> (In reply to Lars T Hansen from comment #7)
> > Yeah. Sucks to be us. The simpler alternative might be to have a private
> > length-setter method that does not take uint, and have all the builtin
> > methods call that, ie, the opposite of what you just tried. After all a
> > setter is just a method, nothing magic about it; the value to be set can be
> > set by other means too. (Even if it's simpler it's annoyingly complex and
> > brittle.)
>
> Okay. The calls would still need to be special-cased on (this is Array),
> but that sounds preferable to putting the uint-or-RangeError checks on all
> the call sites.
Another note: This would only "fix" Array (by special-casing on it). It would not fix cases where the method is being generically applied to instances of classes that define their own var length:uint or likewise uint-typed length setter.
(Examples of such classes include Vector and ByteArray.)
I'm willing to live with that.
Besides, there's really not any way to deal with it, apart from either:
1. changing the semantics of the implicit coercion that occurs when you assign a non-uint to a uint-typed location, or
2. extending the ActionScript language with some way for a program to introspectively detect the type of a location, so that it could avoid the implicit coercion. (Maybe this is already doable, in an expensive fashion, via describeType.)
I'm assuming that (1.) is a non-starter and (2.) would have to wait until there was actual customer demand for such a capability.
Assignee | ||
Comment 19•13 years ago
|
||
The private set_length function added here can only be used for Arrays; so callers from generic routines like Array.prototype.public::push need to first check that the receiver is an Array before invoking private::set_length on it.
The behavior is versioned checked and its up to the caller to provide an appropriate value for when the newLength is not a uint. (This seemed like the cleanest way to go, rather than assuming that all failing calls would be cases where uint.MAX_VALUE is the correct fallback.)
This patch does not introduce any invocations of set_length. Such invocations will be forthcoming on Bug 681803 (its going to be uploaded next), and presumably on Bug 685323 (though I don't have that patch prepared yet).
Attachment #556063 -
Attachment is obsolete: true
Assignee | ||
Comment 20•13 years ago
|
||
Comment on attachment 559447 [details] [diff] [review]
patch A v2: add private set_length with versioned exception
(Ed: feel free to reassign yourself as SR? and put someone else as R?.)
((also, this patch may not make sense without also reviewing Bug 681803's attachment 559450 [details] [diff] [review] in parallel))
Attachment #559447 -
Flags: review?(edwsmith)
Assignee | ||
Updated•13 years ago
|
Attachment #559294 -
Flags: review?(dschaffe)
Assignee | ||
Updated•13 years ago
|
Attachment #559447 -
Flags: review?(edwsmith) → review?(lhansen)
Assignee | ||
Updated•13 years ago
|
Attachment #559447 -
Flags: superreview?(edwsmith)
Assignee | ||
Updated•13 years ago
|
Whiteboard: has-patch
Updated•13 years ago
|
Attachment #559447 -
Flags: review?(lhansen) → review+
Comment 22•13 years ago
|
||
I'll keep the SR open but go ahead and land when you're ready.
Assignee | ||
Comment 23•13 years ago
|
||
(running buildbot now)
Assignee | ||
Comment 24•13 years ago
|
||
Comment on attachment 559294 [details] [diff] [review]
test L v2: acceptance test for length wraparound
(gentle review ping)
Comment 25•13 years ago
|
||
changeset: 6603:7087fdc0c36b
user: Felix S Klock II <fklockii@adobe.com>
summary: Bug 661330: add private set_length method with versioned exception (r=lhansen, sr pending=edwsmith).
http://hg.mozilla.org/tamarin-redux/rev/7087fdc0c36b
Assignee | ||
Updated•13 years ago
|
Blocks: ecma-incompatibility
Updated•13 years ago
|
Attachment #559294 -
Flags: review?(dschaffe) → review+
Comment 26•13 years ago
|
||
changeset: 6709:ac91969bcc46
user: Felix S Klock II <fklockii@adobe.com>
summary: Bug 661330: acceptance tests for modifying Array .length property (r=dschaffe).
http://hg.mozilla.org/tamarin-redux/rev/ac91969bcc46
Comment 27•13 years ago
|
||
length_mods.as fails with 64-bit Release builds and -Dinterp, but apparently other configurations and jit-modes work.
Assignee | ||
Comment 28•13 years ago
|
||
oops, will revert. (didn't see notification in email; is buildbot just laggy at the moment?)
Comment 29•13 years ago
|
||
changeset: 6710:0bd4094457a5
user: Felix S Klock II <fklockii@adobe.com>
summary: Bug 661330: Backed out changeset ac91969bcc46
http://hg.mozilla.org/tamarin-redux/rev/0bd4094457a5
Assignee | ||
Comment 30•13 years ago
|
||
(In reply to Edwin Smith from comment #27)
> length_mods.as fails with 64-bit Release builds and -Dinterp, but apparently
> other configurations and jit-modes work.
This appears to be due to Bug 700613 (which may itself bifurcate into separate bugs).
I am guessing I should either not land the acceptance tests until that is fixed, or disable this paticular part of the tests but still land the tests, so that this bug need not be blocked by Bug 700613.
Comment 31•13 years ago
|
||
changeset: 6714:27339d0b1836
user: Felix S Klock II <fklockii@adobe.com>
summary: Bug 661330: acceptance tests for Array .length property, land attempt II (r=dschaffe).
http://hg.mozilla.org/tamarin-redux/rev/27339d0b1836
Assignee | ||
Updated•13 years ago
|
Status: REOPENED → RESOLVED
Closed: 13 years ago → 13 years ago
Resolution: --- → FIXED
Updated•13 years ago
|
Attachment #559447 -
Flags: superreview?(edwsmith) → superreview+
You need to log in
before you can comment on or make changes to this bug.
Description
•