| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Flags: --harmony-proxies --allow-natives-syntax --expose-debug-as debug | 5 // Flags: --harmony-proxies --allow-natives-syntax --expose-debug-as debug |
| 6 | 6 |
| 7 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 // Test non-JSObject receiver. | 9 // Test non-JSObject receiver. |
| 10 function f(o) { | 10 function f(o) { |
| 11 var result = []; | 11 var result = []; |
| 12 for (var i in o) { | 12 for (var i in o) { |
| 13 result.push(i); | 13 result.push(i); |
| 14 } | 14 } |
| 15 return result; | 15 return result; |
| 16 } | 16 } |
| 17 | 17 |
| 18 assertEquals(["0"], f("a")); | 18 assertEquals(["0"], f("a")); |
| 19 assertEquals(["0"], f("a")); | 19 assertEquals(["0"], f("a")); |
| 20 |
| 20 %OptimizeFunctionOnNextCall(f); | 21 %OptimizeFunctionOnNextCall(f); |
| 21 assertEquals(["0","1","2"], f("bla")); | 22 assertEquals(["0","1","2"], f("bla")); |
| 22 | 23 |
| 23 // Test the lazy deopt points. | 24 // Test the lazy deopt points. |
| 24 var keys = ["a", "b", "c", "d"]; | 25 var keys = ["a", "b", "c", "d"]; |
| 25 var has_keys = []; | 26 var has_keys = []; |
| 26 var deopt_has = false; | 27 var deopt_has = false; |
| 27 var deopt_enum = false; | 28 var deopt_enum = false; |
| 28 | 29 |
| 29 var handler = { | 30 var handler = { |
| 30 enumerate: function(target) { | 31 enumerate(target) { |
| 31 if (deopt_enum) { | 32 if (deopt_enum) { |
| 32 %DeoptimizeFunction(f2); | 33 %DeoptimizeFunction(f2); |
| 33 deopt_enum = false; | 34 deopt_enum = false; |
| 34 } | 35 } |
| 35 return keys; | 36 return keys[Symbol.iterator](); |
| 36 }, | 37 }, |
| 37 | 38 |
| 38 getPropertyDescriptor: function(k) { | 39 has(target, k) { |
| 39 if (deopt_has) { | 40 if (deopt_has) { |
| 40 %DeoptimizeFunction(f2); | 41 %DeoptimizeFunction(f2); |
| 41 deopt_has = false; | 42 deopt_has = false; |
| 42 } | 43 } |
| 43 has_keys.push(k); | 44 has_keys.push(k); |
| 44 return {value: 10, configurable: true, writable: false, enumerable: true}; | 45 return {value: 10, configurable: true, writable: false, enumerable: true}; |
| 45 } | 46 } |
| 46 }; | 47 }; |
| 47 | 48 |
| 48 | 49 |
| 49 var proxy = new Proxy({}, handler); | 50 var proxy = new Proxy({}, handler); |
| 50 var o = {__proto__: proxy}; | 51 var o = {__proto__: proxy}; |
| 51 | 52 |
| 52 function f2(o) { | 53 function f2(o) { |
| 53 var result = []; | 54 var result = []; |
| 54 for (var i in o) { | 55 for (var i in o) { |
| 55 result.push(i); | 56 result.push(i); |
| 56 } | 57 } |
| 57 return result; | 58 return result; |
| 58 } | 59 } |
| 59 | 60 |
| 60 function check_f2() { | 61 function check_f2() { |
| 61 assertEquals(keys, f2(o)); | 62 assertEquals(keys, f2(o)); |
| 62 assertEquals(keys, has_keys); | 63 assertEquals(keys, has_keys); |
| 63 has_keys.length = 0; | 64 has_keys.length = 0; |
| 64 } | 65 } |
| 65 | 66 |
| 66 check_f2(); | 67 check_f2(); |
| 67 check_f2(); | 68 check_f2(); |
| 69 |
| 68 // Test lazy deopt after GetPropertyNamesFast | 70 // Test lazy deopt after GetPropertyNamesFast |
| 69 %OptimizeFunctionOnNextCall(f2); | 71 %OptimizeFunctionOnNextCall(f2); |
| 70 deopt_enum = true; | 72 deopt_enum = true; |
| 71 check_f2(); | 73 check_f2(); |
| 74 |
| 72 // Test lazy deopt after FILTER_KEY | 75 // Test lazy deopt after FILTER_KEY |
| 73 %OptimizeFunctionOnNextCall(f2); | 76 %OptimizeFunctionOnNextCall(f2); |
| 74 deopt_has = true; | 77 deopt_has = true; |
| 75 check_f2(); | 78 check_f2(); |
| 76 | 79 |
| 77 function f3(o) { | 80 function f3(o) { |
| 78 for (var i in o) { | 81 for (var i in o) { |
| 79 } | 82 } |
| 80 } | 83 } |
| 81 | 84 |
| 82 f3({__proto__:{x:1}}); | 85 f3({__proto__:{x:1}}); |
| 83 f3({__proto__:{x:1}}); | 86 f3({__proto__:{x:1}}); |
| 87 |
| 84 %OptimizeFunctionOnNextCall(f3); | 88 %OptimizeFunctionOnNextCall(f3); |
| 85 f3(undefined); | 89 f3(undefined); |
| 86 f3(null); | 90 f3(null); |
| 87 | 91 |
| 88 // Reliable repro for an issue previously flushed out by GC stress. | 92 // Reliable repro for an issue previously flushed out by GC stress. |
| 89 var handler2 = { | 93 var handler2 = { |
| 90 getPropertyDescriptor: function(k) { | 94 getPropertyDescriptor(target, k) { |
| 91 has_keys.push(k); | 95 has_keys.push(k); |
| 92 return {value: 10, configurable: true, writable: false, enumerable: true}; | 96 return {value: 10, configurable: true, writable: false, enumerable: true}; |
| 93 } | 97 } |
| 94 } | 98 } |
| 95 var proxy2 = new Proxy({}, handler2); | 99 var proxy2 = new Proxy({}, handler2); |
| 96 var o2 = {__proto__: proxy2}; | 100 var o2 = {__proto__: proxy2}; |
| 97 var p = {x: "x"} | 101 var p = {x: "x"} |
| 98 | 102 |
| 99 function f4(o, p) { | 103 function f4(o, p) { |
| 100 var result = []; | 104 var result = []; |
| 101 for (var i in o) { | 105 for (var i in o) { |
| 102 var j = p.x + "str"; | 106 var j = p.x + "str"; |
| 103 result.push(i); | 107 result.push(i); |
| 104 } | 108 } |
| 105 return result; | 109 return result; |
| 106 } | 110 } |
| 111 |
| 107 function check_f4() { | 112 function check_f4() { |
| 108 assertEquals(keys, f4(o, p)); | 113 assertEquals(keys, f4(o, p)); |
| 109 assertEquals(keys, has_keys); | 114 assertEquals(keys, has_keys); |
| 110 has_keys.length = 0; | 115 has_keys.length = 0; |
| 111 } | 116 } |
| 117 |
| 112 check_f4(); | 118 check_f4(); |
| 113 check_f4(); | 119 check_f4(); |
| 120 |
| 114 %OptimizeFunctionOnNextCall(f4); | 121 %OptimizeFunctionOnNextCall(f4); |
| 122 |
| 115 p.y = "y"; // Change map, cause eager deopt. | 123 p.y = "y"; // Change map, cause eager deopt. |
| 116 check_f4(); | 124 check_f4(); |
| 117 | 125 |
| 118 // Repro for Turbofan equivalent. | 126 // Repro for Turbofan equivalent. |
| 119 var x; | 127 var x; |
| 120 var count = 0; | 128 var count = 0; |
| 121 | 129 |
| 122 var Debug = debug.Debug; | 130 var Debug = debug.Debug; |
| 123 | 131 |
| 124 function listener(event, exec_state, event_data, data) { | 132 function listener(event, exec_state, event_data, data) { |
| 125 if (event == Debug.DebugEvent.Break) { | 133 if (event == Debug.DebugEvent.Break) { |
| 126 %DeoptimizeFunction(f5); | 134 %DeoptimizeFunction(f5); |
| 127 } | 135 } |
| 128 } | 136 } |
| 129 | 137 |
| 130 var handler3 = { | 138 var handler3 = { |
| 131 enumerate: function(target) { | 139 enumerate(target) { |
| 132 return ["a", "b"]; | 140 return ["a", "b"][Symbol.iterator](); |
| 133 }, | 141 }, |
| 134 | 142 |
| 135 getPropertyDescriptor: function(k) { | 143 has(target, k) { |
| 136 if (k == "a") count++; | 144 if (k == "a") count++; |
| 137 if (x) %ScheduleBreak(); | 145 if (x) %ScheduleBreak(); |
| 138 return {value: 10, configurable: true, writable: false, enumerable: true}; | 146 return {value: 10, configurable: true, writable: false, enumerable: true}; |
| 139 } | 147 } |
| 140 }; | 148 }; |
| 141 | 149 |
| 142 var proxy3 = new Proxy({}, handler3); | 150 var proxy3 = new Proxy({}, handler3); |
| 143 var o3 = {__proto__: proxy3}; | 151 var o3 = {__proto__: proxy3}; |
| 144 | 152 |
| 145 function f5() { | 153 function f5() { |
| 146 for (var p in o3) { | 154 for (var p in o3) { |
| 147 print(p); | 155 print(p); |
| 148 } | 156 } |
| 149 } | 157 } |
| 150 | 158 |
| 151 x = false; | 159 x = false; |
| 152 | 160 |
| 153 f5(); f5(); f5(); | 161 f5(); f5(); f5(); |
| 154 %OptimizeFunctionOnNextCall(f5); | 162 %OptimizeFunctionOnNextCall(f5); |
| 155 x = true; | 163 x = true; |
| 156 count = 0; | 164 count = 0; |
| 157 Debug.setListener(listener); | 165 Debug.setListener(listener); |
| 158 f5(); | 166 f5(); |
| 159 Debug.setListener(null); | 167 Debug.setListener(null); |
| 160 assertEquals(1, count); | 168 assertEquals(1, count); |
| OLD | NEW |