|
1 function loop(f, expected) { |
|
2 // This is the loop that breaks us. |
|
3 // At record time, f's parent is a Call object with no fp. |
|
4 // At second execute time, it is a Call object with fp, |
|
5 // and all the Call object's dslots are still JSVAL_VOID. |
|
6 for (var i = 0; i < 9; i++) |
|
7 assertEq(f(), expected); |
|
8 } |
|
9 |
|
10 function C(bad) { |
|
11 var x = bad; |
|
12 function f() { |
|
13 return x; // We trick TR::callProp() into emitting code that gets |
|
14 // JSVAL_VOID (from the Call object's dslots) |
|
15 // rather than the actual value (true or false). |
|
16 } |
|
17 if (bad) |
|
18 void (f + "a!"); |
|
19 return f; |
|
20 } |
|
21 |
|
22 var obj = { |
|
23 }; |
|
24 |
|
25 // Warm up and trace with C's Call object entrained but its stack frame gone. |
|
26 loop(C.call(obj, false), false); |
|
27 |
|
28 // Sneaky access to f via a prototype method called implicitly by operator +. |
|
29 Function.prototype.toString = function () { loop(this, true); return "hah"; }; |
|
30 |
|
31 // Fail hard if we don't handle the implicit call out of C to F.p.toString. |
|
32 C.call(obj, true); |