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