Closed Bug 401561 Opened 18 years ago Closed 14 years ago

direct-call optimization (done when opt>0) can cause functions to execute in wrong scope

Categories

(Rhino Graveyard :: Compiler, defect)

defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: dgreenspan, Unassigned)

Details

User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.8) Gecko/20071010 Camino/1.5.2 Build Identifier: 1.6r7 When opt>0, Rhino performs a global "direct-call" optimization on code it generates, which changes the caller/callee contract for any functions optimized. As a result, calling these functions indirectly or from a different Script causes the function execution to use the caller's scope(!), not the callee's (lexical) scope. Reproducible: Always Steps to Reproduce: // This code runs correctly when opt<=0, fails when opt>0. // Note the *correct* behavior is to throw an exception. // The *incorrect* behavior is to print a number. // Can test with java -classpath js.jar org.mozilla.javascript.tools.shell.Main -opt 1 bugtest.js // bugtest.js: // This function should never work (no x in lexical scope) function getX() { return x; } global = this; (function() { var x = 12345; (function() { // indirect call, not direct-call-optimized, // uses this scope's parent instead of getX's parent java.lang.System.out.println(global["getX"]()); // Result: if opt <= 0, "x not found" // if opt > 0, prints "12345.0" !! })(); })(); // call site triggers direct-call optimization of getX; // remove this line and the bug doesn't manifest! function neverCalled() { getX(); } Actual Results: prints "12345.0" Expected Results: ReferenceError: "x" is not defined. I discovered this bug because my application uses a shared global scope with multiple "sub-scopes" (http://www.mozilla.org/rhino/scopes.html : "Sharing Scopes"), and some functions are copied from a sub-scope to the global scope. I realized I had a Rhino bug when some really weird stuff happened when class-file optimization was turned on, *but* only in the presence of a particular never-called function declaration. I doubted for a while that the bug could be reproduced in a js file without special scope stuff, but then I found another way to fool the direct-call optimizer. I'm guessing that direct-call optimization is triggered when a function is declared but the function object doesn't "flow" anywhere (and the function is called somewhere else in the script). I honestly don't know exactly what the optimization does, but it seems to remove the call to "getParentScope" at the beginning of the optimized function, putting the burden of determining the scope on the caller. If any call-site doesn't get the memo, it breaks (the function runs with an erroneous scope). The function object corresponding to a top-level function declaration thereby becomes defective, as far as I can tell, while still being accessible as a property of the global object.
That's a weird bug. Thanks for the excellent analysis!
Status: UNCONFIRMED → NEW
Ever confirmed: true
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.