// 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);