1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit-test/tests/debug/Environment-identity-03.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,106 @@ 1.4 +// Two Environments nested in the same runtime scope share the correct tail of their parent chains. 1.5 + 1.6 +// The compiler must be allowed to elide empty scopes and so forth, so this 1.7 +// test does not check the number of unshared Environments. Instead, each test 1.8 +// case identifies the expected innermost shared scope by the name of a 1.9 +// variable in it. 1.10 + 1.11 +var g = newGlobal(); 1.12 +g.eval("function h() { debugger; }"); 1.13 +var dbg = Debugger(g); 1.14 +var hits, name, shared, unshared; 1.15 +dbg.onDebuggerStatement = function (hframe) { 1.16 + var frame = hframe.older; 1.17 + 1.18 + // Find name in frame.environment. 1.19 + var env, child = null; 1.20 + for (env = frame.environment; env !== null; env = env.parent) { 1.21 + if (env.names().indexOf(name) != -1) 1.22 + break; 1.23 + child = env; 1.24 + } 1.25 + assertEq(env !== null, true, "expected '" + name + "' to be in scope"); 1.26 + assertEq(env, frame.environment.find(name), 1.27 + "env.find should find the same frame as the written out search"); 1.28 + 1.29 + if (hits === 0) { 1.30 + // First hit. 1.31 + shared = env; 1.32 + unshared = child; 1.33 + } else { 1.34 + // Subsequent hit. 1.35 + assertEq(env, shared, "the environment containing '" + name + "' should be shared"); 1.36 + assertEq(child === null || unshared === null || unshared !== child, true, 1.37 + "environments nested within the one containing '" + name + "' should not be shared"); 1.38 + } 1.39 + hits++; 1.40 +}; 1.41 + 1.42 +function test(sharedName, expectedHits, code) { 1.43 + hits = 0; 1.44 + name = sharedName; 1.45 + shared = unshared = undefined; 1.46 + g.eval(code); 1.47 + assertEq(hits, expectedHits); 1.48 +} 1.49 + 1.50 +// Basic test cases. 1.51 +// 1.52 +// (The stray "a = b" assignments in these tests are to inhibit the flat closure 1.53 +// optimization, which Environments expose. There's nothing really wrong with 1.54 +// the optimization or with the debugger exposing it, but that's not what we 1.55 +// want to test here.) 1.56 + 1.57 +test("q", 2, "var q = function (a) { h(); }; q(1); q(2);"); 1.58 +test("a", 2, "q = function (a) { (function (b) { h(); a = b; })(2); h(); }; q(1);"); 1.59 +test("a", 2, "q = function (a) { h(); return function (b) { h(); a = b; }; }; q(1)(2);"); 1.60 +test("n", 3, "q = function (n) { for (var i = 0; i < n; i++) { let (j = i) { h(); } } }; q(3);"); 1.61 + 1.62 +// A function with long dynamic and static chains. 1.63 +var N = 80; 1.64 + 1.65 +var code = "function f" + N + "(a" + N + ") {\neval('a0 + a1'); h();\n}\n"; 1.66 +for (var i = N; --i >= 0;) { 1.67 + var call = "f" + (i + 1) + "(a" + i + " - 1);\n"; 1.68 + code = ("function f" + i + "(a" + i + ") {\n" + 1.69 + code + 1.70 + call + 1.71 + "if (a" + i + " === 0) " + call + 1.72 + "}\n"); 1.73 +} 1.74 + 1.75 +g.eval(code); 1.76 +test("a0", 2, "f0(0);"); 1.77 +test("a17", 2, "f0(17);"); 1.78 +test("a" + (N-2), 2, "f0(" + (N-2) + ");"); 1.79 +test("a" + (N-1), 2, "f0(" + (N-1) + ");"); 1.80 + 1.81 +// A function with a short dynamic chain and a long static chain. 1.82 +N = 60; 1.83 + 1.84 +function DeepStaticShallowDynamic(i, n) { 1.85 + var code = "function f" + i + "(a" + i + ") {\n"; 1.86 + if (i >= n) 1.87 + code += "eval('a1 + a2'); h();\n"; 1.88 + else 1.89 + code += "return " + DeepStaticShallowDynamic(i+1, n) + ";\n"; 1.90 + code += "}"; 1.91 + return code; 1.92 +} 1.93 +g.eval(DeepStaticShallowDynamic(1, N)); 1.94 + 1.95 +function range(start, stop) { 1.96 + for (var i = start; i < stop; i++) 1.97 + yield i; 1.98 +} 1.99 + 1.100 +function DSSDsplit(s) { 1.101 + return ("var mid = f1" + ["(" + i + ")" for (i in range(0, s))].join("") + ";\n" + 1.102 + "mid" + ["(" + i + ")" for (i in range(s, N))].join("") + ";\n" + 1.103 + "mid" + ["(" + i + ")" for (i in range(s, N))].join("") + ";\n"); 1.104 +} 1.105 + 1.106 +test("a1", 2, DSSDsplit(1)); 1.107 +test("a17", 2, DSSDsplit(17)); 1.108 +test("a" + (N-2), 2, DSSDsplit(N-2)); 1.109 +test("a" + (N-1), 2, DSSDsplit(N-1));