Closed Bug 724790 Opened 13 years ago Closed 13 years ago

can we avoid this hasOverriddenArgs funny business?

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla13

People

(Reporter: luke, Assigned: luke)

References

Details

Attachments

(1 file, 2 obsolete files)

If I understand correctly, 'arguments' can only be overwritten by a direct assignment in a function or a direct eval in a function. In particular, 'f.arguments = 3' does not overwrite arguments. In that case, it seems like we should just stop emitting jsop_arguments (emitting name ops instead) and avoid the need to test for overwritten arguments.
Attached patch rm overwritten args (obsolete) — Splinter Review
We already track when we overwrite 'arguments' in a formal so it is easy enough to add the symmetric case for overwritten locals. The patch as is, I think, a strict simplification of the current code, but not much. However, this pays off with my later patch to make arguments (mostly) eager in a way that ultimately allows GetCallArguments/SetCallArguments/call_resolve to be replaced by a simple data property.
Assignee: general → luke
Status: NEW → ASSIGNED
Attachment #595232 - Flags: review?(jwalden+bmo)
Comment on attachment 595232 [details] [diff] [review] rm overwritten args Review of attachment 595232 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/frontend/BytecodeEmitter.h @@ +167,5 @@ > #define TCF_RETURN_VOID 0x08 /* function has 'return;' */ > #define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */ > #define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */ > #define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */ > +#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function has local named arguments */ TCF_FUN_ARGUMENTS_LOCAL reads better to me, as in "has an arguments local". The other ordering suggests the arguments are local, which is true -- but vacuously so. Although this doesn't strike me as the best possible name either... @@ -183,2 @@ > from global script */ > -/* bit 0x8000 is unused */ Sigh, I hate keeping long lists of bit names in order. @@ +271,5 @@ > */ > #define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \ > TCF_FUN_USES_ARGUMENTS | \ > TCF_FUN_PARAM_ARGUMENTS | \ > + TCF_FUN_LOCAL_ARGUMENTS | \ Should this really be the case? I wouldn't think so, given every function has its own unique |arguments|. @@ +437,5 @@ > + bool mayOverwriteArguments() const { > + JS_ASSERT(inFunction()); > + return !inStrictMode() && > + (callsEval() || > + flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS)); We might as well assert that if inStrictMode() those flags aren't present. ::: js/src/frontend/Parser.cpp @@ +4422,5 @@ > > if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) { > tc->noteArgumentsNameUse(pn2); > if (!blockObj) > + tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); So we're going to (already do?) deoptimize functions with a let-variable named |arguments|? Fine by me. ::: js/src/jsfun.cpp @@ +672,1 @@ > callobj.initArguments(ObjectValue(fp->argsObj())); Looks like initArguments should take ArgumentsObject&... @@ +759,5 @@ > { > CallObject &callobj = obj->asCall(); > > StackFrame *fp = callobj.maybeStackFrame(); > + if (fp && callobj.arguments().isUndefined()) { SetCallArguments will cheerfully set arguments() to |undefined|, so I don't think this works. [jwalden@wheres-wally src]$ dbg/js js> function f() { var arguments; arguments = undefined; return arguments; } f(1, 2, 3) ({0:1, 1:2, 2:3}) Which just might blow this idea out of the water, actually. But you're the one proposing a simplification, and I'm the one poking holes in it, so maybe you see a clever trick to keep things working. ::: js/src/methodjit/StubCalls.cpp @@ +1368,2 @@ > f.regs.sp++; > + JSObject *arguments = js_GetArgsObject(f.cx, f.fp()); As a reader nicety, it seems better if the variable type here is the narrowest thing possible, i.e. ArgumentsObject*. ::: js/src/vm/ScopeObject.h @@ +132,5 @@ > inline JSFunction *getCalleeFunction() const; > inline void setCallee(JSObject *callee); > > /* Returns the callee's arguments object. */ > + inline const js::Value &arguments() const; This comment's a lie (now?) -- the value returned is whatever the value of |arguments| is inside the function. /* Returns the value of the |arguments| binding for this CallObject. */ Maybe? The way this returns undefined before initing/setting is also a bit weird, and in need of elucidation. But see below. @@ +137,2 @@ > inline void setArguments(const js::Value &v); > inline void initArguments(const js::Value &v); set/init and when to use them are a bit confusing, seems to me. I am going to assume your subsequent patch simplifying arguments to a data property will take care of this. ::: js/src/vm/Stack.h @@ +376,1 @@ > }; This enum needs an entry for the free bits available for future use, if you're going to touch this.
Attachment #595232 - Flags: review?(jwalden+bmo) → review-
(In reply to Jeff Walden (:Waldo) (remove +bmo to email) from comment #2) > > #define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \ > > TCF_FUN_USES_ARGUMENTS | \ > > TCF_FUN_PARAM_ARGUMENTS | \ > > + TCF_FUN_LOCAL_ARGUMENTS | \ > > Should this really be the case? I wouldn't think so, given every function > has its own unique |arguments|. Initially I left it out for the same reason but, iirc, this mask seemed to be applied when copying flags from the body of a function to the emitter for the function so I was losing the flag. > SetCallArguments will cheerfully set arguments() to |undefined|, so I don't > think this works. D'oh, I saw this, but I put the fix in a later patch (http://hg.mozilla.org/users/lwagner_mozilla.com/inbound-patches/file/a74e2b978ca9/eager-args-obj#l941) but I didn't push the fix up to this patch. Good eye; new patch when I get back.
(In reply to Jeff Walden (:Waldo) (remove +bmo to email) from comment #2) > > #define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */ > > +#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function has local named arguments */ > > TCF_FUN_ARGUMENTS_LOCAL reads better to me, as in "has an arguments local". TCF_FUN_LOCAL_ARGUMENTS is symmetric with TCF_FUN_PARAM_ARGUMENTS
Attached patch rm overwritten args v.2 (obsolete) — Splinter Review
Attachment #595232 - Attachment is obsolete: true
Attachment #599234 - Flags: review?(jwalden+bmo)
Green on try
Somehow I managed to re-upload the original patch last time...
Attachment #601050 - Flags: review?(jwalden+bmo)
Attachment #599234 - Attachment is obsolete: true
Attachment #599234 - Flags: review?(jwalden+bmo)
Comment on attachment 601050 [details] [diff] [review] rm overwritten args v.2 (v.2) Review of attachment 601050 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jit-test/tests/basic/testOverwrittenArgumentsWithUndefined.js @@ +6,5 @@ > + eval("assertEq(arguments, undefined)"); > + arguments = a; > + eval("assertEq(arguments[0], 42)"); > + eval("assertEq(arguments, a)"); > +} Tangentially: Does the test pass if you change |f()| to |f(z)| and assign 17 to |z| while |arguments === undefined|, then test for |a[0] === 17|? Add that in the test if it passes. (I'm not sure if it does.) Also add the converse, setting |a[0] = 8675309| while |arguments === undefined|, then testing for |z === 8675309|, if that passes. ::: js/src/jsinterp.cpp @@ +3014,5 @@ > if (cx->typeInferenceEnabled() && !script->strictModeCode) { > if (!script->ensureRanInference(cx)) > goto error; > if (script->createdArgs) { > + JSObject *arguments = js_GetArgsObject(cx, regs.fp()); ArgumentsObject @@ +3022,5 @@ > } else { > rval = MagicValue(JS_LAZY_ARGUMENTS); > } > } else { > + JSObject *arguments = js_GetArgsObject(cx, regs.fp()); ArgumentsObject ::: js/src/vm/Stack.h @@ +376,1 @@ > }; This still needs an entry indicating which bits are free.
Attachment #601050 - Flags: review?(jwalden+bmo) → review+
Free bits left as followup since there was no consensus on irc as to whether this was actually a good thing. https://hg.mozilla.org/integration/mozilla-inbound/rev/bd71047c9b4d
Target Milestone: --- → mozilla13
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
No longer depends on: 735936
Depends on: 737570
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: