3251a03e81
So far the for-in slow path in Crankshaft unconditionally called %ForInFilter for every iteration of the for-in loop, without paying attention to the possible enum cache equipped receiver map. So even though we iterate the enum cache FixedArray associated with the map we don't check the map, but always go to %ForInFilter. This would be perfectly fine if the enum cache FixedArray would be immutable, but due to some funny GC/runtime interaction kicking in, the enum cache can be right trimmed while we are iterating it, and the only way to detect this is to ensure that we check the map when accessing the enum cache. BUG=v8:3650,v8:4715 LOG=n Review URL: https://codereview.chromium.org/1650493002 Cr-Commit-Position: refs/heads/master@{#33599}
49 lines
1.1 KiB
JavaScript
49 lines
1.1 KiB
JavaScript
// Copyright 2016 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.
|
|
|
|
// Flags: --allow-natives-syntax --dead-code-elimination --expose-gc
|
|
|
|
var training = {};
|
|
training.a = "nop";
|
|
training.slow = "nop";
|
|
delete training.slow; // Dictionary-mode properties => slow-mode for-in.
|
|
|
|
var keepalive = {};
|
|
keepalive.a = "nop"; // Keep a map early in the transition chain alive.
|
|
|
|
function GetReal() {
|
|
var r = {};
|
|
r.a = "nop";
|
|
r.b = "nop";
|
|
r.c = "dictionarize",
|
|
r.d = "gc";
|
|
r.e = "result";
|
|
return r;
|
|
};
|
|
|
|
function SideEffect(object, action) {
|
|
if (action === "dictionarize") {
|
|
delete object.a;
|
|
} else if (action === "gc") {
|
|
gc();
|
|
}
|
|
}
|
|
|
|
function foo(object) {
|
|
for (var key in object) {
|
|
SideEffect(object, object[key]);
|
|
}
|
|
return key;
|
|
}
|
|
|
|
// Collect type feedback for slow-mode for-in.
|
|
foo(training);
|
|
SideEffect({a: 0}, "dictionarize");
|
|
SideEffect({}, "gc");
|
|
|
|
// Compile for slow-mode objects...
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
// ...and pass in a fast-mode object.
|
|
assertEquals("e", foo(GetReal()));
|