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. 10function f(o) { 11 var result = []; 12 for (var i in o) { 13 result.push(i); 14 } 15 return result; 16} 17 18assertEquals(["0"], f("a")); 19assertEquals(["0"], f("a")); 20 21%OptimizeFunctionOnNextCall(f); 22assertEquals(["0","1","2"], f("bla")); 23 24// Test the lazy deopt points. 25var keys = ["a", "b", "c", "d"]; 26var has_keys = []; 27var deopt_has = false; 28var deopt_enum = false; 29 30var 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 50var proxy = new Proxy({}, handler); 51var o = {__proto__: proxy}; 52 53function f2(o) { 54 var result = []; 55 for (var i in o) { 56 result.push(i); 57 } 58 return result; 59} 60 61function check_f2() { 62 assertEquals(keys, f2(o)); 63 assertEquals(keys, has_keys); 64 has_keys.length = 0; 65} 66 67check_f2(); 68check_f2(); 69 70// Test lazy deopt after GetPropertyNamesFast 71%OptimizeFunctionOnNextCall(f2); 72deopt_enum = true; 73check_f2(); 74 75// Test lazy deopt after FILTER_KEY 76%OptimizeFunctionOnNextCall(f2); 77deopt_has = true; 78check_f2(); 79 80function f3(o) { 81 for (var i in o) { 82 } 83} 84 85f3({__proto__:{x:1}}); 86f3({__proto__:{x:1}}); 87 88%OptimizeFunctionOnNextCall(f3); 89f3(undefined); 90f3(null); 91 92// Reliable repro for an issue previously flushed out by GC stress. 93var handler2 = { 94 getPropertyDescriptor(target, k) { 95 has_keys.push(k); 96 return {value: 10, configurable: true, writable: false, enumerable: true}; 97 } 98} 99var proxy2 = new Proxy({}, handler2); 100var o2 = {__proto__: proxy2}; 101var p = {x: "x"} 102 103function 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 112function check_f4() { 113 assertEquals(keys, f4(o, p)); 114 assertEquals(keys, has_keys); 115 has_keys.length = 0; 116} 117 118check_f4(); 119check_f4(); 120 121%OptimizeFunctionOnNextCall(f4); 122 123p.y = "y"; // Change map, cause eager deopt. 124check_f4(); 125 126// Repro for Turbofan equivalent. 127var x; 128var count = 0; 129 130var Debug = debug.Debug; 131 132function listener(event, exec_state, event_data, data) { 133 if (event == Debug.DebugEvent.Break) { 134 %DeoptimizeFunction(f5); 135 } 136} 137 138var 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 150var proxy3 = new Proxy({}, handler3); 151var o3 = {__proto__: proxy3}; 152 153function f5() { 154 for (var p in o3) { 155 print(p); 156 } 157} 158 159x = false; 160 161f5(); f5(); f5(); 162%OptimizeFunctionOnNextCall(f5); 163x = true; 164count = 0; 165Debug.setListener(listener); 166f5(); 167Debug.setListener(null); 168assertEquals(1, count); 169