(create_func)
| 72 | } |
| 73 | |
| 74 | function base_getter_test(create_func) { |
| 75 | var calls = 0; |
| 76 | |
| 77 | // Testcase: setter in prototype chain |
| 78 | foo = function(a) { var x = a[0]; return x + 3; } |
| 79 | var a = create_func(); |
| 80 | var ap = []; |
| 81 | ap.__defineGetter__(0, function() { calls++; return 0; }); |
| 82 | |
| 83 | prepareForOptimize(foo); |
| 84 | foo(a); |
| 85 | assertUnoptimized(foo); |
| 86 | // Smi and Double elements transition the KeyedLoadIC to Generic state |
| 87 | // here, because they miss twice with the same map when loading the hole. |
| 88 | // For HOLEY_ELEMENTS, however, the IC knows how to convert the hole |
| 89 | // to undefined if the prototype is the original array prototype, so it |
| 90 | // stays monomorphic for now... |
| 91 | foo(a); |
| 92 | foo(a); |
| 93 | delete a[0]; |
| 94 | |
| 95 | assertEquals(0, calls); |
| 96 | a.__proto__ = ap; |
| 97 | // ...and later becomes polymorphic when it sees a second map. Optimized |
| 98 | // code will therefore inline the elements access, and deopt right away |
| 99 | // when it loads the hole from index [0]. |
| 100 | // Possible solutions: |
| 101 | // - remove the convert_hole_to_undefined flag from the IC, to force it |
| 102 | // into generic state for all elements kinds. Cost: slower ICs in code |
| 103 | // that doesn't get optimized. |
| 104 | // - teach Turbofan about the same trick: for holey elements with the |
| 105 | // original array prototype, convert hole to undefined inline. Cost: |
| 106 | // larger optimized code size, because the loads for different maps with |
| 107 | // the same elements kind can no longer be consolidated if they handle |
| 108 | // the hole differently. |
| 109 | // - call "foo" twice after setting a.__proto__ and before optimizing it; |
| 110 | // this is the simplest fix so let's do that for now. |
| 111 | foo(a); |
| 112 | assertEquals(1, calls); |
| 113 | foo(a); |
| 114 | assertEquals(2, calls); |
| 115 | optimize(foo); |
| 116 | foo(a); |
| 117 | assertEquals(3, calls); |
| 118 | assertOptimized(foo); |
| 119 | |
| 120 | // Testcase: getter "deep" in prototype chain. |
| 121 | clearFunctionTypeFeedback(foo); |
| 122 | deoptimizeFunction(foo); |
| 123 | clearFunctionTypeFeedback(foo); |
| 124 | calls = 0; |
| 125 | |
| 126 | a = create_func(); |
| 127 | var ap2 = []; |
| 128 | a.__proto__ = ap2; |
| 129 | foo(a); |
| 130 | foo(a); |
| 131 | foo(a); |
no test coverage detected