99ce5a2484
version is passing all the existing test + a bunch of new tests (packaged in the change list, too). The patch extends the SlotRef object to describe captured and duplicated objects. Since the SlotRefs are not independent of each other anymore, there is a new SlotRefValueBuilder class that stores the SlotRefs and later materializes the objects from the SlotRefs. Note that unlike the previous implementation of SlotRefs, we now build the SlotRef entries for the entire frame, not just the particular function. This is because duplicate objects might refer to previous captured objects (that might live inside other inlined function's part of the frame). We also need to store the materialized objects between other potential invocations of the same arguments object so that we materialize each captured object at most once. The materialized objects of frames live in the new MaterielizedObjectStore object (contained in Isolate), indexed by the frame's FP address. Each argument materialization (and deoptimization) tries to lookup its captured objects in the store before building new ones. Deoptimization also removes the materialized objects from the store. We also schedule a lazy deopt to be sure that we always get rid of the materialized objects and that the optmized function adopts the materialized objects (instead of happily computing with its captured representations). Concerns: - Is the FP address the right key for a frame? (Note that deoptimizer's representation of frame is different from the argument object materializer's one - it is not easy to find common ground.) - Performance is suboptimal in several places, but a quick local run of benchmarks does not seem to show a perf hit. Examples of possible improvements: smarter generation of SlotRefs (build other functions' SlotRefs only for captured objects and only if necessary), smarter lookup of stored materialized objects. - Ideally, we would like to share the code for argument materialization with deoptimizer's materializer. However, the supporting data structures (mainly the frame descriptor) are quite different in each case, so it looks more like a separate project. Thanks for any feedback. R=danno@chromium.org, mstarzinger@chromium.org LOG=N BUG= Committed: https://code.google.com/p/v8/source/detail?r=18918 Review URL: https://codereview.chromium.org/103243005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
188 lines
4.4 KiB
JavaScript
188 lines
4.4 KiB
JavaScript
// Copyright 2013 the V8 project authors. All rights reserved.
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
// Flags: --allow-natives-syntax --use-escape-analysis --expose-gc
|
|
|
|
|
|
// Simple test of capture
|
|
(function testCapturedArguments() {
|
|
function h() {
|
|
return g.arguments[0];
|
|
}
|
|
|
|
function g(x) {
|
|
return h();
|
|
}
|
|
|
|
function f() {
|
|
var l = { y : { z : 4 }, x : 2 }
|
|
var r = g(l);
|
|
assertEquals(2, r.x);
|
|
assertEquals(2, l.x);
|
|
l.x = 3;
|
|
l.y.z = 5;
|
|
// Test that the arguments object is properly
|
|
// aliased
|
|
assertEquals(3, r.x);
|
|
assertEquals(3, l.x);
|
|
assertEquals(5, r.y.z);
|
|
}
|
|
|
|
f(); f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f();
|
|
})();
|
|
|
|
|
|
// Get the arguments object twice, test aliasing
|
|
(function testTwoCapturedArguments() {
|
|
function h() {
|
|
return g.arguments[0];
|
|
}
|
|
|
|
function i() {
|
|
return g.arguments[0];
|
|
}
|
|
|
|
function g(x) {
|
|
return {h : h() , i : i()};
|
|
}
|
|
|
|
function f() {
|
|
var l = { y : { z : 4 }, x : 2 }
|
|
var r = g(l);
|
|
assertEquals(2, r.h.x)
|
|
l.y.z = 3;
|
|
assertEquals(3, r.h.y.z);
|
|
assertEquals(3, r.i.y.z);
|
|
}
|
|
|
|
f(); f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f();
|
|
})();
|
|
|
|
|
|
// Nested arguments object test
|
|
(function testTwoCapturedArgumentsNested() {
|
|
function i() {
|
|
return { gx : g.arguments[0], hx : h.arguments[0] };
|
|
}
|
|
|
|
function h(x) {
|
|
return i();
|
|
}
|
|
|
|
function g(x) {
|
|
return h(x.y);
|
|
}
|
|
|
|
function f() {
|
|
var l = { y : { z : 4 }, x : 2 }
|
|
var r = g(l);
|
|
assertEquals(2, r.gx.x)
|
|
assertEquals(4, r.gx.y.z)
|
|
assertEquals(4, r.hx.z)
|
|
l.y.z = 3;
|
|
assertEquals(3, r.gx.y.z)
|
|
assertEquals(3, r.hx.z)
|
|
assertEquals(3, l.y.z)
|
|
}
|
|
|
|
f(); f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
})();
|
|
|
|
|
|
// Nested arguments object test with different inlining
|
|
(function testTwoCapturedArgumentsNested2() {
|
|
function i() {
|
|
return { gx : g.arguments[0], hx : h.arguments[0] };
|
|
}
|
|
|
|
function h(x) {
|
|
return i();
|
|
}
|
|
|
|
function g(x) {
|
|
return h(x.y);
|
|
}
|
|
|
|
function f() {
|
|
var l = { y : { z : 4 }, x : 2 }
|
|
var r = g(l);
|
|
assertEquals(2, r.gx.x)
|
|
assertEquals(4, r.gx.y.z)
|
|
assertEquals(4, r.hx.z)
|
|
l.y.z = 3;
|
|
assertEquals(3, r.gx.y.z)
|
|
assertEquals(3, r.hx.z)
|
|
assertEquals(3, l.y.z)
|
|
}
|
|
|
|
%NeverOptimizeFunction(i);
|
|
f(); f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
})();
|
|
|
|
|
|
// Multiple captured argument test
|
|
(function testTwoArgumentsCapture() {
|
|
function h() {
|
|
return { a : g.arguments[1], b : g.arguments[0] };
|
|
}
|
|
|
|
function g(x, y) {
|
|
return h();
|
|
}
|
|
|
|
function f() {
|
|
var l = { y : { z : 4 }, x : 2 }
|
|
var k = { t : { u : 3 } };
|
|
var r = g(k, l);
|
|
assertEquals(2, r.a.x)
|
|
assertEquals(4, r.a.y.z)
|
|
assertEquals(3, r.b.t.u)
|
|
l.y.z = 6;
|
|
r.b.t.u = 7;
|
|
assertEquals(6, r.a.y.z)
|
|
assertEquals(7, k.t.u)
|
|
}
|
|
|
|
f(); f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(); f();
|
|
})();
|