for-in-opt.js 2.89 KB
Newer Older
1 2 3 4
// 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.

5
// Flags: --allow-natives-syntax --expose-debug-as debug
6 7 8 9 10 11 12 13 14 15 16 17 18 19

"use strict";

// Test non-JSObject receiver.
function f(o) {
  var result = [];
  for (var i in o) {
    result.push(i);
  }
  return result;
}

assertEquals(["0"], f("a"));
assertEquals(["0"], f("a"));
20

21 22 23 24 25
%OptimizeFunctionOnNextCall(f);
assertEquals(["0","1","2"], f("bla"));

// Test the lazy deopt points.
var keys = ["a", "b", "c", "d"];
26
var property_descriptor_keys = [];
27
var deopt_enum = false;
28
var deopt_property_descriptor = false;
29 30

var handler = {
31
  ownKeys() {
32 33 34 35
    if (deopt_enum) {
      %DeoptimizeFunction(f2);
      deopt_enum = false;
    }
36
    return keys;
37
  },
38 39
  getOwnPropertyDescriptor(target, k) {
    if (deopt_property_descriptor) {
40
      %DeoptimizeFunction(f2);
41
      deopt_property_descriptor = false;
42
    }
43 44 45
    property_descriptor_keys.push(k);
    return { enumerable: true, configurable: true }
  },
46 47 48
};


49
var proxy = new Proxy({}, handler);
50 51 52 53 54 55 56 57 58 59 60 61
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));
62 63
  assertEquals(keys, property_descriptor_keys);
  property_descriptor_keys.length = 0;
64 65 66 67
}

check_f2();
check_f2();
68

69
// Test lazy deopt after ForInEnumerate
70 71 72
%OptimizeFunctionOnNextCall(f2);
deopt_enum = true;
check_f2();
73

74 75
// Test lazy deopt after FILTER_KEY
%OptimizeFunctionOnNextCall(f2);
76
deopt_property_descriptor = true;
77 78
check_f2();

79

80 81 82 83 84 85 86
function f3(o) {
  for (var i in o) {
  }
}

f3({__proto__:{x:1}});
f3({__proto__:{x:1}});
87

88 89 90
%OptimizeFunctionOnNextCall(f3);
f3(undefined);
f3(null);
91 92 93 94 95 96 97 98 99 100 101 102

// 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;
}
103

104 105
function check_f4() {
  assertEquals(keys, f4(o, p));
106 107
  assertEquals(keys, property_descriptor_keys);
  property_descriptor_keys.length = 0;
108
}
109

110 111
check_f4();
check_f4();
112

113
%OptimizeFunctionOnNextCall(f4);
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
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 = {
131
  ownKeys() { return ["a", "b"] },
132
  getOwnPropertyDescriptor(target, k) {
133
    if (k == "a") count++;
134 135
    if (x) %ScheduleBreak()
    return { enumerable: true, configurable: true }
136 137 138
  }
};

139
var proxy3 = new Proxy({}, handler3);
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
var o3 = {__proto__: proxy3};

function f5() {
  for (var p in o3) {
    print(p);
  }
}

x = false;

f5(); f5(); f5();
%OptimizeFunctionOnNextCall(f5);
x = true;
count = 0;
Debug.setListener(listener);
f5();
Debug.setListener(null);
assertEquals(1, count);