v8/test/mjsunit/maglev/mutable-context-access.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

95 lines
1.8 KiB
JavaScript
Raw Normal View History

// Copyright 2022 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 --maglev --no-stress-opt
function factory() {
var x = 1;
x = 2;
return function foo() {
return x;
}
}
let foo = factory();
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo());
assertEquals(2, foo());
%OptimizeMaglevOnNextCall(foo);
assertEquals(2, foo());
function nested_factory() {
var x = 1;
x = 2;
return (function() {
var z = 3;
return function foo(){
// Add two values from different contexts to force an
// LdaImmutableCurrentContextSlot
return x+z;
}
})();
}
foo = nested_factory();
%PrepareFunctionForOptimization(foo);
assertEquals(5, foo());
assertEquals(5, foo());
%OptimizeMaglevOnNextCall(foo);
assertEquals(5, foo());
[maglev] Fix result regalloc clobbering inputs Consider the following * A ValueNode has inputs A and B * Input A has later uses, input B doesn't * The ValueNode's result must be in the same register as A It can then happen that UpdateUses frees B, and the result allocation emits a gap move from A's register to B's old register (now free) to preserve the value of A when the ValueNode writes into its register. This gap move is emmitted before the ValueNode start, which means that it clobbers B. Now, UpdateUses only clears registers _after_ node result allocation, so that the known free registers are still the ones before updating uses. Done naively, this would have bad consequences -- in the case where A has no later uses, it would still force the regalloc to save its value thinking that it is still live. So, this patch also introduces a concept of "AllocationStage" where we're either allocating at the start or end of a Node. Inputs are allocated at the start, results at the end. When walking registers during an allocation, nodes whose lifetimes end at the current node are considered to be dead at the "end" allocation stage, and we are allowed to a) use their registers, and b) drop them without preserving their value. Bug: v8:7700 Change-Id: I5ca764ed04b12269f189577e81eb7e2a27cd1b09 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3625978 Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/main@{#80371}
2022-05-04 14:55:01 +00:00
function nested_factory_mutable() {
var x = 1;
x = 2;
return (function() {
var z = 3;
z = 4;
return function foo(){
// Add two values from different contexts to force an
// LdaImmutableCurrentContextSlot
return x+z;
}
})();
}
foo = nested_factory_mutable();
%PrepareFunctionForOptimization(foo);
assertEquals(6, foo());
assertEquals(6, foo());
%OptimizeMaglevOnNextCall(foo);
assertEquals(6, foo());
function nested_factory_immutable() {
var x = 1;
return (function() {
var z = 3;
z = 4;
return function foo(){
// Add two values from different contexts to force an
// LdaImmutableCurrentContextSlot
return x+z;
}
})();
}
foo = nested_factory_immutable();
%PrepareFunctionForOptimization(foo);
assertEquals(5, foo());
assertEquals(5, foo());
%OptimizeMaglevOnNextCall(foo);
assertEquals(5, foo());