| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| |
| "use strict"; |
| |
| // Test non-JSObject receiver. |
| function f(o) { |
| var result = []; |
| for (var i in o) { |
| result.push(i); |
| } |
| return result; |
| } |
| |
| %PrepareFunctionForOptimization(f); |
| |
| assertEquals(["0"], f("a")); |
| assertEquals(["0"], f("a")); |
| |
| %OptimizeFunctionOnNextCall(f); |
| assertEquals(["0","1","2"], f("bla")); |
| |
| // Test the lazy deopt points. |
| var keys = ["a", "b", "c", "d"]; |
| var property_descriptor_keys = []; |
| var deopt_enum = false; |
| var deopt_property_descriptor = false; |
| |
| var handler = { |
| ownKeys() { |
| if (deopt_enum) { |
| %DeoptimizeFunction(f2); |
| deopt_enum = false; |
| } |
| return keys; |
| }, |
| getOwnPropertyDescriptor(target, k) { |
| if (deopt_property_descriptor) { |
| %DeoptimizeFunction(f2); |
| deopt_property_descriptor = false; |
| } |
| property_descriptor_keys.push(k); |
| return { enumerable: true, configurable: true } |
| }, |
| }; |
| |
| |
| var proxy = new Proxy({}, handler); |
| var o = {__proto__: proxy}; |
| |
| function f2(o) { |
| var result = []; |
| for (var i in o) { |
| result.push(i); |
| } |
| return result; |
| } |
| |
| function check_f2() { |
| assertEquals(keys, f2(o)); |
| assertEquals(keys, property_descriptor_keys); |
| property_descriptor_keys.length = 0; |
| } |
| |
| %PrepareFunctionForOptimization(f2); |
| |
| check_f2(); |
| check_f2(); |
| |
| // Test lazy deopt after ForInEnumerate |
| %OptimizeFunctionOnNextCall(f2); |
| deopt_enum = true; |
| check_f2(); |
| |
| // Test lazy deopt after FILTER_KEY |
| %PrepareFunctionForOptimization(f2); |
| %OptimizeFunctionOnNextCall(f2); |
| deopt_property_descriptor = true; |
| check_f2(); |
| |
| |
| function f3(o) { |
| for (var i in o) { |
| } |
| } |
| |
| %PrepareFunctionForOptimization(f3); |
| f3({__proto__:{x:1}}); |
| f3({__proto__:{x:1}}); |
| |
| %OptimizeFunctionOnNextCall(f3); |
| f3(undefined); |
| f3(null); |
| |
| // Reliable repro for an issue previously flushed out by GC stress. |
| var p = {x: "x"} |
| |
| function f4(o, p) { |
| var result = []; |
| for (var i in o) { |
| var j = p.x + "str"; |
| result.push(i); |
| } |
| return result; |
| } |
| |
| function check_f4() { |
| assertEquals(keys, f4(o, p)); |
| assertEquals(keys, property_descriptor_keys); |
| property_descriptor_keys.length = 0; |
| } |
| |
| %PrepareFunctionForOptimization(f4); |
| |
| check_f4(); |
| check_f4(); |
| |
| %OptimizeFunctionOnNextCall(f4); |
| |
| p.y = "y"; // Change map, cause eager deopt. |
| check_f4(); |
| |
| // Repro for Turbofan equivalent. |
| var x; |
| var count = 0; |
| |
| var Debug = debug.Debug; |
| |
| function listener(event, exec_state, event_data, data) { |
| if (event == Debug.DebugEvent.Break) { |
| %DeoptimizeFunction(f5); |
| } |
| } |
| |
| var handler3 = { |
| ownKeys() { return ["a", "b"] }, |
| getOwnPropertyDescriptor(target, k) { |
| if (k == "a") count++; |
| if (x) %ScheduleBreak() |
| return { enumerable: true, configurable: true } |
| } |
| }; |
| |
| var proxy3 = new Proxy({}, handler3); |
| var o3 = {__proto__: proxy3}; |
| |
| function f5() { |
| for (var p in o3) { |
| print(p); |
| } |
| } |
| |
| x = false; |
| |
| %PrepareFunctionForOptimization(f5); |
| f5(); f5(); f5(); |
| %OptimizeFunctionOnNextCall(f5); |
| x = true; |
| count = 0; |
| Debug.setListener(listener); |
| f5(); |
| Debug.setListener(null); |
| assertEquals(1, count); |